1 24 package org.objectweb.jalisto.se.impl.lock; 25 26 import org.objectweb.jalisto.se.api.internal.DataWrapper; 27 import org.objectweb.jalisto.se.api.internal.multi.SessionMulti; 28 import org.objectweb.jalisto.se.exception.multi.LockException; 29 import org.objectweb.jalisto.se.exception.multi.SleepingException; 30 import org.objectweb.jalisto.se.JalistoFactory; 31 32 import java.io.Serializable ; 33 import java.util.*; 34 35 public class Lock implements Serializable { 36 37 private Lock() { 38 currentLock = NO_LOCK; 39 writeSession = ""; 40 transactionnalStates = new HashMap(); 41 readSessions = new LinkedList(); 42 sleepingSessions = new LinkedList(); 43 } 44 45 public void release() { 46 instances.add(this); 47 } 48 49 public synchronized int getCurrentAction(Object sessionId) { 50 int result = ObjectTransactionnalState.NO_ACTION; 51 if (transactionnalStates.containsKey(sessionId)) { 52 result = ((ObjectTransactionnalState) transactionnalStates.get(sessionId)).getCurrentAction(); 53 } 54 return result; 55 } 56 57 public synchronized DataWrapper getModifiedValue(Object sessionId) { 58 ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId); 59 if (image != null) { 60 return image.getCurrentValue(); 61 } 62 return null; 63 } 64 65 public synchronized short getUpdate(Object sessionId) { 66 ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId); 67 if (image != null) { 68 return image.getUpdate(); 69 } 70 return (short) -1; 71 } 72 73 public void update(Object sessionId) { 74 ((ObjectTransactionnalState) transactionnalStates.get(sessionId)).update(); 75 } 76 77 78 public synchronized void addTransactionnalValue(Object sessionId, DataWrapper value, 79 int action, short update) { 80 ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId); 82 if (image == null) { 83 image = new ObjectTransactionnalState(action, value, update); 84 transactionnalStates.put(sessionId, image); 85 } else { 86 image.setValue(action, value); 87 image.setUpdate(update); 88 } 89 } 90 91 public synchronized void updateTransactionnalValue(Object sessionId, DataWrapper value, short update) { 92 ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId); 94 if (image != null) { 95 image.setValue(image.getCurrentAction(), value); 96 image.setUpdate(update); 97 } 98 } 99 100 public synchronized boolean addSleepingSession(Object sessionId) { 101 if (currentLock == NO_LOCK) { 102 return false; 103 } 104 if (sleepingSessions.contains(sessionId)) { throw new LockException("dead lock : sessionId = " + String.valueOf(sessionId)); 106 } 107 DeadLockToken asleepingSession = DeadLockToken.getToken(sessionId); 108 if (sleepingSessions.isEmpty()) { 109 if (currentLock == READ_LOCK) { 110 for (int i = 0; i < readSessions.size(); i++) { 111 asleepingSession.waitFor(DeadLockToken.getToken(readSessions.get(i))); 112 } 113 } else if (currentLock == WRITE_LOCK) { 114 asleepingSession.waitFor(DeadLockToken.getToken(writeSession)); 115 } 116 } else { 117 asleepingSession.waitFor(DeadLockToken.getToken(sleepingSessions.getLast())); 118 } 119 sleepingSessions.addLast(sessionId); 120 return true; 121 } 122 123 private void wakeUpASession(Object releasingSessionId) { 124 if (!sleepingSessions.isEmpty()) { 125 Object awakingId = sleepingSessions.getFirst(); 126 DeadLockToken releasingSessionToken = DeadLockToken.getToken(releasingSessionId); 127 DeadLockToken awakingSessionToken = DeadLockToken.getToken(awakingId); 128 synchronized (awakingSessionToken) { 129 awakingSessionToken.noMoreWaitFor(releasingSessionToken); 130 if (awakingSessionToken.couldWakeUp()) { 131 sleepingSessions.remove(awakingId); 132 ((SessionMulti) JalistoFactory.getInternalFactory().getSessionById(awakingId)).wakeUp(); 133 } 134 } 135 } 136 } 137 138 public synchronized void resolveTimeOut(Object sessionId) { 139 DeadLockToken timeOutToken = DeadLockToken.getToken(sessionId); 140 if (sleepingSessions.contains(sessionId)) { int index = sleepingSessions.indexOf(sessionId); 142 if ((index + 1) < sleepingSessions.size()) { 143 DeadLockToken tokenWhoWaitForTimeOutToken = 144 DeadLockToken.getToken(sleepingSessions.get(index + 1)); 145 timeOutToken.timeOutWakeUp(tokenWhoWaitForTimeOutToken); 146 } else { 147 timeOutToken.timeOutWakeUp(null); 148 } 149 sleepingSessions.remove(sessionId); 150 } else { 151 DeadLockToken tokenWhoWaitForTimeOutToken = null; 153 try { 154 tokenWhoWaitForTimeOutToken = DeadLockToken.getToken(sleepingSessions.getFirst()); 155 } catch (NoSuchElementException e) { 156 } 157 timeOutToken.timeOutWakeUp(tokenWhoWaitForTimeOutToken); 158 } 159 } 160 161 164 165 public synchronized void takeReadLock(Object sessionId) { 166 if (currentLock == NO_LOCK) { 170 if (sleepingSessions.isEmpty()) { currentLock = READ_LOCK; 172 } else { 173 DeadLockToken awakingToken = DeadLockToken.getToken(sleepingSessions.getFirst()); 174 if (awakingToken.isWaitingFor(DeadLockToken.getToken(sessionId))) { currentLock = READ_LOCK; 176 } else { throw new SleepingException("takeReadLock case 3", this); 178 } 179 } 180 } else if (currentLock == READ_LOCK) { 184 if (!readSessions.contains(sessionId)) { 185 if (!sleepingSessions.isEmpty()) { 186 throw new SleepingException("takeReadLock case 6", this); } } } else if (currentLock == WRITE_LOCK) { 192 if (!writeSession.equals(sessionId)) { throw new SleepingException("takeReadLock case 8", this); 194 } } 196 if (!readSessions.contains(sessionId)) { 197 readSessions.addLast(sessionId); 198 } 199 } 200 201 public synchronized void takeWriteLock(Object sessionId) { 202 if (currentLock == NO_LOCK) { 206 if (sleepingSessions.isEmpty()) { currentLock = WRITE_LOCK; 208 } else { 209 DeadLockToken awakingToken = DeadLockToken.getToken(sleepingSessions.getFirst()); 210 if (awakingToken.isWaitingFor(DeadLockToken.getToken(sessionId))) { currentLock = WRITE_LOCK; 212 } else { throw new SleepingException(this); 214 } 215 } 216 } else if (currentLock == READ_LOCK) { 220 if (readSessions.contains(sessionId)) { 221 if (readSessions.size() > 1) { wakeUpASession(sessionId); 223 throw new SleepingException(this); 224 } else { currentLock = WRITE_LOCK; 226 } 227 } else { throw new SleepingException(this); 229 } 230 } else { if (writeSession.equals(sessionId)) { return; 235 } else { throw new SleepingException(this); 237 } 238 } 239 writeSession = sessionId; 240 } 241 242 public synchronized void releaseReadLock(Object sessionId) { 243 if (currentLock == WRITE_LOCK) { 244 if (writeSession.equals(sessionId)) { 245 readSessions.remove(sessionId); 246 } else { 247 throw new LockException(); 248 } 249 } else { 250 readSessions.remove(sessionId); 251 if (readSessions.isEmpty()) { 252 currentLock = NO_LOCK; 253 } 254 wakeUpASession(sessionId); 255 } 256 } 257 258 public synchronized void releaseWriteLock(Object sessionId) { 259 if ((currentLock == WRITE_LOCK) && (writeSession.equals(sessionId))) { 260 readSessions.remove(sessionId); 261 currentLock = NO_LOCK; 262 writeSession = ""; 263 wakeUpASession(sessionId); 264 } else { 265 throw new LockException(); 266 } 267 } 268 269 public synchronized void releaseAllLock(Object sessionId) { 270 if ((currentLock == WRITE_LOCK) && (writeSession.equals(sessionId))) { 271 writeSession = ""; 272 currentLock = NO_LOCK; 273 } else if ((currentLock == READ_LOCK) && (readSessions.contains(sessionId))) { 274 currentLock = NO_LOCK; 275 } 276 readSessions.remove(sessionId); 277 transactionnalStates.remove(sessionId); 278 wakeUpASession(sessionId); 279 } 280 281 282 285 286 public synchronized boolean canBeDeleted() { 287 return ((currentLock == NO_LOCK) && 288 transactionnalStates.isEmpty() && 289 sleepingSessions.isEmpty()); 290 } 291 292 public synchronized boolean hasModifiedValueWith(Object sessionId) { 293 return (transactionnalStates.get(sessionId) != null); 294 } 295 296 public synchronized boolean hasReadLockWith(Object sessionId) { 297 return readSessions.contains(sessionId); 298 } 299 300 public synchronized boolean mustTakeWriteLock(Object sessionId) { 301 ObjectTransactionnalState itm = (ObjectTransactionnalState) transactionnalStates.get(sessionId); 302 return ((itm.getCurrentAction() != ObjectTransactionnalState.READ_ACTION) && 303 (itm.getCurrentAction() != ObjectTransactionnalState.NO_ACTION)); 304 } 305 306 public synchronized boolean hasWriteLockWith(Object sessionId) { 307 return writeSession.equals(sessionId); 308 } 309 310 public synchronized boolean hasToBeRemoveForExtentWith(Object sessionId) { 311 if (transactionnalStates.containsKey(sessionId)) { 312 ObjectTransactionnalState itm = (ObjectTransactionnalState) transactionnalStates.get(sessionId); 313 return (itm.getCurrentAction() == ObjectTransactionnalState.DELETE_ACTION); 314 } 315 return false; 316 } 317 318 321 322 private String getLockAsString(int lock) { 323 if (lock == NO_LOCK) { 324 return "no_lock"; 325 } else if (lock == READ_LOCK) { 326 return "r_lock"; 327 } else { 328 return "w_lock"; 329 } 330 } 331 332 333 public String toString() { 334 StringBuffer sb = new StringBuffer (); 335 sb.append(getLockAsString(currentLock)).append(" ").append(super.toString()).append("\n"); 336 sb.append("\tRead Locks : ").append(readSessions).append("\n"); 337 sb.append("\tWrite Lock : ").append(writeSession).append("\n"); 338 sb.append("\tActions : \n"); 339 sb.append("\tSleeping session : ").append(sleepingSessions).append("\n"); 340 Iterator sessions = transactionnalStates.keySet().iterator(); 341 if (!sessions.hasNext()) { 342 sb.append("CurrentStates is empty"); 343 } 344 while (sessions.hasNext()) { 345 Object key = sessions.next(); 346 ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(key); 347 sb.append(" ").append(image); 348 } 349 sb.append("\n"); 350 return sb.toString(); 351 } 352 353 354 private HashMap transactionnalStates; 355 private LinkedList readSessions; 356 private LinkedList sleepingSessions; 357 358 private Object writeSession; private int currentLock; 360 361 362 static final long serialVersionUID = -7589377087694761459L; 363 364 365 public static final int NO_LOCK = 0; 366 public static final int READ_LOCK = 1; 367 public static final int WRITE_LOCK = 2; 368 369 private static ArrayList instances = new ArrayList(); 370 371 public static Lock newInstance() { 372 if (instances.isEmpty()) { 373 return new Lock(); 374 } else { 375 return (Lock) instances.remove(0); 376 } 377 } 378 } 379 | Popular Tags |