docs: protected void backout(Transaction transaction,
                             long savedSequenceNumber,
                             boolean requiresCurrentCheckpoint)
                      throws ObjectManagerException {
          final String methodName = "backout";
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.entry(this, cclass, methodName, new Object[] { transaction,
                                                                  new Boolean(requiresCurrentCheckpoint) });
  
          // No need to synchronize when we copy the entry state as only the locking transaction can cause a state change.
          int entryState = state;
          setState(nextStateForBackout); // Make the state change.
  
          // Revert to the original state of the object in its store and in memory.
          // We do this only after the add/replace/delete records has been written and forced
          // to the log as part of backout processing.
          switch (entryState) {
              case stateAdded:
              case stateMustBeDeleted:
                  // Remove the allocated or added object from its object store.
                  // An optimistic update could have already replaced this even though this
                  // transaction has not done its add as part of commit. The optimistic logic must 
                  // be cope with this eventuality.  
                  // Similarly a checkpoint could have written the object to the ObjectStore.
                  // Make sure another thread does not come along with old information later on.
                  // Taking the forcedUpdateSequenceLock, ensures that any OptimisticReplace 
                  // updates see our state is now deleted.
                  int tempLatestSerializedSize;
                  synchronized (forcedUpdateSequenceLock) {
                      if (savedSequenceNumber > forcedUpdateSequence) {
                          forcedUpdateSequence = savedSequenceNumber;
                          // latestSerializedBytes might be null if they have been written by the store.
                          if (latestSerializedBytes != null) {
                              owningToken.objectStore.getObjectManagerState().returnByteArrayOutputStreamToPool(latestSerializedBytes);
                              latestSerializedBytes = null;
                          } // if (latestSerializedBytes != null).
                      } // if (savedSequenceNumber > forcedUpdateSequence).
  
                      owningToken.objectStore.remove(owningToken,
                                                     requiresCurrentCheckpoint);
                      tempLatestSerializedSize = latestSerializedSize;
                      latestSerializedSize = 0;
                  } // synchronized (forcedUpdateSequenceLock).
                    // following statement moved out of lock in PM41418 to prevent deadlock
                  owningToken.objectStore.reserve(-tempLatestSerializedSize, false);
                  break;
  
              case stateReplaced:
                  // Put this object back the way it was. 
                  backingOut = true;
                  becomeCloneOf(beforeImmage);
                  backingOut = false;
                  break;
  
          // case stateToBeDeleted:
          // Nothing to do if we were going to delete the ManagedObject, since we have backed out
          // we simply dont delete it.  
          } // switch.
  
          beforeImmage = null; // Help garbage collector.
          numberOfLocksTaken = 0;
  
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.exit(this, cclass, methodName);
      }