Exemple #1
0
//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);
            }
Exemple #2
0
//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));
        }
Exemple #3
0
        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();
            }
        }
Exemple #4
0
        // 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));
        }
Exemple #5
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));
        }
Exemple #6
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);
        }
Exemple #7
0
//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);
        }
Exemple #8
0
//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);
        }
Exemple #9
0
        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();
        }
Exemple #10
0
//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));
            }
        }
Exemple #11
0
 internal virtual void StepDownToFollower(Outcome outcome, ReadableRaftState raftState)
 {
     outcome.SteppingDown(raftState.Term());
     outcome.NextRole = FOLLOWER;
     outcome.Leader   = null;
 }
Exemple #12
0
//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));
        }
Exemple #13
0
//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));
        }