private boolean internalPrepare()

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;
    }