XATerminatorImplpublic class XATerminatorImpl extends Object implements javax.resource.spi.XATerminatorThis is used for transaction completion and crash recovery flows. |
Fields Summary |
---|
private static final com.sun.enterprise.transaction.TransactionImport | tim | private static final String | AS_TXN_MGR_JNDI_NAME |
Methods Summary |
---|
private static void | check(javax.transaction.xa.Xid xid)
// check if xid is valid
if (xid == null || xid.getFormatId() == 0 ||
xid.getBranchQualifier() == null ||
xid.getGlobalTransactionId() == null) {
throw new XAException(XAException.XAER_NOTA);
}
| public void | commit(javax.transaction.xa.Xid xid, boolean onePhase)Commits the global transaction specified by xid.
check(xid); // check if xid is valid
GlobalTID tid = new GlobalTID(xid);
if (onePhase) {
// Synchronizers invoked by coord.beforeCompletion must be
// executed with the transaction context of the transaction
// that is being committed as specified in
// in method javax.Synchronization.beforeCompletion
try {
recreate(xid, 0);
} catch (Throwable e) {
// failed check for concurrent activity
XAException xaExc = new XAException(XAException.XAER_PROTO);
xaExc.initCause(e);
throw xaExc;
}
} else {
// check for concurrrent activity
if (RecoveryManager.readAndUpdateTxMap(tid) == false) {
throw new XAException(XAException.XAER_PROTO);
}
}
boolean exceptionFlag = false;
int errorCode = XAException.XAER_PROTO;
try {
// First of all make sure it has been recovered if necessary
RecoveryManager.waitForRecovery();
// Look up the Coordinator for the transaction.
TopCoordinator coord = (TopCoordinator)
RecoveryManager.getCoordinator(tid);
if (coord == null) { // error to receive commit more than once
errorCode = XAException.XAER_PROTO;
throw new XAException(errorCode);
}
// If there is a Coordinator, lock it for the duration of this
// operation. Tell the Coordinator to commit.
synchronized (coord) {
if (onePhase) {
coord.beforeCompletion();
if (coord.getParticipantCount() == 1) {
coord.commitOnePhase();
} else {
Vote vote = Vote.VoteRollback;
try {
vote = coord.prepare();
} catch (HeuristicMixed exc) {
errorCode = XAException.XA_HEURHAZ;
throw new XAException(errorCode);
}
if (vote == Vote.VoteCommit) {
coord.commit();
} else if (vote == Vote.VoteRollback) {
coord.rollback(true);
}
}
} else {
coord.commit();
}
}
} catch (Throwable exc) {
exceptionFlag = true;
XAException xaExc = new XAException(errorCode);
xaExc.initCause(exc);
throw xaExc;
} finally {
if (onePhase) {
// Complete full transactional context created for
// beforeCompletion calls in prepare phase of one phase commit.
try {
release(xid);
} catch (Throwable t) {
if (!exceptionFlag) {
XAException xaExc = new XAException(XAException.XAER_PROTO);
xaExc.initCause(t);
throw xaExc;
}
}
} else {
Thread thread = RecoveryManager.removeFromTxMap(tid);
if (thread == null || (thread != Thread.currentThread())) { // error
if (!exceptionFlag) {
throw new XAException(XAException.XAER_RMERR);
}
}
}
}
| public void | forget(javax.transaction.xa.Xid xid)Tells the resource manager to forget about a heuristically
completed transaction branch.
| private static com.sun.enterprise.transaction.TransactionImport | getTransactionImportManager()
return (TransactionImport)jndiLookup(AS_TXN_MGR_JNDI_NAME);
| private static java.lang.Object | jndiLookup(java.lang.String jndiName)
Object result = null;
try {
final Context ctx = new InitialContext();
result = ctx.lookup(jndiName);
} catch (NamingException e) { }
return result;
| public int | prepare(javax.transaction.xa.Xid xid)Ask the resource manager to prepare for a transaction commit
of the transaction specified in xid.
check(xid); // check if xid is valid
GlobalTID tid = new GlobalTID(xid);
try {
// Synchronizers invoked by coord.beforeCompletion must be
// executed with the transaction context of the transaction
// that is being committed as specified in
// in method javax.Synchronization.beforeCompletion
recreate(xid, 0);
} catch (Throwable e) {
// failed check for concurrent activity for transaction tid.
XAException xaExc = new XAException(XAException.XAER_PROTO);
xaExc.initCause(e);
throw xaExc;
}
boolean exceptionFlag = false;
int errorCode = XAException.XAER_PROTO;
try {
// First of all make sure it has been recovered if necessary
RecoveryManager.waitForRecovery();
// Look up the Coordinator for the transaction.
TopCoordinator coord = (TopCoordinator)
RecoveryManager.getCoordinator(tid);
if (coord == null) { // error to receive prepare more than once
errorCode = XAException.XAER_PROTO;
throw new XAException(errorCode);
}
// If there is a Coordinator, lock it for the duration of this
// operation. Tell the Coordinator to commit.
synchronized (coord) {
coord.beforeCompletion();
Vote vote = coord.prepare();
if (vote == Vote.VoteRollback) {
errorCode = XAException.XA_RBROLLBACK;
} else if (vote == Vote.VoteCommit) {
return XAResource.XA_OK;
} else if (vote == Vote.VoteReadOnly) {
return XAResource.XA_RDONLY;
}
throw new XAException(errorCode);
}
} catch (Throwable exc) {
exceptionFlag = true;
XAException xaExc = new XAException(errorCode);
xaExc.initCause(exc);
throw xaExc;
} finally {
try {
release(xid);
} catch (Throwable t) {
if (!exceptionFlag) {
errorCode = XAException.XAER_PROTO;
XAException xaExc = new XAException(errorCode);
xaExc.initCause(t);
throw xaExc;
}
// else allow original exception to be thrown
}
}
| public javax.transaction.xa.Xid[] | recover(int flag)Obtains a list of prepared transaction branches from a resource
manager. The transaction manager calls this method during recovery
to obtain the list of transaction branches that are currently in
prepared or heuristically completed states.
// wait for recovery to be completed.
RecoveryManager.waitForResync();
return (Xid[]) TimeoutManager.getInDoubtXids();
| private static void | recreate(javax.transaction.xa.Xid xid, int timeout)
if (tim != null) {
tim.recreate(xid, timeout);
}
| private static void | release(javax.transaction.xa.Xid xid)
if (tim != null) {
tim.release(xid);
}
| public void | rollback(javax.transaction.xa.Xid xid)Informs the resource manager to roll back work done on behalf
of a transaction branch.
check(xid); // check if xid is valid
GlobalTID tid = new GlobalTID(xid);
// check for concurrent activity
if (RecoveryManager.readAndUpdateTxMap(tid) == false) {
throw new XAException(XAException.XAER_PROTO);
}
boolean exceptionFlag = false;
int errorCode = XAException.XAER_PROTO;
try {
// First of all make sure it has been recovered if necessary
RecoveryManager.waitForRecovery();
// Look up the Coordinator for the transaction.
TopCoordinator coord = (TopCoordinator)
RecoveryManager.getCoordinator(tid);
if (coord == null) { // error to receive rollback more than once
errorCode = XAException.XAER_PROTO;
throw new XAException(errorCode);
}
// If there is a Coordinator, lock it for the duration of this
// operation. Tell the Coordinator to commit.
synchronized (coord) {
coord.rollback(true);
}
} catch (Throwable exc) {
exceptionFlag = true;
XAException xaExc = new XAException(errorCode);
xaExc.initCause(exc);
throw xaExc;
} finally {
Thread thread = RecoveryManager.removeFromTxMap(tid);
if (thread == null || (thread != Thread.currentThread())) { // error
if (!exceptionFlag) {
throw new XAException(XAException.XAER_RMERR);
}
}
}
|
|