Esempio n. 1
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public Void handle(org.neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request) throws Exception
            public override Void Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request)
            {
                Out.Add(serializeTerms(request.Entries(), Alloc));
                foreach (RaftLogEntry entry in request.Entries())
                {
                    SerializableContents(entry.Content(), Out);
                }
                return(null);
            }
Esempio n. 2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public Void handle(org.neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest) throws Exception
            public override Void Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest)
            {
                Channel.putLong(appendRequest.LeaderTerm());
                Channel.putLong(appendRequest.PrevLogIndex());
                Channel.putLong(appendRequest.PrevLogTerm());
                Channel.putLong(appendRequest.LeaderCommit());
                Channel.putInt(appendRequest.Entries().Length);

                return(null);
            }
Esempio n. 3
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);
            }
Esempio n. 4
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public Void handle(org.neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest) throws Exception
            public override Void Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest)
            {
                Channel.putLong(appendRequest.LeaderTerm());
                Channel.putLong(appendRequest.PrevLogIndex());
                Channel.putLong(appendRequest.PrevLogTerm());
                Channel.putLong(appendRequest.LeaderCommit());

                Channel.putLong(appendRequest.Entries().Length);

                foreach (RaftLogEntry raftLogEntry in appendRequest.Entries())
                {
                    Channel.putLong(raftLogEntry.Term());
                    Marshal.marshal(raftLogEntry.Content(), Channel);
                }

                return(null);
            }
Esempio n. 5
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);
                }
            }
Esempio n. 6
0
        private void SendRange(long startIndex, long endIndex, LeaderContext leaderContext)
        {
            if (startIndex > endIndex)
            {
                return;
            }

            _lastSentIndex = endIndex;

            try
            {
                int            batchSize = ( int )(endIndex - startIndex + 1);
                RaftLogEntry[] entries   = new RaftLogEntry[batchSize];

                long prevLogIndex = startIndex - 1;
                long prevLogTerm  = _raftLog.readEntryTerm(prevLogIndex);

                if (prevLogTerm > leaderContext.Term)
                {
                    _log.warn("%s aborting send. Not leader anymore? %s, prevLogTerm=%d", StatusAsString(), leaderContext, prevLogTerm);
                    return;
                }

                bool entryMissing = false;
                using (InFlightLogEntryReader logEntrySupplier = new InFlightLogEntryReader(_raftLog, _inFlightCache, false))
                {
                    for (int offset = 0; offset < batchSize; offset++)
                    {
                        entries[offset] = logEntrySupplier.Get(startIndex + offset);
                        if (entries[offset] == null)
                        {
                            entryMissing = true;
                            break;
                        }
                        if (entries[offset].Term() > leaderContext.Term)
                        {
                            _log.warn("%s aborting send. Not leader anymore? %s, entryTerm=%d", StatusAsString(), leaderContext, entries[offset].Term());
                            return;
                        }
                    }
                }

                if (entryMissing || DoesNotExistInLog(prevLogIndex, prevLogTerm))
                {
                    if (_raftLog.prevIndex() >= prevLogIndex)
                    {
                        SendLogCompactionInfo(leaderContext);
                    }
                    else
                    {
                        _log.error("%s: Could not send compaction info and entries were missing, but log is not behind.", StatusAsString());
                    }
                }
                else
                {
                    Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, leaderContext.Term, prevLogIndex, prevLogTerm, entries, leaderContext.CommitIndex);

                    _outbound.send(_follower, appendRequest);
                }
            }
            catch (IOException e)
            {
                _log.warn(StatusAsString() + " exception during batch send", e);
            }
        }
