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 -------------------------------------------------------
  
  
  

Reply via email to