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
14namespace leveldb {
15
16class SequentialFile;
17
18namespace log {
19
20class 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();
47
48  // Read the next record into *record.  Returns true if read
49  // successfully, false if we hit end of the input.  May use
50  // "*scratch" as temporary storage.  The contents filled in *record
51  // will only be valid until the next mutating operation on this
52  // reader or the next mutation to *scratch.
53  bool ReadRecord(Slice* record, std::string* scratch);
54
55  // Returns the physical offset of the last record returned by ReadRecord.
56  //
57  // Undefined before the first call to ReadRecord.
58  uint64_t LastRecordOffset();
59
60 private:
61  SequentialFile* const file_;
62  Reporter* const reporter_;
63  bool const checksum_;
64  char* const backing_store_;
65  Slice buffer_;
66  bool eof_;   // Last Read() indicated EOF by returning < kBlockSize
67
68  // Offset of the last record returned by ReadRecord.
69  uint64_t last_record_offset_;
70  // Offset of the first location past the end of buffer_.
71  uint64_t end_of_buffer_offset_;
72
73  // Offset at which to start looking for the first record to return
74  uint64_t const initial_offset_;
75
76  // Extend record types with the following special values
77  enum {
78    kEof = kMaxRecordType + 1,
79    // Returned whenever we find an invalid physical record.
80    // Currently there are three situations in which this happens:
81    // * The record has an invalid CRC (ReadPhysicalRecord reports a drop)
82    // * The record is a 0-length record (No drop is reported)
83    // * The record is below constructor's initial_offset (No drop is reported)
84    kBadRecord = kMaxRecordType + 2
85  };
86
87  // Skips all blocks that are completely before "initial_offset_".
88  //
89  // Returns true on success. Handles reporting.
90  bool SkipToInitialBlock();
91
92  // Return type, or one of the preceding special values
93  unsigned int ReadPhysicalRecord(Slice* result);
94
95  // Reports dropped bytes to the reporter.
96  // buffer_ must be updated to remove the dropped bytes prior to invocation.
97  void ReportCorruption(size_t bytes, const char* reason);
98  void ReportDrop(size_t bytes, const Status& reason);
99
100  // No copying allowed
101  Reader(const Reader&);
102  void operator=(const Reader&);
103};
104
105}  // namespace log
106}  // namespace leveldb
107
108#endif  // STORAGE_LEVELDB_DB_LOG_READER_H_
109