[jboss-svn-commits] JBL Code SVN: r6409 - in labs/jbosstm/trunk: ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore ArjunaJTA/jta/classes/com/arjuna/ats/jta/common ArjunaJTA/jta/classes/com/arjuna/ats/jta/resources ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Sep 25 05:56:56 EDT 2006


Author: kevin.conner at jboss.com
Date: 2006-09-25 05:56:45 -0400 (Mon, 25 Sep 2006)
New Revision: 6409

Added:
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAOnePhaseResource.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/resources/LastResourceCommitOptimisation.java
   labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource/
   labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource/LastOnePhaseResource.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/LastResourceRecord.java
Modified:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/LastResourceRecord.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordType.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/common/Environment.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java
Log:
Add Last Resource Commit Optimisation for JBTM-87

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/LastResourceRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/LastResourceRecord.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/LastResourceRecord.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -143,10 +143,12 @@
 
 		if (_lro != null)
 		{
-			return _lro.rollback();
+			return _lro.rollback() ;
 		}
-
-		return TwoPhaseOutcome.FINISH_ERROR;
+		else
+		{
+			return TwoPhaseOutcome.FINISH_OK;
+		}
 	}
 
 	public int topLevelCommit ()
@@ -157,12 +159,7 @@
 					+ order());
 		}
 
-		if (_lro != null)
-		{
-			return _lro.commit();
-		}
-
-		return TwoPhaseOutcome.FINISH_ERROR;
+		return TwoPhaseOutcome.FINISH_OK;
 	}
 
 	public int topLevelPrepare ()
@@ -173,7 +170,7 @@
 					+ order());
 		}
 
-		if (_lro != null)
+		if ((_lro != null) && (_lro.commit() == TwoPhaseOutcome.FINISH_OK))
 		{
 			return TwoPhaseOutcome.PREPARE_OK;
 		}
@@ -187,90 +184,6 @@
 		super.print(strm);
 	}
 
