docs: 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");
          }
      }