Index: src/main/java/org/jboss/cache/lock/PessimisticNodeBasedLockManager.java =================================================================== --- src/main/java/org/jboss/cache/lock/PessimisticNodeBasedLockManager.java (revision 8157) +++ src/main/java/org/jboss/cache/lock/PessimisticNodeBasedLockManager.java Fri Aug 07 11:53:48 BST 2009 @@ -26,6 +26,7 @@ import org.jboss.cache.Fqn; import org.jboss.cache.InvocationContext; import org.jboss.cache.NodeSPI; +import org.jboss.cache.PessimisticUnversionedNode; import org.jboss.cache.commands.CommandsFactory; import org.jboss.cache.factories.annotations.Inject; import static org.jboss.cache.lock.LockType.WRITE; @@ -137,12 +138,15 @@ do { + boolean skipLockAcquire = false; if (currentNode == null) { if (createIfNotExists) { // if the new node is to be marked as deleted, do not notify! - currentNode = parent.addChildDirect(childName, !skipNotification); + PessimisticUnversionedNode parentInternalNode = (PessimisticUnversionedNode) parent.getDelegationTarget(); + currentNode = parentInternalNode.addChildAndAcquireLock(childName, new LockAcquirer(ctx, WRITE, timeout, owner)); + skipLockAcquire = true; if (!created) { created = true; @@ -171,9 +175,13 @@ Fqn currentNodeFqn = currentNode.getFqn(); + if (!skipLockAcquire) + { - // actually acquire the lock we need. This method blocks. - acquireNodeLock(ctx, currentNode, owner, lockTypeRequired, timeout); + // actually acquire the lock we need. This method blocks. + acquireNodeLock(ctx, currentNode, owner, lockTypeRequired, timeout); + } - + + LockUtil.manageReverseRemove(ctx, currentNode, reverseRemoveCheck, createdNodes, commandsFactory); // make sure the lock we acquired isn't on a deleted node/is an orphan!! // look into invalidated nodes as well @@ -274,4 +282,31 @@ // Record the lock for release on method return or tx commit/rollback if (acquired) ctx.addLock(lock); } + + public class LockAcquirer + { + InvocationContext ctx; + LockType type; + long timeout; + Object owner; + + public LockAcquirer(InvocationContext ctx, LockType type, long timeout, Object owner) { + this.ctx = ctx; + this.type = type; + this.timeout = timeout; + this.owner = owner; -} + } + + public void acquire(NodeSPI node) + { + try + { + acquireNodeLock(ctx, node, owner, type, timeout); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + } + } + } +} Index: src/main/java/org/jboss/cache/PessimisticUnversionedNode.java =================================================================== --- src/main/java/org/jboss/cache/PessimisticUnversionedNode.java (revision 7168) +++ src/main/java/org/jboss/cache/PessimisticUnversionedNode.java Fri Aug 07 11:53:48 BST 2009 @@ -26,6 +26,7 @@ import org.jboss.cache.commands.legacy.write.CreateNodeCommand; import org.jboss.cache.lock.IdentityLock; import org.jboss.cache.lock.LockStrategyFactory; +import org.jboss.cache.lock.PessimisticNodeBasedLockManager; import org.jboss.cache.marshall.MarshalledValue; import org.jboss.cache.transaction.GlobalTransaction; import org.jboss.cache.util.FastCopyHashMap; @@ -161,7 +162,7 @@ throw new CacheException("Attempting to add a child [" + child.getFqn() + "] to [" + getFqn() + "]. Can only add direct children."); } - private NodeSPI getOrCreateChild(Object childName, GlobalTransaction gtx, boolean createIfNotExists, boolean notify) + private NodeSPI getOrCreateChild(Object childName, GlobalTransaction gtx, boolean createIfNotExists, boolean notify, PessimisticNodeBasedLockManager.LockAcquirer la) { NodeSPI child; if (childName == null) @@ -190,6 +191,7 @@ { if (notify) cache.getNotifier().notifyNodeCreated(childFqn, true, ctx); child = newChild; + if (la != null) la.acquire(child); children().put(childName, child); } } @@ -216,7 +218,7 @@ if (f.size() == 1) { GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction(); - return getOrCreateChild(f.getLastElement(), gtx, true, notify); + return getOrCreateChild(f.getLastElement(), gtx, true, notify, null); } else { @@ -228,9 +230,15 @@ public NodeSPI addChildDirect(Object o, boolean notify) { GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction(); - return getOrCreateChild(o, gtx, true, notify); + return getOrCreateChild(o, gtx, true, notify, null); } + public NodeSPI addChildAndAcquireLock(Object o, PessimisticNodeBasedLockManager.LockAcquirer la) + { + GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction(); + return getOrCreateChild(o, gtx, true, false, la); + } + @Override public NodeSPI getChildDirect(Fqn fqn) { @@ -331,7 +339,7 @@ @Override public NodeSPI getOrCreateChild(Object childName, GlobalTransaction gtx) { - return getOrCreateChild(childName, gtx, true, true); + return getOrCreateChild(childName, gtx, true, true, null); } @Override