[jboss-svn-commits] JBL Code SVN: r29095 - in labs/jbosstm/trunk: ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore and 6 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Aug 27 17:36:39 EDT 2009


Author: mark.little at jboss.com
Date: 2009-08-27 17:36:39 -0400 (Thu, 27 Aug 2009)
New Revision: 29095

Modified:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseOutcome.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
   labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/XAResourceRecord.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java
   labs/jbosstm/trunk/ArjunaJTS/jts/classes/com/arjuna/ats/internal/jts/resources/ExtendedResourceRecord.java
Log:
https://jira.jboss.org/jira/browse/JBTM-605

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -2669,8 +2669,11 @@
 		criticalStart();
 
 		if ((heuristicList == null) && reportHeuristics)
-			heuristicList = new RecordList(); // the only list we'll need.
-
+			heuristicList = new RecordList();
+		
+		if (failedList == null)
+		    failedList = new RecordList();
+		
 		/*
 		 * Since it is one-phase, the outcome from the record is the outcome of
 		 * the transaction. Therefore, we don't need to save much intermediary
@@ -2680,10 +2683,10 @@
 		boolean stateToSave = false;
 
 		recordBeingHandled = pendingList.getFront();
-	
+
 		int p = ((actionType == ActionType.TOP_LEVEL) ? recordBeingHandled.topLevelOnePhaseCommit()
 				: recordBeingHandled.nestedOnePhaseCommit());
-	
+	  
 		if ((p == TwoPhaseOutcome.FINISH_OK)
 				|| (p == TwoPhaseOutcome.PREPARE_READONLY))
 		{
@@ -2701,73 +2704,70 @@
 		}
 		else
 		{
-			// aborted or heuristic which we aren't interested in
-
 			if (p == TwoPhaseOutcome.FINISH_ERROR)
 			{
-				/*
-				 * Don't bother about the failedList - we are aborting, and
-				 * there is only one record!
-				 */
-
-				recordBeingHandled = null;
-
-				actionStatus = ActionStatus.ABORTED;
+			    if (!failedList.insert(recordBeingHandled))
+                                recordBeingHandled = null;
+                            else
+                            {
+                                if (!stateToSave)
+                                    stateToSave = recordBeingHandled.doSave();
+                            }
 			}
 			else
 			{
-				/*
-				 * Heuristic decision!!
-				 */
-
-				if (tsLogger.arjLoggerI18N.isWarnEnabled())
-				{
-					tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.BasicAction_47", new Object[]
-					{ get_uid(), TwoPhaseOutcome.stringForm(p) });
-				}
-
-				if (reportHeuristics)
-				{
-					updateHeuristic(p, true);
-
-					if (!heuristicList.insert(recordBeingHandled))
-						recordBeingHandled = null;
-					else
-					{
-						if (!stateToSave)
-							stateToSave = recordBeingHandled.doSave();
-					}
-				}
-
-				if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
-				{
-					/*
-					 * Signal that the action outcome is the same as the
-					 * heuristic decision.
-					 */
-
-					heuristicDecision = TwoPhaseOutcome.PREPARE_OK; // means no
-																	// heuristic
-																	// was
-																	// raised.
-
-					actionStatus = ActionStatus.ABORTED;
-				}
-				else if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_COMMIT)
-				{
-					heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
-					actionStatus = ActionStatus.COMMITTED;
-				}
-				else
-					actionStatus = ActionStatus.COMMITTED; // can't really say
-														   // (could have
-														   // aborted)
-			}
+        			/*
+        			 * Heuristic decision!!
+        			 */
+        
+        			if (tsLogger.arjLoggerI18N.isWarnEnabled())
+        			{
+        			    tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.BasicAction_47", new Object[]
+        			                                                                                               { get_uid(), TwoPhaseOutcome.stringForm(p) });
+        			}
+        
+        			if (reportHeuristics)
+        			{
+        			    updateHeuristic(p, true);
+        
+        			    if (!heuristicList.insert(recordBeingHandled))
+        			        recordBeingHandled = null;
+        			    else
+        			    {
+        			        if (!stateToSave)
+        			            stateToSave = recordBeingHandled.doSave();
+        			    }
+        			}
+        
+        			if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+        			{
+        			    /*
+        			     * Signal that the action outcome is the same as the
+        			     * heuristic decision.
+        			     */
+        
+        			    heuristicDecision = TwoPhaseOutcome.PREPARE_OK; // means no
+        			    // heuristic
+        			    // was
+        			    // raised.
+        
+        			    actionStatus = ActionStatus.ABORTED;
+        			}
+        			else if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_COMMIT)
+        			{
+        			    heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
+        			    actionStatus = ActionStatus.COMMITTED;
+        			}
+        			else
+        			    actionStatus = ActionStatus.H_HAZARD; // can't really say
+        			// (could have
+        			// aborted)
+        		}
 		}
 
 		if (actionType == ActionType.TOP_LEVEL)
 		{			
-			if (stateToSave && (heuristicList.size() > 0))
+			if (stateToSave && ((heuristicList.size() > 0) || (failedList.size() > 0)))
 			{
 				if (store() == null)
 				{
@@ -3227,7 +3227,7 @@
 						{
 							/*
 							 * The commit failed. Add this record to the failed
-							 * list to indicate this.
+							 * list to indicate this. Covers statuses like FAILED_ERROR.
 							 */
 
 							failedList.insert(recordBeingHandled);
@@ -3259,7 +3259,7 @@
 			}
 		}
 
-		return TwoPhaseOutcome.FINISH_OK;
+		return ok;
 	}
 
 	/*

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseOutcome.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseOutcome.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseOutcome.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -48,6 +48,8 @@
  * @since JTS 1.0.
  */
 
+// TODO this needs extending.
+
 public class TwoPhaseOutcome
 {
 

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -447,6 +447,8 @@
 								{
 									if (recoveryStatus == XARecoveryResource.WAITING_FOR_RECOVERY)
 									{
+									    // resource initiated recovery not possible (no distribution).
+									    
 										problem = false;
 
 										if (jtaLogger.loggerI18N
@@ -479,9 +481,7 @@
 									}
 								}
 								else
-									problem = false; // resource initiated
-								// recovery not possible
-								// (no distribution).
+									problem = false;
 							}
 								break;
 							case XARecoveryResource.INFLIGHT_TRANSACTION:

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -51,6 +51,7 @@
 
 import com.arjuna.ats.arjuna.ObjectType;
 import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator;
 import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
 import com.arjuna.ats.arjuna.coordinator.RecordType;
 import com.arjuna.ats.arjuna.coordinator.TxControl;
@@ -447,9 +448,9 @@
 					{
 						if (jtaLogger.loggerI18N.isWarnEnabled())
 						{
-                            jtaLogger.loggerI18N.warn(
-                                    "com.arjuna.ats.internal.jta.resources.arjunacore.rollbackerror",
-                                    new Object[] { _tranID, _theXAResource, XAHelper.printXAErrorCode(e1) }, e1);
+						    jtaLogger.loggerI18N.warn(
+						            "com.arjuna.ats.internal.jta.resources.arjunacore.rollbackerror",
+						            new Object[] { _tranID, _theXAResource, XAHelper.printXAErrorCode(e1) }, e1);
 						}
 
 						switch (e1.errorCode)
@@ -483,12 +484,12 @@
 				}
 				catch (Exception e2)
 				{
-                    if (jtaLogger.loggerI18N.isWarnEnabled())
-                    {
-                        jtaLogger.loggerI18N.warn(
-                                "com.arjuna.ats.internal.jta.resources.arjunacore.rollbackerror",
-                                new Object[] { _tranID, _theXAResource, e2.toString() }, e2);
-                    }
+				    if (jtaLogger.loggerI18N.isWarnEnabled())
+				    {
+				        jtaLogger.loggerI18N.warn(
+				                "com.arjuna.ats.internal.jta.resources.arjunacore.rollbackerror",
+				                new Object[] { _tranID, _theXAResource, e2.toString() }, e2);
+				    }
 
 					return TwoPhaseOutcome.FINISH_ERROR;
 				}
@@ -591,9 +592,9 @@
 					{
 						if (jtaLogger.loggerI18N.isWarnEnabled())
 						{
-                            jtaLogger.loggerI18N.warn(
-                                    "com.arjuna.ats.internal.jta.resources.arjunacore.commitxaerror",
-                                    new Object[] { _tranID, _theXAResource, XAHelper.printXAErrorCode(e1) }, e1);
+						    jtaLogger.loggerI18N.warn(
+						            "com.arjuna.ats.internal.jta.resources.arjunacore.commitxaerror",
+						            new Object[] { _tranID, _theXAResource, XAHelper.printXAErrorCode(e1) }, e1);
 						}
 
 						/*
@@ -611,7 +612,7 @@
 														// this code here.
 							break;
 						case XAException.XA_HEURRB:
-						case XAException.XA_RBROLLBACK:
+						case XAException.XA_RBROLLBACK:  // could really do with an ABORTED status in TwoPhaseOutcome to differentiate
 						case XAException.XA_RBCOMMFAIL:
 						case XAException.XA_RBDEADLOCK:
 						case XAException.XA_RBINTEGRITY:
@@ -630,6 +631,8 @@
 						        return TwoPhaseOutcome.HEURISTIC_HAZARD;  // something terminated the transaction!
 						case XAException.XAER_PROTO:
 						case XAException.XA_RETRY:
+						    _committed = true;  // will cause log to be rewritten
+						    
 	                                            /*
                                                      * Could do timeout retry here, but that could cause other resources in the list to go down the
                                                      * heuristic path (some are far too keen to do this). Fail and let recovery retry. Meanwhile
@@ -648,14 +651,14 @@
 				}
 				catch (Exception e2)
 				{
-					if (jtaLogger.loggerI18N.isWarnEnabled())
-					{
-                        jtaLogger.loggerI18N.warn(
-                                "com.arjuna.ats.internal.jta.resources.arjunacore.commitxaerror",
-                                new Object[] { _tranID, _theXAResource, e2.toString() }, e2);
-					}
+				    if (jtaLogger.loggerI18N.isWarnEnabled())
+				    {
+				        jtaLogger.loggerI18N.warn(
+				                "com.arjuna.ats.internal.jta.resources.arjunacore.commitxaerror",
+				                new Object[] { _tranID, _theXAResource, e2.toString() }, e2);
+				    }
 
-                    return TwoPhaseOutcome.FINISH_ERROR;
+				    return TwoPhaseOutcome.FINISH_ERROR;
 				}
 				finally
 				{
@@ -880,16 +883,19 @@
 					case XAException.XA_RBTRANSIENT:
 					case XAException.XAER_RMERR:
 						forget();
-						return TwoPhaseOutcome.FINISH_ERROR;
+						return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
 					case XAException.XAER_NOTA:
 						return TwoPhaseOutcome.HEURISTIC_HAZARD; // something committed or rolled back without asking us!
-					case XAException.XAER_PROTO:
-					case XAException.XAER_INVAL:
-					case XAException.XAER_RMFAIL: // resource manager failed,
-						// did it rollback?
-						return TwoPhaseOutcome.FINISH_ERROR;
+                                        case XAException.XAER_INVAL:
+                                        case XAException.XAER_RMFAIL: // resource manager
+                                                // failed, did it
+                                                // rollback?
+                                                return TwoPhaseOutcome.HEURISTIC_HAZARD;
+	                                case XAException.XA_RETRY:
+	                                case XAException.XAER_PROTO:
 					default:
-						return TwoPhaseOutcome.FINISH_ERROR;
+					    _committed = true;  // will cause log to be rewritten
+						return TwoPhaseOutcome.FINISH_ERROR;  // recovery should retry
 					}
 				}
 				catch (Exception e2)
@@ -961,7 +967,20 @@
 					"XAResourceRecord.recover");
 		}
 
-		return XARecoveryResource.FAILED_TO_RECOVER;
+		if (_committed)
+		{
+		    /*
+		     * A previous commit attempt failed, but we know the intention
+		     * was to commit. So let's try again.
+		     */
+		    
+		    if (topLevelCommit() == TwoPhaseOutcome.FINISH_OK)
+		        return XARecoveryResource.RECOVERED_OK;
+		    else
+		        return XARecoveryResource.FAILED_TO_RECOVER;
+		}
+		else
+		    return XARecoveryResource.WAITING_FOR_RECOVERY;
 	}
 
 	public static AbstractRecord create()
@@ -987,7 +1006,8 @@
 		try
 		{
 			os.packInt(_heuristic);
-
+			os.packBoolean(_committed);
+			
 			/*
 			 * Since we don't know what type of Xid we are using, leave it up to
 			 * XID to pack.
@@ -1082,6 +1102,8 @@
 		try
 		{
 			_heuristic = os.unpackInt();
+			_committed = os.unpackBoolean();
+			
 			_tranID = XidImple.unpack(os);
 
 			_theXAResource = null;
@@ -1367,6 +1389,8 @@
 
 	private int _heuristic;
 
+	private boolean _committed = false; // try to optimize recovery
+	
 	private TransactionImple _theTransaction;
     private boolean _recovered = false;
 

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -281,6 +281,7 @@
 			switch (status)
 			{
 			case ActionStatus.COMMITTED:
+			case ActionStatus.COMMITTING:
 			case ActionStatus.H_COMMIT:
 				TransactionImple.removeTransaction(this);
 				break;

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -505,17 +505,68 @@
         assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, t.getStatus());
     }
 
-/*
     @Test
-    public void testFailOnCommit() throws Exception
+    public void testFailOnCommitOnePhaseRetry () throws Exception
     {
         final Xid xid = new XidImple(new Uid());
         final Transaction t = SubordinationManager.getTransactionImporter().importTransaction(xid);
 
         final TestXAResource xaResource = new TestXAResource();
+
+        xaResource.setCommitException(new XAException(XAException.XA_RETRY));
+
+        t.enlistResource(xaResource);
+
+        final XATerminator xaTerminator = SubordinationManager.getXATerminator();
+
+        /*
+         * This should not cause problems. The transaction really has committed, or will once
+         * recovery kicks off. So nothing for the parent to do. The subordinate log will
+         * maintain enough information to drive recovery locally if we get to the point of
+         * issuing a commit call from parent to child.
+         */
+        
+        xaTerminator.commit(xid, true);  // transaction is completed (or will be eventually by recovery).
+    }
+
+    @Test
+    public void testFailOnCommitOnePhase () throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final Transaction t = SubordinationManager.getTransactionImporter().importTransaction(xid);
+
+        final TestXAResource xaResource = new TestXAResource();
         // provoke commit into failing with TwoPhaseOutcome.FINISH_ERROR
         // warning: this is sensitive to the impl exception handling in
         // XAResourceRecord.topLevelCommit
+        xaResource.setCommitException(new XAException(XAException.XA_HEURRB));  // should cause an exception!
+
+        t.enlistResource(xaResource);
+
+        final XATerminator xaTerminator = SubordinationManager.getXATerminator();
+
+        try
+        {
+            xaTerminator.commit(xid, true);
+        }
+        catch (final XAException ex)
+        {
+            // success!
+            
+            return;
+        }
+
+        assertTrue("commit should throw an exception and not get to here", false);
+    }
+    
+    @Test
+    public void testFailOnCommitRetry () throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final Transaction t = SubordinationManager.getTransactionImporter().importTransaction(xid);
+
+        final TestXAResource xaResource = new TestXAResource();
+
         xaResource.setCommitException(new XAException(XAException.XA_RETRY));
 
         t.enlistResource(xaResource);
