[jboss-svn-commits] JBL Code SVN: r16529 - in labs/jbosstm/trunk: ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery and 4 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Nov 12 04:56:13 EST 2007


Author: mark.little at jboss.com
Date: 2007-11-12 04:56:13 -0500 (Mon, 12 Nov 2007)
New Revision: 16529

Added:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/AtomicActionExpiryScanner.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/ExpiredTransactionScanner.java
Modified:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/recovery/RecoveryEnvironment.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/jca/TransactionImple.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/common/Environment.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/utils/XAHelper.java
Log:
http://jira.jboss.com/jira/browse/JBTM-301 and http://jira.jboss.com/jira/browse/JBTM-300

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/recovery/RecoveryEnvironment.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/recovery/RecoveryEnvironment.java	2007-11-12 09:53:16 UTC (rev 16528)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/recovery/RecoveryEnvironment.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -41,6 +41,8 @@
     public static final String EXPIRY_SCAN_INTERVAL    = "com.arjuna.ats.arjuna.recovery.expiryScanInterval" ;
     public static final String TRANSACTION_STATUS_MANAGER_EXPIRY_TIME = 
 	"com.arjuna.ats.arjuna.recovery.transactionStatusManagerExpiryTime";
+    public static final String TRANSACTION_EXPIRY_TIME = 
+	"com.arjuna.ats.arjuna.recovery.transactionExpiryTime";
     public static final String ACTIVATOR_PROPERTY_PREFIX  = "com.arjuna.ats.arjuna.recovery.recoveryActivator" ;
     
    /** Not used */

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/AtomicActionExpiryScanner.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/AtomicActionExpiryScanner.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/AtomicActionExpiryScanner.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
+ * as indicated by the @author tags. 
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors. 
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A 
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+
+package ArjunaCore.arjuna.classes.com.arjuna.ats.internal.arjuna.recovery;
+
+import com.arjuna.ats.arjuna.AtomicAction;
+
+/**
+ * This class is a plug-in module for the recovery manager. This class is
+ * responsible for the removing ransaction status manager items that are too
+ * old.
+ */
+
+public class AtomicActionExpiryScanner extends ExpiredTransactionScanner
+{
+
+	public AtomicActionExpiryScanner()
+	{
+		super(_transactionType, _transactionType + "/Expired");
+	}
+
+	// 'type' within the Object Store for AtomicActions.
+	private static final String _transactionType = new AtomicAction().type();
+
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/ExpiredTransactionScanner.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/ExpiredTransactionScanner.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/recovery/ExpiredTransactionScanner.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -0,0 +1,199 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
+ * as indicated by the @author tags. 
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors. 
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A 
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+
+package com.arjuna.ats.internal.arjuna.recovery;
+
+import java.util.*;
+import java.io.PrintWriter;
+import java.text.*;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+import com.arjuna.ats.arjuna.objectstore.ObjectStore;
+import com.arjuna.common.util.propertyservice.PropertyManager;
+import com.arjuna.ats.arjuna.recovery.ExpiryScanner;
+import com.arjuna.ats.arjuna.recovery.RecoveryEnvironment;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+import com.arjuna.ats.arjuna.coordinator.TxControl;
+
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.logging.FacilityCode;
+
+import com.arjuna.common.util.logging.*;
+
+/**
+ * @message com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_1
+ *          [com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_1] -
+ *          ExpiredTransactionScanner created, with expiry time of {0} seconds
+ * @message com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_2
+ *          [com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_2] -
+ *          ExpiredTransactionScanner - exception during attempted move {0} {1}
+ * @message com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_3
+ *          [com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_3] -
+ *          ExpiredTransactionScanner - could not moved log {0}
+ * @message com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_4
+ *          [com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_3] -
+ *          ExpiredTransactionScanner - log {0} is assumed complete and will be
+ *          moved.
+ */
+
+/**
+ * This class is a plug-in module for the recovery manager. This class is
+ * responsible for the removing ransaction status manager items that are too
+ * old.
+ */
+
+public class ExpiredTransactionScanner implements ExpiryScanner
+{
+
+	public ExpiredTransactionScanner(String typeName, String movedTypeName)
+	{
+		_objectStore = TxControl.getStore();
+		_typeName = typeName;
+		_movedTypeName = movedTypeName;
+	}
+
+	/**
+	 * This is called periodically by the RecoveryManager
+	 */
+	public void scan()
+	{
+		boolean initialScan = false;
+
+		if (_scanM == null)
+		{
+			_scanM = new Hashtable();
+			initialScan = true;
+		}
+
+		try
+		{
+			InputObjectState uids = new InputObjectState();
+
+			// take a snapshot of the log
+
+			if (_objectStore.allObjUids(_typeName, uids))
+			{
+				Uid theUid = new Uid(Uid.nullUid());
+
+				boolean endOfUids = false;
+
+				while (!endOfUids)
+				{
+					// extract a uid
+					theUid.unpack(uids);
+
+					if (theUid.equals(Uid.nullUid()))
+						endOfUids = true;
+					else
+					{
+						Uid newUid = new Uid(theUid);
+
+						if (initialScan)
+							_scanM.put(newUid, newUid);
+						else
+						{
+							if (!_scanM.contains(newUid))
+							{
+								if (_scanN == null)
+									_scanN = new Hashtable();
+
+								_scanN.put(newUid, newUid);
+							}
+							else
+							// log is present in this iteration, so move it
+							{
+								if (tsLogger.arjLoggerI18N.isInfoEnabled())
+									tsLogger.arjLoggerI18N
+											.info(
+													"com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_4",
+													new Object[]
+													{ newUid });
+
+								try
+								{
+									InputObjectState state = _objectStore
+											.read_committed(newUid, _typeName);
+
+									if (state != null) // just in case recovery
+														// kicked-in
+									{
+										boolean moved = _objectStore
+												.write_committed(newUid,
+														_movedTypeName,
+														new OutputObjectState(
+																state));
+
+										if (!moved)
+										{
+											tsLogger.arjLoggerI18N
+													.warn(
+															"com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner_3",
+															new Object[]
+															{ newUid });
+										}
+									}
+								}
+								catch (Exception ex)
+								{
+									tsLogger.arjLoggerI18N
+											.warn(
+													"com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionScanner_2",
+													new Object[]
+													{ newUid, ex });
+
+									_scanN.put(newUid, newUid);
+								}
+							}
+						}
+					}
+				}
+
+				if (_scanN != null)
+				{
+					_scanM = _scanN;
+					_scanN = null;
+				}
+			}
+		}
+		catch (Exception e)
+		{
+			// end of uids!
+		}
+	}
+
+	public boolean toBeUsed()
+	{
+		return true;
+	}
+
+	private String _typeName;
+
+	private String _movedTypeName;
+
+	private ObjectStore _objectStore;
+
+	private Hashtable _scanM = null;
+
+	private Hashtable _scanN = null;
+
+}

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	2007-11-12 09:53:16 UTC (rev 16528)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -74,6 +74,13 @@
  * @author Mark Little (mark_little at hp.com)
  * @version $Id: XAResourceRecord.java 2342 2006-03-30 13:06:17Z $
  * @since JTS 1.2.4.
+ *
+ * @message com.arjuna.ats.internal.jta.resources.arjunacore.noresource
+ *          [com.arjuna.ats.internal.jta.resources.arjunacore.noresource]
+ *          No XAResource to recover {0}
+ * @message com.arjuna.ats.internal.jta.resources.arjunacore.assumecomplete
+ *          [com.arjuna.ats.internal.jta.resources.arjunacore.assumecomplete]
+ *          Being told to assume complete on Xid {0}
  */
 
 public class XAResourceRecord extends AbstractRecord
@@ -105,7 +112,7 @@
 					com.arjuna.ats.jta.logging.FacilityCode.FAC_JTA,
 					"XAResourceRecord.XAResourceRecord ( " + xid + " )");
 		}
