@Override
  public void advanceToken(RemoteReplicaInfo remoteReplicaInfo, ExchangeMetadataResponse exchangeMetadataResponse) {
    // Advance in-memory token
    RecoveryToken oldToken = (RecoveryToken) remoteReplicaInfo.getToken();
    super.advanceToken(remoteReplicaInfo, exchangeMetadataResponse);
    // truncate previous token in-place and persist in-place
    RecoveryToken token = (RecoveryToken) remoteReplicaInfo.getToken();
    if (token == null) {
      logger.error("Null token for replica {}", remoteReplicaInfo);
      return;
    }
    if (token.equals(oldToken)) {
      logger.trace("Not persisting recovery token as it is unchanged, oldToken = {}, newToken = {}", oldToken, token);
      return;
    }
    if (token.isEndOfPartition()) {
      logger.info("Completed recovering partition {}", remoteReplicaInfo.getReplicaId().getPartitionId().getId());
      token.endRecovery();
    }
    logger.trace("replica = {}, token = {}", remoteReplicaInfo, token);
    String tokenFilename = recoveryManager.getRecoveryTokenFilename(remoteReplicaInfo);
    logger.trace("Writing recovery token to disk at {}", tokenFilename);
    truncateAndWriteToFile(tokenFilename, token.toString());
  }
Persists token to disk in each replication cycle
@param remoteReplicaInfo Remote replica info object
@param exchangeMetadataResponse Metadata object exchanged between replicas
ambry-cloud/src/main/java/com/github/ambry/cloud/RecoveryThread.java