[jbosscache-commits] JBoss Cache SVN: r7585 - in core/branches/flat/src: main/java/org/horizon/transaction and 1 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Fri Jan 23 07:17:27 EST 2009


Author: manik.surtani at jboss.com
Date: 2009-01-23 07:17:27 -0500 (Fri, 23 Jan 2009)
New Revision: 7585

Added:
   core/branches/flat/src/test/java/org/horizon/tx/MarkAsRollbackTest.java
Modified:
   core/branches/flat/src/main/java/org/horizon/interceptors/TxInterceptor.java
   core/branches/flat/src/main/java/org/horizon/transaction/TransactionTable.java
Log:
JBCACHE-1468:   JBoss Cache ignores transactions with STATUS_MARKED_ROLLBACK and auto commits data changes

Modified: core/branches/flat/src/main/java/org/horizon/interceptors/TxInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/interceptors/TxInterceptor.java	2009-01-23 12:17:02 UTC (rev 7584)
+++ core/branches/flat/src/main/java/org/horizon/interceptors/TxInterceptor.java	2009-01-23 12:17:27 UTC (rev 7585)
@@ -479,7 +479,7 @@
       try {
          // JBCACHE-457
          VisitableCommand rollbackCommand = commandsFactory.buildRollbackCommand(gtx);
-         if (trace) log.trace(" running rollback for " + gtx);
+         if (trace) log.trace(" running rollback for {0}", gtx);
 
          //JBCACHE-359 Store a lookup for the globalTransaction so a listener
          // callback can find it
@@ -547,9 +547,15 @@
     * Creates a gtx (if one doesnt exist), a sync handler, and registers the tx.
     */
    private GlobalTransaction registerTransaction(Transaction tx, InvocationContext ctx) throws Exception {
+      // we have ascertained that the current thread *is* associated with a transaction.  We need to make sure the
+      // transaction is in a valid state before moving on, and throwing an exception if not.
+      boolean txValid = TransactionTable.isValid(tx);
+      if (!txValid)
+         throw new IllegalStateException("Transaction " + tx + " is not in a valid state to be invoking cache operations on.");
+
       GlobalTransaction gtx;
 
-      if (TransactionTable.isValid(tx) && transactions.add(tx)) {
+      if (transactions.add(tx)) {
          gtx = txTable.getCurrentTransaction(tx, true);
          TransactionContext transactionContext;
          if (ctx.getGlobalTransaction() == null) {
@@ -563,16 +569,16 @@
             // should be no need to register a handler since this a remotely initiated globalTransaction
             if (trace) log.trace("is a remotely initiated gtx so no need to register a tx for it");
          } else {
-            if (trace) log.trace("Registering sync handler for tx " + tx + ", gtx " + gtx);
+            if (trace) log.trace("Registering sync handler for tx {0} and gtx {1}", tx, gtx);
 
             // see the comment in the LocalSyncHandler for the last isOriginLocal param.
             LocalSynchronizationHandler myHandler = new LocalSynchronizationHandler(gtx, tx, transactionContext, !ctx.isOriginLocal());
             registerHandler(tx, myHandler, ctx);
          }
       } else if ((gtx = rollbackTransactions.get(tx)) != null) {
-         if (trace) log.trace("Transaction " + tx + " is already registered and is rolling back.");
+         if (trace) log.trace("Transaction {0} is already registered and is rolling back.", tx);
       } else {
-         if (trace) log.trace("Transaction " + tx + " is already registered.");
+         if (trace) log.trace("Transaction {0} is already registered.", tx);
       }
       return gtx;
    }

Modified: core/branches/flat/src/main/java/org/horizon/transaction/TransactionTable.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/transaction/TransactionTable.java	2009-01-23 12:17:02 UTC (rev 7584)
+++ core/branches/flat/src/main/java/org/horizon/transaction/TransactionTable.java	2009-01-23 12:17:27 UTC (rev 7585)
@@ -250,13 +250,29 @@
    }
 
    /**
-    * Return s true of tx's status is ACTIVE or PREPARING
+    * Returns true if transaction is STATUS_MARKED_ROLLBACK, false otherwise
+    */
+   public static boolean isMarkedAsRollback(Transaction tx) {
+      if (tx == null) return false;
+      int status;
+      try {
+         status = tx.getStatus();
+         return status == Status.STATUS_MARKED_ROLLBACK;
+      }
+      catch (SystemException e) {
+         return false;
+      }
+   }
+
+
+   /**
+    * Return s true of tx's status is ACTIVE or PREPARING or MARKED_ROLLBACK
     *
     * @param tx
     * @return true if the tx is active or preparing
     */
    public static boolean isValid(Transaction tx) {
-      return isActive(tx) || isPreparing(tx);
+      return isActive(tx) || isPreparing(tx) || isMarkedAsRollback(tx);
    }
 
    /**

Added: core/branches/flat/src/test/java/org/horizon/tx/MarkAsRollbackTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/tx/MarkAsRollbackTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/horizon/tx/MarkAsRollbackTest.java	2009-01-23 12:17:27 UTC (rev 7585)
@@ -0,0 +1,73 @@
+package org.horizon.tx;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.horizon.CacheSPI;
+import org.horizon.UnitTestCacheFactory;
+import org.horizon.config.Configuration;
+import org.horizon.transaction.DummyTransactionManagerLookup;
+import org.horizon.util.TestingUtil;
+import org.testng.annotations.Test;
+
+import javax.transaction.RollbackException;
+import javax.transaction.TransactionManager;
+
+ at Test(groups = "functional")
+public class MarkAsRollbackTest {
+   private static final Log log = LogFactory.getLog(MarkAsRollbackTest.class);
+
+   public void testMarkAsRollbackAfterMods() throws Exception {
+      Configuration c = new Configuration();
+      c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+      CacheSPI<String, String> cache = (CacheSPI<String, String>) new UnitTestCacheFactory<String, String>().createCache(c);
+      try {
+         TransactionManager tm = cache.getTransactionManager();
+         assert tm != null;
+         tm.begin();
+         cache.put("k", "v");
+         assert cache.get("k").equals("v");
+         tm.setRollbackOnly();
+         try {
+            tm.commit();
+            assert false : "Should have rolled back";
+         }
+         catch (RollbackException expected) {
+         }
+
+         assert tm.getTransaction() == null : "There should be no transaction in scope anymore!";
+         assert cache.get("k") == null : "Expected a null but was " + cache.get("k");
+      }
+      finally {
+         log.warn("Cleaning up");
+         TestingUtil.killCaches(cache);
+      }
+   }
+
+   public void testMarkAsRollbackBeforeMods() throws Exception {
+      Configuration c = new Configuration();
+      c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+      CacheSPI<String, String> cache = (CacheSPI<String, String>) new UnitTestCacheFactory<String, String>().createCache(c);
+      try {
+         TransactionManager tm = cache.getTransactionManager();
+         assert tm != null;
+         tm.begin();
+         tm.setRollbackOnly();
+         cache.put("k", "v");
+         assert cache.get("k").equals("v");
+         try {
+            tm.commit();
+            assert false : "Should have rolled back";
+         }
+         catch (RollbackException expected) {
+
+         }
+
+         assert tm.getTransaction() == null : "There should be no transaction in scope anymore!";
+         assert cache.get("k") == null : "Expected a null but was " + cache.get("k");
+      }
+      finally {
+         log.warn("Cleaning up");
+         TestingUtil.killCaches(cache);
+      }
+   }
+}




More information about the jbosscache-commits mailing list