-
+		
 		_theXAResource = res;
 		_recoveryObject = null;
 		_tranID = xid;
@@ -343,7 +350,7 @@
 
 			return TwoPhaseOutcome.FINISH_OK;
 		}
-
+		
 		if (_tranID == null)
 		{
 			if (jtaLogger.loggerI18N.isWarnEnabled())
@@ -410,6 +417,9 @@
 							return TwoPhaseOutcome.HEURISTIC_COMMIT;
 						case XAException.XA_HEURMIX:
 							return TwoPhaseOutcome.HEURISTIC_MIXED;
+						case XAException.XAER_NOTA:
+						    if (_recovered)
+							break; // rolled back previously and recovery completed
 						case XAException.XA_HEURRB: // forget?
 						case XAException.XA_RBROLLBACK:
 						case XAException.XA_RBEND:
@@ -438,7 +448,30 @@
 				}
 			}
 			else
+			{
+			    if (jtaLogger.loggerI18N.isWarnEnabled())
+			    {
+				jtaLogger.loggerI18N
+				    .warn(
+					  "com.arjuna.ats.internal.jta.resources.arjunacore.noresource",
+					  new Object[] {_tranID});
+			    }
+
+			    if (XAResourceRecord._assumedComplete)
+			    {
+				if (jtaLogger.loggerI18N.isInfoEnabled())
+				{
+				    jtaLogger.loggerI18N
+					.info(
+					      "com.arjuna.ats.internal.jta.resources.arjunacore.assumecomplete",
+					      new Object[] {_tranID});
+				}
+
+				return TwoPhaseOutcome.FINISH_OK;
+			    }
+			    else
 				return TwoPhaseOutcome.FINISH_ERROR;
+			}
 		}
 
 		return TwoPhaseOutcome.FINISH_OK;
