Exemple #1
0
            public override Void Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response appendResponse)
            {
                Channel.putLong(appendResponse.Term());
                Channel.put(( sbyte )(appendResponse.Success() ? 1 : 0));
                Channel.putLong(appendResponse.MatchIndex());
                Channel.putLong(appendResponse.AppendIndex());

                return(null);
            }
Exemple #2
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_Request req) throws java.io.IOException
            public override Outcome Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request req)
            {
                if (req.LeaderTerm() < Ctx.term())
                {
                    Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response appendResponse = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(Ctx.myself(), Ctx.term(), false, req.PrevLogIndex(), Ctx.entryLog().appendIndex());

                    Outcome.addOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(req.From(), appendResponse));
                    return(Outcome);
                }

                Outcome.NextRole = FOLLOWER;
                Log.info("Moving to FOLLOWER state after receiving append entries request from %s at term %d (I am at %d)n", req.From(), req.LeaderTerm(), Ctx.term());
                Appending.HandleAppendEntriesRequest(Ctx, Outcome, req, Log);
                return(Outcome);
            }
Exemple #3
0
 public override Outcome Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response)
 {
     return(Outcome);
 }
Exemple #4
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldStepDownIfAppendEntriesRequestFromLaterTerm() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldStepDownIfAppendEntriesRequestFromLaterTerm()
        {
            // given
            long leaderTerm        = 1;
            long leaderCommitIndex = 10;
            long rivalTerm         = leaderTerm + 1;
            long logIndex          = 20;

            RaftLogEntry[] entries = new RaftLogEntry[] { new RaftLogEntry(rivalTerm, ReplicatedInteger.valueOf(99)) };

            Leader    leader = new Leader();
            RaftState state  = raftState().term(leaderTerm).commitIndex(leaderCommitIndex).build();

            // when
            Outcome outcome = leader.Handle(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_member1, rivalTerm, logIndex, leaderTerm, entries, leaderCommitIndex), state, Log());

            // then
            assertThat(outcome.Role, equalTo(FOLLOWER));
            assertThat(outcome.Leader, equalTo(_member1));
            assertThat(outcome.Term, equalTo(rivalTerm));

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_RaftMessage response = messageFor(outcome, _member1);
            assertThat(response, instanceOf(typeof(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response)));
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response typedResponse = (Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response)response;
            assertThat(typedResponse.Term(), equalTo(rivalTerm));
            // Not checking success or failure of append
        }
Exemple #5
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldRespondNegativelyToAppendEntriesRequestFromEarlierTerm() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldRespondNegativelyToAppendEntriesRequestFromEarlierTerm()
        {
            // given
            long leaderTerm        = 5;
            long leaderCommitIndex = 10;
            long rivalTerm         = leaderTerm - 1;
            long logIndex          = 20;

            RaftLogEntry[] entries = new RaftLogEntry[] { new RaftLogEntry(rivalTerm, ReplicatedInteger.valueOf(99)) };

            Leader    leader = new Leader();
            RaftState state  = raftState().term(leaderTerm).commitIndex(leaderCommitIndex).build();

            // when
            Outcome outcome = leader.Handle(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_member1, rivalTerm, logIndex, leaderTerm, entries, leaderCommitIndex), state, Log());

            // then
            assertThat(outcome.Role, equalTo(LEADER));
            assertThat(outcome.Term, equalTo(leaderTerm));

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_RaftMessage response = messageFor(outcome, _member1);
            assertThat(response, instanceOf(typeof(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response)));
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response typedResponse = (Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response)response;
            assertThat(typedResponse.Term(), equalTo(leaderTerm));
            assertThat(typedResponse.Success(), equalTo(false));
        }
Exemple #6
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void leaderShouldRejectAppendEntriesResponseWithNewerTermAndBecomeAFollower() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void LeaderShouldRejectAppendEntriesResponseWithNewerTermAndBecomeAFollower()
        {
            // given
            RaftState state = raftState().myself(_myself).build();

            Leader leader = new Leader();

            // when
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response message = appendEntriesResponse().from(_member1).term(state.Term() + 1).build();
            Outcome outcome = leader.Handle(message, state, Log());

            // then
            assertEquals(0, count(outcome.OutgoingMessages));
            assertEquals(FOLLOWER, outcome.Role);
            assertEquals(0, count(outcome.LogCommands));
            assertEquals(state.Term() + 1, outcome.Term);
        }
