YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/compaction_picker.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 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
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
24
#ifndef YB_ROCKSDB_DB_COMPACTION_PICKER_H
25
#define YB_ROCKSDB_DB_COMPACTION_PICKER_H
26
27
#pragma once
28
29
#include <memory>
30
#include <set>
31
#include <string>
32
#include <unordered_set>
33
#include <vector>
34
35
#include "yb/rocksdb/db/compaction.h"
36
#include "yb/rocksdb/env.h"
37
#include "yb/rocksdb/options.h"
38
#include "yb/rocksdb/status.h"
39
#include "yb/rocksdb/util/mutable_cf_options.h"
40
41
42
namespace rocksdb {
43
44
class LogBuffer;
45
class Compaction;
46
class VersionStorageInfo;
47
struct CompactionInputFiles;
48
49
class CompactionPicker {
50
 public:
51
  CompactionPicker(const ImmutableCFOptions& ioptions,
52
                   const InternalKeyComparator* icmp);
53
  virtual ~CompactionPicker();
54
55
  // Pick level and inputs for a new compaction.
56
  // Returns nullptr if there is no compaction to be done.
57
  // Otherwise returns a pointer to a heap-allocated object that
58
  // describes the compaction.  Caller should delete the result.
59
  virtual std::unique_ptr<Compaction> PickCompaction(
60
      const std::string& cf_name,
61
      const MutableCFOptions& mutable_cf_options,
62
      VersionStorageInfo* vstorage,
63
      LogBuffer* log_buffer) = 0;
64
65
  // Return a compaction object for compacting the range [begin,end] in
66
  // the specified level.  Returns nullptr if there is nothing in that
67
  // level that overlaps the specified range.  Caller should delete
68
  // the result.
69
  //
70
  // The returned Compaction might not include the whole requested range.
71
  // In that case, compaction_end will be set to the next key that needs
72
  // compacting. In case the compaction will compact the whole range,
73
  // compaction_end will be set to nullptr.
74
  // Client is responsible for compaction_end storage -- when called,
75
  // *compaction_end should point to valid InternalKey!
76
  virtual std::unique_ptr<Compaction> CompactRange(
77
      const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
78
      VersionStorageInfo* vstorage, int input_level, int output_level,
79
      uint32_t output_path_id, const InternalKey* begin, const InternalKey* end,
80
      InternalKey** compaction_end, bool* manual_conflict);
81
82
  // The maximum allowed output level.  Default value is NumberLevels() - 1.
83
3
  virtual int MaxOutputLevel() const {
84
3
    return NumberLevels() - 1;
85
3
  }
86
87
  virtual bool NeedsCompaction(const VersionStorageInfo* vstorage) const = 0;
88
89
  // Sanitize the input set of compaction input files.
90
  // When the input parameters do not describe a valid compaction, the
91
  // function will try to fix the input_files by adding necessary
92
  // files.  If it's not possible to conver an invalid input_files
93
  // into a valid one by adding more files, the function will return a
94
  // non-ok status with specific reason.
95
#ifndef ROCKSDB_LITE
96
  Status SanitizeCompactionInputFiles(
97
      std::unordered_set<uint64_t>* input_files,
98
      const ColumnFamilyMetaData& cf_meta,
99
      const int output_level) const;
100
#endif  // ROCKSDB_LITE
101
102
  // Free up the files that participated in a compaction
103
  //
104
  // Requirement: DB mutex held
105
  void ReleaseCompactionFiles(Compaction* c, Status status);
106
107
  // Returns true if any one of the specified files are being compacted
108
  bool FilesInCompaction(const std::vector<FileMetaData*>& files);
109
110
  // Takes a list of CompactionInputFiles and returns a (manual) Compaction
111
  // object.
112
  std::unique_ptr<Compaction> FormCompaction(
113
      const CompactionOptions& compact_options,
114
      const std::vector<CompactionInputFiles>& input_files, int output_level,
115
      VersionStorageInfo* vstorage, const MutableCFOptions& mutable_cf_options,
116
      uint32_t output_path_id) const;
117
118
  // Converts a set of compaction input file numbers into
119
  // a list of CompactionInputFiles.
120
  Status GetCompactionInputsFromFileNumbers(
121
      std::vector<CompactionInputFiles>* input_files,
122
      std::unordered_set<uint64_t>* input_set,
123
      const VersionStorageInfo* vstorage,
124
      const CompactionOptions& compact_options) const;
125
126
  // Used in universal compaction when the enabled_trivial_move
127
  // option is set. Checks whether there are any overlapping files
128
  // in the input. Returns true if the input files are non
129
  // overlapping.
130
  bool IsInputNonOverlapping(Compaction* c);
131
132
  // Is there currently a compaction involving level 0 taking place
133
1.53k
  bool IsLevel0CompactionInProgress() const {
134
1.53k
    return !level0_compactions_in_progress_.empty();
135
1.53k
  }
136
137
 protected:
138
94.2k
  int NumberLevels() const { return ioptions_.num_levels; }
139
140
  // Stores the minimal range that covers all entries in inputs in
141
  // *smallest, *largest.
142
  // REQUIRES: inputs is not empty
143
  void GetRange(const CompactionInputFiles& inputs,
144
                InternalKey* smallest,
145
                InternalKey* largest);
146
147
  // Stores the minimal range that covers all entries in inputs1 and inputs2
148
  // in *smallest, *largest.
149
  // REQUIRES: inputs is not empty
150
  void GetRange(const CompactionInputFiles& inputs1,
151
                const CompactionInputFiles& inputs2,
152
                InternalKey* smallest,
153
                InternalKey* largest);
154
155
  // Add more files to the inputs on "level" to make sure that
156
  // no newer version of a key is compacted to "level+1" while leaving an older
157
  // version in a "level". Otherwise, any Get() will search "level" first,
158
  // and will likely return an old/stale value for the key, since it always
159
  // searches in increasing order of level to find the value. This could
160
  // also scramble the order of merge operands. This function should be
161
  // called any time a new Compaction is created, and its inputs_[0] are
162
  // populated.
163
  //
164
  // Will return false if it is impossible to apply this compaction.
165
  bool ExpandWhileOverlapping(const std::string& cf_name,
166
                              VersionStorageInfo* vstorage,
167
                              CompactionInputFiles* inputs);
168
169
  // Returns true if any one of the parent files are being compacted
170
  bool RangeInCompaction(VersionStorageInfo* vstorage,
171
                         const InternalKey* smallest,
172
                         const InternalKey* largest,
173
                         int level,
174
                         int* index);
175
176
  bool SetupOtherInputs(const std::string& cf_name,
177
                        const MutableCFOptions& mutable_cf_options,
178
                        VersionStorageInfo* vstorage,
179
                        CompactionInputFiles* inputs,
180
                        CompactionInputFiles* output_level_inputs,
181
                        int* parent_index, int base_index);
182
183
  void GetGrandparents(VersionStorageInfo* vstorage,
184
                       const CompactionInputFiles& inputs,
185
                       const CompactionInputFiles& output_level_inputs,
186
                       std::vector<FileMetaData*>* grandparents);
187
188
  static void MarkL0FilesForDeletion(const VersionStorageInfo* vstorage,
189
                                     const ImmutableCFOptions* ioptions);
190
191
  const ImmutableCFOptions& ioptions_;
192
193
  // A helper function to SanitizeCompactionInputFiles() that
194
  // sanitizes "input_files" by adding necessary files.
195
#ifndef ROCKSDB_LITE
196
  virtual Status SanitizeCompactionInputFilesForAllLevels(
197
      std::unordered_set<uint64_t>* input_files,
198
      const ColumnFamilyMetaData& cf_meta,
199
      const int output_level) const;
200
#endif  // ROCKSDB_LITE
201
202
  // Keeps track of all compactions that are running on Level0.
203
  // It is protected by DB mutex
204
  std::set<Compaction*> level0_compactions_in_progress_;
205
206
  const InternalKeyComparator* const icmp_;
207
};
208
209
class LevelCompactionPicker : public CompactionPicker {
210
 public:
211
  LevelCompactionPicker(const ImmutableCFOptions& ioptions,
212
                        const InternalKeyComparator* icmp)
213
15.7k
      : CompactionPicker(ioptions, icmp) {}
214
215
  std::unique_ptr<Compaction> PickCompaction(
216
      const std::string& cf_name,
217
      const MutableCFOptions& mutable_cf_options,
218
      VersionStorageInfo* vstorage,
219
      LogBuffer* log_buffer) override;
220
221
  virtual bool NeedsCompaction(const VersionStorageInfo* vstorage) const
222
      override;
223
224
  // Pick a path ID to place a newly generated file, with its level
225
  static uint32_t GetPathId(const ImmutableCFOptions& ioptions,
226
                            const MutableCFOptions& mutable_cf_options,
227
                            int level);
228
229
 private:
230
  // For the specfied level, pick a file that we want to compact.
231
  // Returns false if there is no file to compact.
232
  // If it returns true, inputs->files.size() will be exactly one.
233
  // If level is 0 and there is already a compaction on that level, this
234
  // function will return false.
235
  bool PickCompactionBySize(VersionStorageInfo* vstorage, int level,
236
                            int output_level, CompactionInputFiles* inputs,
237
                            int* parent_index, int* base_index);
238
239
  // If there is any file marked for compaction, put put it into inputs.
240
  // This is still experimental. It will return meaningful results only if
241
  // clients call experimental feature SuggestCompactRange()
242
  void PickFilesMarkedForCompactionExperimental(const std::string& cf_name,
243
                                                VersionStorageInfo* vstorage,
244
                                                CompactionInputFiles* inputs,
245
                                                int* level, int* output_level);
246
};
247
248
#ifndef ROCKSDB_LITE
249
class UniversalCompactionPicker : public CompactionPicker {
250
 public:
251
  UniversalCompactionPicker(const ImmutableCFOptions& ioptions,
252
                            const InternalKeyComparator* icmp)
253
331k
      : CompactionPicker(ioptions, icmp) {}
254
255
  std::unique_ptr<Compaction> PickCompaction(
256
      const std::string& cf_name,
257
      const MutableCFOptions& mutable_cf_options,
258
      VersionStorageInfo* vstorage,
259
      LogBuffer* log_buffer) override;
260
261
12
  virtual int MaxOutputLevel() const override { return NumberLevels() - 1; }
262
263
  virtual bool NeedsCompaction(const VersionStorageInfo* vstorage) const
264
      override;
265
266
 private:
267
  struct SortedRun;
268
269
  std::unique_ptr<Compaction> DoPickCompaction(
270
      const std::string& cf_name,
271
      const MutableCFOptions& mutable_cf_options,
272
      VersionStorageInfo* vstorage,
273
      LogBuffer* log_buffer,
274
      const std::vector<SortedRun>& sorted_runs);
275
276
  // Pick Universal compaction to limit read amplification
277
  std::unique_ptr<Compaction> PickCompactionUniversalReadAmp(
278
      const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
279
      VersionStorageInfo* vstorage, double score, unsigned int ratio,
280
      unsigned int num_files, size_t always_include_threshold,
281
      const std::vector<SortedRun>& sorted_runs, LogBuffer* log_buffer);
282
283
  // Pick Universal compaction to limit space amplification.
284
  std::unique_ptr<Compaction> PickCompactionUniversalSizeAmp(
285
      const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
286
      VersionStorageInfo* vstorage, double score,
287
      const std::vector<SortedRun>& sorted_runs, LogBuffer* log_buffer);
288
289
  // Pick Universal compaction to directly delete files that are no longer needed.
290
  std::unique_ptr<Compaction> PickCompactionUniversalDeletion(
291
      const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
292
      VersionStorageInfo* vstorage, double score,
293
      const std::vector<SortedRun>& sorted_runs, LogBuffer* log_buffer);
294
295
  // At level 0 we could compact only continuous sequence of files.
296
  // Since there could be too-large-to-compact files, we could get several such sequences.
297
  // Files from one sequence are compacted together, and files from different sequences are not
298
  // compacted.
299
  // One sequence is std::vector<SortedRun>.
300
  // Several sequences are std::vector<std::vector<SortedRun>>.
301
  static std::vector<std::vector<SortedRun>> CalculateSortedRuns(
302
      const VersionStorageInfo& vstorage,
303
      const ImmutableCFOptions& ioptions,
304
      uint64_t max_file_size);
305
306
  // Pick a path ID to place a newly generated file, with its estimated file
307
  // size.
308
  static uint32_t GetPathId(const ImmutableCFOptions& ioptions,
309
                            uint64_t file_size);
310
};
311
312
class FIFOCompactionPicker : public CompactionPicker {
313
 public:
314
  FIFOCompactionPicker(const ImmutableCFOptions& ioptions,
315
                       const InternalKeyComparator* icmp)
316
290
      : CompactionPicker(ioptions, icmp) {}
317
318
  std::unique_ptr<Compaction> PickCompaction(
319
      const std::string& cf_name,
320
      const MutableCFOptions& mutable_cf_options,
321
      VersionStorageInfo* version,
322
      LogBuffer* log_buffer) override;
323
324
  std::unique_ptr<Compaction> CompactRange(
325
      const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
326
      VersionStorageInfo* vstorage, int input_level, int output_level,
327
      uint32_t output_path_id, const InternalKey* begin, const InternalKey* end,
328
      InternalKey** compaction_end, bool* manual_conflict) override;
329
330
  // The maximum allowed output level.  Always returns 0.
331
0
  virtual int MaxOutputLevel() const override {
332
0
    return 0;
333
0
  }
334
335
  virtual bool NeedsCompaction(const VersionStorageInfo* vstorage) const
336
      override;
337
};
338
339
class NullCompactionPicker : public CompactionPicker {
340
 public:
341
  NullCompactionPicker(const ImmutableCFOptions& ioptions,
342
                       const InternalKeyComparator* icmp) :
343
150
      CompactionPicker(ioptions, icmp) {}
344
146
  virtual ~NullCompactionPicker() {}
345
346
  // Always return "nullptr"
347
  std::unique_ptr<Compaction> PickCompaction(
348
      const std::string& cf_name,
349
      const MutableCFOptions& mutable_cf_options,
350
      VersionStorageInfo* vstorage,
351
0
      LogBuffer* log_buffer) override {
352
0
    return nullptr;
353
0
  }
354
355
  // Always return "nullptr"
356
  std::unique_ptr<Compaction> CompactRange(
357
      const std::string& cf_name,
358
      const MutableCFOptions& mutable_cf_options,
359
      VersionStorageInfo* vstorage, int input_level,
360
      int output_level, uint32_t output_path_id,
361
      const InternalKey* begin, const InternalKey* end,
362
      InternalKey** compaction_end,
363
0
      bool* manual_conflict) override {
364
0
    return nullptr;
365
0
  }
366
367
  // Always returns false.
368
  virtual bool NeedsCompaction(const VersionStorageInfo* vstorage) const
369
302
      override {
370
302
    return false;
371
302
  }
372
};
373
#endif  // !ROCKSDB_LITE
374
375
// Test whether two files have overlapping key-ranges.
376
bool HaveOverlappingKeyRanges(const Comparator* c,
377
                              const SstFileMetaData& a,
378
                              const SstFileMetaData& b);
379
380
CompressionType GetCompressionType(const ImmutableCFOptions& ioptions,
381
                                   int level, int base_level,
382
                                   const bool enable_compression = true);
383
384
}  // namespace rocksdb
385
386
#endif // YB_ROCKSDB_DB_COMPACTION_PICKER_H