Skip to content

Commit

Permalink
[GERONIMO-6543] Aries/Geronimo XA transaction recovery not working fo…
Browse files Browse the repository at this point in the history
…r heuristically completed transactions

git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/txmanager/trunk@1684215 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
gnodet committed Jun 8, 2015
1 parent 8b6b592 commit ce240ae
Showing 1 changed file with 45 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,37 +114,22 @@ public synchronized void recoverResourceManager(NamedXAResource xaResource) thro
// This is a bit wasteful, but given our management of XAResources by "name", is about the best we can do.
if (isNameInTransaction(xidNamesPair, name, xid)) {
log.trace("This xid was prepared from this XAResource: committing");
try {
xaResource.commit(xid, false);
} catch(XAException e) {
recoveryErrors.add(e);
log.error("Recovery error", e);
}
commit(xaResource, xid);
removeNameFromTransaction(xidNamesPair, name, true);
} else {
log.trace("This xid was prepared from another XAResource, ignoring");
}
} else if (txManager.getXidFactory().matchesGlobalId(xid.getGlobalTransactionId())) {
//ours, but prepare not logged
log.trace("this xid was initiated from this tm but not prepared: rolling back");
try {
xaResource.rollback(xid);
} catch (XAException e) {
recoveryErrors.add(e);
log.error("Could not roll back", e);
}
rollback(xaResource, xid);
} else if (txManager.getXidFactory().matchesBranchId(xid.getBranchQualifier())) {
//our branch, but we did not start this tx.
TransactionImpl externalTx = externalGlobalIdMap.get(xid.getGlobalTransactionId());
if (externalTx == null) {
//we did not prepare this branch, rollback.
log.trace("this xid is from an external transaction and was not prepared: rolling back");
try {
xaResource.rollback(xid);
} catch (XAException e) {
recoveryErrors.add(e);
log.error("Could not roll back", e);
}
rollback(xaResource, xid);
} else {
log.trace("this xid is from an external transaction and was prepared in this tm. Waiting for instructions from transaction originator");
//we prepared this branch, must wait for commit/rollback command.
Expand All @@ -161,6 +146,48 @@ public synchronized void recoverResourceManager(NamedXAResource xaResource) thro
}
}

private void commit(NamedXAResource xaResource, Xid xid) {
doCommitOrRollback(xaResource, xid, true);
}

private void rollback(NamedXAResource xaResource, Xid xid) {
doCommitOrRollback(xaResource, xid, false);
}

private void doCommitOrRollback(NamedXAResource xaResource, Xid xid, boolean commit) {
try {
if (commit) {
xaResource.commit(xid, false);
} else {
xaResource.rollback(xid);
}
} catch (XAException e) {
try {
if (e.errorCode == XAException.XA_HEURRB) {
log.info("Transaction has been heuristically rolled back");
xaResource.forget(xid);
} else if (e.errorCode == XAException.XA_HEURMIX) {
log.info("Transaction has been heuristically committed and rolled back");
xaResource.forget(xid);
} else if (e.errorCode == XAException.XA_HEURCOM) {
log.info("Transaction has been heuristically committed");
xaResource.forget(xid);
} else {
recoveryErrors.add(e);
log.error("Could not roll back", e);
}
} catch (XAException e2) {
if (e2.errorCode == XAException.XAER_NOTA) {
// NOTA in response to forget, means the resource already forgot the transaction
// ignore
} else {
recoveryErrors.add(e);
log.error("Could not roll back", e);
}
}
}
}

private boolean isNameInTransaction(XidBranchesPair xidBranchesPair, String name, Xid xid) {
for (TransactionBranchInfo transactionBranchInfo : xidBranchesPair.getBranches()) {
if (name.equals(transactionBranchInfo.getResourceName()) && equals(xid, transactionBranchInfo.getBranchXid())) {
Expand Down

0 comments on commit ce240ae

Please sign in to comment.