Exemple #7
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldIgnoreAppendResponsesFromOldTerms() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldIgnoreAppendResponsesFromOldTerms()
        {
            // given
            Leader leader       = new Leader();
            long   leaderTerm   = 5;
            long   followerTerm = 3;

            RaftState state = raftState().term(leaderTerm).build();

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response incomingResponse = appendEntriesResponse().failure().term(followerTerm).from(_member1).build();

            // when
            Outcome outcome = leader.Handle(incomingResponse, state, Log());

            // then
            assertThat(outcome.Term, equalTo(leaderTerm));
            assertThat(outcome.Role, equalTo(LEADER));

            assertThat(outcome.OutgoingMessages, empty());
            assertThat(outcome.ShipCommands, empty());
        }
Exemple #8
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public void decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf buffer, java.util.List<Object> list) throws Exception
        public override void Decode(ChannelHandlerContext ctx, ByteBuf buffer, IList <object> list)
        {
            ReadableChannel channel   = new NetworkReadableClosableChannelNetty4(buffer);
            ClusterId       clusterId = ClusterId.Marshal.INSTANCE.unmarshal(channel);

            int messageTypeWire = channel.Int;

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_Type[] values      = Enum.GetValues(typeof(Org.Neo4j.causalclustering.core.consensus.RaftMessages_Type));
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_Type   messageType = values[messageTypeWire];

            MemberId from = RetrieveMember(channel);

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_RaftMessage result;

            if (messageType.Equals(VOTE_REQUEST))
            {
                MemberId candidate = RetrieveMember(channel);

                long term         = channel.Long;
                long lastLogIndex = channel.Long;
                long lastLogTerm  = channel.Long;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Vote_Request(from, term, candidate, lastLogIndex, lastLogTerm);
            }
            else if (messageType.Equals(VOTE_RESPONSE))
            {
                long term        = channel.Long;
                bool voteGranted = channel.Get() == 1;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Vote_Response(from, term, voteGranted);
            }
            else if (messageType.Equals(PRE_VOTE_REQUEST))
            {
                MemberId candidate = RetrieveMember(channel);

                long term         = channel.Long;
                long lastLogIndex = channel.Long;
                long lastLogTerm  = channel.Long;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_PreVote_Request(from, term, candidate, lastLogIndex, lastLogTerm);
            }
            else if (messageType.Equals(PRE_VOTE_RESPONSE))
            {
                long term        = channel.Long;
                bool voteGranted = channel.Get() == 1;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_PreVote_Response(from, term, voteGranted);
            }
            else if (messageType.Equals(APPEND_ENTRIES_REQUEST))
            {
                // how many
                long term         = channel.Long;
                long prevLogIndex = channel.Long;
                long prevLogTerm  = channel.Long;

                long leaderCommit = channel.Long;
                long count        = channel.Long;

                RaftLogEntry[] entries = new RaftLogEntry[( int )count];
                for (int i = 0; i < count; i++)
                {
                    long entryTerm = channel.Long;
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.neo4j.causalclustering.core.replication.ReplicatedContent content = marshal.unmarshal(channel);
                    ReplicatedContent content = _marshal.unmarshal(channel);
                    entries[i] = new RaftLogEntry(entryTerm, content);
                }

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(from, term, prevLogIndex, prevLogTerm, entries, leaderCommit);
            }
            else if (messageType.Equals(APPEND_ENTRIES_RESPONSE))
            {
                long term        = channel.Long;
                bool success     = channel.Get() == 1;
                long matchIndex  = channel.Long;
                long appendIndex = channel.Long;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(from, term, success, matchIndex, appendIndex);
            }
            else if (messageType.Equals(NEW_ENTRY_REQUEST))
            {
                ReplicatedContent content = _marshal.unmarshal(channel);

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_NewEntry_Request(from, content);
            }
            else if (messageType.Equals(HEARTBEAT))
            {
                long leaderTerm      = channel.Long;
                long commitIndexTerm = channel.Long;
                long commitIndex     = channel.Long;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Heartbeat(from, leaderTerm, commitIndex, commitIndexTerm);
            }
            else if (messageType.Equals(HEARTBEAT_RESPONSE))
            {
                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_HeartbeatResponse(from);
            }
            else if (messageType.Equals(LOG_COMPACTION_INFO))
            {
                long leaderTerm = channel.Long;
                long prevIndex  = channel.Long;

                result = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_LogCompactionInfo(from, leaderTerm, prevIndex);
            }
            else
            {
                throw new System.ArgumentException("Unknown message type");
            }

            list.Add(Org.Neo4j.causalclustering.core.consensus.RaftMessages_ReceivedInstantClusterIdAwareMessage.of(_clock.instant(), clusterId, result));
        }
