use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class AppendingTest method shouldNotAttemptToTruncateAtIndexBeforeTheLogPrevIndex.
@Test
public void shouldNotAttemptToTruncateAtIndexBeforeTheLogPrevIndex() throws Exception {
// given
// a log with prevIndex and prevTerm set
ReadableRaftLog logMock = mock(ReadableRaftLog.class);
long prevIndex = 5;
long prevTerm = 5;
when(logMock.prevIndex()).thenReturn(prevIndex);
when(logMock.readEntryTerm(prevIndex)).thenReturn(prevTerm);
// and which also properly returns -1 as the term for an unknown entry, in this case prevIndex - 2
when(logMock.readEntryTerm(prevIndex - 2)).thenReturn(-1L);
// also, a state with a given commitIndex, obviously ahead of prevIndex
long commitIndex = 10;
ReadableRaftState state = mock(ReadableRaftState.class);
when(state.entryLog()).thenReturn(logMock);
when(state.commitIndex()).thenReturn(commitIndex);
// which is also the append index
when(logMock.appendIndex()).thenReturn(commitIndex);
// when
// an appendEntriesRequest arrives for appending entries before the prevIndex (for whatever reason)
Outcome outcome = mock(Outcome.class);
Appending.handleAppendEntriesRequest(state, outcome, new RaftMessages.AppendEntries.Request(aMember, prevTerm, prevIndex - 2, prevTerm, new RaftLogEntry[] { new RaftLogEntry(prevTerm, ReplicatedInteger.valueOf(2)) }, commitIndex + 3), NullLog.getInstance());
// then
// there should be no truncate commands. Actually, the whole thing should be a no op
verify(outcome, times(0)).addLogCommand(any());
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class RaftLogShipperTest method shouldSendAllEntriesAndCatchupCompletely.
@Test
public void shouldSendAllEntriesAndCatchupCompletely() throws Throwable {
// given
final int ENTRY_COUNT = catchupBatchSize * 10;
Collection<RaftLogEntry> entries = new ArrayList<>();
for (int i = 0; i < ENTRY_COUNT; i++) {
entries.add(new RaftLogEntry(0, ReplicatedInteger.valueOf(i)));
}
for (RaftLogEntry entry : entries) {
raftLog.append(entry);
}
// then
startLogShipper();
// back-tracking stage
RaftMessages.AppendEntries.Request expected = new RaftMessages.AppendEntries.Request(leader, leaderTerm, 0, 0, RaftLogEntry.empty, leaderCommit);
while (!outbound.sentTo(follower).contains(expected)) {
logShipper.onMismatch(-1, new LeaderContext(0, 0));
}
// catchup stage
long matchIndex;
do {
AppendEntries.Request last = (AppendEntries.Request) Iterables.last(outbound.sentTo(follower));
matchIndex = last.prevLogIndex() + last.entries().length;
outbound.clear();
logShipper.onMatch(matchIndex, new LeaderContext(0, 0));
} while (outbound.sentTo(follower).size() > 0);
assertEquals(ENTRY_COUNT - 1, matchIndex);
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry 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));
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class HeartbeatTest method shouldNotResultInCommitIfReferringToFutureEntries.
@Test
public void shouldNotResultInCommitIfReferringToFutureEntries() throws Exception {
InMemoryRaftLog raftLog = new InMemoryRaftLog();
RaftState state = raftState().myself(myself).entryLog(raftLog).build();
long leaderTerm = state.term() + leaderTermDifference;
raftLog.append(new RaftLogEntry(leaderTerm, content()));
RaftMessages.Heartbeat heartbeat = heartbeat().from(leader).commitIndex(// The leader is talking about committing stuff we don't know about
raftLog.appendIndex() + 1).commitIndexTerm(// And is in the same term
leaderTerm).leaderTerm(leaderTerm).build();
Outcome outcome = role.handler.handle(heartbeat, state, log());
assertThat(outcome.getLogCommands(), empty());
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class HeartbeatTest method shouldResultInCommitIfHistoryMatches.
@Test
public void shouldResultInCommitIfHistoryMatches() throws Exception {
InMemoryRaftLog raftLog = new InMemoryRaftLog();
RaftState state = raftState().myself(myself).entryLog(raftLog).build();
long leaderTerm = state.term() + leaderTermDifference;
raftLog.append(new RaftLogEntry(leaderTerm - 1, content()));
RaftMessages.Heartbeat heartbeat = heartbeat().from(leader).commitIndex(// The leader is talking about committing stuff we don't know about
raftLog.appendIndex()).commitIndexTerm(// And is in the same term
leaderTerm).leaderTerm(leaderTerm).build();
Outcome outcome = role.handler.handle(heartbeat, state, log());
assertThat(outcome.getLogCommands(), empty());
}
Aggregations