@@ -541,8 +574,9 @@
 						case XAException.XA_HEURMIX:
 							return TwoPhaseOutcome.HEURISTIC_MIXED;
 						case XAException.XAER_NOTA:
+						    if (_recovered)
+							break; // committed previously and recovery completed
 						case XAException.XAER_PROTO:
-							break;
 						case XAException.XA_RETRY:
 							return TwoPhaseOutcome.FINISH_ERROR;
 						case XAException.XAER_INVAL:
@@ -565,7 +599,30 @@
 				}
 			}
 			else
+			{
+			    if (jtaLogger.loggerI18N.isWarnEnabled())
+			    {
+				jtaLogger.loggerI18N
+				    .warn(
+					  "com.arjuna.ats.internal.jta.resources.arjunacore.noresource",
+					  new Object[] {_tranID});
+			    }
+
+			    if (XAResourceRecord._assumedComplete)
+			    {
+				if (jtaLogger.loggerI18N.isInfoEnabled())
+				{
+				    jtaLogger.loggerI18N
+					.info(
+					      "com.arjuna.ats.internal.jta.resources.arjunacore.assumecomplete",
+					      new Object[] {_tranID});
+				}
+
+				return TwoPhaseOutcome.FINISH_OK;
+			    }
+			    else
 				return TwoPhaseOutcome.FINISH_ERROR;
+			}
 		}
 
 		return TwoPhaseOutcome.FINISH_OK;
@@ -679,16 +736,14 @@
 						forget();
 						return TwoPhaseOutcome.FINISH_ERROR;
 					case XAException.XAER_NOTA:
+						return TwoPhaseOutcome.HEURISTIC_HAZARD; // something committed or rolled back without asking us!
 					case XAException.XAER_PROTO:
-						break;
 					case XAException.XAER_INVAL:
 					case XAException.XAER_RMFAIL: // resource manager failed,
 						// did it rollback?
 						return TwoPhaseOutcome.FINISH_ERROR;
-						// return TwoPhaseOutcome.HEURISTIC_HAZARD;
 					default:
 						return TwoPhaseOutcome.FINISH_ERROR;
-						// return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
 					}
 				}
 				catch (Exception e2)
@@ -947,7 +1002,13 @@
 										new Object[]
 										{ _tranID });
 
-						return false;
+						/*
+						 * Don't prevent tx from activating because there may be
+						 * other participants that can still recover. Plus, we will
+						 * try to get a new XAResource later for this instance.
+						 */
+						
+						return true;
 					}
 				}
 			}
@@ -1041,6 +1102,7 @@
 		_heuristic = TwoPhaseOutcome.FINISH_OK;
 		_valid = true;
 		_theTransaction = null;
+		_recovered = true;
 	}
 
 	protected XAResourceRecord(Uid u)