Exemple #9
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 #10
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 #11
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 #12
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 #13
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);
            }
Exemple #14
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_Request req) throws java.io.IOException
            public override Outcome Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request req)
            {
                if (req.LeaderTerm() < Ctx.term())
                {
                    Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response appendResponse = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(Ctx.myself(), Ctx.term(), false, -1, Ctx.entryLog().appendIndex());

                    Outcome.addOutgoingMessage(new Org.Neo4j.causalclustering.core.consensus.RaftMessages_Directed(req.From(), appendResponse));
                    return(Outcome);
                }
                else if (req.LeaderTerm() == Ctx.term())
                {
                    throw new System.InvalidOperationException("Two leaders in the same term.");
                }
                else
                {
                    // There is a new leader in a later term, we should revert to follower. (§5.1)
                    StepDownToFollower(Outcome, Ctx);
                    Log.info("Moving to FOLLOWER state after receiving append request at term %d (my term is " + "%d) from %s", req.LeaderTerm(), Ctx.term(), req.From());
                    Appending.HandleAppendEntriesRequest(Ctx, Outcome, req, Log);
                    return(Outcome);
                }
            }
Exemple #15
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSerializeAppendResponse() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSerializeAppendResponse()
        {
            MemberId sender = new MemberId(System.Guid.randomUUID());

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response request = (new AppendEntriesResponseBuilder()).from(sender).success().matchIndex(12).build();
            SerializeReadBackAndVerifyMessage(request);
        }
Exemple #16
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSendCompactionInfoIfFailureWithNoEarlierEntries() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSendCompactionInfoIfFailureWithNoEarlierEntries()
        {
            // given
            Leader leader          = new Leader();
            long   term            = 1;
            long   leaderPrevIndex = 3;
            long   followerIndex   = leaderPrevIndex - 1;

            InMemoryRaftLog raftLog = new InMemoryRaftLog();

            raftLog.Skip(leaderPrevIndex, term);

            RaftState state = raftState().term(term).entryLog(raftLog).build();

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response incomingResponse = appendEntriesResponse().failure().term(term).appendIndex(followerIndex).from(_member1).build();

            // when
            Outcome outcome = leader.Handle(incomingResponse, state, Log());

            // then
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_RaftMessage outgoingMessage = messageFor(outcome, _member1);
            assertThat(outgoingMessage, instanceOf(typeof(Org.Neo4j.causalclustering.core.consensus.RaftMessages_LogCompactionInfo)));

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_LogCompactionInfo typedOutgoingMessage = (Org.Neo4j.causalclustering.core.consensus.RaftMessages_LogCompactionInfo)outgoingMessage;
            assertThat(typedOutgoingMessage.PrevIndex(), equalTo(leaderPrevIndex));
        }
Exemple #17
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldEncodeAndDecodeAppendEntriesResponse()
        public virtual void ShouldEncodeAndDecodeAppendEntriesResponse()
        {
            // given
            MemberId member = new MemberId(System.Guid.randomUUID());

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response response = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Response(member, 1, false, -1, 0);

            // when
            _channel.writeOutbound(response);
            object message = _channel.readOutbound();

            _channel.writeInbound(message);

            // then
            assertEquals(response, _channel.readInbound());
        }
Exemple #18
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));
        }