[jbosscache-commits] JBoss Cache SVN: r4382 - in core/trunk/src: main/java/org/jboss/cache/transaction and 1 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Fri Aug 24 08:17:11 EDT 2007


Author: manik.surtani at jboss.com
Date: 2007-08-24 08:17:11 -0400 (Fri, 24 Aug 2007)
New Revision: 4382

Added:
   core/trunk/src/test/java/org/jboss/cache/transaction/StatusUnknownTest.java
Modified:
   core/trunk/src/main/java/org/jboss/cache/interceptors/OrderedSynchronizationHandler.java
   core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
   core/trunk/src/main/java/org/jboss/cache/transaction/DummyTransaction.java
Log:
JBCACHE-1167

Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/OrderedSynchronizationHandler.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/OrderedSynchronizationHandler.java	2007-08-23 18:22:35 UTC (rev 4381)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/OrderedSynchronizationHandler.java	2007-08-24 12:17:11 UTC (rev 4382)
@@ -87,6 +87,7 @@
 
    public void afterCompletion(int status)
    {
+      RuntimeException exceptionInAfterCompletion = null;
       for (Synchronization sync : handlers)
       {
          try
@@ -96,11 +97,15 @@
          catch (Throwable t)
          {
             log.error("failed calling afterCompletion() on " + sync, t);
+            exceptionInAfterCompletion = (RuntimeException) t;
          }
       }
 
       // finally unregister us from the hashmap
       instances.remove(tx);
+
+      // throw the exception so the TM can deal with it.
+      if (exceptionInAfterCompletion != null) throw exceptionInAfterCompletion;
    }
 
    public String toString()

Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java	2007-08-23 18:22:35 UTC (rev 4381)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java	2007-08-24 12:17:11 UTC (rev 4382)
@@ -1047,7 +1047,8 @@
                   runCommitPhase(ctx, gtx, tx, modifications, onePhaseCommit);
                   log.debug("Finished commit phase");
                   break;
-
+               case Status.STATUS_UNKNOWN:
+                  log.warn("Received JTA STATUS_UNKNOWN in afterCompletion()!  XA resources may not be in sync.  The app should manually clean up resources at this point.");
                case Status.STATUS_MARKED_ROLLBACK:
                case Status.STATUS_ROLLEDBACK:
                   log.debug("Running rollback phase");

Modified: core/trunk/src/main/java/org/jboss/cache/transaction/DummyTransaction.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/transaction/DummyTransaction.java	2007-08-23 18:22:35 UTC (rev 4381)
+++ core/trunk/src/main/java/org/jboss/cache/transaction/DummyTransaction.java	2007-08-24 12:17:11 UTC (rev 4382)
@@ -26,7 +26,7 @@
    private static final Log log = LogFactory.getLog(DummyTransaction.class);
    DummyBaseTransactionManager tm_;
 
-   private final Set<Synchronization> participants = new CopyOnWriteArraySet<Synchronization>();
+   protected final Set<Synchronization> participants = new CopyOnWriteArraySet<Synchronization>();
 
    public DummyTransaction(DummyBaseTransactionManager tm)
    {
@@ -246,7 +246,7 @@
       status = new_status;
    }
 
-   boolean notifyBeforeCompletion()
+   protected boolean notifyBeforeCompletion()
    {
       boolean retval = true;
 
@@ -269,7 +269,7 @@
       return retval;
    }
 
-   void notifyAfterCompletion(int status)
+   protected void notifyAfterCompletion(int status)
    {
       for (Synchronization s : participants)
       {

Added: core/trunk/src/test/java/org/jboss/cache/transaction/StatusUnknownTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/transaction/StatusUnknownTest.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/transaction/StatusUnknownTest.java	2007-08-24 12:17:11 UTC (rev 4382)
@@ -0,0 +1,155 @@
+package org.jboss.cache.transaction;
+
+import junit.framework.TestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.CacheImpl;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.Transaction;
+import javax.transaction.SystemException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.Status;
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.util.Properties;
+import java.util.List;
+import java.util.LinkedList;
+
+/**
+ * This test checks how the cache behaves when a JTA STATUS_UNKNOWN is passed in to the cache during afterCompletion().
+ *
+ * @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
+ */
+ at SuppressWarnings("unchecked")
+public class StatusUnknownTest extends TestCase
+{
+   private Cache cache;
+   private TransactionManager tm;
+
+   protected void setUp() throws Exception
+   {
+      cache = DefaultCacheFactory.getInstance().createCache(false);
+      cache.getConfiguration().setTransactionManagerLookupClass(HeuristicFailingDummyTransactionManagerLookup.class.getName());
+      cache.start();
+      tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+   }
+
+   protected void tearDown()
+   {
+      cache.stop();
+   }
+
+   public void testStatusUnknown() throws Exception
+   {
+      tm.begin();
+      Fqn<String> fqn = Fqn.fromString("/a/b/c");
+
+      cache.put(fqn, "k", "v");
+      assertEquals(4, ((CacheImpl) cache).getNumberOfLocksHeld());
+      assertTrue(cache.getRoot().hasChild(fqn));
+      tm.commit();
+
+      assertEquals(0, ((CacheImpl) cache).getNumberOfLocksHeld());
+      assertFalse(cache.getRoot().hasChild(fqn));
+   }
+
+   public static class HeuristicFailingDummyTransactionManager extends DummyTransactionManager
+   {
+      @Override
+      public void begin() throws SystemException, NotSupportedException
+      {
+         super.begin();
+
+         Transaction tx = new HeuristicFailingDummyTransaction(this);
+         setTransaction(tx);
+      }
+
+      public static DummyTransactionManager getInstance()
+      {
+         if(instance == null)
+         {
+            instance=new HeuristicFailingDummyTransactionManager();
+            try
+            {
+               Properties p=new Properties();
+               p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
+               Context ctx=new InitialContext(p);
+               ctx.bind("java:/TransactionManager", instance);
+               ctx.bind("UserTransaction", new DummyUserTransaction(instance));
+            }
+            catch(NamingException e)
+            {
+               log.error("binding of DummyTransactionManager failed", e);
+            }
+         }
+         return instance;
+      }
+   }
+
+   public static class HeuristicFailingDummyTransaction extends DummyTransaction
+   {
+      public HeuristicFailingDummyTransaction(DummyBaseTransactionManager mgr)
+      {
+         super(mgr);
+      }
+
+      @Override
+      public void commit() throws RollbackException
+      {
+         try
+         {
+            notifyBeforeCompletion();
+            notifyAfterCompletion(Status.STATUS_UNKNOWN);
+         }
+         finally
+         {
+            // Disassociate tx from thread.
+            tm_.setTransaction(null);
+         }
+      }
+
+      @Override
+      protected void notifyAfterCompletion(int status)
+      {
+         List<Synchronization> tmp;
+
+         synchronized(participants)
+         {
+            tmp=new LinkedList<Synchronization>(participants);
+         }
+
+         for (Synchronization s : tmp)
+         {
+            try
+            {
+               s.afterCompletion(status);
+            }
+            catch (Throwable t)
+            {
+               throw (RuntimeException) t;
+            }
+         }
+
+         synchronized(participants)
+         {
+            participants.clear();
+         }
+      }
+   }
+
+   public static class HeuristicFailingDummyTransactionManagerLookup implements TransactionManagerLookup
+   {
+
+      public TransactionManager getTransactionManager() throws Exception
+      {
+         return HeuristicFailingDummyTransactionManager.getInstance();
+      }
+   }
+}
+
+




More information about the jbosscache-commits mailing list