You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by li...@apache.org on 2008/12/17 20:13:47 UTC
svn commit: r727474 -
/geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
Author: linsun
Date: Wed Dec 17 11:13:47 2008
New Revision: 727474
URL: http://svn.apache.org/viewvc?rev=727474&view=rev
Log:
GERONIMO-4471 improve heuristic exception handling in rollback when txmanager.commit is called
Modified:
geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
Modified: geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
URL: http://svn.apache.org/viewvc/geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java?rev=727474&r1=727473&r2=727474&view=diff
==============================================================================
--- geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java (original)
+++ geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java Wed Dec 17 11:13:47 2008
@@ -265,7 +265,7 @@
}
if (status == Status.STATUS_MARKED_ROLLBACK) {
- rollbackResources(resourceManagers);
+ rollbackResourcesDuringCommit(resourceManagers, false);
if (timedout) {
throw new RollbackException("Transaction timeout");
} else {
@@ -333,8 +333,9 @@
if (willCommit) {
commitResources(resourceManagers);
} else {
- rollbackResources(resourceManagers);
- throw new RollbackException("Unable to commit");
+ // set everRollback to true here because the rollback here is caused by
+ // XAException during the above internalPrepare
+ rollbackResourcesDuringCommit(resourceManagers, true);
}
} catch (XAException e) {
throw (SystemException) new SystemException("Error during commit").initCause(e);
@@ -438,8 +439,13 @@
} catch (XAException e) {
synchronized (this) {
status = Status.STATUS_MARKED_ROLLBACK;
- //TODO document why this is true from the spec.
- //XAException during prepare means we can assume resource is rolled back.
+ /* Per JTA spec, If the resource manager wants to roll back the transaction,
+ it should do so by throwing an appropriate XAException in the prepare method.
+ Also per OTS spec:
+ The resource can return VoteRollback under any circumstances, including not having
+ any knowledge about the transaction (which might happen after a crash). If this
+ response is returned, the transaction must be rolled back. Furthermore, the Transaction
+ Service is not required to perform any additional operations on this resource.*/
rms.remove();
break;
}
@@ -609,6 +615,60 @@
throw cause;
}
}
+
+ private void rollbackResourcesDuringCommit(List rms, boolean everRb) throws HeuristicMixedException, RollbackException, SystemException {
+ XAException cause = null;
+ boolean everRolledback = everRb;
+ synchronized (this) {
+ status = Status.STATUS_ROLLING_BACK;
+ }
+ try {
+ for (Iterator i = rms.iterator(); i.hasNext();) {
+ TransactionBranch manager = (TransactionBranch) i.next();
+ try {
+ manager.getCommitter().rollback(manager.getBranchId());
+ everRolledback = true;
+ } catch (XAException e) {
+ if (e.errorCode == XAException.XA_HEURRB) {
+ // let's not set the cause here
+ log.error("Transaction has been heuristically rolled back " + manager.getCommitter() + "; continuing with rollback", e);
+ everRolledback = true;
+ manager.getCommitter().forget(manager.getBranchId());
+ } else if (e.errorCode == XAException.XA_HEURMIX) {
+ log.error("Transaction has been heuristically committed and rolled back " + manager.getCommitter() + "; continuing with rollback", e);
+ cause = e;
+ everRolledback = true;
+ manager.getCommitter().forget(manager.getBranchId());
+ } else if (e.errorCode == XAException.XA_HEURCOM) {
+ log.error("Transaction has been heuristically committed " + manager.getCommitter() + "; continuing with rollback", e);
+ cause = e;
+ manager.getCommitter().forget(manager.getBranchId());
+ } else if (cause == null) {
+ cause = e;
+ }
+ }
+ }
+ } catch (XAException e) {
+ throw (SystemException) new SystemException("Error during rolling back").initCause(e);
+ }
+
+ synchronized (this) {
+ status = Status.STATUS_ROLLEDBACK;
+ }
+
+ if (cause == null) {
+ throw (RollbackException) new RollbackException("Error during two phase commit").initCause(cause);
+ } else {
+ if (cause.errorCode == XAException.XA_HEURCOM && everRolledback) {
+ throw (HeuristicMixedException) new HeuristicMixedException("Error during two phase commit").initCause(cause);
+ } else if (cause.errorCode == XAException.XA_HEURMIX) {
+ throw (HeuristicMixedException) new HeuristicMixedException("Error during two phase commit").initCause(cause);
+ } else {
+ throw (SystemException) new SystemException("Error during two phase commit").initCause(cause);
+ }
+ }
+ }
+
private void commitResources(List rms) throws HeuristicRollbackException, HeuristicMixedException, SystemException {
XAException cause = null;