/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/merge_helper.h
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | #ifndef YB_ROCKSDB_DB_MERGE_HELPER_H |
21 | | #define YB_ROCKSDB_DB_MERGE_HELPER_H |
22 | | |
23 | | #include <memory> |
24 | | #include <string> |
25 | | #include <vector> |
26 | | |
27 | | #include "yb/rocksdb/db/dbformat.h" |
28 | | #include "yb/rocksdb/db/version_edit.h" |
29 | | #include "yb/rocksdb/env.h" |
30 | | #include "yb/rocksdb/util/stop_watch.h" |
31 | | |
32 | | #include "yb/util/slice.h" |
33 | | |
34 | | namespace rocksdb { |
35 | | |
36 | | class Comparator; |
37 | | class Iterator; |
38 | | class Logger; |
39 | | class MergeOperator; |
40 | | class Statistics; |
41 | | class InternalIterator; |
42 | | |
43 | | class MergeHelper { |
44 | | public: |
45 | | MergeHelper(Env* env, const Comparator* user_comparator, |
46 | | const MergeOperator* user_merge_operator, |
47 | | const CompactionFilter* compaction_filter, Logger* logger, |
48 | | unsigned min_partial_merge_operands, |
49 | | bool assert_valid_internal_key, SequenceNumber latest_snapshot, |
50 | | int level = 0, Statistics* stats = nullptr) |
51 | | : env_(env), |
52 | | user_comparator_(user_comparator), |
53 | | user_merge_operator_(user_merge_operator), |
54 | | compaction_filter_(compaction_filter), |
55 | | logger_(logger), |
56 | | min_partial_merge_operands_(min_partial_merge_operands), |
57 | | assert_valid_internal_key_(assert_valid_internal_key), |
58 | | latest_snapshot_(latest_snapshot), |
59 | | level_(level), |
60 | | keys_(), |
61 | | operands_(), |
62 | | filter_timer_(env_), |
63 | 38.6k | stats_(stats) { |
64 | 38.6k | assert(user_comparator_ != nullptr); |
65 | 38.6k | } |
66 | | |
67 | | // Wrapper around MergeOperator::FullMerge() that records perf statistics. |
68 | | // Result of merge will be written to result if status returned is OK. |
69 | | // If operands is empty, the value will simply be copied to result. |
70 | | // Returns one of the following statuses: |
71 | | // - OK: Entries were successfully merged. |
72 | | // - Corruption: Merge operator reported unsuccessful merge. |
73 | | // - NotSupported: Merge operator is missing. |
74 | | static Status TimedFullMerge(const Slice& key, const Slice* value, |
75 | | const std::deque<std::string>& operands, |
76 | | const MergeOperator* merge_operator, |
77 | | Statistics* statistics, Env* env, Logger* logger, |
78 | | std::string* result); |
79 | | |
80 | | // Merge entries until we hit |
81 | | // - a corrupted key |
82 | | // - a Put/Delete, |
83 | | // - a different user key, |
84 | | // - a specific sequence number (snapshot boundary), |
85 | | // or - the end of iteration |
86 | | // iter: (IN) points to the first merge type entry |
87 | | // (OUT) points to the first entry not included in the merge process |
88 | | // stop_before: (IN) a sequence number that merge should not cross. |
89 | | // 0 means no restriction |
90 | | // at_bottom: (IN) true if the iterator covers the bottem level, which means |
91 | | // we could reach the start of the history of this user key. |
92 | | // |
93 | | // Returns one of the following statuses: |
94 | | // - OK: Entries were successfully merged. |
95 | | // - MergeInProgress: Put/Delete not encountered and unable to merge operands. |
96 | | // - Corruption: Merge operator reported unsuccessful merge or a corrupted |
97 | | // key has been encountered and not expected (applies only when compiling |
98 | | // with asserts removed). |
99 | | // |
100 | | // REQUIRED: The first key in the input is not corrupted. |
101 | | Status MergeUntil(InternalIterator* iter, |
102 | | const SequenceNumber stop_before = 0, |
103 | | const bool at_bottom = false); |
104 | | |
105 | | // Filters a merge operand using the compaction filter specified |
106 | | // in the constructor. Returns true if the operand should be filtered out. |
107 | | bool FilterMerge(const Slice& user_key, const Slice& value_slice); |
108 | | |
109 | | // Query the merge result |
110 | | // These are valid until the next MergeUntil call |
111 | | // If the merging was successful: |
112 | | // - keys() contains a single element with the latest sequence number of |
113 | | // the merges. The type will be Put or Merge. See IMPORTANT 1 note, below. |
114 | | // - values() contains a single element with the result of merging all the |
115 | | // operands together |
116 | | // |
117 | | // IMPORTANT 1: the key type could change after the MergeUntil call. |
118 | | // Put/Delete + Merge + ... + Merge => Put |
119 | | // Merge + ... + Merge => Merge |
120 | | // |
121 | | // If the merge operator is not associative, and if a Put/Delete is not found |
122 | | // then the merging will be unsuccessful. In this case: |
123 | | // - keys() contains the list of internal keys seen in order of iteration. |
124 | | // - values() contains the list of values (merges) seen in the same order. |
125 | | // values() is parallel to keys() so that the first entry in |
126 | | // keys() is the key associated with the first entry in values() |
127 | | // and so on. These lists will be the same length. |
128 | | // All of these pairs will be merges over the same user key. |
129 | | // See IMPORTANT 2 note below. |
130 | | // |
131 | | // IMPORTANT 2: The entries were traversed in order from BACK to FRONT. |
132 | | // So keys().back() was the first key seen by iterator. |
133 | | // TODO: Re-style this comment to be like the first one |
134 | 71.6M | const std::deque<std::string>& keys() const { return keys_; } |
135 | 170k | const std::deque<std::string>& values() const { return operands_; } |
136 | 263k | bool HasOperator() const { return user_merge_operator_ != nullptr; } |
137 | | |
138 | | private: |
139 | | Env* env_; |
140 | | const Comparator* user_comparator_; |
141 | | const MergeOperator* user_merge_operator_; |
142 | | const CompactionFilter* compaction_filter_; |
143 | | Logger* logger_; |
144 | | unsigned min_partial_merge_operands_; |
145 | | bool assert_valid_internal_key_; // enforce no internal key corruption? |
146 | | SequenceNumber latest_snapshot_; |
147 | | int level_; |
148 | | |
149 | | // the scratch area that holds the result of MergeUntil |
150 | | // valid up to the next MergeUntil call |
151 | | std::deque<std::string> keys_; // Keeps track of the sequence of keys seen |
152 | | std::deque<std::string> operands_; // Parallel with keys_; stores the values |
153 | | |
154 | | StopWatchNano filter_timer_; |
155 | | Statistics* stats_; |
156 | | }; |
157 | | |
158 | | // MergeOutputIterator can be used to iterate over the result of a merge. |
159 | | class MergeOutputIterator { |
160 | | public: |
161 | | // The MergeOutputIterator is bound to a MergeHelper instance. |
162 | | explicit MergeOutputIterator(const MergeHelper* merge_helper); |
163 | | |
164 | | // Seeks to the first record in the output. |
165 | | void SeekToFirst(); |
166 | | // Advances to the next record in the output. |
167 | | void Next(); |
168 | | |
169 | 290k | Slice key() { return Slice(*it_keys_); } |
170 | 290k | Slice value() { return Slice(*it_values_); } |
171 | 71.5M | bool Valid() { return it_keys_ != merge_helper_->keys().rend(); } |
172 | | |
173 | | private: |
174 | | const MergeHelper* merge_helper_; |
175 | | std::deque<std::string>::const_reverse_iterator it_keys_; |
176 | | std::deque<std::string>::const_reverse_iterator it_values_; |
177 | | }; |
178 | | |
179 | | } // namespace rocksdb |
180 | | |
181 | | #endif // YB_ROCKSDB_DB_MERGE_HELPER_H |