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); }
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); } }
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); }
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); }
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))); }
private static string FormatNodeInfo(MasterCandidate candidate) { return(FormatNodeInfo(candidate.InternalHttp, candidate.InstanceId, candidate.LastCommitPosition, candidate.WriterCheckpoint, candidate.ChaserCheckpoint, candidate.EpochNumber, candidate.EpochPosition, candidate.EpochId)); }