-	public boolean doSave ()
-	{
-		return true;
-	}
-
-	/**
-	 * @message com.arjuna.ats.arjuna.LastResourceRecord_1
-	 *          [com.arjuna.ats.arjuna.LastResourceRecord_1]
-	 *          DisposeRecord::save_state - failed
-	 * @message com.arjuna.ats.arjuna.LastResourceRecord_2
-	 *          [com.arjuna.ats.arjuna.LastResourceRecord_2]
-	 *          DisposeRecord::save_state - no resource to save!
-	 */
-
-	public boolean save_state (OutputObjectState os, int ot)
-	{
-		boolean res = true;
-
-		if (_lro != null)
-		{
-			try
-			{
-				os.packString(OnePhaseResource.class.getName());
-
-				_lro.pack(os);
-			}
-			catch (IOException e)
-			{
-				if (tsLogger.arjLoggerI18N.isWarnEnabled())
-					tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.LastResourceRecord_1");
-				res = false;
-			}
-		}
-		else
-		{
-			if (tsLogger.arjLoggerI18N.isWarnEnabled())
-				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.LastResourceRecord_2");
-
-			res = false;
-		}
-
-		return res;
-	}
-
-	/**
-	 * @message com.arjuna.ats.arjuna.LastResourceRecord_3
-	 *          [com.arjuna.ats.arjuna.LastResourceRecord_3]
-	 *          DisposeRecord::restore_state - failed to unpack.
-	 * @message com.arjuna.ats.arjuna.LastResourceRecord_4
-	 *          [com.arjuna.ats.arjuna.LastResourceRecord_4]
-	 *          DisposeRecord::restore_state - failed to recreate state {0}
-	 */
-
-	public boolean restore_state (InputObjectState os, int ot)
-	{
-		boolean res = true;
-
-		try
-		{
-			String classType = os.unpackString();
-
-			_lro = (OnePhaseResource) (Thread.currentThread().getContextClassLoader().loadClass(classType)).newInstance();
-
-			_lro.unpack(os);
-		}
-		catch (IOException e)
-		{
-			if (tsLogger.arjLoggerI18N.isWarnEnabled())
-				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.LastResourceRecord_3");
-
-			res = false;
-		}
-		catch (Exception ex)
-		{
-			if (tsLogger.arjLoggerI18N.isWarnEnabled())
-				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.LastResourceRecord_4", new Object[]
-				{ ex });
-
-			res = false;
-		}
-
-		return res;
-	}
-
 	public String type ()
 	{
 		return "/StateManager/AbstractRecord/LastResourceRecord";
@@ -334,6 +247,6 @@
 
 	private OnePhaseResource _lro;
 	
-	private static final Uid ONE_PHASE_RESOURCE_UID = new Uid("0:0:0:1");
+	private static final Uid ONE_PHASE_RESOURCE_UID = Uid.maxUid() ;
 
 }

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordType.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordType.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordType.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -58,16 +58,7 @@
 
 public class RecordType
 {
-
     /**
-     * The following is for a one-phase aware resource that we enlist in
-     * a two-phase commit transaction using the last resource commit
-     * optimization. It's commit must go off before any other record.
-     */
-
-    public static final int LASTRESOURCE = 0;
-
-    /**
      * The following values are provided for user-defined
      * records that should have operations invoked BEFORE the
      * system records.
@@ -134,6 +125,13 @@
     public static final int NONE_RECORD = 463;
 
     /**
+     * The following is for a one-phase aware resource that we enlist in
+     * a two-phase commit transaction using the last resource commit
+     * optimization. It's prepare must go off after all other records.
+     */
+    public static final int LASTRESOURCE = Integer.MAX_VALUE;
+    
+    /**
      * @return the <code>ClassName</code> representing this type.
      * @see com.arjuna.ats.arjuna.gandiva.ClassName
      */

Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAOnePhaseResource.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAOnePhaseResource.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAOnePhaseResource.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2005
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id$
+ */
+
+package com.arjuna.ats.internal.jta.resources.arjunacore;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.SQLException;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import com.arjuna.ats.arjuna.coordinator.OnePhaseResource;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+import com.arjuna.ats.jta.logging.FacilityCode;
+import com.arjuna.ats.jta.logging.jtaLogger;
+import com.arjuna.ats.jta.xa.RecoverableXAConnection;
+import com.arjuna.ats.jta.xa.XidImple;
+import com.arjuna.common.util.logging.DebugLevel;
+import com.arjuna.common.util.logging.VisibilityLevel;
+
+/**
+ * One Phase resource wrapper for XAResources. 
+ * @author Kevin Conner (Kevin.Conner at arjuna.com)
+ * @version $Id$
+ * @since ATS 4.1
+  */
+public class XAOnePhaseResource implements OnePhaseResource
+{
+    /**
+     * The one phase XA resource.
+     */
+    private XAResource xaResource ;
+    /**
+     * The recoverable XA connection.
+     */
+    private RecoverableXAConnection recoverableXAConnection ;
+    /**
+     * The transaction identified.
+     */
+    private Xid xid ;
+    
+    /**
+     * Default constructor for deserialising resource.
+     */
+    public XAOnePhaseResource()
+    {
+    }
+    
+    /**
+     * Construct the one phase wrapper for the specified resource.
+     * @param xaResource The XA resource being wrapped.
+     * @param xid The transaction identifier.
+     * @param params additional params to pass through.
+     */
+    public XAOnePhaseResource(final XAResource xaResource, final Xid xid, final Object[] params)
+    {
+        this.xaResource = xaResource ;
+        this.xid = xid ;
+        if ((params != null) && (params.length >= XAResourceRecord.XACONNECTION))
+        {
+            final Object param = params[XAResourceRecord.XACONNECTION] ;
+            if (param instanceof RecoverableXAConnection)
+                recoverableXAConnection = (RecoverableXAConnection)param ;
+        }
+    }
+
+    /**
+     * Commit the one phase resource.
+     * @return TwoPhaseOutcome.FINISH_OK or TwoPhaseOutcome.FINISH_ERROR
+     */
+    public int commit()
+    {
+        try
+        {
+            xaResource.commit(xid, true) ;
+            return TwoPhaseOutcome.FINISH_OK ;
+        }
+        catch (final XAException xae)
+        {
+            if (jtaLogger.logger.isDebugEnabled())
+            {
+                jtaLogger.logger.debug(DebugLevel.ERROR_MESSAGES,
+                    VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_JTA,
+                    "XAOnePhaseResource.commit(" + xid + ") " + xae.getMessage());
+            }
+			if ((xae.errorCode >= XAException.XA_RBBASE)
+					&& (xae.errorCode <= XAException.XA_RBEND))
+			{
+				return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
+			}
+            return TwoPhaseOutcome.FINISH_ERROR ;
+        }
+    }
+
+    /**
+     * Commit the one phase resource.
+     * @return TwoPhaseOutcome.FINISH_OK or TwoPhaseOutcome.FINISH_ERROR
+     */
+    public int rollback()
+    {
+        try
+        {
+            xaResource.rollback(xid) ;
+            return TwoPhaseOutcome.FINISH_OK ;
+        }
+        catch (final XAException xae)
+        {
+            if (jtaLogger.logger.isWarnEnabled())
+            {
+                jtaLogger.logger.warn("XAOnePhaseResource.rollback(" + xid + ") " + xae.getMessage());
+            }
+            return TwoPhaseOutcome.FINISH_ERROR ;
+        }
+    }
+
+    /**
+     * Pack the state of the resource.
+     * @param os The object output state.
+     * 
+     * @message com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.pack
+     * failed to serialise resource {0}
+     */
+    public void pack(final OutputObjectState os)
+        throws IOException
+    {
+        XidImple.pack(os, xid);
+        if (recoverableXAConnection != null)
+        {
+            os.packInt(RecoverableXAConnection.AUTO_RECOVERY);
+            os.packString(recoverableXAConnection.getClass().getName());
+
+            recoverableXAConnection.packInto(os);
+        }
+        else
+        {
+            os.packInt(RecoverableXAConnection.OBJECT_RECOVERY) ;
+            final byte[] data ;
+            try
+            {
+                final ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
+                final ObjectOutputStream oos = new ObjectOutputStream(baos) ;
+                oos.writeObject(xaResource) ;
+                oos.flush() ;
+                oos.close() ;
+                data = baos.toByteArray() ;
+            }
+            catch (final IOException ioe)
+            {
+                final String message = "XAOnePhaseResource.pack() " +
+                    jtaLogger.loggerI18N.getString("com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.pack", new Object[] {ioe}) ;
+                if (jtaLogger.logger.isWarnEnabled())
+                {
+                    jtaLogger.logger.warn(message);
+                }
+                throw new IOException(message) ;
+            }
+            os.packBytes(data) ;
+        }
+    }
+
+    /**
+     * Unpack the state of the resource.
+     * @param is The object input state.
+     * 
+     * @message com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.unpack
+     * failed to deserialise resource {0}
+     *      
+     * @message com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.unpackType
+     * Unknown recovery type {0}
+     */
+    public void unpack(final InputObjectState is)
+        throws IOException
+    {
+        XidImple.unpack(is) ;
+        final int recoveryType = is.unpackInt() ;
+        switch(recoveryType)
+        {
+            case RecoverableXAConnection.AUTO_RECOVERY:
+                final String recoverableXAConnectionClassName = is.unpackString() ;
+                final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader() ;
+                final Class recoverableXAConnectionClass ;
+                try
+                {
+                    recoverableXAConnectionClass = contextClassLoader.loadClass(recoverableXAConnectionClassName) ;
+                }
+                catch (final ClassNotFoundException cnfe)
+                {
+                    throw generateUnpackError(cnfe) ;
+                }
+    
+                try
+                {
+                    recoverableXAConnection = (RecoverableXAConnection)recoverableXAConnectionClass.newInstance() ;
+                }
+                catch (final InstantiationException ie)
+                {
+                    throw generateUnpackError(ie) ;
+                }
+                catch (final IllegalAccessException iae)
+                {
+                    throw generateUnpackError(iae) ;
+                }
+                
+                recoverableXAConnection.unpackFrom(is) ;
+                try
+                {
+                    xaResource = recoverableXAConnection.getResource() ;
+                }
+                catch (final SQLException sqle)
+                {
+                    throw generateUnpackError(sqle) ;
+                }
+                break ;
+            case RecoverableXAConnection.OBJECT_RECOVERY:
+                final byte[] data = is.unpackBytes() ;
+                try
+                {
+                    final ByteArrayInputStream bais = new ByteArrayInputStream(data) ;
+                    final ObjectInputStream ois = new ObjectInputStream(bais) ;
+                    xaResource = (XAResource)ois.readObject() ;
+                }
+                catch (final ClassNotFoundException cnfe)
+                {
+                    throw generateUnpackError(cnfe) ;
+                }
+                catch (final IOException ioe)
+                {
+                    throw generateUnpackError(ioe) ;
+                }
+                catch (final ClassCastException cce)
+                {
+                    throw generateUnpackError(cce) ;
+                }
+                break ;
+            default:
+                final String message = "XAOnePhaseResource.unpack() " +
+                jtaLogger.loggerI18N.getString("com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.unpackType",
+                    new Object[] {new Integer(recoveryType)}) ;
+                if (jtaLogger.logger.isWarnEnabled())
+                {
+                    jtaLogger.logger.warn(message);
+                }
+                throw new IOException(message) ;
+        }
+    }
+    
+    /**
+     * Generate the IOException for the corresponding unpack exception.
+     * @param ex The exception caught in unpack.
+     * @return The corresponding IOException to be thrown.
+     */
+    private static IOException generateUnpackError(final Exception ex)
+    {
+        final String message = "XAOnePhaseResource.unpack() " +
+            jtaLogger.loggerI18N.getString("com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.unpack", new Object[] {ex}) ;
+        if (jtaLogger.logger.isWarnEnabled())
+        {
+            jtaLogger.logger.warn(message);
+        }
+        return new IOException(message) ;
+    }
+}


Property changes on: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAOnePhaseResource.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -35,16 +35,20 @@
 import com.arjuna.ats.internal.jta.utils.*;
 import com.arjuna.ats.internal.jta.utils.arjunacore.StatusConverter;
 import com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple;
+import com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource;
 import com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord;
 
 import com.arjuna.ats.jta.common.Configuration;
 import com.arjuna.ats.jta.common.Environment;
 import com.arjuna.ats.jta.common.jtaPropertyManager;
+import com.arjuna.ats.jta.resources.LastResourceCommitOptimisation;
 import com.arjuna.ats.jta.utils.XAHelper;
 import com.arjuna.ats.jta.xa.XidImple;
 import com.arjuna.ats.jta.logging.*;
 import com.arjuna.ats.jta.xa.XAModifier;
 
+import com.arjuna.ats.arjuna.LastResourceRecord;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
 import com.arjuna.ats.arjuna.coordinator.ActionStatus;
 import com.arjuna.ats.arjuna.coordinator.BasicAction;
 import com.arjuna.ats.arjuna.coordinator.AddOutcome;
@@ -78,6 +82,9 @@
  * @message com.arjuna.ats.internal.jta.transaction.arjunacore.notatomicaction
  *          [com.arjuna.ats.internal.jta.transaction.arjunacore.notatomicaction]
  *          Current transaction is not an AtomicAction!
+ * @message com.arjuna.ats.internal.jta.transaction.arjunacore.lastResourceOptimisationInterface
+ * 			[com.arjuna.ats.internal.jta.transaction.arjunacore.lastResourceOptimisationInterface] - failed
+ *          to load Last Resource Optimisation Interface
  */
 
 public class TransactionImple implements javax.transaction.Transaction,
@@ -761,10 +768,18 @@
 			 * gotten this far!
 			 */
 
-			XAResourceRecord res = new XAResourceRecord(this, xaRes, xid,
-					params);
+			final AbstractRecord record ;
+            if ((xaRes instanceof LastResourceCommitOptimisation) ||
+                ((LAST_RESOURCE_OPTIMISATION_INTERFACE != null) && LAST_RESOURCE_OPTIMISATION_INTERFACE.isInstance(xaRes)))
+			{
+				record = new LastResourceRecord(new XAOnePhaseResource(xaRes, xid, params)) ;
+			}
+			else
+			{
+				record = new XAResourceRecord(this, xaRes, xid, params);
+			}
 
-			if (_theTransaction.add(res) != AddOutcome.AR_ADDED)
+			if (_theTransaction.add(record) != AddOutcome.AR_ADDED)
 			{
 				markRollbackOnly();
 
@@ -1567,6 +1582,7 @@
 	private final boolean _xaTransactionTimeoutEnabled ;
 
 	private static final boolean XA_TRANSACTION_TIMEOUT_ENABLED ;
+	private static final Class LAST_RESOURCE_OPTIMISATION_INTERFACE ;
 
 	static
 	{
@@ -1579,6 +1595,24 @@
 		{
 			XA_TRANSACTION_TIMEOUT_ENABLED = true ;
 		}
+		final String lastResourceOptimisationInterfaceName = jtaPropertyManager.propertyManager.getProperty(Environment.LAST_RESOURCE_OPTIMISATION_INTERFACE) ;
+		Class lastResourceOptimisationInterface = null ;
+		if (lastResourceOptimisationInterfaceName != null)
+		{
+			try
+			{
+				lastResourceOptimisationInterface = Thread.currentThread().getContextClassLoader().loadClass(lastResourceOptimisationInterfaceName) ;
+			}
+			catch (final Throwable th)
+			{
+				if (jtaLogger.loggerI18N.isWarnEnabled())
+				{
+					jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.arjunacore.lastResourceOptimisationInterface",
+						new Object[] {lastResourceOptimisationInterfaceName}, th);
+				}
+			}
+		}
+		LAST_RESOURCE_OPTIMISATION_INTERFACE = lastResourceOptimisationInterface ;
 	}
 
 	private static Hashtable _transactions = new Hashtable();

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	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/common/Environment.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -55,6 +55,7 @@
 
     public static final String XA_ERROR_HANDLER = "com.arjuna.ats.jta.xaErrorHandler";
     public static final String XA_TRANSACTION_TIMEOUT_ENABLED = "com.arjuna.ats.jta.xaTransactionTimeoutEnabled";
+    public static final String LAST_RESOURCE_OPTIMISATION_INTERFACE = "com.arjuna.ats.jta.lastResourceOptimisationInterface";
 
 }
 

Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/resources/LastResourceCommitOptimisation.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/resources/LastResourceCommitOptimisation.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/resources/LastResourceCommitOptimisation.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -0,0 +1,26 @@
+/*
+*
+ * Copyright (C) 2005
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id$
+ */
+
+package com.arjuna.ats.jta.resources;
+
+import javax.transaction.xa.XAResource;
+
+/**
+ * Marker interface for Last Resource Commit Optimisation.
+ * 
+ * @author Kevin Conner (Kevin.Conner at arjuna.com)
+ * @version $Id$
+ * @since ATS 4.1
+ */
+public interface LastResourceCommitOptimisation extends XAResource
+{
+}


