private int ProcessRequestVote(Protocol p) { lock (this) { var r = p as RequestVote; if (LogSequence.TrySetTerm(r.Argument.Term)) { // new term found. ConvertStateTo(RaftState.Follower); } // else continue process r.Result.Term = LogSequence.Term; // RequestVote RPC // Receiver implementation: // 1.Reply false if term < currentTerm(§5.1) // 2.If votedFor is null or candidateId, and candidate’s log is at // least as up - to - date as receiver’s log, grant vote(§5.2, §5.4) r.Result.VoteGranted = (r.Argument.Term >= LogSequence.Term) && LogSequence.CanVoteFor(r.Argument.CandidateId) && IsLastLogUpToDate(r.Argument.LastLogTerm, r.Argument.LastLogIndex); if (r.Result.VoteGranted) { LogSequence.SetVoteFor(r.Argument.CandidateId); } logger.Debug("{0}: VoteFor={1} Rpc={2}", Name, LogSequence.VoteFor, r); r.SendResultCode(0); return(Procedure.Success); } }
private void SendRequestVote(SchedulerTask ThisTask) { lock (this) { VoteSuccess.Clear(); // 每次选举开始清除。 LeaderId = string.Empty; LogSequence.SetVoteFor(Name); // Vote Self First. LogSequence.TrySetTerm(LogSequence.Term + 1); WaitMajorityVoteTimoutTask?.Cancel(); WaitMajorityVoteTimoutTask = null; var arg = new RequestVoteArgument(); arg.Term = LogSequence.Term; arg.CandidateId = Name; var log = LogSequence.LastRaftLog(); arg.LastLogIndex = log.Index; arg.LastLogTerm = log.Term; Server.Config.ForEachConnector( (c) => { if (false == c.IsHandshakeDone) { return; } var rpc = new RequestVote() { Argument = arg }; rpc.Send(c.Socket, (p) => ProcessRequestVoteResult(rpc, c)); logger.Debug("{0}: SendRequestVote {1}", Name, rpc); }); // 定时,如果超时选举还未完成,再次发起选举。 WaitMajorityVoteTimoutTask = Scheduler.Instance.Schedule( (ThisTask) => { lock (this) { StartRequestVoteDelayTask = null; ConvertStateTo(RaftState.Candidate); } }, RaftConfig.AppendEntriesTimeout + 1000); } }
private void ConvertStateFromFollwerTo(RaftState newState) { switch (newState) { case RaftState.Follower: logger.Info($"RaftState {Name}: Follower->Follower"); return; case RaftState.Candidate: logger.Info($"RaftState {Name}: Follower->Candidate"); State = RaftState.Candidate; LeaderLostTimerTask?.Cancel(); LeaderLostTimerTask = null; LogSequence.SetVoteFor(string.Empty); // 先清除,在真正自荐前可以给别人投票。 StartRequestVote(); return; case RaftState.Leader: // 并发的RequestVote的结果如果没有判断当前状态,可能会到达这里。 // 不是什么大问题。see ProcessRequestVoteResult logger.Info($"RaftState {Name} Impossible! Follower->Leader"); return; } }
private void ConvertStateFromCandidateTo(RaftState newState) { switch (newState) { case RaftState.Follower: logger.Info($"RaftState {Name}: Candidate->Follower"); State = RaftState.Follower; VoteSuccess.Clear(); // 选举结束清除。 LogSequence.SetVoteFor(string.Empty); StartRequestVoteDelayTask?.Cancel(); StartRequestVoteDelayTask = null; WaitMajorityVoteTimoutTask?.Cancel(); WaitMajorityVoteTimoutTask = null; StartLeaderLostTimerTask(); return; case RaftState.Candidate: logger.Info($"RaftState {Name}: Candidate->Candidate"); LogSequence.SetVoteFor(string.Empty); // 先清除,在真正自荐前可以给别人投票。 StartRequestVote(); return; case RaftState.Leader: StartRequestVoteDelayTask?.Cancel(); StartRequestVoteDelayTask = null; WaitMajorityVoteTimoutTask?.Cancel(); WaitMajorityVoteTimoutTask = null; VoteSuccess.Clear(); // 选举结束清除。 logger.Info($"RaftState {Name}: Candidate->Leader"); State = RaftState.Leader; LogSequence.SetVoteFor(string.Empty); LeaderId = Name; // set to self // (Reinitialized after election) var nextIndex = LogSequence.LastIndex + 1; Server.Config.ForEachConnector( (c) => { var cex = c as Server.ConnectorEx; cex.NextIndex = nextIndex; cex.MatchIndex = 0; }); // Upon election: // send initial empty AppendEntries RPCs // (heartbeat)to each server; repeat during // idle periods to prevent election timeouts(§5.2) LogSequence.AppendLog(new HeartbeatLog(HeartbeatLog.SetLeaderReadyEvent), false); HearbeatTimerTask = Scheduler.Instance.Schedule( (ThisTask) => { var elapse = Util.Time.NowUnixMillis - LogSequence.AppendLogActiveTime; if (elapse < RaftConfig.LeaderHeartbeatTimer) { LogSequence.AppendLog(new HeartbeatLog(), false); } }, 1000, 1000); return; } }