[jbosscache-commits] JBoss Cache SVN: r4828 - in core/trunk/src: test/java/org/jboss/cache/optimistic and 1 other directory.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Tue Dec 11 12:07:21 EST 2007


Author: manik.surtani at jboss.com
Date: 2007-12-11 12:07:21 -0500 (Tue, 11 Dec 2007)
New Revision: 4828

Added:
   core/trunk/src/test/java/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java
Removed:
   core/trunk/src/test/java/org/jboss/cache/optimistic/OpLockingInterceptorTest.java
Modified:
   core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java
Log:
JBCACHE-1228 - opt locking interceptor always acquires WRITE locks

Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java	2007-12-11 17:00:59 UTC (rev 4827)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java	2007-12-11 17:07:21 UTC (rev 4828)
@@ -6,8 +6,14 @@
  */
 package org.jboss.cache.interceptors;
 
-import org.jboss.cache.*;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.NodeSPI;
 import org.jboss.cache.lock.NodeLock;
+import static org.jboss.cache.lock.NodeLock.LockType.READ;
+import static org.jboss.cache.lock.NodeLock.LockType.WRITE;
 import org.jboss.cache.optimistic.TransactionWorkspace;
 import org.jboss.cache.optimistic.WorkspaceNode;
 import org.jboss.cache.transaction.GlobalTransaction;
