@Override public long append(LogEntry logEntry) { try{ PreparedStatement ps = this.connection.prepareStatement(INSERT_ENTRY_SQL); ps.setLong(1, logEntry.getTerm()); ps.setByte(2, logEntry.getValueType().toByte()); ps.setBytes(3, logEntry.getValue()); ps.execute(); this.connection.commit(); this.lastEntry = logEntry; return this.nextIndex.getAndIncrement(); }catch(Throwable error){ this.logger.error("failed to insert a new entry", error); throw new RuntimeException("log store error", error); } }
@Override public long append(LogEntry logEntry) { try{ PreparedStatement ps = this.connection.prepareStatement(INSERT_ENTRY_SQL); ps.setLong(1, logEntry.getTerm()); ps.setByte(2, logEntry.getValueType().toByte()); ps.setBytes(3, logEntry.getValue()); ps.execute(); this.connection.commit(); this.lastEntry = logEntry; return this.nextIndex.getAndIncrement(); }catch(Throwable error){ this.logger.error("failed to insert a new entry", error); throw new RuntimeException("log store error", error); } }
@Override public void writeAt(long index, LogEntry logEntry) { if(index >= this.nextIndex.get() || index < this.startIndex.get()){ throw new IllegalArgumentException("index out of range"); } try{ PreparedStatement ps = this.connection.prepareStatement(UPDATE_ENTRY_SQL); ps.setLong(1, logEntry.getTerm()); ps.setByte(2, logEntry.getValueType().toByte()); ps.setBytes(3, logEntry.getValue()); ps.setLong(4, index); ps.execute(); ps = this.connection.prepareStatement(TRIM_TABLE_SQL); ps.setLong(1, index); ps.execute(); ps = this.connection.prepareStatement(UPDATE_SEQUENCE_SQL); ps.setLong(1, index + 1); ps.execute(); this.connection.commit(); this.nextIndex.set(index + 1); this.lastEntry = logEntry; }catch(Throwable error){ this.logger.error("failed to write an entry at a specific index", error); throw new RuntimeException("log store error", error); } }
@Override public void writeAt(long index, LogEntry logEntry) { if(index >= this.nextIndex.get() || index < this.startIndex.get()){ throw new IllegalArgumentException("index out of range"); } try{ PreparedStatement ps = this.connection.prepareStatement(UPDATE_ENTRY_SQL); ps.setLong(1, logEntry.getTerm()); ps.setByte(2, logEntry.getValueType().toByte()); ps.setBytes(3, logEntry.getValue()); ps.setLong(4, index); ps.execute(); ps = this.connection.prepareStatement(TRIM_TABLE_SQL); ps.setLong(1, index); ps.execute(); ps = this.connection.prepareStatement(UPDATE_SEQUENCE_SQL); ps.setLong(1, index + 1); ps.execute(); this.connection.commit(); this.nextIndex.set(index + 1); this.lastEntry = logEntry; }catch(Throwable error){ this.logger.error("failed to write an entry at a specific index", error); throw new RuntimeException("log store error", error); } }
public static byte[] logEntryToBytes(LogEntry logEntry){ ByteArrayOutputStream output = new ByteArrayOutputStream(); try{ output.write(longToBytes(logEntry.getTerm())); output.write(logEntry.getValueType().toByte()); output.write(intToBytes(logEntry.getValue().length)); output.write(logEntry.getValue()); output.flush(); return output.toByteArray(); }catch(IOException exception){ LogManager.getLogger("BinaryUtil").error("failed to serialize LogEntry to memory", exception); throw new RuntimeException("Running into bad situation, where memory may not be sufficient", exception); } }
@Override public long append(LogEntry logEntry) { try{ this.storeWriteLock.lock(); this.indexFile.seek(this.indexFile.length()); long dataFileLength = this.dataFile.length(); this.indexFile.writeLong(dataFileLength); this.dataFile.seek(dataFileLength); ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES + 1 + logEntry.getValue().length); buffer.putLong(logEntry.getTerm()); buffer.put(logEntry.getValueType().toByte()); buffer.put(logEntry.getValue()); this.dataFile.write(buffer.array()); this.entriesInStore += 1; this.buffer.append(logEntry); return this.entriesInStore + this.startIndex - 1; }catch(IOException exception){ this.logger.error("failed to append a log entry to store", exception); throw new RuntimeException(exception.getMessage(), exception); }finally{ this.storeWriteLock.unlock(); } }
public static byte[] logEntryToBytes(LogEntry logEntry){ ByteArrayOutputStream output = new ByteArrayOutputStream(); try{ output.write(longToBytes(logEntry.getTerm())); output.write(logEntry.getValueType().toByte()); output.write(intToBytes(logEntry.getValue().length)); output.write(logEntry.getValue()); output.flush(); return output.toByteArray(); }catch(IOException exception){ LogManager.getLogger("BinaryUtil").error("failed to serialize LogEntry to memory", exception); throw new RuntimeException("Running into bad situation, where memory may not be sufficient", exception); } }
@Override public long append(LogEntry logEntry) { try{ this.storeWriteLock.lock(); this.indexFile.seek(this.indexFile.length()); long dataFileLength = this.dataFile.length(); this.indexFile.writeLong(dataFileLength); this.dataFile.seek(dataFileLength); ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES + 1 + logEntry.getValue().length); buffer.putLong(logEntry.getTerm()); buffer.put(logEntry.getValueType().toByte()); buffer.put(logEntry.getValue()); this.dataFile.write(buffer.array()); this.entriesInStore += 1; this.buffer.append(logEntry); return this.entriesInStore + this.startIndex - 1; }catch(IOException exception){ this.logger.error("failed to append a log entry to store", exception); throw new RuntimeException(exception.getMessage(), exception); }finally{ this.storeWriteLock.unlock(); } }
long index = logIndex - this.startIndex + 1; //start index is one based ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES + 1 + logEntry.getValue().length); buffer.putLong(logEntry.getTerm()); buffer.put(logEntry.getValueType().toByte()); buffer.put(logEntry.getValue());
long index = logIndex - this.startIndex + 1; //start index is one based ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES + 1 + logEntry.getValue().length); buffer.putLong(logEntry.getTerm()); buffer.put(logEntry.getValueType().toByte()); buffer.put(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 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 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(); }
long logTermToCompact = this.logStore.getLogEntryAt(indexToCompact).getTerm(); Snapshot snapshot = new Snapshot(indexToCompact, logTermToCompact, config); this.stateMachine.createSnapshot(snapshot).whenCompleteAsync((Boolean result, Throwable error) -> {
private synchronized RaftResponseMessage handleVoteRequest(RaftRequestMessage request){ // we allow the server to be continue after term updated to save a round message this.updateTerm(request.getTerm()); // Reset stepping down value to prevent this server goes down when leader crashes after sending a LeaveClusterRequest if(this.steppingDown > 0){ this.steppingDown = 2; } RaftResponseMessage response = new RaftResponseMessage(); response.setMessageType(RaftMessageType.RequestVoteResponse); response.setSource(this.id); response.setDestination(request.getSource()); response.setTerm(this.state.getTerm()); boolean logOkay = request.getLastLogTerm() > this.logStore.getLastLogEntry().getTerm() || (request.getLastLogTerm() == this.logStore.getLastLogEntry().getTerm() && this.logStore.getFirstAvailableIndex() - 1 <= request.getLastLogIndex()); boolean grant = request.getTerm() == this.state.getTerm() && logOkay && (this.state.getVotedFor() == request.getSource() || this.state.getVotedFor() == -1); response.setAccepted(grant); if(grant){ this.state.setVotedFor(request.getSource()); this.context.getServerStateManager().persistState(this.state); } return response; }
private synchronized RaftResponseMessage handleVoteRequest(RaftRequestMessage request){ // we allow the server to be continue after term updated to save a round message this.updateTerm(request.getTerm()); // Reset stepping down value to prevent this server goes down when leader crashes after sending a LeaveClusterRequest if(this.steppingDown > 0){ this.steppingDown = 2; } RaftResponseMessage response = new RaftResponseMessage(); response.setMessageType(RaftMessageType.RequestVoteResponse); response.setSource(this.id); response.setDestination(request.getSource()); response.setTerm(this.state.getTerm()); boolean logOkay = request.getLastLogTerm() > this.logStore.getLastLogEntry().getTerm() || (request.getLastLogTerm() == this.logStore.getLastLogEntry().getTerm() && this.logStore.getFirstAvailableIndex() - 1 <= request.getLastLogIndex()); boolean grant = request.getTerm() == this.state.getTerm() && logOkay && (this.state.getVotedFor() == request.getSource() || this.state.getVotedFor() == -1); response.setAccepted(grant); if(grant){ this.state.setVotedFor(request.getSource()); this.context.getServerStateManager().persistState(this.state); } return response; }
private synchronized RaftResponseMessage handleVoteRequest(RaftRequestMessage request){ // we allow the server to be continue after term updated to save a round message this.updateTerm(request.getTerm()); // Reset stepping down value to prevent this server goes down when leader crashes after sending a LeaveClusterRequest if(this.steppingDown > 0){ this.steppingDown = 2; } RaftResponseMessage response = new RaftResponseMessage(); response.setMessageType(RaftMessageType.RequestVoteResponse); response.setSource(this.id); response.setDestination(request.getSource()); response.setTerm(this.state.getTerm()); boolean logOkay = request.getLastLogTerm() > this.logStore.getLastLogEntry().getTerm() || (request.getLastLogTerm() == this.logStore.getLastLogEntry().getTerm() && this.logStore.getFirstAvailableIndex() - 1 <= request.getLastLogIndex()); boolean grant = request.getTerm() == this.state.getTerm() && logOkay && (this.state.getVotedFor() == request.getSource() || this.state.getVotedFor() == -1); response.setAccepted(grant); if(grant){ this.state.setVotedFor(request.getSource()); this.context.getServerStateManager().persistState(this.state); } return response; }
long logTermToCompact = this.logStore.getLogEntryAt(indexToCompact).getTerm(); Snapshot snapshot = new Snapshot(indexToCompact, logTermToCompact, config); this.stateMachine.createSnapshot(snapshot).whenCompleteAsync((Boolean result, Throwable error) -> {
long logTermToCompact = this.logStore.getLogEntryAt(indexToCompact).getTerm(); Snapshot snapshot = new Snapshot(indexToCompact, logTermToCompact, config); this.stateMachine.createSnapshot(snapshot).whenCompleteAsync((Boolean result, Throwable error) -> {