Author: mircea.markus
Date: 2008-02-05 09:33:41 -0500 (Tue, 05 Feb 2008)
New Revision: 5290
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
core/trunk/src/main/java/org/jboss/cache/invocation/NodeInvocationDelegate.java
core/trunk/src/main/java/org/jboss/cache/lock/ReadWriteLockWithUpgrade.java
Log:
fixed tests
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2008-02-05
04:22:07 UTC (rev 5289)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2008-02-05
14:33:41 UTC (rev 5290)
@@ -14,10 +14,7 @@
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.annotations.ComponentName;
import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.lock.IsolationLevel;
-import org.jboss.cache.lock.LockingException;
-import org.jboss.cache.lock.NodeLock;
-import org.jboss.cache.lock.TimeoutException;
+import org.jboss.cache.lock.*;
import org.jboss.cache.marshall.MethodDeclarations;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionEntry;
@@ -80,9 +77,46 @@
public Object invoke(InvocationContext ctx) throws Throwable
{
if (rootNode == null) rootNode = cache.getRoot();
- return super.invoke(ctx);
+ try
+ {
+ return super.invoke(ctx);
+ } catch (LockingException le)
+ {
+ if (trace) log.trace("Locking exception occured, cleaning up locks." ,
le);
+ releaseLocks(ctx);
+ throw le;
+ } catch (TimeoutException te)
+ {
+ if (trace) log.trace("Locking exception occured, cleaning up locks." ,
te);
+ releaseLocks(ctx);
+ throw te;
+ }
}
+ /**
+ * If an issue appears while acquiring a lock (e.g. timeout exception, upgrade
exception) then acquire
+ * release all acquired locks before throwing it.
+ */
+ private void releaseLocks(InvocationContext ctx)
+ {
+ GlobalTransaction gtx = ctx.getGlobalTransaction();
+ if (trace) log.trace("Releasing existing locks. Global tx?" + gtx);
+ if (gtx != null)
+ {
+ TransactionEntry te = cache.getTransactionTable().get(gtx);
+ te.releaseAllLocksFIFO(gtx);
+ } else
+ {
+ Thread currentThread = Thread.currentThread();
+ List<NodeLock> locks = getLocks(currentThread);
+ for (NodeLock aLock : locks)
+ {
+ aLock.release(currentThread);
+ }
+ }
+ }
+
+
protected Object handlePutDataMethod(InvocationContext ctx, GlobalTransaction tx, Fqn
fqn, Map data, boolean createUndoOps) throws Throwable
{
return handlePutMethod(ctx, fqn);
@@ -251,9 +285,9 @@
if (trace) log.trace("There were new nodes created, skiping notification on
delete");
Object[] args = ctx.getMethodCall().getArgs();
if (trace) log.trace("Changing 'skipNotification' for method
'_remove' from " + args[args.length - 1] + " to true");
- args[args.length - 1] = Boolean.TRUE;
+ args[args.length - 1] = Boolean.TRUE;
}
-
+
Object retVal = nextInterceptor(ctx);
// and make sure we remove all nodes we've created for the sake of later
removal.
if (ctx.getGlobalTransaction() == null)
@@ -424,13 +458,14 @@
lockTypeRequired = NodeLock.LockType.WRITE;
}
+ Fqn currentNodeFqn = currentNode.getFqn();
// actually acquire the lock we need. This method blocks.
acquireNodeLock(currentNode, owner, gtx, lockTypeRequired, timeout);
manageReverseRemove(gtx, currentNode, reverseRemoveCheck);
// make sure the lock we acquired isn't on a deleted node/is an orphan!!
// look into invalidated nodes as well
- NodeSPI repeek = peekNode(ctx, currentNode.getFqn(), true, true, true);
+ NodeSPI repeek = peekNode(ctx, currentNodeFqn, true, true, true);
if (currentNode != repeek)
{
if (trace)
@@ -445,25 +480,32 @@
if (trace) log.trace("Parent has been deleted again. Go through the
lock method all over again.");
currentNode = rootNode;
parent = null;
- }
- else
+ } else
{
currentNode = parent;
+ currentIndex--;
parent = null;
if (System.currentTimeMillis() > expiryTime)
{
throw new TimeoutException("Unable to acquire lock on child node
" + new Fqn(currentNode.getFqn(), childName) + " after " + timeout + "
millis.");
}
+ if (trace) log.trace("Moving one level up, current node is :" +
currentNode);
}
- }
- else
+ } else
{
- if (currentNode.getFqn().equals(fqn))//we've just processed the last
child
+ if (currentNodeFqn.equals(fqn))//we've just processed the last child
{
break;
}
+ if (!fqn.isChildOrEquals(currentNode.getFqn()))
+ {
+ String message = new StringBuffer("currentNode instance changed the
FQN(").append(currentNode.getFqn())
+ .append(") and do not match the FQN on which we want to acquire
lock(").append(fqn).append(")").toString();
+ log.trace(message);
+ throw new LockingException(message);
+ }
parent = currentNode;
- currentIndex = currentNode.getFqn().size();
+ currentIndex = currentNodeFqn.size();
currentNode = currentNode.getChildDirect(fqn.get(currentIndex));
childName = fqn.get(currentIndex);
}
Modified: core/trunk/src/main/java/org/jboss/cache/invocation/NodeInvocationDelegate.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/invocation/NodeInvocationDelegate.java 2008-02-05
04:22:07 UTC (rev 5289)
+++
core/trunk/src/main/java/org/jboss/cache/invocation/NodeInvocationDelegate.java 2008-02-05
14:33:41 UTC (rev 5290)
@@ -491,4 +491,9 @@
if (!node.isValid())
throw new NodeNotValidException("Node " + getFqn() + " is not
valid. Perhaps it has been moved or removed.");
}
+
+ public String toString()
+ {
+ return node == null ? null : node.toString();
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/lock/ReadWriteLockWithUpgrade.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/lock/ReadWriteLockWithUpgrade.java 2008-02-05
04:22:07 UTC (rev 5289)
+++ core/trunk/src/main/java/org/jboss/cache/lock/ReadWriteLockWithUpgrade.java 2008-02-05
14:33:41 UTC (rev 5290)
@@ -16,7 +16,7 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
-/*
+/**
* <p> This class is similar to PreferredWriterReadWriteLock except that
* the read lock is upgradable to write lock. I.e., when a user calls
* upgradeLock(), it will release the read lock, wait for