コード例 #1
0
        // TODO: This method is inefficient.. we should not have to update this state by a complete
        // TODO: iteration each time. Instead it should be updated as a direct response to each
        // TODO: append response.
        public static long QuorumAppendIndex <MEMBER>(ISet <MEMBER> votingMembers, FollowerStates <MEMBER> states)
        {
            /*
             * Build up a map of tx id -> number of instances that have appended,
             * sorted by tx id.
             *
             * This allows us to then iterate backwards over the values in the map,
             * adding up a total count of how many have appended, until we reach a majority.
             * Once we do, the tx id at the current entry in the map will be the highest one
             * with a majority appended.
             */

            SortedDictionary <long, int> appendedCounts = new SortedDictionary <long, int>();

            foreach (MEMBER member in votingMembers)
            {
                long txId = states.Get(member).MatchIndex;
                appendedCounts.merge(txId, 1, (a, b) => a + b);
            }

            // Iterate over it until we find a majority
            int total = 0;

            foreach (KeyValuePair <long, int> entry in appendedCounts.descendingMap().entrySet())
            {
                total += entry.Value;
                if (MajorityIncludingSelfQuorum.IsQuorum(votingMembers.Count, total))
                {
                    return(entry.Key);
                }
            }

            // No majority for any appended entry
            return(-1);
        }
コード例 #2
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);
        }
コード例 #3
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);
        }
コード例 #4
0
            public override RaftMembershipStateMachineEventHandler OnFollowerStateChange(FollowerStates <MemberId> followerStates)
            {
                CatchupGoalTracker.updateProgress(followerStates.Get(outerInstance.catchingUpMember));

                if (CatchupGoalTracker.Finished)
                {
                    if (CatchupGoalTracker.GoalAchieved)
                    {
                        ISet <MemberId> updatedVotingMembers = new HashSet <MemberId>(outerInstance.membershipManager.VotingMembers());
                        updatedVotingMembers.Add(outerInstance.catchingUpMember);
                        outerInstance.membershipManager.DoConsensus(updatedVotingMembers);

                        MovingToConsensus = true;
                        return(new ConsensusInProgress(_outerInstance));
                    }
                    else
                    {
                        return(new Idle(_outerInstance));
                    }
                }
                return(this);
            }