Search in sources :

Example 1 with TruncateLogCommand

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

the class RaftMembershipManagerTest method membershipManagerShouldRevertToOldMembershipSetAfterTruncationCausesLossOfAllAppendedMembershipSets.

@Test
public void membershipManagerShouldRevertToOldMembershipSetAfterTruncationCausesLossOfAllAppendedMembershipSets() throws Exception {
    // given
    final InMemoryRaftLog raftLog = new InMemoryRaftLog();
    RaftMembershipManager membershipManager = lifeRule.add(raftMembershipManager(raftLog));
    // when
    List<RaftLogCommand> logCommands = asList(new AppendLogEntry(0, new RaftLogEntry(0, new RaftTestGroup(1, 2, 3, 4))), new AppendLogEntry(1, new RaftLogEntry(0, new RaftTestGroup(1, 2, 3, 5))), new TruncateLogCommand(1));
    for (RaftLogCommand logCommand : logCommands) {
        logCommand.applyTo(raftLog, log);
    }
    membershipManager.processLog(0, logCommands);
    // then
    assertEquals(new RaftTestGroup(1, 2, 3, 4).getMembers(), membershipManager.votingMembers());
    assertFalse(membershipManager.uncommittedMemberChangeInLog());
}
Also used : InMemoryRaftLog(org.neo4j.causalclustering.core.consensus.log.InMemoryRaftLog) TruncateLogCommand(org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand) AppendLogEntry(org.neo4j.causalclustering.core.consensus.outcome.AppendLogEntry) RaftLogCommand(org.neo4j.causalclustering.core.consensus.outcome.RaftLogCommand) RaftLogEntry(org.neo4j.causalclustering.core.consensus.log.RaftLogEntry) Test(org.junit.Test)

Example 2 with TruncateLogCommand

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

the class RaftMembershipManagerTest method membershipManagerShouldRevertToEarlierAppendedMembershipSetAfterTruncationCausesLossOfLastAppened.

@Test
public void membershipManagerShouldRevertToEarlierAppendedMembershipSetAfterTruncationCausesLossOfLastAppened() throws Exception {
    // given
    final InMemoryRaftLog raftLog = new InMemoryRaftLog();
    RaftMembershipManager membershipManager = lifeRule.add(raftMembershipManager(raftLog));
    // when
    List<RaftLogCommand> logCommands = asList(new AppendLogEntry(0, new RaftLogEntry(0, new RaftTestGroup(1, 2, 3, 4))), new AppendLogEntry(1, new RaftLogEntry(0, new RaftTestGroup(1, 2, 3, 5))), new AppendLogEntry(2, new RaftLogEntry(0, new RaftTestGroup(1, 2, 3, 6))), new TruncateLogCommand(2));
    for (RaftLogCommand logCommand : logCommands) {
        logCommand.applyTo(raftLog, log);
    }
    membershipManager.processLog(0, logCommands);
    // then
    assertEquals(new RaftTestGroup(1, 2, 3, 5).getMembers(), membershipManager.votingMembers());
}
Also used : InMemoryRaftLog(org.neo4j.causalclustering.core.consensus.log.InMemoryRaftLog) TruncateLogCommand(org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand) AppendLogEntry(org.neo4j.causalclustering.core.consensus.outcome.AppendLogEntry) RaftLogCommand(org.neo4j.causalclustering.core.consensus.outcome.RaftLogCommand) RaftLogEntry(org.neo4j.causalclustering.core.consensus.log.RaftLogEntry) Test(org.junit.Test)

Example 3 with TruncateLogCommand

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

the class AppendEntriesRequestTest method shouldTruncateOnReceiptOfConflictingEntry.

@Test
public void shouldTruncateOnReceiptOfConflictingEntry() throws Exception {
    // given
    InMemoryRaftLog raftLog = new InMemoryRaftLog();
    RaftState state = raftState().myself(myself).term(5).entryLog(raftLog).build();
    long leaderTerm = state.term() + leaderTermDifference;
    raftLog.append(new RaftLogEntry(state.term() - 1, content()));
    raftLog.append(new RaftLogEntry(state.term() - 1, content()));
    // when
    long previousIndex = raftLog.appendIndex() - 1;
    Outcome outcome = role.handler.handle(appendEntriesRequest().from(leader).leaderTerm(leaderTerm).prevLogIndex(previousIndex).prevLogTerm(raftLog.readEntryTerm(previousIndex)).logEntry(new RaftLogEntry(leaderTerm, content())).build(), state, log());
    // then
    assertTrue(((Response) messageFor(outcome, leader)).success());
    assertThat(outcome.getLogCommands(), hasItem(new TruncateLogCommand(1)));
}
Also used : InMemoryRaftLog(org.neo4j.causalclustering.core.consensus.log.InMemoryRaftLog) Outcome(org.neo4j.causalclustering.core.consensus.outcome.Outcome) RaftState(org.neo4j.causalclustering.core.consensus.state.RaftState) TruncateLogCommand(org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand) RaftLogEntry(org.neo4j.causalclustering.core.consensus.log.RaftLogEntry) Test(org.junit.Test)

