User: osh
Date: 01/02/09 10:56:19
Modified: src/main/org/jboss/tm TransactionImpl.java
TransactionManagerService.java
TransactionPropagationContextFactory.java
TxCapsule.java TxManager.java XidImpl.java
Log:
Changed tx export/propagation/import in preparation to JTA independence.
Revision Changes Path
1.13 +53 -76 jboss/src/main/org/jboss/tm/TransactionImpl.java
Index: TransactionImpl.java
===================================================================
RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/TransactionImpl.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- TransactionImpl.java 2001/01/24 05:59:56 1.12
+++ TransactionImpl.java 2001/02/09 18:56:17 1.13
@@ -25,34 +25,28 @@
import javax.transaction.xa.XAException;
/**
- * A light weight transaction.
+ * A light weight transaction frontend to a TxCapsule.
*
- * It is the public face of the TxCapsule.
- * Many of these "transactions" can coexist representing the TxCap.
- * Access to the underlying txCap is done through the TransactionManager.
- *
* @see TxCapsule
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
- * @version $Revision: 1.12 $
+ * @version $Revision: 1.13 $
*/
-public class TransactionImpl
- implements Transaction, Serializable
+class TransactionImpl
+ implements Transaction
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
- Xid xid; // Transaction ID.
-
// Constructors --------------------------------------------------
TransactionImpl(TxCapsule txCapsule, Xid xid)
{
this.txCapsule = txCapsule;
this.xid = xid;
- travelled = false;
+ globalId = new GlobalId(xid);
}
// Public --------------------------------------------------------
@@ -61,6 +55,14 @@
// termination. The travelled flag is not checked, as we assume that the
// transaction has already been imported.
+ // When the transaction is done, instance variable txCapsule is set
+ // to null, and this is used as an indicator that the methods here
+ // should throw an exception.
+ // To avoid too much optimization, txCapsule is declared volatile.
+ // The NPE catches below are meant to catch a null txCapsule. It is
+ // possible that the NPE might come from the method call, but that
+ // would be an error in TxCapsule.
+
public void commit()
throws RollbackException,
HeuristicMixedException,
@@ -69,11 +71,10 @@
java.lang.IllegalStateException,
SystemException
{
- synchronized (this) {
- if (done)
- throw new IllegalStateException("No transaction.");
-
- txCapsule.commit();
+ try {
+ txCapsule.commit();
+ } catch (NullPointerException ex) {
+ throw new IllegalStateException("No transaction.");
}
}
@@ -82,11 +83,10 @@
java.lang.SecurityException,
SystemException
{
- synchronized (this) {
- if (done)
- throw new IllegalStateException("No transaction.");
-
+ try {
txCapsule.rollback();
+ } catch (NullPointerException ex) {
+ throw new IllegalStateException("No transaction.");
}
}
@@ -94,11 +94,10 @@
throws java.lang.IllegalStateException,
SystemException
{
- synchronized (this) {
- if (done)
- throw new IllegalStateException("No transaction.");
-
+ try {
return txCapsule.delistResource(xaRes, flag);
+ } catch (NullPointerException ex) {
+ throw new IllegalStateException("No transaction.");
}
}
@@ -107,22 +106,20 @@
java.lang.IllegalStateException,
SystemException
{
- synchronized (this) {
- if (done)
- throw new IllegalStateException("No transaction.");
-
+ try {
return txCapsule.enlistResource(xaRes);
+ } catch (NullPointerException ex) {
+ throw new IllegalStateException("No transaction.");
}
}
public int getStatus()
throws SystemException
{
- synchronized (this) {
- if (done)
- return Status.STATUS_NO_TRANSACTION;
-
+ try {
return txCapsule.getStatus();
+ } catch (NullPointerException ex) {
+ return Status.STATUS_NO_TRANSACTION;
}
}
@@ -131,11 +128,10 @@
java.lang.IllegalStateException,
SystemException
{
- synchronized (this) {
- if (done)
- throw new IllegalStateException("No transaction.");
-
+ try {
txCapsule.registerSynchronization(s);
+ } catch (NullPointerException ex) {
+ throw new IllegalStateException("No transaction.");
}
}
@@ -143,11 +139,10 @@
throws java.lang.IllegalStateException,
SystemException
{
- synchronized (this) {
- if (done)
- throw new IllegalStateException("No transaction.");
-
+ try {
txCapsule.setRollbackOnly();
+ } catch (NullPointerException ex) {
+ throw new IllegalStateException("No transaction.");
}
}
@@ -170,21 +165,8 @@
// Package protected ---------------------------------------------
- /**
- * Setter for property txCapsule.
- *
- * This is needed when a propagated transaction is imported into the
- * current transaction manager.
- */
- synchronized void setTxCapsule(TxCapsule txCapsule)
- {
- if (done)
- // Shouldn't happen.
- throw new IllegalStateException("Transaction " + toString() +
- " is done.");
- this.txCapsule = txCapsule;
- travelled = false;
- }
+ /** The ID of this transaction. */
+ Xid xid;
/**
* Setter for property done.
@@ -193,8 +175,8 @@
*/
synchronized void setDone()
{
- done = true;
txCapsule = null;
+ TxManager.getInstance().releaseTransactionImpl(this);
}
/**
@@ -202,36 +184,31 @@
*/
boolean isDone()
{
- return done;
+ return txCapsule == null;
}
/**
- * Returns true iff this transaction needs to be imported into the
- * local transaction manager.
+ * Return the global id of this transaction.
*/
- boolean importNeeded()
+ GlobalId getGlobalId()
{
- return !done && travelled;
+ return globalId;
}
// Private -------------------------------------------------------
- private transient TxCapsule txCapsule; // The real implementation.
- private boolean done; // Flags that the transaction has terminated.
- transient boolean travelled; // Flags that the transaction has travelled.
-
- private void writeObject(java.io.ObjectOutputStream stream)
- throws java.io.IOException
- {
- stream.defaultWriteObject();
- }
+ /**
+ * The backend of this transaction.
+ * Null iff this transaction is done.
+ */
+ private volatile TxCapsule txCapsule;
- private void readObject(java.io.ObjectInputStream stream)
- throws java.io.IOException, ClassNotFoundException
- {
- stream.defaultReadObject();
- travelled = true;
- }
+ /**
+ * The global ID of this transaction.
+ * This is used as a transaction propagation context, and in the
+ * TxManager for mapping transaction IDs to transactions.
+ */
+ private GlobalId globalId;
// Inner classes -------------------------------------------------
}
1.7 +57 -35 jboss/src/main/org/jboss/tm/TransactionManagerService.java
Index: TransactionManagerService.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/tm/TransactionManagerService.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TransactionManagerService.java 2001/01/24 05:59:56 1.6
+++ TransactionManagerService.java 2001/02/09 18:56:17 1.7
@@ -31,12 +31,13 @@
import org.jboss.util.ServiceMBeanSupport;
/**
- * This is a JMX service which manages the TransactionManager.
- * The service creates it and binds a Reference to it into JNDI.
+ * This is a JMX service which manages the TransactionManager.
+ * The service creates it and binds a Reference to it into JNDI.
*
- * @see TxManager
- * @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.6 $
+ * @see TxManager
+ * @author Rickard �berg ([EMAIL PROTECTED])
+ * @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
+ * @version $Revision: 1.7 $
*/
public class TransactionManagerService
extends ServiceMBeanSupport
@@ -44,53 +45,64 @@
{
// Constants -----------------------------------------------------
public static String JNDI_NAME = "java:/TransactionManager";
+ public static String JNDI_IMPORTER =
"java:/TransactionPropagationContextExporter";
+ public static String JNDI_EXPORTER =
"java:/TransactionPropagationContextImporter";
// Attributes ----------------------------------------------------
- MBeanServer server;
+
+ MBeanServer server;
- int timeout;
+ int timeout;
// Static --------------------------------------------------------
+
static TxManager tm;
// ServiceMBeanSupport overrides ---------------------------------
+
public String getName()
{
return "Transaction manager";
- }
+ }
protected ObjectName getObjectName(MBeanServer server, ObjectName name)
throws javax.management.MalformedObjectNameException
{
- this.server = server;
+ this.server = server;
return new ObjectName(OBJECT_NAME);
}
protected void startService()
throws Exception
{
- // Get a reference to the TxManager singleton.
- tm = TxManager.getInstance();
+ // Get a reference to the TxManager singleton.
+ tm = TxManager.getInstance();
- // Set timeout
- tm.setTransactionTimeout(timeout);
+ // Set timeout
+ tm.setTransactionTimeout(timeout);
- // Bind reference to TM in JNDI
- // TODO: Move this to start when relationships are in place
- Reference ref = new Reference(tm.getClass().toString(),
getClass().getName(), null);
- new InitialContext().bind(JNDI_NAME, ref);
+ // Bind reference to TM in JNDI
+ // Our TM also implement the tx importer and exporter
+ // interfaces, so we bind it under those names too.
+ // Other transaction managers may have seperate
+ // implementations of these objects, so they are
+ // accessed under seperate names.
+ bindRef(JNDI_NAME, "org.jboss.tm.TxManager");
+ bindRef(JNDI_IMPORTER, "org.jboss.tm.TransactionPropagationContextImporter");
+ bindRef(JNDI_EXPORTER, "org.jboss.tm.TransactionPropagationContextFactory");
}
protected void stopService()
{
- try
- {
- // Remove TM from JNDI
- new InitialContext().unbind(JNDI_NAME);
- } catch (Exception e)
- {
- log.exception(e);
- }
+ try {
+ // Remove TM, importer and exporter from JNDI
+ Context ctx = new InitialContext();
+ ctx.unbind(JNDI_NAME);
+ ctx.unbind(JNDI_IMPORTER);
+ ctx.unbind(JNDI_EXPORTER);
+ } catch (Exception e) {
+ log.exception(e);
+ }
}
public int getTransactionTimeout() {
@@ -101,15 +113,25 @@
this.timeout = timeout;
}
- // ObjectFactory implementation ----------------------------------
- public Object getObjectInstance(Object obj,
- Name name,
- Context nameCtx,
- Hashtable environment)
- throws Exception
- {
- // Return the transaction manager
- return tm;
- }
+
+ // ObjectFactory implementation ----------------------------------
+
+ public Object getObjectInstance(Object obj, Name name,
+ Context nameCtx, Hashtable environment)
+ throws Exception
+ {
+ // Return the transaction manager
+ return tm;
+ }
+
+
+ // Private -------------------------------------------------------
+
+ private void bindRef(String jndiName, String className)
+ throws Exception
+ {
+ Reference ref = new Reference(className, getClass().getName(), null);
+ new InitialContext().bind(jndiName, ref);
+ }
}
1.2 +15 -4
jboss/src/main/org/jboss/tm/TransactionPropagationContextFactory.java
Index: TransactionPropagationContextFactory.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/tm/TransactionPropagationContextFactory.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TransactionPropagationContextFactory.java 2001/01/24 06:07:00 1.1
+++ TransactionPropagationContextFactory.java 2001/02/09 18:56:17 1.2
@@ -6,7 +6,9 @@
*/
package org.jboss.tm;
+import javax.transaction.Transaction;
+
/**
* Implementations of this interface are used for getting
* a transaction propagation context at the client-side.
@@ -15,10 +17,13 @@
* we may have 20 new classes if we are going to interoperate
* with 20 different kinds of distributed transaction
* managers.)
+ * The reason for having the methods in this interface return
+ * Object is that we do not really know what kind of transaction
+ * propagation context is returned.
*
- * @see TransactionImpl
+ * @see TransactionPropagationContextImporter
* @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
*/
public interface TransactionPropagationContextFactory
{
@@ -26,9 +31,15 @@
* Return a transaction propagation context for the transaction
* currently associated with the invoking thread, or <code>null</code>
* if the invoking thread is not associated with a transaction.
- * The reason for having this method return Object is that we do not
- * really know what kind of transaction propagation context we get.
*/
public Object getTransactionPropagationContext();
+
+ /**
+ * Return a transaction propagation context for the transaction
+ * given as an argument, or <code>null</code>
+ * if the argument is <code>null</code> or of a type unknown to
+ * this factory.
+ */
+ public Object getTransactionPropagationContext(Transaction tx);
}
1.24 +69 -66 jboss/src/main/org/jboss/tm/TxCapsule.java
Index: TxCapsule.java
===================================================================
RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/TxCapsule.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- TxCapsule.java 2001/01/27 22:17:36 1.23
+++ TxCapsule.java 2001/02/09 18:56:17 1.24
@@ -6,9 +6,12 @@
*/
package org.jboss.tm;
+import java.lang.ref.SoftReference;
+
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.Set;
import java.util.HashSet;
import java.util.HashMap;
@@ -45,7 +48,7 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
*
- * @version $Revision: 1.23 $
+ * @version $Revision: 1.24 $
*/
class TxCapsule implements TimeoutTarget
{
@@ -86,16 +89,57 @@
}
}
+
+ /**
+ * This collection contains the inactive txCapsules.
+ * We keep these for reuse.
+ * They are referenced through soft references so that they will
+ * be garbage collected if the VM runs low on memory.
+ */
+ static private LinkedList inactiveCapsules = new LinkedList();
+
+ /**
+ * Get a new instance.
+ *
+ * @param timeout The timeout for this transaction in milliseconds.
+ */
+ static TxCapsule getInstance(long timeOut)
+ {
+ TxCapsule txCapsule = null;
+ synchronized (inactiveCapsules) {
+ while (inactiveCapsules.size() > 0) {
+ SoftReference ref = (SoftReference)inactiveCapsules.removeFirst();
+ txCapsule = (TxCapsule)ref.get();
+ if (txCapsule != null)
+ break;
+ }
+ }
+ if (txCapsule == null)
+ txCapsule = new TxCapsule(timeOut);
+ else
+ txCapsule.reUse(timeOut);
+
+ return txCapsule;
+ }
+
+ /**
+ * Release an instance for reuse.
+ */
+ static private void releaseInstance(TxCapsule txCapsule)
+ {
+ synchronized (inactiveCapsules) {
+ inactiveCapsules.add(new SoftReference(txCapsule));
+ }
+ }
+
// Constructors --------------------------------------------------
/**
* Create a new TxCapsule.
*
- * @param tm The transaction manager for this transaction.
- * @param timeout The timeout for this transaction in milliseconds
- * (timeouts are not yet implemented).
+ * @param timeout The timeout for this transaction in milliseconds.
*/
- TxCapsule(TxManager tm, long timeout)
+ private TxCapsule(long timeout)
{
xid = new XidImpl();
@@ -106,7 +150,7 @@
xidConstructorArgs[0] = new Integer(xid.getFormatId());
}
- this.tm = tm;
+ transaction = new TransactionImpl(this, xid);
status = Status.STATUS_ACTIVE;
@@ -118,20 +162,9 @@
}
/**
- * Create a new front for this transaction.
- */
- TransactionImpl createTransactionImpl()
- {
- TransactionImpl tx = new TransactionImpl(this, xid);
- addTransaction(tx);
-
- return tx;
- }
-
- /**
* Prepare this instance for reuse.
*/
- void reUse(long timeout)
+ private void reUse(long timeout)
{
if (!done)
throw new IllegalStateException();
@@ -142,6 +175,8 @@
xid = new XidImpl();
lastBranchId = 0; // BQIDs start over again in scope of the new GID.
+ transaction = new TransactionImpl(this, xid);
+
status = Status.STATUS_ACTIVE;
heuristicCode = HEUR_NONE;
@@ -218,22 +253,16 @@
return XidImpl.toString(xid);
}
- // Package protected ---------------------------------------------
-
/**
- * Import a transaction encapsulated here.
+ * Return the front for this transaction.
*/
- void importTransaction(TransactionImpl tx) {
- try {
- lock();
-
- tx.setTxCapsule(this);
- addTransaction(tx);
- } finally {
- unlock();
- }
+ TransactionImpl getTransactionImpl()
+ {
+ return transaction;
}
+ // Package protected ---------------------------------------------
+
/**
* Commit the transaction encapsulated here.
* Should not be called directly, use <code>TxManager.commit()</code>
@@ -688,20 +717,10 @@
// Private -------------------------------------------------------
/**
- * The public faces of this capsule are JTA Transaction implementations.
+ * The public face of this capsule is a JTA Transaction implementation.
*/
- private TransactionImpl[] transactions = new TransactionImpl[1];
+ private TransactionImpl transaction;
- /**
- * Size of allocated transaction frontend array.
- */
- private int transactionAllocSize = 1;
-
- /**
- * Count of transaction frontends for this transaction.
- */
- private int transactionCount = 0;
-
/**
* The synchronizations to call back.
@@ -811,8 +830,8 @@
/**
* The transaction manager for this transaction.
+ private static TxManager tm = TxManager.getInstance();
*/
- private TxManager tm;
/**
* Mutex for thread-safety. This should only be changed in the
@@ -1043,22 +1062,6 @@
}
/**
- * Add a transaction frontend, expanding the table if needed.
- */
- private void addTransaction(TransactionImpl tx)
- {
- if (transactionCount == transactionAllocSize) {
- // expand table
- transactionAllocSize = 2 * transactionAllocSize;
-
- TransactionImpl[] tr = new TransactionImpl[transactionAllocSize];
- System.arraycopy(transactions, 0, tr, 0, transactionCount);
- transactions = tr;
- }
- transactions[transactionCount++] = tx;
- }
-
- /**
* Call <code>start()</code> on a XAResource and update
* internal state information.
* This will release the lock while calling out.
@@ -1346,9 +1349,8 @@
*/
private void instanceDone()
{
- // Notify transaction fronts that we are done.
- for (int i = 0; i < transactionCount; ++i)
- transactions[i].setDone();
+ // Notify transaction frontend that we are done.
+ transaction.setDone();
synchronized (this) {
// Done with this incarnation.
@@ -1367,9 +1369,10 @@
sync[i] = null; // release for GC
syncCount = 0;
- for (int i = 0; i < transactionCount; ++i)
- transactions[i] = null; // release for GC
- transactionCount = 0;
+ //for (int i = 0; i < transactionCount; ++i)
+ // transactions[i] = null; // release for GC
+ //transactionCount = 0;
+ transaction = null; // release for GC
for (int i = 0; i < resourceCount; ++i) {
resources[i] = null; // release for GC
@@ -1382,7 +1385,7 @@
xidConstructorArgs[1] = null; // This now needs initializing
// This instance is now ready for reuse (when we release the lock).
- tm.releaseTxCapsule(this, xid);
+ releaseInstance(this);
}
/**
1.27 +101 -120 jboss/src/main/org/jboss/tm/TxManager.java
Index: TxManager.java
===================================================================
RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/TxManager.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- TxManager.java 2001/01/24 05:59:56 1.26
+++ TxManager.java 2001/02/09 18:56:18 1.27
@@ -8,8 +8,6 @@
import java.lang.ref.SoftReference;
-import java.util.Hashtable;
-import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
@@ -38,10 +36,12 @@
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
- * @version $Revision: 1.26 $
+ * @version $Revision: 1.27 $
*/
public class TxManager
-implements TransactionManager
+ implements TransactionManager,
+ TransactionPropagationContextImporter,
+ TransactionPropagationContextFactory
{
// Constants -----------------------------------------------------
@@ -63,7 +63,7 @@
/**
* Get a reference to the singleton instance.
*/
- static TxManager getInstance()
+ public static TxManager getInstance()
{
return singleton;
}
@@ -80,34 +80,24 @@
// Public --------------------------------------------------------
+ /**
+ * Begin a new transaction.
+ * The new transaction will be associated with the calling thread.
+ */
public void begin()
throws NotSupportedException,
SystemException
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
- if (current != null &&
- (!(current instanceof TransactionImpl) ||
- !((TransactionImpl)current).isDone()))
+ if (current != null && !current.isDone())
throw new NotSupportedException("Transaction already active, " +
"cannot nest transactions.");
- TxCapsule txCapsule = null;
- synchronized (inactiveCapsules) {
- while (inactiveCapsules.size() > 0) {
- SoftReference ref = (SoftReference)inactiveCapsules.removeFirst();
- txCapsule = (TxCapsule)ref.get();
- if (txCapsule != null)
- break;
- }
- }
- if (txCapsule == null)
- txCapsule = new TxCapsule(this, timeOut);
- else
- txCapsule.reUse(timeOut);
- TransactionImpl tx = txCapsule.createTransactionImpl();
+ TxCapsule txCapsule = TxCapsule.getInstance(timeOut);
+ TransactionImpl tx = txCapsule.getTransactionImpl();
threadTx.set(tx);
- activeCapsules.put(tx.xid, txCapsule);
+ globalIdTx.put(tx.getGlobalId(), tx);
}
/**
@@ -118,10 +108,10 @@
HeuristicMixedException,
HeuristicRollbackException,
java.lang.SecurityException,
- java.lang.IllegalStateException,
+ IllegalStateException,
SystemException
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
if (current != null) {
current.commit();
@@ -138,7 +128,7 @@
public int getStatus()
throws SystemException
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
if (current != null)
return current.getStatus();
@@ -153,46 +143,68 @@
public Transaction getTransaction()
throws SystemException
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
- if (current != null && current instanceof TransactionImpl &&
- ((TransactionImpl)current).isDone()) {
+ if (current != null && current.isDone()) {
threadTx.set(null);
return null;
}
return current;
}
- public void resume(Transaction tobj)
+ /**
+ * Resume a transaction.
+ *
+ * Note: This will not enlist any resources involved in this
+ * transaction. According to JTA1.0.1 specification section 3.2.3,
+ * that is the responsibility of the application server.
+ */
+ public void resume(Transaction transaction)
throws InvalidTransactionException,
- java.lang.IllegalStateException,
+ IllegalStateException,
SystemException
{
- //Useless
+ if (transaction != null && !(transaction instanceof TransactionImpl))
+ throw new RuntimeException("Not a TransactionImpl, but a " +
+ transaction.getClass().getName() + ".");
+
+ TransactionImpl current = (TransactionImpl)threadTx.get();
- //throw new Exception("txMan.resume() NYI");
+ if (current != null)
+ throw new IllegalStateException("Already associated with a tx");
+
+ if (current != transaction)
+ threadTx.set(transaction);
}
+ /**
+ * Suspend the transaction currently associated with the current
+ * thread, and return it.
+ *
+ * Note: This will not delist any resources involved in this
+ * transaction. According to JTA1.0.1 specification section 3.2.3,
+ * that is the responsibility of the application server.
+ */
public Transaction suspend()
throws SystemException
{
- // Logger.log("suspend tx");
+ TransactionImpl current = (TransactionImpl)threadTx.get();
- // Useless
+ if (current != null)
+ threadTx.set(null);
- return null;
- //throw new Exception("txMan.suspend() NYI");
+ return current;
}
/**
* Roll back the transaction associated with the currently running thread.
*/
public void rollback()
- throws java.lang.IllegalStateException,
+ throws IllegalStateException,
java.lang.SecurityException,
SystemException
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
if (current != null) {
current.rollback();
@@ -206,10 +218,10 @@
* so that the only possible outcome is a rollback.
*/
public void setRollbackOnly()
- throws java.lang.IllegalStateException,
+ throws IllegalStateException,
SystemException
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
if (current != null)
current.setRollbackOnly();
@@ -226,6 +238,11 @@
timeOut = 1000 * seconds;
}
+ /**
+ * Get the transaction timeout for new transactions started here.
+ *
+ * @return Transaction timeout in seconds.
+ */
public int getTransactionTimeout()
{
return (int)(timeOut / 1000);
@@ -237,7 +254,7 @@
*/
public Transaction disassociateThread()
{
- Transaction current = (Transaction)threadTx.get();
+ TransactionImpl current = (TransactionImpl)threadTx.get();
threadTx.set(null);
@@ -246,108 +263,78 @@
public void associateThread(Transaction transaction)
{
- //
- // If the transaction has travelled, we have to import it.
- //
- // This implicit import will go away at some point in the
- // future and be replaced by an explicit import by calling
- // importTPC().
- // That will make it possible to only propagate XidImpl over the
- // wire so that we no longer have to handle multible Transaction
- // frontends for each transaction.
- //
- if (transaction != null && transaction instanceof TransactionImpl) {
- TransactionImpl tx = (TransactionImpl)transaction;
-
- if (tx.importNeeded())
- transaction = importTPC(transaction);
- }
+ if (transaction != null && !(transaction instanceof TransactionImpl))
+ throw new RuntimeException("Not a TransactionImpl, but a " +
+ transaction.getClass().getName() + ".");
// Associate with the thread
threadTx.set(transaction);
}
+
+ // Implements TransactionPropagationContextImporter ---------------
+
/**
* Import a transaction propagation context into this TM.
* The TPC is loosely typed, as we may (at a later time) want to
- * import TPCs that come from other transaction monitors without
+ * import TPCs that come from other transaction domains without
* offloading the conversion to the client.
*
* @param tpc The transaction propagation context that we want to
* import into this TM. Currently this is an instance
- * of TransactionImpl. Later this will be changed to an
- * instance of XidImpl. And at some later time this may
- * even be an instance of a transaction propagation context
- * from another kind of transaction monitor like
+ * of GlobalId. At some later time this may be an instance
+ * of a transaction propagation context from another
+ * transaction domain like
* org.omg.CosTransactions.PropagationContext.
*
* @return A transaction representing this transaction propagation
* context, or null if this TPC cannot be imported.
*/
- public Transaction importTPC(Object tpc)
+ public Transaction importTransactionPropagationContext(Object tpc)
{
- if (tpc instanceof TransactionImpl) {
- // TODO: Change to just return the transaction without importing.
- // A raw TransactionImpl will only be used for optimized local calls,
- // where the import will not be needed.
- // But that will have to wait until remote calls use XidImpl instead,
- // otherwise we cannot distinguish cases.
- TransactionImpl tx = (TransactionImpl)tpc;
-
- if (tx.importNeeded()) {
- synchronized(tx) {
- // Recheck with synchronization.
- if (tx.importNeeded()) {
- TxCapsule txCapsule = (TxCapsule)activeCapsules.get(tx.xid);
- if (txCapsule != null)
- txCapsule.importTransaction(tx);
- else
- Logger.warning("Cannot import transaction: " +
- tx.toString());
- }
- }
- }
- return tx;
- } else if (tpc instanceof XidImpl)
- Logger.warning("XidImpl import not yet implemented.");
- else
+ if (tpc instanceof GlobalId)
+ return (Transaction)globalIdTx.get((GlobalId)tpc);
+ else {
Logger.warning("Cannot import transaction propagation context: " +
tpc.toString());
- return null;
+ return null;
+ }
}
- // Package protected ---------------------------------------------
-
+
+ // Implements TransactionPropagationContextFactory ---------------
+
/**
- * Release the given txCapsule for reuse.
+ * Return a TPC for the current transaction.
*/
- void releaseTxCapsule(TxCapsule txCapsule, XidImpl xid)
+ public Object getTransactionPropagationContext()
{
- activeCapsules.remove(xid);
-
- SoftReference ref = new SoftReference(txCapsule);
- synchronized (inactiveCapsules) {
- inactiveCapsules.add(ref);
- }
+ return getTransactionPropagationContext((Transaction)threadTx.get());
}
-
+
/**
- * Return an Xid that identifies the transaction associated
- * with the invoking thread, or <code>null</code> if the invoking
- * thread is not associated with a transaction.
- * This is used for JRMP transaction context propagation.
+ * Return a TPC for the argument transaction.
*/
- Xid getXid()
+ public Object getTransactionPropagationContext(Transaction tx)
{
- Transaction current = (Transaction)threadTx.get();
-
// If no transaction or unknown transaction class, return null.
- if (current == null || !(current instanceof TransactionImpl))
+ if (tx == null || !(tx instanceof TransactionImpl))
return null;
- return ((TransactionImpl)current).xid;
+ return ((TransactionImpl)tx).getGlobalId();
}
+
+ // Package protected ---------------------------------------------
+
+ /**
+ * Release the given TransactionImpl.
+ */
+ void releaseTransactionImpl(TransactionImpl tx)
+ {
+ globalIdTx.remove(tx.getGlobalId());
+ }
+
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
@@ -358,17 +345,11 @@
*/
private ThreadLocal threadTx = new ThreadLocal();
- /**
- * This map contains the active txCapsules as values.
- * The keys are the <code>Xid</code> of the txCapsules.
- */
- private Map activeCapsules = Collections.synchronizedMap(new HashMap());
-
/**
- * This collection contains the inactive txCapsules.
- * We keep these for reuse.
+ * This map contains the active transactions as values.
+ * The keys are the <code>GlobalId</code>s of the transactions.
*/
- private LinkedList inactiveCapsules = new LinkedList();
+ private Map globalIdTx = Collections.synchronizedMap(new HashMap());
// Inner classes -------------------------------------------------
}
1.10 +13 -1 jboss/src/main/org/jboss/tm/XidImpl.java
Index: XidImpl.java
===================================================================
RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/XidImpl.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- XidImpl.java 2001/01/24 05:59:56 1.9
+++ XidImpl.java 2001/02/09 18:56:18 1.10
@@ -19,7 +19,7 @@
* @see TransactionImpl
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
- * @version $Revision: 1.9 $
+ * @version $Revision: 1.10 $
*/
class XidImpl
implements Xid, java.io.Serializable
@@ -221,6 +221,18 @@
// Package protected ---------------------------------------------
+ /**
+ * Return the global transaction id of this transaction.
+ * Unlike the {@link #getGlobalTransactionId()} method, this one
+ * returns a reference to the global id byte array that may <em>not</em>
+ * be changed.
+ */
+ public byte[] getInternalGlobalTransactionId()
+ {
+ return (byte[])globalId.clone();
+ }
+
+
// Protected -----------------------------------------------------
// Private -------------------------------------------------------