Clover Coverage Report
Coverage timestamp: Fri May 24 2013 13:47:27 UTC
../../../../../../img/srcFileCovDistChart6.png 80% of files have more coverage
61   191   27   5.55
30   127   0.44   11
11     2.45  
1    
 
  ModuleArbiter       Line # 40 61 27 52% 0.51960784
 
  (97)
 
1    /* This file is part of the project "Hilbert II" - http://www.qedeq.org
2    *
3    * Copyright 2000-2013, 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.control;
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.QedeqBoSet;
25    import org.qedeq.kernel.bo.common.ServiceProcess;
26    import org.qedeq.kernel.bo.module.InternalServiceProcess;
27    import org.qedeq.kernel.bo.module.KernelQedeqBo;
28    import org.qedeq.kernel.bo.module.KernelQedeqBoSet;
29    import org.qedeq.kernel.se.common.Service;
30    import org.qedeq.kernel.se.visitor.InterruptException;
31   
32    /**
33    * Get locks for modules.
34    * TODO 20130508 m31: Currently we make no difference between read and write locks. We also lock
35    * a module during the whole plugin processing for that module. This could be limited to status
36    * changes only.
37    *
38    * @author Michael Meyling
39    */
 
40    public class ModuleArbiter {
41   
42    /** This class. */
43    private static final Class CLASS = ModuleArbiter.class;
44   
45    /** Map blocked QEDEQ modules to service processes. */
46    private final Map blocked;
47   
48    /**
49    * Constructor.
50    */
 
51  509 toggle public ModuleArbiter() {
52  509 blocked = new HashMap();
53    }
54   
55    /**
56    * Lock QEDEQ module for exclusive read and write access.
57    *
58    * @param process This process acquires the lock.
59    * @param qedeq Lock this module.
60    * @param service For this service.
61    * @return The process locked this module newly. Before this call the module was not locked.
62    * @throws InterruptException Lock acquirement interrupted.
63    */
 
64  2925 toggle public boolean lockRequiredModule(final InternalServiceProcess process,
65    final KernelQedeqBo qedeq, final Service service) throws InterruptException {
66  2925 if (isAlreadyLocked(process, qedeq)) {
67  134 return false;
68    }
69  2791 process.setBlocked(true);
70    // we try to get a lock, if not we wait
71  2791 try {
72  2791 while (!lock(process, qedeq, service)) {
73  0 final Object monitor = new Object();
74  0 synchronized (monitor) {
75  0 try {
76  0 monitor.wait(10000);
77    } catch (InterruptedException e) {
78  0 process.setFailureState();
79  0 throw new InterruptException(qedeq.getModuleAddress().createModuleContext());
80    }
81    }
82  0 if (Thread.interrupted()) {
83  0 process.setFailureState();
84  0 throw new InterruptException(qedeq.getModuleAddress().createModuleContext());
85    }
86    }
87    } finally {
88  2791 process.setBlocked(false);
89    }
90  2791 return true;
91    }
92   
93    /**
94    * Unlock module again.
95    *
96    * @param process This process must have acquired the lock.
97    * @param qedeq This module was locked before.
98    * @return Was this module even locked?
99    */
 
100  2806 toggle public boolean unlockRequiredModule(final ServiceProcess process, final KernelQedeqBo qedeq) {
101  2806 return unlock(process, qedeq);
102   
103    }
104   
 
105  2791 toggle private synchronized boolean lock(final ServiceProcess process, final KernelQedeqBo qedeq, final Service service) {
106  2791 final String method = "lock";
107  2791 if (Trace.isTraceOn()) {
108  0 Trace.info(CLASS, this, method, getName(process) + " is trying to lock " + qedeq.getName());
109    }
110  2791 final ServiceProcess origin = getProcess(qedeq);
111  2791 if (origin != null) {
112  0 if (Trace.isTraceOn()) {
113  0 Trace.info(CLASS, this, method, getName(process) + " failed to lock " + qedeq.getName()
114    + "\tbecause it is locked by " + getName(origin));
115    }
116  0 return false;
117    }
118  2791 addLock(process, qedeq);
119  2791 ((DefaultKernelQedeqBo) qedeq).setCurrentlyRunningService(service);
120  2791 return true;
121    }
122   
 
123  2806 toggle private synchronized boolean unlock(final ServiceProcess process, final KernelQedeqBo qedeq) {
124  2806 final String method = "unlock";
125  2806 if (Trace.isTraceOn()) {
126  0 Trace.info(CLASS, this, method, getName(process) + " is trying to unlock " + qedeq.getName());
127    }
128  2806 ((DefaultKernelQedeqBo) qedeq).setCurrentlyRunningService(null);
129  2806 final ServiceProcess origin = getProcess(qedeq);
130  2806 if (origin != null) {
131  2791 if (origin.equals(process)) {
132  2791 removeLock(process, qedeq);
133  2791 return true;
134    } else {
135  0 RuntimeException e = new IllegalArgumentException(getName(process) + " illegal unlock try for "
136    + qedeq.getName() + " which is currently locked by service process " + getName(origin));
137  0 Trace.fatal(CLASS, this, method, "Programming error. Unallowed unlock try.", e);
138    // TODO 20130324 m31: later on we might handle this differently but for now:
139  0 throw e;
140    }
141    } else {
142  15 if (Trace.isTraceOn()) {
143  0 Trace.info(CLASS, this, method, getName(process) + " unlock unnecessary " + qedeq.getName());
144    }
145  15 return false;
146    }
147    }
148   
 
149  0 toggle private String getName(final ServiceProcess process) {
150  0 return StringUtility.format(process.getId(), 3) + " "
151  0 + (process.getServiceCall() != null ? StringUtility.getLastDotString(
152    process.getServiceCall().getService().getServiceId()) : "");
153    }
154   
 
155  5597 toggle private synchronized ServiceProcess getProcess(final KernelQedeqBo qedeq) {
156  5597 return (ServiceProcess) blocked.get(qedeq);
157    }
158   
 
159  2925 toggle private synchronized boolean isAlreadyLocked(final ServiceProcess process,
160    final KernelQedeqBo qedeq) {
161  2925 return process.equals(blocked.get(qedeq));
162    }
163   
 
164  2791 toggle private synchronized void addLock(final ServiceProcess process, final KernelQedeqBo qedeq) {
165  2791 if (Trace.isTraceOn()) {
166  0 Trace.info(CLASS, this, "addLock", getName(process) + " locked successfuly " + qedeq.getName());
167    }
168  2791 blocked.put(qedeq, process);
169    }
170   
 
171  2791 toggle private synchronized void removeLock(final ServiceProcess process, final KernelQedeqBo qedeq) {
172  2791 if (Trace.isTraceOn()) {
173  0 Trace.info(CLASS, this, "removeLock", getName(process) + " unlocked " + qedeq.getName());
174    }
175  2791 blocked.remove(qedeq);
176    }
177   
 
178  0 toggle public synchronized QedeqBoSet getBlockedModules(final ServiceProcess process) {
179  0 KernelQedeqBoSet result = new KernelQedeqBoSet();
180  0 final Iterator i = blocked.entrySet().iterator();
181  0 while (i.hasNext()) {
182  0 final Map.Entry entry = (Map.Entry) i.next();
183  0 KernelQedeqBo qedeq = (KernelQedeqBo) entry.getKey();
184  0 if (process.equals(entry.getValue())) {
185  0 result.add(qedeq);
186    }
187    }
188  0 return result;
189    }
190   
191    }