Example 4 with TruncateLogCommand

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

the class RaftStateTest method shouldUpdateCacheState.

@Test
public void shouldUpdateCacheState() throws Exception {
    //Test that updates applied to the raft state will be refelcted in the entry cache.
    //given
    InFlightMap<RaftLogEntry> cache = new InFlightMap<>();
    RaftState raftState = new RaftState(member(0), new InMemoryStateStorage<>(new TermState()), new FakeMembership(), new InMemoryRaftLog(), new InMemoryStateStorage<>(new VoteState()), cache, NullLogProvider.getInstance());
    List<RaftLogCommand> logCommands = new LinkedList<RaftLogCommand>() {

        {
            add(new AppendLogEntry(1, new RaftLogEntry(0L, valueOf(0))));
            add(new AppendLogEntry(2, new RaftLogEntry(0L, valueOf(1))));
            add(new AppendLogEntry(3, new RaftLogEntry(0L, valueOf(2))));
            add(new AppendLogEntry(4, new RaftLogEntry(0L, valueOf(4))));
            add(new TruncateLogCommand(3));
            add(new AppendLogEntry(3, new RaftLogEntry(0L, valueOf(5))));
        }
    };
    Outcome raftTestMemberOutcome = new Outcome(CANDIDATE, 0, null, -1, null, emptySet(), -1, initialFollowerStates(), true, logCommands, emptyOutgoingMessages(), emptySet(), -1, emptySet());
    //when
    raftState.update(raftTestMemberOutcome);
    //then
    assertNotNull(cache.get(1L));
    assertNotNull(cache.get(2L));
    assertNotNull(cache.get(3L));
    assertEquals(valueOf(5), cache.get(3L).content());
    assertNull(cache.get(4L));
}
Also used : TruncateLogCommand(org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand) LinkedList(java.util.LinkedList) RaftLogCommand(org.neo4j.causalclustering.core.consensus.outcome.RaftLogCommand) RaftLogEntry(org.neo4j.causalclustering.core.consensus.log.RaftLogEntry) InMemoryRaftLog(org.neo4j.causalclustering.core.consensus.log.InMemoryRaftLog) VoteState(org.neo4j.causalclustering.core.consensus.vote.VoteState) Outcome(org.neo4j.causalclustering.core.consensus.outcome.Outcome) AppendLogEntry(org.neo4j.causalclustering.core.consensus.outcome.AppendLogEntry) InFlightMap(org.neo4j.causalclustering.core.consensus.log.segmented.InFlightMap) TermState(org.neo4j.causalclustering.core.consensus.term.TermState) Test(org.junit.Test)

Example 5 with TruncateLogCommand

use of org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand 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

TruncateLogCommand (org.neo4j.causalclustering.core.consensus.outcome.TruncateLogCommand)5 Test (org.junit.Test)4 InMemoryRaftLog (org.neo4j.causalclustering.core.consensus.log.InMemoryRaftLog)4 RaftLogEntry (org.neo4j.causalclustering.core.consensus.log.RaftLogEntry)4 AppendLogEntry (org.neo4j.causalclustering.core.consensus.outcome.AppendLogEntry)3 RaftLogCommand (org.neo4j.causalclustering.core.consensus.outcome.RaftLogCommand)3 Outcome (org.neo4j.causalclustering.core.consensus.outcome.Outcome)2 LinkedList (java.util.LinkedList)1 RaftMessages (org.neo4j.causalclustering.core.consensus.RaftMessages)1 InFlightMap (org.neo4j.causalclustering.core.consensus.log.segmented.InFlightMap)1 BatchAppendLogEntries (org.neo4j.causalclustering.core.consensus.outcome.BatchAppendLogEntries)1 RaftState (org.neo4j.causalclustering.core.consensus.state.RaftState)1 TermState (org.neo4j.causalclustering.core.consensus.term.TermState)1 VoteState (org.neo4j.causalclustering.core.consensus.vote.VoteState)1