@@ -1054,6 +1116,7 @@
 		_heuristic = TwoPhaseOutcome.FINISH_OK;
 		_valid = true;
 		_theTransaction = null;
+		_recovered = true;
 	}
 
 	/**
@@ -1090,6 +1153,10 @@
 
 				if (m instanceof XARecoveryModule)
 				{
+				    /*
+				     * Blaargh! There are better ways to do this!
+				     */
+
 					return ((XARecoveryModule) m).getNewXAResource(_tranID);
 				}
 			}
@@ -1143,7 +1210,6 @@
 	protected XAResource _theXAResource;
 
 	private RecoverableXAConnection _recoveryObject;
-
 	private Xid _tranID;
 
 	private boolean _prepared;
@@ -1153,8 +1219,10 @@
 	private int _heuristic;
 
 	private TransactionImple _theTransaction;
+    private boolean _recovered = false;
 
 	private static boolean _rollbackOptimization = false;
+    private static boolean _assumedComplete = false;
 
 	static
 	{
@@ -1163,6 +1231,25 @@
 
 		if (optimization.equals("ON"))
 			_rollbackOptimization = true;
+
+		/*
+		 * WARNING: USE WITH EXTEREME CARE!!
+		 *
+		 * This assumes that if there is no XAResource that can deal with an Xid
+		 * after recovery, then we failed after successfully committing the transaction
+		 * but before updating the log. In which case we just need to ignore this
+		 * resource and remove the entry from the log.
+		 *
+		 * BUT if not all XAResourceRecovery instances are correctly implemented
+		 * (or present) we may end up removing participants that have not been dealt
+		 * with. Hence USE WITH EXTREME CARE!!
+		 */
+
+		String assumedComplete = jtaPropertyManager.propertyManager.getProperty(
+				Environment.XA_ASSUME_RECOVERY_COMPLETE, "FALSE");
+
+		if (assumedComplete.equalsIgnoreCase("true"))
+			_assumedComplete = true;
 	}
 
 }

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java	2007-11-12 09:53:16 UTC (rev 16528)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -38,7 +38,8 @@
 
 import javax.transaction.xa.Xid;
 
-public class TransactionImple extends
+public class TransactionImple
+		extends
 		com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.TransactionImple
 {
 
@@ -46,12 +47,12 @@
 	 * Create a new transaction with the specified timeout.
 	 */
 
-	public TransactionImple (int timeout)
+	public TransactionImple(int timeout)
 	{
 		this(timeout, null);
 	}
-	
-	public TransactionImple (int timeout, Xid importedXid)
+
+	public TransactionImple(int timeout, Xid importedXid)
 	{
 		super(new SubordinateAtomicAction(timeout, importedXid));
 
@@ -61,30 +62,34 @@
 	/**
 	 * Used for failure recovery.
 	 * 
-	 * @param actId the transaction state to recover.
+	 * @param actId
+	 *            the transaction state to recover.
 	 */
-	
-	public TransactionImple (Uid actId)
+
+	public TransactionImple(Uid actId)
 	{
 		super(new SubordinateAtomicAction(actId));
-		
+
 		// don't put it into list here: it may already be there!
 	}
-	
-	public final void recordTransaction ()
+
+	public final void recordTransaction()
 	{
 		TransactionImple.putTransaction(this);
 	}
-	
+
 	/**
 	 * Overloads Object.equals()
 	 */
 
-	public boolean equals (Object obj)
+	public boolean equals(Object obj)
 	{
 		if (jtaLogger.logger.isDebugEnabled())
 		{
-			jtaLogger.logger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, com.arjuna.ats.jta.logging.FacilityCode.FAC_JTA, "TransactionImple.equals");
+			jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+					VisibilityLevel.VIS_PUBLIC,
+					com.arjuna.ats.jta.logging.FacilityCode.FAC_JTA,
+					"TransactionImple.equals");
 		}
 
 		if (obj == null)
@@ -101,7 +106,7 @@
 		return false;
 	}
 