@@ -523,11 +574,45 @@
         final XATerminator xaTerminator = SubordinationManager.getXATerminator();
 
         xaTerminator.prepare(xid);
+        
+        /*
+         * This should not cause problems. The transaction really has committed, or will once
+         * recovery kicks off. So nothing for the parent to do. The subordinate log will
+         * maintain enough information to drive recovery locally if we get to the point of
+         * issuing a commit call from parent to child.
+         */
+        
         xaTerminator.commit(xid, false);
+    }
+    
+    @Test
+    public void testFailOnCommit() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final Transaction t = SubordinationManager.getTransactionImporter().importTransaction(xid);
 
-        //assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, t.getStatus());
+        final TestXAResource xaResource = new TestXAResource();
+        // provoke commit into failing with TwoPhaseOutcome.FINISH_ERROR
+        // warning: this is sensitive to the impl exception handling in
+        // XAResourceRecord.topLevelCommit
+        xaResource.setCommitException(new XAException(XAException.XA_HEURHAZ));  // throw a little spice into things!
 
+        t.enlistResource(xaResource);
+
+        final XATerminator xaTerminator = SubordinationManager.getXATerminator();
+
+        try
+        {
+            xaTerminator.prepare(xid);
+            xaTerminator.commit(xid, false);
+        }
+        catch (final XAException ex)
+        {
+            // success!!
+            
+            return;
+        }
+        
         assertTrue("commit should throw an exception and not get to here", false);
     }
