void ReadFilter(Slice filterHandleValue) { Slice v = filterHandleValue; BlockHandle filterHandle = new BlockHandle(); if (!filterHandle.DecodeFrom(ref v).IsOk) { return; } // We might want to unify with ReadBlock() if we start // requiring checksum verification in Table::Open. ReadOptions opt = ReadOptions.Default; BlockContents block; if (!FormatHelper.ReadBlock(rep_.File, opt, filterHandle, out block).IsOk) { return; } if (block.HeapAllocated) { rep_.FilterData = block.Data.Data; // Will need to delete later } rep_.Filter = new FilterBlockReader(rep_.Options.FilterPolicy, block.Data); }
private static Iterator BlockReader(object arg, ReadOptions options, Slice indexValue) { Table table = (Table)arg; Cache blockCache = table.rep_.Options.BlockCache; Block block = null; Cache.Handle cacheHandle = null; BlockHandle handle = new BlockHandle(); Slice input = indexValue; Status s = handle.DecodeFrom(ref input); // We intentionally allow extra stuff in index_value so that we // can add more features in the future. if (s.IsOk) { BlockContents contents; if (blockCache != null) { ByteArrayPointer cacheKeyBuffer = new ByteArrayPointer(16); Coding.EncodeFixed64(cacheKeyBuffer, table.rep_.CacheId); Coding.EncodeFixed64(cacheKeyBuffer + 8, handle.Offset); Slice key = new Slice(cacheKeyBuffer, cacheKeyBuffer.Length); cacheHandle = blockCache.Lookup(key); if (cacheHandle != null) { block = (Block)(blockCache.Value(cacheHandle)); } else { s = FormatHelper.ReadBlock(table.rep_.File, options, handle, out contents); if (s.IsOk) { block = new Block(contents); if (contents.Cachable && options.FillCache) { cacheHandle = blockCache.Insert(key, block, block.Size); } } } } else { s = FormatHelper.ReadBlock(table.rep_.File, options, handle, out contents); if (s.IsOk) { block = new Block(contents); } } } Iterator iter; if (block != null) { iter = block.NewIterator(table.rep_.Options.Comparator); if (cacheHandle != null) { iter.RegisterCleanup(ReleaseBlock, blockCache, cacheHandle); } } else { iter = Iterator.NewErrorIterator(s); } return iter; }
/// <summary> /// Given a key, return an approximate byte offset in the file where /// the data for that key begins (or would begin if the key were /// present in the file). The returned value is in terms of file /// bytes, and so includes effects like compression of the underlying data. /// E.g., the approximate offset of the last key in the table will /// be close to the file length. /// </summary> public UInt64 ApproximateOffsetOf(Slice key) { Iterator index_iter = rep_.IndexBlock.NewIterator(rep_.Options.Comparator); index_iter.Seek(key); UInt64 result; if (index_iter.Valid) { BlockHandle handle = new BlockHandle(); Slice input = index_iter.Value; Status s = handle.DecodeFrom(ref input); if (s.IsOk) { result = handle.Offset; } else { // Strange: we can't decode the block handle in the index block. // We'll just return the offset of the metaindex block, which is // close to the whole file size for this case. result = rep_.MetaindexHandle.Offset; } } else { // key is past the last key in the file. Approximate the offset // by returning the offset of the metaindex block (which is // right near the end of the file). result = rep_.MetaindexHandle.Offset; } return result; }
internal Status InternalGet( ReadOptions options, Slice k, object arg, HandleResultDelegate saver) { Status s = new Status(); Iterator iiter = rep_.IndexBlock.NewIterator(rep_.Options.Comparator); iiter.Seek(k); if (iiter.Valid) { Slice handle_value = iiter.Value; FilterBlockReader filter = rep_.Filter; BlockHandle handle = new BlockHandle(); if (filter != null && handle.DecodeFrom(ref handle_value).IsOk && !filter.KeyMayMatch(handle.Offset, k)) { // Not found } else { Slice tempHandle = iiter.Value; Iterator blockIter = BlockReader(this, options, iiter.Value); blockIter.Seek(k); if (blockIter.Valid) { saver(arg, blockIter.Key, blockIter.Value); } s = blockIter.Status; } } if (s.IsOk) { s = iiter.Status; } return s; }
public static Status ReadBlock(RandomAccessFile file, ReadOptions options, BlockHandle handle, out BlockContents result) { result.Data = new Slice(); result.Cachable = false; result.HeapAllocated = false; // Read the block contents as well as the type/crc footer. // See table_builder.cc for the code that built this structure. int n = (int)handle.Size; ByteArrayPointer buf = new ByteArrayPointer(n + kBlockTrailerSize); Slice contents; Status s = file.Read(handle.Offset, n + kBlockTrailerSize, out contents, buf); if (!s.IsOk) { return s; } if (contents.Size != n + kBlockTrailerSize) { return Status.Corruption("truncated block read"); } // Check the crc of the type and the block contents ByteArrayPointer data = contents.Data; // Pointer to where Read put the data if (options.VerifyChecksums) { // const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); //const uint32_t actual = crc32c::Value(data, n + 1); //if (actual != crc) { // delete[] buf; // s = Status::Corruption("block checksum mismatch"); // return s; //} throw new NotSupportedException("CRC is not supported yet"); } switch ((CompressionType)data[n]) { case CompressionType.kNoCompression: if (data != buf) { // File implementation gave us pointer to some other data. // Use it directly under the assumption that it will be live // while the file is open. result.Data = new Slice(data, n); result.HeapAllocated = false; result.Cachable = false; // Do not double-cache } else { result.Data = new Slice(buf, n); result.HeapAllocated = true; result.Cachable = true; } // Ok break; case CompressionType.kSnappyCompression: throw new NotSupportedException("snappy not supported"); // { // int ulength = 0; // if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { // delete[] buf; // return Status::Corruption("corrupted compressed block contents"); // } // char* ubuf = new char[ulength]; // if (!port::Snappy_Uncompress(data, n, ubuf)) { // delete[] buf; // delete[] ubuf; // return Status::Corruption("corrupted compressed block contents"); // } // delete[] buf; // result->data = Slice(ubuf, ulength); // result->heap_allocated = true; // result->cachable = true; // break; //} default: return Status.Corruption("bad block type"); } return Status.OK; }