Search in sources :

Example 6 with BatchAppendLogEntries

use of org.neo4j.causalclustering.core.consensus.outcome.BatchAppendLogEntries in project neo4j by neo4j.

the class Appending method handleAppendEntriesRequest.

static void handleAppendEntriesRequest(ReadableRaftState state, Outcome outcome, RaftMessages.AppendEntries.Request request, Log log) throws IOException {
    if (request.leaderTerm() < state.term()) {
        RaftMessages.AppendEntries.Response appendResponse = new RaftMessages.AppendEntries.Response(state.myself(), state.term(), false, -1, state.entryLog().appendIndex());
        outcome.addOutgoingMessage(new RaftMessages.Directed(request.from(), appendResponse));
        return;
    }
    outcome.renewElectionTimeout();
    outcome.setNextTerm(request.leaderTerm());
    outcome.setLeader(request.from());
    outcome.setLeaderCommit(request.leaderCommit());
    if (!Follower.logHistoryMatches(state, request.prevLogIndex(), request.prevLogTerm(), log)) {
        assert request.prevLogIndex() > -1 && request.prevLogTerm() > -1;
        RaftMessages.AppendEntries.Response appendResponse = new RaftMessages.AppendEntries.Response(state.myself(), request.leaderTerm(), false, -1, state.entryLog().appendIndex());
        outcome.addOutgoingMessage(new RaftMessages.Directed(request.from(), appendResponse));
        return;
    }
    long baseIndex = request.prevLogIndex() + 1;
    int offset;
    /* Find possible truncation point. */
    for (offset = 0; offset < request.entries().length; offset++) {
        long logIndex = baseIndex + offset;
        long logTerm = state.entryLog().readEntryTerm(logIndex);
        if (logIndex > state.entryLog().appendIndex()) {
            // entry doesn't exist because it's beyond the current log end, so we can go ahead and append
            break;
        } else if (logIndex < state.entryLog().prevIndex()) {
            // entry doesn't exist because it's before the earliest known entry, so continue with the next one
            continue;
        } else if (logTerm != request.entries()[offset].term()) {
            /*
                 * the entry's index falls within our current range and the term doesn't match what we know. We must
                 * truncate.
                 */
            if (// first, assert that we haven't committed what we are about to truncate
            logIndex <= state.commitIndex()) {
                throw new IllegalStateException(format("Cannot truncate entry at index %d with term %d when commit index is at %d", logIndex, logTerm, state.commitIndex()));
            }
            outcome.addLogCommand(new TruncateLogCommand(logIndex));
            break;
        }
    }
    if (offset < request.entries().length) {
        outcome.addLogCommand(new BatchAppendLogEntries(baseIndex, offset, request.entries()));
    }
    Follower.commitToLogOnUpdate(state, request.prevLogIndex() + request.entries().length, request.leaderCommit(), outcome);
    // this is the index of the last incoming entry
    long endMatchIndex = request.prevLogIndex() + request.entries().length;
    RaftMessages.AppendEntries.Response appendResponse = new RaftMessages.AppendEntries.Response(state.myself(), request.leaderTerm(), true, endMatchIndex, endMatchIndex);
    outcome.addOutgoingMessage(new RaftMessages.Directed(request.from(), appendResponse));
}
Also used : TruncateLogCommand(org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand) RaftMessages(org.neo4j.causalclustering.core.consensus.RaftMessages) BatchAppendLogEntries(org.neo4j.causalclustering.core.consensus.outcome.BatchAppendLogEntries)

Aggregations

BatchAppendLogEntries (org.neo4j.causalclustering.core.consensus.outcome.BatchAppendLogEntries)6 RaftLogEntry (org.neo4j.causalclustering.core.consensus.log.RaftLogEntry)5 Outcome (org.neo4j.causalclustering.core.consensus.outcome.Outcome)5 Test (org.junit.Test)4 RaftState (org.neo4j.causalclustering.core.consensus.state.RaftState)4 RaftMessages (org.neo4j.causalclustering.core.consensus.RaftMessages)3 InMemoryRaftLog (org.neo4j.causalclustering.core.consensus.log.InMemoryRaftLog)3 RaftLog (org.neo4j.causalclustering.core.consensus.log.RaftLog)2 ShipCommand (org.neo4j.causalclustering.core.consensus.outcome.ShipCommand)2 TruncateLogCommand (org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand)2 ReadableRaftState (org.neo4j.causalclustering.core.consensus.state.ReadableRaftState)2 IOException (java.io.IOException)1 String.format (java.lang.String.format)1 List (java.util.List)1 AppendLogEntry (org.neo4j.causalclustering.core.consensus.outcome.AppendLogEntry)1 ReplicatedContent (org.neo4j.causalclustering.core.replication.ReplicatedContent)1 Log (org.neo4j.logging.Log)1