Exemple #1
0
 internal bool EnsureExistGreaterTermAndChangeRole(ulong term)
 {
     lock (_ensureTermLockObj)
     {
         if (term > _stateController.PersistentState.CurrentTerm)
         {
             DebugConsole.WriteLine($"Existed a term greater than current term.");
             _stateController.UpdateTerm(term);
             ChangeRole(RoleType.Follower);
             return(true);
         }
         return(false);
     }
 }
        private void RequestVote()
        {
            _stateController.UpdateTerm(_stateController.PersistentState.CurrentTerm + 1);
            DebugConsole.WriteLine($"Starting election ... term :{_stateController.PersistentState.CurrentTerm}" + Environment.NewLine);
            //Vote for current object
            int  votes            = 1;
            bool transferedLeader = false;

            List <Task> taskList      = new List <Task>();
            int         majorityCount = _node.Peers.Count;

            foreach (Peer peer in _node.Peers)
            {
                Task task = Task.Run(() =>
                {
                    try
                    {
                        VoteResponse response = RequestVoteCore(peer.RemoteClient);
                        if (_node.EnsureExistGreaterTermAndChangeRole(response.Term))
                        {
                            return;
                        }

                        if (response.VoteGranted)
                        {
                            lock (_transferedLeaderLockObj)
                            {
                                votes += 1;
                                if (!transferedLeader && votes > majorityCount / 2 + 1)
                                {
                                    transferedLeader = true;
                                    _node.ChangeRole(RoleType.Leader);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        DebugConsole.WriteLine($"{ex.Message}");
                    }
                });
                taskList.Add(task);
            }
            Task.WaitAll(taskList.ToArray());
        }
        public AppendEntriesResponse AppendEntries(AppendEntriesRequest request)
        {
            if (string.IsNullOrEmpty(LeaderId))
            {
                LeaderId = request.LeaderId;
            }
            if (request.Term == _stateController.PersistentState.CurrentTerm)
            {
                lock (this)
                {
                    _isFromLegalLeaderRequest = true;
                }
            }
            AppendEntriesResponse response = new AppendEntriesResponse();

            if (_stateController.PersistentState.Logs.Any())
            {
                LogEntry logEntry = _stateController.PersistentState.Logs.SingleOrDefault(w => w.Index == request.PrevLogIndex && w.Term == request.PrevLogTerm);
                if (logEntry == null)
                {
                    response.IsSuccess = false;
                    response.Term      = _stateController.PersistentState.CurrentTerm;
                    return(response);
                }

                LogEntry diffTermLogEntry = _stateController.PersistentState.Logs.SingleOrDefault(w => request.Entries.Exists(e => e.Index == w.Index && w.Term != e.Term));
                if (diffTermLogEntry != null)
                {
                    _stateController.PersistentState.Logs.RemoveRange((int)diffTermLogEntry.Index, _stateController.PersistentState.Logs.Count - (int)diffTermLogEntry.Index);
                }
                _stateController.PersistentState.Logs.AddRange(request.Entries);
            }

            if (request.LeaderCommit > _stateController.VolatileState.CommitIndex)
            {
                _stateController.UpdateTerm(request.Term);
                _stateController.UpdateCommitIndex(Math.Min(request.LeaderCommit, request.PrevLogIndex));
            }
            response.IsSuccess = true;
            response.Term      = _stateController.PersistentState.CurrentTerm;
            return(response);
        }