public static T TryGet <T>(this DB db, ReadOptions options, DataEntryPrefix prefix, ISerializable key, Func <Slice, T> resultSelector) where T : class { Slice slice; if (!db.TryGet(options, SliceBuilder.Begin(prefix).Add(key), out slice)) { return(null); } return(resultSelector(slice)); }
public static T TryGet <T>(this DB db, ReadOptions options, DataEntryPrefix prefix, ISerializable key) where T : class, ISerializable, new() { Slice slice; if (!db.TryGet(options, SliceBuilder.Begin(prefix).Add(key), out slice)) { return(null); } return(slice.ToArray().AsSerializable <T>()); }
public TValue GetOrAdd(TKey key, Func <TValue> factory) { if (dictionary.ContainsKey(key)) { return(dictionary[key]); } TValue value; if (deleted.Contains(key)) { value = factory(); deleted.Remove(key); } else { value = db.TryGet <TValue>(ReadOptions.Default, prefix, key); if (value == null) { value = factory(); } } dictionary.Add(key, value); return(value); }
public LevelDBBlockchain(string path) { 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.CFG_Version), out value) && Version.TryParse(value.ToString(), out version) && version >= Version.Parse("0.6.6043.32131")) { 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_Header), (k, v) => Header.FromTrimmedData(v.ToArray(), sizeof(long))).OrderBy(p => p.Height).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_Header).Add(hash)).ToArray(), sizeof(long)); header_index.Insert((int)stored_header_count, hash); hash = header.PrevBlock; } } } 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.CFG_Version), GetType().GetTypeInfo().Assembly.GetName().Version.ToString()); } thread_persistence = new Thread(PersistBlocks); thread_persistence.Name = "LevelDBBlockchain.PersistBlocks"; thread_persistence.Start(); }
public override bool ContainsTransaction(UInt256 hash) { if (base.ContainsTransaction(hash)) { return(true); } Slice value; return(db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.DATA_Transaction).Add(hash), out value)); }
protected override TValue TryGetInternal(TKey key) { return(db.TryGet <TValue>(ReadOptions.Default, prefix, key)); }
public LevelDBBlockchain(string path) { 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.CFG_Version), out value) && Version.TryParse(value.ToString(), out version) && version >= Version.Parse("0.5")) { ReadOptions options = new ReadOptions { FillCache = false }; value = db.Get(options, SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock)); this.current_block_hash = new UInt256(value.ToArray().Take(32).ToArray()); this.current_block_height = BitConverter.ToUInt32(value.ToArray(), 32); foreach (Block header in db.Find(options, SliceBuilder.Begin(DataEntryPrefix.DATA_HeaderList), (k, v) => { using (MemoryStream ms = new MemoryStream(v.ToArray(), false)) using (BinaryReader r = new BinaryReader(ms)) { return(new { Index = BitConverter.ToUInt32(k.ToArray(), 1), Headers = r.ReadSerializableArray <Block>() }); } }).OrderBy(p => p.Index).SelectMany(p => p.Headers).ToArray()) { if (header.Hash != GenesisBlock.Hash) { header_chain.Add(header.Hash, header, header.PrevBlock); header_index.Add(header.Hash); } stored_header_count++; } if (stored_header_count == 0) { Dictionary <UInt256, Block> table = db.Find(options, SliceBuilder.Begin(DataEntryPrefix.DATA_Block), (k, v) => Block.FromTrimmedData(v.ToArray(), sizeof(long))).ToDictionary(p => p.PrevBlock); for (UInt256 hash = GenesisBlock.Hash; hash != current_block_hash;) { Block header = table[hash]; header_chain.Add(header.Hash, header, header.PrevBlock); header_index.Add(header.Hash); hash = header.Hash; } } else if (current_block_height >= stored_header_count) { List <Block> list = new List <Block>(); for (UInt256 hash = current_block_hash; hash != header_index[(int)stored_header_count - 1];) { Block header = Block.FromTrimmedData(db.Get(options, SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(hash)).ToArray(), sizeof(long)); list.Add(header); header_index.Insert((int)stored_header_count, hash); hash = header.PrevBlock; } for (int i = list.Count - 1; i >= 0; i--) { header_chain.Add(list[i].Hash, list[i], list[i].PrevBlock); } } this.current_header_hash = header_index[header_index.Count - 1]; } 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.CFG_Version), Assembly.GetExecutingAssembly().GetName().Version.ToString()); } thread_persistence = new Thread(PersistBlocks); thread_persistence.Name = "LevelDBBlockchain.PersistBlocks"; thread_persistence.Start(); AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; }