1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 //
6 #pragma once
7 
8 #include <memory>
9 
10 #include "db/blob/blob_log_format.h"
11 #include "rocksdb/slice.h"
12 
13 #define MAX_HEADER_SIZE(a, b, c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
14 
15 namespace ROCKSDB_NAMESPACE {
16 
17 class RandomAccessFileReader;
18 class Env;
19 class Statistics;
20 class Status;
21 class SystemClock;
22 
23 /**
24  * BlobLogSequentialReader is a general purpose log stream reader
25  * implementation. The actual job of reading from the device is implemented by
26  * the RandomAccessFileReader interface.
27  *
28  * Please see BlobLogWriter for details on the file and record layout.
29  */
30 
31 class BlobLogSequentialReader {
32  public:
33   enum ReadLevel {
34     kReadHeader,
35     kReadHeaderKey,
36     kReadHeaderKeyBlob,
37   };
38 
39   // Create a reader that will return log records from "*file_reader".
40   BlobLogSequentialReader(std::unique_ptr<RandomAccessFileReader>&& file_reader,
41                           SystemClock* clock, Statistics* statistics);
42 
43   // No copying allowed
44   BlobLogSequentialReader(const BlobLogSequentialReader&) = delete;
45   BlobLogSequentialReader& operator=(const BlobLogSequentialReader&) = delete;
46 
47   ~BlobLogSequentialReader();
48 
49   Status ReadHeader(BlobLogHeader* header);
50 
51   // Read the next record into *record.  Returns true if read
52   // successfully, false if we hit end of the input. The contents filled in
53   // *record will only be valid until the next mutating operation on this
54   // reader.
55   // If blob_offset is non-null, return offset of the blob through it.
56   Status ReadRecord(BlobLogRecord* record, ReadLevel level = kReadHeader,
57                     uint64_t* blob_offset = nullptr);
58 
59   Status ReadFooter(BlobLogFooter* footer);
60 
ResetNextByte()61   void ResetNextByte() { next_byte_ = 0; }
62 
GetNextByte()63   uint64_t GetNextByte() const { return next_byte_; }
64 
65  private:
66   Status ReadSlice(uint64_t size, Slice* slice, char* buf);
67 
68   const std::unique_ptr<RandomAccessFileReader> file_;
69   SystemClock* clock_;
70 
71   Statistics* statistics_;
72 
73   Slice buffer_;
74   char header_buf_[MAX_HEADER_SIZE(BlobLogHeader::kSize, BlobLogFooter::kSize,
75                                    BlobLogRecord::kHeaderSize)];
76 
77   // which byte to read next
78   uint64_t next_byte_;
79 };
80 
81 }  // namespace ROCKSDB_NAMESPACE
82 
83 #undef MAX_HEADER_SIZE