示例#1
0
        public static StateLogEntryRequest BiserDecode(byte[] enc = null, Biser.Decoder extDecoder = null) //!!!!!!!!!!!!!! change return type
        {
            Biser.Decoder decoder = null;
            if (extDecoder == null)
            {
                if (enc == null || enc.Length == 0)
                {
                    return(null);
                }
                decoder = new Biser.Decoder(enc);
                if (decoder.CheckNull())
                {
                    return(null);
                }
            }
            else
            {
                if (extDecoder.CheckNull())
                {
                    return(null);
                }
                else
                {
                    decoder = extDecoder;
                }
            }

            StateLogEntryRequest m = new StateLogEntryRequest();  //!!!!!!!!!!!!!! change return type

            m.StateLogEntryId   = decoder.GetULong();
            m.StateLogEntryTerm = decoder.GetULong();

            return(m);
        }
示例#2
0
        /// <summary>
        /// Only for Leader.
        /// Follower requests new Log Entry Index from the Leader and Leader answers to the Follower
        /// </summary>
        /// <param name="address"></param>
        /// <param name="data"></param>
        void ParseStateLogEntryRequest(NodeAddress address, byte[] data)
        {
            if (this.NodeState != eNodeState.Leader)
            {
                return;
            }

            StateLogEntryRequest req = StateLogEntryRequest.BiserDecode(data);//.DeserializeProtobuf<StateLogEntryRequest>();

            //Getting suggestion
            var suggestion = this.NodeStateLog.GetNextStateLogEntrySuggestionFromRequested(req);

            //VerbosePrint($"{NodeAddress.NodeAddressId} (Leader)> Request (I/T): {req.StateLogEntryId}/{req.StateLogEntryTerm} from {address.NodeAddressId};");
            VerbosePrint($"{NodeAddress.NodeAddressId} (Leader)> Request (I): {req.StateLogEntryId} from {address.NodeAddressId};");

            if (suggestion != null)
            {
                this.Sender.SendTo(address, eRaftSignalType.StateLogEntrySuggestion, suggestion.SerializeBiser(), this.NodeAddress, entitySettings.EntityName);
            }
        }
示例#3
0
        /// <summary>
        /// Only for Leader.
        /// Follower requests new Log Entry Index from the Leader and Leader answers to the Follower
        /// </summary>
        /// <param name="address"></param>
        /// <param name="data"></param>
        void ParseStateLogEntryRequest(NodeRaftAddress address, object data)
        {
            if (this.States.NodeState != eNodeState.Leader)
            {
                return;
            }
            StateLogEntryRequest req = data as StateLogEntryRequest;
            //Getting suggestion
            var suggestion = this.NodeStateLog.GetNextStateLogEntrySuggestion(req);

            if (GlobalConfig.Verbose)
            {
                Console.WriteLine($"create suggestion to req:{req.StateLogEntryId}" + suggestion.StateLogEntry.Index + " is commit:" + suggestion.StateLogEntry.IsCommitted);
            }
            //VerbosePrint($"{NodeAddress.NodeAddressId} (Leader)> Request (I): {req.StateLogEntryId} from {address.NodeAddressId};");
            if (suggestion != null)
            {
                this.network.SendTo(address, eRaftSignalType.StateLogEntrySuggestion, suggestion, this.NodeAddress, entitySettings.EntityName);
            }
        }
示例#4
0
        /// <summary>
        /// Is called from tryCatch and lock.
        /// Synchronizes starting from last committed value
        /// </summary>
        /// <param name="stateLogEntryId"></param>
        internal void SyncronizeWithLeader(bool selfCall = false)
        {
            if (!selfCall)
            {
                if (IsLeaderSynchroTimerActive)
                {
                    return;
                }
                NodeStateLog.RollbackToLastestCommit();
            }
            States.LeaderSynchronizationIsActive       = true;
            States.LeaderSynchronizationRequestWasSent = DateTime.UtcNow;

            StateLogEntryRequest req = null;

            req = new StateLogEntryRequest()
            {
                StateLogEntryId = NodeStateLog.LastCommittedIndex
            };
            this.network.SendTo(this.LeaderNodeAddress, eRaftSignalType.StateLogEntryRequest, req, this.NodeAddress, entitySettings.EntityName);
        }