Property changes on: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/resources/LastResourceCommitOptimisation.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource/LastOnePhaseResource.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource/LastOnePhaseResource.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource/LastOnePhaseResource.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -0,0 +1,91 @@
+package com.hp.mwtests.ts.jta.lastresource;
+
+import java.io.Serializable;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import com.arjuna.ats.jta.resources.LastResourceCommitOptimisation;
+
+public class LastOnePhaseResource implements XAResource, Serializable, LastResourceCommitOptimisation
+{
+    private static final long serialVersionUID = -2677829642809706893L ;
+    
+    public static final int INITIAL = 0 ;
+    public static final int COMMIT = 1 ;
+    public static final int ROLLBACK = 2 ;
+    
+    private int status = INITIAL ;
+    
+    public int prepare(final Xid xid)
+        throws XAException
+    {
+        throw new XAException("Prepare called on LastOnePhaseResource") ;
+    }
+    
+    public void commit(final Xid xid, final boolean onePhaseCommit)
+        throws XAException
+    {
+        if (!onePhaseCommit)
+        {
+            throw new XAException("commit called with onePhaseCommit false") ;
+        }
+        status = COMMIT ;
+    }
+
+    public void rollback(final Xid xid)
+        throws XAException
+    {
+        status = ROLLBACK ;
+    }
+    
+    public int getStatus()
+    {
+        return status ;
+    }
+
+    public boolean isSameRM(final XAResource xaResource)
+        throws XAException
+    {
+        return this.equals(xaResource) ;
+    }
+
+    public void start(final Xid xid, final int flags)
+        throws XAException
+    {
+        System.out.println("start called on LastOnePhaseResource for xid: " + xid + " with flags 0x" + Integer.toHexString(flags)) ;
+    }
+
+    public void end(final Xid xid, final int flags)
+        throws XAException
+    {
+        System.out.println("end called on LastOnePhaseResource for xid: " + xid + " with flags 0x" + Integer.toHexString(flags)) ;
+    }
+
+    public Xid[] recover(final int flags)
+        throws XAException
+    {
+        System.out.println("recover called on LastOnePhaseResource with flags 0x" + Integer.toHexString(flags)) ;
+        return null ;
+    }
+
+    public void forget(final Xid xid)
+        throws XAException
+    {
+        System.out.println("forget called on LastOnePhaseResource for xid: " + xid) ;
+    }
+
+    public boolean setTransactionTimeout(final int timeout)
+        throws XAException
+    {
+        // don't support it
+        return false ;
+    }
+
+    public int getTransactionTimeout()
+        throws XAException
+    {
+        return 60 ;
+    }
+}


