use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class AppendEntriesRequestTest method bootstrappedLog.
private RaftLog bootstrappedLog() throws IOException {
InMemoryRaftLog raftLog = new InMemoryRaftLog();
raftLog.append(new RaftLogEntry(0, content()));
return raftLog;
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class AppendingTest method shouldNotAllowTruncationAtCommit.
@Test
public void shouldNotAllowTruncationAtCommit() throws Exception {
// given
long commitIndex = 5;
long localTermForAllEntries = 1L;
Outcome outcome = mock(Outcome.class);
ReadableRaftLog logMock = mock(ReadableRaftLog.class);
// for simplicity, all entries are at term 1
when(logMock.readEntryTerm(anyLong())).thenReturn(localTermForAllEntries);
when(logMock.appendIndex()).thenReturn(commitIndex);
ReadableRaftState state = mock(ReadableRaftState.class);
when(state.entryLog()).thenReturn(logMock);
when(state.commitIndex()).thenReturn(commitIndex);
// when - then
try {
Appending.handleAppendEntriesRequest(state, outcome, new RaftMessages.AppendEntries.Request(aMember, localTermForAllEntries, commitIndex - 1, localTermForAllEntries, new RaftLogEntry[] { new RaftLogEntry(localTermForAllEntries + 1, ReplicatedInteger.valueOf(2)) }, commitIndex + 3), NullLog.getInstance());
fail("Appending should not allow truncation at or before the commit index");
} catch (IllegalStateException expected) {
// ok
}
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class InFlightLogEntryReaderTest method shouldUseTheCacheWhenTheIndexIsPresent.
@Test
public void shouldUseTheCacheWhenTheIndexIsPresent() throws Exception {
// given
InFlightLogEntryReader reader = new InFlightLogEntryReader(raftLog, inFlightMap, clearCache);
startingFromIndexReturnEntries(inFlightMap, logIndex, entry);
startingFromIndexReturnEntries(raftLog, -1, null);
// when
RaftLogEntry raftLogEntry = reader.get(logIndex);
// then
assertEquals(entry, raftLogEntry);
verify(inFlightMap).get(logIndex);
assertCacheIsUpdated(inFlightMap, logIndex);
verifyNoMoreInteractions(inFlightMap);
verifyZeroInteractions(raftLog);
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class RaftMessageEncoder method encode.
@Override
protected synchronized void encode(ChannelHandlerContext ctx, RaftMessages.ClusterIdAwareMessage decoratedMessage, ByteBuf out) throws Exception {
RaftMessages.RaftMessage message = decoratedMessage.message();
ClusterId clusterId = decoratedMessage.clusterId();
MemberId.Marshal memberMarshal = new MemberId.Marshal();
NetworkFlushableByteBuf channel = new NetworkFlushableByteBuf(out);
ClusterId.Marshal.INSTANCE.marshal(clusterId, channel);
channel.putInt(message.type().ordinal());
memberMarshal.marshal(message.from(), channel);
if (message instanceof RaftMessages.Vote.Request) {
RaftMessages.Vote.Request voteRequest = (RaftMessages.Vote.Request) message;
memberMarshal.marshal(voteRequest.candidate(), channel);
channel.putLong(voteRequest.term());
channel.putLong(voteRequest.lastLogIndex());
channel.putLong(voteRequest.lastLogTerm());
} else if (message instanceof RaftMessages.Vote.Response) {
RaftMessages.Vote.Response voteResponse = (RaftMessages.Vote.Response) message;
channel.putLong(voteResponse.term());
channel.put((byte) (voteResponse.voteGranted() ? 1 : 0));
} else if (message instanceof RaftMessages.AppendEntries.Request) {
RaftMessages.AppendEntries.Request appendRequest = (RaftMessages.AppendEntries.Request) message;
channel.putLong(appendRequest.leaderTerm());
channel.putLong(appendRequest.prevLogIndex());
channel.putLong(appendRequest.prevLogTerm());
channel.putLong(appendRequest.leaderCommit());
channel.putLong(appendRequest.entries().length);
for (RaftLogEntry raftLogEntry : appendRequest.entries()) {
channel.putLong(raftLogEntry.term());
marshal.marshal(raftLogEntry.content(), channel);
}
} else if (message instanceof RaftMessages.AppendEntries.Response) {
RaftMessages.AppendEntries.Response appendResponse = (RaftMessages.AppendEntries.Response) message;
channel.putLong(appendResponse.term());
channel.put((byte) (appendResponse.success() ? 1 : 0));
channel.putLong(appendResponse.matchIndex());
channel.putLong(appendResponse.appendIndex());
} else if (message instanceof RaftMessages.NewEntry.Request) {
RaftMessages.NewEntry.Request newEntryRequest = (RaftMessages.NewEntry.Request) message;
marshal.marshal(newEntryRequest.content(), channel);
} else if (message instanceof RaftMessages.Heartbeat) {
RaftMessages.Heartbeat heartbeat = (RaftMessages.Heartbeat) message;
channel.putLong(heartbeat.leaderTerm());
channel.putLong(heartbeat.commitIndexTerm());
channel.putLong(heartbeat.commitIndex());
} else if (message instanceof RaftMessages.HeartbeatResponse) {
//Heartbeat Response does not have any data attached to it.
} else if (message instanceof RaftMessages.LogCompactionInfo) {
RaftMessages.LogCompactionInfo logCompactionInfo = (RaftMessages.LogCompactionInfo) message;
channel.putLong(logCompactionInfo.leaderTerm());
channel.putLong(logCompactionInfo.prevIndex());
} else {
throw new IllegalArgumentException("Unknown message type: " + message);
}
}
use of org.neo4j.causalclustering.core.consensus.log.RaftLogEntry in project neo4j by neo4j.
the class RaftMessageDecoder method decode.
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> list) throws Exception {
ReadableChannel channel = new NetworkReadableClosableChannelNetty4(buffer);
ClusterId clusterId = ClusterId.Marshal.INSTANCE.unmarshal(channel);
int messageTypeWire = channel.getInt();
RaftMessages.Type[] values = RaftMessages.Type.values();
RaftMessages.Type messageType = values[messageTypeWire];
MemberId from = retrieveMember(channel);
RaftMessages.RaftMessage result;
if (messageType.equals(VOTE_REQUEST)) {
MemberId candidate = retrieveMember(channel);
long term = channel.getLong();
long lastLogIndex = channel.getLong();
long lastLogTerm = channel.getLong();
result = new RaftMessages.Vote.Request(from, term, candidate, lastLogIndex, lastLogTerm);
} else if (messageType.equals(VOTE_RESPONSE)) {
long term = channel.getLong();
boolean voteGranted = channel.get() == 1;
result = new RaftMessages.Vote.Response(from, term, voteGranted);
} else if (messageType.equals(APPEND_ENTRIES_REQUEST)) {
// how many
long term = channel.getLong();
long prevLogIndex = channel.getLong();
long prevLogTerm = channel.getLong();
long leaderCommit = channel.getLong();
long count = channel.getLong();
RaftLogEntry[] entries = new RaftLogEntry[(int) count];
for (int i = 0; i < count; i++) {
long entryTerm = channel.getLong();
final ReplicatedContent content = marshal.unmarshal(channel);
entries[i] = new RaftLogEntry(entryTerm, content);
}
result = new RaftMessages.AppendEntries.Request(from, term, prevLogIndex, prevLogTerm, entries, leaderCommit);
} else if (messageType.equals(APPEND_ENTRIES_RESPONSE)) {
long term = channel.getLong();
boolean success = channel.get() == 1;
long matchIndex = channel.getLong();
long appendIndex = channel.getLong();
result = new RaftMessages.AppendEntries.Response(from, term, success, matchIndex, appendIndex);
} else if (messageType.equals(NEW_ENTRY_REQUEST)) {
ReplicatedContent content = marshal.unmarshal(channel);
result = new RaftMessages.NewEntry.Request(from, content);
} else if (messageType.equals(HEARTBEAT)) {
long leaderTerm = channel.getLong();
long commitIndexTerm = channel.getLong();
long commitIndex = channel.getLong();
result = new RaftMessages.Heartbeat(from, leaderTerm, commitIndex, commitIndexTerm);
} else if (messageType.equals(HEARTBEAT_RESPONSE)) {
result = new RaftMessages.HeartbeatResponse(from);
} else if (messageType.equals(LOG_COMPACTION_INFO)) {
long leaderTerm = channel.getLong();
long prevIndex = channel.getLong();
result = new RaftMessages.LogCompactionInfo(from, leaderTerm, prevIndex);
} else {
throw new IllegalArgumentException("Unknown message type");
}
list.add(new RaftMessages.ClusterIdAwareMessage(clusterId, result));
}
Aggregations