[jboss-svn-commits] JBL Code SVN: r33314 - in labs/jbosstm/trunk/txbridge: tests and 2 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Jun 2 13:03:52 EDT 2010


Author: jhalliday
Date: 2010-06-02 13:03:51 -0400 (Wed, 02 Jun 2010)
New Revision: 33314

Modified:
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java
   labs/jbosstm/trunk/txbridge/tests/build.xml
   labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/BasicTests.java
   labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java
Log:
Improved txbridge outbound crash recovery. JBTM-44


Modified: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java	2010-06-02 16:20:36 UTC (rev 33313)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java	2010-06-02 17:03:51 UTC (rev 33314)
@@ -38,6 +38,10 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Provides method call mapping between JTA parent coordinator and WS-AT subordinate transaction.
@@ -51,12 +55,17 @@
 
     private static final Logger log = Logger.getLogger(BridgeXAResource.class);
 
+    private static final List<BridgeXAResource> xaResourcesAwaitingRecovery =
+            Collections.synchronizedList(new LinkedList<BridgeXAResource>());
+
     private transient volatile BridgeWrapper bridgeWrapper;
 
     private volatile Uid externalTxId; // JTA i.e. parent id
 
     private volatile String bridgeWrapperId; // XTS i.e. subordinate.
 
+    private transient volatile boolean isAwaitingRecovery = false;
+
     /**
      * Create a new XAResource which wraps the subordinate WS-AT transaction.
      *
@@ -103,6 +112,12 @@
         externalTxId = (Uid)in.readObject();
         bridgeWrapperId = (String)in.readObject();
 
+        // this readObject method executes only when a log is being read at recovery time:
+        isAwaitingRecovery = true;
+        synchronized(xaResourcesAwaitingRecovery) {
+            xaResourcesAwaitingRecovery.add(this);
+        }
+
         try
         {
             bridgeWrapper = BridgeWrapper.recover(bridgeWrapperId);
@@ -169,7 +184,7 @@
                 log.trace("prepare returning XAResource.XA_OK");
                 return XAResource.XA_OK;
             case TwoPhaseOutcome.PREPARE_READONLY:
-                OutboundBridgeManager.removeMapping(externalTxId);
+                cleanupRefs();
                 log.trace("prepare returning XAResource.XA_RDONLY");
                 return XAResource.XA_RDONLY;
             default:
@@ -183,6 +198,45 @@
     }
 
     /**
+     * Release any BridgeXAResource instances that have been driven
+     * through to completion by their parent JTA transaction.
+     */
+    public static void cleanupRecoveredXAResources()
+    {
+        log.trace("cleanupRecoveredXAResources()");
+
+        synchronized(xaResourcesAwaitingRecovery) {
+            Iterator<BridgeXAResource> iter = xaResourcesAwaitingRecovery.iterator();
+            while(iter.hasNext()) {
+                BridgeXAResource xaResource = iter.next();
+                if(!xaResource.isAwaitingRecovery()) {
+                    iter.remove();
+                }
+            }
+        }
+    }
+
+    /**
+     * Determine if the specified BridgeWrapper is awaiting recovery or not.
+     *
+     * @param bridgeWrapperId the Id to search for.
+     * @return true if the BridgeWrapper is known to be awaiting recovery, false otherwise.
+     */
+    public static boolean isAwaitingRecovery(String bridgeWrapperId)
+    {
+        synchronized(xaResourcesAwaitingRecovery) {
+            for(BridgeXAResource bridgeXAResource : xaResourcesAwaitingRecovery) {
+                if(bridgeXAResource.bridgeWrapperId.equals(bridgeWrapperId)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
      * Informs the resource manager to roll back work done on behalf of a transaction branch.
      *
      * @param xid A global transaction identifier
@@ -202,7 +256,7 @@
         }
         finally
         {
-            OutboundBridgeManager.removeMapping(externalTxId);
+            cleanupRefs();
         }
     }
 
@@ -235,7 +289,7 @@
         }
         finally
         {
-            OutboundBridgeManager.removeMapping(externalTxId);
+            cleanupRefs();
         }
     }
 
@@ -321,4 +375,16 @@
 
         return 0;  // TODO
     }
+
+    public boolean isAwaitingRecovery() {
+        return isAwaitingRecovery;
+    }
+
+    private void cleanupRefs()
+    {
+        log.trace("cleanupRefs()");
+
+        OutboundBridgeManager.removeMapping(externalTxId);
+        isAwaitingRecovery = false;
+    }
 }

