public static VoteOfCandidate BiserDecode(byte[] enc = null, Biser.Decoder extDecoder = null) //!!!!!!!!!!!!!! change return type { Biser.Decoder decoder = null; if (extDecoder == null) { if (enc == null || enc.Length == 0) { return(null); } decoder = new Biser.Decoder(enc); if (decoder.CheckNull()) { return(null); } } else { if (extDecoder.CheckNull()) { return(null); } else { decoder = extDecoder; } } VoteOfCandidate m = new VoteOfCandidate(); //!!!!!!!!!!!!!! change return type m.TermId = decoder.GetULong(); m.VoteType = (eVoteType)decoder.GetInt(); return(m); }
/// <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; } }
/// <summary> /// Is called from tryCatch and in lock /// </summary> /// <param name="data"></param> void ParseCandidateRequest(NodeAddress address, byte[] data) { var req = CandidateRequest.BiserDecode(data); VoteOfCandidate vote = new VoteOfCandidate(); vote.VoteType = VoteOfCandidate.eVoteType.VoteFor; var termState = CompareCurrentTermWithIncoming(req.TermId); vote.TermId = NodeTerm; switch (termState) { case eTermComparationResult.CurrentTermIsHigher: vote.VoteType = VoteOfCandidate.eVoteType.VoteReject; break; case eTermComparationResult.CurrentTermIsSmaller: //Now this Node is Follower break; } if (vote.VoteType == VoteOfCandidate.eVoteType.VoteFor) { switch (this.NodeState) { case eNodeState.Leader: vote.VoteType = VoteOfCandidate.eVoteType.VoteReject; break; case eNodeState.Candidate: vote.VoteType = VoteOfCandidate.eVoteType.VoteReject; break; case eNodeState.Follower: //Probably we can vote for this Node (if we didn't vote for any other one) if (LastVotedTermId < req.TermId) { //formula of voting if ( (NodeStateLog.StateLogTerm > req.LastTermId) || ( NodeStateLog.StateLogTerm == req.LastTermId && NodeStateLog.StateLogId > req.LastLogId ) ) { vote.VoteType = VoteOfCandidate.eVoteType.VoteReject; } else { LastVotedTermId = req.TermId; vote.VoteType = VoteOfCandidate.eVoteType.VoteFor; //Restaring Election Timer this.RemoveElectionTimer(); this.RunElectionTimer(); } } else { vote.VoteType = VoteOfCandidate.eVoteType.VoteReject; } break; } } //Sending vote signal back //VerbosePrint("Node {0} voted to node {1} as {2} _ParseCandidateRequest", NodeAddress.NodeAddressId, address.NodeAddressId, vote.VoteType); VerbosePrint($"Node {NodeAddress.NodeAddressId} ({this.NodeState}) {vote.VoteType} {address.NodeAddressId} in _ParseCandidateRequest"); Sender.SendTo(address, eRaftSignalType.VoteOfCandidate, vote.SerializeBiser(), this.NodeAddress, entitySettings.EntityName); }