code: public void exitRecoveryMode(SegmentMetadata newMetadata) {
          Exceptions.checkNotClosed(this.closed, this);
          Preconditions.checkState(this.recoveryMode, "Read Index is not in recovery mode.");
          Preconditions.checkNotNull(newMetadata, "newMetadata");
          Exceptions.checkArgument(newMetadata.getId() == this.metadata.getId(), "newMetadata", "New Metadata StreamSegmentId is different from existing one.");
          Exceptions.checkArgument(newMetadata.getLength() == this.metadata.getLength(), "newMetadata", "New Metadata Length is different from existing one.");
          Exceptions.checkArgument(newMetadata.getStorageLength() == this.metadata.getStorageLength(), "newMetadata", "New Metadata StorageLength is different from existing one.");
          Exceptions.checkArgument(newMetadata.isSealed() == this.metadata.isSealed(), "newMetadata", "New Metadata Sealed Flag is different from existing one.");
          Exceptions.checkArgument(newMetadata.isMerged() == this.metadata.isMerged(), "newMetadata", "New Metadata Merged Flag is different from existing one.");
          Exceptions.checkArgument(newMetadata.isDeleted() == this.metadata.isDeleted(), "newMetadata", "New Metadata Deletion Flag is different from existing one.");
  
          this.metadata = newMetadata;
          this.recoveryMode = false;
          log.debug("{}: Exit RecoveryMode.", this.traceObjectId);
      }
docs: Puts this Read Index out of recovery mode, while pointing it to the new metadata (Metadata objects can differ
  between recovery and non-recovery).
  
  @param newMetadata The new metadata object to use from now on.
  @throws IllegalStateException    If the Read Index is not in recovery mode.
  @throws NullPointerException     If the given metadata is null.
  @throws IllegalArgumentException If the new metadata does not match the old one perfectly.