merge_helper.h 6.7 KB
Newer Older
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 3 4 5
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
6 7 8
#ifndef MERGE_HELPER_H
#define MERGE_HELPER_H

9
#include <deque>
10 11 12
#include <string>

#include "db/dbformat.h"
I
Igor Canadi 已提交
13
#include "rocksdb/compaction_filter.h"
14
#include "rocksdb/env.h"
15
#include "rocksdb/slice.h"
I
Igor Canadi 已提交
16
#include "util/stop_watch.h"
17

18
namespace rocksdb {
19 20 21 22 23

class Comparator;
class Iterator;
class Logger;
class MergeOperator;
24
class Statistics;
S
sdong 已提交
25
class InternalIterator;
26 27 28

class MergeHelper {
 public:
I
Igor Canadi 已提交
29 30 31
  MergeHelper(Env* env, const Comparator* user_comparator,
              const MergeOperator* user_merge_operator,
              const CompactionFilter* compaction_filter, Logger* logger,
32
              unsigned min_partial_merge_operands,
I
Igor Canadi 已提交
33 34 35 36
              bool assert_valid_internal_key, SequenceNumber latest_snapshot,
              int level = 0, Statistics* stats = nullptr)
      : env_(env),
        user_comparator_(user_comparator),
37
        user_merge_operator_(user_merge_operator),
I
Igor Canadi 已提交
38
        compaction_filter_(compaction_filter),
39
        logger_(logger),
40
        min_partial_merge_operands_(min_partial_merge_operands),
41
        assert_valid_internal_key_(assert_valid_internal_key),
I
Igor Canadi 已提交
42 43
        latest_snapshot_(latest_snapshot),
        level_(level),
44
        keys_(),
I
Igor Canadi 已提交
45 46 47 48
        operands_(),
        filter_timer_(env_),
        total_filter_time_(0U),
        stats_(stats) {
49 50
    assert(user_comparator_ != nullptr);
  }
51

A
agiardullo 已提交
52 53 54
  // Wrapper around MergeOperator::FullMerge() that records perf statistics.
  // Result of merge will be written to result if status returned is OK.
  // If operands is empty, the value will simply be copied to result.
55 56 57
  // Returns one of the following statuses:
  // - OK: Entries were successfully merged.
  // - Corruption: Merge operator reported unsuccessful merge.
58 59
  static Status TimedFullMerge(const MergeOperator* merge_operator,
                               const Slice& key, const Slice* value,
A
agiardullo 已提交
60
                               const std::deque<std::string>& operands,
61 62
                               std::string* result, Logger* logger,
                               Statistics* statistics, Env* env);
A
agiardullo 已提交
63

64 65 66 67 68 69 70 71 72 73 74 75
  // Merge entries until we hit
  //     - a corrupted key
  //     - a Put/Delete,
  //     - a different user key,
  //     - a specific sequence number (snapshot boundary),
  //  or - the end of iteration
  // iter: (IN)  points to the first merge type entry
  //       (OUT) points to the first entry not included in the merge process
  // stop_before: (IN) a sequence number that merge should not cross.
  //                   0 means no restriction
  // at_bottom:   (IN) true if the iterator covers the bottem level, which means
  //                   we could reach the start of the history of this user key.
I
Igor Canadi 已提交
76
  //
77 78 79
  // Returns one of the following statuses:
  // - OK: Entries were successfully merged.
  // - MergeInProgress: Put/Delete not encountered and unable to merge operands.
A
Andres Noetzli 已提交
80 81 82
  // - Corruption: Merge operator reported unsuccessful merge or a corrupted
  //   key has been encountered and not expected (applies only when compiling
  //   with asserts removed).
83 84
  //
  // REQUIRED: The first key in the input is not corrupted.
S
sdong 已提交
85 86
  Status MergeUntil(InternalIterator* iter,
                    const SequenceNumber stop_before = 0,
I
Igor Canadi 已提交
87 88 89 90 91
                    const bool at_bottom = false);

  // Filters a merge operand using the compaction filter specified
  // in the constructor. Returns true if the operand should be filtered out.
  bool FilterMerge(const Slice& user_key, const Slice& value_slice);
92 93

  // Query the merge result
94 95
  // These are valid until the next MergeUntil call
  // If the merging was successful:
96 97 98 99
  //   - keys() contains a single element with the latest sequence number of
  //     the merges. The type will be Put or Merge. See IMPORTANT 1 note, below.
  //   - values() contains a single element with the result of merging all the
  //     operands together
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
  //
  //   IMPORTANT 1: the key type could change after the MergeUntil call.
  //        Put/Delete + Merge + ... + Merge => Put
  //        Merge + ... + Merge => Merge
  //
  // If the merge operator is not associative, and if a Put/Delete is not found
  // then the merging will be unsuccessful. In this case:
  //   - keys() contains the list of internal keys seen in order of iteration.
  //   - values() contains the list of values (merges) seen in the same order.
  //              values() is parallel to keys() so that the first entry in
  //              keys() is the key associated with the first entry in values()
  //              and so on. These lists will be the same length.
  //              All of these pairs will be merges over the same user key.
  //              See IMPORTANT 2 note below.
  //
  //   IMPORTANT 2: The entries were traversed in order from BACK to FRONT.
  //                So keys().back() was the first key seen by iterator.
  // TODO: Re-style this comment to be like the first one
118 119
  const std::deque<std::string>& keys() const { return keys_; }
  const std::deque<std::string>& values() const { return operands_; }
I
Igor Canadi 已提交
120
  uint64_t TotalFilterTime() const { return total_filter_time_; }
121
  bool HasOperator() const { return user_merge_operator_ != nullptr; }
122 123

 private:
I
Igor Canadi 已提交
124
  Env* env_;
125 126
  const Comparator* user_comparator_;
  const MergeOperator* user_merge_operator_;
I
Igor Canadi 已提交
127
  const CompactionFilter* compaction_filter_;
128
  Logger* logger_;
129
  unsigned min_partial_merge_operands_;
130
  bool assert_valid_internal_key_; // enforce no internal key corruption?
I
Igor Canadi 已提交
131 132
  SequenceNumber latest_snapshot_;
  int level_;
133 134 135

  // the scratch area that holds the result of MergeUntil
  // valid up to the next MergeUntil call
136 137
  std::deque<std::string> keys_;    // Keeps track of the sequence of keys seen
  std::deque<std::string> operands_;  // Parallel with keys_; stores the values
I
Igor Canadi 已提交
138 139 140 141

  StopWatchNano filter_timer_;
  uint64_t total_filter_time_;
  Statistics* stats_;
142 143
};

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
// MergeOutputIterator can be used to iterate over the result of a merge.
class MergeOutputIterator {
 public:
  // The MergeOutputIterator is bound to a MergeHelper instance.
  explicit MergeOutputIterator(const MergeHelper* merge_helper);

  // Seeks to the first record in the output.
  void SeekToFirst();
  // Advances to the next record in the output.
  void Next();

  Slice key() { return Slice(*it_keys_); }
  Slice value() { return Slice(*it_values_); }
  bool Valid() { return it_keys_ != merge_helper_->keys().rend(); }

 private:
  const MergeHelper* merge_helper_;
  std::deque<std::string>::const_reverse_iterator it_keys_;
  std::deque<std::string>::const_reverse_iterator it_values_;
};

165
} // namespace rocksdb
166 167

#endif