Property changes on: labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/lastresource/LastOnePhaseResource.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/LastResourceRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/LastResourceRecord.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/LastResourceRecord.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2005
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id$
+ */
+package com.arjuna.ats.internal.jta.resources.jts.orbspecific;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
+import org.omg.CosTransactions.HeuristicHazard;
+import org.omg.CosTransactions.HeuristicMixed;
+import org.omg.CosTransactions.HeuristicRollback;
+import org.omg.CosTransactions.NotPrepared;
+import org.omg.CosTransactions.Vote;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.RecordType;
+import com.arjuna.ats.internal.jta.transaction.jts.TransactionImple;
+
+/**
+ * XAResourceRecord implementing the Last Resource Commit Optimisation.
+ * 
+ * @author Kevin Conner (Kevin.Conner at arjuna.com)
+ * @version $Id$
+ * @since ATS 4.1
+ */
+public class LastResourceRecord extends XAResourceRecord
+{
+    /**
+     * The Uid for all last xa resource records.
+     */
+    private static final String UID = Uid.maxUid().stringForm() ;
+    
+    /**
+     * Construct the record for last resource commit optimisation. 
+     * @param tx The current transaction.
+     * @param xaResource The associated XA resource.
+     * @param xid The X/Open transaction identifier.
+     * @param params Additional parameters.
+     */
+    public LastResourceRecord(final TransactionImple tx, final XAResource xaResource, final Xid xid, final Object[] params)
+    {
+        super(tx, xaResource, xid, params) ;
+    }
+    
+    /**
+     * The type id for this record.
+     */
+    public int type_id()
+        throws SystemException
+    {
+        return RecordType.LASTRESOURCE ;
+    }
+    
+    /**
+     * The UID for this resource.
+     */
+    public String uid()
+        throws SystemException
+    {
+        return UID ;
+    }
+    
+    /**
+     * Commit this resource.
+     */
+    public void commit()
+        throws SystemException, NotPrepared, HeuristicRollback, HeuristicMixed, HeuristicHazard
+    {
+    }
+    
+    /**
+     * Prepare this resource.
+     */
+    public Vote prepare()
+        throws HeuristicMixed, HeuristicHazard, SystemException
+    {
+    	try
+    	{
+	        commit_one_phase() ;
+	        return Vote.VoteCommit ;
+    	}
+    	catch (final TRANSACTION_ROLLEDBACK tr)
+    	{
+    		return Vote.VoteRollback ;
+    	}
+    }
+    
+    /**
+     * The type for saving state.
+     */
+    public String type()
+    {
+        return "/CosTransactions/LastXAResourceRecord" ;
+    }
+
+	public boolean saveRecord() throws SystemException
+	{
+		return true;
+	}
+}


