Ejemplo n.º 1
0
		public override void Handle(AppendEntriesResponse resp)
		{
			base.Handle(resp);

			var maxIndexOnQuorom = GetMaxIndexOnQuorum();

			var lastLogEntry = Engine.PersistentState.LastLogEntry();

			if (maxIndexOnQuorom >= lastLogEntry.Index)
			{
				_log.Info("Done sending all events to the cluster, can step down gracefully now");
				TransferToBestMatch();
			}
		}
Ejemplo n.º 2
0
        private void PromoteNodeToVoter(AppendEntriesResponse resp)
        {
            // if we got a successful append entries response from a promotable node, and it has caught up
            // with the committed entries, it means that we can promote it to voting positions, since it
            // can now become a leader.
            var upgradedNode = Engine.CurrentTopology.GetNodeByName(resp.From);
            if (upgradedNode == null)
                return;
            var requestTopology = new Topology(
                Engine.CurrentTopology.TopologyId,
                Engine.CurrentTopology.AllVotingNodes.Union(new[] { upgradedNode }),
                Engine.CurrentTopology.NonVotingNodes,
                Engine.CurrentTopology.PromotableNodes.Where(x => x != upgradedNode)
                );
            if (Engine.CurrentlyChangingTopology() == false)
            {
                _log.Info(
                    "Node {0} is a promotable node, and it has caught up to the current cluster commit index, but we are currently updating the topology, will try again later",
                    resp.From);
                return;
            }

            _log.Info(
                "Node {0} is a promotable node, and it has caught up to the current cluster commit index, promoting to voting member",
                resp.From);
            Engine.ModifyTopology(requestTopology);
        }
Ejemplo n.º 3
0
        public override void Handle(AppendEntriesResponse resp)
        {
            if (FromOurTopology(resp) == false)
            {
                _log.Info("Got an append entries response message outside my cluster topology (id: {0}), ignoring", resp.ClusterTopologyId);
                return;
            }

            if (Engine.CurrentTopology.Contains(resp.From) == false)
            {
                _log.Info("Rejecting append entries response from {0} because it is not in my cluster", resp.From);
                return;
            }

            _log.Debug("Handling AppendEntriesResponse from {0}", resp.From);

            // there is a new leader in town, time to step down
            if (resp.CurrentTerm > Engine.PersistentState.CurrentTerm)
            {
                Engine.UpdateCurrentTerm(resp.CurrentTerm, resp.LeaderId);
                return;
            }

            Debug.Assert(resp.From != null);
            _nextIndexes[resp.From] = resp.LastLogIndex + 1;
            _matchIndexes[resp.From] = resp.LastLogIndex;
            _lastContact[resp.From] = DateTime.UtcNow;

            if (Engine.CurrentTopology.IsPromotable(resp.From) &&
                resp.LastLogIndex == Engine.CommitIndex)
            {
                PromoteNodeToVoter(resp);
            }

            _log.Debug("Follower ({0}) has LastLogIndex = {1}", resp.From, resp.LastLogIndex);

            if (resp.Success == false)
            {
                _log.Debug("Received Success = false in AppendEntriesResponse from {1}. Now _nextIndexes[{1}] = {0}. Reason: {2}",
                    _nextIndexes[resp.From], resp.From, resp.Message);
                return;
            }

            var maxIndexOnCurrentQuorum = GetMaxIndexOnQuorum();
            if (maxIndexOnCurrentQuorum <= Engine.CommitIndex)
            {
                _log.Debug("maxIndexOnCurrentQuorum = {0} <= Engine.CommitIndex = {1}.",
                    maxIndexOnCurrentQuorum, Engine.CommitIndex);
                return;
            }

            // we update the heartbeat time whenever we get a successful quorum, because
            // that means that we are good to run without any issues. Further handling is done
            // in the HandleTimeout, to handle a situation where the leader can't talk to the clients
            LastHeartbeatTime = DateTime.UtcNow;

            _log.Debug(
                "AppendEntriesResponse => applying commits, maxIndexOnQuorom = {0}, Engine.CommitIndex = {1}", maxIndexOnCurrentQuorum,
                Engine.CommitIndex);
            Engine.ApplyCommits(Engine.CommitIndex + 1, maxIndexOnCurrentQuorum, _pendingCommands.ToDictionary(x => x.AssignedIndex, x => x));

            Command result;
            while (_pendingCommands.TryPeek(out result) && result.AssignedIndex <= maxIndexOnCurrentQuorum)
            {
                if (_pendingCommands.TryDequeue(out result) == false)
                    break; // should never happen

                result.Complete();
            }
        }
Ejemplo n.º 4
0
			public override void Reply(AppendEntriesResponse resp)
			{
				Reply(resp.Success, resp);	
			}
Ejemplo n.º 5
0
		public void SendToSelf(AppendEntriesResponse resp)
		{
			Publish(resp, null);
		}
Ejemplo n.º 6
0
		public void SendToSelf(AppendEntriesResponse resp)
		{
			_bus.SendToSelf(resp);
		}
Ejemplo n.º 7
0
 public abstract void Reply(AppendEntriesResponse resp);
Ejemplo n.º 8
0
		public virtual void Handle(AppendEntriesResponse resp)
		{
			// not a leader, no idea what to do with this. Probably an old
			// message from when we were a leader, ignoring.			
		}