YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/rocksdb/compaction_filter.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
// Copyright (c) 2013 The LevelDB Authors. All rights reserved.
6
// Use of this source code is governed by a BSD-style license that can be
7
// found in the LICENSE file. See the AUTHORS file for names of contributors.
8
//
9
// The following only applies to changes made to this file as part of YugaByte development.
10
//
11
// Portions Copyright (c) YugaByte, Inc.
12
//
13
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
14
// in compliance with the License.  You may obtain a copy of the License at
15
//
16
// http://www.apache.org/licenses/LICENSE-2.0
17
//
18
// Unless required by applicable law or agreed to in writing, software distributed under the License
19
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
20
// or implied.  See the License for the specific language governing permissions and limitations
21
// under the License.
22
//
23
24
#ifndef YB_ROCKSDB_COMPACTION_FILTER_H
25
#define YB_ROCKSDB_COMPACTION_FILTER_H
26
27
#include <memory>
28
#include <string>
29
#include <vector>
30
31
#include "yb/util/slice.h"
32
#include "yb/rocksdb/metadata.h"
33
#include "yb/rocksdb/db/version_edit.h"
34
35
namespace rocksdb {
36
37
class SliceTransform;
38
39
// Context information of a compaction run
40
struct CompactionFilterContext {
41
  // Does this compaction run include all data files
42
  bool is_full_compaction;
43
  // Is this compaction requested by the client (true),
44
  // or is it occurring as an automatic compaction process
45
  bool is_manual_compaction;
46
};
47
48
// CompactionFilter allows an application to modify/delete a key-value at
49
// the time of compaction.
50
51
YB_DEFINE_ENUM(FilterDecision, (kKeep)(kDiscard));
52
53
class CompactionFilter {
54
 public:
55
  // Context information of a compaction run
56
  struct Context {
57
    // Does this compaction run include all data files
58
    bool is_full_compaction;
59
    // Is this compaction requested by the client (true),
60
    // or is it occurring as an automatic compaction process
61
    bool is_manual_compaction;
62
    // Which column family this compaction is for.
63
    uint32_t column_family_id;
64
  };
65
66
3.17k
  virtual ~CompactionFilter() {}
67
68
  // The compaction process invokes this
69
  // method for kv that is being compacted. A return value
70
  // of false indicates that the kv should be preserved in the
71
  // output of this compaction run and a return value of true
72
  // indicates that this key-value should be removed from the
73
  // output of the compaction.  The application can inspect
74
  // the existing value of the key and make decision based on it.
75
  //
76
  // Key-Values that are results of merge operation during compaction are not
77
  // passed into this function. Currently, when you have a mix of Put()s and
78
  // Merge()s on a same key, we only guarantee to process the merge operands
79
  // through the compaction filters. Put()s might be processed, or might not.
80
  //
81
  // When the value is to be preserved, the application has the option
82
  // to modify the existing_value and pass it back through new_value.
83
  // value_changed needs to be set to true in this case.
84
  //
85
  // If you use snapshot feature of RocksDB (i.e. call GetSnapshot() API on a
86
  // DB* object), CompactionFilter might not be very useful for you. Due to
87
  // guarantees we need to maintain, compaction process will not call Filter()
88
  // on any keys that were written before the latest snapshot. In other words,
89
  // compaction will only call Filter() on keys written after your most recent
90
  // call to GetSnapshot(). In most cases, Filter() will not be called very
91
  // often. This is something we're fixing. See the discussion at:
92
  // https://www.facebook.com/groups/mysqlonrocksdb/permalink/999723240091865/
93
  //
94
  // If multithreaded compaction is being used *and* a single CompactionFilter
95
  // instance was supplied via Options::compaction_filter, this method may be
96
  // called from different threads concurrently.  The application must ensure
97
  // that the call is thread-safe.
98
  //
99
  // If the CompactionFilter was created by a factory, then it will only ever
100
  // be used by a single thread that is doing the compaction run, and this
101
  // call does not need to be thread-safe.  However, multiple filters may be
102
  // in existence and operating concurrently.
103
  //
104
  // The last paragraph is not true if you set max_subcompactions to more than
105
  // 1. In that case, subcompaction from multiple threads may call a single
106
  // CompactionFilter concurrently.
107
  virtual FilterDecision Filter(int level,
108
                                const Slice& key,
109
                                const Slice& existing_value,
110
                                std::string* new_value,
111
                                bool* value_changed) = 0;
112
113
  // The compaction process invokes this method on every merge operand. If this
114
  // method returns true, the merge operand will be ignored and not written out
115
  // in the compaction output
116
  //
117
  // Note: If you are using a TransactionDB, it is not recommended to implement
118
  // FilterMergeOperand().  If a Merge operation is filtered out, TransactionDB
119
  // may not realize there is a write conflict and may allow a Transaction to
120
  // Commit that should have failed.  Instead, it is better to implement any
121
  // Merge filtering inside the MergeOperator.
122
  virtual bool FilterMergeOperand(int level, const Slice& key,
123
160k
                                  const Slice& operand) const {
124
160k
    return false;
125
160k
  }
126
127
3.07k
  virtual void CompactionFinished() {
128
3.07k
  }
129
130
  // By default, compaction will only call Filter() on keys written after the
131
  // most recent call to GetSnapshot(). However, if the compaction filter
132
  // overrides IgnoreSnapshots to make it return false, the compaction filter
133
  // will be called even if the keys were written before the last snapshot.
134
  // This behavior is to be used only when we want to delete a set of keys
135
  // irrespective of snapshots. In particular, care should be taken
136
  // to understand that the values of thesekeys will change even if we are
137
  // using a snapshot.
138
3.15k
  virtual bool IgnoreSnapshots() const { return false; }
139
140
  // Gives the compaction filter an opportunity to return a "user frontier" that will be used to
141
  // update the frontier stored in the version edit metadata when the compaction result is
142
  // installed.
143
  //
144
  // As a concrete use case, we use this to pass the history cutoff timestamp from the DocDB
145
  // compaction filter into the version edit metadata. See DocDBCompactionFilter.
146
2.06k
  virtual UserFrontierPtr GetLargestUserFrontier() const { return nullptr; }
147
148
  // Returns a name that identifies this compaction filter.
149
  // The name will be printed to LOG file on start up for diagnosis.
150
  virtual const char* Name() const = 0;
151
152
  // Returns a list of the ranges which should be considered "live" on this tablet. Returns an empty
153
  // list if the whole key range of the tablet should be considered live. Returned ranges are
154
  // represented as pairs of Slices denoting the beginning and end of the range in user space.
155
2.06k
  virtual std::vector<std::pair<Slice, Slice>> GetLiveRanges() const { return {}; }
156
};
157
158
// Each compaction will create a new CompactionFilter allowing the
159
// application to know about different compactions
160
class CompactionFilterFactory {
161
 public:
162
382k
  virtual ~CompactionFilterFactory() { }
163
164
  virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter(
165
      const CompactionFilter::Context& context) = 0;
166
167
  // Returns a name that identifies this compaction filter factory.
168
  virtual const char* Name() const = 0;
169
};
170
171
// Makes a decision about whether or not to exclude a file in a compaction based on whether
172
// or not the file has expired.  If expired, file will be removed at the end of compaction.
173
class CompactionFileFilter {
174
 public:
175
24
  virtual ~CompactionFileFilter() = default;
176
177
  // Determines whether to keep or discard a file based on the file's metadata.
178
  virtual FilterDecision Filter(const FileMetaData* file) = 0;
179
180
  // Returns a name that identifies this compaction filter.
181
  // The name will be printed to LOG file on start up for diagnosis.
182
  virtual const char* Name() const = 0;
183
};
184
185
// Each compaction will create a new CompactionFileFilter allowing each
186
// filter to have unique state when making expiration decisions.
187
class CompactionFileFilterFactory {
188
 public:
189
11
  virtual ~CompactionFileFilterFactory() { }
190
191
  // Creates a unique pointer to a new CompactionFileFilter.
192
  virtual std::unique_ptr<CompactionFileFilter> CreateCompactionFileFilter(
193
      const std::vector<FileMetaData*>& input_files) = 0;
194
195
  // Returns a name that identifies this compaction filter factory.
196
  virtual const char* Name() const = 0;
197
};
198
199
}  // namespace rocksdb
200
201
#endif // YB_ROCKSDB_COMPACTION_FILTER_H