in geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java [419:478]
private boolean internalPrepare() throws SystemException {
for (Iterator rms = resourceManagers.iterator(); rms.hasNext();) {
synchronized (this) {
if (status != Status.STATUS_PREPARING) {
// we were marked for rollback
break;
}
}
TransactionBranch manager = (TransactionBranch) rms.next();
try {
int vote = manager.getCommitter().prepare(manager.getBranchId());
if (vote == XAResource.XA_RDONLY) {
// we don't need to consider this RM any more
rms.remove();
}
} catch (XAException e) {
if (e.errorCode == XAException.XAER_RMERR
|| e.errorCode == XAException.XAER_PROTO
|| e.errorCode == XAException.XAER_INVAL) {
throw (SystemException) new SystemException("Error during prepare; transaction was rolled back").initCause(e);
}
synchronized (this) {
markRollbackCause(e);
status = Status.STATUS_MARKED_ROLLBACK;
/* 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;
}
}
}
// decision time...
boolean willCommit;
synchronized (this) {
willCommit = (status != Status.STATUS_MARKED_ROLLBACK);
if (willCommit) {
status = Status.STATUS_PREPARED;
}
}
// log our decision
if (willCommit && !resourceManagers.isEmpty()) {
try {
logMark = txManager.getTransactionLog().prepare(xid, resourceManagers);
} catch (LogException e) {
try {
rollbackResources(resourceManagers, false);
} catch (Exception se) {
log.log(Level.SEVERE, "Unable to rollback after failure to log prepare", se.getCause());
}
throw (SystemException) new SystemException("Error logging prepare; transaction was rolled back)").initCause(e);
}
}
return willCommit;
}