public static SortedList <long, BlockSliceInfo> GetBlockSlices(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, bool finalizedOnly) { var result = new SortedList <long, BlockSliceInfo>(); var path = GetBlockStoragePath(chainType, chainId, chainIndex); var blockStorages = storage.GetFiles(path, "*.header"); foreach (var blockStorage in blockStorages) { var sliceIndex = long.Parse(blockStorage.Name.Split('.')[0]); var blockInfo = new BlockSliceInfo(sliceIndex); var header = DiscStorage.GetHeader(storage, Path.Combine(path, sliceIndex.ToString())); if (header.Count > 0) { blockInfo.FirstBlockId = header.StartIndex; blockInfo.LastBlockId = header.EndIndex; } if (finalizedOnly) { if (blockInfo.Finalized) { result.Add(sliceIndex, blockInfo); } } else { result.Add(sliceIndex, blockInfo); } } return(result); }
void CheckBlockSlices() { var slices = GetBlockSlices(_storage, ChainType, ChainId, ChainIndex, false); BlockSliceInfo previous = null; foreach (var info in slices) { var slice = info.Value; if (!slice.Valid) { Log.Warn($"Removing all block slices, invalid slice found {slice.SliceIndex}.", this); RemoveAllBlockSlices(); return; } if (previous == null) { previous = slice; } else { if (!previous.Finalized || (previous.LastBlockId + 1) != slice.FirstBlockId) { Log.Warn($"Removing all block slices, invalid slice order found {slice.SliceIndex}.", this); RemoveAllBlockSlices(); return; } previous = info.Value; } // missing checksums, happend before, possibly through power outage if (slice.Finalized) { var result = DiscStorage.CheckDiscStorage(_storage, Path.Combine(_blocksPath, slice.SliceIndex.ToString())); if (result == DiscStorage.CheckDiscStorageResult.CheckumFailed) { Log.Warn($"Removing all block slices, invalid slice checksum found {slice.SliceIndex}.", this); RemoveAllBlockSlices(); return; } if (result == DiscStorage.CheckDiscStorageResult.DataCrcError) { Log.Warn($"Removing all block slices, slice data crc error found {slice.SliceIndex}.", this); RemoveAllBlockSlices(); return; } if (result == DiscStorage.CheckDiscStorageResult.MissingChecksum) { Log.Info($"Rebuilding checksum for block slice {slice.SliceIndex}.", this); DiscStorage.BuildChecksum(_storage, Path.Combine(_blocksPath, slice.SliceIndex.ToString())); } } } }
Task <BlockData> LoadBlock(long blockid) { BlockData result = null; try { if (blockid >= Protocol.GenesisBlockId) { var sliceIndex = BlockSliceInfo.GetSliceIndex(blockid); var blockStorage = _blocksStorage.Get(sliceIndex); if (blockStorage == null) { blockStorage = new BlockDiscStorage(_storage, ChainType, ChainId, ChainIndex, sliceIndex, true); if (blockStorage.Length > 0) { _blocksStorage.Add(sliceIndex, blockStorage); } } if (blockStorage.Length > 0) { var blockData = blockStorage.GetBlockData(blockid); if (blockData != null) { result = BlockData.Restore(blockData); _blockData.Add(blockid, result); } } } } catch (Exception ex) { Log.HandleException(ex, this); } return(Task.FromResult(result)); }
public async Task <BlockConsumeResult> StoreBlock(BlockData blockData) { var block = blockData.Block; lock (_lock) { if (!_active) { return(BlockConsumeResult.NotActive); } } await _consuming.WaitAsync(); var next = LastStoredBlockId + 1; if (block.BlockId > next) { _consuming.Release(); return(BlockConsumeResult.SyncRequired); } if (block.BlockId < next) { lock (_lock) { if (_blockSlices.Count > 0) { if (block.BlockId != (next - 1)) { _consuming.Release(); return(BlockConsumeResult.MissingBlock); } } } } if (block.BlockId < next) { _consuming.Release(); return(BlockConsumeResult.Ok); } if (LastBlock != null) { if (block.PreviousBlockHash != LastBlock.BlockHash) { _consuming.Release(); return(BlockConsumeResult.InvalidHash); } } var sliceIndex = BlockSliceInfo.GetSliceIndex(block.BlockId); if (_blockDiscStorage == null) { _blockDiscStorage = new BlockDiscStorage(_storage, ChainType, ChainId, ChainIndex, sliceIndex, false); } if (sliceIndex != _blockDiscStorage.SliceIndex) { _blockDiscStorage.Dispose(); DiscStorage.BuildChecksum(_storage, Path.Combine(_blocksPath, _blockDiscStorage.SliceIndex.ToString())); _blockDiscStorage = new BlockDiscStorage(_storage, ChainType, ChainId, ChainIndex, sliceIndex, false); } _blockDiscStorage.AddEntry(block.BlockId, blockData.ToByteArray()); _blockDiscStorage.Commit(); _blockData.Add(block.BlockId, blockData); lock (_lock) { if (_blockSlices.TryGetValue(sliceIndex, out var blockStorageInfo)) { blockStorageInfo.LastBlockId = block.BlockId; } else { blockStorageInfo = new BlockSliceInfo(sliceIndex) { FirstBlockId = block.BlockId, LastBlockId = block.BlockId }; _blockSlices.Add(sliceIndex, blockStorageInfo); } } if (!await History.Update(blockData)) { await History.Init(blockData); } lock (_lock) { LastBlock = block; LastBlockData = blockData; } _consuming.Release(); return(BlockConsumeResult.Ok); }