//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public org.neo4j.causalclustering.core.consensus.outcome.Outcome handle(org.neo4j.causalclustering.core.consensus.RaftMessages_PreVote_Response res, org.neo4j.causalclustering.core.consensus.outcome.Outcome outcome, org.neo4j.causalclustering.core.consensus.state.ReadableRaftState ctx, org.neo4j.logging.Log log) throws java.io.IOException public override Outcome Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_PreVote_Response res, Outcome outcome, ReadableRaftState ctx, Log log) { if (res.Term() > ctx.Term()) { outcome.NextTerm = res.Term(); outcome.PreElection = false; log.Info("Aborting pre-election after receiving pre-vote response from %s at term %d (I am at %d)", res.From(), res.Term(), ctx.Term()); return(outcome); } else if (res.Term() < ctx.Term() || !res.VoteGranted()) { return(outcome); } if (!res.From().Equals(ctx.Myself())) { outcome.AddPreVoteForMe(res.From()); } if (isQuorum(ctx.VotingMembers(), outcome.PreVotesForMe)) { outcome.RenewElectionTimeout(); outcome.PreElection = false; if (Election.StartRealElection(ctx, outcome, log)) { outcome.NextRole = CANDIDATE; log.Info("Moving to CANDIDATE state after successful pre-election stage"); } } return(outcome); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: static void appendNewEntry(org.neo4j.causalclustering.core.consensus.state.ReadableRaftState ctx, org.neo4j.causalclustering.core.consensus.outcome.Outcome outcome, org.neo4j.causalclustering.core.replication.ReplicatedContent content) throws java.io.IOException internal static void AppendNewEntry(ReadableRaftState ctx, Outcome outcome, ReplicatedContent content) { long prevLogIndex = ctx.EntryLog().appendIndex(); long prevLogTerm = prevLogIndex == -1 ? -1 : prevLogIndex > ctx.LastLogIndexBeforeWeBecameLeader() ? ctx.Term() : ctx.EntryLog().readEntryTerm(prevLogIndex); RaftLogEntry newLogEntry = new RaftLogEntry(ctx.Term(), content); outcome.AddShipCommand(new ShipCommand.NewEntries(prevLogIndex, prevLogTerm, new RaftLogEntry[] { newLogEntry })); outcome.AddLogCommand(new AppendLogEntry(prevLogIndex + 1, newLogEntry)); }
private static void HandleLeaderLogCompaction(ReadableRaftState ctx, Outcome outcome, Org.Neo4j.causalclustering.core.consensus.RaftMessages_LogCompactionInfo compactionInfo) { if (compactionInfo.LeaderTerm() < ctx.Term()) { return; } if (ctx.EntryLog().appendIndex() <= -1 || compactionInfo.PrevIndex() > ctx.EntryLog().appendIndex()) { outcome.MarkNeedForFreshSnapshot(); } }
// TODO: rethink this test, it does too much //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void leaderShouldSpawnMismatchCommandOnFailure() throws Exception //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: public virtual void LeaderShouldSpawnMismatchCommandOnFailure() { // given /* * A leader who * - has an append index of 100 * - knows about instance 2 * - assumes that instance 2 is fully caught up */ Leader leader = new Leader(); MemberId instance2 = member(2); FollowerState instance2State = CreateArtificialFollowerState(100); ReadableRaftState state = mock(typeof(ReadableRaftState)); FollowerStates <MemberId> followerState = new FollowerStates <MemberId>(); followerState = new FollowerStates <MemberId>(followerState, instance2, instance2State); RaftLog log = new InMemoryRaftLog(); for (int i = 0; i <= 100; i++) { log.Append(new RaftLogEntry(0, valueOf(i))); } when(state.CommitIndex()).thenReturn(-1L); when(state.EntryLog()).thenReturn(log); when(state.FollowerStates()).thenReturn(followerState); when(state.Term()).thenReturn(4L); // both leader and follower are in the same term // when // that leader is asked to handle a response from that follower that says that the follower is still missing // things Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response = appendEntriesResponse().failure().appendIndex(0).matchIndex(-1).term(4).from(instance2).build(); Outcome outcome = leader.Handle(response, state, mock(typeof(Log))); // then int mismatchCount = 0; foreach (ShipCommand shipCommand in outcome.ShipCommands) { if (shipCommand is ShipCommand.Mismatch) { mismatchCount++; } } assertThat(mismatchCount, greaterThan(0)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void leaderShouldRespondToSuccessResponseThatIndicatesLaggingFollowerWithJustWhatItsMissing() throws Exception //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: public virtual void LeaderShouldRespondToSuccessResponseThatIndicatesLaggingFollowerWithJustWhatItsMissing() { // given /* * A leader who * - has an append index of 100 * - knows about instance 2 * - assumes that instance 2 is at an index less than 100 -say 50 */ Leader leader = new Leader(); MemberId instance2 = member(2); FollowerState instance2State = CreateArtificialFollowerState(50); ReadableRaftState state = mock(typeof(ReadableRaftState)); FollowerStates <MemberId> followerState = new FollowerStates <MemberId>(); followerState = new FollowerStates <MemberId>(followerState, instance2, instance2State); ReadableRaftLog logMock = mock(typeof(ReadableRaftLog)); when(logMock.AppendIndex()).thenReturn(100L); // with commit requests in this test when(state.CommitIndex()).thenReturn(-1L); when(state.EntryLog()).thenReturn(logMock); when(state.FollowerStates()).thenReturn(followerState); when(state.Term()).thenReturn(231L); // both leader and follower are in the same term // when that leader is asked to handle a response from that follower that says that the follower is still // missing things Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response = appendEntriesResponse().success().matchIndex(89).term(231).from(instance2).build(); Outcome outcome = leader.Handle(response, state, mock(typeof(Log))); // then int matchCount = 0; foreach (ShipCommand shipCommand in outcome.ShipCommands) { if (shipCommand is ShipCommand.Match) { matchCount++; } } assertThat(matchCount, greaterThan(0)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void leaderShouldIgnoreSuccessResponseThatIndicatesLaggingWhileLocalStateIndicatesFollowerIsCaughtUp() throws Exception //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: public virtual void LeaderShouldIgnoreSuccessResponseThatIndicatesLaggingWhileLocalStateIndicatesFollowerIsCaughtUp() { // given /* * A leader who * - has an append index of 100 * - knows about instance 2 * - assumes that instance 2 is fully caught up */ Leader leader = new Leader(); MemberId instance2 = member(2); int j = 100; FollowerState instance2State = CreateArtificialFollowerState(j); ReadableRaftState state = mock(typeof(ReadableRaftState)); FollowerStates <MemberId> followerState = new FollowerStates <MemberId>(); followerState = new FollowerStates <MemberId>(followerState, instance2, instance2State); ReadableRaftLog logMock = mock(typeof(ReadableRaftLog)); when(logMock.AppendIndex()).thenReturn(100L); // with commit requests in this test when(state.CommitIndex()).thenReturn(-1L); when(state.EntryLog()).thenReturn(logMock); when(state.FollowerStates()).thenReturn(followerState); when(state.Term()).thenReturn(4L); // both leader and follower are in the same term // when that leader is asked to handle a response from that follower that says that the follower is still // missing things Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response = appendEntriesResponse().success().matchIndex(80).term(4).from(instance2).build(); Outcome outcome = leader.Handle(response, state, mock(typeof(Log))); // then the leader should not send anything, since this is a delayed, out of order response to a previous append // request assertTrue(outcome.OutgoingMessages.Count == 0); // The follower state should not be touched FollowerStates <MemberId> updatedFollowerStates = outcome.FollowerStates; assertEquals(100, updatedFollowerStates.Get(instance2).MatchIndex); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void leaderShouldNotRespondToSuccessResponseThatIndicatesUpToDateFollower() throws Exception //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: public virtual void LeaderShouldNotRespondToSuccessResponseThatIndicatesUpToDateFollower() { // given /* * A leader who * - has an append index of 100 * - knows about instance 2 * - assumes that instance 2 is at an index less than 100 -say 84 */ Leader leader = new Leader(); MemberId instance2 = member(2); FollowerState instance2State = CreateArtificialFollowerState(84); ReadableRaftState state = mock(typeof(ReadableRaftState)); FollowerStates <MemberId> followerState = new FollowerStates <MemberId>(); followerState = new FollowerStates <MemberId>(followerState, instance2, instance2State); ReadableRaftLog logMock = mock(typeof(ReadableRaftLog)); when(logMock.AppendIndex()).thenReturn(100L); when(state.CommitIndex()).thenReturn(-1L); when(state.EntryLog()).thenReturn(logMock); when(state.FollowerStates()).thenReturn(followerState); when(state.Term()).thenReturn(4L); // both leader and follower are in the same term // when // that leader is asked to handle a response from that follower that says that the follower is up to date Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response = appendEntriesResponse().success().matchIndex(100).term(4).from(instance2).build(); Outcome outcome = leader.Handle(response, state, mock(typeof(Log))); // then // The leader should not be trying to send any messages to that instance assertTrue(outcome.OutgoingMessages.Count == 0); // And the follower state should be updated FollowerStates <MemberId> updatedFollowerStates = outcome.FollowerStates; assertEquals(100, updatedFollowerStates.Get(instance2).MatchIndex); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public static boolean startRealElection(org.neo4j.causalclustering.core.consensus.state.ReadableRaftState ctx, org.neo4j.causalclustering.core.consensus.outcome.Outcome outcome, org.neo4j.logging.Log log) throws java.io.IOException public static bool StartRealElection(ReadableRaftState ctx, Outcome outcome, Log log) { ISet <MemberId> currentMembers = ctx.VotingMembers(); if (currentMembers == null || !currentMembers.Contains(ctx.Myself())) { log.Info("Election attempted but not started, current members are %s, I am %s", currentMembers, ctx.Myself()); return(false); } outcome.NextTerm = ctx.Term() + 1; Org.Neo4j.causalclustering.core.consensus.RaftMessages_Vote_Request voteForMe = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Vote_Request(ctx.Myself(), outcome.Term, ctx.Myself(), ctx.EntryLog().appendIndex(), ctx.EntryLog().readEntryTerm(ctx.EntryLog().appendIndex())); currentMembers.Where(member => !member.Equals(ctx.Myself())).ForEach(member => outcome.addOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(member, voteForMe))); outcome.VotedFor = ctx.Myself(); log.Info("Election started with vote request: %s and members: %s", voteForMe, currentMembers); return(true); }
private void Defaults(Role currentRole, ReadableRaftState ctx) { _nextRole = currentRole; _term = ctx.Term(); _leader = ctx.Leader(); _leaderCommit = ctx.LeaderCommit(); _votedFor = ctx.VotedFor(); _renewElectionTimeout = false; _needsFreshSnapshot = false; _isPreElection = (currentRole == Role.FOLLOWER) && ctx.PreElection; _steppingDownInTerm = long?.empty(); _preVotesForMe = _isPreElection ? new HashSet <MemberId>(ctx.PreVotesForMe()) : emptySet(); _votesForMe = (currentRole == Role.CANDIDATE) ? new HashSet <MemberId>(ctx.VotesForMe()) : emptySet(); _heartbeatResponses = (currentRole == Role.LEADER) ? new HashSet <MemberId>(ctx.HeartbeatResponses()) : emptySet(); _lastLogIndexBeforeWeBecameLeader = (currentRole == Role.LEADER) ? ctx.LastLogIndexBeforeWeBecameLeader() : -1; _followerStates = (currentRole == Role.LEADER) ? ctx.FollowerStates() : new FollowerStates <MemberId>(); _commitIndex = ctx.CommitIndex(); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: static void sendHeartbeats(org.neo4j.causalclustering.core.consensus.state.ReadableRaftState ctx, org.neo4j.causalclustering.core.consensus.outcome.Outcome outcome) throws java.io.IOException internal static void SendHeartbeats(ReadableRaftState ctx, Outcome outcome) { long commitIndex = ctx.CommitIndex(); long commitIndexTerm = ctx.EntryLog().readEntryTerm(commitIndex); RaftMessages_Heartbeat heartbeat = new RaftMessages_Heartbeat(ctx.Myself(), ctx.Term(), commitIndex, commitIndexTerm); foreach (MemberId to in ReplicationTargets(ctx)) { outcome.AddOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(to, heartbeat)); } }
internal virtual void StepDownToFollower(Outcome outcome, ReadableRaftState raftState) { outcome.SteppingDown(raftState.Term()); outcome.NextRole = FOLLOWER; outcome.Leader = null; }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: static void handleAppendEntriesRequest(org.neo4j.causalclustering.core.consensus.state.ReadableRaftState state, org.neo4j.causalclustering.core.consensus.outcome.Outcome outcome, org.neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request, org.neo4j.logging.Log log) throws java.io.IOException internal static void HandleAppendEntriesRequest(ReadableRaftState state, Outcome outcome, Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request, Log log) { if (request.LeaderTerm() < state.Term()) { Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response appendResponse = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(state.Myself(), state.Term(), false, -1, state.EntryLog().appendIndex()); outcome.AddOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(request.From(), appendResponse)); return; } outcome.PreElection = false; outcome.NextTerm = request.LeaderTerm(); outcome.Leader = request.From(); outcome.LeaderCommit = request.LeaderCommit(); if (!Follower.LogHistoryMatches(state, request.PrevLogIndex(), request.PrevLogTerm())) { Debug.Assert(request.PrevLogIndex() > -1 && request.PrevLogTerm() > -1); Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response appendResponse = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(state.Myself(), request.LeaderTerm(), false, -1, state.EntryLog().appendIndex()); outcome.AddOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.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 (logIndex <= state.CommitIndex()) // first, assert that we haven't committed what we are about to truncate { throw new System.InvalidOperationException(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); long endMatchIndex = request.PrevLogIndex() + request.Entries().Length; // this is the index of the last incoming entry Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response appendResponse = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(state.Myself(), request.LeaderTerm(), true, endMatchIndex, endMatchIndex); outcome.AddOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(request.From(), appendResponse)); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: static void appendNewEntries(org.neo4j.causalclustering.core.consensus.state.ReadableRaftState ctx, org.neo4j.causalclustering.core.consensus.outcome.Outcome outcome, java.util.Collection<org.neo4j.causalclustering.core.replication.ReplicatedContent> contents) throws java.io.IOException internal static void AppendNewEntries(ReadableRaftState ctx, Outcome outcome, ICollection <ReplicatedContent> contents) { long prevLogIndex = ctx.EntryLog().appendIndex(); long prevLogTerm = prevLogIndex == -1 ? -1 : prevLogIndex > ctx.LastLogIndexBeforeWeBecameLeader() ? ctx.Term() : ctx.EntryLog().readEntryTerm(prevLogIndex); //JAVA TO C# CONVERTER TODO TASK: Method reference constructor syntax is not converted by Java to C# Converter: RaftLogEntry[] raftLogEntries = contents.Select(content => new RaftLogEntry(ctx.Term(), content)).ToArray(RaftLogEntry[] ::new); outcome.AddShipCommand(new ShipCommand.NewEntries(prevLogIndex, prevLogTerm, raftLogEntries)); outcome.AddLogCommand(new BatchAppendLogEntries(prevLogIndex + 1, 0, raftLogEntries)); }