[jbosscache-commits] JBoss Cache SVN: r6181 - in core/trunk/src: main/java/org/jboss/cache/commands/legacy/read and 8 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Fri Jul 4 08:13:44 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-07-04 08:13:44 -0400 (Fri, 04 Jul 2008)
New Revision: 6181

Added:
   core/trunk/src/main/java/org/jboss/cache/commands/legacy/read/
   core/trunk/src/main/java/org/jboss/cache/commands/legacy/read/PessGetChildrenNamesCommand.java
   core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/ReadCommittedLockParentTest.java
   core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadLockParentTest.java
Modified:
   core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java
   core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java
   core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java
   core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java
   core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java
   core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java
   core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java
Log:
Re-added lockParentForInsertRemove tests with MVCC


Added: core/trunk/src/main/java/org/jboss/cache/commands/legacy/read/PessGetChildrenNamesCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/legacy/read/PessGetChildrenNamesCommand.java	                        (rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/commands/legacy/read/PessGetChildrenNamesCommand.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -0,0 +1,23 @@
+package org.jboss.cache.commands.legacy.read;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.commands.read.GetChildrenNamesCommand;
+import org.jboss.cache.invocation.InvocationContext;
+
+public class PessGetChildrenNamesCommand extends GetChildrenNamesCommand
+{
+   public PessGetChildrenNamesCommand()
+   {
+   }
+
+   public PessGetChildrenNamesCommand(Fqn fqn)
+   {
+      super(fqn);
+   }
+
+   @Override
+   public Object perform(InvocationContext ctx)
+   {
+      return fetchChildrenNames(ctx);
+   }
+}

Modified: core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -4,9 +4,9 @@
 import org.jboss.cache.NodeSPI;
 import org.jboss.cache.commands.Visitor;
 import org.jboss.cache.invocation.InvocationContext;
+import org.jboss.cache.mvcc.ReadCommittedNode;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -33,19 +33,13 @@
       this.fqn = fqn;
    }
 
-   /**
-    * Retrieves the names of children for a specific Fqn.
-    *
-    * @param ctx invocation context
-    * @return a Set<Object> of child names, for a given Fqn, or null if the Fqn refers to a node that does not exist.
-    */
-   public Object perform(InvocationContext ctx)
+   protected final Set<Object> fetchChildrenNames(InvocationContext ctx)
    {
       NodeSPI n = fqn == null ? null : ctx.lookUpNode(fqn);
       if (n == null || n.isDeleted()) return null;
       Map childrenMap = n.getChildrenMapDirect();
-      if (childrenMap == null || childrenMap.isEmpty()) return Collections.emptySet();
-      Set childNames = new HashSet();
+      if (childrenMap == null || childrenMap.isEmpty()) return new HashSet<Object>();
+      Set<Object> childNames = new HashSet<Object>();
       Collection s = childrenMap.values();
       // prune deleted children - JBCACHE-1136
       for (Object c : s)
@@ -61,6 +55,36 @@
    }
 
 
