Clover Coverage Report
Coverage timestamp: Fri Feb 14 2014 01:47:57 UTC
../../../../../../img/srcFileCovDistChart7.png 58% of files have more coverage
72   199   31   5.54
32   148   0.43   13
13     2.38  
1    
 
  ModuleArbiterImpl       Line # 42 72 31 64.1% 0.64102566
 
  (104)
 
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  516 toggle public ModuleArbiterImpl() {
54  516 blocked = new HashMap();
55    }
56   
 
57  1439 toggle public boolean lockRequiredModule(final InternalModuleServiceCall call) throws InterruptException {
58  1439 call.pause();
59  1439 call.getInternalServiceProcess().setBlocked(true);
60  1439 try {
61  1439 final boolean result = lockRequiredModule(call.getInternalServiceProcess(), call.getQedeq(),
62    call.getService());
63  1439 ((InternalModuleServiceCallImpl) call).setNewlyBlockedModule(result);
64  1439 return result;
65    } finally {
66  1439 call.getInternalServiceProcess().setBlocked(false);
67  1439 call.resume();
68    }
69    }
70   
 
71  1439 toggle private boolean lockRequiredModule(final InternalServiceJob process,
72    final QedeqBo qedeq, final Service service) throws InterruptException {
73  1439 if (isAlreadyLocked(process, qedeq)) {
74  493 return false;
75    }
76  946 process.setBlocked(true);
77    // we try to get a lock, if not we wait
78  946 try {
79  947 while (!lock(process, qedeq, service)) {
80  1 final Object monitor = new Object();
81  1 synchronized (monitor) {
82  1 try {
83  1 monitor.wait(1000);
84    } catch (InterruptedException e) {
85  0 process.setInterruptedState();
86  0 throw new InterruptException(qedeq.getModuleAddress().createModuleContext());
87    }
88    }
89  1 if (Thread.interrupted()) {
90  0 process.setInterruptedState();
91  0 throw new InterruptException(qedeq.getModuleAddress().createModuleContext());
92    }
93    }
94    } finally {
95  946 process.setBlocked(false);
96    }
97  946 return true;
98    }
99   
 
100  1591 toggle public boolean unlockRequiredModule(final InternalModuleServiceCall call) {
101    // TODO 20130521 m31: do it without cast
102  1591 if (call != null && ((InternalModuleServiceCallImpl) call).getNewlyBlockedModule()) {
103  946 return unlockRequiredModule(call.getInternalServiceProcess(), call.getQedeq());
104    }
105  645 return false;
106    }
107   
 
108  946 toggle public boolean unlockRequiredModule(final ServiceJob process, final QedeqBo qedeq) {
109  946 return unlock(process, qedeq);
110   
111    }
112   
 
113  947 toggle private synchronized boolean lock(final ServiceJob process, final QedeqBo qedeq, final Service service) {
114  947 final String method = "lock";
115  947 if (Trace.isTraceOn()) {
116  0 Trace.info(CLASS, this, method, getName(process) + " is trying to lock " + qedeq.getName());
117    }
118  947 final ServiceJob origin = getProcess(qedeq);
119  947 if (origin != null) {
120  1 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  1 return false;
125    }
126  946 addLock(process, qedeq);
127  946 ((DefaultKernelQedeqBo) qedeq).setCurrentlyRunningService(service);
128  946 return true;
129    }
130   
 
131  946 toggle private synchronized boolean unlock(final ServiceJob process, final QedeqBo qedeq) {
132  946 final String method = "unlock";
133  946 if (Trace.isTraceOn()) {
134  0 Trace.info(CLASS, this, method, getName(process) + " is trying to unlock " + qedeq.getName());
135    }
136  946 ((DefaultKernelQedeqBo) qedeq).setCurrentlyRunningService(null);
137  946 final ServiceJob origin = getProcess(qedeq);
138  946 if (origin != null) {
139  946 if (origin.equals(process)) {
140  946 removeLock(process, qedeq);
141  946 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  1893 toggle private synchronized ServiceJob getProcess(final QedeqBo qedeq) {
164  1893 return (ServiceJob) blocked.get(qedeq);
165    }
166   
 
167  1439 toggle private synchronized boolean isAlreadyLocked(final ServiceJob process,
168    final QedeqBo qedeq) {
169  1439 return process.equals(blocked.get(qedeq));
170    }
171   
 
172  946 toggle private synchronized void addLock(final ServiceJob process, final QedeqBo qedeq) {
173  946 if (Trace.isTraceOn()) {
174  0 Trace.info(CLASS, this, "addLock", getName(process) + " locked successfuly " + qedeq.getName());
175    }
176  946 blocked.put(qedeq, process);
177    }
178   
 
179  946 toggle private synchronized void removeLock(final ServiceJob process, final QedeqBo qedeq) {
180  946 if (Trace.isTraceOn()) {
181  0 Trace.info(CLASS, this, "removeLock", getName(process) + " unlocked " + qedeq.getName());
182    }
183  946 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    }