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);
          }
  
          // We need to throw an exception if an attempt is made to open the log when the server is stopping
          if (_serverStopping) {
              Tr.audit(tc, "WTRN0100E: " +
                           "Cannot open SQL RecoveryLog " + _logName + " for server " + _serverName + " as the server is stopping");
              InternalLogException ile = new InternalLogException("Cannot open the log as the server is stopping", null);
              markFailed(ile);
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "openLog", "InternalLogException");
              throw ile;
          }
  
          // The Database Connection
          Connection conn = null;
  
          // If this is the first time the recovery log has been opened during the current server run, then
          // obtain a connection to the underlying DB
          if (_closesRequired == 0) {
              // Allocate the map which holds the RecoverableUnit objects
              _recoverableUnits = new HashMap<Long, RecoverableUnit>();
  
              try {
                  String fullLogDirectory = _internalLogProperties.getProperty("LOG_DIRECTORY");
                  if (tc.isDebugEnabled())
                      Tr.debug(tc, "fullLogDirectory = " + fullLogDirectory);
  
                  if (!fullLogDirectory.contains("datasource")) {
                      // The absence of this string indicates a fully specified JDBC connection string has been specified
                      // by the administrator ** THIS IS RETAINED FOR TESTING PURPOSES ONLY **
                      conn = getConnFromTranLogDirString(fullLogDirectory);
                  } else {
                      // The presence of this string means that a Data Source has been specified
                      conn = getConnection(fullLogDirectory); // DB2 = ny01DS, Oracle = nyoraDS
                  }
  
                  // If we were unable to get a connection, throw an exception
                  if (conn == null) {
                      if (tc.isEntryEnabled())
                          Tr.exit(tc, "openLog", "Null connection InternalLogException");
                      throw new InternalLogException("Failed to get JDBC Connection", null);
                  }
  
                  if (tc.isDebugEnabled())
                      Tr.debug(tc, "Set autocommit FALSE on the connection");
                  conn.setAutoCommit(false);
  
                  //
                  // FIRST PHASE DB PROCESSING: Take HA Lock if possible, create table + HA Lock row if necessary
                  //
                  if (tc.isDebugEnabled())
                      Tr.debug(tc, "create a statement");
                  Statement lockingStmt = conn.createStatement();
  
                  boolean newTable = true;
                  ResultSet lockingRS = null;
                  boolean handleFailover = false;
                  synchronized (_CreateTableLock) // Guard against trying to create a table from multiple threads
                  {
                      int queryRetries = 0;
                      boolean tableCreated = false;
                      Exception excToCheck = null;
                      while (queryRetries < 3) {
                          try {
                              // If this flag is true, then we are assuming an HA DB may have failed over and so we need a new connection
                              if (handleFailover) {
                                  // Try and get a new connection
                                  conn = _theDS.getConnection();
                                  if (tc.isDebugEnabled())
                                      Tr.debug(tc, "Acquired connection in Database retry scenario");
                                  conn.setAutoCommit(false);
                                  lockingStmt = conn.createStatement();
                              }
  
                              // Use RDBMS SELECT FOR UPDATE to lock table for recovery
                              String queryString = "SELECT SERVER_NAME" +
                                                   " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix +
                                                   " WHERE RU_ID=" + "-1 FOR UPDATE";
                              if (tc.isDebugEnabled())
                                  Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE - " + queryString);
                              lockingRS = lockingStmt.executeQuery(queryString);
  
                              // We can do recovery on this rs
                              newTable = false;
                              break;
                          } catch (Exception e) {
                              if (tc.isDebugEnabled())
                                  Tr.debug(tc, "Query failed with exception: " + e);
  
                              // Set the current exception to e
                              excToCheck = e;
  
                              try {
                                  // Perhaps we couldn't find the table ... so attempt to create it
                                  createDBTable(conn);
  
                                  conn.commit();
  
                                  tableCreated = true;
                              } catch (Exception ine) {
                                  if (tc.isDebugEnabled())
                                      Tr.debug(tc, "Table Creation failed with exception: " + ine);
                                  // Set the current exception to ine
                                  excToCheck = ine;
                              }
  
                              // If table creation succeeded then we are done, otherwise retry both the query and the table creation step.
                              if (tableCreated) {
                                  if (tc.isDebugEnabled())
                                      Tr.debug(tc, "Table Creation succeeded");
                                  break;
                              } else {
                                  // Attempt a rollback. If it fails, trace the failure but allow processing to continue
                                  try {
                                      conn.rollback();
                                  } catch (Throwable exc) {
                                      // Trace the exception
                                      if (tc.isDebugEnabled())
                                          Tr.debug(tc, "Rollback Failed, after table creation failure, got exception: " + exc);
                                  }
                                  // The query failed. We'll retry as another process may have been in the process of creating the table.
                                  queryRetries++;
                                  if (tc.isDebugEnabled())
                                      Tr.debug(tc, "Table Creation failed, query retries: " + queryRetries);
                                  if (queryRetries >= 2) {
                                      boolean allowHARetry = false;
  
                                      // We'll go into this block in the case where we are failing but have yet to check for failover
                                      if (!handleFailover) {
                                          if (tc.isDebugEnabled())
                                              Tr.debug(tc, "Have we encounted a DB HA FAilover?");
                                          // We may have encountered a DB HA failover
                                          if (excToCheck instanceof SQLException) {
                                              SQLException sqlex = (SQLException) excToCheck;
                                              if (sqlTransientErrorHandlingEnabled && isSQLErrorTransient(sqlex)) {
                                                  allowHARetry = true;
                                                  // We may have encountered a failover, so reset counters and retry
                                                  queryRetries = 0;
                                                  handleFailover = true;
                                              }
                                          }
                                      }
  
                                      if (!allowHARetry) {
                                          // We are really struggling, we retried in case we were failing to create a table and we have retried
                                          // in case the Database is HA and was failing over. So log an FFDC and rethrow the exception to allow
                                          // the server to "fail to start"
                                          FFDCFilter.processException(excToCheck, "com.ibm.ws.recoverylog.spi.SQLMultiScopeRecoveryLog.openLog", "48", this);
                                          throw excToCheck;
                                      }
                                  } else
                                      Thread.sleep(1000);
                              }
                          }
                      }
                  }
  
                  // If we have not just created the table, then we need to update the HA Lock if we are operating against
                  // another server's recovery logs.
                  if (!newTable) {
                      boolean secondPhaseSuccess = false;
                      SQLException currentSqlEx = null;
                      try {
                          //
                          // SECOND PHASE DB PROCESSING: Update HA Lock row if necessary
                          //
                          updateHADBLock(conn, lockingStmt, lockingRS);
  
                          // We are ready to drive recovery
                          recover(conn);
  
                          conn.commit();
                          secondPhaseSuccess = true;
                      }
                      //NEW CODE FOR DB SWITCH GOES HERE
                      catch (SQLException sqlex) {
                          Tr.audit(tc, "WTRN0107W: " +
                                       "Caught SQLException when opening SQL RecoveryLog " + _logName + " for server " + _serverName + " SQLException: " + sqlex);
                          // Set the exception that will be reported
                          currentSqlEx = sqlex;
                      } finally {
                          if (conn != null) {
                              if (secondPhaseSuccess) {
                                  // Close the connection
                                  conn.close();
                              } else {
                                  // Tidy up connection before dropping into handleOpenLogSQLException method
                                  // Attempt a rollback. If it fails, trace the failure but allow processing to continue
                                  try {
                                      conn.rollback();
                                  } catch (Throwable exc) {
                                      // Trace the exception
                                      if (tc.isDebugEnabled())
                                          Tr.debug(tc, "Rollback Failed, in second phase open log, got exception: " + exc);
                                  }
                                  // Attempt a close. If it fails, trace the failure but allow processing to continue
                                  try {
                                      conn.close();
                                  } catch (Throwable exc) {
                                      // Trace the exception
                                      if (tc.isDebugEnabled())
                                          Tr.debug(tc, "Close Failed, in second phase open log, got exception: " + exc);
                                  }
  
                                  // The following method will set "_nonTransientExceptionAtOpen" if it cannot recover
                                  boolean failAndReport = handleOpenLogSQLException(currentSqlEx);
                                  // We've been through the while loop
                                  if (failAndReport) {
                                      Tr.audit(tc, "WTRN0100E: " +
                                                   "Cannot recover from SQLException when opening SQL RecoveryLog " + _logName + " for server " + _serverName + " Exception: "
                                                   + _nonTransientExceptionAtOpen);
                                      markFailed(_nonTransientExceptionAtOpen);
                                      if (tc.isEntryEnabled())
                                          Tr.exit(tc, "openLog", "InternalLogException");
                                      throw new InternalLogException(_nonTransientExceptionAtOpen);
                                  } else {
                                      Tr.audit(tc, "WTRN0108I: " +
                                                   "Have recovered from SQLException when opening SQL RecoveryLog " + _logName + " for server " + _serverName);
                                  }
  
                              }
                          }
                      }
                  }
  
                  // Ensure that we have closed the DB connection
                  if (conn != null) {
                      if (conn.isClosed()) {
                          if (tc.isDebugEnabled())
                              Tr.debug(tc, "Connection is already closed");
                      } else {
                          if (tc.isDebugEnabled())
                              Tr.debug(tc, "Closing DB Connection");
                          if (_reservedConn == null)
                              conn.close();
                      }
                  } else if (tc.isDebugEnabled())
                      Tr.debug(tc, "Connection was NULL");
              } catch (SQLException exc) {
                  // The code above should have checked if the log is open or not fron the point of view of this class.
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.SQLMultiScopeRecoveryLog.openLog", "464", this);
                  markFailed(exc); /* @MD19484C */
                  _recoverableUnits = null;
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", "InternalLogException");
                  throw new InternalLogException(exc);
              } catch (Throwable exc) {
                  FFDCFilter.processException(exc, "com.ibm.ws.recoverylog.spi.SQLMultiScopeRecoveryLog.openLog", "500", this);
                  if (tc.isEventEnabled())
                      Tr.event(tc, "Unexpected exception caught in openLog", exc);
                  markFailed(exc); /* @MD19484C */
                  _recoverableUnits = null;
  
                  // Output full stack
                  for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
                      if (tc.isDebugEnabled())
                          Tr.debug(tc, " " + ste);
                  }
  
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "openLog", "InternalLogException");
                  throw new InternalLogException(exc);
              }
          }
  
          // 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");
      }