1 25 26 package org.objectweb.perseus.concurrency.pessimistic; 27 28 import org.objectweb.perseus.concurrency.api.ConcurrencyException; 29 import org.objectweb.perseus.concurrency.api.ConcurrencyManager; 30 import org.objectweb.perseus.concurrency.lib.ReadWriteLockValue; 31 import org.objectweb.perseus.dependency.api.DependencyGraph; 32 import org.objectweb.fractal.api.control.BindingController; 33 import org.objectweb.fractal.api.control.IllegalBindingException; 34 import org.objectweb.fractal.api.control.LifeCycleController; 35 import org.objectweb.fractal.api.control.IllegalLifeCycleException; 36 import org.objectweb.fractal.api.NoSuchInterfaceException; 37 import org.objectweb.util.monolog.api.Logger; 38 import org.objectweb.util.monolog.api.BasicLevel; 39 40 import java.util.Collection ; 41 import java.util.Map ; 42 import java.util.HashMap ; 43 import java.util.Iterator ; 44 45 48 public abstract class PessimisticConcurrencyManager 49 implements ConcurrencyManager, BindingController, 50 PessimisticConcurrencyManagerAC, LifeCycleController { 51 52 public final static short POLICY_UNDEFINED = 0; 53 public final static short POLICY_MUTEX = 1; 54 public final static short POLICY_RW_PRIORITY2READERS = 2; 55 public final static short POLICY_RW_FIFO = 3; 56 public final static String [] policyStringVal = { 57 "POLICY_UNDEFINED", 58 "POLICY_MUTEX", 59 "POLICY_RW_PRIORITY2READERS", 60 "POLICY_RW_FIFO" 61 }; 62 public final static String DEPENDENCY_GRAPH_BINDING = "dependency-graph"; 63 64 private String state = LifeCycleController.STOPPED; 65 66 70 private short policy = POLICY_RW_FIFO; 71 private final static short POLICY_LAST = POLICY_RW_FIFO; 72 75 protected Map locks; 76 77 protected DependencyGraph dg = null; 78 79 82 protected Map contextInfos; 83 84 protected Logger logger = null; 85 86 protected boolean thinLockAllowed = true; 87 88 public PessimisticConcurrencyManager() throws ConcurrencyException { 89 } 91 92 public PessimisticConcurrencyManager(short policy) throws ConcurrencyException { 93 } 95 96 103 protected abstract Object getState(Object ctx, 104 Object resourceId, 105 Lock lock) throws ConcurrencyException; 106 107 108 111 public String [] listFc() { 112 return new String [] {DEPENDENCY_GRAPH_BINDING}; 113 } 114 115 public Object lookupFc(String s) throws NoSuchInterfaceException { 116 if (DEPENDENCY_GRAPH_BINDING.equals(s)) { 117 return dg; 118 } 119 return null; 121 } 122 123 public void bindFc(String s, Object o) throws IllegalBindingException, 124 NoSuchInterfaceException { 125 try { 126 if ("logger".equals(s)) { 127 logger = (Logger) o; 128 } else if (DEPENDENCY_GRAPH_BINDING.equals(s)) { 129 if (dg != null) { 130 throw new IllegalBindingException(s + ": Already bound"); 131 } 132 dg = (DependencyGraph) o; 133 } 134 } catch (ClassCastException e) { 135 throw new IllegalBindingException(s + ":" + e.getMessage()); 136 } 137 } 139 140 public void unbindFc(String s) throws NoSuchInterfaceException { 141 if (DEPENDENCY_GRAPH_BINDING.equals(s)) { 142 dg = null; 143 } 144 } 146 147 public String getFcState() { 150 return state; 151 } 152 153 public void startFc() throws IllegalLifeCycleException { 154 if (state == LifeCycleController.STARTED) return; 155 locks = new HashMap (); 156 contextInfos = new HashMap (); 157 state = LifeCycleController.STARTED; 158 switch (policy) { 159 case POLICY_MUTEX: 160 logger.log(BasicLevel.INFO, "Pessimistic Concurrency Manager runs with POLICY_MUTEX."); 161 break; 162 case POLICY_RW_PRIORITY2READERS: 163 logger.log(BasicLevel.INFO, "Pessimistic Concurrency Manager runs with POLICY_RW_PRIORITY2READERS."); 164 break; 165 case POLICY_RW_FIFO: 166 logger.log(BasicLevel.INFO, "Pessimistic Concurrency Manager runs with POLICY_RW_FIFO."); 167 break; 168 } 169 } 170 171 public void stopFc() throws IllegalLifeCycleException { 172 if (state == LifeCycleController.STOPPED) return; 173 contextInfos = null; 174 locks = null; 175 state = LifeCycleController.STOPPED; 176 } 177 178 181 public void begin(Object ctx) { 182 getContextInfo(ctx).rollback = false; 183 } 184 185 public boolean validate(Object ctx) { 186 ContextInfo info = (ContextInfo) contextInfos.get(ctx); 187 return info == null || !info.rollback; 188 } 189 190 public void finalize(Object ctx) { 191 freeLocks(ctx); 192 } 193 private void freeLocks(Object ctx) { 194 boolean debug = logger != null && logger.isLoggable(BasicLevel.DEBUG); 195 if (debug) { 196 logger.log(BasicLevel.DEBUG, "Finalize the context: " + ctx); 197 } 198 synchronized (locks) { 199 Iterator entries = locks.entrySet().iterator(); 200 while (entries.hasNext()) { 201 Map.Entry entry = (Map.Entry ) entries.next(); 202 Lock lock = (Lock) entry.getValue(); 203 if (lock.close(ctx)) { 204 closeLock(lock, ctx); 205 entries.remove(); 206 } 207 } 208 } 209 contextInfos.remove(ctx); 210 } 211 212 public void closeLock(Lock lock, Object ctx) { 213 } 214 215 public void abort(Object ctx) { 216 freeLocks(ctx); 217 } 218 219 protected Object getResourceId(Object object) { 220 return object; 221 } 222 223 public Object readIntention(Object ctx, Object resource, Object thinLock) 224 throws ConcurrencyException { 225 Object resourceId = getResourceId(resource); 226 Lock lock = getLock(resourceId, null); 227 try { 228 lock.readIntention(ctx); 229 } catch (ConcurrencyException e) { 230 getContextInfo(ctx).rollback = true; 231 throw e; 232 } 233 return getState(ctx, resource, lock); 234 } 235 236 public Object writeIntention(Object ctx, Object resource, Object thinLock) 237 throws ConcurrencyException { 238 Object resourceId = getResourceId(resource); 239 if (thinLockAllowed && thinLock != null) { 240 Lock lock = getLock(resourceId, null); 244 try { 245 lock.readIntention(ctx); 246 } catch (ConcurrencyException e) { 247 getContextInfo(ctx).rollback = true; 248 throw e; 249 } 250 if (lock.getMax() >= ReadWriteLockValue.UPGRADE) { 251 return getState(ctx, resource, lock); 255 } 256 if (thinLock instanceof Collection ) { 258 for(Iterator it = ((Collection ) thinLock).iterator(); it.hasNext();) { 259 lock = getLock(resourceId, it.next()); 260 try { 261 lock.writeIntention(ctx); 262 } catch (ConcurrencyException e) { 263 getContextInfo(ctx).rollback = true; 264 throw e; 265 } 266 } 267 return getState(ctx, resource, lock); 270 } 271 } 272 Lock lock = getLock(resourceId, (thinLockAllowed ? thinLock : null)); 273 try { 274 lock.writeIntention(ctx); 275 } catch (ConcurrencyException e) { 276 getContextInfo(ctx).rollback = true; 277 throw e; 278 } 279 return getState(ctx, resource, lock); 280 } 281 282 private static class OID { 285 public Object oid; 286 public Object lockHints; 287 public OID(Object _oid, Object _lockHints) { 288 this.oid = _oid; 289 this.lockHints = _lockHints; 290 291 } 292 public boolean equals(Object o) { 293 return o instanceof OID 294 && ((OID) o).oid.equals(oid) 295 && ((OID) o).lockHints.equals(lockHints); 296 } 297 } 298 303 protected Lock getLock(Object oid, Object hints) { 304 if (thinLockAllowed && hints != null) { 305 oid = new OID(oid, hints); 306 } 307 synchronized (locks) { 308 Lock lock = (Lock) locks.get(oid); 309 if (lock == null) { 310 switch (policy) { 311 case POLICY_MUTEX: 312 lock = new MutexLock(hints, dg); 313 break; 314 case POLICY_RW_PRIORITY2READERS: 315 lock = new RWPri2RLock(hints, dg); 316 break; 317 case POLICY_RW_FIFO: 318 lock = new RWFifoLock(hints, dg); 319 break; 320 } 321 lock.oid = oid; 322 locks.put(oid, lock); 323 if (logger != null) { 324 lock.logger = logger; 325 if (logger.isLoggable(BasicLevel.DEBUG)) { 326 logger.log(BasicLevel.DEBUG, "Allocate a Lock for the oid: " + oid); 327 } 328 } 329 } 330 lock.reserve(); 331 return lock; 332 } 333 } 334 335 protected ContextInfo getContextInfo(Object ctxt) { 336 ContextInfo info = (ContextInfo) contextInfos.get(ctxt); 337 if (info == null) { 338 info = new ContextInfo(); 339 contextInfos.put(ctxt, info); 340 } 341 return info; 342 } 343 344 public String getPolicy() { 345 return policyStringVal[policy]; 346 } 347 348 public void setPolicy(String policy) throws IllegalLifeCycleException { 349 if (!LifeCycleController.STOPPED.equals(state)) { 350 throw new IllegalLifeCycleException("Cannot change lock policy of started pessimistic component"); 351 } 352 for (short p = 0; p <= POLICY_LAST; p++) { 353 if (policyStringVal[p].equals(policy)) { 354 this.policy = p; 355 return; 356 } 357 } 358 throw new IllegalArgumentException ("unrecognized locking policy: " + policy); 359 } 360 361 public boolean getThinkLockAllowed() { 362 return thinLockAllowed; 363 } 364 365 public void setThinkLockAllowed(boolean val) { 366 thinLockAllowed = val; 367 } 368 369 370 373 protected static class ContextInfo { 374 public boolean rollback; } 377 } 378 | Popular Tags |