예제 #1
0
        private void ConvertStateFromLeaderTo(RaftState newState)
        {
            switch (newState)
            {
            case RaftState.Follower:
                logger.Info($"RaftState {Name}: Leader->Follower");
                State = RaftState.Follower;
                ResetLeaderReadyAfterChangeState();
                Monitor.PulseAll(this);

                HearbeatTimerTask?.Cancel();
                HearbeatTimerTask = null;

                StartLeaderLostTimerTask();
                return;

            case RaftState.Candidate:
                logger.Error($"RaftState {Name} Impossible! Leader->Candidate");
                return;

            case RaftState.Leader:
                logger.Error($"RaftState {Name} Impossible! Leader->Leader");
                return;
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        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;
            }
        }