示例#5
0
        /// <summary>
        /// Is called from tryCatch and lock.
        /// Synchronizes starting from last committed value
        /// </summary>
        /// <param name="stateLogEntryId"></param>
        internal void SyncronizeWithLeader(bool selfCall = false)
        {
            if (!selfCall)
            {
                if (IsLeaderSynchroTimerActive)
                {
                    return;
                }

                NodeStateLog.ClearStateLogStartingFromCommitted();
            }

            NodeStateLog.LeaderSynchronizationIsActive       = true;
            NodeStateLog.LeaderSynchronizationRequestWasSent = DateTime.UtcNow;

            StateLogEntryRequest req = null;

            if (entitySettings.InMemoryEntity && entitySettings.InMemoryEntityStartSyncFromLatestEntity)
            {
                req = new StateLogEntryRequest()
                {
                    StateLogEntryId = this.LeaderHeartbeat.LastStateLogCommittedIndex == 0 ? 0 : this.LeaderHeartbeat.LastStateLogCommittedIndex - 1
                };
            }
            else
            {
                req = new StateLogEntryRequest()
                {
                    StateLogEntryId = NodeStateLog.LastCommittedIndex
                };
            }



            this.Sender.SendTo(this.LeaderNodeAddress, eRaftSignalType.StateLogEntryRequest, req.SerializeBiser(), this.NodeAddress, entitySettings.EntityName);
        }
示例#6
0
        /// <summary>
        /// +
        /// Can be null.
        /// Must be called inside of operation lock.
        /// </summary>
        /// <param name="logEntryId"></param>
        /// <param name="LeaderTerm"></param>
        /// <returns></returns>
        public StateLogEntrySuggestion GetNextStateLogEntrySuggestionFromRequested(StateLogEntryRequest req)
        {
            StateLogEntrySuggestion le = new StateLogEntrySuggestion()
            {
                LeaderTerm = rn.NodeTerm
            };

            int           cnt      = 0;
            StateLogEntry sle      = null;
            ulong         prevId   = 0;
            ulong         prevTerm = 0;

            using (var t = this.rn.db.GetTransaction())
            {
                if (req.StateLogEntryId == 0)// && req.StateLogEntryTerm == 0)
                {
                    if (rn.entitySettings.DelayedPersistenceIsActive && sleCache.Count > 0)
                    {
                        sle = sleCache.OrderBy(r => r.Key).First().Value.Item2;
                    }
                    else
                    {
                        var trow = t.SelectForwardFromTo <byte[], byte[]>(tblStateLogEntry,
                                                                          new byte[] { 1 }.ToBytes(ulong.MinValue, ulong.MinValue), true,
                                                                          new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).FirstOrDefault();

                        if (trow != null && trow.Exists)
                        {
                            sle = StateLogEntry.BiserDecode(trow.Value);
                        }
                    }


                    //else
                    //{
                    //    //should not normally happen
                    //}

                    if (sle != null)
                    {
                        le.StateLogEntry = sle;

                        if (
                            LastCommittedIndexTerm >= le.StateLogEntry.Term
                            &&
                            LastCommittedIndex >= le.StateLogEntry.Index
                            )
                        {
                            le.IsCommitted = true;
                        }

                        cnt = 2;
                    }
                }
                else
                {
                    Tuple <ulong, StateLogEntry> sleTpl;
                    bool reForward = true;

                    if (rn.entitySettings.DelayedPersistenceIsActive &&
                        sleCache.TryGetValue(req.StateLogEntryId, out sleTpl)
                        )
                    {
                        cnt++;
                        sle      = sleTpl.Item2;
                        prevId   = sle.Index;
                        prevTerm = sle.Term;

                        if (sleCache.TryGetValue(req.StateLogEntryId + 1, out sleTpl))
                        {
                            cnt++;
                            sle = sleTpl.Item2;
                            le.StateLogEntry = sle;
                        }
                    }
                    else
                    {
                        reForward = false;
                        foreach (var el in t.SelectForwardFromTo <byte[], byte[]>(tblStateLogEntry,
                                                                                  //new byte[] { 1 }.ToBytes(req.StateLogEntryId, req.StateLogEntryTerm), true,
                                                                                  new byte[] { 1 }.ToBytes(req.StateLogEntryId, ulong.MinValue), true,
                                                                                  new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).Take(2))
                        {
                            cnt++;
                            sle = StateLogEntry.BiserDecode(el.Value);
                            if (cnt == 1)
                            {
                                prevId   = sle.Index;
                                prevTerm = sle.Term;
                            }
                            else
                            {
                                le.StateLogEntry = sle;
                            }
                        }
                    }


                    if (cnt < 2 && reForward)
                    {
                        ulong toAdd = (ulong)cnt;
                        foreach (var el in t.SelectForwardFromTo <byte[], byte[]>(tblStateLogEntry,
                                                                                  //new byte[] { 1 }.ToBytes(req.StateLogEntryId + toAdd, req.StateLogEntryTerm), true,
                                                                                  new byte[] { 1 }.ToBytes(req.StateLogEntryId + toAdd, ulong.MinValue), true,
                                                                                  new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).Take(2))
                        {
                            cnt++;
                            sle = StateLogEntry.BiserDecode(el.Value);
                            if (cnt == 1)
                            {
                                prevId   = sle.Index;
                                prevTerm = sle.Term;
                            }
                            else
                            {
                                le.StateLogEntry = sle;
                            }
                        }
                    }


                    if (cnt == 2)
                    {
                        le.StateLogEntry.PreviousStateLogId   = prevId;
                        le.StateLogEntry.PreviousStateLogTerm = prevTerm;
                        if (
                            LastCommittedIndexTerm >= le.StateLogEntry.Term
                            &&
                            LastCommittedIndex >= le.StateLogEntry.Index
                            )
                        {
                            le.IsCommitted = true;
                        }
                    }
                }
            }

            //if (first)
            if (cnt != 2)
            {
                return(null);
            }
            return(le);
        }
