text: // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file. See the AUTHORS file for names of contributors.
  
  #ifndef STORAGE_LEVELDB_DB_LOG_READER_H_
  #define STORAGE_LEVELDB_DB_LOG_READER_H_
  
  #include <cstdint>
  
  #include "db/log_format.h"
  #include "leveldb/slice.h"
  #include "leveldb/status.h"
  
  namespace leveldb {
  
  class SequentialFile;
  
  namespace log {
  
  class Reader {
  public:
      // Interface for reporting errors.
      class Reporter {
      public:
          virtual ~Reporter();
  
          // Some corruption was detected.  "size" is the approximate number
          // of bytes dropped due to the corruption.
          virtual void Corruption(size_t bytes, const Status& status) = 0;
      };
  
      // Create a reader that will return log records from "*file".
      // "*file" must remain live while this Reader is in use.
      //
      // If "reporter" is non-null, it is notified whenever some data is
      // dropped due to a detected corruption.  "*reporter" must remain
      // live while this Reader is in use.
      //
      // If "checksum" is true, verify checksums if available.
      //
      // The Reader will start reading at the first record located at physical
      // position >= initial_offset within the file.
      Reader(SequentialFile* file, Reporter* reporter, bool checksum,
             uint64_t initial_offset);
  
      Reader(const Reader&) = delete;
      Reader& operator=(const Reader&) = delete;
  
      ~Reader();
  
      // Read the next record into *record.  Returns true if read
      // successfully, false if we hit end of the input.  May use
      // "*scratch" as temporary storage.  The contents filled in *record
      // will only be valid until the next mutating operation on this
      // reader or the next mutation to *scratch.
      bool ReadRecord(Slice* record, std::string* scratch);
  
      // Returns the physical offset of the last record returned by ReadRecord.
      //
      // Undefined before the first call to ReadRecord.
      uint64_t LastRecordOffset();
  
  private:
      // Extend record types with the following special values
      enum {
          kEof = kMaxRecordType + 1,
          // Returned whenever we find an invalid physical record.
          // Currently there are three situations in which this happens:
          // * The record has an invalid CRC (ReadPhysicalRecord reports a drop)
          // * The record is a 0-length record (No drop is reported)
          // * The record is below constructor's initial_offset (No drop is reported)
          kBadRecord = kMaxRecordType + 2
      };
  
      // Skips all blocks that are completely before "initial_offset_".
      //
      // Returns true on success. Handles reporting.
      bool SkipToInitialBlock();
  
      // Return type, or one of the preceding special values
      unsigned int ReadPhysicalRecord(Slice* result);
  
      // Reports dropped bytes to the reporter.
      // buffer_ must be updated to remove the dropped bytes prior to invocation.
      void ReportCorruption(uint64_t bytes, const char* reason);
      void ReportDrop(uint64_t bytes, const Status& reason);
  
      SequentialFile* const file_;
      Reporter* const reporter_;
      bool const checksum_;
      char* const backing_store_;
      Slice buffer_;
      bool eof_;  // Last Read() indicated EOF by returning < kBlockSize
  
      // Offset of the last record returned by ReadRecord.
      uint64_t last_record_offset_;
      // Offset of the first location past the end of buffer_.
      uint64_t end_of_buffer_offset_;
  
      // Offset at which to start looking for the first record to return
      uint64_t const initial_offset_;
  
      // True if we are resynchronizing after a seek (initial_offset_ > 0). In
      // particular, a run of kMiddleType and kLastType records can be silently
      // skipped in this mode
      bool resyncing_;
  };
  
  }  // namespace log
  }  // namespace leveldb
  
  #endif  // STORAGE_LEVELDB_DB_LOG_READER_H_
  