@Override
  public void setReplicaContext(ReplicaContext replicaContext) {
    this.config = replicaContext.getStaticConfiguration();
    if (log == null) {
      globalCheckpointPeriod = config.getGlobalCheckpointPeriod();
      replicaCkpIndex = getCheckpointPortionIndex();
      checkpointPortion = globalCheckpointPeriod / config.getN();

      //			byte[] state = getSnapshot();
      if (config.isToLog()) {
        int replicaId = config.getProcessId();
        boolean isToLog = config.isToLog();
        boolean syncLog = config.isToWriteSyncLog();
        boolean syncCkp = config.isToWriteSyncCkp();
        //				log = new DurableStateLog(replicaId, state, computeHash(state), isToLog, syncLog,
        // syncCkp);
        log = new DurableStateLog(replicaId, null, null, isToLog, syncLog, syncCkp);
        CSTState storedState = log.loadDurableState();
        if (storedState.getLastCID() > -1) {
          System.out.println("LAST CID RECOVERED FROM LOG: " + storedState.getLastCID());
          setState(storedState);
          getStateManager().setLastCID(storedState.getLastCID());
        } else {
          System.out.println("REPLICA IS IN INITIAL STATE");
        }
      }
      getStateManager().askCurrentConsensusId();
    }
  }
 /**
  * Iterates over the commands to find if any replica took a checkpoint. When a replica take a
  * checkpoint, it is necessary to save in an auxiliary table the position in the log in which that
  * replica took the checkpoint. It is used during state transfer to find lower or upper log
  * portions to be restored in the recovering replica. This iteration over commands is needed due
  * to the batch execution strategy introduced with the durable techniques to improve state
  * management. As several consensus instances can be executed in the same batch of commands, it is
  * necessary to identify if the batch contains checkpoint indexes.
  *
  * @param msgCtxs the contexts of the consensus where the messages where executed. There is one
  *     msgCtx message for each command to be executed
  * @return the index in which a replica is supposed to take a checkpoint. If there is no replica
  *     taking a checkpoint during the period comprised by this command batch, it is returned -1
  */
 private int findCheckpointPosition(int[] cids) {
   if (config.getGlobalCheckpointPeriod() < 1) return -1;
   if (cids.length == 0) throw new IllegalArgumentException();
   int firstCID = cids[0];
   if ((firstCID + 1) % checkpointPortion == 0) {
     return cidPosition(cids, firstCID);
   } else {
     int nextCkpIndex = (((firstCID / checkpointPortion) + 1) * checkpointPortion) - 1;
     if (nextCkpIndex <= cids[cids.length - 1]) {
       return cidPosition(cids, nextCkpIndex);
     }
   }
   return -1;
 }
  /**
   * Write commands to log file
   *
   * @param commands array of commands. Each command is an array of bytes
   * @param msgCtx
   */
  private void saveCommands(byte[][] commands, MessageContext[] msgCtx) {
    if (!config.isToLog()) return;

    if (commands.length != msgCtx.length) {
      System.out.println("----SIZE OF COMMANDS AND MESSAGE CONTEXTS IS DIFFERENT----");
      System.out.println(
          "----COMMANDS: " + commands.length + ", CONTEXTS: " + msgCtx.length + " ----");
    }

    logLock.lock();

    int cid = msgCtx[0].getConsensusId();
    int batchStart = 0;
    for (int i = 0; i <= msgCtx.length; i++) {
      if (i
          == msgCtx
              .length) { // the batch command contains only one command or it is the last position
                         // of the array
        byte[][] batch = Arrays.copyOfRange(commands, batchStart, i);
        MessageContext[] batchMsgCtx = Arrays.copyOfRange(msgCtx, batchStart, i);
        log.addMessageBatch(batch, batchMsgCtx, cid);
        log.setLastCID(cid, globalCheckpointPeriod, checkpointPortion);
        //				if(batchStart > 0)
        //					System.out.println("Last batch: " + commands.length + "," + batchStart + "-" + i +
        // "," + batch.length);
      } else {
        if (msgCtx[i].getConsensusId()
            > cid) { // saves commands when the CID changes or when it is the last batch
          byte[][] batch = Arrays.copyOfRange(commands, batchStart, i);
          MessageContext[] batchMsgCtx = Arrays.copyOfRange(msgCtx, batchStart, i);
          //					System.out.println("THERE IS MORE THAN ONE CID in this batch." + commands.length +
          // "," + batchStart + "-" + i + "," + batch.length);
          log.addMessageBatch(batch, batchMsgCtx, cid);
          log.setLastCID(cid, globalCheckpointPeriod, checkpointPortion);
          cid = msgCtx[i].getConsensusId();
          batchStart = i;
        }
      }
    }
    logLock.unlock();
  }
 private int getCheckpointPortionIndex() {
   int numberOfReplicas = config.getN();
   int ckpIndex = ((globalCheckpointPeriod / numberOfReplicas) * (config.getProcessId() + 1)) - 1;
   return ckpIndex;
 }