docs: public int prepare() throws ProtocolException, RollbackException, SeverePersistenceException, TransactionException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "prepare");
  
          // Check the current transaction state (use state lock to ensure we see the latest value)
          synchronized (_stateLock)
          {
              if (_state != TransactionState.STATE_ACTIVE)
              {
                  ProtocolException pe = new ProtocolException("TRAN_PROTOCOL_ERROR_SIMS1001", new Object[]{});
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Cannot prepare Transaction. Transaction is complete or completing!", pe);
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare");
                  throw pe;
              }
  
              // Transition our prepare sub-state immediately - before we call the callbacks
              _preCommitSubstate = TransactionState.STATE_PREPARING;
          }
  
          // PK81848
          // From this point on, we must perform a rollback if we fail to complete the prepare,
          // or another thread requests a deferred rollback
          try
          {
              // Call beforeCompletion on MP callback
              for (int i = 0; i < _callbacks.size(); i++)
              {
                  TransactionCallback callback = (TransactionCallback) _callbacks.get(i);
                  callback.beforeCompletion(this);
              }
  
              // Do we have work to do?
              if (_workList != null)
              {
                  _workList.preCommit(this);
  
                  synchronized (_stateLock)
                  {
                      // Need to change the overalll state after we have 
                      // called the callbacks and preCommitted 
                      // the workList as they may trigger
                      // an addWork call to add work to the
                      // transaction.
                      _state = TransactionState.STATE_PREPARING;
                  }
  
                  // The transaction is about to be in a state where any rollback must
                  // update the database.  We cannot narrow the window any more than this
                  _rollbackChanges = true;
                  
                  // Perform the prepare
                  _persistence.prepare(this);
  
                  // State check/change must be performed holding the state lock
                  synchronized (_stateLock)
                  {
                      // Another thread may have have received a rollback, while we were
                      // performing our prepare - if the database was extremely slow to respond
                      if (_preCommitSubstate == TransactionState.STATE_ROLLBACK_DEFERRED)
                      {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.event(this, tc, "Deferred rollback requested during prepare for TranId: "+_ptid);
  
                          // Throw an exception to trigger rollback processing.
                          throw new DeferredRollbackException();
                      }
                      else
                      {
                          _state = _preCommitSubstate = TransactionState.STATE_PREPARED;
                      }
                  }                
              }
              else
              {
                  // State change must be performed holding the state lock
                  synchronized (_stateLock)
                  {
                      // Defect 301480
                      // We don't have any work in our workList so in theory we should be
                      // able to vote READ_ONLY at this point. However in a particular case
                      // (Best Effort message being sent off server) a call back in an empty
                      // XAResource is used to trigger work on a remote server. In this case 
                      // we need beforeCompletion AND afterCompletion to be called at the 
                      // CORRECT time during transaction completion to ensure that the off 
                      // server work stays part of the XA transaction and gets informed of 
                      // the correct completion direction.
                      _state = _preCommitSubstate = TransactionState.STATE_PREPARED;
                  }
              }
          }
          catch (SeverePersistenceException spe)
          {
              // SPE exceptions are handled with an RMFAIL return code by the caller,
              // so unlike all other types of exception no attempt is made here to
              // rollback the transaction. However, we report a local error - so
              // the whole JVM will be coming down with a few minutes.
              com.ibm.ws.ffdc.FFDCFilter.processException(spe, "com.ibm.ws.sib.msgstore.transactions.XidParticipant.prepare", "1:420: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 prepare phase of transaction!", spe);
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare", spe);
              throw spe;
          }
          // 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.prepare", "1:436:1.73", this);
              if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Transaction will roll-back due to Exception in prepare!", e);
  
              // Update our prepare state before calling rollback. If we are responding
              // to a deferred rollback request this will have no affect but if this is 
              // due to some other failure it will lock out any other attempts to rollback
              synchronized (_stateLock)
              {
                  _preCommitSubstate = TransactionState.STATE_ROLLINGBACK;
              }
  
              // An error has occurred but we are able to keep the ME
              // going so we just need to clean up this transaction.
              try
              {
                  // When we throw our RollbackException the TM is
                  // going to assume we are complete so we need to 
                  // ensure we are rolled-back.
                  // 
                  // PK81848.2
                  // We need to pass "true" in order to turn off the
                  // state checking which should block other threads 
                  // from attempting a rollback when we are in the 
                  // middle of internal rollback processing.
                  rollback(true);
              }
              // Catch and handle all exceptions but allow 
              // Errors to filter up without interference
              catch (Exception e2)
              {
                  com.ibm.ws.ffdc.FFDCFilter.processException(e2, "com.ibm.ws.sib.msgstore.transactions.XIDParticipant.prepare", "1:466:1.73", this);
                  
                  // This is a problem because we now must RMFAIL this prepare call as we do not know the outcome.
                  // Transition to rollback expected state now even if we are in deferred rollback.  This is the
                  // only thing we can do (problem is we said XA_OK to roll back in deferred case and now we
                  // cannot honour it).  This case may still leave indoubts.
                  synchronized(_stateLock)
                  {
                      _state = _preCommitSubstate = TransactionState.STATE_ROLLBACK_EXPECTED;
                  }
                  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare", "Exception caught rolling-back transaction after preCommit failure! " + e2);
                  throw new TransactionException(e2);
              }
  
              // Mark ourselves as complete, regardless of the outcome of the attempt to rollback.
              synchronized (_stateLock)
              {
                  _state = _preCommitSubstate = TransactionState.STATE_ROLLEDBACK;
              }
  
              // Wrap any persistence exception, or an unexpected exception, in a rollback exception.
              // This informs the TM that they can forget about this transaction.
              RollbackException re = new RollbackException("COMPLETION_EXCEPTION_SIMS1002", new Object[]{e}, e);
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare", re);
              throw re;
          }
  
          // Non-exception return path always returns XA_OK
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare", "return="+XAResource.XA_OK);
          return XAResource.XA_OK;
      }