Property changes on: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/resources/jts/orbspecific/LastResourceRecord.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java	2006-09-25 09:42:28 UTC (rev 6408)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java	2006-09-25 09:56:45 UTC (rev 6409)
@@ -35,14 +35,17 @@
 import com.arjuna.ats.internal.jta.utils.jts.StatusConverter;
 import com.arjuna.ats.internal.jta.resources.jts.CleanupSynchronization;
 import com.arjuna.ats.internal.jta.resources.jts.LocalCleanupSynchronization;
+import com.arjuna.ats.internal.jta.resources.jts.orbspecific.LastResourceRecord;
 import com.arjuna.ats.internal.jta.resources.jts.orbspecific.SynchronizationImple;
 import com.arjuna.ats.internal.jta.resources.jts.orbspecific.XAResourceRecord;
 
+import com.arjuna.ats.jta.resources.LastResourceCommitOptimisation;
 import com.arjuna.ats.jta.utils.XAHelper;
 
 import org.omg.CosTransactions.*;
 
 import com.arjuna.ats.arjuna.coordinator.BasicAction;
+import com.arjuna.ats.arjuna.coordinator.OnePhaseResource;
 import com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator;
 
 import com.arjuna.ats.jta.xa.*;
@@ -105,6 +108,9 @@
  * @message com.arjuna.ats.internal.jta.transaction.jts.syncproblem
  *          [com.arjuna.ats.internal.jta.transaction.jts.syncproble] - cleanup
  *          synchronization failed to register:
