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())); } } }
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())); } } }
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())); } }
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(); } } }
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())); } }
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(); }