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.
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
15 #include <unordered_set>
18 #include "db/compaction.h"
19 #include "db/version_set.h"
20 #include "options/cf_options.h"
21 #include "rocksdb/env.h"
22 #include "rocksdb/options.h"
23 #include "rocksdb/status.h"
29 class VersionStorageInfo
;
30 struct CompactionInputFiles
;
32 class CompactionPicker
{
34 CompactionPicker(const ImmutableCFOptions
& ioptions
,
35 const InternalKeyComparator
* icmp
);
36 virtual ~CompactionPicker();
38 // Pick level and inputs for a new compaction.
39 // Returns nullptr if there is no compaction to be done.
40 // Otherwise returns a pointer to a heap-allocated object that
41 // describes the compaction. Caller should delete the result.
42 virtual Compaction
* PickCompaction(const std::string
& cf_name
,
43 const MutableCFOptions
& mutable_cf_options
,
44 VersionStorageInfo
* vstorage
,
45 LogBuffer
* log_buffer
) = 0;
47 // Return a compaction object for compacting the range [begin,end] in
48 // the specified level. Returns nullptr if there is nothing in that
49 // level that overlaps the specified range. Caller should delete
52 // The returned Compaction might not include the whole requested range.
53 // In that case, compaction_end will be set to the next key that needs
54 // compacting. In case the compaction will compact the whole range,
55 // compaction_end will be set to nullptr.
56 // Client is responsible for compaction_end storage -- when called,
57 // *compaction_end should point to valid InternalKey!
58 virtual Compaction
* CompactRange(
59 const std::string
& cf_name
, const MutableCFOptions
& mutable_cf_options
,
60 VersionStorageInfo
* vstorage
, int input_level
, int output_level
,
61 uint32_t output_path_id
, const InternalKey
* begin
, const InternalKey
* end
,
62 InternalKey
** compaction_end
, bool* manual_conflict
);
64 // The maximum allowed output level. Default value is NumberLevels() - 1.
65 virtual int MaxOutputLevel() const { return NumberLevels() - 1; }
67 virtual bool NeedsCompaction(const VersionStorageInfo
* vstorage
) const = 0;
69 // Sanitize the input set of compaction input files.
70 // When the input parameters do not describe a valid compaction, the
71 // function will try to fix the input_files by adding necessary
72 // files. If it's not possible to conver an invalid input_files
73 // into a valid one by adding more files, the function will return a
74 // non-ok status with specific reason.
76 Status
SanitizeCompactionInputFiles(std::unordered_set
<uint64_t>* input_files
,
77 const ColumnFamilyMetaData
& cf_meta
,
78 const int output_level
) const;
79 #endif // ROCKSDB_LITE
81 // Free up the files that participated in a compaction
83 // Requirement: DB mutex held
84 void ReleaseCompactionFiles(Compaction
* c
, Status status
);
86 // Returns true if any one of the specified files are being compacted
87 bool AreFilesInCompaction(const std::vector
<FileMetaData
*>& files
);
89 // Takes a list of CompactionInputFiles and returns a (manual) Compaction
91 Compaction
* CompactFiles(const CompactionOptions
& compact_options
,
92 const std::vector
<CompactionInputFiles
>& input_files
,
93 int output_level
, VersionStorageInfo
* vstorage
,
94 const MutableCFOptions
& mutable_cf_options
,
95 uint32_t output_path_id
);
97 // Converts a set of compaction input file numbers into
98 // a list of CompactionInputFiles.
99 Status
GetCompactionInputsFromFileNumbers(
100 std::vector
<CompactionInputFiles
>* input_files
,
101 std::unordered_set
<uint64_t>* input_set
,
102 const VersionStorageInfo
* vstorage
,
103 const CompactionOptions
& compact_options
) const;
105 // Is there currently a compaction involving level 0 taking place
106 bool IsLevel0CompactionInProgress() const {
107 return !level0_compactions_in_progress_
.empty();
110 // Return true if the passed key range overlap with a compaction output
111 // that is currently running.
112 bool RangeOverlapWithCompaction(const Slice
& smallest_user_key
,
113 const Slice
& largest_user_key
,
116 // Stores the minimal range that covers all entries in inputs in
117 // *smallest, *largest.
118 // REQUIRES: inputs is not empty
119 void GetRange(const CompactionInputFiles
& inputs
, InternalKey
* smallest
,
120 InternalKey
* largest
) const;
122 // Stores the minimal range that covers all entries in inputs1 and inputs2
123 // in *smallest, *largest.
124 // REQUIRES: inputs is not empty
125 void GetRange(const CompactionInputFiles
& inputs1
,
126 const CompactionInputFiles
& inputs2
, InternalKey
* smallest
,
127 InternalKey
* largest
) const;
129 // Stores the minimal range that covers all entries in inputs
130 // in *smallest, *largest.
131 // REQUIRES: inputs is not empty (at least on entry have one file)
132 void GetRange(const std::vector
<CompactionInputFiles
>& inputs
,
133 InternalKey
* smallest
, InternalKey
* largest
) const;
135 int NumberLevels() const { return ioptions_
.num_levels
; }
137 // Add more files to the inputs on "level" to make sure that
138 // no newer version of a key is compacted to "level+1" while leaving an older
139 // version in a "level". Otherwise, any Get() will search "level" first,
140 // and will likely return an old/stale value for the key, since it always
141 // searches in increasing order of level to find the value. This could
142 // also scramble the order of merge operands. This function should be
143 // called any time a new Compaction is created, and its inputs_[0] are
146 // Will return false if it is impossible to apply this compaction.
147 bool ExpandInputsToCleanCut(const std::string
& cf_name
,
148 VersionStorageInfo
* vstorage
,
149 CompactionInputFiles
* inputs
);
151 // Returns true if any one of the parent files are being compacted
152 bool IsRangeInCompaction(VersionStorageInfo
* vstorage
,
153 const InternalKey
* smallest
,
154 const InternalKey
* largest
, int level
, int* index
);
156 // Returns true if the key range that `inputs` files cover overlap with the
157 // key range of a currently running compaction.
158 bool FilesRangeOverlapWithCompaction(
159 const std::vector
<CompactionInputFiles
>& inputs
, int level
) const;
161 bool SetupOtherInputs(const std::string
& cf_name
,
162 const MutableCFOptions
& mutable_cf_options
,
163 VersionStorageInfo
* vstorage
,
164 CompactionInputFiles
* inputs
,
165 CompactionInputFiles
* output_level_inputs
,
166 int* parent_index
, int base_index
);
168 void GetGrandparents(VersionStorageInfo
* vstorage
,
169 const CompactionInputFiles
& inputs
,
170 const CompactionInputFiles
& output_level_inputs
,
171 std::vector
<FileMetaData
*>* grandparents
);
173 // Register this compaction in the set of running compactions
174 void RegisterCompaction(Compaction
* c
);
176 // Remove this compaction from the set of running compactions
177 void UnregisterCompaction(Compaction
* c
);
179 std::set
<Compaction
*>* level0_compactions_in_progress() {
180 return &level0_compactions_in_progress_
;
182 std::unordered_set
<Compaction
*>* compactions_in_progress() {
183 return &compactions_in_progress_
;
187 const ImmutableCFOptions
& ioptions_
;
189 // A helper function to SanitizeCompactionInputFiles() that
190 // sanitizes "input_files" by adding necessary files.
192 virtual Status
SanitizeCompactionInputFilesForAllLevels(
193 std::unordered_set
<uint64_t>* input_files
,
194 const ColumnFamilyMetaData
& cf_meta
, const int output_level
) const;
195 #endif // ROCKSDB_LITE
197 // Keeps track of all compactions that are running on Level0.
198 // Protected by DB mutex
199 std::set
<Compaction
*> level0_compactions_in_progress_
;
201 // Keeps track of all compactions that are running.
202 // Protected by DB mutex
203 std::unordered_set
<Compaction
*> compactions_in_progress_
;
205 const InternalKeyComparator
* const icmp_
;
208 class LevelCompactionPicker
: public CompactionPicker
{
210 LevelCompactionPicker(const ImmutableCFOptions
& ioptions
,
211 const InternalKeyComparator
* icmp
)
212 : CompactionPicker(ioptions
, icmp
) {}
213 virtual Compaction
* PickCompaction(const std::string
& cf_name
,
214 const MutableCFOptions
& mutable_cf_options
,
215 VersionStorageInfo
* vstorage
,
216 LogBuffer
* log_buffer
) override
;
218 virtual bool NeedsCompaction(
219 const VersionStorageInfo
* vstorage
) const override
;
223 class FIFOCompactionPicker
: public CompactionPicker
{
225 FIFOCompactionPicker(const ImmutableCFOptions
& ioptions
,
226 const InternalKeyComparator
* icmp
)
227 : CompactionPicker(ioptions
, icmp
) {}
229 virtual Compaction
* PickCompaction(const std::string
& cf_name
,
230 const MutableCFOptions
& mutable_cf_options
,
231 VersionStorageInfo
* version
,
232 LogBuffer
* log_buffer
) override
;
234 virtual Compaction
* CompactRange(
235 const std::string
& cf_name
, const MutableCFOptions
& mutable_cf_options
,
236 VersionStorageInfo
* vstorage
, int input_level
, int output_level
,
237 uint32_t output_path_id
, const InternalKey
* begin
, const InternalKey
* end
,
238 InternalKey
** compaction_end
, bool* manual_conflict
) override
;
240 // The maximum allowed output level. Always returns 0.
241 virtual int MaxOutputLevel() const override
{ return 0; }
243 virtual bool NeedsCompaction(
244 const VersionStorageInfo
* vstorage
) const override
;
247 class NullCompactionPicker
: public CompactionPicker
{
249 NullCompactionPicker(const ImmutableCFOptions
& ioptions
,
250 const InternalKeyComparator
* icmp
)
251 : CompactionPicker(ioptions
, icmp
) {}
252 virtual ~NullCompactionPicker() {}
254 // Always return "nullptr"
255 Compaction
* PickCompaction(const std::string
& cf_name
,
256 const MutableCFOptions
& mutable_cf_options
,
257 VersionStorageInfo
* vstorage
,
258 LogBuffer
* log_buffer
) override
{
262 // Always return "nullptr"
263 Compaction
* CompactRange(const std::string
& cf_name
,
264 const MutableCFOptions
& mutable_cf_options
,
265 VersionStorageInfo
* vstorage
, int input_level
,
266 int output_level
, uint32_t output_path_id
,
267 const InternalKey
* begin
, const InternalKey
* end
,
268 InternalKey
** compaction_end
,
269 bool* manual_conflict
) override
{
273 // Always returns false.
274 virtual bool NeedsCompaction(
275 const VersionStorageInfo
* vstorage
) const override
{
279 #endif // !ROCKSDB_LITE
281 CompressionType
GetCompressionType(const ImmutableCFOptions
& ioptions
,
282 const VersionStorageInfo
* vstorage
,
283 const MutableCFOptions
& mutable_cf_options
,
284 int level
, int base_level
,
285 const bool enable_compression
= true);
287 } // namespace rocksdb