public static CandidateRequest 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 { decoder = new Biser.Decoder(extDecoder); if (decoder.IsNull) { return(null); } } CandidateRequest m = new CandidateRequest(); //!!!!!!!!!!!!!! change return type m.TermId = decoder.GetULong(); m.LastLogId = decoder.GetULong(); m.LastTermId = decoder.GetULong(); return(m); }
/// <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); }
/// <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" }); } }