public async Task <RequestVoteResponse> Handle(RequestVote requestVote) { var response = RequestVoteTermIsGreaterThanCurrentTerm(requestVote); if (response.shouldReturn) { return(response.requestVoteResponse); } response = _rules.RequestVoteTermIsLessThanCurrentTerm(requestVote, CurrentState); if (response.shouldReturn) { return(response.requestVoteResponse); } response = _rules.VotedForIsNotThisOrNobody(requestVote, CurrentState); if (response.shouldReturn) { return(response.requestVoteResponse); } response = await LastLogIndexAndLastLogTermMatchesThis(requestVote); _messagesSinceLastElectionExpiry++; if (response.shouldReturn) { return(response.requestVoteResponse); } return(new RequestVoteResponse(false, CurrentState.CurrentTerm)); }
public void RunVotingProcess(PeerInfo peerInfo) { var voteRequest = new RequestVote() { CandidateId = MyState.Id, LastLogIndex = MyState.Log.Count - 1, LastLogTerm = MyState.Log.Select(l => l.Term).LastOrDefault(), Term = MyState.CurrentTerm }; MyState.PeerlList[peerInfo] = ConnectToPeer(MyState.ThisServerInfo.Id, new Uri(peerInfo.Address)); MyState.PeerlList[peerInfo].Persist(MyState.ThisServerInfo); var voteResponse = MyState.PeerlList[peerInfo].GetVote(voteRequest); if (voteResponse.Term > MyState.CurrentTerm) { MyState.CurrentTerm = voteResponse.Term; VotesReceived = 0; ChangeToFollower(); MyState.ThisServerInfo.PersistedState.SavePeerState(MyState); MyState.PeerlList[peerInfo].Persist(MyState.ThisServerInfo); } else if (voteResponse.VoteGranted && MyState.CurrentState == CurrentServerState.Candidate) { VotesReceived++; if (VotesReceived >= (MyState.PeerlList.Count / 2 + 1) && MyState.CurrentState == CurrentServerState.Candidate) { StartLeadership(); } } }
public RequestVoteResponse Request(RequestVote requestVote) { var response = new RequestVoteResponse(_grantVote, _term); RequestVoteResponses.Add(response); return(response); }
public async Task <RequestVoteResponse> Send(RequestVote requestVote) { try { var serverToSendMessageTo = _serviceRegistry.Get(RaftyServiceDiscoveryName.Get()).First(x => x.Id == requestVote.VoterId); var json = JsonConvert.SerializeObject(requestVote, Formatting.None, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }); var httpContent = new StringContent(json); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using (var httpClient = new HttpClient()) { httpClient.BaseAddress = serverToSendMessageTo.Location; var response = await httpClient.PostAsync(_requestVoteUrl, httpContent); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var requestVoteResponse = JsonConvert.DeserializeObject <RequestVoteResponse>(content); return(requestVoteResponse); } } catch (Exception exception) { _logger.LogError(new EventId(1), exception, "Error in Send(RequestVote requestVote)"); throw; } }
public void Receive(BecomeCandidate becomeCandidate) { if ((State is Candidate || State is Follower) && becomeCandidate.LastAppendEntriesMessageIdFromLeader == _lastAppendEntriesMessageId) { State = new Candidate(); CurrentTerm++; VotedFor = default(Guid); CurrentTermVotes = 0; var requestVoteResponse = new RequestVoteResponse(CurrentTerm, true, Id, Id); Receive(requestVoteResponse); var remoteServers = GetRemoteServers(); var tasks = new Task <RequestVoteResponse> [remoteServers.Count]; for (int i = 0; i < tasks.Length; i++) { var lastLogIndex = Log.Count > 0 ? Log.Count - 1 : 0; var lastLogTerm = Log.Count > 0 ? Log[lastLogIndex].Term : 0; var requestVote = new RequestVote(CurrentTerm, Id, lastLogIndex, lastLogTerm, remoteServers[i].Id); tasks[i] = _messageBus.Send(requestVote); } Task.WaitAll(tasks); foreach (var task in tasks) { Receive(task.Result); } } SendElectionTimeoutMessage(10); }
public override RaftEventResult ReceiveRequestVote(RequestVote requestVote) { if (requestVote.CandidateTerm > CurrentTerm) { return(Node.TranslateToState(RaftNodeState.Follower, requestVote)); } return(RaftEventResult.ReplyMessage(DenyVote)); }
internal override void ProcessVoteRequest(RequestVote request) { bool vote; var currentTerm = this.CurrentTerm; if (request.Term < currentTerm) { // requesting a vote for a node that has less recent information // we decline this.Logger.TraceFormat("Vote request from node with lower term. Declined {0}.", request); vote = false; } else { if (request.Term > currentTerm) { this.Logger.DebugFormat( "Vote request from node with higher term. Updating our term. {0}", request); // we need to upgrade our term this.Node.State.CurrentTerm = request.Term; } // we check how complete is the log ? if (this.Node.State.LogIsBetterOrSameAs(request.LastLogTerm, request.LastLogIndex)) { // our log is better than the candidate's vote = false; this.Logger.TraceFormat( "Vote request from node with less information. We do not vote. Message: {0}.", request); } else if (string.IsNullOrEmpty(this.Node.State.VotedFor) || this.Node.State.VotedFor == request.CandidateId) { // grant vote this.Logger.TraceFormat( "We do vote for node {1}. Message: {0}.", request, request.CandidateId); vote = true; this.Node.State.VotedFor = request.CandidateId; // as we did vote, we are ok to wait longer this.ResetTimeout(0, 2); } else { // we already voted for someone vote = false; this.Logger.TraceFormat( "We already voted. We do not grant vote. Message: {0}.", request); } } // send back the response this.Node.SendVote(request.CandidateId, vote); }
public void should_add_remote_server_if_receive_request_votes_from_unknown_remote_server() { var requestVote = new RequestVote(0, Guid.NewGuid(), 0, 0, Guid.NewGuid()); this.Given(x => GivenANewServer()) .When(x => ServerReceives(requestVote)) .Then(x => TheRemoteServerCountIs(1)) .BDDfy(); }
private bool GrantVote(RequestVote requestVote) { if (requestVote.Term < Peer.MyState.CurrentTerm) { return(false); } return((Peer.MyState.VotedForId == null || Peer.MyState.VotedForId == requestVote.CandidateId) && IsLogOlderOrEqual(requestVote.LastLogIndex, requestVote.LastLogTerm)); }
public void server_should_reply_true_if_voted_for_is_null() { var requestVote = new RequestVote(1, Guid.NewGuid(), 0, 0, Guid.NewGuid()); var expected = new RequestVoteResponse(1, true, Guid.NewGuid(), Guid.NewGuid()); this.Given(x => GivenANewServer()) .When(x => WhenServerReceives(requestVote)) .Then(x => x.ThenTheReplyIs(expected)) .BDDfy(); }
public void server_should_become_follower_if_receives_greater_term_in_request_vote_message() { var requestVote = new RequestVote(20, Guid.NewGuid(), 0, 0, Guid.NewGuid()); this.Given(x => GivenANewServer()) .When(x => ServerReceives(requestVote)) .Then(x => ThenTheCurrentTermIs(20)) .And(x => TheServerIsAFollower()) .BDDfy(); }
//投票 peer public async Task <RequestVoteResponse> Handle(RequestVote requestVote) { var node = _nodePeer.GetNode(requestVote.ChannelId); if (node == null) { throw new Exception($"节点未加入{requestVote.ChannelId} 通道"); } return(await node.Handle(requestVote)); }
public async Task <RequestVoteResponse> Request(RequestVote requestVote) { try { return(await _node.Handle(requestVote)); } catch (Exception e) { return(new RequestVoteResponse(false, 0)); } }
public void server_should_reply_true_if_candidate_id_and_log_is_up_to_date_with_server() { var firstRequestVote = new RequestVote(1, Guid.NewGuid(), 0, 0, Guid.NewGuid()); var expected = new RequestVoteResponse(1, true, Guid.NewGuid(), Guid.NewGuid()); this.Given(x => GivenANewServer()) .When(x => WhenServerReceives(firstRequestVote)) .Then(x => x.ThenTheReplyIs(expected)) .BDDfy(); }
public async Task <RequestVoteResponse> Handle(RequestVote requestVote) { var response = RequestVoteTermIsGreaterThanCurrentTerm(requestVote); if (response.shouldReturn) { return(response.requestVoteResponse); } return(new RequestVoteResponse(false, CurrentState.CurrentTerm)); }
public void server_should_reply_false_if_term_is_less_than_current_term() { var requestVote = new RequestVote(1, Guid.NewGuid(), 0, 0, Guid.NewGuid()); var expected = new RequestVoteResponse(2, false, Guid.NewGuid(), Guid.NewGuid()); this.Given(x => GivenANewServer()) .And(x => GivenTheCurrentTermIs(2)) .When(x => WhenServerReceives(requestVote)) .Then(x => x.ThenTheReplyIs(expected)) .BDDfy(); }
public RequestVoteResponse Request(RequestVote requestVote) { try { return(_node.Handle(requestVote)); } catch (Exception e) { return(new RequestVoteResponse(false, 0)); } }
public async Task <RequestVoteResponse> Handle(RequestVote requestVote) { try { await _requestVote.WaitAsync(); return(await State.Handle(requestVote)); } finally { _requestVote.Release(); } }
public void server_should_reply_false_if_voted_for_is_another_candidate() { var firstRequestVote = new RequestVote(1, Guid.NewGuid(), 0, 0, Guid.NewGuid()); var secondRequestVote = new RequestVote(1, Guid.NewGuid(), 0, 0, Guid.NewGuid()); var expected = new RequestVoteResponse(1, false, Guid.NewGuid(), Guid.NewGuid()); this.Given(x => GivenANewServer()) .And(x => GivenTheServerReceives(firstRequestVote)) .When(x => WhenServerReceives(secondRequestVote)) .Then(x => x.ThenTheReplyIs(expected)) .BDDfy(); }
public RequestVoteResponse Request(RequestVote requestVote) { var json = JsonConvert.SerializeObject(requestVote, _jsonSerializerSettings); var content = new StringContent(json); var response = _httpClient.PostAsync($"{_hostAndPort}/requestvote", content).GetAwaiter().GetResult(); if (response.IsSuccessStatusCode) { return(JsonConvert.DeserializeObject <RequestVoteResponse>(response.Content.ReadAsStringAsync().GetAwaiter().GetResult())); } else { return(new RequestVoteResponse(false, requestVote.Term)); } }
public RequestVoteResponse RequestVoteRPCHandler(RequestVote requestVoteRPC) { var successful = false; if (NodeStateService.IsBootstrapped) { //To requests might come in at the same time causing the VotedFor to not match lock (VoteLock) { //Ref1 $5.2, $5.4 if (_nodeStorage.CurrentTerm <= requestVoteRPC.Term && ((_nodeStorage.VotedFor == null || _nodeStorage.VotedFor == requestVoteRPC.CandidateId) && (requestVoteRPC.LastLogIndex >= _nodeStorage.GetTotalLogCount() && requestVoteRPC.LastLogTerm >= _nodeStorage.GetLastLogTerm()))) { _nodeStorage.SetVotedFor(requestVoteRPC.CandidateId); Logger.LogDebug(NodeStateService.GetNodeLogId() + "Voting for " + requestVoteRPC.CandidateId + " for term " + requestVoteRPC.Term); SetNodeRole(NodeState.Follower); _nodeStorage.SetCurrentTerm(requestVoteRPC.Term); successful = true; } else if (_nodeStorage.CurrentTerm > requestVoteRPC.Term) { Logger.LogDebug(NodeStateService.GetNodeLogId() + "Rejected vote from " + requestVoteRPC.CandidateId + " as current term is greater (" + requestVoteRPC.Term + "<" + _nodeStorage.CurrentTerm + ")"); } else if (requestVoteRPC.LastLogIndex < _nodeStorage.GetTotalLogCount() - 1) { Logger.LogDebug(NodeStateService.GetNodeLogId() + "Rejected vote from " + requestVoteRPC.CandidateId + " as last log index is less then local index (" + requestVoteRPC.LastLogIndex + "<" + (_nodeStorage.GetTotalLogCount() - 1) + ")"); } else if (requestVoteRPC.LastLogTerm < _nodeStorage.GetLastLogTerm()) { Logger.LogDebug(NodeStateService.GetNodeLogId() + "Rejected vote from " + requestVoteRPC.CandidateId + " as last log term is less then local term (" + requestVoteRPC.LastLogTerm + "<" + _nodeStorage.GetLastLogTerm() + ")"); } else if ((_nodeStorage.VotedFor != null && _nodeStorage.VotedFor != requestVoteRPC.CandidateId)) { Logger.LogDebug(NodeStateService.GetNodeLogId() + "Rejected vote from " + requestVoteRPC.CandidateId + " as I have already voted for " + _nodeStorage.VotedFor + " | "); } else if (!successful) { Logger.LogError("Rejected vote from " + requestVoteRPC.CandidateId + " due to unknown reason."); } } } return(new RequestVoteResponse() { NodeId = _nodeStorage.Id, IsSuccessful = successful }); }
RaftEventResult StartNewElection() { VoteTable.Clear(); Node.RaftEventListener.OnElectionStarted(); // increment current term Node.PersistedState.CurrentTerm++; // vote for self ProcessVote(Node.Id); Node.PersistedState.VotedFor = Node.Id; // send request votes to all servers var requestVote = new RequestVote() { CandidateId = Node.Id, CandidateTerm = CurrentTerm }; return(RaftEventResult.BroadcastMessage(requestVote).SetTimer(Node.RaftSettings.FollowerTimeoutFrom, Node.RaftSettings.FollowerTimeoutTo)); }
public override RaftEventResult ReceiveRequestVote(RequestVote requestVote) { if (requestVote.CandidateId == Node.Id) { return(RaftEventResult.Empty); } bool voteGranted = false; if (requestVote.CandidateTerm >= CurrentTerm) { // Node.CurrentTerm = requestVote.CandidateTerm; return(Node.TranslateToState(RaftNodeState.Follower, requestVote)); } return(RaftEventResult.ReplyMessage(DenyVote)); }
internal override void EnterState() { // increase term this.voteReceived.Clear(); var nextTerm = this.Node.IncrementTerm(); // vote for self! this.Node.SendVote(this.Node.Id, true); this.RegisterVote(new GrantVote(true, this.Node.Id, nextTerm)); // send vote request this.Logger.TraceFormat("Broadcast a vote request for term {0}", this.CurrentTerm); var request = new RequestVote(nextTerm, this.Node.Id, this.Node.State.LastPersistedIndex, this.Node.State.LastPersistedTerm); this.Node.SendToOthers(request); this.ResetTimeout(.3); }
public RequestVoteResponse Receive(RequestVote requestVote) { _logger.LogDebug($"Server: {Id} received request vote in term: {CurrentTerm}"); if (!_serversInClusterInCluster.Contains(requestVote.CandidateId)) { var remoteServer = new ServerInCluster(requestVote.CandidateId); _serversInClusterInCluster.Add(remoteServer); } // If RPC request or response contains term T > currentTerm: // set currentTerm = T, convert to follower (§5.1) if (requestVote.Term > CurrentTerm) { BecomeFollowerAndMatchTerm(requestVote.Term, requestVote.CandidateId); _logger.LogDebug($"Server: {Id} received request vote in term: {CurrentTerm}, became follower"); } /* * 1.Reply false if term < currentTerm(�5.1)*/ if (requestVote.Term < CurrentTerm) { _logger.LogDebug($"Server: {Id} received request vote in term: {CurrentTerm}, voted false because term was less than current term"); return(new RequestVoteResponse(CurrentTerm, false, requestVote.CandidateId, Id)); } lock (_lock) { /* * 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)*/ if (VotedForIsNullOrAlreadyVotingForCandidate(requestVote)) { if (CandidatesLogIsAtLeastUpToDateAsServers(requestVote)) { VotedFor = requestVote.CandidateId; _logger.LogDebug($"Server: {Id} received request vote in term: {CurrentTerm}, voted true"); return(new RequestVoteResponse(CurrentTerm, true, requestVote.CandidateId, Id)); } } } _logger.LogDebug($"Server: {Id} received request vote in term: {CurrentTerm}, voted false because already voted for or candidates log isnt up to date"); return(new RequestVoteResponse(CurrentTerm, false, requestVote.CandidateId, Id)); }
internal override void ProcessVoteRequest(RequestVote request) { var currentTerm = this.CurrentTerm; if (request.CandidateId == this.Node.Id) { return; } if (request.Term > currentTerm) { this.Logger.DebugFormat( "Received vote request from node with higher term ({0}'s term is {1}, our {2}). Resigning.", request.CandidateId, request.Term, currentTerm); // we step down this.Node.SwitchToAndProcessMessage(NodeStatus.Follower, request); return; } if (request.Term == this.CurrentTerm && !this.Node.State.LogIsBetterOrSameAs(request.LastLogTerm, request.LastLogIndex)) { this.Logger.DebugFormat( "Received vote request from node with better log ({0}'s log is at {1}, our at {2}). Resigning.", request.LastLogIndex, this.Node.LastCommit, currentTerm); // we step down this.Node.SwitchToAndProcessMessage(NodeStatus.Follower, request); return; } // requesting a vote for a node that has less recent information // we decline this.Logger.TraceFormat( "Received a vote request from a node with a lower term. We decline {0}", request); this.Node.SendVote(request.CandidateId, false); }
public void Send(JsonOperationContext context, RequestVote rv) { if (_log.IsInfoEnabled) { _log.Info( $"{rv.Source} requests vote in {rv.Term:#,#;;0}, trial: {rv.IsTrialElection}, forced: {rv.IsForcedElection}, result: {rv.ElectionResult} with: ({rv.LastLogIndex:#,#;;0} / {rv.LastLogTerm:#,#;;0})."); } Send(context, new DynamicJsonValue { ["Type"] = nameof(RequestVote), [nameof(RequestVote.Term)] = rv.Term, [nameof(RequestVote.Source)] = rv.Source, [nameof(RequestVote.LastLogTerm)] = rv.LastLogTerm, [nameof(RequestVote.LastLogIndex)] = rv.LastLogIndex, [nameof(RequestVote.IsTrialElection)] = rv.IsTrialElection, [nameof(RequestVote.IsForcedElection)] = rv.IsForcedElection, [nameof(RequestVote.ElectionResult)] = rv.ElectionResult, [nameof(RequestVote.SendingThread)] = Thread.CurrentThread.ManagedThreadId }); }
public async Task <RequestVoteResponse> Request(RequestVote requestVote) { if (_token == null) { await SetToken(); } var json = JsonConvert.SerializeObject(requestVote, _jsonSerializerSettings); var content = new StringContent(json); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); var response = await _httpClient.PostAsync($"{_hostAndPort}/administration/raft/requestvote", content); if (response.IsSuccessStatusCode) { return(JsonConvert.DeserializeObject <RequestVoteResponse>(await response.Content.ReadAsStringAsync(), _jsonSerializerSettings)); } return(new RequestVoteResponse(false, requestVote.Term)); }
public override RaftEventResult ReceiveRequestVote(RequestVote requestVote) { // we have more recent term so we dont vote if (requestVote.CandidateTerm < CurrentTerm) { return(RaftEventResult.ReplyMessage(DenyVote)); } if (requestVote.CandidateTerm > CurrentTerm) { CurrentTerm = requestVote.CandidateTerm; } // if haven't voted before if (Node.PersistedState.VotedFor == null || Node.PersistedState.VotedFor == requestVote.CandidateId) { Node.PersistedState.VotedFor = requestVote.CandidateId; return(RaftEventResult.ReplyMessage(GrantVote).SetTimer(Node.RaftSettings.FollowerTimeoutFrom * 2, Node.RaftSettings.FollowerTimeoutTo * 2)); } return(RaftEventResult.Empty); }
public async Task <RequestVoteResponse> Request(RequestVote request) { try { var model = new NetRequest { Data = Newtonsoft.Json.JsonConvert.SerializeObject(request) }; var rs = await GetClient().VoteAsync(model); return(Newtonsoft.Json.JsonConvert.DeserializeObject <RequestVoteResponse>(rs.Data)); } catch (Exception ex) { _logger.LogError(ex, ex.Message); return(new RequestVoteResponse() { VoteGranted = false, }); } }