/// <summary> /// Calls <paramref name="onBlock"/> on the contents of the block at /// address <paramref name="address"/>. /// </summary> /// <remarks> /// If the block has pending work (such as validating contents, or /// writing them out), that pending work is performed before the call. /// /// Fully thread-safe. /// /// Function <paramref name="onBlock"/> should endeavour to return /// quickly, as the provided span is pinned, for all intents and /// purposes, until it does. /// </remarks> /// <returns> /// True of the block could be extracted and passed to <paramref name="onBlock"/>. /// This may fail if the file is being unpinned, or if the block does not /// have the expected realm/hash, or if it is corrupted, or if the address has /// somehow expired. /// /// The out argument contains the return value of <paramref name="onBlock"/>. /// </returns> /// <see cref="BlockFile.TryWithBlockAtAddress"/> public bool TryWithBlockAtAddress <T>( BlockAddress address, uint realm, Hash hash, WithSpan.ReadOnlyReturns <T> onBlock, out T result) { if (address.IsNone()) { result = default; return(false); } // BlockAddress.File() is 1..1023 but our array is zero-indexed. var fid = address.File() - 1; var file = _readFiles[fid]; if (file == null) { result = default; return(false); } return(file.TryWithBlockAtAddress( address, realm, hash, onBlock, out result)); }
/// <summary> /// Calls <paramref name="reader"/> on the block represented by the /// realm and hash. /// </summary> /// <exception cref="MissingBlockException"> /// If the block is not present in the scratch space, or was corrupted /// and failed a checksum check. /// </exception> public T Read <T>(uint realm, Hash hash, WithSpan.ReadOnlyReturns <T> reader) { var addr = _index.Get(realm, hash); try { if (_wheel.TryWithBlockAtAddress(addr, realm, hash, reader, out var result)) { return(result); } } // 'MissingBlock' and 'ChecksumFailed', if they happen inside, should // converted to a 'MissingBlock' and ensure that the broken block is // removed. catch (MissingBlockException) {} catch (CheckSumFailedException) {} _index.Remove(realm, hash, addr); throw new MissingBlockException(realm, hash); }