+ * @message com.arjuna.ats.internal.jta.transaction.jts.lastResourceOptimisationInterface
+ * 			[com.arjuna.ats.internal.jta.transaction.jts.lastResourceOptimisationInterface] - failed
+ *          to load Last Resource Optimisation Interface
  */
 
 public class TransactionImple implements javax.transaction.Transaction,
@@ -819,8 +825,18 @@
 			 * gotten this far!
 			 */
 
-			XAResourceRecord res = new XAResourceRecord(this, xaRes, xid,
-					params);
+			final XAResourceRecord res ;
+            if ((xaRes instanceof LastResourceCommitOptimisation) ||
+                ((LAST_RESOURCE_OPTIMISATION_INTERFACE != null) && LAST_RESOURCE_OPTIMISATION_INTERFACE.isInstance(xaRes)))
+            {
+                res = new LastResourceRecord(this, xaRes, xid,
+                        params) ;
+            }
+            else
+            {
+                res = new XAResourceRecord(this, xaRes, xid,
+                        params);
+            }
 
 			RecoveryCoordinator recCoord = _theTransaction.registerResource(res.getResource());
 
@@ -829,8 +845,6 @@
 
 			res.setRecoveryCoordinator(recCoord);
 
-			res = null;
-
 			return true;
 		}
 		catch (Exception e)