Esempio n. 7
0
        private void SendEmpty(long logIndex, LeaderContext leaderContext)
        {
            ScheduleTimeout(_retryTimeMillis);

            logIndex       = max(_raftLog.prevIndex() + 1, logIndex);
            _lastSentIndex = logIndex;

            try
            {
                long prevLogIndex = logIndex - 1;
                long prevLogTerm  = _raftLog.readEntryTerm(prevLogIndex);

                if (prevLogTerm > leaderContext.Term)
                {
                    _log.warn("%s: aborting send. Not leader anymore? %s, prevLogTerm=%d", StatusAsString(), leaderContext, prevLogTerm);
                    return;
                }

                if (DoesNotExistInLog(prevLogIndex, prevLogTerm))
                {
                    _log.warn("%s: Entry was pruned when sending empty (prevLogIndex=%d, prevLogTerm=%d)", StatusAsString(), prevLogIndex, prevLogTerm);
                    return;
                }

                Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, leaderContext.Term, prevLogIndex, prevLogTerm, RaftLogEntry.empty, leaderContext.CommitIndex);
                _outbound.send(_follower, appendRequest);
            }
            catch (IOException e)
            {
                _log.warn(StatusAsString() + " exception during empty send", e);
            }
        }
Esempio n. 8
0
        private void SendNewEntries(long prevLogIndex, long prevLogTerm, RaftLogEntry[] newEntries, LeaderContext leaderContext)
        {
            ScheduleTimeout(_retryTimeMillis);

            _lastSentIndex = prevLogIndex + 1;

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request appendRequest = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, leaderContext.Term, prevLogIndex, prevLogTerm, newEntries, leaderContext.CommitIndex);

            _outbound.send(_follower, appendRequest);
        }
Esempio n. 9
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSendLastEntryOnStart() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSendLastEntryOnStart()
        {
            // given
            _raftLog.append(_entry0);
            _raftLog.append(_entry1);

            // when
            StartLogShipper();

            // then
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request expected = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, _leaderTerm, 0, _entry0.term(), RaftLogEntry.empty, _leaderCommit);
            assertThat(_outbound.sentTo(_follower), hasItem(expected));
        }
Esempio n. 10
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSerializeAppendRequestWithNoEntries() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSerializeAppendRequestWithNoEntries()
        {
            MemberId sender = new MemberId(System.Guid.randomUUID());

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request = (new AppendEntriesRequestBuilder()).from(sender).leaderCommit(2).leaderTerm(4).build();
            SerializeReadBackAndVerifyMessage(request);
        }
Esempio n. 11
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));
        }
Esempio n. 12
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSendMostRecentlyAvailableEntryIfPruningHappened() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSendMostRecentlyAvailableEntryIfPruningHappened()
        {
            //given
            _raftLog.append(_entry0);
            _raftLog.append(_entry1);
            _raftLog.append(_entry2);
            _raftLog.append(_entry3);

            StartLogShipper();

            //when
            _raftLog.prune(2);
            _outbound.clear();
            _logShipper.onMismatch(0, new LeaderContext(0, 0));

            //then
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request expected = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, _leaderTerm, 2, _entry2.term(), RaftLogEntry.empty, _leaderCommit);
            assertThat(_outbound.sentTo(_follower), hasItem(expected));
        }
Esempio n. 13
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSendAllEntriesAndCatchupCompletely() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSendAllEntriesAndCatchupCompletely()
        {
            // given
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int ENTRY_COUNT = catchupBatchSize * 10;
            int entryCount = _catchupBatchSize * 10;
            ICollection <RaftLogEntry> entries = new List <RaftLogEntry>();

            for (int i = 0; i < entryCount; i++)
            {
                entries.Add(new RaftLogEntry(0, ReplicatedInteger.valueOf(i)));
            }

            foreach (RaftLogEntry entry in entries)
            {
                _raftLog.append(entry);
            }

            // then
            StartLogShipper();

            // back-tracking stage
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request expected = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, _leaderTerm, 0, 0, RaftLogEntry.empty, _leaderCommit);
            while (!_outbound.sentTo(_follower).Contains(expected))
            {
                _logShipper.onMismatch(-1, new LeaderContext(0, 0));
            }

            // catchup stage
            long matchIndex;

            do
            {
                Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request last = (Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request)Iterables.last(_outbound.sentTo(_follower));
                matchIndex = last.PrevLogIndex() + last.Entries().Length;

                _outbound.clear();
                _logShipper.onMatch(matchIndex, new LeaderContext(0, 0));
            } while (_outbound.sentTo(_follower).Count > 0);

            assertEquals(entryCount - 1, matchIndex);
        }
