public static SortedList <long, TransactionSliceInfo> GetTransactionSlices(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, bool finalizedOnly) { var chainPath = GetTransactionStoragePath(chainType, chainId, chainIndex); var discSlices = storage.GetFiles(chainPath, "*.header"); var result = new SortedList <long, TransactionSliceInfo>(); foreach (var slice in discSlices) { var sliceId = int.Parse(slice.Name.Split('.')[0]); var info = DiscStorage.GetHeader(storage, Path.Combine(chainPath, sliceId.ToString())); var userData = new Unpacker(info.UserData); var firstBlockId = Protocol.InvalidBlockId; var blockId = Protocol.InvalidBlockId; var split = false; if (userData.UnpackBool()) { firstBlockId = userData.UnpackLong(); blockId = userData.UnpackLong(); split = userData.UnpackBool(); } if (!finalizedOnly || split) { result.Add(sliceId, new TransactionSliceInfo(sliceId, firstBlockId, blockId, split, info.Count, info.StartIndex, info.EndIndex)); } } return(result); }
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())); } } } }
public byte[] GetTransactionItemData(long transactionId) { var sliceIndex = TransactionSliceInfo.GetSliceIndex(transactionId); var inCurrentSlice = sliceIndex == _currentSliceId; if (sliceIndex >= 0) { DiscStorage storage = null; if (!inCurrentSlice) { TransactionSliceInfo slice = null; lock (_lock) slice = _slices[(int)sliceIndex]; lock (_lock) { _readonlyTransactionSlices.TryGetValue(slice.SliceId, out storage); } if (storage == null) { storage = GetTransactionStorage(slice.SliceId); lock (_lock) { _readonlyTransactionSlices[slice.SliceId] = storage; } } } else { lock (_lock) { storage = _transactionSlice; } } if (storage != null) { if (transactionId >= 0) { return(storage.GetBlockData(transactionId)); } } } return(null); }
void Split(long blockId) { lock (_lock) { if (_transactionSlice.Length <= 0) { return; } if (_currentFirsBlockId == Protocol.InvalidBlockId) { _currentFirsBlockId = blockId; } _currentBlockId = blockId; _slices.Add(_currentSliceId, new TransactionSliceInfo(_currentSliceId, _currentFirsBlockId, _currentBlockId, true, _transactionSlice.Length, _transactionSlice.StartIndex, _transactionSlice.EndIndex)); } _transactionSlice.Close(); DiscStorage.BuildChecksum(_storage, Path.Combine(TransactionsPath, _currentSliceId.ToString())); lock (_lock) { _currentSliceId++; _currentBlockId = Protocol.InvalidBlockId; _currentFirsBlockId = Protocol.InvalidBlockId; _transactionSlice = new TransactionDiscStorage(_storage, Path.Combine(TransactionsPath, _currentSliceId.ToString()), _blockSize, _storageFlags) { FirstBlockId = _currentFirsBlockId, LastBlockId = _currentBlockId, Split = false }; } Save(); }
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); }