internal Task ModifyTopology(Topology requested) { if (State != RaftEngineState.Leader) { throw new NotLeadingException("Cannot modify topology from a non leader node, current leader is: " + (CurrentLeader ?? "no leader")); } var logEntry = PersistentState.GetLogEntry(CommitIndex); if (logEntry == null) { throw new InvalidOperationException("No log entry for committed for index " + CommitIndex + ", this is probably a brand new cluster with no committed entries or a serious problem"); } if (logEntry.Term != PersistentState.CurrentTerm) { throw new InvalidOperationException("Cannot modify the cluster topology when the committed index " + CommitIndex + " is in term " + logEntry.Term + " but the current term is " + PersistentState.CurrentTerm + ". Wait until the leader finishes committing entries from the current term and try again"); } var tcc = new TopologyChangeCommand { Completion = new TaskCompletionSource <object>(), Requested = requested, Previous = _currentTopology, BufferCommand = false, }; if (Interlocked.CompareExchange(ref _changingTopology, tcc.Completion.Task, null) != null) { throw new InvalidOperationException("Cannot change the cluster topology while another topology change is in progress"); } try { if (_log.IsDebugEnabled) { _log.Debug("Topology change started on leader"); } StartTopologyChange(tcc); AppendCommand(tcc); return(tcc.Completion.Task); } catch (Exception) { Interlocked.Exchange(ref _changingTopology, null); throw; } }