Example #1
0
        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);
        }
Example #2
0
        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;
        }
Example #3
0
        /// <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;
        }
Example #4
0
        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;
        }
Example #5
0
        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;
        }