Modified: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java	2010-06-02 16:20:36 UTC (rev 33313)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java	2010-06-02 17:03:51 UTC (rev 33314)
@@ -25,6 +25,11 @@
 import org.apache.log4j.Logger;
 import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
 
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
 /**
  * Integrates with JBossAS MC lifecycle and JBossTS recovery manager to provide
  * recovery services for outbound bridged transactions.
@@ -37,6 +42,8 @@
 
     private final RecoveryManager acRecoveryManager = RecoveryManager.manager();
 
+    private volatile boolean orphanedBridgeWrappersAreIdentifiable = false;
+
     /**
      * MC lifecycle callback, used to register components with the recovery manager.
      */
@@ -75,18 +82,22 @@
     @Override
     public void periodicWorkSecondPass()
     {
-        // by the time we are called, the JTA tx recovery module has already been called, as it is registered
-        // and hence ordered before us. Therefore by the time we get here any BridgeWrappers belonging to
-        // a parent that was logged, will have been resolved top down. Anything left at this point can therefore
-        // be assumed orphaned and hence we apply presumed abort.
-
         log.trace("periodicWorkSecondPass()");
 
+        BridgeXAResource.cleanupRecoveredXAResources();
+
+        // the JTA top level tx recovery module is registered and hence run before us. Therefore by the time
+        // we get here we know readObject has been called for any BridgeXAResource for which a log exists.
+        // thus if it's not in our xaResourcesAwaitingRecovery list by now, it's presumed rollback.
+        orphanedBridgeWrappersAreIdentifiable = true;
+
         BridgeWrapper[] bridgeWrappers = BridgeWrapper.scan(OutboundBridgeManager.BRIDGEWRAPPER_PREFIX);
 
         for(BridgeWrapper bridgeWrapper : bridgeWrappers) {
-            log.info("rolling back orphaned subordinate BridgeWrapper "+bridgeWrapper.getIdentifier());
-            bridgeWrapper.rollback();
+            if( !BridgeXAResource.isAwaitingRecovery(bridgeWrapper.getIdentifier()) ) {
+                log.info("rolling back orphaned subordinate BridgeWrapper "+bridgeWrapper.getIdentifier());
+                bridgeWrapper.rollback();
+            }
         }
     }
 }

Modified: labs/jbosstm/trunk/txbridge/tests/build.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/build.xml	2010-06-02 16:20:36 UTC (rev 33313)
+++ labs/jbosstm/trunk/txbridge/tests/build.xml	2010-06-02 17:03:51 UTC (rev 33314)
@@ -198,8 +198,8 @@
             </batchtest>
 
             <jvmarg value="-Djava.rmi.server.codebase=file://build/classes/"/>
-            <jvmarg value="-Xdebug"/>
-            <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/>
+            <!--<jvmarg value="-Xdebug"/>-->
+            <!--<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/>-->
 	        <additional.jvmargs/>
         </junit>
         </sequential>

Modified: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/BasicTests.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/BasicTests.java	2010-06-02 16:20:36 UTC (rev 33313)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/BasicTests.java	2010-06-02 17:03:51 UTC (rev 33314)
@@ -62,9 +62,7 @@
         instrumentedTestSynchronization = instrumentor.instrumentClass(TestSynchronization.class);
         instrumentedTestXAResource = instrumentor.instrumentClass(TestXAResource.class);
 
-        //instrumentor.captureLogging(TestSynchronization.class, null, org.apache.log4j.Logger.class, "error");
         instrumentor.injectOnCall(TestServiceImpl.class, "doNothing", "$0.enlistSynchronization(1), $0.enlistXAResource(1)");
-
     }
 
     @After

Modified: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java	2010-06-02 16:20:36 UTC (rev 33313)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java	2010-06-02 17:03:51 UTC (rev 33314)
@@ -184,7 +184,7 @@
         manager.startServer("default");
     }
 
-    //@Test
+    @Test
     public void testCrashOneLog() throws Exception {
 
         instrumentor.injectOnCall(TestClient.class,  "terminateTransaction", "$1 = true"); // shouldCommit=true
@@ -245,7 +245,7 @@
     }
 
     // this one requires <property name="commitOnePhase">false</property> on CoordinatorEnvironmentBean
-    //@Test
+    @Test
     public void testCrashThreeLogs() throws Exception {
 
         instrumentor.injectOnCall(TestClient.class,  "terminateTransaction", "$1 = true"); // shouldCommit=true



More information about the jboss-svn-commits mailing list