docs: private final void performRecovery(LogInput logInput)
                      throws ObjectManagerException {
          final String methodName = "performRecovery";
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.entry(this,
                          cclass,
                          methodName,
                          new Object[] { logInput });
  
          // Set no checkpoint end yest seen.
          checkpointEndSeen = false;
          // We start reading the log at the start of the last complete checkpoint.
          // The checkpointed and in flight transactions are recovered until we find checkpoint end.
  
          try {
              for (;;) { // Loop over input log records.
                  LogRecord logRecordRead = logInput.readNext();
                  logRecordRead.performRecovery(this);
              } // for log records to read.
  
          } catch (LogFileExhaustedException exception) {
              // No FFDC Code Needed, condition expected when end of log seen.
              if (Tracing.isAnyTracingEnabled() && trace.isEventEnabled())
                  trace.event(this,
                              cclass,
                              methodName,
                              exception);
  
          } catch (ObjectManagerException exception) {
              // No FFDC Code Needed.
              ObjectManager.ffdc.processException(this,
                                                  cclass,
                                                  methodName,
                                                  exception,
                                                  "1:751:1.62");
  
              shutdown();
              if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                  trace.exit(this,
                             cclass,
                             methodName,
                             "ObjectManagerException:758");
              throw exception;
          } // try.
  
          // Have wee seen a completed checkpoint?
          if (checkpointEndSeen == false) {
              // TODO At cold start, we need to mark the log header so that it indicates that we have not yet
              //      completed the first ever checkpoint. If we fail before we do this we then know
              //      that we crashed before it is rewritten, we can safely have another go at writing it
              //      another first checkpoint. We could just assume that because we have not seen
              //      a checkpoint end then we did not successfully cold start and have another go.
              shutdown();
              if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                  trace.exit(this,
                             cclass,
                             methodName,
                             new Object[] { "CheckpointEndNotFoundException:774", logFileName });
              throw new CheckpointEndNotFoundException(this,
                                                       logFileName);
          }
  
          synchronized (this) {
              // Make the state change.
              setState(nextStateForLogReplayed);
          } // synchronized (this).
  
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.exit(this,
                         cclass,
                         methodName);
      }