예제 #1
0
파일: RaftNode.cs 프로젝트: ww-it/Raft.Net
        /// <summary>
        /// Node receives answer votes (to become Leader) from other nodes.
        /// Is called from tryCatch and in lock
        /// </summary>
        /// <param name="data"></param>
        void ParseVoteOfCandidate(NodeAddress address, byte[] data)
        {
            //Node received a node
            var vote = VoteOfCandidate.BiserDecode(data);

            var termState = CompareCurrentTermWithIncoming(vote.TermId);

            if (this.NodeState != eNodeState.Candidate)
            {
                return;
            }

            switch (vote.VoteType)
            {
            case VoteOfCandidate.eVoteType.VoteFor:
                //Calculating if node has Majority of

                //VotesQuantity++;
                VotesQuantity.Add(address.EndPointSID);

                if ((VotesQuantity.Count + 1) >= this.GetMajorityQuantity())
                {
                    //Majority

                    //Node becomes a Leader
                    this.NodeState = eNodeState.Leader;
                    this.NodeStateLog.FlushSleCache();
                    this.NodeStateLog.ClearLogAcceptance();
                    this.NodeStateLog.ClearLogEntryForDistribution();

                    VerbosePrint("Node {0} state is {1} _ParseVoteOfCandidate", NodeAddress.NodeAddressId, this.NodeState);
                    VerbosePrint("Node {0} is Leader **********************************************", NodeAddress.NodeAddressId);

                    //Stopping timers
                    this.RemoveElectionTimer();
                    this.RemoveLeaderHeartbeatWaitingTimer();

                    /*
                     * It's possible that we receive higher term from another leader
                     * (in case if this leader was disconnected for some seconds from the network,
                     * other leader can be elected and it will definitely have higher Term, so every Leader node must be ready to it)
                     */

                    this.RunLeaderTimer();
                }
                //else
                //{
                //    //Accumulating voices
                //    //Do nothing
                //}

                break;

            case VoteOfCandidate.eVoteType.VoteReject:
                //Do nothing
                break;
            }
        }
예제 #2
0
파일: RaftNode.cs 프로젝트: ww-it/Raft.Net
        /// <summary>
        ///
        /// </summary>
        void SetNodeFollower()
        {
            if (this.NodeState != eNodeState.Follower)
            {
                VerbosePrint("Node {0} state is {1} of {2}", NodeAddress.NodeAddressId, this.NodeState, this.LeaderNodeAddress?.NodeAddressId);
            }

            this.NodeState = eNodeState.Follower;

            this.NodeStateLog.LeaderSynchronizationIsActive = false;
            //Removing timers
            RemoveElectionTimer();
            RemoveLeaderHeartbeatWaitingTimer();
            RemoveLeaderTimer();
            RemoveLeaderLogResendTimer();
            //Starting Leaderheartbeat
            RunLeaderHeartbeatWaitingTimer();
        }
예제 #3
0
파일: RaftNode.cs 프로젝트: ww-it/Raft.Net
        /// <summary>
        /// Stops the node
        /// </summary>
        public void NodeStop()
        {
            lock (lock_Operations)
            {
                RemoveElectionTimer();
                RemoveLeaderHeartbeatWaitingTimer();
                RemoveLeaderTimer();
                RemoveDelayedPersistenceTimer();
                RemoveNoLeaderAddCommandTimer();


                this.NodeState = eNodeState.Follower;

                this.NodeStateLog.LeaderSynchronizationIsActive = false;
                this.NodeStateLog.FlushSleCache();


                VerbosePrint("Node {0} state is {1}", NodeAddress.NodeAddressId, this.NodeState);

                IsRunning = false;
            }
        }
예제 #4
0
파일: RaftNode.cs 프로젝트: ww-it/Raft.Net
        /// <summary>
        /// Time to become a candidate
        /// </summary>
        /// <param name="userToken"></param>
        void ElectionTimeout(object userToken)
        {
            CandidateRequest req = null;

            try
            {
                lock (lock_Operations)
                {
                    if (Election_TimerId == 0)  //Timer was switched off and we don't need to run it again
                    {
                        return;
                    }

                    Election_TimerId = 0;

                    if (this.NodeState == eNodeState.Leader)
                    {
                        return;
                    }



                    VerbosePrint("Node {0} election timeout", NodeAddress.NodeAddressId);

                    this.NodeState = eNodeState.Candidate;

                    this.LeaderNodeAddress = null;

                    VerbosePrint("Node {0} state is {1} _ElectionTimeout", NodeAddress.NodeAddressId, this.NodeState);

                    //Voting for self
                    //VotesQuantity = 1;
                    VotesQuantity.Clear();

                    //Increasing local term number
                    NodeTerm++;

                    req = new CandidateRequest()
                    {
                        TermId     = this.NodeTerm,
                        LastLogId  = NodeStateLog.StateLogId,
                        LastTermId = NodeStateLog.StateLogTerm
                    };


                    //send to all was here

                    //Setting up new Election Timer
                    RunElectionTimer();
                }

                this.Sender.SendToAll(eRaftSignalType.CandidateRequest, req.SerializeBiser(), this.NodeAddress, entitySettings.EntityName);
            }
            catch (Exception ex)
            {
                Log.Log(new WarningLogEntry()
                {
                    Exception = ex, Method = "Raft.RaftNode.ElectionTimeout"
                });
            }
        }