[jboss-cvs] JBossCache/tests/functional/org/jboss/cache/transaction ...

Manik Surtani msurtani at jboss.com
Wed Dec 6 07:46:53 EST 2006


  User: msurtani
  Date: 06/12/06 07:46:53

  Modified:    tests/functional/org/jboss/cache/transaction 
                        TransactionTest.java
  Log:
  Partially brought in tests for JBCACHE-875 and JBCACHE-871
  
  Revision  Changes    Path
  1.18      +281 -86   JBossCache/tests/functional/org/jboss/cache/transaction/TransactionTest.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: TransactionTest.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossCache/tests/functional/org/jboss/cache/transaction/TransactionTest.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -b -r1.17 -r1.18
  --- TransactionTest.java	20 Nov 2006 03:53:57 -0000	1.17
  +++ TransactionTest.java	6 Dec 2006 12:46:53 -0000	1.18
  @@ -15,9 +15,10 @@
   import org.jboss.cache.DataNode;
   import org.jboss.cache.Fqn;
   import org.jboss.cache.GlobalTransaction;
  +import org.jboss.cache.NodeImpl;
   import org.jboss.cache.TreeCache;
  +import org.jboss.cache.lock.IdentityLock;
   import org.jboss.cache.lock.IsolationLevel;
  -import org.jboss.cache.lock.NodeLock;
   
   import javax.naming.Context;
   import javax.naming.InitialContext;
  @@ -37,7 +38,7 @@
    * Tests transactional access to a local TreeCache.
    * Note: we use DummpyTranasctionManager to replace jta
    *
  - * @version $Id: TransactionTest.java,v 1.17 2006/11/20 03:53:57 genman Exp $
  + * @version $Id: TransactionTest.java,v 1.18 2006/12/06 12:46:53 msurtani Exp $
    */
   public class TransactionTest extends TestCase
   {
  @@ -152,27 +153,40 @@
      }
   
   
  -   public void testRollbackTx()
  +   public void testGetAfterRemovalRollback() throws Exception
      {
  -      try
  -      {
  -         cache.put("/a/b/c", "age", new Integer(38));
  -         assertNotNull(cache.get("/a/b/c", "age"));
  +      cache.put("/a/b", null);
  +      assertTrue(cache.exists("/a/b"));
            tx.begin();
  -         cache.remove("/a/b/c");
  +      cache.remove("/a/b");
  +      assertFalse(cache.exists("/a/b"));
            tx.rollback();
  -
  -         // This test is done outside the TX, it wouldn't work if someone else
  -         // modified "age". This works because we're the only TX running.
  -         assertNotNull(cache.get("/a/b/c", "age"));
  +      assertTrue(cache.exists("/a/b"));
  +      assertEquals(0, cache.getNumberOfLocksHeld());
  +      // new tx in new thread
  +      Thread th = new Thread()
  +      {
  +         public void run()
  +         {
  +            try
  +            {
  +               cache.getTransactionManager().begin();
  +               assertNotNull(cache.get("/a/b"));
  +               cache.getTransactionManager().rollback();
         }
  -      catch (Throwable t)
  +            catch (Exception e)
         {
  -         t.printStackTrace();
  -         fail(t.toString());
  +               e.printStackTrace();
  +               fail("Caught exception");
         }
      }
  +      };
   
  +      th.start();
  +      th.join();
  +
  +      assertEquals(0, cache.getNumberOfLocksHeld());
  +   }
   
      public void testRollbackTx2()
      {
  @@ -360,109 +374,288 @@
      }
   
   
  -   public void testNodeDeletionRollback3()
  +   public void testNodeCreation() throws Exception
  +   {
  +      GlobalTransaction gtx;
  +      cache.put("/a/b", null);
  +      tx.begin();
  +      gtx = cache.getCurrentTransaction();
  +      cache.put("/a/b/c", null);
  +      assertLocked(gtx, "/a", false);
  +      assertLocked(gtx, "/a/b", true);
  +      assertLocked(gtx, "/a/b/c", true);
  +      System.out.println("locks: " + cache.printLockInfo());
  +   }
  +
  +
  +   public void testNodeCreation2() throws Exception
  +   {
  +      GlobalTransaction gtx;
  +      tx.begin();
  +      gtx = cache.getCurrentTransaction();
  +      cache.put("/a/b/c", null);
  +      assertLocked(gtx, "/a", true);
  +      assertLocked(gtx, "/a/b", true);
  +      assertLocked(gtx, "/a/b/c", true);
  +      System.out.println("locks: " + cache.printLockInfo());
  +   }
  +
  +
  +   public void testNodeRemoval()
      {
         GlobalTransaction gtx;
         try
         {
  +         cache.put("/a/b/c", null);
  +         tx.begin();
  +         gtx = cache.getCurrentTransaction();
  +         cache.remove("/a/b/c"); // need to remove the node, not just the data in the node.
  +         assertLocked(gtx, "/a", false);
  +         assertLocked(gtx, "/a/b", true);
  +         assertLocked(gtx, "/a/b/c", true);
  +         System.out.println("locks: " + cache.printLockInfo());
  +      }
  +      catch (Throwable t)
  +      {
  +         t.printStackTrace();
  +         fail(t.toString());
  +      }
  +   }
  +
  +
  +   public void testNodeRemoval2()
  +   {
  +      GlobalTransaction gtx;
  +      try
  +      {
  +         cache.put("/a/b/c", null);
  +         tx.begin();
  +         gtx = cache.getCurrentTransaction();
  +         cache.remove("/a/b"); // need to remove the node, not just the data in the node.
  +         assertLocked(gtx, "/a", true);
  +         assertLocked(gtx, "/a/b", true);
  +         assertLocked(gtx, "/a/b/c", true);
  +         System.out.println("locks: " + cache.printLockInfo());
  +      }
  +      catch (Throwable t)
  +      {
  +         t.printStackTrace();
  +         fail(t.toString());
  +      }
  +   }
  +
  +   public void testIntermediateNodeCreationOnWrite() throws Exception
  +   {
  +      cache.put("/a", null);
  +      tx.begin();
  +      cache.put("/a/b/c", null);
  +      // expecting WLs on /a, /a/b and /a/b/c.
  +      GlobalTransaction gtx = cache.getCurrentTransaction();
  +      assertLocked(gtx, "/a", true);
  +      assertLocked(gtx, "/a/b", true);
  +      assertLocked(gtx, "/a/b/c", true);
  +      tx.rollback();
  +
  +   }
  +
  +   public void testIntermediateNodeCreationOnRead() throws Exception
  +   {
  +      cache.put("/a", null);
  +      tx.begin();
  +      cache.get("/a/b/c");
  +
  +      // expecting RLs on /, /a
  +      // /a/b, /a/b/c should NOT be created!
  +      GlobalTransaction gtx = cache.getCurrentTransaction();
  +      assertLocked(gtx, "/", false);
  +      assertLocked(gtx, "/a", false);
  +      assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b")));
  +      assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c")));
  +      tx.rollback();
  +      assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b")));
  +      assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c")));
  +
  +   }
  +
  +
  +   public void testIntermediateNodeCreationOnRemove() throws Exception
  +   {
  +      cache.put("/a", null);
  +      tx.begin();
  +      cache.remove("/a/b/c");
  +
  +      // expecting RLs on /, /a
  +      // /a/b, /a/b/c should NOT be created!
  +      GlobalTransaction gtx = cache.getCurrentTransaction();
  +      assertLocked(gtx, "/", false);
  +      assertLocked(gtx, "/a", false);
  +      assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b")));
  +      assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c")));
  +      tx.rollback();
  +      assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b")));
  +      assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c")));
  +
  +   }
  +
  +
  +   public void testNodeDeletionRollback3() throws Exception
  +   {
  +      GlobalTransaction gtx;
  +      cache.put("/a/b/c1", null);
  +
            tx.begin();
            gtx = cache.getCurrentTransaction();
            cache.put("/a/b/c1", null);
  -         checkLock(gtx, "/a", false);
  -         checkLock(gtx, "/a/b", false);
  -         checkLock(gtx, "/a/b/c1", true);
  +      assertLocked(gtx, "/a", false);
  +      assertLocked(gtx, "/a/b", false);
  +      assertLocked(gtx, "/a/b/c1", true);
   
            cache.put("/a/b/c2", null);
  -         checkLock(gtx, "/a/b/c2", true);
  +      assertLocked(gtx, "/a/b", true);
  +      assertLocked(gtx, "/a/b/c2", true);
   
            cache.put("/a/b/c3", null);
            cache.put("/a/b/c1/one", null);
  -         checkLock(gtx, "/a/b/c1", true);
  -         checkLock(gtx, "/a/b/c1/one", true);
  +      assertLocked(gtx, "/a/b/c1", true);
  +      assertLocked(gtx, "/a/b/c1/one", true);
   
            cache.put("/a/b/c1/two", null);
            cache.put("/a/b/c1/one/1", null);
  -         checkLock(gtx, "/a/b/c1", true);
  -         checkLock(gtx, "/a/b/c1/one", true);
  -         checkLock(gtx, "/a/b/c1/one/1", true);
  +      assertLocked(gtx, "/a/b/c1", true);
  +      assertLocked(gtx, "/a/b/c1/one", true);
  +      assertLocked(gtx, "/a/b/c1/one/1", true);
   
            cache.put("/a/b/c1/two/2/3/4", null);
  -         checkLock(gtx, "/a/b/c1", true);
  -         checkLock(gtx, "/a/b/c1/two", true);
  -         checkLock(gtx, "/a/b/c1/two/2", false);
  -         checkLock(gtx, "/a/b/c1/two/2/3", false);
  -         checkLock(gtx, "/a/b/c1/two/2/3/4", true);
  +      assertLocked(gtx, "/a/b/c1", true);
  +      assertLocked(gtx, "/a/b/c1/two", true);
  +      assertLocked(gtx, "/a/b/c1/two/2", true);
  +      assertLocked(gtx, "/a/b/c1/two/2/3", true);
  +      assertLocked(gtx, "/a/b/c1/two/2/3/4", true);
   
            System.out.println("locks: " + cache.printLockInfo());
   
            cache.remove("/a/b");
            tx.rollback();
  -         assertNull(cache.getChildrenNames("/a/b"));
  -      }
  -      catch (Throwable t)
  -      {
  -         t.printStackTrace();
  -         fail(t.toString());
  -      }
  +      assertTrue(cache.getChildrenNames("/a/b/c1").isEmpty());
  +      Set cn = cache.getChildrenNames("/a/b");
  +      assertEquals(1, cn.size());
  +      assertEquals("c1", cn.iterator().next());
      }
   
  -   public void testDoubleLocks()
  -   {
  -      try
  +   public void testDoubleLocks() throws Exception
         {
            tx.begin();
  +      GlobalTransaction gtx = cache.getCurrentTransaction();
            cache.put("/a/b/c", null);
            cache.put("/a/b/c", null);
   
  -         DataNode n = cache.get("/a");
  -         NodeLock lock = n.getNodeSPI().getLock();
  +      NodeImpl n = cache.get("/a");
  +      IdentityLock lock = n.getLock();
            int num = lock.getReaderOwners().size();
  -         assertEquals(1, num);
  +      assertEquals(0, num);
  +      // make sure this is write locked.
  +      assertLocked(gtx, "/a", true);
   
            n = cache.get("/a/b");
  -         lock = n.getNodeSPI().getLock();
  +      lock = n.getLock();
            num = lock.getReaderOwners().size();
  -         assertEquals(1, num);
  -         // added this here since we had stale gtxs lurking about. - Manik, 02Jan06
  +      assertEquals(0, num);
  +      // make sure this is write locked.
  +      assertLocked(gtx, "/a/b", true);
  +
  +      n = cache.get("/a/b/c");
  +      lock = n.getLock();
  +      num = lock.getReaderOwners().size();
  +      assertEquals(0, num);
  +      // make sure this is write locked.
  +      assertLocked(gtx, "/a/b/c", true);
  +
            tx.rollback();
  -      }
  -      catch (Throwable t)
  -      {
  -         t.printStackTrace();
  -         fail(t.toString());
  -      }
  +      assertEquals(0, cache.getNumberOfLocksHeld());
      }
   
  -   private void checkLock(Object owner, String fqn, boolean write_locked) throws Exception
  +   private void assertLocked(Object owner, String fqn, boolean write_locked) throws Exception
      {
  -      DataNode n = cache.get(fqn);
  -      NodeLock lock = n.getNodeSPI().getLock();
  +      NodeImpl n = cache.get(fqn);
  +      IdentityLock lock = n.getLock();
         if (owner == null)
  -      {
            owner = Thread.currentThread();
  +      assertTrue("node " + fqn + " is not locked", lock.isLocked());
  +      if (write_locked)
  +      {
  +         assertTrue("node " + fqn + " is not write-locked" + (lock.isReadLocked() ? " but is read-locked instead!" : "!"), lock.isWriteLocked());
         }
  -      if (lock.isLocked() == false)
  +      else
         {
  -         throw new Exception("node " + fqn + " is not locked");
  +         assertTrue("node " + fqn + " is not read-locked" + (lock.isWriteLocked() ? " but is write-locked instead!" : "!"), lock.isReadLocked());
         }
  -      if (write_locked)
  +      assertTrue("owner " + owner + "is not owner", lock.isOwner(owner));
  +   }
  +
  +   public void testConcurrentNodeAccessOnRemovalWithTx() throws Exception
         {
  -         if (lock.isWriteLocked() == false)
  +      cache.put("/a/b/c", null);
  +      tx.begin();
  +      cache.remove("/a/b/c");
  +      // this node should now be locked.
  +      Transaction t = cache.getTransactionManager().suspend();
  +      Transaction t2 = null;
  +      try
            {
  -            throw new Exception("node " + fqn + " is not write-locked");
  +         System.out.println(cache.printLockInfo());
  +         // start a new tx
  +         cache.getTransactionManager().begin();
  +         t2 = cache.getTransactionManager().getTransaction();
  +         cache.get("/a/b/c"); // should fail
  +         t2.commit();
  +         fail("Should not be able to get a hold of /a/b/c until the deleting tx completes");
            }
  +      catch (Exception e)
  +      {
  +         // expected
  +         t2.commit();
         }
  -      else
  +
  +      cache.getTransactionManager().resume(t);
  +      tx.rollback();
  +
  +      assertNotNull(cache.get("/a/b/c"));
  +      assertEquals(0, cache.getNumberOfLocksHeld());
  +   }
  +
  +   public void testConcurrentNodeAccessOnRemovalWithoutTx() throws Exception
  +   {
  +      cache.put("/a/b/c", null);
  +      tx.begin();
  +      cache.remove("/a/b/c");
  +      // this node should now be locked.
  +      Transaction t = cache.getTransactionManager().suspend();
  +      Thread th = new Thread()
         {
  -         if (lock.isReadLocked() == false)
  +         public void run()
            {
  -            throw new Exception("node " + fqn + " is not read-locked");
  -         }
  +            try
  +            {
  +               System.out.println(cache.printLockInfo());
  +               cache.get("/a/b/c"); // should fail
  +
  +               fail("Should not be able to get a hold of /a/b/c until the deleting tx completes");
         }
  -      if (lock.isOwner(owner) == false)
  +            catch (Exception e)
         {
  -         throw new Exception("owner " + owner + "is not owner");
  +               // expected
  +            }
         }
  +      };
  +
  +      th.start();
  +      th.join();
  +
  +      cache.getTransactionManager().resume(t);
  +      tx.rollback();
  +
  +      assertNotNull(cache.get("/a/b/c"));
  +      assertEquals(0, cache.getNumberOfLocksHeld());
      }
   
   
  @@ -480,7 +673,9 @@
         tx.begin();
         cache.remove("/a/b/c");
         System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo());
  -      assertEquals(2, cache.getNumberOfLocksHeld());
  +      // this used to test for 2 locks held.  After the fixes for JBCACHE-875 however, 2 more locks are acquired - for the root node as well as the deleted node.
  +      // and since we would lock all children of the deleted node as well, we have 10 locks here.
  +      assertEquals(10, cache.getNumberOfLocksHeld());
         tx.commit();
         System.out.println("locks held (after committing /a/b/c): \n" + cache.printLockInfo());
         assertEquals(0, cache.getNumberOfLocksHeld());
  @@ -502,7 +697,7 @@
         System.out.println("locks held (before removing /a/b/c): \n" + cache.printLockInfo());
         cache.remove("/a/b/c");
         System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo());
  -      assertEquals(2, cache.getNumberOfLocksHeld());
  +      assertEquals(10, cache.getNumberOfLocksHeld());
         tx.rollback();
         System.out.println("locks held (after rollback): \n" + cache.printLockInfo());
         assertEquals(0, cache.getNumberOfLocksHeld());
  
  
  



More information about the jboss-cvs-commits mailing list