YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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