예제 #1
0
        public void SendAppendEntries(int peerId, long term, int leaderId, long prevLogIndex, long prevLogTerm,
                                      Entry[] entries, long leaderCommit, AppendEntriesResponseHandler handler)
        {
            if (rafts.TryGetValue(peerId, out var r))
            {
                Task.Run(() =>
                {
                    //    await Task.Delay(randomDelay());

                    try
                    {
                        r.HandleAppendEntriesRequest(term, leaderId, prevLogIndex, prevLogTerm, entries, leaderCommit, handler);
                    }
                    catch (Exception)
                    {
                        // logger.error(t.getMessage(), t);
                    }
                });
            }
        }
예제 #2
0
        public void HandleAppendEntriesRequest(long term, int leaderId, long prevLogIndex, long prevLogTerm, IEnumerable <Entry> entries,
                                               long leaderCommit, AppendEntriesResponseHandler handler)
        {
            lock (this)
            {
                if (!Log.IsRunning)
                {
                    return;
                }

                logger.LogTrace($"{this} append entries from {leaderId}: from <{prevLogTerm}:{prevLogIndex}>");
                if (term >= currentTerm)
                {
                    bool rescheduled = false;
                    if (term > currentTerm || this.leaderId != leaderId)
                    {
                        this.leaderId = leaderId;
                        rescheduled   = StepDown(term);
                        role          = Role.Follower;
                    }

                    if (!rescheduled)
                    {
                        RescheduleElection();
                    }

                    if (Log.IsConsistentWith(prevLogIndex, prevLogTerm))
                    {
                        if (entries != null)
                        {
                            foreach (Entry e in entries)
                            {
                                if (!Log.Append(e))
                                {
                                    logger.LogWarning($"{this} is failing append entries from {leaderId}: {e}");
                                    handler(currentTerm, false, Log.LastIndex);
                                    return;
                                }
                            }
                        }

                        Log.CommitIndex = Math.Min(leaderCommit, Log.LastIndex);

                        logger.LogTrace($"{this} is fine with append entries from {leaderId}");
                        if (handler != null)
                        {
                            handler(currentTerm, true, Log.LastIndex);
                        }
                        return;
                    }
                    else
                    {
                        logger.LogWarning($"{this} is failing with inconsistent append entries from {leaderId}");
                        logger.LogWarning($"Leader prevLogTerm={prevLogTerm}, prevLogIndex={prevLogIndex}");
                        logger.LogWarning($"Follower firstTerm={Log.FirstTerm}, firstIndex={Log.FirstIndex}");
                        logger.LogWarning($"Follower lastTerm={Log.LastTerm}, lastIndex={Log.LastIndex}");

                        if (prevLogIndex > Log.CommitIndex)
                        {
                            Log.WipeConflictedEntries(prevLogIndex);
                        }
                        else
                        {
                            Stop();
                        }
                    }
                }

                logger.LogTrace($"{this} is rejecting append entries from {leaderId}");
                handler(currentTerm, false, Log.LastIndex);
            }
        }
예제 #3
0
        void IRaftRPC.SendAppendEntries(int peerId, long term, int leaderId, long prevLogIndex, long prevLogTerm, Entry[] entries, long leaderCommit, AppendEntriesResponseHandler handler)
        {
            var peer = Configuration.GetPeer(peerId);

            string data = "[]";

            if (entries != null)
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                    {
                        foreach (var entry in entries)
                        {
                            entry.Serialize(writer);
                        }
                    }
                    data = Convert.ToBase64String(stream.ToArray());
                }
            }
            var msg = new RequestMessage(peerId, term, leaderId, prevLogIndex, prevLogTerm, data, leaderCommit);

            Task.Run(async() =>
            {
                var response = await sender.SendMessage(peer, msg) as ResponseMessage;
                if (response != null)
                {
                    handler(response.Term, response.Success, response.LastLogIndex);
                }
            });
        }