private boolean handleSnapshotSyncRequest(SnapshotSyncRequest snapshotSyncRequest){ try{ this.stateMachine.saveSnapshotData(snapshotSyncRequest.getSnapshot(), snapshotSyncRequest.getOffset(), snapshotSyncRequest.getData()); if(snapshotSyncRequest.isDone()){ this.stateMachine.exit(-1); try{ this.logger.info("successfully compact the log store, will now ask the statemachine to apply the snapshot"); if(!this.stateMachine.applySnapshot(snapshotSyncRequest.getSnapshot())){ this.logger.error("failed to apply the snapshot after log compacted, to ensure the safety, will shutdown the system"); this.stateMachine.exit(-1); return false; //should never be reached this.stateMachine.exit(-1); return false;
&& this.snapshotInProgress.compareAndSet(0, 1)){ snapshotInAction = true; Snapshot currentSnapshot = this.stateMachine.getLastSnapshot(); if(currentSnapshot != null && indexCommitted - currentSnapshot.getLastLogIndex() < this.context.getRaftParameters().getSnapshotDistance()){ this.logger.info("a very recent snapshot is available at index %d, will skip this one", currentSnapshot.getLastLogIndex()); Snapshot lastSnapshot = this.stateMachine.getLastSnapshot(); if(lastSnapshot == null){ this.logger.error("No snapshot could be found while no configuration cannot be found in current committed logs, this is a system error, exiting"); this.stateMachine.exit(-1); return; }else if(config.getLogIndex() > indexCommitted && config.getLastLogIndex() == 0){ this.logger.error("BUG!!! stop the system, there must be a configuration at index one"); this.stateMachine.exit(-1); long logTermToCompact = this.logStore.getLogEntryAt(indexToCompact).getTerm(); Snapshot snapshot = new Snapshot(indexToCompact, logTermToCompact, config); this.stateMachine.createSnapshot(snapshot).whenCompleteAsync((Boolean result, Throwable error) -> { try{ if(error != null){
SnapshotSyncContext context = peer.getSnapshotSyncContext(); Snapshot snapshot = context == null ? null : context.getSnapshot(); Snapshot lastSnapshot = this.stateMachine.getLastSnapshot(); if(snapshot == null || (lastSnapshot != null && lastSnapshot.getLastLogIndex() > snapshot.getLastLogIndex())){ snapshot = lastSnapshot; this.stateMachine.exit(-1); return null; this.stateMachine.exit(-1); return null; byte[] data = new byte[sizeLeft > blockSize ? blockSize : (int)sizeLeft]; try{ int sizeRead = this.stateMachine.readSnapshotData(snapshot, offset, data); if(sizeRead < data.length){ this.logger.error("only %d bytes could be read from snapshot while %d bytes are expected, should be something wrong" , sizeRead, data.length); this.stateMachine.exit(-1); return null; this.stateMachine.exit(-1); return null;
}else if(this.role == ServerRole.Leader){ this.logger.error("Receive AppendEntriesRequest from another leader(%d) with same term, there must be a bug, server exits", request.getSource()); this.stateMachine.exit(-1); }else{ this.restartElectionTimer(); LogEntry oldEntry = this.logStore.getLogEntryAt(index); if(oldEntry.getValueType() == LogValueType.Application){ this.stateMachine.rollback(index, oldEntry.getValue()); }else if(oldEntry.getValueType() == LogValueType.Configuration){ this.logger.info("revert a previous config change to config at %d", this.config.getLogIndex()); this.logStore.writeAt(index, logEntry); if (logEntry.getValueType() == LogValueType.Application) { this.stateMachine.preCommit(index, logEntry.getValue()); } else if (logEntry.getValueType() == LogValueType.Configuration) { this.logger.info("received a configuration change at index %d from leader", index); this.configChanging = true; } else if(logEntry.getValueType() == LogValueType.Application) { this.stateMachine.preCommit(indexForEntry, logEntry.getValue());
&& this.snapshotInProgress.compareAndSet(0, 1)){ snapshotInAction = true; Snapshot currentSnapshot = this.stateMachine.getLastSnapshot(); if(currentSnapshot != null && indexCommitted - currentSnapshot.getLastLogIndex() < this.context.getRaftParameters().getSnapshotDistance()){ this.logger.info("a very recent snapshot is available at index %d, will skip this one", currentSnapshot.getLastLogIndex()); Snapshot lastSnapshot = this.stateMachine.getLastSnapshot(); if(lastSnapshot == null){ this.logger.error("No snapshot could be found while no configuration cannot be found in current committed logs, this is a system error, exiting"); long logTermToCompact = this.logStore.getLogEntryAt(indexToCompact).getTerm(); Snapshot snapshot = new Snapshot(indexToCompact, logTermToCompact, config); this.stateMachine.createSnapshot(snapshot).whenCompleteAsync((Boolean result, Throwable error) -> { try{ if(error != null){
SnapshotSyncContext context = peer.getSnapshotSyncContext(); Snapshot snapshot = context == null ? null : context.getSnapshot(); Snapshot lastSnapshot = this.stateMachine.getLastSnapshot(); if(snapshot == null || (lastSnapshot != null && lastSnapshot.getLastLogIndex() > snapshot.getLastLogIndex())){ snapshot = lastSnapshot; byte[] data = new byte[sizeLeft > blockSize ? blockSize : (int)sizeLeft]; try{ int sizeRead = this.stateMachine.readSnapshotData(snapshot, offset, data); if(sizeRead < data.length){ this.logger.error("only %d bytes could be read from snapshot while %d bytes are expected, should be something wrong" , sizeRead, data.length);
private boolean handleSnapshotSyncRequest(SnapshotSyncRequest snapshotSyncRequest){ try{ this.stateMachine.saveSnapshotData(snapshotSyncRequest.getSnapshot(), snapshotSyncRequest.getOffset(), snapshotSyncRequest.getData()); if(snapshotSyncRequest.isDone()){ try{ this.logger.info("successfully compact the log store, will now ask the statemachine to apply the snapshot"); if(!this.stateMachine.applySnapshot(snapshotSyncRequest.getSnapshot())){ this.logger.error("failed to apply the snapshot after log compacted, to ensure the safety, will shutdown the system"); System.exit(-1);
this.stateMachine.exit(0); return;
LogEntry logEntry = server.logStore.getLogEntryAt(currentCommitIndex); if(logEntry.getValueType() == LogValueType.Application){ server.stateMachine.commit(currentCommitIndex, logEntry.getValue()); }else if(logEntry.getValueType() == LogValueType.Configuration){ synchronized(server){ }catch(Throwable error){ server.logger.error("error %s encountered for committing thread, which should not happen, according to this, state machine may not have further progress, stop the system", error, error.getMessage()); server.stateMachine.exit(-1);
LogEntry oldEntry = this.logStore.getLogEntryAt(index); if(oldEntry.getValueType() == LogValueType.Application){ this.stateMachine.rollback(index, oldEntry.getValue()); }else if(oldEntry.getValueType() == LogValueType.Configuration){ this.logger.info("revert a previous config change to config at %d", this.config.getLogIndex()); this.configChanging = true; }else{ this.stateMachine.preCommit(indexForEntry, logEntry.getValue());
private long termForLastLog(long logIndex){ if(logIndex == 0){ return 0; } if(logIndex >= this.logStore.getStartIndex()){ return this.logStore.getLogEntryAt(logIndex).getTerm(); } Snapshot lastSnapshot = this.stateMachine.getLastSnapshot(); if(lastSnapshot == null || logIndex != lastSnapshot.getLastLogIndex()){ throw new IllegalArgumentException("logIndex is beyond the range that no term could be retrieved"); } return lastSnapshot.getLastLogTerm(); }
private RaftResponseMessage handleClientRequest(RaftRequestMessage request){ RaftResponseMessage response = new RaftResponseMessage(); response.setMessageType(RaftMessageType.AppendEntriesResponse); response.setSource(this.id); response.setDestination(this.leader); response.setTerm(this.state.getTerm()); long term; synchronized(this){ if(this.role != ServerRole.Leader){ response.setAccepted(false); return response; } term = this.state.getTerm(); } LogEntry[] logEntries = request.getLogEntries(); if(logEntries != null && logEntries.length > 0){ for(int i = 0; i < logEntries.length; ++i){ this.stateMachine.preCommit(this.logStore.append(new LogEntry(term, logEntries[i].getValue())), logEntries[i].getValue()); } } // Urgent commit, so that the commit will not depend on heartbeat this.requestAppendEntries(); response.setAccepted(true); response.setNextIndex(this.logStore.getFirstAvailableIndex()); return response; }
LogEntry logEntry = server.logStore.getLogEntryAt(currentCommitIndex); if(logEntry.getValueType() == LogValueType.Application){ server.stateMachine.commit(currentCommitIndex, logEntry.getValue()); }else if(logEntry.getValueType() == LogValueType.Configuration){ synchronized(server){
public static RaftMessageSender run(RaftContext context){ if(context == null){ throw new IllegalArgumentException("context cannot be null"); } RaftServer server = new RaftServer(context); RaftMessageSender messageSender = server.createMessageSender(); context.getStateMachine().start(messageSender); context.getRpcListener().startListening(server); return messageSender; } }
}else if(this.role == ServerRole.Leader){ this.logger.error("Receive AppendEntriesRequest from another leader(%d) with same term, there must be a bug, server exits", request.getSource()); this.stateMachine.exit(-1); }else{ this.restartElectionTimer(); LogEntry oldEntry = this.logStore.getLogEntryAt(index); if(oldEntry.getValueType() == LogValueType.Application){ this.stateMachine.rollback(index, oldEntry.getValue()); }else if(oldEntry.getValueType() == LogValueType.Configuration){ this.logger.info("revert a previous config change to config at %d", this.config.getLogIndex()); this.logStore.writeAt(index, logEntry); if (logEntry.getValueType() == LogValueType.Application) { this.stateMachine.preCommit(index, logEntry.getValue()); } else if (logEntry.getValueType() == LogValueType.Configuration) { this.logger.info("received a configuration change at index %d from leader", index); this.configChanging = true; } else if(logEntry.getValueType() == LogValueType.Application) { this.stateMachine.preCommit(indexForEntry, logEntry.getValue());
this.stateMachine.exit(0); return;
LogEntry logEntry = server.logStore.getLogEntryAt(currentCommitIndex); if(logEntry.getValueType() == LogValueType.Application){ server.stateMachine.commit(currentCommitIndex, logEntry.getValue()); }else if(logEntry.getValueType() == LogValueType.Configuration){ synchronized(server){ }catch(Throwable error){ server.logger.error("error %s encountered for committing thread, which should not happen, according to this, state machine may not have further progress, stop the system", error, error.getMessage()); server.stateMachine.exit(-1);
private long termForLastLog(long logIndex){ if(logIndex == 0){ return 0; } if(logIndex >= this.logStore.getStartIndex()){ return this.logStore.getLogEntryAt(logIndex).getTerm(); } Snapshot lastSnapshot = this.stateMachine.getLastSnapshot(); if(lastSnapshot == null || logIndex != lastSnapshot.getLastLogIndex()){ throw new IllegalArgumentException("logIndex is beyond the range that no term could be retrieved"); } return lastSnapshot.getLastLogTerm(); }
private RaftResponseMessage handleClientRequest(RaftRequestMessage request){ RaftResponseMessage response = new RaftResponseMessage(); response.setMessageType(RaftMessageType.AppendEntriesResponse); response.setSource(this.id); response.setDestination(this.leader); response.setTerm(this.state.getTerm()); long term; synchronized(this){ if(this.role != ServerRole.Leader){ response.setAccepted(false); return response; } term = this.state.getTerm(); } LogEntry[] logEntries = request.getLogEntries(); if(logEntries != null && logEntries.length > 0){ for(int i = 0; i < logEntries.length; ++i){ this.stateMachine.preCommit(this.logStore.append(new LogEntry(term, logEntries[i].getValue())), logEntries[i].getValue()); } } // Urgent commit, so that the commit will not depend on heartbeat this.requestAppendEntries(); response.setAccepted(true); response.setNextIndex(this.logStore.getFirstAvailableIndex()); return response; }
public static RaftMessageSender run(RaftContext context){ if(context == null){ throw new IllegalArgumentException("context cannot be null"); } RaftServer server = new RaftServer(context); RaftMessageSender messageSender = server.createMessageSender(); context.getStateMachine().start(messageSender); context.getRpcListener().startListening(server); return messageSender; } }