예제 #1
0
 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"
         });
     }
 }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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();
            }
        }
예제 #4
0
 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
         });
     }
 }
예제 #5
0
 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
         });
     }
 }
예제 #6
0
        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);
            }
        }