docs: protected synchronized void checkpoint(long forcedLogSequenceNumber)
                      throws ObjectManagerException
      {
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.entry(this, cclass
                          , "checkpoint"
                          , new Object[] { new Long(forcedLogSequenceNumber), new Boolean(requiresPersistentCheckpoint) });
  
          // TODO If we have a STRATEGY_SAVE_ON_CHECKPOINT store then these objects need to be included here.
          // TODO currently STRATEGY_KEEP_UNTIL_NEXT_OPEN are not saved during a checkpoint.
          // TODO We will also need to track, nonPersistent,Serialized,and Persistent state in order to figure
          // TODO out whether or not to include the transaction in the checkpoint.
  
          // Was data logging required when we started the checkpoint
          // and is it still needed for recovery?
          if (requiresPersistentCheckpoint) {
              // Build subset lists of persistent tokens to recover.
              java.util.List persistentTokensToAdd = new java.util.ArrayList();
              java.util.List persistentTokensToReplace = new java.util.ArrayList();
              java.util.List persistentSerializedBytesToReplace = new java.util.ArrayList();
              java.util.List persistentTokensToOptimisticReplace = new java.util.ArrayList();
              java.util.List persistentTokensToDelete = new java.util.ArrayList();
  
              // Drive checkpoint for each included MangedObject.
              for (java.util.Iterator managedObjectIterator = includedManagedObjects.values().iterator(); managedObjectIterator.hasNext();) {
                  ManagedObject managedObject = (ManagedObject) managedObjectIterator.next();
                  if (managedObject.owningToken.getObjectStore()
                                  .getPersistence()) {
  
                      // Has the last logged update been Forced to disk?
                      // If not the normal log record will be after the start of the chekpoint and it will
                      // cause normal recovery for that ManagedObject.
                      long logSequenceNumber = ((Long) logSequenceNumbers.get(managedObject.owningToken)).longValue();
                      if (forcedLogSequenceNumber >= logSequenceNumber) {
                          // The loggedSerializedBytes we currently have will have had any corrections made at preBackoutTime
                          // incorporated into them, so they are now the correct ones to write to the ObjectStore.
                          ObjectManagerByteArrayOutputStream serializedBytes = (ObjectManagerByteArrayOutputStream) loggedSerializedBytes.get(managedObject.owningToken);
                          long managedObjectSequenceNumber = ((Long) managedObjectSequenceNumbers.get(managedObject.owningToken)).longValue();
                          managedObject.checkpoint(this,
                                                   serializedBytes,
                                                   managedObjectSequenceNumber);
  
                          // Build the lists of objects to log.
  
                          if (managedObject.lockedBy(this)) { // Locking update?
                              switch (managedObject.getState()) {
                                  case ManagedObject.stateAdded:
                                      persistentTokensToAdd.add(managedObject.owningToken);
                                      break;
  
                                  case ManagedObject.stateReplaced:
                                      persistentTokensToReplace.add(managedObject.owningToken);
                                      // We have to rewrite the replaced serialized bytes in the log as part of the checkpoint.
                                      persistentSerializedBytesToReplace.add(serializedBytes);
                                      break;
  
                                  case ManagedObject.stateToBeDeleted:
                                      persistentTokensToDelete.add(managedObject.owningToken);
                                      break;
                              } // switch.
  
                          } else { // OptimisticReplace update.
                              // A bit pointless as we dont do anything at recovery time.
                              persistentTokensToOptimisticReplace.add(managedObject.owningToken);
                          } // if (lockedBy(transaction)).
  
                      } // if (forcedLogSequenceNumber >= logSequenceNumber).
                  } // if (managedObject.owningToken.getObjectStore().getPersistence()).
              } // for ... includedMansagedObjects.
  
              // The state indicates if the transaction is prepared, commiting or backing out.
              TransactionCheckpointLogRecord transactionCheckpointLogRecord = new TransactionCheckpointLogRecord(this,
                                                                                                                 persistentTokensToAdd,
                                                                                                                 persistentTokensToReplace,
                                                                                                                 persistentSerializedBytesToReplace,
                                                                                                                 persistentTokensToOptimisticReplace,
                                                                                                                 persistentTokensToDelete,
                                                                                                                 allPersistentTokensToNotify);
  
              // TODO Could correct any overestimate of the reserved log file space here.
              // We previously reserved some log space for this logRecord to be sure it will fit in the log.
              // We do not release it here because w reserved an extra page which we might not be able to get back after the
              // checkpoint has completed. Instead we just supress the check on the space used in the log.
              objectManagerState.logOutput.writeNext(transactionCheckpointLogRecord,
                                                     0,
                                                     false
                                                     , false);
  
              requiresPersistentCheckpoint = false;
          } // if (requiresPersistentCheckpoint).
  
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.exit(this, cclass
                         , "checkpoint"
                              );
      }