private void saveState(byte[] snapshot, int lastCID) {
    logLock.lock();

    Logger.println("(TOMLayer.saveState) Saving state of CID " + lastCID);

    log.newCheckpoint(snapshot, computeHash(snapshot), lastCID);
    log.setLastCID(-1);
    log.setLastCheckpointCID(lastCID);

    logLock.unlock();
    Logger.println("(TOMLayer.saveState) Finished saving state of CID " + lastCID);
  }
  @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();
    }
  }
  /**
   * 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();
  }
  @Override
  public int setState(ApplicationState recvState) {
    int lastCID = -1;
    if (recvState instanceof CSTState) {
      CSTState state = (CSTState) recvState;

      int lastCheckpointCID = state.getCheckpointCID();
      lastCID = state.getLastCID();

      bftsmart.tom.util.Logger.println(
          "(DurabilityCoordinator.setState) I'm going to update myself from CID "
              + lastCheckpointCID
              + " to CID "
              + lastCID);

      stateLock.lock();
      if (state.getSerializedState() != null) {
        System.out.println("The state is not null. Will install it");
        log.update(state);
        installSnapshot(state.getSerializedState());
      }

      System.out.print("--- Installing log from " + (lastCheckpointCID + 1) + " to " + lastCID);

      for (int cid = lastCheckpointCID + 1; cid <= lastCID; cid++) {
        try {
          bftsmart.tom.util.Logger.println(
              "(DurabilityCoordinator.setState) interpreting and verifying batched requests for CID "
                  + cid);
          CommandsInfo cmdInfo = state.getMessageBatch(cid);
          byte[][] commands = cmdInfo.commands;
          MessageContext[] msgCtx = cmdInfo.msgCtx;

          if (commands == null || msgCtx == null || msgCtx[0].isNoOp()) {
            continue;
          }

          appExecuteBatch(commands, msgCtx);
        } catch (Exception e) {
          e.printStackTrace(System.err);
        }
      }
      System.out.println("--- Installed");
      stateLock.unlock();
    }

    return lastCID;
  }
 public CSTState getState(CSTRequest cstRequest) {
   CSTState ret = log.getState(cstRequest);
   return ret;
 }