예제 #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_AppendEntries_Response response) throws java.io.IOException
            public override Outcome Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response)
            {
                if (response.Term() < Ctx.term())
                {
                    /* Ignore responses from old terms! */
                    return(Outcome);
                }
                else if (response.Term() > Ctx.term())
                {
                    Outcome.NextTerm = response.Term();
                    StepDownToFollower(Outcome, Ctx);
                    Log.info("Moving to FOLLOWER state after receiving append response at term %d (my term is " + "%d) from %s", response.Term(), Ctx.term(), response.From());
                    Outcome.replaceFollowerStates(new FollowerStates <MemberId>());
                    return(Outcome);
                }

                FollowerState follower = Ctx.followerStates().get(response.From());

                if (response.Success())
                {
                    Debug.Assert(response.MatchIndex() <= Ctx.entryLog().appendIndex());

                    bool followerProgressed = response.MatchIndex() > follower.MatchIndex;

                    Outcome.replaceFollowerStates(Outcome.FollowerStates.onSuccessResponse(response.From(), max(response.MatchIndex(), follower.MatchIndex)));

                    Outcome.addShipCommand(new ShipCommand.Match(response.MatchIndex(), response.From()));

                    /*
                     * Matches from older terms can in complicated leadership change / log truncation scenarios
                     * be overwritten, even if they were replicated to a majority of instances. Thus we must only
                     * consider matches from this leader's term when figuring out which have been safely replicated
                     * and are ready for commit.
                     * This is explained nicely in Figure 3.7 of the thesis
                     */
                    bool matchInCurrentTerm = Ctx.entryLog().readEntryTerm(response.MatchIndex()) == Ctx.term();

                    /*
                     * The quorum situation may have changed only if the follower actually progressed.
                     */
                    if (followerProgressed && matchInCurrentTerm)
                    {
                        // TODO: Test that mismatch between voting and participating members affects commit outcome

                        long quorumAppendIndex = Followers.quorumAppendIndex(Ctx.votingMembers(), Outcome.FollowerStates);
                        if (quorumAppendIndex > Ctx.commitIndex())
                        {
                            Outcome.LeaderCommit = quorumAppendIndex;
                            Outcome.CommitIndex  = quorumAppendIndex;
                            Outcome.addShipCommand(new ShipCommand.CommitUpdate());
                        }
                    }
                }
                else                         // Response indicated failure.
                {
                    if (response.AppendIndex() > -1 && response.AppendIndex() >= Ctx.entryLog().prevIndex())
                    {
                        // Signal a mismatch to the log shipper, which will serve an earlier entry.
                        Outcome.addShipCommand(new ShipCommand.Mismatch(response.AppendIndex(), response.From()));
                    }
                    else
                    {
                        // There are no earlier entries, message the follower that we have compacted so that
                        // it can take appropriate action.
                        RaftMessages_LogCompactionInfo compactionInfo = new RaftMessages_LogCompactionInfo(Ctx.myself(), Ctx.term(), Ctx.entryLog().prevIndex());
                        Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed directedCompactionInfo = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(response.From(), compactionInfo);

                        Outcome.addOutgoingMessage(directedCompactionInfo);
                    }
                }
                return(Outcome);
            }