docs: @Override
      public synchronized void openLog() throws LogCorruptedException, LogAllocationException,
                      InternalLogException, LogIncompatibleException
      {
          if (tc.isEntryEnabled())
              Tr.entry(tc, "openLog", this);
  
          // If this recovery log instance has been marked as incompatible then throw an exception
          // accordingly.
          if (incompatible())
          {
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "openLog", "LogIncompatibleException");
              throw new LogIncompatibleException();
          }
  
          // If this recovery log instance has experienced a serious internal error then prevent this operation from
          // executing.
          if (failed())
          {
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "openLog", "InternalLogException");
              throw new InternalLogException(null);
          }
  
          // If this is the first time the recovery log has been opened during the current server run, then
          // allocate a new LogHandle to manage the underlying recovery log and retrieve the information stored
          // on disk, otherwise just return directly to the caller (after incrementing the closes required counter)
          if (_logHandle == null)
          {
              // Create the LogHandle which will manage the physical log files.
              _logHandle = new LogHandle(this, _clientName, _clientVersion, _serverName, _logName, _logDirectory, _logFileSize, _maxLogFileSize, _failureScope);
  
              // Allocate the map which holds the RecoverableUnit objects
              _recoverableUnits = new HashMap<Long, RecoverableUnit>();
  
              try
              {
                  // Open the log and restore the logged objects. As long as the basic header information at the front of the 
                  // target log file is formatted correctly, the code behind openLog will tollerate a single corruption at any
                  // point through the reload process. If a corruption is detected then the read will stop and recovery will
                  // take place with the information read upto that point. The rational behind this is that the recovery log
                  // is designed to cope with corruption that occurs due to a system failure (eg power failure) where the corrption
                  // will actually occur at the end of the file. In this case the code which attempted to force the data to
                  // disk will not have regained control, so it is safe to ignore the corrupted data. The recovery log is
                  // NOT designed to be able to recovery if arbitary corrption (eg user has damaged the file manually) has
                  // occured. In such cases the recovery log will not open and this method will generate a LogCorruptedException
                  // exception.
                  _logHandle.openLog();
              } catch (LogOpenException exc)
              {
                  // The code above should have checked if the log is open or not fron the point of view of this class.
                  // If the LogHandle thinks the log is open but this class does not then they have become out of step
                  // and this represents an internal recovery log failure.
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "464", this);
                  markFailed(exc); /* @MD19484C */
                  _logHandle = null;
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", "InternalLogException");
                  throw new InternalLogException(exc);
              } catch (LogCorruptedException exc)
              {
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "473", this);
                  markFailed(exc); /* @MD19484C */
                  _logHandle = null;
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", exc);
                  throw exc;
              } catch (LogIncompatibleException exc)
              {
                  // No FFDC code needed
                  // This specific failure type where a recovery log has been found to be incompatible
                  // with this version of the RLS is most likely to occur in an HA enabled environment
                  // where there are other servers in the cluster that are from a down-level websphere
                  // product. For example 5.1 and 6.0 servers in the same cluster. When a 6.0 server
                  // attempts to peer recover the 5.1 log (as will be the case since the 5.1 server
                  // will not join an HA group get ownership of its recovery logs) a
                  // LogIncompatibleException will be generated. To try and avoid confusion, this is 
                  // logged in a single place only (in the trace - to be replaced with messages asap)
                  // Additionally, no FFDC is generated.
                  //
                  // Clearly, this is somewhat in conflict with the reporting of errors when a recovery
                  // log from an older WS install is manually recovered on newer WS install (not supported
                  // anyway). The HA issues above are deemed to be more important.
                  markIncompatible();
                  _logHandle = null;
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", exc);
                  throw exc;
              } catch (LogAllocationException exc)
              {
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "482", this);
                  markFailed(exc); /* @MD19484C */
                  _logHandle = null;
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", exc);
                  throw exc;
              } catch (InternalLogException exc)
              {
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "491", this);
                  markFailed(exc); /* @MD19484C */
                  _logHandle = null;
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", exc);
                  throw exc;
              } catch (Throwable exc)
              {
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "500", this);
                  if (tc.isEventEnabled())
                      Tr.event(tc, "Unexpected exception caught in openLog", exc);
                  markFailed(exc); /* @MD19484C */
                  _logHandle = null;
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", "InternalLogException");
                  throw new InternalLogException(exc);
              }
  
              // Obtain a list of recovered RecoverableUnits
              final ArrayList<ReadableLogRecord> records = _logHandle.recoveredRecords();
  
              if ((records != null) && (records.size() > 0))
              {
                  try
                  {
                      if (tc.isDebugEnabled())
                          Tr.debug(tc, "MultiScopeRecoveryLog " + _logName + " contains " + records.size() + " records to recover");
  
                      // Process each recovered record and rebuild the objects it represents
                      for (int i = 0; i < records.size(); i++)
                      {
                          final ReadableLogRecord record = records.get(i);
  
                          if (tc.isDebugEnabled())
                              Tr.debug(tc, "Recovering record " + i);
  
                          RecoverableUnitImpl.recover(this, record, _logHandle, _storageMode, _controlLock);
  
                      }
                  } catch (LogCorruptedException exc)
                  {
                      FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "531", this);
                      markFailed(exc); /* @MD19484C */
                      _logHandle = null;
                      _recoverableUnits = null;
                      if (tc.isDebugEnabled())
                          Tr.debug(tc, "A LogCorruptedException exception occured when reconstructng a RecoverableUnit");
                      if (tc.isEntryEnabled())
                          Tr.exit(tc, "openLog", exc);
                      throw exc;
                  } catch (InternalLogException exc)
                  {
                      FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "541", this);
                      markFailed(exc); /* @MD19484C */
                      _logHandle = null;
                      _recoverableUnits = null;
                      if (tc.isDebugEnabled())
                          Tr.debug(tc, "An InternalLogException exception occured when reconstructng a RecoverableUnit");
                      if (tc.isEntryEnabled())
                          Tr.exit(tc, "openLog", exc);
                      throw exc;
                  } catch (Throwable exc)
                  {
                      FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.MultiScopeRecoveryLog.openLog", "551", this);
                      markFailed(exc); /* @MD19484C */
                      _logHandle = null;
                      _recoverableUnits = null;
                      if (tc.isDebugEnabled())
                          Tr.debug(tc, "An exception occured reconstructng a RecoverableUnit", exc);
                      if (tc.isEntryEnabled())
                          Tr.exit(tc, "openLog", "InternalLogException");
                      throw new InternalLogException(exc);
                  }
              }
              else
              {
                  if (tc.isDebugEnabled())
                      Tr.debug(tc, "MultiScopeRecoveryLog " + _logName + " is empty");
              }
          }
  
          // In light of this open operation, the caller will need to issue an additional close operation to fully close
          // the recovey log.
          _closesRequired++;
  
          if (tc.isDebugEnabled())
              Tr.debug(tc, "Closes required: " + _closesRequired);
  
          if (tc.isEntryEnabled())
              Tr.exit(tc, "openLog");
      }