/src/rocksdb/table/block_based/block_builder.h
Line | Count | Source (jump to first uncovered line) |
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 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
7 | | // Use of this source code is governed by a BSD-style license that can be |
8 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
9 | | |
10 | | #pragma once |
11 | | #include <stdint.h> |
12 | | |
13 | | #include <vector> |
14 | | |
15 | | #include "rocksdb/slice.h" |
16 | | #include "rocksdb/table.h" |
17 | | #include "table/block_based/data_block_hash_index.h" |
18 | | |
19 | | namespace ROCKSDB_NAMESPACE { |
20 | | |
21 | | class BlockBuilder { |
22 | | public: |
23 | | BlockBuilder(const BlockBuilder&) = delete; |
24 | | void operator=(const BlockBuilder&) = delete; |
25 | | |
26 | | explicit BlockBuilder(int block_restart_interval, |
27 | | bool use_delta_encoding = true, |
28 | | bool use_value_delta_encoding = false, |
29 | | BlockBasedTableOptions::DataBlockIndexType index_type = |
30 | | BlockBasedTableOptions::kDataBlockBinarySearch, |
31 | | double data_block_hash_table_util_ratio = 0.75, |
32 | | size_t ts_sz = 0, |
33 | | bool persist_user_defined_timestamps = true, |
34 | | bool is_user_key = false); |
35 | | |
36 | | // Reset the contents as if the BlockBuilder was just constructed. |
37 | | void Reset(); |
38 | | |
39 | | // Swap the contents in BlockBuilder with buffer, then reset the BlockBuilder. |
40 | | void SwapAndReset(std::string& buffer); |
41 | | |
42 | | // REQUIRES: Finish() has not been called since the last call to Reset(). |
43 | | // REQUIRES: Unless a range tombstone block, key is larger than any previously |
44 | | // added key |
45 | | // DO NOT mix with AddWithLastKey() between Resets. For efficiency, use |
46 | | // AddWithLastKey() in contexts where previous added key is already known |
47 | | // and delta encoding might be used. |
48 | | void Add(const Slice& key, const Slice& value, |
49 | | const Slice* const delta_value = nullptr); |
50 | | |
51 | | // A faster version of Add() if the previous key is already known for all |
52 | | // Add()s. |
53 | | // REQUIRES: Finish() has not been called since the last call to Reset(). |
54 | | // REQUIRES: Unless a range tombstone block, key is larger than any previously |
55 | | // added key |
56 | | // REQUIRES: if AddWithLastKey has been called since last Reset(), last_key |
57 | | // is the key from most recent AddWithLastKey. (For convenience, last_key |
58 | | // is ignored on first call after creation or Reset().) |
59 | | // DO NOT mix with Add() between Resets. |
60 | | void AddWithLastKey(const Slice& key, const Slice& value, |
61 | | const Slice& last_key, |
62 | | const Slice* const delta_value = nullptr); |
63 | | |
64 | | // Finish building the block and return a slice that refers to the |
65 | | // block contents. The returned slice will remain valid for the |
66 | | // lifetime of this builder or until Reset() is called. |
67 | | Slice Finish(); |
68 | | |
69 | | // Returns an estimate of the current (uncompressed) size of the block |
70 | | // we are building. |
71 | 102k | inline size_t CurrentSizeEstimate() const { |
72 | 102k | return estimate_ + (data_block_hash_index_builder_.Valid() |
73 | 102k | ? data_block_hash_index_builder_.EstimateSize() |
74 | 102k | : 0); |
75 | 102k | } |
76 | | |
77 | | // Returns an estimated block size after appending key and value. |
78 | | size_t EstimateSizeAfterKV(const Slice& key, const Slice& value) const; |
79 | | |
80 | | // Return true iff no entries have been added since the last Reset() |
81 | 134k | bool empty() const { return buffer_.empty(); } |
82 | | |
83 | | private: |
84 | | inline void AddWithLastKeyImpl(const Slice& key, const Slice& value, |
85 | | const Slice& last_key, |
86 | | const Slice* const delta_value, |
87 | | size_t buffer_size); |
88 | | |
89 | | inline const Slice MaybeStripTimestampFromKey(std::string* key_buf, |
90 | | const Slice& key); |
91 | | |
92 | | const int block_restart_interval_; |
93 | | // TODO(myabandeh): put it into a separate IndexBlockBuilder |
94 | | const bool use_delta_encoding_; |
95 | | // Refer to BlockIter::DecodeCurrentValue for format of delta encoded values |
96 | | const bool use_value_delta_encoding_; |
97 | | // Size in bytes for the user-defined timestamp to strip in a user key. |
98 | | // This is non-zero if there is user-defined timestamp in the user key and it |
99 | | // should not be persisted. |
100 | | const size_t strip_ts_sz_; |
101 | | // Whether the keys provided to build this block are user keys. If not, |
102 | | // the keys are internal keys. This will affect how timestamp stripping is |
103 | | // done for the key if `persisted_user_defined_timestamps_` is false and |
104 | | // `ts_sz_` is non-zero. |
105 | | // The timestamp stripping only applies to the keys added to the block. If the |
106 | | // value contains user defined timestamp that needed to be stripped too, such |
107 | | // as the `first_internal_key` in an `IndexValue` for an index block, the |
108 | | // value part for a range deletion entry, their timestamp should be stripped |
109 | | // before calling `BlockBuilder::Add`. |
110 | | // Timestamp stripping only applies to data block and index blocks including |
111 | | // index block for data blocks, index block for partitioned filter blocks, |
112 | | // index block for partitioned index blocks. In summary, this only applies to |
113 | | // block whose key are real user keys or internal keys created from user keys. |
114 | | const bool is_user_key_; |
115 | | |
116 | | std::string buffer_; // Destination buffer |
117 | | std::vector<uint32_t> restarts_; // Restart points |
118 | | size_t estimate_; |
119 | | int counter_; // Number of entries emitted since restart |
120 | | bool finished_; // Has Finish() been called? |
121 | | std::string last_key_; |
122 | | DataBlockHashIndexBuilder data_block_hash_index_builder_; |
123 | | #ifndef NDEBUG |
124 | | bool add_with_last_key_called_ = false; |
125 | | #endif |
126 | | }; |
127 | | |
128 | | } // namespace ROCKSDB_NAMESPACE |