-	public String toString ()
+	public String toString()
 	{
 		if (super._theTransaction == null)
 			return "TransactionImple < jca-subordinate, NoTransaction >";
@@ -113,44 +118,34 @@
 	}
 
 	/**
-	 * If this is an imported transaction (via JCA) then this will be the Xid
-	 * we are pretending to be. Otherwise, it will be null.
+	 * If this is an imported transaction (via JCA) then this will be the Xid we
+	 * are pretending to be. Otherwise, it will be null.
 	 * 
 	 * @return null if we are a local transaction, a valid Xid if we have been
-	 * imported.
+	 *         imported.
 	 */
-	
-	public final Xid baseXid ()
+
+	public final Xid baseXid()
 	{
 		return ((SubordinateAtomicAction) _theTransaction).getXid();
 	}
 
 	/**
-	 * Has the transaction been activated successfully? If not, we wait
-	 * and try again later.
+	 * Force this transaction to try to recover itself again.
 	 */
-	
-    public boolean activated ()
-    {
-    	return ((SubordinateAtomicAction) _theTransaction).activated();
-    }
 
-    /**
-     * Force this transaction to try to recover itself again.
-     */
-    
-    public void recover ()
-    {
-		Uid actId = _theTransaction.get_uid();
+	public void recover()
+	{
+		_theTransaction.activate();
+	}
 
-		/*
-		 * Get a new subordinate instance. This will force activate to
-		 * be called again. Calling _theTransaction.activate should work,
-		 * but this is cleaner and guarantees the instance is in the right
-		 * state for recovery. Performance should not be an issue during
-		 * recovery either.
-		 */
-		
-		_theTransaction = new SubordinateAtomicAction(actId);
-    }
+	/**
+	 * Has the transaction been activated successfully? If not, we wait and try
+	 * again later.
+	 */
+
+	public boolean activated()
+	{
+		return ((SubordinateAtomicAction) _theTransaction).activated();
+	}
 }

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/common/Environment.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/common/Environment.java	2007-11-12 09:53:16 UTC (rev 16528)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/common/Environment.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -52,6 +52,7 @@
     public static final String XA_BACKOFF_PERIOD = "com.arjuna.ats.jta.xaBackoffPeriod";
     public static final String XA_RECOVERY_NODE = "com.arjuna.ats.jta.xaRecoveryNode";
     public static final String XA_ROLLBACK_OPTIMIZATION = "com.arjuna.ats.jta.xaRollbackOptimization";
+    public static final String XA_ASSUME_RECOVERY_COMPLETE = "com.arjuna.ats.jta.xaAssumeRecoveryComplete";
 
     public static final String UT_JNDI_CONTEXT = "com.arjuna.ats.jta.utils.UTJNDIContext";
     public static final String TM_JNDI_CONTEXT = "com.arjuna.ats.jta.utils.TMJNDIContext";

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/utils/XAHelper.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/utils/XAHelper.java	2007-11-12 09:53:16 UTC (rev 16528)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/utils/XAHelper.java	2007-11-12 09:56:13 UTC (rev 16529)
@@ -168,6 +168,47 @@
 	}
 
 	/**
+	 * Compares two Xid instances at the gtid level only.
+	 * 
+	 * @param Xid
+	 *            x1 first Xid
+	 * @param Xid
+	 *            x2 second Xid
+	 * 
+	 * @return <code>true</code> if the two instances are the same,
+	 *         <code>false</code> otherwise.
+	 */
+
+	public static boolean sameTransaction (Xid x1, Xid x2)
+	{
+		if (x1 == x2)
+			return true;
+		else
+		{
+			if (x1.getFormatId() == x2.getFormatId())
+			{
+				byte[] gtrid1 = x1.getGlobalTransactionId();
+				byte[] gtrid2 = x2.getGlobalTransactionId();
+
+				if (gtrid1.length == gtrid2.length)
+				{
+					for (int i = 0; i < gtrid1.length; i++)
+					{
+						if (gtrid1[i] != gtrid2[i])
+							return false;
+					}
+
+					return true;
+				}
+				else
+					return false;
+			}
+			else
+			    return false;
+		}
+	}
+
+	/**
 	 * get a string representing anyones Xid similar too, but not the same as
 	 * OTS_Transaction/xa/XID.toString()
 	 */




More information about the jboss-svn-commits mailing list