@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; }