示例#7
0
        /// <summary>
        /// +
        /// Can be null.
        /// Must be called inside of operation lock.
        /// get local commit history for follower
        /// </summary>
        /// <param name="logEntryId"></param>
        /// <param name="LeaderTerm"></param>
        /// <returns></returns>
        public StateLogEntrySuggestion GetNextStateLogEntrySuggestionFromRequested(StateLogEntryRequest req)
        {
            StateLogEntrySuggestion le = new StateLogEntrySuggestion()
            {
                LeaderTerm = statemachine.NodeTerm
            };

            int           cnt      = 0;
            StateLogEntry sle      = null;
            ulong         prevId   = 0;
            ulong         prevTerm = 0;

            var col = this.db.GetCollection <StateLogEntry>(stateTableName);

            //using (var t = this.db.GetTransaction())
            {
                if (req.StateLogEntryId == 0)
                {
                    var trow = col.Query().OrderBy(s => s.Term, 1).OrderBy(s => s.Term, 1).FirstOrDefault();
                    if (trow != null)
                    {
                        le.StateLogEntry = trow;
                        if (LastCommittedIndexTerm >= le.StateLogEntry.Term &&
                            LastCommittedIndex >= le.StateLogEntry.Index
                            )
                        {
                            le.IsCommitted = true;
                        }
                        cnt = 2;
                    }
                }
                else
                {
                    var list = col.Query().Where(s => s.Index >= req.StateLogEntryId).ToList().OrderBy(s => s.Term).OrderBy(s => s.Term).ToList();
                    foreach (var item in list)
                    {
                        cnt++;
                        sle = item;
                        if (cnt == 1)
                        {
                            prevId   = sle.Index;
                            prevTerm = sle.Term;
                        }
                        else
                        {
                            le.StateLogEntry = sle;
                        }
                    }
                    if (cnt < 2)
                    {
                        ulong toAdd = (ulong)cnt;
                        list = col.Query().Where(s => s.Index >= req.StateLogEntryId + toAdd).ToList().OrderBy(s => s.Term).OrderBy(s => s.Index).ToList();
                        foreach (var item in list)
                        {
                            cnt++;
                            sle = item;
                            if (cnt == 1)
                            {
                                prevId   = sle.Index;
                                prevTerm = sle.Term;
                            }
                            else
                            {
                                le.StateLogEntry = sle;
                            }
                        }
                    }
                }
                //if (req.StateLogEntryId == 0)// && req.StateLogEntryTerm == 0)
                //{

                //  var trow = t.SelectForwardFromTo<byte[], byte[]>(stateTableName,
                //               new byte[] { 1 }.ToBytes(ulong.MinValue, ulong.MinValue), true,
                //               new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).FirstOrDefault();

                //  if (trow != null && trow.Exists)
                //      sle = StateLogEntry.BiserDecode(trow.Value);
                //  if (sle != null)
                //    {
                //        le.StateLogEntry = sle;
                //        if (
                //            LastCommittedIndexTerm >= le.StateLogEntry.Term
                //            &&
                //            LastCommittedIndex >= le.StateLogEntry.Index
                //            )
                //        {
                //            le.IsCommitted = true;
                //        }
                //        cnt = 2;
                //    }
                //}
                //else
                //{
                //    Tuple<ulong, StateLogEntry> sleTpl;
                //    bool reForward = true;
                //        reForward = false;
                //        foreach (var el in t.SelectForwardFromTo<byte[], byte[]>(stateTableName,
                //            new byte[] { 1 }.ToBytes(req.StateLogEntryId, ulong.MinValue), true,
                //            new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).Take(2))
                //        {
                //            cnt++;
                //            sle = StateLogEntry.BiserDecode(el.Value);
                //            if (cnt == 1)
                //            {
                //                prevId = sle.Index;
                //                prevTerm = sle.Term;
                //            }
                //            else
                //            {
                //                le.StateLogEntry = sle;
                //            }
                //    }
                //    if (cnt < 2 && reForward)
                //    {
                //        ulong toAdd = (ulong)cnt;
                //        foreach (var el in t.SelectForwardFromTo<byte[], byte[]>(stateTableName,
                //        //new byte[] { 1 }.ToBytes(req.StateLogEntryId + toAdd, req.StateLogEntryTerm), true,
                //        new byte[] { 1 }.ToBytes(req.StateLogEntryId + toAdd, ulong.MinValue), true,
                //        new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).Take(2))
                //        {
                //            cnt++;
                //            sle = StateLogEntry.BiserDecode(el.Value);
                //            if (cnt == 1)
                //            {
                //                prevId = sle.Index;
                //                prevTerm = sle.Term;
                //            }
                //            else
                //            {
                //                le.StateLogEntry = sle;
                //            }
                //        }
            }

            if (cnt == 2)
            {
                le.StateLogEntry.PreviousStateLogId   = prevId;
                le.StateLogEntry.PreviousStateLogTerm = prevTerm;
                if (
                    LastCommittedIndexTerm >= le.StateLogEntry.Term
                    &&
                    LastCommittedIndex >= le.StateLogEntry.Index
                    )
                {
                    le.IsCommitted = true;
                }
            }


            if (cnt != 2)
            {
                return(null);
            }
            return(le);
        }
