[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