1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 5 #ifndef STORAGE_LEVELDB_DB_LOG_READER_H_
6 #define STORAGE_LEVELDB_DB_LOG_READER_H_
7 8 #include <stdint.h>
9 10 #include "db/log_format.h"
11 #include "leveldb/slice.h"
12 #include "leveldb/status.h"
13 14 namespace leveldb {
15 16 class SequentialFile;
17 18 namespace log {
19 20 class Reader {
21 public:
22 // Interface for reporting errors.
23 class Reporter {
24 public:
25 virtual ~Reporter();
26 27 // Some corruption was detected. "size" is the approximate number
28 // of bytes dropped due to the corruption.
29 virtual void Corruption(size_t bytes, const Status& status) = 0;
30 };
31 32 // Create a reader that will return log records from "*file".
33 // "*file" must remain live while this Reader is in use.
34 //
35 // If "reporter" is non-null, it is notified whenever some data is
36 // dropped due to a detected corruption. "*reporter" must remain
37 // live while this Reader is in use.
38 //
39 // If "checksum" is true, verify checksums if available.
40 //
41 // The Reader will start reading at the first record located at physical
42 // position >= initial_offset within the file.
43 Reader(SequentialFile* file, Reporter* reporter, bool checksum,
44 uint64_t initial_offset);
45 46 Reader(const Reader&) = delete;
47 Reader& operator=(const Reader&) = delete;
48 49 ~Reader();
50 51 // Read the next record into *record. Returns true if read
52 // successfully, false if we hit end of the input. May use
53 // "*scratch" as temporary storage. The contents filled in *record
54 // will only be valid until the next mutating operation on this
55 // reader or the next mutation to *scratch.
56 bool ReadRecord(Slice* record, std::string* scratch);
57 58 // Returns the physical offset of the last record returned by ReadRecord.
59 //
60 // Undefined before the first call to ReadRecord.
61 uint64_t LastRecordOffset();
62 63 private:
64 // Extend record types with the following special values
65 enum {
66 kEof = kMaxRecordType + 1,
67 // Returned whenever we find an invalid physical record.
68 // Currently there are three situations in which this happens:
69 // * The record has an invalid CRC (ReadPhysicalRecord reports a drop)
70 // * The record is a 0-length record (No drop is reported)
71 // * The record is below constructor's initial_offset (No drop is reported)
72 kBadRecord = kMaxRecordType + 2
73 };
74 75 // Skips all blocks that are completely before "initial_offset_".
76 //
77 // Returns true on success. Handles reporting.
78 bool SkipToInitialBlock();
79 80 // Return type, or one of the preceding special values
81 unsigned int ReadPhysicalRecord(Slice* result);
82 83 // Reports dropped bytes to the reporter.
84 // buffer_ must be updated to remove the dropped bytes prior to invocation.
85 void ReportCorruption(uint64_t bytes, const char* reason);
86 void ReportDrop(uint64_t bytes, const Status& reason);
87 88 SequentialFile* const file_;
89 Reporter* const reporter_;
90 bool const checksum_;
91 char* const backing_store_;
92 Slice buffer_;
93 bool eof_; // Last Read() indicated EOF by returning < kBlockSize
94 95 // Offset of the last record returned by ReadRecord.
96 uint64_t last_record_offset_;
97 // Offset of the first location past the end of buffer_.
98 uint64_t end_of_buffer_offset_;
99 100 // Offset at which to start looking for the first record to return
101 uint64_t const initial_offset_;
102 103 // True if we are resynchronizing after a seek (initial_offset_ > 0). In
104 // particular, a run of kMiddleType and kLastType records can be silently
105 // skipped in this mode
106 bool resyncing_;
107 };
108 109 } // namespace log
110 } // namespace leveldb
111 112 #endif // STORAGE_LEVELDB_DB_LOG_READER_H_
113