public StateLogEntrySuggestion GetNextStateLogEntrySuggestion(StateLogEntryRequest req)
        {
            StateLogEntrySuggestion le = new StateLogEntrySuggestion()
            {
                LeaderTerm = this.stateMachine.NodeTerm
            };
            ulong         prevId   = 0;
            ulong         prevTerm = 0;
            StateLogEntry entry    = null;

            if (req.StateLogEntryId == 0)
            {
                //send first record to sync
                var   key = GetKey(0, 0);
                Slice value;
                var   iter = db.NewIterator(ReadOptions.Default);
                iter.Seek(key);
                iter.Next();
                while (iter.Valid())
                {
                    entry = StateLogEntry.BiserDecode(value.ToArray());
                    if (entry.IsCommitted)
                    {
                        break;
                    }
                    iter.Next();
                }
            }
            else
            {
                var   key = GetKey(req.StateLogEntryTerm, req.StateLogEntryId);
                Slice value;
                var   iter = db.NewIterator(ReadOptions.Default);
                iter.Seek(key);
                var lastOne = iter.Value();
                iter.Next();
                while (iter.Valid())
                {
                    entry = StateLogEntry.BiserDecode(value.ToArray());
                    if (entry.Index > req.StateLogEntryId)
                    {
                        var oldEntry = StateLogEntry.BiserDecode(lastOne.ToArray());
                        prevId   = oldEntry.Index;
                        prevTerm = oldEntry.Term;
                    }
                }
            }
            if (entry != null)
            {
                le.StateLogEntry           = entry;
                entry.PreviousStateLogId   = prevId;
                entry.PreviousStateLogTerm = prevTerm;
                le.IsCommitted             = entry.IsCommitted;
                return(le);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Is called from lock_operations
        /// Adds to silo table, until is moved to log table.
        /// This table can be cleared up on start
        /// returns concatenated term+index inserted identifier
        /// </summary>
        /// <param name="data"></param>
        /// <param name="externalID">if set up must be returned in OnCommitted to notify that command is executed</param>
        /// <returns></returns>
        public StateLogEntry AddStateLogEntryForDistribution(byte[] data, byte[] externalID = null)
        {
            /*
             * Only nodes of the current term can be distributed
             */

            tempPrevStateLogId   = tempStateLogId;
            tempPrevStateLogTerm = tempStateLogTerm;

            tempStateLogId++;
            tempStateLogTerm = rn.NodeTerm;


            StateLogEntry le = new StateLogEntry()
            {
                Index = tempStateLogId,
                Data  = data,
                Term  = tempStateLogTerm,
                PreviousStateLogId   = tempPrevStateLogId,
                PreviousStateLogTerm = tempPrevStateLogTerm,
                ExternalID           = externalID
            };

            qDistribution.Add(le.Index, le);
            return(le);
        }
Beispiel #3
0
        /// <summary>
        /// +
        /// Must be called inside of operation lock.
        /// </summary>
        /// <param name="logEntryId"></param>
        /// <returns></returns>
        public StateLogEntry GetCommitedEntryByIndex(ulong logEntryId)
        {
            try
            {
                if (this.LastCommittedIndex < logEntryId)
                {
                    return(null);
                }

                StateLogEntry isle = null;
                lock (inMem.Sync)
                {
                    foreach (var el in inMem.SelectForwardFromTo(logEntryId, ulong.MinValue, true, ulong.MaxValue, ulong.MaxValue))
                    {
                        if (el.Item3.FakeEntry)
                        {
                            continue;
                        }
                        return(el.Item3);
                    }

                    return(isle);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Beispiel #4
0
 public bool CommitLogEntry(NodeRaftAddress address, uint majorityQuantity, StateLogEntryApplied applied)
 {
     //If we receive acceptance signals of already Committed entries, we just ignore them
     if (this.LastCommittedIndex < applied.StateLogEntryId && stateMachine.NodeTerm == applied.StateLogEntryTerm)    //Setting LastCommittedId
     {
         var key  = GetKey(applied.StateLogEntryTerm, applied.StateLogEntryId);
         var iter = db.NewIterator();
         iter.Seek(key);
         int update = 0;
         while (iter.Valid())
         {
             var entry = StateLogEntry.BiserDecode(iter.Value());
             if (entry.IsCommitted)
             {
                 break;
             }
             entry.IsCommitted = true;
             var value = entry.BiserEncode();
             db.Put(key, value);
             update++;
             iter.Prev();
         }
         this.LastCommittedIndex     = applied.StateLogEntryId;
         this.LastCommittedIndexTerm = applied.StateLogEntryTerm;
         return(update > 0);
     }
     return(false);
 }
        public ReturnValueBase ExecuteBusinessLogic(StateLogEntry entry, RaftStateMachine node)
        {
            node.NodeStateLog.LastBusinessLogicCommittedIndex = entry.Index;
            if (GlobalConfig.Verbose)
            {
                Console.WriteLine("receive entry:" + entry.Index + " on node:" + node.NodeName);
            }
            string text = System.Text.Encoding.UTF8.GetString(entry.Data);
            var    cmd  = Newtonsoft.Json.JsonConvert.DeserializeObject <LockOper>(text);

            if (cmd != null)
            {
                bool succ = this.table.GetQueue(cmd.Key).LockNoWait(cmd.Session, cmd.Type);
                return(new ReturnValueBase
                {
                    Success = succ,
                    Message = "operation finished"
                });
            }
            return(new ReturnValueBase()
            {
                Success = false,
                Message = "wrong command"
            });
        }
        public StateLogEntry GetEntryByIndexTerm(ulong logEntryId, ulong logEntryTerm)
        {
            var   key = GetKey(logEntryTerm, logEntryId);
            Slice value;
            var   find = db.TryGet(ReadOptions.Default, (Slice)key, out value);

            if (find)
            {
                var entry = StateLogEntry.BiserDecode(value.ToArray());
                return(entry);
            }
            return(null);
        }
Beispiel #7
0
        public StateLogEntry GetEntryByIndexTerm(ulong logEntryId, ulong logEntryTerm)
        {
            var key = GetKey(logEntryTerm, logEntryId);

            var value = db.Get(key);
            var find  = value == null;

            if (find)
            {
                var entry = StateLogEntry.BiserDecode(value);
                return(entry);
            }
            return(null);
        }
Beispiel #8
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
         });
     }
 }
Beispiel #9
0
 /// <summary>
 /// +
 /// Get Term by EntryLogIndex. Returns First element false if not found, Second - Term (if found).
 /// Must be called inside of operation lock.
 /// </summary>
 /// <param name="logId"></param>
 /// <returns>first element true if exists</returns>
 public StateLogEntry GetEntryByIndexTerm(ulong logEntryId, ulong logEntryTerm)
 {
     try
     {
         Tuple <ulong, StateLogEntry> sleTpl;
         StateLogEntry isle = null;
         lock (inMem.Sync)
         {
             inMem.Select(logEntryId, logEntryTerm, out isle);
         }
         return(isle);
     }
     catch (Exception ex)
     {
         throw ex;
     }
 }
Beispiel #10
0
        public StateLogEntrySuggestion GetNextStateLogEntrySuggestion(StateLogEntryRequest req)
        {
            StateLogEntrySuggestion le = new StateLogEntrySuggestion()
            {
                LeaderTerm = this.stateMachine.NodeTerm
            };
            ulong         prevId   = 0;
            ulong         prevTerm = 0;
            StateLogEntry entry    = null;

            if (req.StateLogEntryId == 0)
            {
                //send first record to sync
                entry = list.Find(s => s.IsCommitted == true);
            }
            else
            {
                for (int index = 0; index < list.Count; index++)
                {
                    if (list[index].Index > req.StateLogEntryId)
                    {
                        //find next one and set preview value
                        if (index > 0)
                        {
                            prevId   = list[index - 1].Index;
                            prevTerm = list[index - 1].Term;
                            entry    = list[index];
                            break;
                        }
                    }
                }
            }
            if (entry != null)
            {
                le.StateLogEntry           = entry;
                entry.PreviousStateLogId   = prevId;
                entry.PreviousStateLogTerm = prevTerm;
                le.IsCommitted             = entry.IsCommitted;
                return(le);
            }
            else
            {
                return(null);
            }
        }
        public void RollbackToLastestCommit()
        {
            if (LastCommittedIndex == 0 || LastCommittedIndexTerm == 0)
            {
                return;
            }
            var   key = GetKey(0, 0);
            Slice value;
            var   iter = db.NewIterator(ReadOptions.Default);

            iter.SeekToLast();
            while (iter.Valid())
            {
                var entry = StateLogEntry.BiserDecode(iter.Value().ToArray());
                if (entry.Term >= LastCommittedIndexTerm && entry.Index > LastCommittedIndex)
                {
                    db.Delete(WriteOptions.Default, iter.Key());
                }
            }
        }
Beispiel #12
0
        public void RollbackToLastestCommit()
        {
            if (LastCommittedIndex == 0 || LastCommittedIndexTerm == 0)
            {
                return;
            }
            var key = GetKey(0, 0);

            var iter = db.NewIterator();

            iter.SeekToLast();
            while (iter.Valid())
            {
                var entry = StateLogEntry.BiserDecode(iter.Value());
                if (entry.Term >= LastCommittedIndexTerm && entry.Index > LastCommittedIndex)
                {
                    db.Remove(iter.Key());
                }
            }
        }
Beispiel #13
0
        public void AddLogEntry(StateLogEntrySuggestion suggestion)
        {
            PreviousStateLogId   = suggestion.StateLogEntry.PreviousStateLogId;
            PreviousStateLogTerm = suggestion.StateLogEntry.PreviousStateLogTerm;
            StateLogId           = suggestion.StateLogEntry.Index;
            StateLogTerm         = suggestion.StateLogEntry.Term;
            var key   = GetKey(suggestion.StateLogEntry.Term, suggestion.StateLogEntry.Index);
            var value = db.Get(key);
            var find  = value != null;

            if (find)
            {
                var entry = StateLogEntry.BiserDecode(value);
                entry.IsCommitted = suggestion.IsCommitted;
                value             = entry.BiserEncoder().Encode();
                db.Put(key, value);
            }
            else
            {
                var data = suggestion.StateLogEntry.BiserEncode();
                db.Put(key, data);
            }
        }
Beispiel #14
0
        public void ReloadFromStorage()
        {
            //should load from log files
            var iter = db.NewIterator();

            iter.SeekToLast();
            while (iter.Valid())
            {
                var entry = StateLogEntry.BiserDecode(iter.Value());
                StateLogId            = entry.Index;
                StateLogTerm          = entry.Term;
                PreviousStateLogId    = entry.PreviousStateLogId;
                PreviousStateLogTerm  = entry.PreviousStateLogTerm;
                stateMachine.NodeTerm = entry.Term;
                if (entry.IsCommitted)
                {
                    LastCommittedIndex              = entry.Index;
                    LastCommittedIndexTerm          = entry.Term;
                    LastBusinessLogicCommittedIndex = entry.Index;
                    return;
                }
            }
        }
        public void AddLogEntry(StateLogEntrySuggestion suggestion)
        {
            PreviousStateLogId   = suggestion.StateLogEntry.PreviousStateLogId;
            PreviousStateLogTerm = suggestion.StateLogEntry.PreviousStateLogTerm;
            StateLogId           = suggestion.StateLogEntry.Index;
            StateLogTerm         = suggestion.StateLogEntry.Term;
            var   key = GetKey(suggestion.StateLogEntry.Term, suggestion.StateLogEntry.Index);
            Slice value;
            var   find = db.TryGet(ReadOptions.Default, (Slice)key, out value);

            if (find)
            {
                var entry = StateLogEntry.BiserDecode(value.ToArray());
                entry.IsCommitted = suggestion.IsCommitted;
                value             = (Slice)entry.BiserEncoder().Encode();
                db.Put(WriteOptions.Default, key, value);
            }
            else
            {
                var data = suggestion.StateLogEntry.BiserEncode();
                db.Put(WriteOptions.Default, key, (Slice)data);
            }
        }
Beispiel #16
0
        static void t1()
        {
            /*
             * Start
             *  Protobuf obj length: 22
             *  Biser Binary obj length: 17
             *  NetJson obj length: 129
             *  Biser Json obj length: 129
             *
             *  Protobuf encode: 1184 ms
             *  Protobuf decode: 1569 ms
             *  Biser Binary encode: 396 ms
             *  Biser Binary decode: 209 ms
             *  NetJson encode: 1350 ms
             *  NetJson decode: 1902 ms
             *  Biser Json encode: 2266 ms
             *  Biser Json decode: 3659 ms
             * Press any key
             */

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

            // It's an operational class from https://github.com/hhblaze/Raft.Net/blob/master/Raft/StateMachine/StateLogEntry.cs
            StateLogEntry obj = new StateLogEntry()
            {
                Data                 = new byte[] { 1, 2, 3, 4, 5 },
                Index                = 458,
                IsCommitted          = true,
                PreviousStateLogId   = 4789,
                PreviousStateLogTerm = 447,
                RedirectId           = 12,
                Term                 = 99
            };

            Console.WriteLine("t1----------------------------------");

            //Protobuf. Warming up, getting length
            var pBt = obj.SerializeProtobuf();

            Console.WriteLine($"Protobuf obj length: {pBt.Length}");
            var pObj = pBt.DeserializeProtobuf <StateLogEntry>();

            //Biser. Getting length
            var bBt = new Biser.Encoder().Add(obj).Encode();

            Console.WriteLine($"Biser Binary obj length: {bBt.Length}");
            var bObj = StateLogEntry.BiserDecode(bBt);

            //NetJson. Getting length
            var njss = NetJSON.NetJSON.Serialize(obj);

            Console.WriteLine($"NetJson obj length: {System.Text.Encoding.UTF8.GetBytes(njss).Length}");
            var bnjss = NetJSON.NetJSON.Deserialize <StateLogEntry>(njss);

            //Biser Json. Getting length
            var bjss = new Biser.JsonEncoder(obj).GetJSON();

            Console.WriteLine($"Biser Json obj length: {System.Text.Encoding.UTF8.GetBytes(bjss).Length}");
            var bbjss = StateLogEntry.BiserJsonDecode(bjss);

            //Message Pack
            var mBt = MessagePackSerializer.Serialize(obj);

            Console.WriteLine($"Message Pack obj length: {mBt.Length}");
            var mc2 = MessagePackSerializer.Deserialize <StateLogEntry>(mBt);

            Console.WriteLine("");

            byte[]        tbt  = null;
            StateLogEntry tobj = null;

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                tbt = obj.SerializeProtobuf();
            }
            sw.Stop();
            Console.WriteLine($"Protobuf encode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                tobj = pBt.DeserializeProtobuf <StateLogEntry>();
            }
            sw.Stop();
            Console.WriteLine($"Protobuf decode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                tbt = new Biser.Encoder().Add(obj).Encode();
            }
            sw.Stop();
            Console.WriteLine($"Biser Binary encode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                tobj = StateLogEntry.BiserDecode(bBt);
            }
            sw.Stop();
            Console.WriteLine($"Biser Binary decode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                njss = NetJSON.NetJSON.Serialize(obj);
            }
            sw.Stop();
            Console.WriteLine($"NetJson encode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                bnjss = NetJSON.NetJSON.Deserialize <StateLogEntry>(njss);
            }
            sw.Stop();
            Console.WriteLine($"NetJson decode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();


            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                bjss = new Biser.JsonEncoder(obj).GetJSON();
            }
            sw.Stop();
            Console.WriteLine($"Biser Json encode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                bbjss = StateLogEntry.BiserJsonDecode(bjss);
            }
            sw.Stop();
            Console.WriteLine($"Biser Json decode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();


            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                mBt = MessagePackSerializer.Serialize(obj);
            }
            sw.Stop();
            Console.WriteLine($"MessagePack encode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();

            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                mc2 = MessagePackSerializer.Deserialize <StateLogEntry>(mBt);
            }
            sw.Stop();
            Console.WriteLine($"MessagePack decode: {sw.ElapsedMilliseconds} ms");
            sw.Reset();
        }
