コード例 #1
0
ファイル: Follower.cs プロジェクト: PhillipPruett/JollyRaft
            public async Task StartElection()
            {
                var now = node.settings.Scheduler.Now;

                if (node.lastHeartBeat <= now - node.electionTimeout)
                {
                    lock (node.grantVoteLocker)
                    {
                        node.requestHandler = new Candidate(node);
                        Debug.WriteLine("{0}: Starting a new Election. current term {1}. election Timout {2}ms", node.NodeInfo(), node.Term, node.electionTimeout.TotalMilliseconds);
                        node.Term++;

                        node.CurrentLeader = node.Id;
                    }
                    var successCount = 0;

                    var blah = node.Peers.Select(async p =>
                    {
                        var vote = await p.RequestVote(new VoteRequest(node.Id, node.Term, node.LocalLog.LastTerm, node.LocalLog.LastIndex));
                        if (vote.VoteGranted)
                        {
                            Debug.WriteLine("{0}: Vote granted from {1}", node.NodeInfo(), p.Id);
                            Interlocked.Increment(ref successCount);
                        }
                        else
                        {
                            if (vote.CurrentTerm > node.Term)
                            {
                                Debug.WriteLine("{0}: stepping down as vote returned had higher term {1}", node.NodeInfo(), vote.CurrentTerm);
                                node.StepDown(vote.CurrentTerm, p.Id);
                            }
                        }
                    });

                    foreach (var task in blah)
                    {
                        await task;
                    }

                    if (node.ConcencusIsReached(successCount) && node.State == State.Candidate)
                    {
                        node.requestHandler = new Leader(node);
                        Debug.WriteLine("{0}: Elected as Leader. votes {1}. needed {2}", node.NodeInfo(), successCount, node.PeerAgreementsNeededForConcensus());
                        await SendHeartBeat();
                    }
                    else
                    {
                        Debug.WriteLine("{0}: Not elected. votes {1}. needed {2}", node.NodeInfo(), successCount, node.PeerAgreementsNeededForConcensus());
                        node.randomizeElectionDelays = true;
                    }
                }
                else
                {
                    Debug.WriteLine("{0}: election was attempted before election timeout. lastHeartBeat {1} < now {2} - electionTimeout {3}", node.NodeInfo(), node.lastHeartBeat, now, node.electionTimeout.TotalSeconds);
                    Debug.WriteLine("{0}: need {1}ms more.", node.NodeInfo(), ((now - node.electionTimeout) - node.lastHeartBeat).TotalMilliseconds, now, node.electionTimeout.TotalSeconds);
                }
            }
コード例 #2
0
ファイル: Candidate.cs プロジェクト: PhillipPruett/JollyRaft
            public async Task <VoteResult> Vote(VoteRequest request)
            {
                if (request.Term < node.Term)
                {
                    return(new VoteResult(node.Term, false));
                }
                //this needs some sort of lock around it. although it would be very rare in a deployed system, the nodes in unit tests have hit
                //this block at the exact same time, resulting in both nodes getting the vote.
                //using a lock for now. should be replaced at some point with interlocked for perf
                lock (node.grantVoteLocker)
                {
                    if (request.Term > node.Term)
                    {
                        node.StepDown(node.Term, request.Id);
                    }

                    return(new VoteResult(node.Term, false));
                }
            }