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]