-*/
 }

Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/XAResourceRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/XAResourceRecord.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/XAResourceRecord.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -603,7 +603,8 @@
                             throw new TRANSACTION_ROLLEDBACK();
 
 						case XAException.XA_RETRY:
-							throw new UNKNOWN();
+						    _committed = true;  // remember for recovery later.
+							throw new UNKNOWN();  // will cause log to be rewritten.
 						case XAException.XAER_INVAL:
 						case XAException.XAER_RMFAIL: // resource manager
 													  // failed, did it
@@ -878,8 +879,11 @@
 					case XAException.XAER_INVAL:
 					case XAException.XAER_RMFAIL: // resource manager failed,
 												  // did it rollback?
-						throw new UNKNOWN();
+						throw new org.omg.CosTransactions.HeuristicHazard();
+					case XAException.XA_RETRY:
 					default:
+					    _committed = true;  // will cause log to be rewritten
+					
 						throw new UNKNOWN();
 					}
 				}
@@ -957,7 +961,8 @@
 		try
 		{
 			os.packInt(_heuristic);
-
+			os.packBoolean(_committed);
+			
 			/*
 			 * Since we don't know what type of Xid we are using, leave it up to
 			 * XID to pack.
@@ -1058,6 +1063,8 @@
 		try
 		{
 			_heuristic = os.unpackInt();
+			_committed = os.unpackBoolean();
+			
 			_tranID = XidImple.unpack(os);
 
 			_theXAResource = null;
@@ -1253,8 +1260,11 @@
 			}
 			catch (OBJECT_NOT_EXIST ex)
 			{
-				// no coordinator, so presumed abort.
+				// no coordinator, so presumed abort unless we have better information.
 
+			    if (_committed)
+			        s = org.omg.CosTransactions.Status.StatusCommitted;
+			    else
 				s = org.omg.CosTransactions.Status.StatusRolledBack;
 			}
 			catch (NotPrepared ex1)

Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -31,6 +31,7 @@
 import javax.transaction.Status;
 
 import org.omg.CORBA.SystemException;
+import org.omg.CORBA.UNKNOWN;
 import org.omg.CosTransactions.HeuristicHazard;
 import org.omg.CosTransactions.HeuristicMixed;
 import org.omg.CosTransactions.NoTransaction;
@@ -175,6 +176,10 @@
 	    {
 	        return ActionStatus.ABORTED;
 	    }
+	    catch (final UNKNOWN ex)
+	    {
+	        return ActionStatus.COMMITTING;  // recovery to kick in.
+	    }
 	    catch (final Exception ex)
 	    {
 	        return ActionStatus.H_HAZARD;

Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -332,6 +332,7 @@
                         {
                         case ActionStatus.COMMITTED:
                         case ActionStatus.H_COMMIT:
+                        case ActionStatus.COMMITTING:
                                 break;
                         case ActionStatus.ABORTED:
                         case ActionStatus.ABORTING:

Modified: labs/jbosstm/trunk/ArjunaJTS/jts/classes/com/arjuna/ats/internal/jts/resources/ExtendedResourceRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jts/classes/com/arjuna/ats/internal/jts/resources/ExtendedResourceRecord.java	2009-08-27 16:32:09 UTC (rev 29094)
+++ labs/jbosstm/trunk/ArjunaJTS/jts/classes/com/arjuna/ats/internal/jts/resources/ExtendedResourceRecord.java	2009-08-27 21:36:39 UTC (rev 29095)
@@ -640,12 +640,25 @@
 		}
 		catch (TRANSACTION_ROLLEDBACK e4)
 		{			
-			return TwoPhaseOutcome.FINISH_ERROR;
+		    /*
+		     * It rolled back. That's ok, but we need to be able
+		     * to communicate that back to the caller.
+		     */
+		    
+			return TwoPhaseOutcome.HEURISTIC_ROLLBACK;  // TODO TPO extension required.
 		}
 		catch (INVALID_TRANSACTION e5)
 		{
 			return TwoPhaseOutcome.FINISH_ERROR;
 		}
+		catch (final UNKNOWN ex)
+		{
+		    /*
+		     * Means we can retry.
+		     */
+		    
+		    return TwoPhaseOutcome.FINISH_ERROR;
+		}
 		catch (Exception e5)
 		{
 			e5.printStackTrace();



More information about the jboss-svn-commits mailing list