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