/// <summary> /// Attempt to open the table that is stored in bytes [0..file_size) /// of "file", and read the metadata entries necessary to allow /// retrieving data from the table. /// /// If successful, returns ok and sets "*table" to the newly opened /// table. The client should delete "*table" when no longer needed. /// If there was an error while initializing the table, sets "*table" /// to NULL and returns a non-ok status. Does not take ownership of /// "*source", but the client must ensure that "source" remains live /// for the duration of the returned table's lifetime. /// /// *file must remain live while this Table is in use. /// </summary> public static Status Open(Options options, RandomAccessFile file, UInt64 size, out Table table) { table = null; if (size < Footer.kEncodedLength) { return Status.InvalidArgument("file is too short to be an sstable"); } ByteArrayPointer footerSpace = new ByteArrayPointer(Footer.kEncodedLength); Slice footerInput; Status s = file.Read(size - Footer.kEncodedLength, Footer.kEncodedLength, out footerInput, footerSpace); if (!s.IsOk) return s; Footer footer = new Footer(); s = footer.DecodeFrom(ref footerInput); if (!s.IsOk) return s; // Read the index block BlockContents contents; Block indexBlock = null; if (s.IsOk) { s = FormatHelper.ReadBlock(file, ReadOptions.Default, footer.IndexHandle, out contents); if (s.IsOk) { indexBlock = new Block(contents); } } if (s.IsOk) { // We've successfully read the footer and the index block: we're // ready to serve requests. Rep rep = new Rep(); rep.Options = options; rep.File = file; rep.MetaindexHandle = footer.MetaindexHandle; rep.IndexBlock = indexBlock; rep.CacheId = (options.BlockCache != null ? options.BlockCache.NewId() : 0); rep.FilterData = ByteArrayPointer.Null; rep.Filter = null; table = new Table(rep); table.ReadMeta(footer); } 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; }