status = Status.STATUS_MARKED_ROLLBACK;
}
if (status == Status.STATUS_MARKED_ROLLBACK) {
rollbackResources(resourceManagers, false);
RollbackException rollbackException = new RollbackException("Unable to commit: transaction marked for rollback");
if (markRollbackCause != null) {
rollbackException.initCause(markRollbackCause);
}
throw rollbackException;
}
synchronized (this) {
if (status == Status.STATUS_ACTIVE) {
if (this.resourceManagers.size() == 0) {
// nothing to commit
status = Status.STATUS_COMMITTED;
} else if (this.resourceManagers.size() == 1) {
// one-phase commit decision
status = Status.STATUS_COMMITTING;
} else {
// start prepare part of two-phase
status = Status.STATUS_PREPARING;
}
}
// resourceManagers is now immutable
}
// no-phase
if (resourceManagers.size() == 0) {
synchronized (this) {
status = Status.STATUS_COMMITTED;
}
return;
}
// one-phase
if (resourceManagers.size() == 1) {
TransactionBranch manager = resourceManagers.getFirst();
commitResource(manager);
return;
}
boolean willCommit = false;
try {
// two-phase
willCommit = internalPrepare();
} catch (SystemException e) {
rollbackResources(resourceManagers, false);
throw e;
}
// notify the RMs
if (willCommit) {
//Re-check whether there are still left resourceMangers, as we might remove those Read-Only Resource in the voting process
if (resourceManagers.size() == 0) {
synchronized (this) {
status = Status.STATUS_COMMITTED;
}
return;
}
commitResources(resourceManagers);
} else {
// set everRollback to true here because the rollback here is caused by
// XAException during the above internalPrepare
rollbackResources(resourceManagers, true);
throw new RollbackException("transaction rolled back due to problems in prepare");
}
} finally {
afterCompletion();
synchronized (this) {
status = Status.STATUS_NO_TRANSACTION;