/Users/deen/code/yugabyte-db/src/yb/docdb/doc_key.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #ifndef YB_DOCDB_DOC_KEY_H_ |
15 | | #define YB_DOCDB_DOC_KEY_H_ |
16 | | |
17 | | #include <ostream> |
18 | | #include <vector> |
19 | | |
20 | | #include <boost/container/small_vector.hpp> |
21 | | #include <boost/optional/optional.hpp> |
22 | | |
23 | | #include "yb/docdb/docdb_fwd.h" |
24 | | #include "yb/docdb/key_bytes.h" |
25 | | #include "yb/docdb/primitive_value.h" |
26 | | |
27 | | #include "yb/rocksdb/env.h" |
28 | | #include "yb/rocksdb/filter_policy.h" |
29 | | |
30 | | #include "yb/util/ref_cnt_buffer.h" |
31 | | #include "yb/util/slice.h" |
32 | | #include "yb/util/strongly_typed_bool.h" |
33 | | #include "yb/util/uuid.h" |
34 | | |
35 | | namespace yb { |
36 | | namespace docdb { |
37 | | |
38 | | // ------------------------------------------------------------------------------------------------ |
39 | | // DocKey |
40 | | // ------------------------------------------------------------------------------------------------ |
41 | | |
42 | | // A key that allows us to locate a document. This is the prefix of all RocksDB keys of records |
43 | | // inside this document. A document key contains: |
44 | | // - An optional ID (cotable id or pgtable id). |
45 | | // - An optional fixed-width hash prefix. |
46 | | // - A group of primitive values representing "hashed" components (this is what the hash is |
47 | | // computed based on, so this group is present/absent together with the hash). |
48 | | // - A group of "range" components suitable for doing ordered scans. |
49 | | // |
50 | | // The encoded representation of the key is as follows: |
51 | | // - Optional ID: |
52 | | // * For cotable id, the byte ValueType::kTableId followed by a sixteen byte UUID. |
53 | | // * For pgtable id, the byte ValueType::kPgTableOid followed by a four byte PgTableId. |
54 | | // - Optional fixed-width hash prefix, followed by hashed components: |
55 | | // * The byte ValueType::kUInt16Hash, followed by two bytes of the hash prefix. |
56 | | // * Hashed components: |
57 | | // 1. Each hash component consists of a type byte (ValueType) followed by the encoded |
58 | | // representation of the respective type (see PrimitiveValue's key encoding). |
59 | | // 2. ValueType::kGroupEnd terminates the sequence. |
60 | | // - Range components are stored similarly to the hashed components: |
61 | | // 1. Each range component consists of a type byte (ValueType) followed by the encoded |
62 | | // representation of the respective type (see PrimitiveValue's key encoding). |
63 | | // 2. ValueType::kGroupEnd terminates the sequence. |
64 | | YB_DEFINE_ENUM( |
65 | | DocKeyPart, |
66 | | (kUpToHashCode) |
67 | | (kUpToHash) |
68 | | (kUpToId) |
69 | | // Includes all doc key components up to hashed ones. If there are no hashed components - |
70 | | // includes the first range component. |
71 | | (kUpToHashOrFirstRange) |
72 | | (kWholeDocKey)); |
73 | | |
74 | | class DocKeyDecoder; |
75 | | |
76 | | YB_STRONGLY_TYPED_BOOL(HybridTimeRequired) |
77 | | |
78 | | // Whether to allow parts of the range component of a doc key that should not be present in stored |
79 | | // doc key, but could be used during read, for instance kLowest and kHighest. |
80 | | YB_STRONGLY_TYPED_BOOL(AllowSpecial) |
81 | | |
82 | | class DocKey { |
83 | | public: |
84 | | // Constructs an empty document key with no hash component. |
85 | | DocKey(); |
86 | | |
87 | | // Construct a document key with only a range component, but no hashed component. |
88 | | explicit DocKey(std::vector<PrimitiveValue> range_components); |
89 | | |
90 | | // Construct a document key including a hashed component and a range component. The hash value has |
91 | | // to be calculated outside of the constructor, and we're not assuming any specific hash function |
92 | | // here. |
93 | | // @param hash A hash value calculated using the appropriate hash function based on |
94 | | // hashed_components. |
95 | | // @param hashed_components Components of the key that go into computing the hash prefix. |
96 | | // @param range_components Components of the key that we want to be able to do range scans on. |
97 | | DocKey(DocKeyHash hash, |
98 | | std::vector<PrimitiveValue> hashed_components, |
99 | | std::vector<PrimitiveValue> range_components = std::vector<PrimitiveValue>()); |
100 | | |
101 | | DocKey(const Uuid& cotable_id, |
102 | | DocKeyHash hash, |
103 | | std::vector<PrimitiveValue> hashed_components, |
104 | | std::vector<PrimitiveValue> range_components = std::vector<PrimitiveValue>()); |
105 | | |
106 | | DocKey(PgTableOid pgtable_id, |
107 | | DocKeyHash hash, |
108 | | std::vector<PrimitiveValue> hashed_components, |
109 | | std::vector<PrimitiveValue> range_components = std::vector<PrimitiveValue>()); |
110 | | |
111 | | explicit DocKey(const Uuid& cotable_id); |
112 | | |
113 | | explicit DocKey(PgTableOid pgtable_id); |
114 | | |
115 | | // Constructors to create a DocKey for the given schema to support co-located tables. |
116 | | explicit DocKey(const Schema& schema); |
117 | | DocKey(const Schema& schema, DocKeyHash hash); |
118 | | DocKey(const Schema& schema, std::vector<PrimitiveValue> range_components); |
119 | | DocKey(const Schema& schema, DocKeyHash hash, |
120 | | std::vector<PrimitiveValue> hashed_components, |
121 | | std::vector<PrimitiveValue> range_components = std::vector<PrimitiveValue>()); |
122 | | |
123 | | KeyBytes Encode() const; |
124 | | void AppendTo(KeyBytes* out) const; |
125 | | |
126 | | // Encodes DocKey to binary representation returning result as RefCntPrefix. |
127 | | RefCntPrefix EncodeAsRefCntPrefix() const; |
128 | | |
129 | | // Resets the state to an empty document key. |
130 | | void Clear(); |
131 | | |
132 | | // Clear the range components of the document key only. |
133 | | void ClearRangeComponents(); |
134 | | |
135 | | // Resize the range components: |
136 | | // - drop elements (primitive values) from the end if new_size is smaller than the old size. |
137 | | // - append default primitive values (kNullLow) if new_size is bigger than the old size. |
138 | | void ResizeRangeComponents(int new_size); |
139 | | |
140 | 0 | const Uuid& cotable_id() const { |
141 | 0 | return cotable_id_; |
142 | 0 | } |
143 | | |
144 | 20.3M | bool has_cotable_id() const { |
145 | 20.3M | return !cotable_id_.IsNil(); |
146 | 20.3M | } |
147 | | |
148 | 0 | PgTableOid pgtable_id() const { |
149 | 0 | return pgtable_id_; |
150 | 0 | } |
151 | | |
152 | 0 | bool has_pgtable_id() const { |
153 | 0 | return pgtable_id_ > 0; |
154 | 0 | } |
155 | | |
156 | 4.61M | DocKeyHash hash() const { |
157 | 4.61M | return hash_; |
158 | 4.61M | } |
159 | | |
160 | 378 | const std::vector<PrimitiveValue>& hashed_group() const { |
161 | 378 | return hashed_group_; |
162 | 378 | } |
163 | | |
164 | 378 | const std::vector<PrimitiveValue>& range_group() const { |
165 | 378 | return range_group_; |
166 | 378 | } |
167 | | |
168 | 433k | std::vector<PrimitiveValue>& hashed_group() { |
169 | 433k | return hashed_group_; |
170 | 433k | } |
171 | | |
172 | 28.4M | std::vector<PrimitiveValue>& range_group() { |
173 | 28.4M | return range_group_; |
174 | 28.4M | } |
175 | | |
176 | | // Decodes a document key from the given RocksDB key. |
177 | | // slice (in/out) - a slice corresponding to a RocksDB key. Any consumed bytes are removed. |
178 | | // part_to_decode specifies which part of key to decode. |
179 | | CHECKED_STATUS DecodeFrom( |
180 | | Slice* slice, |
181 | | DocKeyPart part_to_decode = DocKeyPart::kWholeDocKey, |
182 | | AllowSpecial allow_special = AllowSpecial::kFalse); |
183 | | |
184 | | // Decodes a document key from the given RocksDB key similar to the above but return the number |
185 | | // of bytes decoded from the input slice. |
186 | | Result<size_t> DecodeFrom( |
187 | | const Slice& slice, |
188 | | DocKeyPart part_to_decode = DocKeyPart::kWholeDocKey, |
189 | | AllowSpecial allow_special = AllowSpecial::kFalse); |
190 | | |
191 | | // Splits given RocksDB key into vector of slices that forms range_group of document key. |
192 | | static CHECKED_STATUS PartiallyDecode(Slice* slice, |
193 | | boost::container::small_vector_base<Slice>* out); |
194 | | |
195 | | // Decode just the hash code of a DocKey. |
196 | | static Result<DocKeyHash> DecodeHash(const Slice& slice); |
197 | | |
198 | | static Result<size_t> EncodedSize( |
199 | | Slice slice, DocKeyPart part, AllowSpecial allow_special = AllowSpecial::kFalse); |
200 | | |
201 | | // Returns size of the encoded `part` of DocKey and whether it has hash code present. |
202 | | static Result<std::pair<size_t, bool>> EncodedSizeAndHashPresent(Slice slice, DocKeyPart part); |
203 | | |
204 | | // Returns size of encoded hash part and whole part of DocKey. |
205 | | static Result<std::pair<size_t, size_t>> EncodedHashPartAndDocKeySizes( |
206 | | Slice slice, AllowSpecial allow_special = AllowSpecial::kFalse); |
207 | | |
208 | | // Decode the current document key from the given slice, but expect all bytes to be consumed, and |
209 | | // return an error status if that is not the case. |
210 | | CHECKED_STATUS FullyDecodeFrom(const rocksdb::Slice& slice); |
211 | | |
212 | | // Converts the document key to a human-readable representation. |
213 | | std::string ToString(AutoDecodeKeys auto_decode_keys = AutoDecodeKeys::kFalse) const; |
214 | | static std::string DebugSliceToString(Slice slice); |
215 | | |
216 | | // Check if it is an empty key. |
217 | 8.04M | bool empty() const { |
218 | 8.04M | return !hash_present_ && range_group_.empty(); |
219 | 8.04M | } |
220 | | |
221 | | bool operator ==(const DocKey& other) const; |
222 | | |
223 | 0 | bool operator !=(const DocKey& other) const { |
224 | 0 | return !(*this == other); |
225 | 0 | } |
226 | | |
227 | | bool HashedComponentsEqual(const DocKey& other) const; |
228 | | |
229 | | void AddRangeComponent(const PrimitiveValue& val); |
230 | | |
231 | | void SetRangeComponent(const PrimitiveValue& val, int idx); |
232 | | |
233 | | int CompareTo(const DocKey& other) const; |
234 | | |
235 | 0 | bool operator <(const DocKey& other) const { |
236 | 0 | return CompareTo(other) < 0; |
237 | 0 | } |
238 | | |
239 | 0 | bool operator <=(const DocKey& other) const { |
240 | 0 | return CompareTo(other) <= 0; |
241 | 0 | } |
242 | | |
243 | 0 | bool operator >(const DocKey& other) const { |
244 | 0 | return CompareTo(other) > 0; |
245 | 0 | } |
246 | | |
247 | 0 | bool operator >=(const DocKey& other) const { |
248 | 0 | return CompareTo(other) >= 0; |
249 | 0 | } |
250 | | |
251 | | bool BelongsTo(const Schema& schema) const; |
252 | | |
253 | 0 | void set_cotable_id(const Uuid& cotable_id) { |
254 | 0 | if (!cotable_id.IsNil()) { |
255 | 0 | DCHECK_EQ(pgtable_id_, 0); |
256 | 0 | } |
257 | 0 | cotable_id_ = cotable_id; |
258 | 0 | } |
259 | | |
260 | 0 | void set_pgtable_id(const PgTableOid pgtable_id) { |
261 | 0 | if (pgtable_id > 0) { |
262 | 0 | DCHECK(cotable_id_.IsNil()); |
263 | 0 | } |
264 | 0 | pgtable_id_ = pgtable_id; |
265 | 0 | } |
266 | | |
267 | 160k | void set_hash(DocKeyHash hash) { |
268 | 160k | hash_ = hash; |
269 | 160k | hash_present_ = true; |
270 | 160k | } |
271 | | |
272 | 6.92M | bool has_hash() const { |
273 | 6.92M | return hash_present_; |
274 | 6.92M | } |
275 | | |
276 | | // Converts a redis string key to a doc key |
277 | | static DocKey FromRedisKey(uint16_t hash, const std::string& key); |
278 | | static KeyBytes EncodedFromRedisKey(uint16_t hash, const std::string &key); |
279 | | |
280 | | private: |
281 | | class DecodeFromCallback; |
282 | | friend class DecodeFromCallback; |
283 | | |
284 | | template<class Callback> |
285 | | static CHECKED_STATUS DoDecode(DocKeyDecoder* decoder, |
286 | | DocKeyPart part_to_decode, |
287 | | AllowSpecial allow_special, |
288 | | const Callback& callback); |
289 | | |
290 | | // Uuid of the non-primary table this DocKey belongs to co-located in a tablet. Nil for the |
291 | | // primary or single-tenant table. |
292 | | Uuid cotable_id_; |
293 | | |
294 | | // Postgres table OID of the non-primary table this DocKey belongs to in colocated tables. |
295 | | // 0 for primary or single tenant table. |
296 | | PgTableOid pgtable_id_; |
297 | | |
298 | | // TODO: can we get rid of this field and just use !hashed_group_.empty() instead? |
299 | | bool hash_present_; |
300 | | |
301 | | DocKeyHash hash_; |
302 | | std::vector<PrimitiveValue> hashed_group_; |
303 | | std::vector<PrimitiveValue> range_group_; |
304 | | }; |
305 | | |
306 | | template <class Collection> |
307 | 47.8M | void AppendDocKeyItems(const Collection& doc_key_items, KeyBytes* result) { |
308 | 40.5M | for (const auto& item : doc_key_items) { |
309 | 40.5M | item.AppendToKey(result); |
310 | 40.5M | } |
311 | 47.8M | result->AppendGroupEnd(); |
312 | 47.8M | } _ZN2yb5docdb17AppendDocKeyItemsINSt3__16vectorINS0_14PrimitiveValueENS2_9allocatorIS4_EEEEEEvRKT_PNS0_8KeyBytesE Line | Count | Source | 307 | 47.8M | void AppendDocKeyItems(const Collection& doc_key_items, KeyBytes* result) { | 308 | 40.4M | for (const auto& item : doc_key_items) { | 309 | 40.4M | item.AppendToKey(result); | 310 | 40.4M | } | 311 | 47.8M | result->AppendGroupEnd(); | 312 | 47.8M | } |
_ZN2yb5docdb17AppendDocKeyItemsISt16initializer_listINS0_14PrimitiveValueEEEEvRKT_PNS0_8KeyBytesE Line | Count | Source | 307 | 81.4k | void AppendDocKeyItems(const Collection& doc_key_items, KeyBytes* result) { | 308 | 47.4k | for (const auto& item : doc_key_items) { | 309 | 47.4k | item.AppendToKey(result); | 310 | 47.4k | } | 311 | 81.4k | result->AppendGroupEnd(); | 312 | 81.4k | } |
|
313 | | |
314 | | class DocKeyEncoderAfterHashStep { |
315 | | public: |
316 | 26.3M | explicit DocKeyEncoderAfterHashStep(KeyBytes* out) : out_(out) {} |
317 | | |
318 | | template <class Collection> |
319 | 26.4M | void Range(const Collection& range_group) { |
320 | 26.4M | AppendDocKeyItems(range_group, out_); |
321 | 26.4M | } _ZN2yb5docdb26DocKeyEncoderAfterHashStep5RangeISt16initializer_listINS0_14PrimitiveValueEEEEvRKT_ Line | Count | Source | 319 | 40.7k | void Range(const Collection& range_group) { | 320 | 40.7k | AppendDocKeyItems(range_group, out_); | 321 | 40.7k | } |
_ZN2yb5docdb26DocKeyEncoderAfterHashStep5RangeINSt3__16vectorINS0_14PrimitiveValueENS3_9allocatorIS5_EEEEEEvRKT_ Line | Count | Source | 319 | 26.3M | void Range(const Collection& range_group) { | 320 | 26.3M | AppendDocKeyItems(range_group, out_); | 321 | 26.3M | } |
|
322 | | |
323 | | private: |
324 | | KeyBytes* out_; |
325 | | }; |
326 | | |
327 | | class DocKeyEncoderAfterTableIdStep { |
328 | | public: |
329 | 26.6M | explicit DocKeyEncoderAfterTableIdStep(KeyBytes* out) : out_(out) { |
330 | 26.6M | } |
331 | | |
332 | | template <class Collection> |
333 | | DocKeyEncoderAfterHashStep Hash( |
334 | 17.2M | bool hash_present, uint16_t hash, const Collection& hashed_group) { |
335 | 17.2M | if (!hash_present) { |
336 | 4.89M | return DocKeyEncoderAfterHashStep(out_); |
337 | 4.89M | } |
338 | | |
339 | 12.3M | return Hash(hash, hashed_group); |
340 | 12.3M | } |
341 | | |
342 | | template <class Collection> |
343 | 21.5M | DocKeyEncoderAfterHashStep Hash(uint16_t hash, const Collection& hashed_group) { |
344 | | // We are not setting the "more items in group" bit on the hash field because it is not part |
345 | | // of "hashed" or "range" groups. |
346 | 21.5M | AppendHash(hash, out_); |
347 | 21.5M | AppendDocKeyItems(hashed_group, out_); |
348 | | |
349 | 21.5M | return DocKeyEncoderAfterHashStep(out_); |
350 | 21.5M | } _ZN2yb5docdb29DocKeyEncoderAfterTableIdStep4HashINSt3__16vectorINS0_14PrimitiveValueENS3_9allocatorIS5_EEEEEENS0_26DocKeyEncoderAfterHashStepEtRKT_ Line | Count | Source | 343 | 21.4M | DocKeyEncoderAfterHashStep Hash(uint16_t hash, const Collection& hashed_group) { | 344 | | // We are not setting the "more items in group" bit on the hash field because it is not part | 345 | | // of "hashed" or "range" groups. | 346 | 21.4M | AppendHash(hash, out_); | 347 | 21.4M | AppendDocKeyItems(hashed_group, out_); | 348 | | | 349 | 21.4M | return DocKeyEncoderAfterHashStep(out_); | 350 | 21.4M | } |
_ZN2yb5docdb29DocKeyEncoderAfterTableIdStep4HashISt16initializer_listINS0_14PrimitiveValueEEEENS0_26DocKeyEncoderAfterHashStepEtRKT_ Line | Count | Source | 343 | 40.7k | DocKeyEncoderAfterHashStep Hash(uint16_t hash, const Collection& hashed_group) { | 344 | | // We are not setting the "more items in group" bit on the hash field because it is not part | 345 | | // of "hashed" or "range" groups. | 346 | 40.7k | AppendHash(hash, out_); | 347 | 40.7k | AppendDocKeyItems(hashed_group, out_); | 348 | | | 349 | 40.7k | return DocKeyEncoderAfterHashStep(out_); | 350 | 40.7k | } |
|
351 | | |
352 | | template <class HashCollection, class RangeCollection> |
353 | | void HashAndRange(uint16_t hash, const HashCollection& hashed_group, |
354 | 9.10M | const RangeCollection& range_collection) { |
355 | 9.10M | Hash(hash, hashed_group).Range(range_collection); |
356 | 9.10M | } |
357 | | |
358 | | void HashAndRange(uint16_t hash, const std::initializer_list<PrimitiveValue>& hashed_group, |
359 | 40.7k | const std::initializer_list<PrimitiveValue>& range_collection) { |
360 | 40.7k | Hash(hash, hashed_group).Range(range_collection); |
361 | 40.7k | } |
362 | | |
363 | | private: |
364 | | KeyBytes* out_; |
365 | | }; |
366 | | |
367 | | class DocKeyEncoder { |
368 | | public: |
369 | 26.6M | explicit DocKeyEncoder(KeyBytes* out) : out_(out) {} |
370 | | |
371 | | DocKeyEncoderAfterTableIdStep CotableId(const Uuid& cotable_id); |
372 | | |
373 | | DocKeyEncoderAfterTableIdStep PgtableId(const PgTableOid pgtable_id); |
374 | | |
375 | | DocKeyEncoderAfterTableIdStep Schema(const Schema& schema); |
376 | | |
377 | | private: |
378 | | KeyBytes* out_; |
379 | | }; |
380 | | |
381 | | class DocKeyDecoder { |
382 | | public: |
383 | 384M | explicit DocKeyDecoder(const Slice& input) : input_(input) {} |
384 | | |
385 | | Result<bool> DecodeCotableId(Uuid* uuid = nullptr); |
386 | | Result<bool> DecodePgtableId(PgTableOid* pgtable_id = nullptr); |
387 | | |
388 | | Result<bool> HasPrimitiveValue(); |
389 | | |
390 | | Result<bool> DecodeHashCode( |
391 | | uint16_t* out = nullptr, AllowSpecial allow_special = AllowSpecial::kFalse); |
392 | | |
393 | | Result<bool> DecodeHashCode(AllowSpecial allow_special); |
394 | | |
395 | | CHECKED_STATUS DecodePrimitiveValue( |
396 | | PrimitiveValue* out = nullptr, AllowSpecial allow_special = AllowSpecial::kFalse); |
397 | | |
398 | | CHECKED_STATUS DecodePrimitiveValue(AllowSpecial allow_special); |
399 | | |
400 | | CHECKED_STATUS ConsumeGroupEnd(); |
401 | | |
402 | | bool GroupEnded() const; |
403 | | |
404 | 694M | const Slice& left_input() const { |
405 | 694M | return input_; |
406 | 694M | } |
407 | | |
408 | 31.7M | size_t ConsumedSizeFrom(const uint8_t* start) const { |
409 | 31.7M | return input_.data() - start; |
410 | 31.7M | } |
411 | | |
412 | 440M | Slice* mutable_input() { |
413 | 440M | return &input_; |
414 | 440M | } |
415 | | |
416 | | CHECKED_STATUS DecodeToRangeGroup(); |
417 | | |
418 | | private: |
419 | | Slice input_; |
420 | | }; |
421 | | |
422 | | // Clears range components from provided key. Returns true if they were exists. |
423 | | Result<bool> ClearRangeComponents(KeyBytes* out, AllowSpecial allow_special = AllowSpecial::kFalse); |
424 | | |
425 | | // Returns true if both keys have hashed components and them are equal or both keys don't have |
426 | | // hashed components and first range components are equal and false otherwise. |
427 | | Result<bool> HashedOrFirstRangeComponentsEqual(const Slice& lhs, const Slice& rhs); |
428 | | |
429 | | bool DocKeyBelongsTo(Slice doc_key, const Schema& schema); |
430 | | |
431 | | // Consumes single primitive value from start of slice. |
432 | | // Returns true when value was consumed, false when group end is found. The group end byte is |
433 | | // consumed in the latter case. |
434 | | Result<bool> ConsumePrimitiveValueFromKey(Slice* slice); |
435 | | |
436 | | // Consume a group of document key components, ending with ValueType::kGroupEnd. |
437 | | // @param slice - the current point at which we are decoding a key |
438 | | // @param result - vector to append decoded values to. |
439 | | Status ConsumePrimitiveValuesFromKey(rocksdb::Slice* slice, |
440 | | std::vector<PrimitiveValue>* result); |
441 | | |
442 | | Result<boost::optional<DocKeyHash>> DecodeDocKeyHash(const Slice& encoded_key); |
443 | | |
444 | 0 | inline std::ostream& operator <<(std::ostream& out, const DocKey& doc_key) { |
445 | 0 | out << doc_key.ToString(); |
446 | 0 | return out; |
447 | 0 | } |
448 | | |
449 | | // ------------------------------------------------------------------------------------------------ |
450 | | // SubDocKey |
451 | | // ------------------------------------------------------------------------------------------------ |
452 | | |
453 | | // A key pointing to a subdocument. Consists of a DocKey identifying the document, a list of |
454 | | // primitive values leading to the subdocument in question, from the outermost to innermost order, |
455 | | // and an optional hybrid_time of when the subdocument (which may itself be a primitive value) was |
456 | | // last fully overwritten or deleted. |
457 | | // |
458 | | // Keys stored in RocksDB should always have the hybrid_time field set. However, it is useful to |
459 | | // make the hybrid_time field optional while a SubDocKey is being constructed. If the hybrid_time |
460 | | // is not set, it is omitted from the encoded representation of a SubDocKey. |
461 | | // |
462 | | // Implementation note: we use HybridTime::kInvalid to represent an omitted hybrid_time. |
463 | | // We rely on that being the default-constructed value of a HybridTime. |
464 | | // |
465 | | // TODO: this should be renamed to something more generic, e.g. Key or LogicalKey, to reflect that |
466 | | // this is actually the logical representation of keys that we store in the RocksDB key-value store. |
467 | | class SubDocKey { |
468 | | public: |
469 | 130M | SubDocKey() {} |
470 | 543 | explicit SubDocKey(const DocKey& doc_key) : doc_key_(doc_key) {} |
471 | 63.5k | explicit SubDocKey(DocKey&& doc_key) : doc_key_(std::move(doc_key)) {} |
472 | | |
473 | | SubDocKey(const DocKey& doc_key, HybridTime hybrid_time) |
474 | | : doc_key_(doc_key), |
475 | 1.88M | doc_ht_(DocHybridTime(hybrid_time)) { |
476 | 1.88M | } |
477 | | |
478 | | SubDocKey(DocKey&& doc_key, |
479 | | HybridTime hybrid_time) |
480 | | : doc_key_(std::move(doc_key)), |
481 | 0 | doc_ht_(DocHybridTime(hybrid_time)) { |
482 | 0 | } |
483 | | |
484 | | SubDocKey(const DocKey& doc_key, const DocHybridTime& hybrid_time) |
485 | | : doc_key_(doc_key), |
486 | 0 | doc_ht_(std::move(hybrid_time)) { |
487 | 0 | } |
488 | | |
489 | | SubDocKey(const DocKey& doc_key, |
490 | | DocHybridTime doc_hybrid_time, |
491 | | const std::vector<PrimitiveValue>& subkeys) |
492 | | : doc_key_(doc_key), |
493 | | doc_ht_(doc_hybrid_time), |
494 | 0 | subkeys_(subkeys) { |
495 | 0 | } |
496 | | |
497 | | SubDocKey(const DocKey& doc_key, |
498 | | HybridTime hybrid_time, |
499 | | const std::vector<PrimitiveValue>& subkeys) |
500 | | : doc_key_(doc_key), |
501 | | doc_ht_(DocHybridTime(hybrid_time)), |
502 | 0 | subkeys_(subkeys) { |
503 | 0 | } |
504 | | |
505 | | template <class ...T> |
506 | | SubDocKey(const DocKey& doc_key, T... subkeys_and_maybe_hybrid_time) |
507 | | : doc_key_(doc_key), |
508 | 2.09M | doc_ht_(DocHybridTime::kInvalid) { |
509 | 2.09M | AppendSubKeysAndMaybeHybridTime(subkeys_and_maybe_hybrid_time...); |
510 | 2.09M | } Unexecuted instantiation: _ZN2yb5docdb9SubDocKeyC2IJNS0_14PrimitiveValueENS_10HybridTimeEEEERKNS0_6DocKeyEDpT_ Unexecuted instantiation: _ZN2yb5docdb9SubDocKeyC2IJNS0_14PrimitiveValueES3_S3_NS_10HybridTimeEEEERKNS0_6DocKeyEDpT_ _ZN2yb5docdb9SubDocKeyC2IJNS0_14PrimitiveValueEEEERKNS0_6DocKeyEDpT_ Line | Count | Source | 508 | 2.08M | doc_ht_(DocHybridTime::kInvalid) { | 509 | 2.08M | AppendSubKeysAndMaybeHybridTime(subkeys_and_maybe_hybrid_time...); | 510 | 2.08M | } |
_ZN2yb5docdb9SubDocKeyC2IJNS0_14PrimitiveValueES3_EEERKNS0_6DocKeyEDpT_ Line | Count | Source | 508 | 10.5k | doc_ht_(DocHybridTime::kInvalid) { | 509 | 10.5k | AppendSubKeysAndMaybeHybridTime(subkeys_and_maybe_hybrid_time...); | 510 | 10.5k | } |
|
511 | | |
512 | | CHECKED_STATUS FromDocPath(const DocPath& doc_path); |
513 | | |
514 | | // Return the subkeys within this SubDocKey |
515 | 0 | const std::vector<PrimitiveValue>& subkeys() const { |
516 | 0 | return subkeys_; |
517 | 0 | } |
518 | | |
519 | 10 | std::vector<PrimitiveValue>& subkeys() { |
520 | 10 | return subkeys_; |
521 | 10 | } |
522 | | |
523 | | // Append a sequence of sub-keys to this key. |
524 | | template<class ...T> |
525 | | void AppendSubKeysAndMaybeHybridTime(PrimitiveValue subdoc_key, |
526 | 10.5k | T... subkeys_and_maybe_hybrid_time) { |
527 | 10.5k | subkeys_.push_back(std::move(subdoc_key)); |
528 | 10.5k | AppendSubKeysAndMaybeHybridTime(subkeys_and_maybe_hybrid_time...); |
529 | 10.5k | } Unexecuted instantiation: _ZN2yb5docdb9SubDocKey31AppendSubKeysAndMaybeHybridTimeIJNS0_14PrimitiveValueES3_NS_10HybridTimeEEEEvS3_DpT_ Unexecuted instantiation: _ZN2yb5docdb9SubDocKey31AppendSubKeysAndMaybeHybridTimeIJNS0_14PrimitiveValueENS_10HybridTimeEEEEvS3_DpT_ _ZN2yb5docdb9SubDocKey31AppendSubKeysAndMaybeHybridTimeIJNS0_14PrimitiveValueEEEEvS3_DpT_ Line | Count | Source | 526 | 10.5k | T... subkeys_and_maybe_hybrid_time) { | 527 | 10.5k | subkeys_.push_back(std::move(subdoc_key)); | 528 | 10.5k | AppendSubKeysAndMaybeHybridTime(subkeys_and_maybe_hybrid_time...); | 529 | 10.5k | } |
|
530 | | |
531 | | template<class ...T> |
532 | 2.09M | void AppendSubKeysAndMaybeHybridTime(PrimitiveValue subdoc_key) { |
533 | 2.09M | subkeys_.emplace_back(std::move(subdoc_key)); |
534 | 2.09M | } |
535 | | |
536 | | template<class ...T> |
537 | 0 | void AppendSubKeysAndMaybeHybridTime(PrimitiveValue subdoc_key, HybridTime hybrid_time) { |
538 | 0 | DCHECK(!has_hybrid_time()); |
539 | 0 | subkeys_.emplace_back(subdoc_key); |
540 | 0 | DCHECK(hybrid_time.is_valid()); |
541 | 0 | doc_ht_ = DocHybridTime(hybrid_time); |
542 | 0 | } |
543 | | |
544 | | void AppendSubKey(PrimitiveValue subkey); |
545 | | |
546 | | void RemoveLastSubKey(); |
547 | | |
548 | | void KeepPrefix(size_t num_sub_keys_to_keep); |
549 | | |
550 | 0 | void remove_hybrid_time() { |
551 | 0 | doc_ht_ = DocHybridTime::kInvalid; |
552 | 0 | } |
553 | | |
554 | | void Clear(); |
555 | | |
556 | 0 | bool IsValid() const { |
557 | 0 | return !doc_key_.empty(); |
558 | 0 | } |
559 | | |
560 | 2.16M | KeyBytes Encode() const { return DoEncode(true /* include_hybrid_time */); } |
561 | 11.5k | KeyBytes EncodeWithoutHt() const { return DoEncode(false /* include_hybrid_time */); } |
562 | | |
563 | | // Decodes a SubDocKey from the given slice, typically retrieved from a RocksDB key. |
564 | | // @param slice |
565 | | // A pointer to the slice containing the bytes to decode the SubDocKey from. This slice is |
566 | | // modified, with consumed bytes being removed. |
567 | | // @param require_hybrid_time |
568 | | // Whether a hybrid_time is required in the end of the SubDocKey. If this is true, we require |
569 | | // a ValueType::kHybridTime byte followed by a hybrid_time to be present in the input slice. |
570 | | // Otherwise, we allow decoding an incomplete SubDocKey without a hybrid_time in the end. Note |
571 | | // that we also allow input that has a few bytes in the end but not enough to represent a |
572 | | // hybrid_time. |
573 | | // @param allow_special |
574 | | // Whether it is allowed to have special value types in slice, that are used during seek. |
575 | | // If such value type is found, decoding is stopped w/o error. |
576 | | CHECKED_STATUS DecodeFrom(rocksdb::Slice* slice, |
577 | | HybridTimeRequired require_hybrid_time = HybridTimeRequired::kTrue, |
578 | | AllowSpecial allow_special = AllowSpecial::kFalse); |
579 | | |
580 | | // Similar to DecodeFrom, but requires that the entire slice is decoded, and thus takes a const |
581 | | // reference to a slice. This still respects the require_hybrid_time parameter, but in case a |
582 | | // hybrid_time is omitted, we don't allow any extra bytes to be present in the slice. |
583 | | CHECKED_STATUS FullyDecodeFrom( |
584 | | const rocksdb::Slice& slice, |
585 | | HybridTimeRequired hybrid_time_required = HybridTimeRequired::kTrue); |
586 | | |
587 | | // Splits given RocksDB key into vector of slices that forms range_group of document key and |
588 | | // hybrid_time. |
589 | | static CHECKED_STATUS PartiallyDecode(Slice* slice, |
590 | | boost::container::small_vector_base<Slice>* out); |
591 | | |
592 | | // Splits the given RocksDB sub key into a vector of slices that forms the range group of document |
593 | | // key and sub keys. |
594 | | // |
595 | | // We don't use Result<...> to be able to reuse memory allocated by out. |
596 | | // |
597 | | // When key does not start with a hash component, the returned prefix would start with the first |
598 | | // range component. |
599 | | // |
600 | | // For instance, for a (hash_value, h1, h2, r1, r2, s1) doc key the following values will be |
601 | | // returned: |
602 | | // encoded_length(hash_value, h1, h2) <-------------- (includes the kGroupEnd of the hashed part) |
603 | | // encoded_length(hash_value, h1, h2, r1) |
604 | | // encoded_length(hash_value, h1, h2, r1, r2) |
605 | | // encoded_length(hash_value, h1, h2, r1, r2, s1) <------- (includes kGroupEnd of the range part). |
606 | | static CHECKED_STATUS DecodePrefixLengths( |
607 | | Slice slice, boost::container::small_vector_base<size_t>* out); |
608 | | |
609 | | // Fills out with ends of SubDocKey components. First item in out will be size of ID part |
610 | | // (cotable id or pgtable id) of DocKey (0 if ID is not present), second size of whole DocKey, |
611 | | // third size of DocKey + size of first subkey, and so on. |
612 | | // |
613 | | // To illustrate, |
614 | | // * for key |
615 | | // SubDocKey(DocKey(0xfca0, [3], []), [SystemColumnId(0); HT{ physical: 1581475435181551 }]) |
616 | | // aka |
617 | | // 47FCA0488000000321214A80238001B5E605A0CA10804A |
618 | | // (and with spaces to make it clearer) |
619 | | // 47FCA0 4880000003 21 21 4A80 238001B5E605A0CA10804A |
620 | | // the ends will be |
621 | | // {0, 10, 12} |
622 | | // * for key |
623 | | // SubDocKey(DocKey(PgTableId=16385, [], [5]), [SystemColumnId(0); HT{ physical: ... }]) |
624 | | // aka |
625 | | // 30000040014880000005214A80238001B5E700309553804A |
626 | | // (and with spaces to make it clearer) |
627 | | // 3000004001 4880000005 21 4A80 238001B5E700309553804A |
628 | | // the ends will be |
629 | | // {5, 11, 13} |
630 | | // * for key |
631 | | // SubDocKey(DocKey(PgTableId=16385, [], []), [HT{ physical: 1581471227403848 }]) |
632 | | // aka |
633 | | // 300000400121238001B5E7006E61B7804A |
634 | | // (and with spaces to make it clearer) |
635 | | // 3000004001 21 238001B5E7006E61B7804A |
636 | | // the ends will be |
637 | | // {5} |
638 | | // |
639 | | // If out is not empty, then it will be interpreted as partial result for this decoding operation |
640 | | // and the appropriate prefix will be skipped. |
641 | | static CHECKED_STATUS DecodeDocKeyAndSubKeyEnds( |
642 | | Slice slice, boost::container::small_vector_base<size_t>* out); |
643 | | |
644 | | // Attempts to decode a subkey at the beginning of the given slice, consuming the corresponding |
645 | | // prefix of the slice. Returns false if there is no next subkey, as indicated by the slice being |
646 | | // empty or encountering an encoded hybrid time. |
647 | | static Result<bool> DecodeSubkey(Slice* slice); |
648 | | |
649 | | CHECKED_STATUS FullyDecodeFromKeyWithOptionalHybridTime(const rocksdb::Slice& slice); |
650 | | |
651 | | std::string ToString(AutoDecodeKeys auto_decode_keys = AutoDecodeKeys::kFalse) const; |
652 | | static std::string DebugSliceToString(Slice slice); |
653 | | static Result<std::string> DebugSliceToStringAsResult(Slice slice); |
654 | | |
655 | 756 | const DocKey& doc_key() const { |
656 | 756 | return doc_key_; |
657 | 756 | } |
658 | | |
659 | 54.1M | DocKey& doc_key() { |
660 | 54.1M | return doc_key_; |
661 | 54.1M | } |
662 | | |
663 | 81 | size_t num_subkeys() const { |
664 | 81 | return subkeys_.size(); |
665 | 81 | } |
666 | | |
667 | | bool StartsWith(const SubDocKey& prefix) const; |
668 | | |
669 | | bool operator ==(const SubDocKey& other) const; |
670 | | |
671 | 0 | bool operator !=(const SubDocKey& other) const { |
672 | 0 | return !(*this == other); |
673 | 0 | } |
674 | | |
675 | 0 | const PrimitiveValue& last_subkey() const { |
676 | 0 | assert(!subkeys_.empty()); |
677 | 0 | return subkeys_.back(); |
678 | 0 | } |
679 | | |
680 | | int CompareTo(const SubDocKey& other) const; |
681 | | int CompareToIgnoreHt(const SubDocKey& other) const; |
682 | | |
683 | 0 | bool operator <(const SubDocKey& other) const { |
684 | 0 | return CompareTo(other) < 0; |
685 | 0 | } |
686 | | |
687 | 0 | bool operator <=(const SubDocKey& other) const { |
688 | 0 | return CompareTo(other) <= 0; |
689 | 0 | } |
690 | | |
691 | 0 | bool operator >(const SubDocKey& other) const { |
692 | 0 | return CompareTo(other) > 0; |
693 | 0 | } |
694 | | |
695 | 0 | bool operator >=(const SubDocKey& other) const { |
696 | 0 | return CompareTo(other) >= 0; |
697 | 0 | } |
698 | | |
699 | 0 | HybridTime hybrid_time() const { |
700 | 0 | DCHECK(has_hybrid_time()); |
701 | 0 | return doc_ht_.hybrid_time(); |
702 | 0 | } |
703 | | |
704 | 27.1M | const DocHybridTime& doc_hybrid_time() const { |
705 | 27.1M | DCHECK(has_hybrid_time()); |
706 | 27.1M | return doc_ht_; |
707 | 27.1M | } |
708 | | |
709 | 0 | void set_hybrid_time(const DocHybridTime& hybrid_time) { |
710 | 0 | DCHECK(hybrid_time.is_valid()); |
711 | 0 | doc_ht_ = hybrid_time; |
712 | 0 | } |
713 | | |
714 | 64.0M | bool has_hybrid_time() const { |
715 | 64.0M | return doc_ht_.is_valid(); |
716 | 64.0M | } |
717 | | |
718 | | // Generate a RocksDB key that would allow us to seek to the smallest SubDocKey that has a |
719 | | // lexicographically higher sequence of subkeys than this one, but is not an extension of this |
720 | | // sequence of subkeys. In other words, ensure we advance to the next field (subkey) either |
721 | | // within the object (subdocument) we are currently scanning, or at any higher level, including |
722 | | // advancing to the next document key. |
723 | | // |
724 | | // E.g. assuming the SubDocKey this is being called on is #2 from the following example, |
725 | | // performing a RocksDB seek on the return value of this takes us to #7. |
726 | | // |
727 | | // 1. SubDocKey(DocKey([], ["a"]), [HT(1)]) -> {} |
728 | | // 2. SubDocKey(DocKey([], ["a"]), ["x", HT(1)]) -> {} ---------------------------. |
729 | | // 3. SubDocKey(DocKey([], ["a"]), ["x", "x", HT(2)]) -> null | |
730 | | // 4. SubDocKey(DocKey([], ["a"]), ["x", "x", HT(1)]) -> {} | |
731 | | // 5. SubDocKey(DocKey([], ["a"]), ["x", "x", "y", HT(1)]) -> {} | |
732 | | // 6. SubDocKey(DocKey([], ["a"]), ["x", "x", "y", "x", HT(1)]) -> true | |
733 | | // 7. SubDocKey(DocKey([], ["a"]), ["y", HT(3)]) -> {} <--------- |
734 | | // 8. SubDocKey(DocKey([], ["a"]), ["y", "y", HT(3)]) -> {} |
735 | | // 9. SubDocKey(DocKey([], ["a"]), ["y", "y", "x", HT(3)]) -> |
736 | | // |
737 | | // This is achieved by simply appending a byte that is higher than any ValueType in an encoded |
738 | | // representation of a SubDocKey that extends the vector of subkeys present in the current one, |
739 | | // or has the same vector of subkeys, i.e. key/value pairs #3-6 in the above example. HybridTime |
740 | | // is omitted from the resulting encoded representation. |
741 | | KeyBytes AdvanceOutOfSubDoc() const; |
742 | | |
743 | | // Similar to AdvanceOutOfSubDoc, but seek to the smallest key that skips documents with this |
744 | | // DocKey and DocKeys that have the same hash components but add more range components to it. |
745 | | // |
746 | | // E.g. assuming the SubDocKey this is being called on is #2 from the following example: |
747 | | // |
748 | | // 1. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), [HT(1)]) -> {} |
749 | | // 2. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["x", HT(1)]) -> {} <----------------. |
750 | | // 3. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["x", "x", HT(2)]) -> null | |
751 | | // 4. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["x", "x", HT(1)]) -> {} | |
752 | | // 5. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["x", "x", "y", HT(1)]) -> {} | |
753 | | // 6. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["x", "x", "y", "x", HT(1)]) -> true | |
754 | | // 7. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["y", HT(3)]) -> {} | |
755 | | // 8. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["y", "y", HT(3)]) -> {} | |
756 | | // 9. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"]), ["y", "y", "x", HT(3)]) -> {} | |
757 | | // ... | |
758 | | // 20. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d", "e"]), ["y", HT(3)]) -> {} | |
759 | | // 21. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d", "e"]), ["z", HT(3)]) -> {} | |
760 | | // 22. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "f"]), [HT(1)]) -> {} <--- (*** 1 ***)-| |
761 | | // 23. SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "f"]), ["x", HT(1)]) -> {} | |
762 | | // ... | |
763 | | // 30. SubDocKey(DocKey(0x2345, ["a", "c"], ["c", "f"]), [HT(1)]) -> {} <--- (*** 2 ***)- |
764 | | // 31. SubDocKey(DocKey(0x2345, ["a", "c"], ["c", "f"]), ["x", HT(1)]) -> {} |
765 | | // |
766 | | // SubDocKey(DocKey(0x1234, ["a", "b"], ["c", "d"])).AdvanceOutOfDocKeyPrefix() will seek to #22 |
767 | | // (*** 1 ***), pass doc keys with additional range components when they are present. |
768 | | // |
769 | | // And when given a doc key without range component like below, it can help seek pass all doc |
770 | | // keys with the same hash components, e.g. |
771 | | // SubDocKey(DocKey(0x1234, ["a", "b"], [])).AdvanceOutOfDocKeyPrefix() will seek to #30 |
772 | | // (*** 2 ***). |
773 | | |
774 | | KeyBytes AdvanceOutOfDocKeyPrefix() const; |
775 | | |
776 | | private: |
777 | | class DecodeCallback; |
778 | | friend class DecodeCallback; |
779 | | |
780 | | // Attempts to decode and consume a subkey from the beginning of the given slice. |
781 | | // A non-error false result means e.g. that the slice is empty or if the next thing is an encoded |
782 | | // hybrid time. |
783 | | template<class Callback> |
784 | | static Result<bool> DecodeSubkey(Slice* slice, const Callback& callback); |
785 | | |
786 | | template<class Callback> |
787 | | static Status DoDecode(rocksdb::Slice* slice, |
788 | | HybridTimeRequired require_hybrid_time, |
789 | | AllowSpecial allow_special, |
790 | | const Callback& callback); |
791 | | |
792 | | KeyBytes DoEncode(bool include_hybrid_time) const; |
793 | | |
794 | | DocKey doc_key_; |
795 | | DocHybridTime doc_ht_; |
796 | | |
797 | | // TODO: make this a small_vector. |
798 | | std::vector<PrimitiveValue> subkeys_; |
799 | | }; |
800 | | |
801 | 0 | inline std::ostream& operator <<(std::ostream& out, const SubDocKey& subdoc_key) { |
802 | 0 | out << subdoc_key.ToString(); |
803 | 0 | return out; |
804 | 0 | } |
805 | | |
806 | | // A best-effort to decode the given sequence of key bytes as either a DocKey or a SubDocKey. |
807 | | // If not possible to decode, return the key_bytes directly as a readable string. |
808 | | std::string BestEffortDocDBKeyToStr(const KeyBytes &key_bytes); |
809 | | std::string BestEffortDocDBKeyToStr(const rocksdb::Slice &slice); |
810 | | |
811 | | class DocDbAwareFilterPolicyBase : public rocksdb::FilterPolicy { |
812 | | public: |
813 | 1.26M | explicit DocDbAwareFilterPolicyBase(size_t filter_block_size_bits, rocksdb::Logger* logger) { |
814 | 1.26M | builtin_policy_.reset(rocksdb::NewFixedSizeFilterPolicy( |
815 | 1.26M | filter_block_size_bits, rocksdb::FilterPolicy::kDefaultFixedSizeFilterErrorRate, logger)); |
816 | 1.26M | } |
817 | | |
818 | | void CreateFilter(const rocksdb::Slice* keys, int n, std::string* dst) const override; |
819 | | |
820 | | bool KeyMayMatch(const rocksdb::Slice& key, const rocksdb::Slice& filter) const override; |
821 | | |
822 | | rocksdb::FilterBitsBuilder* GetFilterBitsBuilder() const override; |
823 | | |
824 | | rocksdb::FilterBitsReader* GetFilterBitsReader(const rocksdb::Slice& contents) const override; |
825 | | |
826 | | FilterType GetFilterType() const override; |
827 | | |
828 | | private: |
829 | | std::unique_ptr<const rocksdb::FilterPolicy> builtin_policy_; |
830 | | }; |
831 | | |
832 | | // This filter policy only takes into account hashed components of keys for filtering. |
833 | | class DocDbAwareHashedComponentsFilterPolicy : public DocDbAwareFilterPolicyBase { |
834 | | public: |
835 | | DocDbAwareHashedComponentsFilterPolicy(size_t filter_block_size_bits, rocksdb::Logger* logger) |
836 | 422k | : DocDbAwareFilterPolicyBase(filter_block_size_bits, logger) {} |
837 | | |
838 | 422k | const char* Name() const override { return "DocKeyHashedComponentsFilter"; } |
839 | | |
840 | | const KeyTransformer* GetKeyTransformer() const override; |
841 | | }; |
842 | | |
843 | | // Together with the fix for BlockBasedTableBuild::Add |
844 | | // (https://github.com/yugabyte/yugabyte-db/issues/6435) we also disable DocKeyV2Filter |
845 | | // for range-partitioned tablets. For hash-partitioned tablets it will be supported during read |
846 | | // path and will work the same way as DocDbAwareV3FilterPolicy. |
847 | | class DocDbAwareV2FilterPolicy : public DocDbAwareFilterPolicyBase { |
848 | | public: |
849 | | DocDbAwareV2FilterPolicy(size_t filter_block_size_bits, rocksdb::Logger* logger) |
850 | 422k | : DocDbAwareFilterPolicyBase(filter_block_size_bits, logger) {} |
851 | | |
852 | 422k | const char* Name() const override { return "DocKeyV2Filter"; } |
853 | | |
854 | | const KeyTransformer* GetKeyTransformer() const override; |
855 | | }; |
856 | | |
857 | | // This filter policy takes into account following parts of keys for filtering: |
858 | | // - For range-based partitioned tables (such tables have 0 hashed components): |
859 | | // use all hash components of the doc key. |
860 | | // - For hash-based partitioned tables (such tables have >0 hashed components): |
861 | | // use first range component of the doc key. |
862 | | class DocDbAwareV3FilterPolicy : public DocDbAwareFilterPolicyBase { |
863 | | public: |
864 | | DocDbAwareV3FilterPolicy(size_t filter_block_size_bits, rocksdb::Logger* logger) |
865 | 422k | : DocDbAwareFilterPolicyBase(filter_block_size_bits, logger) {} |
866 | | |
867 | 1.92M | const char* Name() const override { return "DocKeyV3Filter"; } |
868 | | |
869 | | const KeyTransformer* GetKeyTransformer() const override; |
870 | | }; |
871 | | |
872 | | } // namespace docdb |
873 | | } // namespace yb |
874 | | |
875 | | #endif // YB_DOCDB_DOC_KEY_H_ |