Beispiel #1
0
        private void SendProposal()
        {
            _acceptsReceived.Clear();
            _masterProposal = null;

            var master = GetBestMasterCandidate();

            if (master == null)
            {
                Log.Trace("ELECTIONS: (V={lastAttemptedView}) NO MASTER CANDIDATE WHEN TRYING TO SEND PROPOSAL.",
                          _lastAttemptedView);
                return;
            }

            _masterProposal = master;

            Log.Debug("ELECTIONS: (V={lastAttemptedView}) SENDING PROPOSAL CANDIDATE: {formatNodeInfo}, ME: {ownInfo}.",
                      _lastAttemptedView, FormatNodeInfo(master), FormatNodeInfo(GetOwnInfo()));

            var proposal = new ElectionMessage.Proposal(_nodeInfo.InstanceId, _nodeInfo.InternalHttp,
                                                        master.InstanceId, master.InternalHttp,
                                                        _lastInstalledView,
                                                        master.EpochNumber, master.EpochPosition, master.EpochId,
                                                        master.LastCommitPosition, master.WriterCheckpoint, master.ChaserCheckpoint);

            Handle(new ElectionMessage.Accept(_nodeInfo.InstanceId, _nodeInfo.InternalHttp,
                                              master.InstanceId, master.InternalHttp, _lastInstalledView));
            SendToAllExceptMe(proposal);
        }
Beispiel #2
0
        public void Handle(ElectionMessage.Proposal message)
        {
            if (_state == ElectionsState.Shutdown)
            {
                return;
            }
            if (message.ServerId == _nodeInfo.InstanceId)
            {
                return;
            }
            if (_state != ElectionsState.NonLeader)
            {
                return;
            }
            if (message.View != _lastInstalledView)
            {
                return;
            }
            if (_servers.All(x => x.InstanceId != message.ServerId))
            {
                return;
            }
            if (_servers.All(x => x.InstanceId != message.MasterId))
            {
                return;
            }

            var candidate = new MasterCandidate(message.MasterId, message.MasterInternalHttp,
                                                message.EpochNumber, message.EpochPosition, message.EpochId,
                                                message.LastCommitPosition, message.WriterCheckpoint, message.ChaserCheckpoint, 0);

            if (!IsLegitimateMaster(message.View, message.ServerInternalHttp, message.ServerId, candidate))
            {
                return;
            }

            Log.Debug(
                "ELECTIONS: (V={lastAttemptedView}) PROPOSAL FROM [{serverInternalHttp},{serverId:B}] M={candidateInfo}. ME={ownInfo}.",
                _lastAttemptedView,
                message.ServerInternalHttp, message.ServerId, FormatNodeInfo(candidate), FormatNodeInfo(GetOwnInfo()));

            if (_masterProposal == null)
            {
                _masterProposal = candidate;
                _acceptsReceived.Clear();
            }

            if (_masterProposal.InstanceId == message.MasterId)
            {
                // NOTE: proposal from other server is also implicit Accept from that server
                Handle(new ElectionMessage.Accept(message.ServerId, message.ServerInternalHttp,
                                                  message.MasterId, message.MasterInternalHttp, message.View));
                var accept = new ElectionMessage.Accept(_nodeInfo.InstanceId, _nodeInfo.InternalHttp,
                                                        message.MasterId, message.MasterInternalHttp, message.View);
                Handle(accept);                 // implicitly sent accept to ourselves
                SendToAllExceptMe(accept);
            }
        }
Beispiel #3
0
 private bool IsCandidateGoodEnough(MasterCandidate candidate, MasterCandidate ownInfo)
 {
     if (candidate.EpochNumber != ownInfo.EpochNumber)
     {
         return(candidate.EpochNumber > ownInfo.EpochNumber);
     }
     if (candidate.LastCommitPosition != ownInfo.LastCommitPosition)
     {
         return(candidate.LastCommitPosition > ownInfo.LastCommitPosition);
     }
     if (candidate.WriterCheckpoint != ownInfo.WriterCheckpoint)
     {
         return(candidate.WriterCheckpoint > ownInfo.WriterCheckpoint);
     }
     if (candidate.ChaserCheckpoint != ownInfo.ChaserCheckpoint)
     {
         return(candidate.ChaserCheckpoint > ownInfo.ChaserCheckpoint);
     }
     return(true);
 }
Beispiel #4
0
        private bool IsLegitimateMaster(int view, IPEndPoint proposingServerEndPoint, Guid proposingServerId,
                                        MasterCandidate candidate)
        {
            var master = _servers.FirstOrDefault(x =>
                                                 x.IsAlive && x.InstanceId == _lastElectedMaster && x.State == VNodeState.Master);

            if (master != null)
            {
                if (candidate.InstanceId == master.InstanceId ||
                    candidate.EpochNumber > master.EpochNumber ||
                    (candidate.EpochNumber == master.EpochNumber && candidate.EpochId != master.EpochId))
                {
                    return(true);
                }

                Log.Debug(
                    "ELECTIONS: (V={view}) NOT LEGITIMATE MASTER PROPOSAL FROM [{proposingServerEndPoint},{proposingServerId:B}] M={candidateInfo}. "
                    + "PREVIOUS MASTER IS ALIVE: [{masterInternalHttp},{masterId:B}].",
                    view, proposingServerEndPoint, proposingServerId, FormatNodeInfo(candidate),
                    master.InternalHttpEndPoint, master.InstanceId);
                return(false);
            }

            if (candidate.InstanceId == _nodeInfo.InstanceId)
            {
                return(true);
            }

            var ownInfo = GetOwnInfo();

            if (!IsCandidateGoodEnough(candidate, ownInfo))
            {
                Log.Debug(
                    "ELECTIONS: (V={view}) NOT LEGITIMATE MASTER PROPOSAL FROM [{proposingServerEndPoint},{proposingServerId:B}] M={candidateInfo}. ME={ownInfo}.",
                    view, proposingServerEndPoint, proposingServerId, FormatNodeInfo(candidate),
                    FormatNodeInfo(ownInfo));
                return(false);
            }

            return(true);
        }
Beispiel #5
0
        private void ShiftToLeaderElection(int view)
        {
            Log.Debug("ELECTIONS: (V={view}) SHIFT TO LEADER ELECTION.", view);

            _state = ElectionsState.ElectingLeader;
            _vcReceived.Clear();
            _prepareOkReceived.Clear();
            _lastAttemptedView = view;

            _masterProposal = null;
            _master         = null;
            _acceptsReceived.Clear();

            var viewChangeMsg = new ElectionMessage.ViewChange(_nodeInfo.InstanceId, _nodeInfo.InternalHttp, view);

            Handle(viewChangeMsg);
            SendToAllExceptMe(viewChangeMsg);
            _publisher.Publish(TimerMessage.Schedule.Create(LeaderElectionProgressTimeout,
                                                            _publisherEnvelope,
                                                            new ElectionMessage.ElectionsTimedOut(view)));
        }
Beispiel #6
0
 private static string FormatNodeInfo(MasterCandidate candidate)
 {
     return(FormatNodeInfo(candidate.InternalHttp, candidate.InstanceId,
                           candidate.LastCommitPosition, candidate.WriterCheckpoint, candidate.ChaserCheckpoint,
                           candidate.EpochNumber, candidate.EpochPosition, candidate.EpochId));
 }