[jboss-cvs] JBossAS SVN: r77961 - trunk/connector/src/main/org/jboss/resource/connectionmanager.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Sep 4 07:25:43 EDT 2008


Author: jesper.pedersen
Date: 2008-09-04 07:25:43 -0400 (Thu, 04 Sep 2008)
New Revision: 77961

Modified:
   trunk/connector/src/main/org/jboss/resource/connectionmanager/BaseConnectionManager2.java
   trunk/connector/src/main/org/jboss/resource/connectionmanager/NoTxConnectionManager.java
   trunk/connector/src/main/org/jboss/resource/connectionmanager/TxConnectionManager.java
Log:
[JBAS-5095] Race condition between connection.close() and transaction.rollback()

Modified: trunk/connector/src/main/org/jboss/resource/connectionmanager/BaseConnectionManager2.java
===================================================================
--- trunk/connector/src/main/org/jboss/resource/connectionmanager/BaseConnectionManager2.java	2008-09-04 11:18:20 UTC (rev 77960)
+++ trunk/connector/src/main/org/jboss/resource/connectionmanager/BaseConnectionManager2.java	2008-09-04 11:25:43 UTC (rev 77961)
@@ -31,6 +31,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanServer;
@@ -519,7 +520,7 @@
    //does NOT put the mc back in the pool if no more handles. Doing so would introduce a race condition
    //whereby the mc got back in the pool while still enlisted in the tx.
    //The mc could be checked out again and used before the delist occured.
-   protected void unregisterAssociation(ConnectionListener cl, Object c) throws ResourceException
+   protected void unregisterAssociation(ConnectionListener cl, Object c)
    {
       cl.unregisterConnection(c);
    }
@@ -631,7 +632,7 @@
 
       private long lastUse;
 
-      private boolean trackByTx = false;
+      private AtomicBoolean trackByTx = new AtomicBoolean(false);
 
       private boolean permit = false;
 
@@ -689,12 +690,12 @@
 
       public boolean isTrackByTx()
       {
-         return trackByTx;
+         return trackByTx.get();
       }
 
       public void setTrackByTx(boolean trackByTx)
       {
-         this.trackByTx = trackByTx;
+         this.trackByTx.set(trackByTx);
       }
 
       public void tidyup() throws ResourceException
@@ -812,7 +813,7 @@
          buffer.append(" handles=").append(handles.size());
          buffer.append(" lastUse=").append(lastUse);
          buffer.append(" permit=").append(permit);
-         buffer.append(" trackByTx=").append(trackByTx);
+         buffer.append(" trackByTx=").append(trackByTx.get());
          buffer.append(" mcp=").append(mcp);
          buffer.append(" context=").append(context);
          toString(buffer);

Modified: trunk/connector/src/main/org/jboss/resource/connectionmanager/NoTxConnectionManager.java
===================================================================
--- trunk/connector/src/main/org/jboss/resource/connectionmanager/NoTxConnectionManager.java	2008-09-04 11:18:20 UTC (rev 77960)
+++ trunk/connector/src/main/org/jboss/resource/connectionmanager/NoTxConnectionManager.java	2008-09-04 11:25:43 UTC (rev 77961)
@@ -91,18 +91,12 @@
          {
             log.info("Throwable from unregisterConnection", t);
          }
-         try
+
+         unregisterAssociation(this, ce.getConnectionHandle());
+         if (isManagedConnectionFree())
          {
-            unregisterAssociation(this, ce.getConnectionHandle());
-            if (isManagedConnectionFree())
-            {
-               returnManagedConnection(this, false);
-            }
+           returnManagedConnection(this, false);
          }
-         catch (ResourceException re)
-         {
-            log.error("ResourceException while closing connection handle!", re);
-         }
       }
 
       public void localTransactionStarted(ConnectionEvent ce)

Modified: trunk/connector/src/main/org/jboss/resource/connectionmanager/TxConnectionManager.java
===================================================================
--- trunk/connector/src/main/org/jboss/resource/connectionmanager/TxConnectionManager.java	2008-09-04 11:18:20 UTC (rev 77960)
+++ trunk/connector/src/main/org/jboss/resource/connectionmanager/TxConnectionManager.java	2008-09-04 11:25:43 UTC (rev 77961)
@@ -423,11 +423,16 @@
       }
 
       //if there are no more handles and tx is complete, we can return to pool.
-      boolean isFree = cl.isManagedConnectionFree();
-      if (trace)
-         log.trace("Disconnected isManagedConnectionFree=" + isFree + " cl=" + cl);
-      if (isFree)
+      if (cl.isManagedConnectionFree())
+      {
+         if (trace)
+            log.trace("Disconnected isManagedConnectionFree=true" + " cl=" + cl);
          returnManagedConnection(cl, false);
+      }
+      else if (trace)
+      {
+         log.trace("Disconnected isManagedConnectionFree=false" + " cl=" + cl);
+      }
 
       // Rethrow the error
       if (throwable != null)
@@ -513,7 +518,7 @@
 
       /** Whether there is a local transaction */
       private AtomicBoolean localTransaction = new AtomicBoolean(false);
-      
+
       public TxConnectionEventListener(final ManagedConnection mc, final ManagedConnectionPool mcp, final Object context, Logger log, final XAResource xaResource) throws ResourceException
       {
          super(mc, mcp, context, log);
@@ -721,16 +726,18 @@
 
          try
          {
-            unregisterAssociation(this, ce.getConnectionHandle());
-            boolean isFree = isManagedConnectionFree();
-            if (trace)
-               log.trace("isManagedConnectionFree=" + isFree + " mc=" + this.getManagedConnection());
-            //no more handles
-            if (isFree)
+            if (wasFreed(ce.getConnectionHandle()))
             {
                delist();
+               if (trace)
+                  log.trace("isManagedConnectionFree=true mc=" + this.getManagedConnection());
                returnManagedConnection(this, false);
             }
+            else
+            {
+               if (trace)
+                  log.trace("isManagedConnectionFree=false mc=" + this.getManagedConnection());
+            }
          }
          catch (Throwable t)
          {
@@ -793,6 +800,41 @@
          return super.isManagedConnectionFree();
       }
 
+      /**
+       * This method changes the number of handles or 
+       * the track-by-tx value depending on the parameter passed in
+       * @param handle The handle; if <code>null</code> track-by-tx is changed
+       * @return True if the managed connection was freed
+       */
+      synchronized boolean wasFreed(Object handle)
+      {
+         if (handle != null)
+         {
+            if (isManagedConnectionFree())
+            {
+               // This shouldn't really happen now all the state is changed atomically
+               return false;
+            }
+
+            // Change the number of handles
+            unregisterAssociation(this, handle);
+         }
+         else
+         {
+            if (!isTrackByTx())
+            {
+               // Only change the state once
+               return false;
+            }
+
+            // Set track-by-tx to false
+            setTrackByTx(false);
+         }
+         
+         // Return if the managed connection was just freed
+         return isManagedConnectionFree();
+      }
+      
       private class TransactionSynchronization implements Synchronization
       {
          /** Transaction */
@@ -918,8 +960,10 @@
             // This is where we close when doing track by transaction
             if (wasTrackByTx)
             {
-               setTrackByTx(false);
-               if (isManagedConnectionFree())
+               if (trace)
+                  log.trace("afterCompletion(" + status + ") isTrackByTx=" + isTrackByTx() + " for " + TxConnectionEventListener.this);
+
+               if (wasFreed(null))
                   returnManagedConnection(TxConnectionEventListener.this, false);
             }
          }




More information about the jboss-cvs-commits mailing list