private void rollback(boolean internal) throws ProtocolException, SeverePersistenceException, TransactionException, PersistenceException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "rollback", "internal="+internal);

        // State check/change must be performed holding the state lock
        synchronized (_stateLock)
        {
            // For XA tranasctions, we accept a rollback on any thread, at any time until the point
            // we have begun commit processing. The XA spec says we must be able to rollback until we
            // have successfully committed. Hence it could be argued that we should still be able
            // to accept a rollback while in committing states. However, it is beyond the scope of
            // PK81848 (which adds the committing checks) to address that.

            if (!internal && _state != TransactionState.STATE_ROLLBACK_EXPECTED)
            {
                // It is worth noting in these state checks that once the transition into ROLLBACK_DEFERRED
                // has taken place a succesful return from rollback will follow and therefore no further 
                // attempts should be made. In case we get really unlucky however and have multiple threads
                // calling rollback at once the preCommit states should be checked for also.
                if ((_state == TransactionState.STATE_COMMITTED) ||                     // Tran has committed
                    (_state == TransactionState.STATE_ROLLEDBACK) ||                    // Tran has rolled back
                    (_state == TransactionState.STATE_COMMITTING_1PC) ||                // Tran has started one-phase commit
                    (_state == TransactionState.STATE_COMMITTING_2PC) ||                // Tran has started two-phase commit
                    (_preCommitSubstate == TransactionState.STATE_ROLLBACK_DEFERRED) || // Rollback has been deferred and is awaiting prepare thread
                    (_preCommitSubstate == TransactionState.STATE_ROLLINGBACK))         // Prepare thread has is processing the deferred rollback
                {
                    ProtocolException pe = new ProtocolException("TRAN_PROTOCOL_ERROR_SIMS1001", new Object[]{});
                    if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Cannot rollback Transaction. Transaction is not in a valid state: _state="+_state+", _preCommitSubstate="+_preCommitSubstate, pe);
                    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "rollback");
                    throw pe;
                }
            }

            // If another thread is currently preparing this transaction, then we cannot safely
            // perform the rollback - even though it's a valid XA transition.
            // As such, we change the state to deferred rollback, and leave the preparing
            // thread to perform the rollback and throw XA_RBROLLBACK to the caller of prepare.
            // Holding the _stateLock allows us to ensure that the rollback will occur, as the
            // preparing thread must take this lock and check for the state before it returns.
            // This does mean we will be returning from the rollback before the work of the rollback
            // has completed. This is an interpretation of the spec, based on our inabillty
            // to honor "xa_rollback() must not itself be susceptible to indefinite blocking" with
            // an external database that is outside of our control.
            if (_preCommitSubstate == TransactionState.STATE_PREPARING)
            {
                _preCommitSubstate = TransactionState.STATE_ROLLBACK_DEFERRED;

                // Return immediately, with good completion
                if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Deferred rollback request accepted for TranId: "+_ptid);
                if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "rollback", "STATE_ROLLBACK_DEFERRED");
                return;
            }
            else
            {
                _state = TransactionState.STATE_ROLLINGBACK;
            }
        }

        try
        {
            // Peek the current values of our state variables, and drop the lock before making any calls
            boolean rollbackChanges;
            boolean indoubt;
            synchronized (_stateLock)
            {
                rollbackChanges = _rollbackChanges;
                indoubt         = _indoubt;
            }
            // Do we have work to do?
            if (_workList != null)
            {
                if (rollbackChanges)
                {
                    // We need to rollback the persistence layer as
                    // work will have been committed to the database
                    // in the prepare stage.
                    _persistence.rollback(this);
                }

                _workList.rollback(this);
            }
            else if (_workList == null && indoubt)
            {
                // Defect 572430
                // If this transaction is a recovered in-doubt and its work
                // list is null then it will have contained aysnchronous
                // persistent work at prepare time. As a result of an ME
                // failure the asynchronous work did not have time to be 
                // written to the database. However as the write of the 
                // row to the tran table is synchronous we will have a 
                // transaction to clean up.
                _persistence.rollback(this);
            }

            if (indoubt)
            {
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Indoubt transaction completed successfully. TranId="+_ptid);
            }

            // State change must be performed holding the state lock
            synchronized (_stateLock)
            {
                _state = TransactionState.STATE_ROLLEDBACK;
            }
        }
        catch (SeverePersistenceException spe)
        {
            com.ibm.ws.ffdc.FFDCFilter.processException(spe, "com.ibm.ws.sib.msgstore.transactions.XidParticipant.rollback", "1:896:1.73", this);

            // As we have thrown a severe exception we need to inform
            // the ME that this instance is no longer able to continue.
            if (_ms != null)
            {
                _ms.reportLocalError();
            }

            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Unrecoverable persistence exception caught during rollback phase of transaction!", spe);
            throw spe;
        }
        catch (PersistenceException pe)
        {
            com.ibm.ws.ffdc.FFDCFilter.processException(pe, "com.ibm.ws.sib.msgstore.transactions.XidParticipant.rollback", "1:910:1.73", this);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Persistence exception caught during rollback phase of transaction!", pe);
            throw pe;
        }
        // Catch and handle all exceptions but allow 
        // Errors to filter up without interference
        catch (Exception e) 
        {
            com.ibm.ws.ffdc.FFDCFilter.processException(e, "com.ibm.ws.sib.msgstore.transactions.XidParticipant.rollback", "1:918:1.73", this);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Unexpected exception caught during rollback phase of transaction!", e);
            throw new TransactionException("COMPLETION_EXCEPTION_SIMS1002", new Object[]{e}, e);
        }
        finally
        {
            // Peek the current transaction state and drop the lock before making any calls
            TransactionState state;
            synchronized (_stateLock)
            {
                state = _state;
            }

            if (state == TransactionState.STATE_ROLLEDBACK)
            {
                // Defect 316887
                try
                {
                    if (_workList != null)
                    {
                        _workList.postComplete(this, false);
                    }

                    for (int i = 0; i < _callbacks.size(); i++)
                    {
                        TransactionCallback callback = (TransactionCallback) _callbacks.get(i);
                        callback.afterCompletion(this, false);
                    }
                }
                // Catch and handle all exceptions but allow 
                // Errors to filter up without interference
                catch (Exception e)
                {
                    com.ibm.ws.ffdc.FFDCFilter.processException(e, "com.ibm.ws.sib.msgstore.transactions.XidParticipant.commit", "1:951:1.73", this);
                    if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Exception caught during post commit phase of transaction!", e);
                    // We aren't going to rethrow this exception as if
                    // a previous exception has been thrown outside the 
                    // finally block it is likely to have more 
                    // information about the root problem.
                }
            }

            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "rollback");
        }
    }
