public void LeaderTimerElapse(object userToken) { try { //Sending signal to all (except self that it is a leader) LeaderHeartbeat heartBeat = null; lock (this.stateMachine.lock_Operations) { heartBeat = new LeaderHeartbeat() { LeaderTerm = this.stateMachine.NodeTerm, StateLogLatestIndex = this.stateMachine.NodeStateLog.StateLogId, StateLogLatestTerm = this.stateMachine.NodeStateLog.StateLogTerm, LastStateLogCommittedIndex = this.stateMachine.NodeStateLog.LastCommittedIndex, LastStateLogCommittedIndexTerm = this.stateMachine.NodeStateLog.LastCommittedIndexTerm }; } //VerbosePrint($"{NodeAddress.NodeAddressId} (Leader)> leader_heartbeat"); this.stateMachine.network.SendToAll(eRaftSignalType.LeaderHearthbeat, heartBeat, this.stateMachine.NodeAddress, entitySettings.EntityName, true); } catch (Exception ex) { this.stateMachine.Log.Log(new WarningLogEntry() { Exception = ex, Method = "Raft.RaftNode.LeaderTimerElapse" }); } }
/// <summary> /// under lock_operations /// only for followers /// </summary> /// <param name="lhb"></param> /// <returns>will return false if node needs synchronization from LastCommittedIndex/Term</returns> public bool SetLastCommittedIndexFromLeader(LeaderHeartbeat lhb) { if (this.LastCommittedIndex < lhb.LastStateLogCommittedIndex) { //Node tries to understand if it contains already this index/term, if not it will need synchronization ulong populateFrom = 0; lock (inMem.Sync) { if (inMem.Select(lhb.LastStateLogCommittedIndex, lhb.LastStateLogCommittedIndexTerm, out var rSle)) { populateFrom = this.LastCommittedIndex + 1; this.LastCommittedIndex = lhb.LastStateLogCommittedIndex; this.LastCommittedIndexTerm = lhb.LastStateLogCommittedIndexTerm; } else { return(false); } } if (populateFrom > 0) { this.rn.logHandler.Commited(); } } return(true); }
/// <summary> /// Leader receives accepted Log /// </summary> /// <param name="address"></param> /// <param name="data"></param> public void ParseStateLogEntryAccepted(NodeRaftAddress address, object data) { if (this.stateMachine.States.NodeState != eNodeState.Leader) { return; } StateLogEntryApplied applied = data as StateLogEntryApplied; var res = this.EntryIsAccepted(address, this.stateMachine.GetMajorityQuantity(), applied); if (res == eEntryAcceptanceResult.Committed) { distributeQueue.Remove(applied.StateLogEntryId); //this.VerbosePrint($"{this.NodeAddress.NodeAddressId}> LogEntry {applied.StateLogEntryId} is COMMITTED (answer from {address.NodeAddressId})"+DateTime.Now.Second+":"+DateTime.Now.Millisecond); this.stateMachine.timerLoop.StopLeaderLogResendTimeLoop(); //Force heartbeat, to make followers to get faster info about commited elements LeaderHeartbeat heartBeat = new LeaderHeartbeat() { LeaderTerm = this.stateMachine.NodeTerm, StateLogLatestIndex = this.stateMachine.NodeStateLog.StateLogId, StateLogLatestTerm = this.stateMachine.NodeStateLog.StateLogTerm, LastStateLogCommittedIndex = this.stateMachine.NodeStateLog.LastCommittedIndex, LastStateLogCommittedIndexTerm = this.stateMachine.NodeStateLog.LastCommittedIndexTerm }; this.stateMachine.network.SendToAll(eRaftSignalType.LeaderHearthbeat, heartBeat, this.stateMachine.NodeAddress, this.stateMachine.entitySettings.EntityName, true); //--------------------------------------- this.stateMachine.States.InLogEntrySend = false; EnqueueAndDistrbuteLog(); } }
public SyncResult SyncCommitByHeartBeat(LeaderHeartbeat lhb) { if (GlobalConfig.Verbose) { Console.WriteLine($"leader info:{lhb.LastStateLogCommittedIndex} ,mine:{this.LastCommittedIndex}"); } if (this.LastCommittedIndex < lhb.LastStateLogCommittedIndex) { //find if this entry exist var key = GetKey(lhb.LastStateLogCommittedIndexTerm, lhb.StateLogLatestIndex); var value = db.Get(key); var find = value == null; if (find) { var entry = StateLogEntry.BiserDecode(value); if (!entry.IsCommitted) { entry.IsCommitted = true; value = entry.BiserEncode(); db.Put(key, value); this.LastCommittedIndex = lhb.LastStateLogCommittedIndex; return(new SyncResult() { HasCommit = true, Synced = true }); } else { return(new SyncResult() { HasCommit = false, Synced = true }); } } else { return(new SyncResult() { HasCommit = false, Synced = false }); } } else { return(new SyncResult() { HasCommit = false, Synced = true }); } }
public SyncResult SyncCommitByHeartBeat(LeaderHeartbeat lhb) { if (GlobalConfig.Verbose) { Console.WriteLine($"leader info:{lhb.LastStateLogCommittedIndex} ,mine:{this.LastCommittedIndex}"); } if (this.LastCommittedIndex < lhb.LastStateLogCommittedIndex) { //find if this entry exist var entry = list.Find(s => s.Term == lhb.LastStateLogCommittedIndexTerm && s.Index == lhb.StateLogLatestIndex); if (entry != null) { if (!entry.IsCommitted) { entry.IsCommitted = true; this.LastCommittedIndex = lhb.LastStateLogCommittedIndex; return(new SyncResult() { HasCommit = true, Synced = true }); } else { return(new SyncResult() { HasCommit = false, Synced = true }); } } else { return(new SyncResult() { HasCommit = false, Synced = false }); } } else { return(new SyncResult() { HasCommit = false, Synced = true }); } }
public async Task OnRecieve(IChannelHandlerContext context, string msgstr) { // if (!string.IsNullOrEmpty(msgstr)) { //RaftCommand msgObj = Newtonsoft.Json.JsonConvert.DeserializeObject<RaftCommand>(msgstr, new JsonSerializerSettings() //{ // NullValueHandling = NullValueHandling.Ignore, // TypeNameHandling = TypeNameHandling.All, // TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full //} //); int index = msgstr.IndexOf(','); string num = msgstr.Substring(0, index); string base64 = msgstr.Substring(index + 1); byte[] data = Convert.FromBase64String(base64); RaftCommand cmd = new RaftCommand(); cmd.Code = Convert.ToInt32(num); switch (cmd.Code) { case RaftCommand.Handshake: cmd.Message = TcpMsgHandshake.BiserDecode(data); break; case RaftCommand.HandshakeACK: cmd.Message = TcpMsgHandshake.BiserDecode(data); break; case RaftCommand.RaftMessage: cmd.Message = TcpMsgRaft.BiserDecode(data); TcpMsgRaft t = (TcpMsgRaft)cmd.Message; switch (t.RaftSignalType) { case eRaftSignalType.LeaderHearthbeat: t.orginalObject = LeaderHeartbeat.BiserDecode(t.Data); break; case eRaftSignalType.CandidateRequest: t.orginalObject = CandidateRequest.BiserDecode(t.Data); break; case eRaftSignalType.StateLogEntryAccepted: t.orginalObject = StateLogEntryApplied.BiserDecode(t.Data); break; case eRaftSignalType.StateLogEntryRequest: t.orginalObject = StateLogEntryRequest.BiserDecode(t.Data); break; case eRaftSignalType.StateLogEntrySuggestion: t.orginalObject = StateLogEntrySuggestion.BiserDecode(t.Data); break; case eRaftSignalType.StateLogRedirectRequest: t.orginalObject = StateLogEntryRedirectRequest.BiserDecode(t.Data); break; case eRaftSignalType.VoteOfCandidate: t.orginalObject = VoteOfCandidate.BiserDecode(t.Data); break; } break; case RaftCommand.FreeMessage: cmd.Message = TcpMsg.BiserDecode(data); break; } this.packetParser(cmd as RaftCommand); } }