ozeigermann 2004/12/17 08:36:22 Modified: transaction/src/java/org/apache/commons/transaction/locking GenericLockManager.java GenericLock.java Log: Fix for possbile lock out with incompatible preferred locks. Revision Changes Path 1.5 +7 -5 jakarta-commons/transaction/src/java/org/apache/commons/transaction/locking/GenericLockManager.java Index: GenericLockManager.java =================================================================== RCS file: /home/cvs/jakarta-commons/transaction/src/java/org/apache/commons/transaction/locking/GenericLockManager.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- GenericLockManager.java 16 Dec 2004 23:26:31 -0000 1.4 +++ GenericLockManager.java 17 Dec 2004 16:36:21 -0000 1.5 @@ -88,7 +88,9 @@ public boolean tryLock(Object ownerId, Object resourceId, int targetLockLevel, boolean reentrant) { GenericLock lock = (GenericLock) atomicGetOrCreateLock(resourceId); boolean acquired = lock.tryLock(ownerId, targetLockLevel, - reentrant ? GenericLock.COMPATIBILITY_REENTRANT : GenericLock.COMPATIBILITY_NONE); + reentrant ? GenericLock.COMPATIBILITY_REENTRANT : GenericLock.COMPATIBILITY_NONE, + false); + if (acquired) { addOwner(ownerId, lock); } 1.6 +44 -25 jakarta-commons/transaction/src/java/org/apache/commons/transaction/locking/GenericLock.java Index: GenericLock.java =================================================================== RCS file: /home/cvs/jakarta-commons/transaction/src/java/org/apache/commons/transaction/locking/GenericLock.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- GenericLock.java 17 Dec 2004 00:20:36 -0000 1.5 +++ GenericLock.java 17 Dec 2004 16:36:21 -0000 1.6 @@ -176,7 +176,7 @@ public boolean test(Object ownerId, int targetLockLevel, int compatibility) { boolean success = false; try { - success = tryLock(ownerId, targetLockLevel, compatibility); + success = tryLock(ownerId, targetLockLevel, compatibility, false); } finally { release(ownerId); } @@ -248,7 +248,7 @@ + System.currentTimeMillis()); } - if (tryLock(ownerId, targetLockLevel, compatibility)) { + if (tryLock(ownerId, targetLockLevel, compatibility, preferred)) { if (logger.isFinerEnabled()) { logger.logFiner( @@ -288,7 +288,7 @@ oldLock = (LockOwner) owners.get(ownerId); // this creates a new owner, so we do not need to // copy the old one - setLockLevel(ownerId, null, targetLockLevel); + setLockLevel(ownerId, null, targetLockLevel, preferred); // finally wait wait(remaining); @@ -299,14 +299,18 @@ // following check // and not to have it in case of success either // as there will be an ordinary lock then - owners.put(ownerId, oldLock); + if (oldLock != null) { + owners.put(ownerId, oldLock); + } else { + owners.remove(ownerId); + } } } else { wait(remaining); } - if (tryLock(ownerId, targetLockLevel, compatibility)) { + if (tryLock(ownerId, targetLockLevel, compatibility, preferred)) { if (logger.isFinerEnabled()) { logger.logFiner( @@ -394,37 +398,43 @@ for (Iterator it = owners.values().iterator(); it.hasNext();) { LockOwner owner = (LockOwner) it.next(); - buf.append("- ").append(owner.ownerId.toString()).append(": ").append(owner.lockLevel).append("\n"); + buf.append("- ").append(owner.ownerId.toString()).append(": ").append(owner.lockLevel) + .append(owner.intention ? " intention" : " acquired").append("\n"); } return buf.toString(); } protected synchronized LockOwner getMaxLevelOwner() { - return getMaxLevelOwner(null, -1); + return getMaxLevelOwner(null, -1, false); } - protected synchronized LockOwner getMaxLevelOwner(LockOwner reentrantOwner) { - return getMaxLevelOwner(reentrantOwner, -1); + protected synchronized LockOwner getMaxLevelOwner(LockOwner reentrantOwner, boolean preferred) { + return getMaxLevelOwner(reentrantOwner, -1, preferred); } - protected synchronized LockOwner getMaxLevelOwner(int supportLockLevel) { - return getMaxLevelOwner(null, supportLockLevel); + protected synchronized LockOwner getMaxLevelOwner(int supportLockLevel, boolean preferred) { + return getMaxLevelOwner(null, supportLockLevel, preferred); } - protected synchronized LockOwner getMaxLevelOwner(LockOwner reentrantOwner, int supportLockLevel) { + protected synchronized LockOwner getMaxLevelOwner(LockOwner reentrantOwner, + int supportLockLevel, boolean preferred) { LockOwner maxOwner = null; for (Iterator it = owners.values().iterator(); it.hasNext();) { LockOwner owner = (LockOwner) it.next(); if (owner.lockLevel != supportLockLevel && !owner.equals(reentrantOwner) - && (maxOwner == null || maxOwner.lockLevel < owner.lockLevel)) { + && (maxOwner == null || maxOwner.lockLevel < owner.lockLevel) + // if we are a preferred lock we must not interfere with other intention + // locks as we otherwise might mututally lock without resolvation + && !(preferred && owner.intention)) { maxOwner = owner; } } return maxOwner; } - protected synchronized void setLockLevel(Object ownerId, LockOwner lock, int targetLockLevel) { + protected synchronized void setLockLevel(Object ownerId, LockOwner lock, int targetLockLevel, + boolean intention) { // be sure there exists at most one lock per owner if (lock != null) { @@ -440,6 +450,7 @@ } lock.lockLevel = targetLockLevel; + lock.intention = intention; } else { if (logger.isFinestEnabled()) { @@ -453,11 +464,12 @@ + System.currentTimeMillis()); } - owners.put(ownerId, new LockOwner(ownerId, targetLockLevel)); + owners.put(ownerId, new LockOwner(ownerId, targetLockLevel, intention)); } } - protected synchronized boolean tryLock(Object ownerId, int targetLockLevel, int compatibility) { + protected synchronized boolean tryLock(Object ownerId, int targetLockLevel, int compatibility, + boolean preferred) { LockOwner myLock = (LockOwner) owners.get(ownerId); @@ -469,12 +481,12 @@ return true; } else { // our own lock will not be compromised by ourself - highestOwner = getMaxLevelOwner(myLock); + highestOwner = getMaxLevelOwner(myLock, preferred); } } else if (compatibility == COMPATIBILITY_SUPPORT) { // we are compatible with any other lock owner holding // the same lock level - highestOwner = getMaxLevelOwner(targetLockLevel); + highestOwner = getMaxLevelOwner(targetLockLevel, preferred); } else if (compatibility == COMPATIBILITY_REENTRANT_AND_SUPPORT) { if (myLock != null && targetLockLevel <= myLock.lockLevel) { @@ -482,7 +494,7 @@ return true; } else { // our own lock will not be compromised by ourself and same lock level - highestOwner = getMaxLevelOwner(myLock, targetLockLevel); + highestOwner = getMaxLevelOwner(myLock, targetLockLevel, preferred); } } else { highestOwner = getMaxLevelOwner(); @@ -498,7 +510,8 @@ // we are only allowed to acquire our locks if we do not compromise locks of any other lock owner if (isCompatible(targetLockLevel, currentLockLevel)) { - setLockLevel(ownerId, myLock, targetLockLevel); + // if we really have the lock, it no longer is an intention + setLockLevel(ownerId, myLock, targetLockLevel, false); return true; } else { return false; @@ -547,10 +560,16 @@ protected static class LockOwner { public Object ownerId; public int lockLevel; + public boolean intention; - public LockOwner(Object ownerId, int lockLevel) { + public LockOwner(Object ownerId, int lockLevel, boolean intention) { this.ownerId = ownerId; this.lockLevel = lockLevel; + this.intention = intention; + } + + public LockOwner(Object ownerId, int lockLevel) { + this(ownerId, lockLevel, false); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]