| 54 | } |
| 55 | |
| 56 | bool Reader::ReadRecord(Slice* record, std::string* scratch) { |
| 57 | if (last_record_offset_ < initial_offset_) { |
| 58 | if (!SkipToInitialBlock()) { |
| 59 | return false; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | scratch->clear(); |
| 64 | record->clear(); |
| 65 | bool in_fragmented_record = false; |
| 66 | // Record offset of the logical record that we're reading |
| 67 | // 0 is a dummy value to make compilers happy |
| 68 | uint64_t prospective_record_offset = 0; |
| 69 | |
| 70 | Slice fragment; |
| 71 | while (true) { |
| 72 | const unsigned int record_type = ReadPhysicalRecord(&fragment); |
| 73 | |
| 74 | // ReadPhysicalRecord may have only had an empty trailer remaining in its |
| 75 | // internal buffer. Calculate the offset of the next physical record now |
| 76 | // that it has returned, properly accounting for its header size. |
| 77 | uint64_t physical_record_offset = |
| 78 | end_of_buffer_offset_ - buffer_.size() - kHeaderSize - fragment.size(); |
| 79 | |
| 80 | if (resyncing_) { |
| 81 | if (record_type == kMiddleType) { |
| 82 | continue; |
| 83 | } else if (record_type == kLastType) { |
| 84 | resyncing_ = false; |
| 85 | continue; |
| 86 | } else { |
| 87 | resyncing_ = false; |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | switch (record_type) { |
| 92 | case kFullType: |
| 93 | if (in_fragmented_record) { |
| 94 | // Handle bug in earlier versions of log::Writer where |
| 95 | // it could emit an empty kFirstType record at the tail end |
| 96 | // of a block followed by a kFullType or kFirstType record |
| 97 | // at the beginning of the next block. |
| 98 | if (!scratch->empty()) { |
| 99 | ReportCorruption(scratch->size(), "partial record without end(1)"); |
| 100 | } |
| 101 | } |
| 102 | prospective_record_offset = physical_record_offset; |
| 103 | scratch->clear(); |
| 104 | *record = fragment; |
| 105 | last_record_offset_ = prospective_record_offset; |
| 106 | return true; |
| 107 | |
| 108 | case kFirstType: |
| 109 | if (in_fragmented_record) { |
| 110 | // Handle bug in earlier versions of log::Writer where |
| 111 | // it could emit an empty kFirstType record at the tail end |
| 112 | // of a block followed by a kFullType or kFirstType record |
| 113 | // at the beginning of the next block. |