[jbosscache-commits] JBoss Cache SVN: r4826 - in core/branches/1.4.X: tests/functional/org/jboss/cache/optimistic and 1 other directory.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Tue Dec 11 11:41:18 EST 2007


Author: manik.surtani at jboss.com
Date: 2007-12-11 11:41:18 -0500 (Tue, 11 Dec 2007)
New Revision: 4826

Added:
   core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java
Removed:
   core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OpLockingInterceptorTest.java
Modified:
   core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java
   core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
Log:
JBCACHE-1228 - optimistic locking interceptor always acquired write locks

Modified: core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java	2007-12-10 23:47:41 UTC (rev 4825)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java	2007-12-11 16:41:18 UTC (rev 4826)
@@ -8,6 +8,7 @@
 
 import org.jboss.cache.CacheException;
 import org.jboss.cache.DataNode;
+import org.jboss.cache.Fqn;
 import org.jboss.cache.GlobalTransaction;
 import org.jboss.cache.InvocationContext;
 import org.jboss.cache.TransactionEntry;
@@ -20,7 +21,10 @@
 
 import java.lang.reflect.Method;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
 /**
  * Locks nodes during transaction boundaries
@@ -137,9 +141,10 @@
     }
 
 
-    private Object lockNodes(GlobalTransaction gtx) throws Exception
+    private void lockNodes(GlobalTransaction gtx) throws Exception
     {
         TransactionWorkspace workspace = getTransactionWorkspace(gtx);
+        TransactionEntry te = cache.getTransactionTable().get(gtx);
         log.debug("locking nodes");
 
         // should be an ordered list
@@ -150,20 +155,19 @@
             WorkspaceNode workspaceNode = (WorkspaceNode) it.next();
             DataNode node = workspaceNode.getNode();
 
-            boolean acquired = node.acquire(gtx, lockAcquisitionTimeout, DataNode.LOCK_TYPE_WRITE);
+            boolean writeLock = workspaceNode.isDirty() || workspaceNode.isCreated() || workspaceNode.isDeleted() || (workspaceNode.isChildrenModified() && cache.getLockParentForChildInsertRemove());
+
+            boolean acquired = node.acquire(gtx, lockAcquisitionTimeout, writeLock ? DataNode.LOCK_TYPE_WRITE : DataNode.LOCK_TYPE_READ);
             if (acquired)
             {
                 if (log.isTraceEnabled()) log.trace("acquired lock on node " + node.getName());
-                cache.getTransactionTable().addLock(gtx, node.getLock());
+                te.addLock(node.getLock());
             }
             else
             {
                 throw new CacheException("unable to acquire lock on node " + node.getName());
             }
-
         }
-        return null;
-
     }
 
 

Modified: core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java	2007-12-10 23:47:41 UTC (rev 4825)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java	2007-12-11 16:41:18 UTC (rev 4826)
@@ -366,13 +366,16 @@
          DataNode node = cache.peek(fqn);
          if (node == null)
          {
-            return null; // seems to happen quite a bit
+            workspaceNode = null; // seems to happen quite a bit
          }
-         workspaceNode = NodeFactory.getInstance().createWorkspaceNode(node, workspace);
-         workspace.addNode(workspaceNode);
+         else
+         {
+            workspaceNode = NodeFactory.getInstance().createWorkspaceNode(node, workspace);
+            workspace.addNode(workspaceNode);
+         }
       }
       // the node has been deleted dude!
-      if (workspaceNode.isDeleted())
+      if (workspaceNode != null && workspaceNode.isDeleted())
       {
          if (log.isDebugEnabled()) log.debug("Node " + fqn + " has been deleted in the workspace.");
          if (undeleteIfNecessary)
@@ -393,6 +396,13 @@
          log.trace("Setting versioning to explicit");
          workspaceNode.setVersioningImplicit(false);
       }
+
+      // now make sure all parents are in the wsp as well
+      if (workspaceNode != null)
+      {
+         if (!fqn.isRoot()) getOrCreateWorkspaceNode(fqn.getParent(), workspace, false);
+      }
+
       return workspaceNode;
    }
 }

Deleted: core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OpLockingInterceptorTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OpLockingInterceptorTest.java	2007-12-10 23:47:41 UTC (rev 4825)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OpLockingInterceptorTest.java	2007-12-11 16:41:18 UTC (rev 4826)
@@ -1,366 +0,0 @@
-/*
- * Created on 17-Feb-2005
- *
- *
- *
- */
-package org.jboss.cache.optimistic;
-
-import org.jboss.cache.*;
-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.IdentityLock;
-import org.jboss.cache.marshall.MethodCallFactory;
-import org.jboss.cache.marshall.MethodDeclarations;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.jgroups.blocks.MethodCall;
-
-import javax.transaction.Transaction;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * @author xenephon
- */
-public class OpLockingInterceptorTest extends AbstractOptimisticTestCase
-{
-
-
-    /**
-     * @param name
-     */
-    public OpLockingInterceptorTest(String name)
-    {
-        super(name);
-
-    }
-
-    public void testTransactionPrepareMethod() throws Exception
-    {
-
-        TestListener listener = new TestListener();
-        final TreeCache 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();)
-        {
-            IdentityLock lock = (IdentityLock) 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.stopService();
-
-    }
-
-    public void testTransactionCommitMethod() throws Exception
-    {
-
-        TestListener listener = new TestListener();
-        final TreeCache 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();)
-        {
-            IdentityLock lock = (IdentityLock) 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();)
-        {
-            IdentityLock lock = (IdentityLock) 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();)
-        {
-            DataNode node = ((WorkspaceNode) it.next()).getNode();
-            assertEquals(node.getLock(), entry.getLocks().get(i));
-            i++;
-        }
-        assertEquals(MethodDeclarations.commitMethod, dummy.getCalled());
-        mgr.commit();
-
-        cache.stopService();
-
-    }
-
-    public void testTransactionRollbackMethod() throws Exception
-    {
-
-        TestListener listener = new TestListener();
-        final TreeCache 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();)
-        {
-            IdentityLock lock = (IdentityLock) 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();)
-        {
-            IdentityLock lock = (IdentityLock) 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();)
-        {
-            DataNode node = ((WorkspaceNode) it.next()).getNode();
-            assertEquals(node.getLock(), entry.getLocks().get(i));
-            i++;
-        }
-        assertEquals(MethodDeclarations.rollbackMethod, dummy.getCalled());
-        mgr.commit();
-
-        cache.stopService();
-
-    }
-
-}

