Clover Coverage Report
Coverage timestamp: Fri Feb 14 2014 07:28:57 UTC
../../../../../../img/srcFileCovDistChart6.png 81% of files have more coverage
72   199   31   5.54
32   148   0.43   13
13     2.38  
1    
 
  ModuleArbiterImpl       Line # 42 72 31 54.7% 0.5470086
 
  (8)
 
1    /* This file is part of the project "Hilbert II" - http://www.qedeq.org
2    *
3    * Copyright 2000-2014, Michael Meyling <mime@qedeq.org>.
4    *
5    * "Hilbert II" is free software; you can redistribute
6    * it and/or modify it under the terms of the GNU General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10    * This program is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    * GNU General Public License for more details.
14    */
15   
16    package org.qedeq.kernel.bo.service.internal;
17   
18    import java.util.HashMap;
19    import java.util.Iterator;
20    import java.util.Map;
21   
22    import org.qedeq.base.trace.Trace;
23    import org.qedeq.base.utility.StringUtility;
24    import org.qedeq.kernel.bo.common.QedeqBo;
25    import org.qedeq.kernel.bo.common.QedeqBoSet;
26    import org.qedeq.kernel.bo.common.ServiceJob;
27    import org.qedeq.kernel.bo.job.InternalModuleServiceCallImpl;
28    import org.qedeq.kernel.bo.module.InternalModuleServiceCall;
29    import org.qedeq.kernel.bo.module.InternalServiceJob;
30    import org.qedeq.kernel.bo.module.ModuleArbiter;
31    import org.qedeq.kernel.se.common.Service;
32    import org.qedeq.kernel.se.visitor.InterruptException;
33   
34    /**
35    * Get locks for modules.
36    * TODO 20130508 m31: Currently we make no difference between read and write locks. We also lock
37    * a module during the whole plugin processing for that module. This could be limited to status
38    * changes only.
39    *
40    * @author Michael Meyling
41    */
 
