Example #1
0
        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));
        }
Example #2
0
        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();
                }
            }
        }
Example #3
0
        public RequestVoteResponse Request(RequestVote requestVote)
        {
            var response = new RequestVoteResponse(_grantVote, _term);

            RequestVoteResponses.Add(response);
            return(response);
        }
Example #4
0
        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;
            }
        }
Example #5
0
        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);
        }
Example #6
0
 public override RaftEventResult ReceiveRequestVote(RequestVote requestVote)
 {
     if (requestVote.CandidateTerm > CurrentTerm)
     {
         return(Node.TranslateToState(RaftNodeState.Follower, requestVote));
     }
     return(RaftEventResult.ReplyMessage(DenyVote));
 }
Example #7
0
        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);
        }
Example #8
0
        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));
 }
Example #10
0
        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();
        }
Example #11
0
        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();
        }
Example #12
0
        //投票 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));
        }
Example #13
0
 public async Task <RequestVoteResponse> Request(RequestVote requestVote)
 {
     try
     {
         return(await _node.Handle(requestVote));
     }
     catch (Exception e)
     {
         return(new RequestVoteResponse(false, 0));
     }
 }
Example #14
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();
        }
Example #15
0
        public async Task <RequestVoteResponse> Handle(RequestVote requestVote)
        {
            var response = RequestVoteTermIsGreaterThanCurrentTerm(requestVote);

            if (response.shouldReturn)
            {
                return(response.requestVoteResponse);
            }

            return(new RequestVoteResponse(false, CurrentState.CurrentTerm));
        }
Example #16
0
        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();
        }
Example #17
0
 public RequestVoteResponse Request(RequestVote requestVote)
 {
     try
     {
         return(_node.Handle(requestVote));
     }
     catch (Exception e)
     {
         return(new RequestVoteResponse(false, 0));
     }
 }
Example #18
0
        public async Task <RequestVoteResponse> Handle(RequestVote requestVote)
        {
            try
            {
                await _requestVote.WaitAsync();

                return(await State.Handle(requestVote));
            }
            finally
            {
                _requestVote.Release();
            }
        }
Example #19
0
        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();
        }
Example #20
0
        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));
            }
        }
Example #21
0
        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
            });
        }
Example #22
0
        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));
        }
Example #23
0
        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));
        }
Example #24
0
        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);
        }
Example #25
0
        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));
        }
Example #26
0
        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);
        }
Example #27
0
 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
     });
 }
Example #28
0
        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));
        }
Example #29
0
        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);
        }
Example #30
0
        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,
                });
            }
        }