+   /**
+    * Retrieves the names of children for a specific Fqn.
+    *
+    * @param ctx invocation context
+    * @return a Set<Object> of child names, for a given Fqn, or null if the Fqn refers to a node that does not exist.
+    */
+   public Object perform(InvocationContext ctx)
+   {
+      Set<Object> childNames = fetchChildrenNames(ctx);
+
+      // check for *new* children added.
+      for (Map.Entry<Fqn, NodeSPI> n : ctx.getLookedUpNodes().entrySet())
+      {
+         if (n.getKey().getParent().equals(fqn))
+         {
+            if (n.getValue().isDeleted())
+            {
+               childNames.remove(n.getKey());
+            }
+            else if (((ReadCommittedNode) n.getValue()).isCreated())
+            {
+               childNames.add(n.getKey().getLastElement());
+            }
+         }
+      }
+
+      return childNames;
+   }
+
+
    public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
    {
       return visitor.visitGetChildrenNamesCommand(ctx, this);

Modified: core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -2,6 +2,7 @@
 
 import org.jboss.cache.Fqn;
 import org.jboss.cache.commands.ReplicableCommand;
+import org.jboss.cache.commands.legacy.read.PessGetChildrenNamesCommand;
 import org.jboss.cache.commands.legacy.write.PessClearDataCommand;
 import org.jboss.cache.commands.legacy.write.PessCreateNodeCommand;
 import org.jboss.cache.commands.legacy.write.PessMoveCommand;
@@ -10,6 +11,7 @@
 import org.jboss.cache.commands.legacy.write.PessPutKeyValueCommand;
 import org.jboss.cache.commands.legacy.write.PessRemoveKeyCommand;
 import org.jboss.cache.commands.legacy.write.PessRemoveNodeCommand;
+import org.jboss.cache.commands.read.GetChildrenNamesCommand;
 import org.jboss.cache.commands.write.ClearDataCommand;
 import org.jboss.cache.commands.write.CreateNodeCommand;
 import org.jboss.cache.commands.write.MoveCommand;
@@ -33,6 +35,14 @@
 public class PessimisticCommandsFactoryImpl extends OptimisticCommandsFactoryImpl
 {
    @Override
+   public GetChildrenNamesCommand buildGetChildrenNamesCommand(Fqn fqn)
+   {
+      GetChildrenNamesCommand command = new PessGetChildrenNamesCommand(fqn);
+      command.initialize(dataContainer);
+      return command;
+   }
+
+   @Override
    public PutDataMapCommand buildPutDataMapCommand(GlobalTransaction gtx, Fqn fqn, Map data)
    {
       PutDataMapCommand cmd = new PessPutDataMapCommand(gtx, fqn, data);
@@ -103,6 +113,13 @@
       boolean skipSetParams = false;
       switch (id)
       {
+         case GetChildrenNamesCommand.METHOD_ID:
+         {
+            GetChildrenNamesCommand returnValue = new PessGetChildrenNamesCommand();
+            returnValue.initialize(dataContainer);
+            command = returnValue;
+            break;
+         }
          case MoveCommand.METHOD_ID:
          {
             MoveCommand returnValue = new PessMoveCommand();

Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -56,6 +56,7 @@
    DataContainer dataContainer;
    NodeFactory nodeFactory;
    private long defaultLockAcquisitionTimeout;
+   private boolean lockParentForChildInsertRemove;
 
    @Inject
    public void setDependencies(LockManager lockManager, DataContainer dataContainer, NodeFactory nodeFactory)
@@ -70,8 +71,19 @@
    {
       allowWriteSkew = configuration.isAllowWriteSkew();
       defaultLockAcquisitionTimeout = configuration.getLockAcquisitionTimeout();
+      lockParentForChildInsertRemove = configuration.isLockParentForChildInsertRemove();
    }
 
+   private boolean parentLockNeeded(NodeSPI parent)
+   {
+      return lockParentForChildInsertRemove || (parent != null && parent.isLockForChildInsertRemove());
+   }
+
+   private boolean parentLockNeeded(Fqn parent)
+   {
+      return parentLockNeeded(dataContainer.peek(parent, true, true));
+   }
+
    @Override
    protected boolean doBeforeCall(InvocationContext ctx, VisitableCommand command)
    {
@@ -115,11 +127,15 @@
 
       Fqn parentFqn = nodeFqn.getParent();
       // inspect parent
-      boolean needToCopyParent = lock(ctx, parentFqn);
+      boolean needToCopyParent = false;
+      boolean parentLockNeeded = parentLockNeeded(parentFqn);
+      if (parentLockNeeded)
+      {
+         needToCopyParent = lock(ctx, parentFqn);
+         // Ensure the node is in the context.
+         putNodeInContext(ctx, parentFqn, needToCopyParent);
+      }
 
-      // Ensure the node is in the context.
-      putNodeInContext(ctx, parentFqn, needToCopyParent);
-
       boolean needToCopyNode = lock(ctx, nodeFqn);
 
       // Ensure the node is in the context.
@@ -130,9 +146,8 @@
       // update child ref on parent to point to child as this is now a copy.
       if (node != null && !(node instanceof NullMarkerNode))
       {
-         if (needToCopyNode || needToCopyParent)
+         if (parentLockNeeded && (needToCopyNode || needToCopyParent))
          {
-
             ReadCommittedNode parent = (ReadCommittedNode) ctx.lookUpNode(parentFqn);
             parent.addChildDirect(nodeFactory.createNodeInvocationDelegate((InternalNode) node.getDelegationTarget()));
          }
@@ -345,13 +360,13 @@
       // for non-transactional stuff.
       if (ctx.getTransaction() == null)
       {
-         if (trace) log.trace("Releasing locks for thread " + Thread.currentThread());
          List<Fqn> locks;
          if (!(locks = ctx.getLocks()).isEmpty())
          {
             // clean up.
             Fqn[] fqnsToUnlock = new Fqn[locks.size()];
             fqnsToUnlock = locks.toArray(fqnsToUnlock);
+            if (trace) log.trace("Releasing locks for thread " + Thread.currentThread() + " on fqns " + locks);
             Object owner = Thread.currentThread();
 
             for (int i = fqnsToUnlock.length - 1; i > -1; i--)
@@ -485,8 +500,9 @@
          Fqn parentFqn = fqn.getParent();
          NodeSPI parent = getWrappedNode(context, parentFqn, false, createIfAbsent, false);
          // do we need to lock the parent to create children?
+         boolean parentLockNeeded = parentLockNeeded(parent);
          // get a lock on the parent.
-         if (lock(context, parentFqn))
+         if (parentLockNeeded && lock(context, parentFqn))
          {
             ReadCommittedNode parentRCN = (ReadCommittedNode) context.lookUpNode(parentFqn);
             parentRCN.copyNodeForUpdate(dataContainer, allowWriteSkew, context, nodeFactory);
@@ -496,12 +512,19 @@
          lock(context, fqn);
 
          NodeSPI temp = parent.getOrCreateChild(fqn.getLastElement(), context.getGlobalTransaction());
+         // TODO: warning, hack!  There is a race condition here.  Add a way to create nodes without attaching to a parent.
+         parent.removeChildDirect(fqn.getLastElement());
+
          in = (InternalNode) ((NodeInvocationDelegate) temp).getDelegationTarget();
          ReadCommittedNode wrapped = nodeFactory.createMvccNode(in);
+         wrapped.setCreated(true);
          context.putLookedUpNode(fqn, wrapped);
          wrapped.copyNodeForUpdate(dataContainer, allowWriteSkew, context, nodeFactory);
-         // since we copied the child make sure we update the parent's ref
-         parent.addChildDirect(nodeFactory.createNodeInvocationDelegate(wrapped.getNode()));
+//         if (parentLockNeeded)
+//         {
+//            // since we copied the child make sure we update the parent's ref
+//            parent.addChildDirect(nodeFactory.createNodeInvocationDelegate(wrapped.getNode()));
+//         }
 
          return wrapped;
       }

Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -3,6 +3,7 @@
 import org.jboss.cache.DataContainer;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.NodeFactory;
+import org.jboss.cache.NodeNotExistsException;
 import org.jboss.cache.NodeSPI;
 import org.jboss.cache.invocation.InvocationContext;
 import org.jboss.cache.invocation.NodeInvocationDelegate;
@@ -19,6 +20,7 @@
 {
    protected volatile InternalNode backup;
    protected boolean changed;
+   protected boolean created;
 
    public ReadCommittedNode(InternalNode node)
    {
@@ -50,6 +52,15 @@
       }
    }
 
+   protected NodeSPI lookupParent(Fqn fqn, InvocationContext ctx, DataContainer container)
+   {
+      Fqn parentFqn = fqn.getParent();
+      NodeSPI parent = ctx.lookUpNode(parentFqn);
+      if (parent != null) return parent;
+      parent = container.peek(parentFqn);
+      return parent;
+   }
+
    protected void updateNode(DataContainer container, NodeFactory nf, InvocationContext ctx)
    {
       if (isDeleted())
@@ -57,7 +68,7 @@
          Fqn fqn = getFqn();
          if (!fqn.isRoot())
          {
-            NodeSPI parent = ctx.lookUpNode(fqn.getParent()); // this will be there since parent nodes are locked when a child is removed.
+            NodeSPI parent = lookupParent(fqn, ctx, container);
             parent.removeChildDirect(fqn.getLastElement());
          }
          else
@@ -65,6 +76,14 @@
             log.warn("Attempting to remove the root node.  Not doing anything!");
          }
       }
+      else if (created)
+      {
+         Fqn fqn = getFqn();
+         NodeSPI parent = lookupParent(fqn, ctx, container);
+         if (parent == null)
+            throw new NodeNotExistsException("Cannot add node " + fqn + " to data structure since its parent is null!");
+         parent.addChildDirect(nf.createNodeInvocationDelegate(node));
+      }
       else
       {
          ((NodeReference) backup).setDelegate(((NodeReference) node).getDelegate());
@@ -89,6 +108,16 @@
       this.changed = changed;
    }
 
+   public boolean isCreated()
+   {
+      return created;
+   }
+
+   public void setCreated(boolean created)
+   {
+      this.created = created;
+   }
+
    public InternalNode getNode()
    {
       return node;

Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -3,6 +3,7 @@
 import org.jboss.cache.DataContainer;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.NodeFactory;
+import org.jboss.cache.NodeNotExistsException;
 import org.jboss.cache.NodeSPI;
 import org.jboss.cache.invocation.InvocationContext;
 import org.jboss.cache.optimistic.DataVersion;
@@ -55,28 +56,36 @@
    {
       if (trace)
          log.trace("Updating RepeatableReadNode.  IsDeleted? " + isDeleted() + " isValid? " + isValid() + " isChanged? " + isChanged());
-      if (getFqn().isRoot())
+
+      Fqn fqn = getFqn();
+      if (fqn.isRoot())
       {
          dataContainer.setRoot(nf.createNodeInvocationDelegate(node));
       }
+      else if (created)
+      {
+         NodeSPI parent = lookupParent(fqn, ctx, dataContainer);
+         if (parent == null)
+            throw new NodeNotExistsException("Cannot add node " + fqn + " to data structure since its parent is null!");
+         parent.addChildDirect(nf.createNodeInvocationDelegate(node));
+      }
       else
       {
-         Fqn fqn = getFqn();
-         NodeSPI parent = dataContainer.peek(fqn.getParent());
+         NodeSPI parent = lookupParent(fqn, ctx, dataContainer);
          if (parent != null)
          {
             Object name = fqn.getLastElement();
-            NodeSPI oldChild = parent.getChildDirect(name);
+//            NodeSPI oldChild = parent.getChildDirect(name);
             if (isDeleted())
             {
                parent.removeChildDirect(name);
             }
             else
             {
-               if (oldChild != null)
-               {
-                  node.setChildrenMapDirect(oldChild.getChildrenMapDirect());
-               }
+//               if (oldChild != null)
+//               {
+//                  node.setChildrenMapDirect(oldChild.getChildrenMapDirect());
+//               }
                parent.addChildDirect(nf.createNodeInvocationDelegate(node));
             }
          }

Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -36,7 +36,9 @@
    protected LockManager lockManager;
    protected InvocationContextContainer icc;
    protected boolean repeatableRead = true;
+   protected boolean lockParentForChildInsertRemove = false;
 
+
    @BeforeMethod
    public void setUp()
    {
@@ -44,6 +46,7 @@
       cache.getConfiguration().setNodeLockingScheme(NodeLockingScheme.MVCC);
       cache.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
       cache.getConfiguration().setIsolationLevel(repeatableRead ? IsolationLevel.REPEATABLE_READ : IsolationLevel.READ_COMMITTED);
+      cache.getConfiguration().setLockParentForChildInsertRemove(lockParentForChildInsertRemove);
       // reduce lock acquisition timeout so this doesn't take forever to run
       cache.getConfiguration().setLockAcquisitionTimeout(200); // 200 ms
       cache.start();
@@ -77,7 +80,10 @@
    {
       tm.begin();
       cache.put(AB, "k", "v");
-      assertLocked(Fqn.ROOT);
+      if (lockParentForChildInsertRemove)
+         assertLocked(Fqn.ROOT);
+      else
+         assertNotLocked(Fqn.ROOT);
       assertLocked(A);
       assertLocked(AB);
       assertNotLocked(ABC);
@@ -99,7 +105,10 @@
       cache.put(ABC, "k", "v");
       assertNotLocked(Fqn.ROOT);
       assertNotLocked(A);
-      assertLocked(AB);
+      if (lockParentForChildInsertRemove)
+         assertLocked(AB);
+      else
+         assertNotLocked(AB);
       assertLocked(ABC);
       tm.commit();
 
@@ -110,7 +119,10 @@
    {
       tm.begin();
       cache.put(AB, Collections.singletonMap("k", "v"));
-      assertLocked(Fqn.ROOT);
+      if (lockParentForChildInsertRemove)
+         assertLocked(Fqn.ROOT);
+      else
+         assertNotLocked(Fqn.ROOT);
       assertLocked(A);
       assertLocked(AB);
       assertNotLocked(ABC);
@@ -133,7 +145,10 @@
       cache.put(ABC, Collections.singletonMap("k", "v"));
       assertNotLocked(Fqn.ROOT);
       assertNotLocked(A);
-      assertLocked(AB);
+      if (lockParentForChildInsertRemove)
+         assertLocked(AB);
+      else
+         assertNotLocked(AB);
       assertLocked(ABC);
       tm.commit();
 
@@ -150,7 +165,10 @@
       tm.begin();
       cache.removeNode(AB);
       assertLocked(AB);
-      assertLocked(A);
+      if (lockParentForChildInsertRemove)
+         assertLocked(A);
+      else
+         assertNotLocked(A);
       assertNotLocked(Fqn.ROOT);
       tm.commit();
       assert cache.getNode(AB) == null : "Should not exist";
@@ -167,7 +185,10 @@
       tm.begin();
       cache.evict(AB);
       assertLocked(AB);
-      assertLocked(A);
+      if (lockParentForChildInsertRemove)
+         assertLocked(A);
+      else
+         assertNotLocked(A);
       assertNotLocked(Fqn.ROOT);
       tm.commit();
       assert cache.getNode(AB) == null : "Should not exist";
@@ -190,7 +211,10 @@
       assertLocked(AB);
       assertLocked(ABC);
       assertLocked(ABCD);
-      assertLocked(A);
+      if (lockParentForChildInsertRemove)
+         assertLocked(A);
+      else
+         assertNotLocked(A);
       assertNotLocked(Fqn.ROOT);
       tm.commit();
       assert cache.getNode(AB) == null : "Should not exist";
@@ -204,7 +228,10 @@
       tm.begin();
       cache.removeNode(AB);
       assertLocked(AB);
-      assertLocked(A);
+      if (lockParentForChildInsertRemove)
+         assertLocked(A);
+      else
+         assertNotLocked(A);
       assertNotLocked(Fqn.ROOT);
       tm.commit();
       assert cache.getNode(AB) == null : "Should not exist";
@@ -218,7 +245,10 @@
       tm.begin();
       cache.evict(AB);
       assertLocked(AB);
-      assertLocked(A);
+      if (lockParentForChildInsertRemove)
+         assertLocked(A);
+      else
+         assertNotLocked(A);
       assertNotLocked(Fqn.ROOT);
       tm.commit();
       assert cache.getNode(AB) == null : "Should not exist";
@@ -450,4 +480,64 @@
       assert null == cache.getNode(AB);
       assertNoLocks();
    }
+
+   public void testPhantomChildren() throws Exception
+   {
+      cache.put(AB, "k", "v");
+      assert cache.getNode(AB).getChildren().size() == 0;
+      assert cache.getNode(A).getChildren().size() == 1;
+
+      tm.begin();
+      cache.put(ABC, "k", "v");
+      assert cache.getRoot().hasChild(ABC);
+      assert cache.getNode(ABC) != null;
+      assert cache.getNode(AB).getChild(ABC.getLastElement()) != null;
+      assert cache.getNode(AB).getChildren().size() == 1;
+      Transaction t = tm.suspend();
+
+
+      assert cache.getNode(ABC) == null;
+      assert cache.getNode(AB).getChild(ABC.getLastElement()) == null;
+      assert cache.getNode(AB).getChildren().size() == 0;
+
+      tm.resume(t);
+      assert cache.getRoot().hasChild(ABC);
+      assert cache.getNode(ABC) != null;
+      tm.commit();
+
+      assert cache.getNode(ABC) != null;
+      assert cache.getNode(AB).getChild(ABC.getLastElement()) != null;
+      assert cache.getNode(AB).getChildren().size() == 1;
+   }
+
+   public void testChildCount() throws Exception
+   {
+      cache.put(AB, "k", "v");
+      assert cache.getNode(AB).getChildren().size() == 0;
+      assert cache.getNode(A).getChildren().size() == 1;
+
+      tm.begin();
+      assert cache.getNode(AB).getChildren().size() == 0;
+      assert cache.getNode(A).getChildren().size() == 1;
+      cache.removeNode(AB);
+      assert cache.getNode(A).getChildren().size() == 0;
+      assert cache.getNode(A).hasChild(AB.getLastElement()) == false;
+      assert cache.getNode(AB) == null;
+      Transaction t = tm.suspend();
+
+
+      assert cache.getNode(AB) != null;
+      assert cache.getNode(A).getChild(AB.getLastElement()) != null;
+      assert cache.getNode(A).getChildren().size() == 1;
+
+      tm.resume(t);
+      assert cache.getNode(A).getChildren().size() == 0;
+      assert cache.getNode(A).hasChild(AB.getLastElement()) == false;
+      assert cache.getNode(AB) == null;
+      tm.commit();
+
+      assert cache.getNode(A).getChildren().size() == 0;
+      assert cache.getNode(A).hasChild(AB.getLastElement()) == false;
+      assert cache.getNode(AB) == null;
+   }
 }

Added: core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/ReadCommittedLockParentTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/ReadCommittedLockParentTest.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/ReadCommittedLockParentTest.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -0,0 +1,12 @@
+package org.jboss.cache.api.mvcc.read_committed;
+
+import org.testng.annotations.Test;
+
+ at Test(groups = {"functional", "mvcc"})
+public class ReadCommittedLockParentTest extends ReadCommittedLockTest
+{
+   public ReadCommittedLockParentTest()
+   {
+      lockParentForChildInsertRemove = true;
+   }
+}

Added: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadLockParentTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadLockParentTest.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadLockParentTest.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -0,0 +1,12 @@
+package org.jboss.cache.api.mvcc.repeatable_read;
+
+import org.testng.annotations.Test;
+
+ at Test(groups = {"functional", "mvcc"})
+public class RepeatableReadLockParentTest extends RepeatableReadLockTest
+{
+   public RepeatableReadLockParentTest()
+   {
+      lockParentForChildInsertRemove = true;
+   }
+}

Modified: core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java	2008-07-04 12:13:03 UTC (rev 6180)
+++ core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java	2008-07-04 12:13:44 UTC (rev 6181)
@@ -2,6 +2,7 @@
 
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
+import org.jboss.cache.commands.legacy.read.PessGetChildrenNamesCommand;
 import org.jboss.cache.mock.MockNodesFixture;
 import org.jboss.cache.mock.NodeSpiMock;
 import org.testng.annotations.Test;
@@ -23,7 +24,7 @@
    protected void moreSetup()
    {
       nodes = new MockNodesFixture();
-      command = new GetChildrenNamesCommand(testFqn);
+      command = new PessGetChildrenNamesCommand(testFqn);
       command.initialize(container);
    }
 




More information about the jbosscache-commits mailing list