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); } }); } }
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); } }
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); } }); }