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