| 62 | } |
| 63 | |
| 64 | Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, |
| 65 | const BlockHandle& handle, BlockContents* result) { |
| 66 | result->data = Slice(); |
| 67 | result->cachable = false; |
| 68 | result->heap_allocated = false; |
| 69 | |
| 70 | // Read the block contents as well as the type/crc footer. |
| 71 | // See table_builder.cc for the code that built this structure. |
| 72 | size_t n = static_cast<size_t>(handle.size()); |
| 73 | char* buf = new char[n + kBlockTrailerSize]; |
| 74 | Slice contents; |
| 75 | Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); |
| 76 | if (!s.ok()) { |
| 77 | delete[] buf; |
| 78 | return s; |
| 79 | } |
| 80 | if (contents.size() != n + kBlockTrailerSize) { |
| 81 | delete[] buf; |
| 82 | return Status::Corruption("truncated block read", file->GetName()); |
| 83 | } |
| 84 | |
| 85 | // Check the crc of the type and the block contents |
| 86 | const char* data = contents.data(); // Pointer to where Read put the data |
| 87 | if (options.verify_checksums) { |
| 88 | const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); |
| 89 | const uint32_t actual = crc32c::Value(data, n + 1); |
| 90 | if (actual != crc) { |
| 91 | delete[] buf; |
| 92 | s = Status::Corruption("block checksum mismatch", file->GetName()); |
| 93 | return s; |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | switch (data[n]) { |
| 98 | case kNoCompression: |
| 99 | if (data != buf) { |
| 100 | // File implementation gave us pointer to some other data. |
| 101 | // Use it directly under the assumption that it will be live |
| 102 | // while the file is open. |
| 103 | delete[] buf; |
| 104 | result->data = Slice(data, n); |
| 105 | result->heap_allocated = false; |
| 106 | result->cachable = false; // Do not double-cache |
| 107 | } else { |
| 108 | result->data = Slice(buf, n); |
| 109 | result->heap_allocated = true; |
| 110 | result->cachable = true; |
| 111 | } |
| 112 | |
| 113 | // Ok |
| 114 | break; |
| 115 | case kSnappyCompression: { |
| 116 | size_t ulength = 0; |
| 117 | if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { |
| 118 | delete[] buf; |
| 119 | return Status::Corruption("corrupted compressed block contents", file->GetName()); |
| 120 | } |
| 121 | char* ubuf = new char[ulength]; |
no test coverage detected