| 78 | } |
| 79 | |
| 80 | Status ReadBlock(RandomAccessFile* file, const BlockHandle& handle, |
| 81 | BlockContents* result) { |
| 82 | result->data = StringPiece(); |
| 83 | result->cachable = false; |
| 84 | result->heap_allocated = false; |
| 85 | |
| 86 | // Read the block contents as well as the type/crc footer. |
| 87 | // See table_builder.cc for the code that built this structure. |
| 88 | size_t n = static_cast<size_t>(handle.size()); |
| 89 | |
| 90 | if (kBlockTrailerSize > std::numeric_limits<size_t>::max() - n) { |
| 91 | return errors::DataLoss("handle.size() too big"); |
| 92 | } |
| 93 | |
| 94 | char* buf = new char[n + kBlockTrailerSize]; |
| 95 | StringPiece contents; |
| 96 | Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); |
| 97 | if (!s.ok()) { |
| 98 | delete[] buf; |
| 99 | return s; |
| 100 | } |
| 101 | if (contents.size() != n + kBlockTrailerSize) { |
| 102 | delete[] buf; |
| 103 | return errors::DataLoss("truncated block read"); |
| 104 | } |
| 105 | |
| 106 | // Check the crc of the type and the block contents |
| 107 | const char* data = contents.data(); // Pointer to where Read put the data |
| 108 | // This checksum verification is optional. We leave it on for now |
| 109 | const bool verify_checksum = true; |
| 110 | if (verify_checksum) { |
| 111 | const uint32 crc = crc32c::Unmask(core::DecodeFixed32(data + n + 1)); |
| 112 | const uint32 actual = crc32c::Value(data, n + 1); |
| 113 | if (actual != crc) { |
| 114 | delete[] buf; |
| 115 | s = errors::DataLoss("block checksum mismatch"); |
| 116 | return s; |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | switch (data[n]) { |
| 121 | case kNoCompression: |
| 122 | if (data != buf) { |
| 123 | // File implementation gave us pointer to some other data. |
| 124 | // Use it directly under the assumption that it will be live |
| 125 | // while the file is open. |
| 126 | delete[] buf; |
| 127 | result->data = StringPiece(data, n); |
| 128 | result->heap_allocated = false; |
| 129 | result->cachable = false; // Do not double-cache |
| 130 | } else { |
| 131 | result->data = StringPiece(buf, n); |
| 132 | result->heap_allocated = true; |
| 133 | result->cachable = true; |
| 134 | } |
| 135 | |
| 136 | // Ok |
| 137 | break; |
no test coverage detected