You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2003/11/19 18:33:44 UTC
cvs commit: incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/outbound TransactionCachingInterceptor.java
djencks 2003/11/19 09:33:44
Modified: modules/core/src/java/org/apache/geronimo/connector/outbound
TransactionCachingInterceptor.java
Log:
Another egregious bug: release connections at end of tx if they have no more handles
Revision Changes Path
1.3 +83 -35 incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java
Index: TransactionCachingInterceptor.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TransactionCachingInterceptor.java 14 Nov 2003 16:00:23 -0000 1.2
+++ TransactionCachingInterceptor.java 19 Nov 2003 17:33:44 -0000 1.3
@@ -60,10 +60,14 @@
import java.util.Iterator;
import java.util.Collection;
import java.util.LinkedList;
+import java.util.Map;
+import java.util.HashMap;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.SystemException;
+import javax.transaction.Synchronization;
+import javax.transaction.RollbackException;
import javax.resource.ResourceException;
import org.apache.geronimo.connector.TxUtils;
@@ -80,74 +84,118 @@
private final ConnectionInterceptor next;
private final TransactionManager tm;
- private final WeakHashMap txToMCIListMap = new WeakHashMap();
+ private final Map txToConnectionList = new HashMap();
public TransactionCachingInterceptor(final ConnectionInterceptor next, final TransactionManager tm) {
this.next = next;
this.tm = tm;
- } // TransactionCachingInterceptor constructor
+ }
public void getConnection(ConnectionInfo ci) throws ResourceException {
try {
Transaction tx = tm.getTransaction();
if (TxUtils.isActive(tx)) {
ManagedConnectionInfo mci = ci.getManagedConnectionInfo();
- Collection mcis = null;
- synchronized (txToMCIListMap) {
- mcis = (Collection) txToMCIListMap.get(tx);
+ Collection mcis;
+ synchronized (txToConnectionList) {
+ mcis = (Collection)txToConnectionList.get(tx);
+ if (mcis == null) {
+ mcis = new LinkedList();
+ txToConnectionList.put(tx, mcis);
+ tx.registerSynchronization(new Synch(tx, this, mcis));
+ }
}
+
/*Access to mcis should not need to be synchronized
* unless several requests in the same transaction in
* different threads are being processed at the same
* time. This cannot occur with transactions imported
* through jca. I don't know about any other possible
* ways this could occur.*/
- if (mcis != null) {
- for (Iterator i = mcis.iterator(); i.hasNext();) {
- ManagedConnectionInfo oldmci = (ManagedConnectionInfo) i.next();
- if (mci.securityMatches(oldmci)) {
- ci.setManagedConnectionInfo(oldmci);
- return;
- } // end of if ()
-
- } // end of for ()
-
- } // end of if ()
- else {
- mcis = new LinkedList();
- synchronized (txToMCIListMap) {
- txToMCIListMap.put(tx, mcis);
+ for (Iterator i = mcis.iterator(); i.hasNext();) {
+ ManagedConnectionInfo oldmci = (ManagedConnectionInfo) i.next();
+ if (mci.securityMatches(oldmci)) {
+ ci.setManagedConnectionInfo(oldmci);
+ return;
}
- } // end of else
- next.getConnection(ci);
- //put it in the map
- synchronized (mcis) {
- mcis.add(ci.getManagedConnectionInfo());
+
}
- } // end of if ()
- else {
next.getConnection(ci);
- } // end of else
+ //put it in the map
+ mcis.add(ci.getManagedConnectionInfo());
+ } else {
+ next.getConnection(ci);
+ }
} catch (SystemException e) {
throw new ResourceException("Could not get transaction from transaction manager", e);
- } // end of try-catch
-
+ } catch (RollbackException e) {
+ throw new ResourceException("Transaction is rolled back, can't enlist synchronization", e);
+ }
}
public void returnConnection(ConnectionInfo ci, ConnectionReturnAction cra) {
try {
- Transaction tx = tm.getTransaction();
- if (cra == ConnectionReturnAction.DESTROY || !TxUtils.isActive(tx)) {
+ if (cra == ConnectionReturnAction.DESTROY) {
next.returnConnection(ci, cra);
}
- //if tx is active, we keep it cached and do nothing.
+
+ Transaction tx = tm.getTransaction();
+ if (TxUtils.isActive(tx)) {
+ return;
+ }
+ if (ci.getManagedConnectionInfo().hasConnectionHandles()) {
+ return;
+ }
+ //No transaction, no handles, we return it.
+ next.returnConnection(ci, cra);
} catch (SystemException e) {
//throw new ResourceException("Could not get transaction from transaction manager", e);
- } // end of try-catch
+ }
+
+ }
+
+
+ public void afterCompletion(Transaction tx) {
+ Collection connections = (Collection) txToConnectionList.get(tx);
+ if (connections != null) {
+ for (Iterator iterator = connections.iterator(); iterator.hasNext();) {
+ ManagedConnectionInfo managedConnectionInfo = (ManagedConnectionInfo) iterator.next();
+ ConnectionInfo connectionInfo = new ConnectionInfo();
+ connectionInfo.setManagedConnectionInfo(managedConnectionInfo);
+ returnConnection(connectionInfo, ConnectionReturnAction.RETURN_HANDLE);
+ }
+ }
+
+ }
+
+ private static class Synch implements Synchronization {
+
+ private final Transaction transaction;
+ private final TransactionCachingInterceptor returnStack;
+ private final Collection connections;
+
+ public Synch(Transaction transaction, TransactionCachingInterceptor returnStack, Collection connections) {
+ this.transaction = transaction;
+ this.returnStack = returnStack;
+ this.connections = connections;
+ }
+
+ public void beforeCompletion() {
+ }
+
+ public void afterCompletion(int status) {
+ for (Iterator iterator = connections.iterator(); iterator.hasNext();) {
+ ManagedConnectionInfo managedConnectionInfo = (ManagedConnectionInfo) iterator.next();
+ iterator.remove();
+ if (!managedConnectionInfo.hasConnectionHandles()) {
+ returnStack.returnConnection(new ConnectionInfo(managedConnectionInfo), ConnectionReturnAction.RETURN_HANDLE);
+ }
+ }
+ }
}
-} // TransactionCachingInterceptor
+}