Exemple #1
0
        private AppendEntriesResponse AppendEntries(string address, IHost host, ulong nextIndex)
        {
            AppendEntriesRequest request = new AppendEntriesRequest
            {
                LeaderId     = Id,
                Term         = _stateController.PersistentState.CurrentTerm,
                PrevLogIndex = _stateController.PersistentState.LastLogIndex,
                PrevLogTerm  = _stateController.PersistentState.LastLogTerm,
                LeaderCommit = _stateController.VolatileState.CommitIndex
            };

            if (_stateController.PersistentState.LastLogIndex >= nextIndex)
            {
                List <LogEntry> logEntries = _uncommittiedLogs.FindAll(w => w.Index >= nextIndex);
                if (logEntries != null && logEntries.Any())
                {
                    request.Entries = logEntries;
                }
            }

            AppendEntriesResponse response = host.AppendEntriesInvoke(request);

            if (!response.IsSuccess && _leaderVolatileStates[address].NextIndex != 0)
            {
                _leaderVolatileStates[address].NextIndex -= 1;
                response = AppendEntries(address, host, _leaderVolatileStates[address].NextIndex);
            }
            return(response);
        }
        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);
        }
Exemple #3
0
        public AppendEntriesResponse AppendEntriesInvoke(AppendEntriesRequest reqeust)
        {
            lock (this)
            {
                DebugConsole.WriteLine($"Append entries from leader(Id:{reqeust.LeaderId} Term:{reqeust.Term}...");
                _node.EnsureExistGreaterTermAndChangeRole(reqeust.Term);

                if (reqeust.Term < _stateController.PersistentState.CurrentTerm)
                {
                    return(new AppendEntriesResponse()
                    {
                        Term = _stateController.PersistentState.CurrentTerm,
                        IsSuccess = false
                    });
                }

                if (_node.CurrentRole.Type == RoleType.Candidate && reqeust.Term == _stateController.PersistentState.CurrentTerm)
                {
                    _node.ChangeRole(RoleType.Follower);
                }
                return(((Follower)_node.CurrentRole).AppendEntries(reqeust));
            }
        }