Beispiel #17
0
        internal void Commited()
        {
            if (System.Threading.Interlocked.CompareExchange(ref this.stateMachine.States.inCommit, 1, 0) != 0)
            {
                return;
            }
            Task.Run(async() =>
            {
                StateLogEntry sle = null;
                while (true)
                {
                    if (GlobalConfig.Verbose)
                    {
                        Console.WriteLine("in commited");
                    }
                    lock (this.stateMachine.lock_Operations)
                    {
                        if (this.stateMachine.NodeStateLog.LastCommittedIndex == this.stateMachine.NodeStateLog.LastBusinessLogicCommittedIndex)
                        {
                            System.Threading.Interlocked.Exchange(ref this.stateMachine.States.inCommit, 0);
                            return;
                        }
                        else
                        {
                            sle = this.stateMachine.NodeStateLog.GetCommitedEntryByIndex(
                                this.stateMachine.NodeStateLog.LastCommittedIndexTerm,
                                this.stateMachine.NodeStateLog.LastBusinessLogicCommittedIndex + 1);
                            if (sle == null)
                            {
                                System.Threading.Interlocked.Exchange(ref this.stateMachine.States.inCommit, 0);
                                return;
                            }
                        }
                    }

                    try
                    {
                        if (GlobalConfig.Verbose)
                        {
                            Console.WriteLine("before call business logic");
                        }
                        var executeResult = this.businessLogicHandler.ExecuteBusinessLogic(sle, this.stateMachine);
                        //In case if business logic commit was successful

                        //Notifying Async AddLog
                        //if (GlobalConfig.Verbose)
                        //{
                        //    Console.WriteLine("before release lock");
                        //}
                        if (sle.ExternalID != null && AsyncResponseHandler.df.TryGetValue(sle.ExternalID.ToBytesString(), out var responseCrate))
                        {
                            responseCrate.IsRespOk    = true;
                            responseCrate.ReturnValue = executeResult;
                            responseCrate.res         = sle.ExternalID;
                            responseCrate.Set_MRE();
                        }

                        //else
                        //{
                        //    await Task.Delay(500);
                        //    //repeating with the same id
                        //}
                    }
                    catch (Exception ex)
                    {
                        this.stateMachine.Log.Log(new WarningLogEntry()
                        {
                            Exception = ex, Method = "Raft.RaftNode.Commited"
                        });
                        //Notifying Async AddLog
                        if (sle.ExternalID != null && AsyncResponseHandler.df.TryGetValue(sle.ExternalID.ToBytesString(), out var responseCrate))
                        {
                            responseCrate.IsRespOk = false;
                            responseCrate.res      = sle.ExternalID;
                            responseCrate.Set_MRE();
                        }
                    }
                }
            });
        }