Exemplo n.º 1
0
        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;
            }
        }