示例#8
0
        /// <summary>
        /// +
        /// Can be null.
        /// Must be called inside of operation lock.
        /// get local commit history for follower
        /// </summary>
        /// <param name="logEntryId"></param>
        /// <param name="LeaderTerm"></param>
        /// <returns></returns>
        public StateLogEntrySuggestion GetNextStateLogEntrySuggestion(StateLogEntryRequest req)
        {
            StateLogEntrySuggestion le = new StateLogEntrySuggestion()
            {
                LeaderTerm = statemachine.NodeTerm
            };

            int           cnt      = 0;
            StateLogEntry sle      = null;
            ulong         prevId   = 0;
            ulong         prevTerm = 0;

            using (var t = this.db.GetTransaction())
            {
                if (req.StateLogEntryId == 0)// && req.StateLogEntryTerm == 0)
                {
                    var trow = t.SelectForwardFromTo <byte[], byte[]>(stateTableName,
                                                                      new byte[] { 1 }.ToBytes(ulong.MinValue, ulong.MinValue), true,
                                                                      new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).FirstOrDefault();

                    if (trow != null && trow.Exists)
                    {
                        sle = StateLogEntry.BiserDecode(trow.Value);
                    }
                    if (sle != null)
                    {
                        le.StateLogEntry = sle;
                        if (
                            LastCommittedIndexTerm >= le.StateLogEntry.Term
                            &&
                            LastCommittedIndex >= le.StateLogEntry.Index
                            )
                        {
                            le.IsCommitted = true;
                        }
                        cnt = 2;
                    }
                }
                else
                {
                    Tuple <ulong, StateLogEntry> sleTpl;
                    bool reForward = true;
                    reForward = false;
                    foreach (var el in t.SelectForwardFromTo <byte[], byte[]>(stateTableName,
                                                                              new byte[] { 1 }.ToBytes(req.StateLogEntryId, ulong.MinValue), true,
                                                                              new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).Take(2))
                    {
                        cnt++;
                        sle = StateLogEntry.BiserDecode(el.Value);
                        if (cnt == 1)
                        {
                            prevId   = sle.Index;
                            prevTerm = sle.Term;
                        }
                        else
                        {
                            le.StateLogEntry = sle;
                        }
                    }
                    if (cnt < 2 && reForward)
                    {
                        ulong toAdd = (ulong)cnt;
                        foreach (var el in t.SelectForwardFromTo <byte[], byte[]>(stateTableName,
                                                                                  //new byte[] { 1 }.ToBytes(req.StateLogEntryId + toAdd, req.StateLogEntryTerm), true,
                                                                                  new byte[] { 1 }.ToBytes(req.StateLogEntryId + toAdd, ulong.MinValue), true,
                                                                                  new byte[] { 1 }.ToBytes(ulong.MaxValue, ulong.MaxValue), true).Take(2))
                        {
                            cnt++;
                            sle = StateLogEntry.BiserDecode(el.Value);
                            if (cnt == 1)
                            {
                                prevId   = sle.Index;
                                prevTerm = sle.Term;
                            }
                            else
                            {
                                le.StateLogEntry = sle;
                            }
                        }
                    }
                    if (cnt == 2)
                    {
                        le.StateLogEntry.PreviousStateLogId   = prevId;
                        le.StateLogEntry.PreviousStateLogTerm = prevTerm;
                        if (
                            LastCommittedIndexTerm >= le.StateLogEntry.Term
                            &&
                            LastCommittedIndex >= le.StateLogEntry.Index
                            )
                        {
                            le.IsCommitted = true;
                        }
                    }
                }
            }
            if (cnt != 2)
            {
                return(null);
            }
            return(le);
        }