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).
7 #include "db/blob/blob_log_sequential_reader.h"
9 #include "file/random_access_file_reader.h"
10 #include "monitoring/statistics.h"
11 #include "util/stop_watch.h"
13 namespace ROCKSDB_NAMESPACE
{
15 BlobLogSequentialReader::BlobLogSequentialReader(
16 std::unique_ptr
<RandomAccessFileReader
>&& file_reader
, Env
* env
,
17 Statistics
* statistics
)
18 : file_(std::move(file_reader
)),
20 statistics_(statistics
),
23 BlobLogSequentialReader::~BlobLogSequentialReader() = default;
25 Status
BlobLogSequentialReader::ReadSlice(uint64_t size
, Slice
* slice
,
30 StopWatch
read_sw(env_
, statistics_
, BLOB_DB_BLOB_FILE_READ_MICROS
);
31 Status s
= file_
->Read(IOOptions(), next_byte_
, static_cast<size_t>(size
),
37 RecordTick(statistics_
, BLOB_DB_BLOB_FILE_BYTES_READ
, slice
->size());
38 if (slice
->size() != size
) {
39 return Status::Corruption("EOF reached while reading record");
44 Status
BlobLogSequentialReader::ReadHeader(BlobLogHeader
* header
) {
46 assert(next_byte_
== 0);
48 static_assert(BlobLogHeader::kSize
<= sizeof(header_buf_
),
49 "Buffer is smaller than BlobLogHeader::kSize");
51 Status s
= ReadSlice(BlobLogHeader::kSize
, &buffer_
, header_buf_
);
56 if (buffer_
.size() != BlobLogHeader::kSize
) {
57 return Status::Corruption("EOF reached before file header");
60 return header
->DecodeFrom(buffer_
);
63 Status
BlobLogSequentialReader::ReadRecord(BlobLogRecord
* record
,
65 uint64_t* blob_offset
) {
67 static_assert(BlobLogRecord::kHeaderSize
<= sizeof(header_buf_
),
68 "Buffer is smaller than BlobLogRecord::kHeaderSize");
70 Status s
= ReadSlice(BlobLogRecord::kHeaderSize
, &buffer_
, header_buf_
);
74 if (buffer_
.size() != BlobLogRecord::kHeaderSize
) {
75 return Status::Corruption("EOF reached before record header");
78 s
= record
->DecodeHeaderFrom(buffer_
);
83 uint64_t kb_size
= record
->key_size
+ record
->value_size
;
84 if (blob_offset
!= nullptr) {
85 *blob_offset
= next_byte_
+ record
->key_size
;
90 next_byte_
+= kb_size
;
94 record
->key_buf
.reset(new char[record
->key_size
]);
95 s
= ReadSlice(record
->key_size
, &record
->key
, record
->key_buf
.get());
96 next_byte_
+= record
->value_size
;
99 case kReadHeaderKeyBlob
:
100 record
->key_buf
.reset(new char[record
->key_size
]);
101 s
= ReadSlice(record
->key_size
, &record
->key
, record
->key_buf
.get());
103 record
->value_buf
.reset(new char[record
->value_size
]);
104 s
= ReadSlice(record
->value_size
, &record
->value
,
105 record
->value_buf
.get());
108 s
= record
->CheckBlobCRC();
115 Status
BlobLogSequentialReader::ReadFooter(BlobLogFooter
* footer
) {
117 static_assert(BlobLogFooter::kSize
<= sizeof(header_buf_
),
118 "Buffer is smaller than BlobLogFooter::kSize");
120 Status s
= ReadSlice(BlobLogFooter::kSize
, &buffer_
, header_buf_
);
125 if (buffer_
.size() != BlobLogFooter::kSize
) {
126 return Status::Corruption("EOF reached before file footer");
129 return footer
->DecodeFrom(buffer_
);
132 } // namespace ROCKSDB_NAMESPACE