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 2004/07/11 23:25:21 UTC
cvs commit: incubator-geronimo/modules/transaction/src/java/org/apache/geronimo/transaction TransactionManagerProxy.java XAWork.java
djencks 2004/07/11 14:25:21
Modified: modules/transaction/src/java/org/apache/geronimo/transaction
TransactionManagerProxy.java XAWork.java
Log:
Fix problems with synchronization and suspend/restore of imported tx
Revision Changes Path
1.11 +93 -36 incubator-geronimo/modules/transaction/src/java/org/apache/geronimo/transaction/TransactionManagerProxy.java
Index: TransactionManagerProxy.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/transaction/src/java/org/apache/geronimo/transaction/TransactionManagerProxy.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- TransactionManagerProxy.java 11 Jun 2004 19:20:54 -0000 1.10
+++ TransactionManagerProxy.java 11 Jul 2004 21:25:21 -0000 1.11
@@ -18,13 +18,11 @@
package org.apache.geronimo.transaction;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.Collection;
import javax.resource.spi.XATerminator;
import javax.transaction.HeuristicMixedException;
@@ -63,6 +61,8 @@
* @version $Revision$ $Date$
*/
public class TransactionManagerProxy implements TransactionManager, XATerminator, XAWork, GBeanLifecycle {
+ private static final boolean NOT_IN_RECOVERY = false;
+ private static final boolean IN_RECOVERY = true;
private static final Log recoveryLog = LogFactory.getLog("RecoveryController");
@@ -70,10 +70,7 @@
private final XidImporter importer;
private final ThreadLocal threadTx = new ThreadLocal();
private final Map importedTransactions = new HashMap();
- private Set activeTransactions = new HashSet();
private boolean recoveryState = NOT_IN_RECOVERY;
- private static final boolean NOT_IN_RECOVERY = false;
- private static final boolean IN_RECOVERY = true;
private final Recovery recovery;
private final ReferenceCollection resourceManagers;
private List recoveryErrors = new ArrayList();
@@ -230,10 +227,14 @@
* @see javax.resource.spi.XATerminator#commit(javax.transaction.xa.Xid, boolean)
*/
public void commit(Xid xid, boolean onePhase) throws XAException {
- TransactionProxy tx = (TransactionProxy) importedTransactions.remove(xid);
- if (tx == null) {
+ ImportedTransactionInfo txInfo;
+ synchronized (importedTransactions) {
+ txInfo = (ImportedTransactionInfo) importedTransactions.remove(xid);
+ }
+ if (txInfo == null) {
throw new XAException("No imported transaction for xid: " + xid);
}
+ TransactionProxy tx = txInfo.getTransactionProxy();
try {
int status = tx.getStatus();
@@ -248,10 +249,14 @@
* @see javax.resource.spi.XATerminator#forget(javax.transaction.xa.Xid)
*/
public void forget(Xid xid) throws XAException {
- TransactionProxy tx = (TransactionProxy) importedTransactions.remove(xid);
- if (tx == null) {
+ ImportedTransactionInfo txInfo;
+ synchronized (importedTransactions) {
+ txInfo = (ImportedTransactionInfo) importedTransactions.remove(xid);
+ }
+ if (txInfo == null) {
throw new XAException("No imported transaction for xid: " + xid);
}
+ TransactionProxy tx = txInfo.getTransactionProxy();
//todo is there a correct status test here?
// try {
// int status = tx.getStatus();
@@ -266,11 +271,14 @@
* @see javax.resource.spi.XATerminator#prepare(javax.transaction.xa.Xid)
*/
public int prepare(Xid xid) throws XAException {
- TransactionProxy tx = (TransactionProxy) importedTransactions.get(xid);
- if (tx == null) {
+ ImportedTransactionInfo txInfo;
+ synchronized (importedTransactions) {
+ txInfo = (ImportedTransactionInfo) importedTransactions.get(xid);
+ }
+ if (txInfo == null) {
throw new XAException("No imported transaction for xid: " + xid);
}
-
+ TransactionProxy tx = txInfo.getTransactionProxy();
try {
int status = tx.getStatus();
assert status == Status.STATUS_ACTIVE;
@@ -296,8 +304,19 @@
//we always return all xids in first call.
//calling "startrscan" repeatedly starts at beginning of list again.
if ((flag & XAResource.TMSTARTRSCAN) != 0) {
- importedTransactions.putAll(recovery.getExternalXids());
- return (Xid[]) importedTransactions.keySet().toArray(new Xid[importedTransactions.size()]);
+ Map recoveredXidMap = recovery.getExternalXids();
+ Xid[] recoveredXids = new Xid[recoveredXidMap.size()];
+ int i = 0;
+ synchronized (importedTransactions) {
+ for (Iterator iterator = recoveredXidMap.entrySet().iterator(); iterator.hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ Xid xid = (Xid) entry.getKey();
+ recoveredXids[i++] = xid;
+ ImportedTransactionInfo txInfo = new ImportedTransactionInfo(new TransactionProxy((Transaction)entry.getValue()));
+ importedTransactions.put(xid, txInfo);
+ }
+ }
+ return recoveredXids;
} else {
return new Xid[0];
}
@@ -307,10 +326,14 @@
* @see javax.resource.spi.XATerminator#rollback(javax.transaction.xa.Xid)
*/
public void rollback(Xid xid) throws XAException {
- TransactionProxy tx = (TransactionProxy) importedTransactions.remove(xid);
- if (tx == null) {
+ ImportedTransactionInfo txInfo;
+ synchronized (importedTransactions) {
+ txInfo = (ImportedTransactionInfo) importedTransactions.remove(xid);
+ }
+ if (txInfo == null) {
throw new XAException("No imported transaction for xid: " + xid);
}
+ TransactionProxy tx = txInfo.getTransactionProxy();
try {
int status = tx.getStatus();
@@ -321,31 +344,65 @@
importer.rollback(tx.getDelegate());
}
- public void begin(Xid xid, long txTimeoutMillis) throws XAException {
- TransactionProxy tx = (TransactionProxy) importedTransactions.get(xid);
- if (tx == null) {
- try {
- tx = new TransactionProxy(importer.importXid(xid));
- } catch (SystemException e) {
- throw (XAException) new XAException("Could not import xid").initCause(e);
+ public void begin(Xid xid, long txTimeoutMillis) throws XAException, InvalidTransactionException, SystemException {
+ ImportedTransactionInfo txInfo;
+ boolean old = true;
+ synchronized (importedTransactions) {
+ txInfo = (ImportedTransactionInfo) importedTransactions.get(xid);
+ if (txInfo == null) {
+ try {
+ txInfo = new ImportedTransactionInfo(new TransactionProxy(importer.importXid(xid)));
+ old = false;
+ } catch (SystemException e) {
+ throw (XAException) new XAException("Could not import xid").initCause(e);
+ }
+ importedTransactions.put(xid, txInfo);
}
- importedTransactions.put(xid, tx);
+ if (txInfo.isActive()) {
+ throw new XAException("Xid already active");
+ }
+ txInfo.setActive(true);
}
- if (activeTransactions.contains(tx)) {
- throw new XAException("Xid already active");
+ threadTx.set(txInfo.getTransactionProxy());
+ if (old) {
+ delegate.resume(txInfo.getTransactionProxy().getDelegate());
}
- activeTransactions.add(tx);
- threadTx.set(tx);
importer.setTransactionTimeout(txTimeoutMillis);
}
- public void end(Xid xid) throws XAException {
- TransactionProxy tx = (TransactionProxy) importedTransactions.get(xid);
- if (tx == null) {
- throw new XAException("No imported transaction for xid: " + xid);
+ public void end(Xid xid) throws XAException, SystemException {
+ synchronized (importedTransactions) {
+ ImportedTransactionInfo txInfo = (ImportedTransactionInfo) importedTransactions.get(xid);
+ if (txInfo == null) {
+ throw new XAException("No imported transaction for xid: " + xid);
+ }
+ if (!txInfo.isActive()) {
+ throw new XAException("tx not active for xid: " + xid);
+ }
+ txInfo.setActive(false);
}
- if (!activeTransactions.remove(tx)) {
- throw new XAException("tx not active for xid: " + xid);
+ threadTx.set(null);
+ delegate.suspend();
+ }
+
+ private static class ImportedTransactionInfo {
+ private final TransactionProxy transactionProxy;
+ private boolean active;
+
+ public ImportedTransactionInfo(TransactionProxy transactionProxy) {
+ this.transactionProxy = transactionProxy;
+ }
+
+ public TransactionProxy getTransactionProxy() {
+ return transactionProxy;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
}
}
1.3 +5 -3 incubator-geronimo/modules/transaction/src/java/org/apache/geronimo/transaction/XAWork.java
Index: XAWork.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/transaction/src/java/org/apache/geronimo/transaction/XAWork.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- XAWork.java 25 Feb 2004 09:58:19 -0000 1.2
+++ XAWork.java 11 Jul 2004 21:25:21 -0000 1.3
@@ -19,6 +19,8 @@
import javax.transaction.xa.Xid;
import javax.transaction.xa.XAException;
+import javax.transaction.SystemException;
+import javax.transaction.InvalidTransactionException;
/**
* primarily an interface between the WorkManager/ExecutionContext and the tm.
@@ -27,6 +29,6 @@
*
* */
public interface XAWork {
- void begin(Xid xid, long txTimeout) throws XAException;
- void end(Xid xid) throws XAException;
+ void begin(Xid xid, long txTimeout) throws XAException, InvalidTransactionException, SystemException;
+ void end(Xid xid) throws XAException, SystemException;
}