@@ -48,16 +54,20 @@
       try
       {
          TransactionWorkspace<?, ?> workspace = getTransactionWorkspace(gtx);
+         TransactionEntry te = cache.getTransactionTable().get(gtx);
          if (log.isDebugEnabled()) log.debug("Locking nodes in transaction workspace for GlobalTransaction " + gtx);
 
          for (WorkspaceNode workspaceNode : workspace.getNodes().values())
          {
             NodeSPI node = workspaceNode.getNode();
-            boolean acquired = node.getLock().acquire(gtx, lockAcquisitionTimeout, NodeLock.LockType.WRITE);
+
+            boolean isWriteLockNeeded = workspaceNode.isDirty() || (workspaceNode.isChildrenModified() && (configuration.isLockParentForChildInsertRemove() || node.isLockForChildInsertRemove()));
+
+            boolean acquired = node.getLock().acquire(gtx, lockAcquisitionTimeout, isWriteLockNeeded ? WRITE : READ);
             if (acquired)
             {
                if (trace) log.trace("Acquired lock on node " + node.getFqn());
-               cache.getTransactionTable().addLock(gtx, node.getLock());
+               te.addLock(node.getLock());
             }
             else
             {
@@ -102,15 +112,14 @@
       throw new CacheException("_lock() passed up the interceptor stack when Optimistic Locking is used.  This is NOT supported.");
    }
 
-   private Object transactionFinalized(InvocationContext ctx)
-      throws Throwable
+   private Object transactionFinalized(InvocationContext ctx) throws Throwable
    {
       Object retval = null;
       // we need to let the stack run its commits or rollbacks first -
       // we unlock last - even if an exception occurs
       try
-            {
-               retval = nextInterceptor(ctx);
+      {
+         retval = nextInterceptor(ctx);
       }
       finally
       {

Deleted: core/trunk/src/test/java/org/jboss/cache/optimistic/OpLockingInterceptorTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/optimistic/OpLockingInterceptorTest.java	2007-12-11 17:00:59 UTC (rev 4827)
+++ core/trunk/src/test/java/org/jboss/cache/optimistic/OpLockingInterceptorTest.java	2007-12-11 17:07:21 UTC (rev 4828)
@@ -1,366 +0,0 @@
-/*
- * Created on 17-Feb-2005
- *
- *
- *
- */
-package org.jboss.cache.optimistic;
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNotNull;
-import static org.testng.AssertJUnit.assertTrue;
-import static org.testng.AssertJUnit.fail;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.transaction.Transaction;
-
-import org.jboss.cache.CacheImpl;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.NodeSPI;
-import org.jboss.cache.interceptors.Interceptor;
-import org.jboss.cache.interceptors.OptimisticCreateIfNotExistsInterceptor;
-import org.jboss.cache.interceptors.OptimisticLockingInterceptor;
-import org.jboss.cache.interceptors.OptimisticNodeInterceptor;
-import org.jboss.cache.loader.SamplePojo;
-import org.jboss.cache.lock.NodeLock;
-import org.jboss.cache.marshall.MethodCall;
-import org.jboss.cache.marshall.MethodCallFactory;
-import org.jboss.cache.marshall.MethodDeclarations;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.jboss.cache.transaction.GlobalTransaction;
-import org.jboss.cache.transaction.OptimisticTransactionEntry;
-import org.jboss.cache.transaction.TransactionTable;
-
-/**
- * @author xenephon
- */
- at SuppressWarnings("unchecked")
-public class OpLockingInterceptorTest extends AbstractOptimisticTestCase
-{
-   public void testTransactionPrepareMethod() throws Exception
-   {
-
-      TestListener listener = new TestListener();
-      final CacheImpl cache = createCacheWithListener(listener);
-
-      Interceptor lockingInterceptor = new OptimisticLockingInterceptor();
-      lockingInterceptor.setCache(cache);
-      Interceptor interceptor = new OptimisticCreateIfNotExistsInterceptor();
-      interceptor.setCache(cache);
-      Interceptor nodeInterceptor = new OptimisticNodeInterceptor();
-      nodeInterceptor.setCache(cache);
-      MockInterceptor dummy = new MockInterceptor();
-      dummy.setCache(cache);
-      lockingInterceptor.setNext(interceptor);
-      interceptor.setNext(nodeInterceptor);
-      nodeInterceptor.setNext(dummy);
-
-      cache.setInterceptorChain(lockingInterceptor);
-
-      //		 first set up a node with a pojo
-      DummyTransactionManager mgr = DummyTransactionManager.getInstance();
-      mgr.begin();
-      Transaction tx = mgr.getTransaction();
-
-      // inject InvocationContext
-      cache.getInvocationContext().setTransaction(tx);
-      cache.getInvocationContext().setGlobalTransaction(cache.getCurrentTransaction(tx));
-
-      SamplePojo pojo = new SamplePojo(21, "test");
-      Map temp = new HashMap();
-      temp.put("key1", pojo);
-      cache.put("/one/two", temp);
-
-      assertEquals(null, dummy.getCalled());
-      TransactionTable table = cache.getTransactionTable();
-
-      GlobalTransaction gtx = table.get(tx);
-
-      OptimisticTransactionEntry entry = (OptimisticTransactionEntry) table.get(gtx);
-
-      TransactionWorkspace workspace = entry.getTransactionWorkSpace();
-
-      /*GlobalTransaction.class,
-      List.class,
-      Address.class,
-      boolean.class*/
-
-      assertEquals(3, workspace.getNodes().size());
-      assertNotNull(workspace.getNode(Fqn.fromString("/one/two")));
-      assertEquals(pojo, workspace.getNode(Fqn.fromString("/one/two")).get("key1"));
-      assertEquals(1, workspace.getNode(Fqn.fromString("/one/two")).getMergedData().size());
-      assertTrue(entry.getLocks().isEmpty());
-      assertEquals(1, entry.getModifications().size());
-      assertTrue(!cache.exists("/one/two"));
-      assertEquals(null, dummy.getCalled());
-
-      //now let us do a prepare
-      MethodCall prepareMethod = MethodCallFactory.create(MethodDeclarations.optimisticPrepareMethod, new Object[]{gtx, entry.getModifications(), gtx.getAddress(), Boolean.FALSE});
-      try
-      {
-         cache._replicate(prepareMethod);
-      }
-      catch (Throwable t)
-      {
-
-      }
-
-
-      assertEquals(3, workspace.getNodes().size());
-      assertNotNull(workspace.getNode(Fqn.fromString("/one/two")));
-      assertEquals(pojo, workspace.getNode(Fqn.fromString("/one/two")).get("key1"));
-      assertEquals(1, workspace.getNode(Fqn.fromString("/one/two")).getMergedData().size());
-      assertEquals(3, entry.getLocks().size());
-      for (Iterator it = entry.getLocks().iterator(); it.hasNext();)
-      {
-         NodeLock lock = (NodeLock) it.next();
-         assertTrue(lock.isWriteLocked());
-         assertEquals(gtx, lock.getWriterOwner());
-      }
-      assertEquals(1, entry.getModifications().size());
-      assertTrue(!cache.exists("/one/two"));
-      //assertEquals(null,dummy.getCalled());
-
-
-      mgr.commit();
-
-      cache.stop();
-
-   }
-
-   public void testTransactionCommitMethod() throws Exception
-   {
-
-      TestListener listener = new TestListener();
-      final CacheImpl cache = createCacheWithListener(listener);
-
-      Interceptor lockingInterceptor = new OptimisticLockingInterceptor();
-      lockingInterceptor.setCache(cache);
-      Interceptor interceptor = new OptimisticCreateIfNotExistsInterceptor();
-      interceptor.setCache(cache);
-      Interceptor nodeInterceptor = new OptimisticNodeInterceptor();
-      nodeInterceptor.setCache(cache);
-      MockInterceptor dummy = new MockInterceptor();
-      dummy.setCache(cache);
-      lockingInterceptor.setNext(interceptor);
-      interceptor.setNext(nodeInterceptor);
-      nodeInterceptor.setNext(dummy);
-
-      cache.setInterceptorChain(lockingInterceptor);
-
-      //		 first set up a node with a pojo
-      DummyTransactionManager mgr = DummyTransactionManager.getInstance();
-      mgr.begin();
-      Transaction tx = mgr.getTransaction();
-
-      // inject InvocationContext
-      cache.getInvocationContext().setTransaction(tx);
-      cache.getInvocationContext().setGlobalTransaction(cache.getCurrentTransaction(tx));
-
-      SamplePojo pojo = new SamplePojo(21, "test");
-      Map temp = new HashMap();
-      temp.put("key1", pojo);
-      cache.put("/one/two", temp);
-
-      assertEquals(null, dummy.getCalled());
-      TransactionTable table = cache.getTransactionTable();
-
-      GlobalTransaction gtx = table.get(tx);
-
-      OptimisticTransactionEntry entry = (OptimisticTransactionEntry) table.get(gtx);
-
-      TransactionWorkspace workspace = entry.getTransactionWorkSpace();
-
-      /*GlobalTransaction.class,
-      List.class,
-      Address.class,
-      boolean.class*/
-
-      assertEquals(3, workspace.getNodes().size());
-      assertNotNull(workspace.getNode(Fqn.fromString("/one/two")));
-      assertEquals(pojo, workspace.getNode(Fqn.fromString("/one/two")).get("key1"));
-      assertEquals(1, workspace.getNode(Fqn.fromString("/one/two")).getMergedData().size());
-      assertTrue(entry.getLocks().isEmpty());
-      assertEquals(1, entry.getModifications().size());
-      assertTrue(!cache.exists("/one/two"));
-      assertEquals(null, dummy.getCalled());
-
-      //now let us do a prepare
-      MethodCall prepareMethod = MethodCallFactory.create(MethodDeclarations.optimisticPrepareMethod, new Object[]{gtx, entry.getModifications(), gtx.getAddress(), Boolean.FALSE});
-      try
-      {
-         cache._replicate(prepareMethod);
-      }
-      catch (Throwable t)
-      {
-
-      }
-
-
-      assertEquals(3, workspace.getNodes().size());
-      assertNotNull(workspace.getNode(Fqn.fromString("/one/two")));
-      assertEquals(pojo, workspace.getNode(Fqn.fromString("/one/two")).get("key1"));
-      assertEquals(1, workspace.getNode(Fqn.fromString("/one/two")).getMergedData().size());
-      assertEquals(3, entry.getLocks().size());
-      for (Iterator it = entry.getLocks().iterator(); it.hasNext();)
-      {
-         NodeLock lock = (NodeLock) it.next();
-         assertTrue(lock.isWriteLocked());
-         assertEquals(gtx, lock.getWriterOwner());
-      }
-      assertEquals(1, entry.getModifications().size());
-      assertTrue(!cache.exists("/one/two"));
-      //assertEquals(null,dummy.getCalled());
-      assertEquals(MethodDeclarations.optimisticPrepareMethod, dummy.getCalled());
-
-
-      MethodCall commitMethod = MethodCallFactory.create(MethodDeclarations.commitMethod, new Object[]{gtx});
-      try
-      {
-         cache._replicate(commitMethod);
-      }
-      catch (Throwable t)
-      {
-         fail();
-      }
-      assertEquals(3, entry.getLocks().size());
-      for (Iterator it = entry.getLocks().iterator(); it.hasNext();)
-      {
-         NodeLock lock = (NodeLock) it.next();
-         assertEquals(false, lock.isLocked());
-
-      }
-      //make sure the nodes and locks are the same order
-      int i = 0;
-      for (Iterator it = workspace.getNodes().values().iterator(); it.hasNext();)
-      {
-         NodeSPI node = ((WorkspaceNode) it.next()).getNode();
-         assertEquals(node.getLock(), entry.getLocks().get(i));
-         i++;
-      }
-      assertEquals(MethodDeclarations.commitMethod, dummy.getCalled());
-      mgr.commit();
-
-      cache.stop();
-
-   }
-
-   public void testTransactionRollbackMethod() throws Exception
-   {
-
-      TestListener listener = new TestListener();
-      final CacheImpl cache = createCacheWithListener(listener);
-
-      Interceptor lockingInterceptor = new OptimisticLockingInterceptor();
-      lockingInterceptor.setCache(cache);
-      Interceptor interceptor = new OptimisticCreateIfNotExistsInterceptor();
-      interceptor.setCache(cache);
-      Interceptor nodeInterceptor = new OptimisticNodeInterceptor();
-      nodeInterceptor.setCache(cache);
-      MockInterceptor dummy = new MockInterceptor();
-      dummy.setCache(cache);
-      lockingInterceptor.setNext(interceptor);
-      interceptor.setNext(nodeInterceptor);
-      nodeInterceptor.setNext(dummy);
-
-      cache.setInterceptorChain(lockingInterceptor);
-
-      //		 first set up a node with a pojo
-      DummyTransactionManager mgr = DummyTransactionManager.getInstance();
-      mgr.begin();
-      Transaction tx = mgr.getTransaction();
-
-      // inject InvocationContext
-      cache.getInvocationContext().setTransaction(tx);
-      cache.getInvocationContext().setGlobalTransaction(cache.getCurrentTransaction(tx));
-
-      SamplePojo pojo = new SamplePojo(21, "test");
-      Map temp = new HashMap();
-      temp.put("key1", pojo);
-      cache.put("/one/two", temp);
-
-      assertEquals(null, dummy.getCalled());
-      TransactionTable table = cache.getTransactionTable();
-
-      GlobalTransaction gtx = table.get(tx);
-
-      OptimisticTransactionEntry entry = (OptimisticTransactionEntry) table.get(gtx);
-
-      TransactionWorkspace workspace = entry.getTransactionWorkSpace();
-
-      /*GlobalTransaction.class,
-      List.class,
-      Address.class,
-      boolean.class*/
-
-      assertEquals(3, workspace.getNodes().size());
-      assertNotNull(workspace.getNode(Fqn.fromString("/one/two")));
-      assertEquals(pojo, workspace.getNode(Fqn.fromString("/one/two")).get("key1"));
-      assertEquals(1, workspace.getNode(Fqn.fromString("/one/two")).getMergedData().size());
-      assertTrue(entry.getLocks().isEmpty());
-      assertEquals(1, entry.getModifications().size());
-      assertTrue(!cache.exists("/one/two"));
-      assertEquals(null, dummy.getCalled());
-
-      //now let us do a prepare
-      MethodCall prepareMethod = MethodCallFactory.create(MethodDeclarations.optimisticPrepareMethod, new Object[]{gtx, entry.getModifications(), gtx.getAddress(), Boolean.FALSE});
-      try
-      {
-         cache._replicate(prepareMethod);
-      }
-      catch (Throwable t)
-      {
-
-      }
-
-
-      assertEquals(3, workspace.getNodes().size());
-      assertNotNull(workspace.getNode(Fqn.fromString("/one/two")));
-      assertEquals(pojo, workspace.getNode(Fqn.fromString("/one/two")).get("key1"));
-      assertEquals(1, workspace.getNode(Fqn.fromString("/one/two")).getMergedData().size());
-      assertEquals(3, entry.getLocks().size());
-      for (Iterator it = entry.getLocks().iterator(); it.hasNext();)
-      {
-         NodeLock lock = (NodeLock) it.next();
-         assertTrue(lock.isWriteLocked());
-         assertEquals(gtx, lock.getWriterOwner());
-      }
-      assertEquals(1, entry.getModifications().size());
-      assertTrue(!cache.exists("/one/two"));
-      assertEquals(MethodDeclarations.optimisticPrepareMethod, dummy.getCalled());
-
-
-      MethodCall rollbackMethod = MethodCallFactory.create(MethodDeclarations.rollbackMethod, new Object[]{gtx});
-      try
-      {
-         cache._replicate(rollbackMethod);
-      }
-      catch (Throwable t)
-      {
-         fail();
-      }
-      assertEquals(3, entry.getLocks().size());
-      for (Iterator it = entry.getLocks().iterator(); it.hasNext();)
-      {
-         NodeLock lock = (NodeLock) it.next();
-         assertEquals(false, lock.isLocked());
-
-      }
-      //make sure the nodes and locks are the same order
-      int i = 0;
-      for (Iterator it = workspace.getNodes().values().iterator(); it.hasNext();)
-      {
-         NodeSPI node = ((WorkspaceNode) it.next()).getNode();
-         assertEquals(node.getLock(), entry.getLocks().get(i));
-         i++;
-      }
-      assertEquals(MethodDeclarations.rollbackMethod, dummy.getCalled());
-      mgr.commit();
-
-      cache.stop();
-
-   }
-
-}

Added: core/trunk/src/test/java/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java	2007-12-11 17:07:21 UTC (rev 4828)
@@ -0,0 +1,246 @@
+package org.jboss.cache.optimistic;
+
+import junit.framework.Assert;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.interceptors.Interceptor;
+import org.jboss.cache.interceptors.OptimisticInterceptor;
+import org.jboss.cache.interceptors.OptimisticLockingInterceptor;
+import org.jboss.cache.lock.NodeLock;
+import static org.jboss.cache.lock.NodeLock.LockType.READ;
+import static org.jboss.cache.lock.NodeLock.LockType.WRITE;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.transaction.TransactionManager;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * // Test for JBCACHE-1228
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ */
+ at Test(groups = "functional")
+public class OptimisticLockInterceptorTest extends AbstractOptimisticTestCase
+{
+   private CacheSPI<Object, Object> cache;
+   private LockReportInterceptor lri;
+   private Fqn parent = Fqn.fromString("/parent");
+   private Fqn child = Fqn.fromString("/parent/child");
+   private TransactionManager tm;
+
+   @BeforeMethod
+   protected void setUp() throws Exception
+   {
+      cache = createCache();
+      lri = new LockReportInterceptor();
+      lri.setCache(cache);
+
+      Interceptor i = cache.getInterceptorChain().get(0);
+      Interceptor lockInterceptor = i;
+      // find the OptimisticLockInterceptor and insert LockReportInterceptor after that.
+      while (!(lockInterceptor instanceof OptimisticLockingInterceptor))
+      {
+         System.out.println("Inspecting " + lockInterceptor.getClass().getSimpleName());
+         lockInterceptor = lockInterceptor.getNext();
+      }
+      Interceptor next = lockInterceptor.getNext();
+
+      lockInterceptor.setNext(lri);
+      lri.setNext(next);
+
+      cache.put(child, "key", "value");
+
+      tm = cache.getTransactionManager();
+   }
+
+   @AfterMethod
+   public void tearDown()
+   {
+      cache.stop();
+   }
+
+   public void testPut() throws Exception
+   {
+      tm.begin();
+      cache.put(child, "key2", "value2");
+      lri.reset();
+      lri.expectsReadLock(Fqn.ROOT);
+      lri.expectsReadLock(parent);
+      lri.expectsWriteLock(child);
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testGet() throws Exception
+   {
+      tm.begin();
+      cache.get(child, "key2");
+      lri.reset();
+      // nothing is stale, expecting nothing here.
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testRemove() throws Exception
+   {
+      tm.begin();
+      cache.remove(child, "key2");
+      lri.reset();
+      lri.expectsReadLock(Fqn.ROOT);
+      lri.expectsReadLock(parent);
+      lri.expectsWriteLock(child);
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testPutLockParentForCIR() throws Exception
+   {
+      cache.getConfiguration().setLockParentForChildInsertRemove(true);
+      cache.removeNode(parent);
+      cache.put(parent, "k", "v");
+
+      tm.begin();
+      cache.put(child, "key2", "value2");
+      lri.reset();
+      lri.expectsReadLock(Fqn.ROOT);
+      lri.expectsWriteLock(parent);
+      lri.expectsWriteLock(child);
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testGetLockParentForCIR() throws Exception
+   {
+      cache.getConfiguration().setLockParentForChildInsertRemove(true);
+      tm.begin();
+      cache.get(child, "key2");
+      lri.reset();
+      // nothing is stale, expecting nothing here.
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testRemoveLockParentForCIR() throws Exception
+   {
+      cache.getConfiguration().setLockParentForChildInsertRemove(true);
+      tm.begin();
+      cache.removeNode(child);
+      lri.reset();
+      lri.expectsReadLock(Fqn.ROOT);
+      lri.expectsWriteLock(parent);
+      lri.expectsWriteLock(child);
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+
+   public void testPutNodeNotExists() throws Exception
+   {
+      cache.removeNode(Fqn.ROOT);
+      tm.begin();
+      cache.put(child, "key2", "value2");
+      lri.reset();
+      lri.expectsReadLock(Fqn.ROOT);
+      lri.expectsWriteLock(parent);
+      lri.expectsWriteLock(child);
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testGetNodeNotExists() throws Exception
+   {
+      cache.removeNode(Fqn.ROOT);
+      tm.begin();
+      cache.get(child, "key2");
+      lri.reset();
+      // nothing is stale, expecting nothing here.
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   public void testRemoveNodeNotExists() throws Exception
+   {
+      cache.removeNode(Fqn.ROOT);
+      tm.begin();
+      cache.remove(child, "key2");
+      lri.reset();
+      // nothing is stale, expecting nothing here.
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   private void assertNoStaleLocks()
+   {
+      assert cache.getNumberOfLocksHeld() == 0;
+   }
+}
+
+class LockReportInterceptor extends OptimisticInterceptor
+{
+   private Map<Fqn, NodeLock.LockType> expected = new HashMap<Fqn, NodeLock.LockType>();
+   private Map<Fqn, NodeLock.LockType> actual = new HashMap<Fqn, NodeLock.LockType>();
+
+   void reset()
+   {
+      expected.clear();
+      actual.clear();
+   }
+
+   void assertReceivedExpectedLocks()
+   {
+      Assert.assertEquals(expected, actual);
+   }
+
+   void expectsReadLock(Fqn f)
+   {
+      expected.put(f, READ);
+   }
+
+   void expectsWriteLock(Fqn f)
+   {
+      expected.put(f, WRITE);
+   }
+
+   @Override
+   public Object invoke(InvocationContext ctx) throws Throwable
+   {
+      TransactionWorkspace w = getTransactionWorkspace(ctx.getGlobalTransaction());
+      Map nodeMap = w.getNodes();
+      for (Iterator i = nodeMap.keySet().iterator(); i.hasNext();)
+      {
+         WorkspaceNode wn = (WorkspaceNode) nodeMap.get(i.next());
+         NodeSPI n = wn.getNode();
+         NodeLock lock = n.getLock();
+         if (lock.isLocked())
+         {
+            actual.put(n.getFqn(), lock.isReadLocked() ? READ : WRITE);
+         }
+      }
+
+      return super.invoke(ctx);
+   }
+}




More information about the jbosscache-commits mailing list