Exemple #1
0
        public static IEnumerable <T> Seek <T>(this DB db, ReadOptions options, byte[] prefix, SeekDirection direction, Func <byte[], byte[], T> resultSelector)
        {
            using Iterator it = db.NewIterator(options);
            if (direction == SeekDirection.Forward)
            {
                for (it.Seek(prefix); it.Valid(); it.Next())
                {
                    yield return(resultSelector(it.Key(), it.Value()));
                }
            }
            else
            {
                // SeekForPrev

                it.Seek(prefix);
                if (!it.Valid())
                {
                    it.SeekToLast();
                }
                else if (it.Key().AsSpan().SequenceCompareTo(prefix) > 0)
                {
                    it.Prev();
                }

                for (; it.Valid(); it.Prev())
                {
                    yield return(resultSelector(it.Key(), it.Value()));
                }
            }
        }
Exemple #2
0
        public static IEnumerable <T> Seek <T>(this DB db, ReadOptions options, byte table, byte[] prefix, SeekDirection direction, Func <byte[], byte[], T> resultSelector)
        {
            using Iterator it = db.NewIterator(options);
            byte[] target = CreateKey(table, prefix);
            if (direction == SeekDirection.Forward)
            {
                for (it.Seek(target); it.Valid(); it.Next())
                {
                    var key = it.Key();
                    if (key.Length < 1 || key[0] != table)
                    {
                        break;
                    }
                    yield return(resultSelector(it.Key(), it.Value()));
                }
            }
            else
            {
                // SeekForPrev

                it.Seek(target);
                if (!it.Valid())
                {
                    it.SeekToLast();
                }
                else if (it.Key().AsSpan().SequenceCompareTo(target) > 0)
                {
                    it.Prev();
                }

                for (; it.Valid(); it.Prev())
                {
                    var key = it.Key();
                    if (key.Length < 1 || key[0] != table)
                    {
                        break;
                    }
                    yield return(resultSelector(it.Key(), it.Value()));
                }
            }
        }
Exemple #3
0
 public static IEnumerable <T> FindRange <T>(this DB db, ReadOptions options, byte[] startKey, byte[] endKey, Func <byte[], byte[], T> resultSelector)
 {
     using Iterator it = db.NewIterator(options);
     for (it.Seek(startKey); it.Valid(); it.Next())
     {
         byte[] key = it.Key();
         if (key.AsSpan().SequenceCompareTo(endKey) > 0)
         {
             break;
         }
         yield return(resultSelector(key, it.Value()));
     }
 }
Exemple #4
0
        public static IEnumerable <T> Seek <T>(this DB db, ReadOptions options, byte table, byte[] prefix, SeekDirection direction, Func <byte[], byte[], T> resultSelector)
        {
            using Iterator it = db.NewIterator(options);
            for (it.Seek(CreateKey(table, prefix)); it.Valid();)
            {
                var key = it.Key();
                if (key.Length < 1 || key[0] != table)
                {
                    break;
                }
                yield return(resultSelector(it.Key(), it.Value()));

                if (direction == SeekDirection.Forward)
                {
                    it.Next();
                }
                else
                {
                    it.Prev();
                }
            }
        }
Exemple #5
0
 public static IEnumerable <T> Find <T>(this DB db, ReadOptions options, byte[] prefix, Func <byte[], byte[], T> resultSelector)
 {
     using Iterator it = db.NewIterator(options);
     for (it.Seek(prefix); it.Valid(); it.Next())
     {
         byte[] key = it.Key();
         if (key.Length < prefix.Length)
         {
             break;
         }
         if (!key.AsSpan().StartsWith(prefix))
         {
             break;
         }
         yield return(resultSelector(key, it.Value()));
     }
 }
