public void Send(JsonOperationContext context, AppendEntries ae, List <BlittableJsonReaderObject> items = null) { var msg = new DynamicJsonValue { ["Type"] = nameof(AppendEntries), [nameof(AppendEntries.EntriesCount)] = ae.EntriesCount, [nameof(AppendEntries.LeaderCommit)] = ae.LeaderCommit, [nameof(AppendEntries.PrevLogIndex)] = ae.PrevLogIndex, [nameof(AppendEntries.PrevLogTerm)] = ae.PrevLogTerm, [nameof(AppendEntries.Term)] = ae.Term, [nameof(AppendEntries.TruncateLogBefore)] = ae.TruncateLogBefore, [nameof(AppendEntries.TimeAsLeader)] = ae.TimeAsLeader }; if (ae.ForceElections) { msg[nameof(AppendEntries.ForceElections)] = true; } Send(context, msg); if (items == null || items.Count == 0) { return; } foreach (var item in items) { Send(context, item); } }
public void Send(JsonOperationContext context, Action updateFollowerTicks, AppendEntries ae, List <BlittableJsonReaderObject> items = null) { if (_log.IsInfoEnabled) { if (ae.EntriesCount > 0) { _log.Info( $"AppendEntries ({ae.EntriesCount:#,#;;0}) in {ae.Term:#,#;;0}, commit: {ae.LeaderCommit:#,#;;0}, leader for: {ae.TimeAsLeader:#,#;;0}, ({ae.PrevLogIndex:#,#;;0} / {ae.PrevLogTerm:#,#;;0}), truncate: {ae.TruncateLogBefore:#,#;;0}, force elections: {ae.ForceElections}."); } } var msg = new DynamicJsonValue { ["Type"] = nameof(AppendEntries), [nameof(AppendEntries.EntriesCount)] = ae.EntriesCount, [nameof(AppendEntries.LeaderCommit)] = ae.LeaderCommit, [nameof(AppendEntries.PrevLogIndex)] = ae.PrevLogIndex, [nameof(AppendEntries.PrevLogTerm)] = ae.PrevLogTerm, [nameof(AppendEntries.Term)] = ae.Term, [nameof(AppendEntries.TruncateLogBefore)] = ae.TruncateLogBefore, [nameof(AppendEntries.TimeAsLeader)] = ae.TimeAsLeader, [nameof(AppendEntries.SendingThread)] = Thread.CurrentThread.ManagedThreadId, [nameof(AppendEntries.MinCommandVersion)] = ae.MinCommandVersion }; if (ae.ForceElections) { msg[nameof(AppendEntries.ForceElections)] = true; } Send(context, msg); if (items == null || items.Count == 0) { return; } foreach (var item in items) { updateFollowerTicks(); Send(context, item); } }
private (bool HasRemovedFromTopology, long LastAcknowledgedIndex, long LastTruncate, long LastCommit) ApplyLeaderStateToLocalState(Stopwatch sp, ClusterOperationContext context, List <RachisEntry> entries, AppendEntries appendEntries) { long lastTruncate; long lastCommit; bool removedFromTopology = false; // we start the tx after we finished reading from the network if (_engine.Log.IsInfoEnabled) { _engine.Log.Info($"{ToString()}: Ready to start tx in {sp.Elapsed}"); } using (var tx = context.OpenWriteTransaction()) { _engine.ValidateTerm(_term); if (_engine.Log.IsInfoEnabled) { _engine.Log.Info($"{ToString()}: Tx running in {sp.Elapsed}"); } if (entries.Count > 0) { var(lastTopology, lastTopologyIndex) = _engine.AppendToLog(context, entries); using (lastTopology) { if (lastTopology != null) { if (_engine.Log.IsInfoEnabled) { _engine.Log.Info($"Topology changed to {lastTopology}"); } var topology = JsonDeserializationRachis <ClusterTopology> .Deserialize(lastTopology); if (topology.Members.ContainsKey(_engine.Tag) || topology.Promotables.ContainsKey(_engine.Tag) || topology.Watchers.ContainsKey(_engine.Tag)) { RachisConsensus.SetTopology(_engine, context, topology); } else { removedFromTopology = true; _engine.ClearAppendedEntriesAfter(context, lastTopologyIndex); } } } } var lastEntryIndexToCommit = Math.Min( _engine.GetLastEntryIndex(context), appendEntries.LeaderCommit); var lastAppliedIndex = _engine.GetLastCommitIndex(context); var lastAppliedTerm = _engine.GetTermFor(context, lastEntryIndexToCommit); // we start to commit only after we have any log with a term of the current leader if (lastEntryIndexToCommit > lastAppliedIndex && lastAppliedTerm == appendEntries.Term) { lastAppliedIndex = _engine.Apply(context, lastEntryIndexToCommit, null, sp); } lastTruncate = Math.Min(appendEntries.TruncateLogBefore, lastAppliedIndex); _engine.TruncateLogBefore(context, lastTruncate); lastCommit = lastAppliedIndex; if (_engine.Log.IsInfoEnabled) { _engine.Log.Info($"{ToString()}: Ready to commit in {sp.Elapsed}"); } tx.Commit(); } if (_engine.Log.IsInfoEnabled) { _engine.Log.Info($"{ToString()}: Processing entries request with {entries.Count} entries took {sp.Elapsed}"); } var lastAcknowledgedIndex = entries.Count == 0 ? appendEntries.PrevLogIndex : entries[entries.Count - 1].Index; return(HasRemovedFromTopology : removedFromTopology, LastAcknowledgedIndex : lastAcknowledgedIndex, LastTruncate : lastTruncate, LastCommit : lastCommit); }