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); }
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)); } }