docs: @Override
      public RecoveryLogManager registerService(RecoveryAgent recoveryAgent, int sequence) throws ConflictingCredentialsException, InvalidStateException {
          if (tc.isEntryEnabled())
              Tr.entry(tc, "registerService", new Object[] { recoveryAgent, new Integer(sequence), this });
  
          RecoveryLogManager clientRLM = null;
  
          // Synchronize on the _registeredRecoveryAgents map since we may have cocurrent registrations
          // taking place.
          synchronized (_registeredRecoveryAgents) {
              // Ensure that this registration event is occuring prior to the first recovery cycle. Throw an exception if its not.
              // This check is required to ensure that recovery agents do not register late and miss recovery processing events.
              if (!_registrationAllowed) {
                  if (tc.isEventEnabled())
                      Tr.event(tc, "Client service registration attempted after recovery processing has been driven");
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "registerService", "InvalidStateException");
                  throw new InvalidStateException(null);
              }
  
              // Ensure that the supplied RecoveryAgent supplies a unique identity and name.
              final int clientIdentifier = recoveryAgent.clientIdentifier();
              final String clientName = recoveryAgent.clientName();
  
              // Extract the 'values' collection from the _registeredRecoveryAgents map and create an iterator
              // from it. This iterator will return ArrayList objects each containing a set of RecoveryAgent
              // objects. Each ArrayList corrisponds to a different sequence priority value.
              final Collection registeredRecoveryAgentsValues = _registeredRecoveryAgents.values();
              final Iterator registeredRecoveryAgentsValuesIterator = registeredRecoveryAgentsValues.iterator();
  
              while (registeredRecoveryAgentsValuesIterator.hasNext()) {
                  // Extract the next ArrayList and create an iterator from it. This iterator will return RecoveryAgent
                  // objects that are registered at the same sequence priority value.
                  final ArrayList registeredRecoveryAgentsArray = (java.util.ArrayList) registeredRecoveryAgentsValuesIterator.next();
                  final Iterator registeredRecoveryAgentsArrayIterator = registeredRecoveryAgentsArray.iterator();
  
                  while (registeredRecoveryAgentsArrayIterator.hasNext()) {
                      // Extract the next RecoveryAgent object
                      final RecoveryAgent registeredRecoveryAgent = (RecoveryAgent) registeredRecoveryAgentsArrayIterator.next();
  
                      if ((registeredRecoveryAgent.clientIdentifier() == clientIdentifier) ||
                          (registeredRecoveryAgent.clientName().equals(clientName))) {
                          // The client service has attempted registration with a RecoveryAgent that reports either an
                          // identity or name that conflicts with an existing identity or name. Throw the registration
                          // request out with an exception.
                          if (tc.isEventEnabled())
                              Tr.event(tc, "Client service registration attempted with non-unique identity or name");
                          if (tc.isEntryEnabled())
                              Tr.exit(tc, "registerService", "ConflictingCredentialsException");
                          throw new ConflictingCredentialsException(null);
                      }
                  }
              }
  
              // This is a valid registration. Store the RecoveryAgent, keyed from the supplied sequence value.
              final Integer sequenceI = new Integer(sequence);
              ArrayList<RecoveryAgent> sequenceArray = _registeredRecoveryAgents.get(sequenceI);
  
              if (sequenceArray == null) {
                  sequenceArray = new java.util.ArrayList<RecoveryAgent>();
                  _registeredRecoveryAgents.put(sequenceI, sequenceArray);
              }
  
              sequenceArray.add(recoveryAgent);
  
              // Create a new RecoveryLogManager object that the client service can use to access
              // their recovery logs.
              clientRLM = new RecoveryLogManagerImpl(recoveryAgent, _customLogFactories);
              if (tc.isEventEnabled())
                  Tr.event(tc, "New service '" + clientName + "' (" + clientIdentifier + ") registered with RecoveryDirectorImpl");
  
              // When the transaction service registers, stash this RA away so that we can make a special
              // query of its recovery log directory in support of the exclusive locking model. Once
              // the HA framework provides more support for Network Paritioning, we can remove this logic.
              if (clientIdentifier == ClientId.RLCI_TRANSACTIONSERVICE) {
                  Configuration.txRecoveryAgent(recoveryAgent);
  
                  // Also set the isSnapshotSafe flag - we've used the transaction
                  // service admin console to configure this custom property,
                  // although it's really a RLS specific property.   Here, we extract
                  // it from the Tx Recovery Agent and update the RLS configuration
                  Configuration.setSnapshotSafe(recoveryAgent.isSnapshotSafe());
              }
          }
  
          if (tc.isEntryEnabled())
              Tr.exit(tc, "registerService", clientRLM);
          return clientRLM;
      }