public void run()

in geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/RollbackTask.java [56:150]


    public void run() {
        synchronized (this) {
            status = Status.STATUS_ROLLING_BACK;
        }
        for (int index = 0; index < rms.size(); ) {
            TransactionBranch manager = rms.get(index);
            try {
                try {
                    manager.getCommitter().rollback(manager.getBranchId());
                    remove(index);
                    everRolledBack = true;
                } catch (XAException e) {
                    log.log(Level.SEVERE, "Unexpected exception committing " + manager.getCommitter() + "; continuing to commit other RMs", e);

                    if (e.errorCode >= XAException.XA_RBBASE && e.errorCode <= XAException.XA_RBEND || e.errorCode == XAException.XAER_NOTA) {
                        remove(index);
                        everRolledBack = true;
                    } else if (e.errorCode == XAException.XA_HEURRB) {
                        remove(index);
                        // let's not throw an exception as the transaction has been rolled back
                        log.info("Transaction has been heuristically rolled back");
                        everRolledBack = true;
                        manager.getCommitter().forget(manager.getBranchId());
                    } else if (e.errorCode == XAException.XA_HEURMIX) {
                        remove(index);
                        log.info("Transaction has been heuristically committed and rolled back");
                        everRolledBack = true;
                        cause = e;
                        manager.getCommitter().forget(manager.getBranchId());
                    } else if (e.errorCode == XAException.XA_HEURCOM) {
                        remove(index);
                        log.info("Transaction has been heuristically committed");
                        cause = e;
                        manager.getCommitter().forget(manager.getBranchId());
                    } else if (e.errorCode == XAException.XA_RETRY) {
                        // do nothing, retry later
                        index++;
                    } else if (e.errorCode == XAException.XAER_RMFAIL || e.errorCode == XAException.XAER_RMERR) {
                        //refresh the xa resource from the NamedXAResourceFactory
                        if (manager.getCommitter() instanceof NamedXAResource) {
                            String xaResourceName = manager.getResourceName();
                            NamedXAResourceFactory namedXAResourceFactory = txManager.getNamedXAResourceFactory(xaResourceName);
                            if (namedXAResourceFactory != null) {
                                try {
                                    TransactionBranch newManager = new ReturnableTransactionBranch(manager.getBranchXid(), namedXAResourceFactory);
                                    remove(index);
                                    rms.add(index, newManager);
                                    //loop will try this one again immediately.
                                } catch (SystemException e1) {
                                    //try again later
                                    index++;
                                }
                            } else {
                                //else hope NamedXAResourceFactory reappears soon.
                                index++;
                            }
                        } else {
                            //no hope.  Since we don't record the exception if we do manage to retry stuff later, presumably we shouldn't now, either.
                            remove(index);
                        }
                    } else {
                        //nothing we can do about it
                        remove(index);
                        cause = e;
                    }
                }
            } catch (XAException e) {
                if (e.errorCode == XAException.XAER_NOTA) {
                    // NOTA in response to forget, means the resource already forgot the transaction
                    // ignore
                } else {
                    cause = e;
                }
            }
        }

        if (rms.isEmpty()) {
            try {
                if (logMark != null) {
                    txManager.getTransactionLog().rollback(xid, logMark);
                }
                synchronized (this) {
                    status = Status.STATUS_ROLLEDBACK;
                }
            } catch (LogException e) {
                log.log(Level.SEVERE, "Unexpected exception logging commit completion for xid " + xid, e);
                cause = (XAException) new XAException("Unexpected error logging commit completion for xid " + xid).initCause(e);
            }
        } else {
            synchronized (this) {
                status = Status.STATUS_UNKNOWN;
            }
            txManager.getRetryScheduler().retry(this, count++);
        }
    }