// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. An additional grant // of patent rights can be found in the PATENTS file in the same directory. // // Log format information shared by reader and writer. #pragma once #ifndef ROCKSDB_LITE #include #include #include #include #include #include "rocksdb/options.h" #include "rocksdb/status.h" #include "rocksdb/types.h" namespace rocksdb { namespace blob_db { class BlobFile; class BlobDBImpl; enum RecordType : uint8_t { // Zero is reserved for preallocated files kFullType = 0, // For fragments kFirstType = 1, kMiddleType = 2, kLastType = 3, kMaxRecordType = kLastType }; enum RecordSubType : uint8_t { kRegularType = 0, kTTLType = 1, kTimestampType = 2, }; extern const uint32_t kMagicNumber; class Reader; typedef std::pair ttlrange_t; typedef std::pair tsrange_t; typedef std::pair snrange_t; class BlobLogHeader { friend class BlobFile; friend class BlobDBImpl; private: uint32_t magic_number_ = 0; uint32_t version_ = 1; CompressionType compression_; std::unique_ptr ttl_guess_; std::unique_ptr ts_guess_; private: void set_ttl_guess(const ttlrange_t& ttl) { ttl_guess_.reset(new ttlrange_t(ttl)); } void set_version(uint32_t v) { version_ = v; } void set_ts_guess(const tsrange_t& ts) { ts_guess_.reset(new tsrange_t(ts)); } public: // magic number + version + flags + ttl guess + timestamp range static const size_t kHeaderSize = 4 + 4 + 4 + 4 * 2 + 8 * 2; // 32 void EncodeTo(std::string* dst) const; Status DecodeFrom(Slice* input); BlobLogHeader(); bool HasTTL() const { return !!ttl_guess_; } bool HasTimestamp() const { return !!ts_guess_; } BlobLogHeader& operator=(BlobLogHeader&& in) noexcept; }; // Footer encapsulates the fixed information stored at the tail // end of every blob log file. class BlobLogFooter { friend class BlobFile; public: // Use this constructor when you plan to write out the footer using // EncodeTo(). Never use this constructor with DecodeFrom(). BlobLogFooter(); uint64_t magic_number() const { return magic_number_; } void EncodeTo(std::string* dst) const; Status DecodeFrom(Slice* input); // convert this object to a human readable form std::string ToString() const; // footer size = 4 byte magic number // 8 bytes count // 4, 4 - ttl range // 8, 8 - sn range // 8, 8 - ts range // = 56 static const size_t kFooterSize = 4 + 4 + 8 + (4 * 2) + (8 * 2) + (8 * 2); bool HasTTL() const { return !!ttl_range_; } bool HasTimestamp() const { return !!ts_range_; } uint64_t GetBlobCount() const { return blob_count_; } ttlrange_t GetTTLRange() const { if (ttl_range_) { *ttl_range_; } return {0, 0}; } tsrange_t GetTimeRange() const { if (ts_range_) { return *ts_range_; } return {0, 0}; } const snrange_t& GetSNRange() const { return sn_range_; } private: uint32_t magic_number_ = 0; uint64_t blob_count_ = 0; std::unique_ptr ttl_range_; std::unique_ptr ts_range_; snrange_t sn_range_; private: void set_ttl_range(const ttlrange_t& ttl) { ttl_range_.reset(new ttlrange_t(ttl)); } void set_time_range(const tsrange_t& ts) { ts_range_.reset(new tsrange_t(ts)); } }; extern const size_t kBlockSize; class BlobLogRecord { friend class Reader; private: // this might not be set. uint32_t checksum_; uint32_t header_cksum_; uint32_t key_size_; uint64_t blob_size_; uint64_t time_val_; uint32_t ttl_val_; SequenceNumber sn_; uint32_t footer_cksum_; char type_; char subtype_; Slice key_; Slice blob_; std::string key_buffer_; std::string blob_buffer_; private: void Clear(); char* GetKeyBuffer() { return &(key_buffer_[0]); } char* GetBlobBuffer() { return &(blob_buffer_[0]); } void ResizeKeyBuffer(size_t kbs); void ResizeBlobBuffer(size_t bbs); public: // Header is // Key Length ( 4 bytes ), // Blob Length ( 8 bytes), timestamp/ttl (8 bytes), // type (1 byte), subtype (1 byte) // header checksum (4 bytes), blob checksum (4 bytes), // = 34 static const size_t kHeaderSize = 4 + 4 + 4 + 8 + 4 + 8 + 1 + 1; static const size_t kFooterSize = 8 + 4; public: BlobLogRecord(); ~BlobLogRecord(); const Slice& Key() const { return key_; } const Slice& Blob() const { return blob_; } uint32_t GetKeySize() const { return key_size_; } uint64_t GetBlobSize() const { return blob_size_; } uint32_t GetTTL() const { return ttl_val_; } uint64_t GetTimeVal() const { return time_val_; } SequenceNumber GetSN() const { return sn_; } Status DecodeHeaderFrom(const Slice& hdrslice); Status DecodeFooterFrom(const Slice& footerslice); }; } // namespace blob_db } // namespace rocksdb #endif // ROCKSDB_LITE