Added: core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java	                        (rev 0)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/OptimisticLockInterceptorTest.java	2007-12-11 16:41:18 UTC (rev 4826)
@@ -0,0 +1,245 @@
+package org.jboss.cache.optimistic;
+
+import junit.framework.Assert;
+import org.jboss.cache.DataNode;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.interceptors.Interceptor;
+import org.jboss.cache.interceptors.OptimisticCreateIfNotExistsInterceptor;
+import org.jboss.cache.interceptors.OptimisticInterceptor;
+import org.jboss.cache.interceptors.OptimisticLockingInterceptor;
+import org.jboss.cache.lock.IdentityLock;
+import org.jgroups.blocks.MethodCall;
+
+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>)
+ */
+public class OptimisticLockInterceptorTest extends AbstractOptimisticTestCase
+{
+   private TreeCache cache;
+   private LockReportInterceptor lri;
+   private Fqn parent = Fqn.fromString("/parent");
+   private Fqn child = Fqn.fromString("/parent/child");
+   private TransactionManager tm;
+
+   public OptimisticLockInterceptorTest(String name)
+   {
+      super(name);
+   }
+
+   protected void setUp() throws Exception
+   {
+      cache = createCache();
+      lri = new LockReportInterceptor();
+      lri.setCache(cache);
+
+      Interceptor i = (Interceptor) cache.getInterceptors().get(0);
+      Interceptor lockInterceptor = i;
+      // find the OptimisticLockInterceptor and insert LockReportInterceptor after that.
+      while (!(lockInterceptor instanceof OptimisticLockingInterceptor)) lockInterceptor = lockInterceptor.getNext();
+      Interceptor next = lockInterceptor.getNext();
+
+      lockInterceptor.setNext(lri);
+      lri.setNext(next);
+
+      cache.setInterceptorChain(i);
+
+      cache.put(child, "key", "value");
+
+      tm = cache.getTransactionManager();
+   }
+
+   protected 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.setLockParentForChildInsertRemove(true);
+      cache.remove(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.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.setLockParentForChildInsertRemove(true);
+      tm.begin();
+      cache.remove(child);
+      lri.reset();
+      lri.expectsReadLock(Fqn.ROOT);
+      lri.expectsWriteLock(parent);
+      lri.expectsWriteLock(child);
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+
+   public void testPutNodeNotExists() throws Exception
+   {
+      cache.remove(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.remove(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.remove(Fqn.ROOT);
+      tm.begin();
+      cache.remove(child, "key2");
+      lri.reset();
+      // nothing is stale, expecting nothing here.
+      tm.commit();
+      lri.assertReceivedExpectedLocks();
+
+      assertNoStaleLocks();
+   }
+
+   private void assertNoStaleLocks()
+   {
+      assertEquals(cache.getNumberOfLocksHeld(), 0);
+   }
+}
+
+class LockReportInterceptor extends OptimisticInterceptor
+{
+   private Object READ = "READ";
+   private Object WRITE = "WRITE";
+   private Map expected = new HashMap();
+   private Map actual = new HashMap();
+
+   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);
+   }
+
+   public Object invoke(MethodCall call) throws Throwable
+   {
+      TransactionWorkspace w = getTransactionWorkspace(getInvocationContext().getGlobalTransaction());
+      Map nodeMap = w.getNodes();
+      for (Iterator i = nodeMap.keySet().iterator(); i.hasNext();)
+      {
+         WorkspaceNode wn = (WorkspaceNode) nodeMap.get(i.next());
+         DataNode n = wn.getNode();
+         IdentityLock lock = n.getLock();
+         if (lock.isLocked())
+         {
+            actual.put(n.getFqn(), lock.isReadLocked() ? READ : WRITE);
+         }
+      }
+
+      return super.invoke(call);
+   }
+
+
+}




More information about the jbosscache-commits mailing list