Esempio n. 14
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldResendLastSentEntryOnFirstMismatch() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldResendLastSentEntryOnFirstMismatch()
        {
            // given
            _raftLog.append(_entry0);
            StartLogShipper();
            _raftLog.append(_entry1);
            _raftLog.append(_entry2);

            _logShipper.onMatch(0, new LeaderContext(0, 0));
            _logShipper.onNewEntries(0, 0, new RaftLogEntry[] { _entry1 }, new LeaderContext(0, 0));
            _logShipper.onNewEntries(1, 0, new RaftLogEntry[] { _entry2 }, new LeaderContext(0, 0));

            // when
            _outbound.clear();
            _logShipper.onMismatch(1, new LeaderContext(0, 0));

            // then
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request expected = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, _leaderTerm, 1, _entry1.term(), RaftLogEntry.empty, _leaderCommit);
            assertThat(_outbound.sentTo(_follower), hasItem(expected));
        }
Esempio n. 15
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldKeepSendingFirstEntryAfterSeveralMismatches() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldKeepSendingFirstEntryAfterSeveralMismatches()
        {
            // given
            _raftLog.append(_entry0);
            _raftLog.append(_entry1);
            StartLogShipper();

            _logShipper.onMismatch(0, new LeaderContext(0, 0));
            _logShipper.onMismatch(0, new LeaderContext(0, 0));

            // when
            _outbound.clear();
            _logShipper.onMismatch(0, new LeaderContext(0, 0));

            // then
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request expected = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, _leaderTerm, 0, 0, RaftLogEntry.empty, _leaderCommit);
            assertThat(_outbound.sentTo(_follower), hasItem(expected));
        }
Esempio n. 16
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSendPreviousEntryOnMismatch() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSendPreviousEntryOnMismatch()
        {
            // given
            _raftLog.append(_entry0);
            _raftLog.append(_entry1);
            _raftLog.append(_entry2);
            StartLogShipper();               // ships entry2 on start

            // when
            _outbound.clear();
            _logShipper.onMismatch(0, new LeaderContext(0, 0));

            // then: we expect it to ship (empty) entry1 next
            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request expected = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(_leader, _leaderTerm, 0, 0, RaftLogEntry.empty, _leaderCommit);
            assertThat(_outbound.sentTo(_follower), hasItem(expected));
        }
Esempio n. 17
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldSerializeAppendRequestWithMultipleEntries() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldSerializeAppendRequestWithMultipleEntries()
        {
            MemberId sender = new MemberId(System.Guid.randomUUID());

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request = (new AppendEntriesRequestBuilder()).from(sender).leaderCommit(2).leaderTerm(4).logEntry(new RaftLogEntry(1, ReplicatedInteger.valueOf(2))).logEntry(new RaftLogEntry(1, ReplicatedInteger.valueOf(3))).logEntry(new RaftLogEntry(1, ReplicatedInteger.valueOf(4))).build();
            SerializeReadBackAndVerifyMessage(request);
        }
Esempio n. 18
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 request) throws java.io.IOException
            public override Outcome Handle(Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request)
            {
                Appending.HandleAppendEntriesRequest(Ctx, Outcome, request, Log);
                return(Outcome);
            }
Esempio n. 19
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldEncodeAndDecodeAppendEntriesRequest()
        public virtual void ShouldEncodeAndDecodeAppendEntriesRequest()
        {
            // given
            MemberId     member   = new MemberId(System.Guid.randomUUID());
            RaftLogEntry logEntry = new RaftLogEntry(1, ReplicatedInteger.valueOf(1));

            Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request request = new Org.Neo4j.causalclustering.core.consensus.RaftMessages_AppendEntries_Request(member, 1, 1, 99, new RaftLogEntry[] { logEntry }, 1);

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

            _channel.writeInbound(message);

            // then
            assertEquals(request, _channel.readInbound());
        }
Esempio n. 20
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));
        }