]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 | #pragma once | |
11fdf7f2 | 6 | |
f67539c2 TL |
7 | #include <sstream> |
8 | #include <string> | |
9 | ||
20effc67 | 10 | #include "rocksdb/compression_type.h" |
11fdf7f2 | 11 | #include "util/coding.h" |
20effc67 | 12 | #include "util/compression.h" |
11fdf7f2 TL |
13 | #include "util/string_util.h" |
14 | ||
f67539c2 | 15 | namespace ROCKSDB_NAMESPACE { |
11fdf7f2 TL |
16 | |
17 | // BlobIndex is a pointer to the blob and metadata of the blob. The index is | |
18 | // stored in base DB as ValueType::kTypeBlobIndex. | |
19 | // There are three types of blob index: | |
20 | // | |
21 | // kInlinedTTL: | |
22 | // +------+------------+---------------+ | |
23 | // | type | expiration | value | | |
24 | // +------+------------+---------------+ | |
25 | // | char | varint64 | variable size | | |
26 | // +------+------------+---------------+ | |
27 | // | |
28 | // kBlob: | |
29 | // +------+-------------+----------+----------+-------------+ | |
30 | // | type | file number | offset | size | compression | | |
31 | // +------+-------------+----------+----------+-------------+ | |
32 | // | char | varint64 | varint64 | varint64 | char | | |
33 | // +------+-------------+----------+----------+-------------+ | |
34 | // | |
35 | // kBlobTTL: | |
36 | // +------+------------+-------------+----------+----------+-------------+ | |
37 | // | type | expiration | file number | offset | size | compression | | |
38 | // +------+------------+-------------+----------+----------+-------------+ | |
39 | // | char | varint64 | varint64 | varint64 | varint64 | char | | |
40 | // +------+------------+-------------+----------+----------+-------------+ | |
41 | // | |
42 | // There isn't a kInlined (without TTL) type since we can store it as a plain | |
43 | // value (i.e. ValueType::kTypeValue). | |
44 | class BlobIndex { | |
45 | public: | |
46 | enum class Type : unsigned char { | |
47 | kInlinedTTL = 0, | |
48 | kBlob = 1, | |
49 | kBlobTTL = 2, | |
50 | kUnknown = 3, | |
51 | }; | |
52 | ||
53 | BlobIndex() : type_(Type::kUnknown) {} | |
54 | ||
1e59de90 TL |
55 | BlobIndex(const BlobIndex&) = default; |
56 | BlobIndex& operator=(const BlobIndex&) = default; | |
57 | ||
11fdf7f2 TL |
58 | bool IsInlined() const { return type_ == Type::kInlinedTTL; } |
59 | ||
60 | bool HasTTL() const { | |
61 | return type_ == Type::kInlinedTTL || type_ == Type::kBlobTTL; | |
62 | } | |
63 | ||
64 | uint64_t expiration() const { | |
65 | assert(HasTTL()); | |
66 | return expiration_; | |
67 | } | |
68 | ||
69 | const Slice& value() const { | |
70 | assert(IsInlined()); | |
71 | return value_; | |
72 | } | |
73 | ||
74 | uint64_t file_number() const { | |
75 | assert(!IsInlined()); | |
76 | return file_number_; | |
77 | } | |
78 | ||
79 | uint64_t offset() const { | |
80 | assert(!IsInlined()); | |
81 | return offset_; | |
82 | } | |
83 | ||
84 | uint64_t size() const { | |
85 | assert(!IsInlined()); | |
86 | return size_; | |
87 | } | |
88 | ||
20effc67 TL |
89 | CompressionType compression() const { |
90 | assert(!IsInlined()); | |
91 | return compression_; | |
92 | } | |
93 | ||
11fdf7f2 | 94 | Status DecodeFrom(Slice slice) { |
1e59de90 | 95 | const char* kErrorMessage = "Error while decoding blob index"; |
11fdf7f2 TL |
96 | assert(slice.size() > 0); |
97 | type_ = static_cast<Type>(*slice.data()); | |
98 | if (type_ >= Type::kUnknown) { | |
1e59de90 TL |
99 | return Status::Corruption(kErrorMessage, |
100 | "Unknown blob index type: " + | |
101 | std::to_string(static_cast<char>(type_))); | |
11fdf7f2 TL |
102 | } |
103 | slice = Slice(slice.data() + 1, slice.size() - 1); | |
104 | if (HasTTL()) { | |
105 | if (!GetVarint64(&slice, &expiration_)) { | |
106 | return Status::Corruption(kErrorMessage, "Corrupted expiration"); | |
107 | } | |
108 | } | |
109 | if (IsInlined()) { | |
110 | value_ = slice; | |
111 | } else { | |
112 | if (GetVarint64(&slice, &file_number_) && GetVarint64(&slice, &offset_) && | |
113 | GetVarint64(&slice, &size_) && slice.size() == 1) { | |
114 | compression_ = static_cast<CompressionType>(*slice.data()); | |
115 | } else { | |
116 | return Status::Corruption(kErrorMessage, "Corrupted blob offset"); | |
117 | } | |
118 | } | |
119 | return Status::OK(); | |
120 | } | |
121 | ||
f67539c2 TL |
122 | std::string DebugString(bool output_hex) const { |
123 | std::ostringstream oss; | |
124 | ||
125 | if (IsInlined()) { | |
126 | oss << "[inlined blob] value:" << value_.ToString(output_hex); | |
127 | } else { | |
128 | oss << "[blob ref] file:" << file_number_ << " offset:" << offset_ | |
20effc67 TL |
129 | << " size:" << size_ |
130 | << " compression: " << CompressionTypeToString(compression_); | |
f67539c2 TL |
131 | } |
132 | ||
133 | if (HasTTL()) { | |
134 | oss << " exp:" << expiration_; | |
135 | } | |
136 | ||
137 | return oss.str(); | |
138 | } | |
139 | ||
11fdf7f2 TL |
140 | static void EncodeInlinedTTL(std::string* dst, uint64_t expiration, |
141 | const Slice& value) { | |
142 | assert(dst != nullptr); | |
143 | dst->clear(); | |
144 | dst->reserve(1 + kMaxVarint64Length + value.size()); | |
145 | dst->push_back(static_cast<char>(Type::kInlinedTTL)); | |
146 | PutVarint64(dst, expiration); | |
147 | dst->append(value.data(), value.size()); | |
148 | } | |
149 | ||
150 | static void EncodeBlob(std::string* dst, uint64_t file_number, | |
151 | uint64_t offset, uint64_t size, | |
152 | CompressionType compression) { | |
153 | assert(dst != nullptr); | |
154 | dst->clear(); | |
155 | dst->reserve(kMaxVarint64Length * 3 + 2); | |
156 | dst->push_back(static_cast<char>(Type::kBlob)); | |
157 | PutVarint64(dst, file_number); | |
158 | PutVarint64(dst, offset); | |
159 | PutVarint64(dst, size); | |
160 | dst->push_back(static_cast<char>(compression)); | |
161 | } | |
162 | ||
163 | static void EncodeBlobTTL(std::string* dst, uint64_t expiration, | |
164 | uint64_t file_number, uint64_t offset, | |
165 | uint64_t size, CompressionType compression) { | |
166 | assert(dst != nullptr); | |
167 | dst->clear(); | |
168 | dst->reserve(kMaxVarint64Length * 4 + 2); | |
169 | dst->push_back(static_cast<char>(Type::kBlobTTL)); | |
170 | PutVarint64(dst, expiration); | |
171 | PutVarint64(dst, file_number); | |
172 | PutVarint64(dst, offset); | |
173 | PutVarint64(dst, size); | |
174 | dst->push_back(static_cast<char>(compression)); | |
175 | } | |
176 | ||
177 | private: | |
178 | Type type_ = Type::kUnknown; | |
179 | uint64_t expiration_ = 0; | |
180 | Slice value_; | |
181 | uint64_t file_number_ = 0; | |
182 | uint64_t offset_ = 0; | |
183 | uint64_t size_ = 0; | |
184 | CompressionType compression_ = kNoCompression; | |
185 | }; | |
186 | ||
f67539c2 | 187 | } // namespace ROCKSDB_NAMESPACE |