@@ -1669,6 +1683,7 @@
 	private final boolean _xaTransactionTimeoutEnabled ;
 
 	private static final boolean XA_TRANSACTION_TIMEOUT_ENABLED ;
+	private static final Class LAST_RESOURCE_OPTIMISATION_INTERFACE ;
 
 	static
 	{
@@ -1681,6 +1696,24 @@
 		{
 			XA_TRANSACTION_TIMEOUT_ENABLED = true ;
 		}
+		final String lastResourceOptimisationInterfaceName = jtsPropertyManager.propertyManager.getProperty(Environment.LAST_RESOURCE_OPTIMISATION_INTERFACE) ;
+		Class lastResourceOptimisationInterface = null ;
+		if (lastResourceOptimisationInterfaceName != null)
+		{
+			try
+			{
+				lastResourceOptimisationInterface = Thread.currentThread().getContextClassLoader().loadClass(lastResourceOptimisationInterfaceName) ;
+			}
+			catch (final Throwable th)
+			{
+				if (jtaLogger.loggerI18N.isWarnEnabled())
+				{
+					jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.jts.lastResourceOptimisationInterface",
+						new Object[] {lastResourceOptimisationInterfaceName}, th);
+				}
+			}
+		}
+		LAST_RESOURCE_OPTIMISATION_INTERFACE = lastResourceOptimisationInterface ;
 	}
 	
 	private static Hashtable _transactions = new Hashtable();




More information about the jboss-svn-commits mailing list