public ArraySegment <byte> GetBlock(Hash hash) { // Cache { var result = _blocksManager.Get(hash); if (result != null) { return(result.Value); } } // Share { ArraySegment <byte>?result = null; string path = null; lock (_lockObject) { var shareInfo = _contentInfoManager.GetShareInfo(hash); if (shareInfo != null) { var buffer = _bufferManager.TakeBuffer(shareInfo.BlockLength); try { int length; try { using (var stream = new UnbufferedFileStream(shareInfo.Path, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None, _bufferManager)) { stream.Seek((long)shareInfo.GetIndex(hash) * shareInfo.BlockLength, SeekOrigin.Begin); length = (int)Math.Min(stream.Length - stream.Position, shareInfo.BlockLength); stream.Read(buffer, 0, length); } } catch (ArgumentOutOfRangeException) { throw new BlockNotFoundException(); } catch (IOException) { throw new BlockNotFoundException(); } result = new ArraySegment <byte>(buffer, 0, length); path = shareInfo.Path; } catch (Exception) { _bufferManager.ReturnBuffer(buffer); throw; } } } if (result != null) { if (hash.Algorithm == HashAlgorithm.Sha256 && Unsafe.Equals(Sha256.Compute(result.Value), hash.Value)) { return(result.Value); } else { _bufferManager.ReturnBuffer(result.Value.Array); result = null; this.RemoveContent(path); } } } throw new BlockNotFoundException(); }
public bool TryGetBlock(OmniHash hash, [NotNullWhen(true)] out IMemoryOwner <byte>?memoryOwner) { if (!EnumHelper.IsValid(hash.AlgorithmType)) { throw new ArgumentException($"Incorrect HashAlgorithmType: {hash.AlgorithmType}"); } // Cache { var result = _blockStorage.TryGet(hash, out memoryOwner); if (result) { return(true); } } bool success = false; string?path = null; // Share try { lock (_lockObject) { var sharedBlocksInfo = _contentMetadataStorage.GetSharedBlocksInfo(hash); if (sharedBlocksInfo != null) { ulong position = (ulong)sharedBlocksInfo.GetIndex(hash) * sharedBlocksInfo.BlockLength; uint length = (uint)Math.Min(sharedBlocksInfo.Length - position, sharedBlocksInfo.BlockLength); memoryOwner = _bufferPool.Rent((int)length); try { using (var stream = new UnbufferedFileStream(sharedBlocksInfo.Path, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None, _bufferPool)) { stream.Seek((long)position, SeekOrigin.Begin); stream.Read(memoryOwner.Memory.Span); } path = sharedBlocksInfo.Path; } catch (Exception e) { _logger.Debug(e); return(false); } } } if (memoryOwner == null) { return(false); } if (hash.AlgorithmType == OmniHashAlgorithmType.Sha2_256 && BytesOperations.SequenceEqual(Sha2_256.ComputeHash(memoryOwner.Memory.Span), hash.Value.Span)) { success = true; return(true); } else { _logger.Warn("Broken block."); return(false); } } finally { if (!success) { if (memoryOwner != null) { memoryOwner.Dispose(); memoryOwner = null; } if (path != null) { this.RemoveContent(path); } } } }