use of com.arjuna.ats.internal.jts.recovery.recoverycoordinators.ResourceCompletor in project narayana by jbosstm.
the class GenericRecoveryCoordinator method replay_completion.
/**
* Respond to a replay_completion request for the RecoveryCoordinator
* identified by parameter id.
*/
protected static Status replay_completion(RecoveryCoordinatorId id, Resource res) throws SystemException, NotPrepared {
if (jtsLogger.logger.isDebugEnabled()) {
jtsLogger.logger.debug("GenericRecoveryCoordinator(" + id._RCUid + ").replay_completion(" + (res != null ? "resource supplied)" : "null resource)"));
}
Status currentStatus = Status.StatusUnknown;
/*
* First check to see if the transaction is active by asking the
* per-process contact.
* If alive, return the status reported by the
* transaction. If not alive then try and recover the
* transaction from the intentions list.
*/
boolean transactionActive = true;
try {
currentStatus = get_status(id._actionUid, id._originalProcessUid);
} catch (Inactive e) {
// original process is dead.
transactionActive = false;
}
if (currentStatus == Status.StatusNoTransaction) {
/*
* There is no intentions list, so the transaction either
* committed or rolled back. However, this routine is only
* ever called by replay_completion, which means that there
* is a resource (hopefully one which was participating in
* the transaction) that is in doubt as to the
* transaction's outcome. If the transaction had committed,
* then this resource would know of the outcome. Therefore,
* it must have rolled back!
*/
/*
* Unfortunately the last statement is wrong. There is a timing
* issue here: the resource recovery may be doing an upcall while
* the downcall (from coordinator recovery) is going on and
* removing the log. What can then happen is that a resource may
* see a commit folled by a rollback.
*/
currentStatus = Status.StatusRolledBack;
}
if (!transactionActive) {
// original process is dead, so reasonable for us to try to
// recover
/*
* The RecoveredTransactionReplayer is a threaded object
* so we can get the status and return it while the
* replayer does the phase 2 commit in a new thread.
*/
String tranType = ((id._isServerTransaction) ? ServerTransaction.typeName() : ArjunaTransactionImple.typeName());
try {
if (id._isServerTransaction && (StoreManager.getRecoveryStore().currentState(id._actionUid, ServerTransaction.typeName() + "/JCA") != StateStatus.OS_UNKNOWN)) {
tranType = tranType + "/JCA";
}
} catch (ObjectStoreException e) {
// Can't read store
}
com.arjuna.ats.internal.jts.recovery.transactions.RecoveredTransactionReplayer replayer = new com.arjuna.ats.internal.jts.recovery.transactions.RecoveredTransactionReplayer(id._actionUid, tranType);
// this will cause the activatation attempt
currentStatus = replayer.getStatus();
if ((replayer.getRecoveryStatus() != com.arjuna.ats.internal.jts.recovery.transactions.RecoveryStatus.ACTIVATE_FAILED) && (res != null)) {
if (jtsLogger.logger.isDebugEnabled()) {
jtsLogger.logger.debug("GenericRecoveryCoordinator - swapping Resource for RC " + id._RCUid);
}
replayer.swapResource(id._RCUid, res);
}
if (replayer.getRecoveryStatus() != com.arjuna.ats.internal.jts.recovery.transactions.RecoveryStatus.ACTIVATE_FAILED) {
replayer.replayPhase2();
} else {
replayer.tidyup();
/*
* The transaction didn't activate so we have a
* rollback situation but we can't rollback the
* resource that we have been given through the
* intentions list but we can issue rollback
* directly. This is configurable through the System
* properties.
*/
currentStatus = Status.StatusRolledBack;
}
}
if (currentStatus == Status.StatusRolledBack) {
if (_issueRecoveryRollback) {
ResourceCompletor resourceCompletor = new ResourceCompletor(res, ResourceCompletor.ROLLBACK);
resourceCompletor.start();
}
}
if (currentStatus == Status.StatusActive)
throw new NotPrepared();
return currentStatus;
}
Aggregations