private void rollback ( boolean internal ) throws ProtocolException , SeverePersistenceException , TransactionException , PersistenceException { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . entry ( this , tc , "rollback" , "internal=" + internal ) ; synchronized ( _stateLock ) { if ( ! internal && _state != TransactionState . STATE_ROLLBACK_EXPECTED ) { if ( ( _state == TransactionState . STATE_COMMITTED ) || ( _state == TransactionState . STATE_ROLLEDBACK ) || ( _state == TransactionState . STATE_COMMITTING_1PC ) || ( _state == TransactionState . STATE_COMMITTING_2PC ) || ( _preCommitSubstate == TransactionState . STATE_ROLLBACK_DEFERRED ) || ( _preCommitSubstate == TransactionState . STATE_ROLLINGBACK ) ) { ProtocolException pe = new ProtocolException ( "TRAN_PROTOCOL_ERROR_SIMS1001" , new Object [ ] { } ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . event ( this , tc , "Cannot rollback Transaction. Transaction is not in a valid state: _state=" + _state + ", _preCommitSubstate=" + _preCommitSubstate , pe ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . exit ( this , tc , "rollback" ) ; throw pe ; } } if ( _preCommitSubstate == TransactionState . STATE_PREPARING ) { _preCommitSubstate = TransactionState . STATE_ROLLBACK_DEFERRED ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . event ( this , tc , "Deferred rollback request accepted for TranId: " + _ptid ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . exit ( this , tc , "rollback" , "STATE_ROLLBACK_DEFERRED" ) ; return ; } else { _state = TransactionState . STATE_ROLLINGBACK ; } } try { boolean rollbackChanges ; boolean indoubt ; synchronized ( _stateLock ) { rollbackChanges = _rollbackChanges ; indoubt = _indoubt ; } if ( _workList != null ) { if ( rollbackChanges ) { _persistence . rollback ( this ) ; } _workList . rollback ( this ) ; } else if ( _workList == null && indoubt ) { _persistence . rollback ( this ) ; } if ( indoubt ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "Indoubt transaction completed successfully. TranId=" + _ptid ) ; } synchronized ( _stateLock ) { _state = TransactionState . STATE_ROLLEDBACK ; } } catch ( SeverePersistenceException spe ) { com . ibm . ws . ffdc . FFDCFilter . processException ( spe , "com.ibm.ws.sib.msgstore.transactions.XidParticipant.rollback" , "1:896:1.73" , this ) ; if ( _ms != null ) { _ms . reportLocalError ( ) ; } if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . event ( this , tc , "Unrecoverable persistence exception caught during rollback phase of transaction!" , spe ) ; throw spe ; } catch ( PersistenceException pe ) { com . ibm . ws . ffdc . FFDCFilter . processException ( pe , "com.ibm.ws.sib.msgstore.transactions.XidParticipant.rollback" , "1:910:1.73" , this ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . event ( this , tc , "Persistence exception caught during rollback phase of transaction!" , pe ) ; throw pe ; } catch ( Exception e ) { com . ibm . ws . ffdc . FFDCFilter . processException ( e , "com.ibm.ws.sib.msgstore.transactions.XidParticipant.rollback" , "1:918:1.73" , this ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . event ( this , tc , "Unexpected exception caught during rollback phase of transaction!" , e ) ; throw new TransactionException ( "COMPLETION_EXCEPTION_SIMS1002" , new Object [ ] { e } , e ) ; } finally { TransactionState state ; synchronized ( _stateLock ) { state = _state ; } if ( state == TransactionState . STATE_ROLLEDBACK ) { try { if ( _workList != null ) { _workList . postComplete ( this , false ) ; } for ( int i = 0 ; i < _callbacks . size ( ) ; i ++ ) { TransactionCallback callback = ( TransactionCallback ) _callbacks . get ( i ) ; callback . afterCompletion ( this , false ) ; } } catch ( Exception e ) { com . ibm . ws . ffdc . FFDCFilter . processException ( e , "com.ibm.ws.sib.msgstore.transactions.XidParticipant.commit" , "1:951:1.73" , this ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . event ( this , tc , "Exception caught during post commit phase of transaction!" , e ) ; } } if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . exit ( this , tc , "rollback" ) ; } }
it would not pass the state check.