42    public class ModuleArbiterImpl implements ModuleArbiter {
43   
44    /** This class. */
45    private static final Class CLASS = ModuleArbiterImpl.class;
46   
47    /** Map blocked QEDEQ modules to service processes. */
48    private final Map blocked;
49   
50    /**
51    * Constructor.
52    */
 
53  528 toggle public ModuleArbiterImpl() {
54  528 blocked = new HashMap();
55    }
56   
 
57  1589 toggle public boolean lockRequiredModule(final InternalModuleServiceCall call) throws InterruptException {
58  1589 call.pause();
59  1589 call.getInternalServiceProcess().setBlocked(true);
60  1589 try {
61  1589 final boolean result = lockRequiredModule(call.getInternalServiceProcess(), call.getQedeq(),
62    call.getService());
63  1589 ((InternalModuleServiceCallImpl) call).setNewlyBlockedModule(result);
64  1589 return result;
65    } finally {
66  1589 call.getInternalServiceProcess().setBlocked(false);
67  1589 call.resume();
68    }
69    }
70   
 
71  1589 toggle private boolean lockRequiredModule(final InternalServiceJob process,
72    final QedeqBo qedeq, final Service service) throws InterruptException {
73  1589 if (isAlreadyLocked(process, qedeq)) {
74  497 return false;
75    }
76  1092 process.setBlocked(true);
77    // we try to get a lock, if not we wait
78  1092 try {
79  1092 while (!lock(process, qedeq, service)) {
80  0 final Object monitor = new Object();
81  0 synchronized (monitor) {
82  0 try {
83  0 monitor.wait(1000);
84    } catch (InterruptedException e) {
85  0 process.setInterruptedState();
86  0 throw new InterruptException(qedeq.getModuleAddress().createModuleContext());
87    }
88    }
89  0 if (Thread.interrupted()) {
90  0 process.setInterruptedState();
91  0 throw new InterruptException(qedeq.getModuleAddress().createModuleContext());
92    }
93    }
94    } finally {
95  1092 process.setBlocked(false);
96    }
97  1092 return true;
98    }
99   
 
100  1741 toggle public boolean unlockRequiredModule(final InternalModuleServiceCall call) {
101    // TODO 20130521 m31: do it without cast
102  1741 if (call != null && ((InternalModuleServiceCallImpl) call).getNewlyBlockedModule()) {
103  1092 return unlockRequiredModule(call.getInternalServiceProcess(), call.getQedeq());
104    }
105  649 return false;
106    }
107   
 
108  1092 toggle public boolean unlockRequiredModule(final ServiceJob process, final QedeqBo qedeq) {
109  1092 return unlock(process, qedeq);
110   
111    }
112   
 
113  1092 toggle private synchronized boolean lock(final ServiceJob process, final QedeqBo qedeq, final Service service) {
114  1092 final String method = "lock";
115  1092 if (Trace.isTraceOn()) {
116  0 Trace.info(CLASS, this, method, getName(process) + " is trying to lock " + qedeq.getName());
117    }
118  1092 final ServiceJob origin = getProcess(qedeq);
119  1092 if (origin != null) {
120  0 if (Trace.isTraceOn()) {
121  0 Trace.info(CLASS, this, method, getName(process) + " failed to lock " + qedeq.getName()
122    + "\tbecause it is locked by " + getName(origin));
123    }
124  0 return false;
125    }
126  1092 addLock(process, qedeq);
127  1092 ((DefaultKernelQedeqBo) qedeq).setCurrentlyRunningService(service);
128  1092 return true;
129    }
130   
 
131  1092 toggle private synchronized boolean unlock(final ServiceJob process, final QedeqBo qedeq) {
132  1092 final String method = "unlock";
133  1092 if (Trace.isTraceOn()) {
134  0 Trace.info(CLASS, this, method, getName(process) + " is trying to unlock " + qedeq.getName());
135    }
136  1092 ((DefaultKernelQedeqBo) qedeq).setCurrentlyRunningService(null);
137  1092 final ServiceJob origin = getProcess(qedeq);
138  1092 if (origin != null) {
139  1092 if (origin.equals(process)) {
140  1092 removeLock(process, qedeq);
141  1092 return true;
142    } else {
143  0 RuntimeException e = new IllegalArgumentException(getName(process) + " illegal unlock try for "
144    + qedeq.getName() + " which is currently locked by service process " + getName(origin));
145  0 Trace.fatal(CLASS, this, method, "Programming error. Unallowed unlock try.", e);
146    // TODO 20130324 m31: later on we might handle this differently but for now:
147  0 throw e;
148    }
149    } else {
150  0 if (Trace.isTraceOn()) {
151  0 Trace.info(CLASS, this, method, getName(process) + " unlock unnecessary " + qedeq.getName());
152    }
153  0 return false;
154    }
155    }
156   
 
157  0 toggle private String getName(final ServiceJob process) {
158  0 return StringUtility.format(process.getId(), 3) + " "
159  0 + (process.getModuleServiceCall() != null ? StringUtility.getLastDotString(
160    process.getModuleServiceCall().getService().getServiceId()) : "");
161    }
162   
 
163  2184 toggle private synchronized ServiceJob getProcess(final QedeqBo qedeq) {
164  2184 return (ServiceJob) blocked.get(qedeq);
165    }
166   
 
167  1589 toggle private synchronized boolean isAlreadyLocked(final ServiceJob process,
168    final QedeqBo qedeq) {
169  1589 return process.equals(blocked.get(qedeq));
170    }
171   
 
172  1092 toggle private synchronized void addLock(final ServiceJob process, final QedeqBo qedeq) {
173  1092 if (Trace.isTraceOn()) {
174  0 Trace.info(CLASS, this, "addLock", getName(process) + " locked successfuly " + qedeq.getName());
175    }
176  1092 blocked.put(qedeq, process);
177    }
178   
 
179  1092 toggle private synchronized void removeLock(final ServiceJob process, final QedeqBo qedeq) {
180  1092 if (Trace.isTraceOn()) {
181  0 Trace.info(CLASS, this, "removeLock", getName(process) + " unlocked " + qedeq.getName());
182    }
183  1092 blocked.remove(qedeq);
184    }
185   
 
186  0 toggle public synchronized QedeqBoSet getBlockedModules(final ServiceJob process) {
187  0 QedeqBoSet result = new QedeqBoSet();
188  0 final Iterator i = blocked.entrySet().iterator();
189  0 while (i.hasNext()) {
190  0 final Map.Entry entry = (Map.Entry) i.next();
191  0 QedeqBo qedeq = (QedeqBo) entry.getKey();
192  0 if (process.equals(entry.getValue())) {
193  0 result.add(qedeq);
194    }
195    }
196  0 return result;
197    }
198   
199    }