| 187 | } |
| 188 | |
| 189 | unsigned int Reader::ReadPhysicalRecord(Slice* result) { |
| 190 | while (true) { |
| 191 | if (buffer_.size() < kHeaderSize) { |
| 192 | if (!eof_) { |
| 193 | // Last read was a full read, so this is a trailer to skip |
| 194 | buffer_.clear(); |
| 195 | Status status = file_->Read(kBlockSize, &buffer_, backing_store_); |
| 196 | end_of_buffer_offset_ += buffer_.size(); |
| 197 | if (!status.ok()) { |
| 198 | buffer_.clear(); |
| 199 | ReportDrop(kBlockSize, status); |
| 200 | eof_ = true; |
| 201 | return kEof; |
| 202 | } else if (buffer_.size() < kBlockSize) { |
| 203 | eof_ = true; |
| 204 | } |
| 205 | continue; |
| 206 | } else { |
| 207 | // Note that if buffer_ is non-empty, we have a truncated header at the |
| 208 | // end of the file, which can be caused by the writer crashing in the |
| 209 | // middle of writing the header. Instead of considering this an error, |
| 210 | // just report EOF. |
| 211 | buffer_.clear(); |
| 212 | return kEof; |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | // Parse the header |
| 217 | const char* header = buffer_.data(); |
| 218 | const uint32_t a = static_cast<uint32_t>(header[4]) & 0xff; |
| 219 | const uint32_t b = static_cast<uint32_t>(header[5]) & 0xff; |
| 220 | const unsigned int type = header[6]; |
| 221 | const uint32_t length = a | (b << 8); |
| 222 | if (kHeaderSize + length > buffer_.size()) { |
| 223 | size_t drop_size = buffer_.size(); |
| 224 | buffer_.clear(); |
| 225 | if (!eof_) { |
| 226 | ReportCorruption(drop_size, "bad record length"); |
| 227 | return kBadRecord; |
| 228 | } |
| 229 | // If the end of the file has been reached without reading |length| bytes |
| 230 | // of payload, assume the writer died in the middle of writing the record. |
| 231 | // Don't report a corruption. |
| 232 | return kEof; |
| 233 | } |
| 234 | |
| 235 | if (type == kZeroType && length == 0) { |
| 236 | // Skip zero length record without reporting any drops since |
| 237 | // such records are produced by the mmap based writing code in |
| 238 | // env_posix.cc that preallocates file regions. |
| 239 | buffer_.clear(); |
| 240 | return kBadRecord; |
| 241 | } |
| 242 | |
| 243 | // Check crc |
| 244 | if (checksum_) { |
| 245 | uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); |
| 246 | uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); |