Exemple #6
0
 public static IEnumerable <T> Find <T>(this DB db, ReadOptions options, Slice prefix, Func <Slice, Slice, T> resultSelector)
 {
     using (Iterator it = db.NewIterator(options))
     {
         for (it.Seek(prefix); it.Valid(); it.Next())
         {
             Slice  key = it.Key();
             byte[] x   = key.ToArray();
             byte[] y   = prefix.ToArray();
             if (x.Length < y.Length)
             {
                 break;
             }
             if (!x.Take(y.Length).SequenceEqual(y))
             {
                 break;
             }
             yield return(resultSelector(key, it.Value()));
         }
     }
 }
        public LevelDBBlockchain(string path, string fulllogpath = null, int _fulllog_splitcount = 1, int _fulllog_splitindex = 0)
        {
            this.FullLogPath        = fulllogpath;
            this.fulllog_splitcount = _fulllog_splitcount;
            this.fulllog_splitindex = _fulllog_splitindex;
            if (string.IsNullOrEmpty(this.FullLogPath) == false)
            {
                if (System.IO.Directory.Exists(FullLogPath) == false)
                {
                    System.IO.Directory.CreateDirectory(FullLogPath);
                }
            }
            else
            {
                this.FullLogPath = null;
            }

            header_index.Add(GenesisBlock.Hash);
            Version version;
            Slice   value;

            db = DB.Open(path, new Options {
                CreateIfMissing = true
            });
            if (db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.SYS_Version), out value) && Version.TryParse(value.ToString(), out version) && version >= Version.Parse("2.6.0"))
            {
                ReadOptions options = new ReadOptions {
                    FillCache = false
                };
                value = db.Get(options, SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock));
                UInt256 current_header_hash = new UInt256(value.ToArray().Take(32).ToArray());
                this.current_block_height = value.ToArray().ToUInt32(32);
                uint current_header_height = current_block_height;
                if (db.TryGet(options, SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentHeader), out value))
                {
                    current_header_hash   = new UInt256(value.ToArray().Take(32).ToArray());
                    current_header_height = value.ToArray().ToUInt32(32);
                }
                foreach (UInt256 hash in db.Find(options, SliceBuilder.Begin(DataEntryPrefix.IX_HeaderHashList), (k, v) =>
                {
                    using (MemoryStream ms = new MemoryStream(v.ToArray(), false))
                        using (BinaryReader r = new BinaryReader(ms))
                        {
                            return(new
                            {
                                Index = k.ToArray().ToUInt32(1),
                                Hashes = r.ReadSerializableArray <UInt256>()
                            });
                        }
                }).OrderBy(p => p.Index).SelectMany(p => p.Hashes).ToArray())
                {
                    if (!hash.Equals(GenesisBlock.Hash))
                    {
                        header_index.Add(hash);
                    }
                    stored_header_count++;
                }
                if (stored_header_count == 0)
                {
                    Header[] headers = db.Find(options, SliceBuilder.Begin(DataEntryPrefix.DATA_Block), (k, v) => Header.FromTrimmedData(v.ToArray(), sizeof(long))).OrderBy(p => p.Index).ToArray();
                    for (int i = 1; i < headers.Length; i++)
                    {
                        header_index.Add(headers[i].Hash);
                    }
                }
                else if (current_header_height >= stored_header_count)
                {
                    for (UInt256 hash = current_header_hash; hash != header_index[(int)stored_header_count - 1];)
                    {
                        Header header = Header.FromTrimmedData(db.Get(options, SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(hash)).ToArray(), sizeof(long));
                        header_index.Insert((int)stored_header_count, hash);
                        hash = header.PrevHash;
                    }
                }
            }
            else
            {
                WriteBatch  batch   = new WriteBatch();
                ReadOptions options = new ReadOptions {
                    FillCache = false
                };
                using (Iterator it = db.NewIterator(options))
                {
                    for (it.SeekToFirst(); it.Valid(); it.Next())
                    {
                        batch.Delete(it.Key());
                    }
                }
                db.Write(WriteOptions.Default, batch);
                Persist(GenesisBlock);
                db.Put(WriteOptions.Default, SliceBuilder.Begin(DataEntryPrefix.SYS_Version), GetType().GetTypeInfo().Assembly.GetName().Version.ToString());
            }
            thread_persistence      = new Thread(PersistBlocks);
            thread_persistence.Name = "LevelDBBlockchain.PersistBlocks";
            thread_persistence.Start();
        }