compaction_picker.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  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.
  9. #pragma once
  10. #include <memory>
  11. #include <set>
  12. #include <string>
  13. #include <unordered_set>
  14. #include <vector>
  15. #include "db/compaction/compaction.h"
  16. #include "db/version_set.h"
  17. #include "options/cf_options.h"
  18. #include "rocksdb/env.h"
  19. #include "rocksdb/options.h"
  20. #include "rocksdb/status.h"
  21. namespace ROCKSDB_NAMESPACE {
  22. // The file contains an abstract class CompactionPicker, and its two
  23. // sub-classes LevelCompactionPicker and NullCompactionPicker, as
  24. // well as some helper functions used by them.
  25. class LogBuffer;
  26. class Compaction;
  27. class VersionStorageInfo;
  28. struct CompactionInputFiles;
  29. // An abstract class to pick compactions from an existing LSM-tree.
  30. //
  31. // Each compaction style inherits the class and implement the
  32. // interface to form automatic compactions. If NeedCompaction() is true,
  33. // then call PickCompaction() to find what files need to be compacted
  34. // and where to put the output files.
  35. //
  36. // Non-virtual functions CompactRange() and CompactFiles() are used to
  37. // pick files to compact based on users' DB::CompactRange() and
  38. // DB::CompactFiles() requests, respectively. There is little
  39. // compaction style specific logic for them.
  40. class CompactionPicker {
  41. public:
  42. CompactionPicker(const ImmutableCFOptions& ioptions,
  43. const InternalKeyComparator* icmp);
  44. virtual ~CompactionPicker();
  45. // Pick level and inputs for a new compaction.
  46. // Returns nullptr if there is no compaction to be done.
  47. // Otherwise returns a pointer to a heap-allocated object that
  48. // describes the compaction. Caller should delete the result.
  49. virtual Compaction* PickCompaction(
  50. const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
  51. VersionStorageInfo* vstorage, LogBuffer* log_buffer,
  52. SequenceNumber earliest_memtable_seqno = kMaxSequenceNumber) = 0;
  53. // Return a compaction object for compacting the range [begin,end] in
  54. // the specified level. Returns nullptr if there is nothing in that
  55. // level that overlaps the specified range. Caller should delete
  56. // the result.
  57. //
  58. // The returned Compaction might not include the whole requested range.
  59. // In that case, compaction_end will be set to the next key that needs
  60. // compacting. In case the compaction will compact the whole range,
  61. // compaction_end will be set to nullptr.
  62. // Client is responsible for compaction_end storage -- when called,
  63. // *compaction_end should point to valid InternalKey!
  64. virtual Compaction* CompactRange(
  65. const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
  66. VersionStorageInfo* vstorage, int input_level, int output_level,
  67. const CompactRangeOptions& compact_range_options,
  68. const InternalKey* begin, const InternalKey* end,
  69. InternalKey** compaction_end, bool* manual_conflict,
  70. uint64_t max_file_num_to_ignore);
  71. // The maximum allowed output level. Default value is NumberLevels() - 1.
  72. virtual int MaxOutputLevel() const { return NumberLevels() - 1; }
  73. virtual bool NeedsCompaction(const VersionStorageInfo* vstorage) const = 0;
  74. // Sanitize the input set of compaction input files.
  75. // When the input parameters do not describe a valid compaction, the
  76. // function will try to fix the input_files by adding necessary
  77. // files. If it's not possible to conver an invalid input_files
  78. // into a valid one by adding more files, the function will return a
  79. // non-ok status with specific reason.
  80. #ifndef ROCKSDB_LITE
  81. Status SanitizeCompactionInputFiles(std::unordered_set<uint64_t>* input_files,
  82. const ColumnFamilyMetaData& cf_meta,
  83. const int output_level) const;
  84. #endif // ROCKSDB_LITE
  85. // Free up the files that participated in a compaction
  86. //
  87. // Requirement: DB mutex held
  88. void ReleaseCompactionFiles(Compaction* c, Status status);
  89. // Returns true if any one of the specified files are being compacted
  90. bool AreFilesInCompaction(const std::vector<FileMetaData*>& files);
  91. // Takes a list of CompactionInputFiles and returns a (manual) Compaction
  92. // object.
  93. //
  94. // Caller must provide a set of input files that has been passed through
  95. // `SanitizeCompactionInputFiles` earlier. The lock should not be released
  96. // between that call and this one.
  97. Compaction* CompactFiles(const CompactionOptions& compact_options,
  98. const std::vector<CompactionInputFiles>& input_files,
  99. int output_level, VersionStorageInfo* vstorage,
  100. const MutableCFOptions& mutable_cf_options,
  101. uint32_t output_path_id);
  102. // Converts a set of compaction input file numbers into
  103. // a list of CompactionInputFiles.
  104. Status GetCompactionInputsFromFileNumbers(
  105. std::vector<CompactionInputFiles>* input_files,
  106. std::unordered_set<uint64_t>* input_set,
  107. const VersionStorageInfo* vstorage,
  108. const CompactionOptions& compact_options) const;
  109. // Is there currently a compaction involving level 0 taking place
  110. bool IsLevel0CompactionInProgress() const {
  111. return !level0_compactions_in_progress_.empty();
  112. }
  113. // Return true if the passed key range overlap with a compaction output
  114. // that is currently running.
  115. bool RangeOverlapWithCompaction(const Slice& smallest_user_key,
  116. const Slice& largest_user_key,
  117. int level) const;
  118. // Stores the minimal range that covers all entries in inputs in
  119. // *smallest, *largest.
  120. // REQUIRES: inputs is not empty
  121. void GetRange(const CompactionInputFiles& inputs, InternalKey* smallest,
  122. InternalKey* largest) const;
  123. // Stores the minimal range that covers all entries in inputs1 and inputs2
  124. // in *smallest, *largest.
  125. // REQUIRES: inputs is not empty
  126. void GetRange(const CompactionInputFiles& inputs1,
  127. const CompactionInputFiles& inputs2, InternalKey* smallest,
  128. 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;
  134. int NumberLevels() const { return ioptions_.num_levels; }
  135. // Add more files to the inputs on "level" to make sure that
  136. // no newer version of a key is compacted to "level+1" while leaving an older
  137. // version in a "level". Otherwise, any Get() will search "level" first,
  138. // and will likely return an old/stale value for the key, since it always
  139. // searches in increasing order of level to find the value. This could
  140. // also scramble the order of merge operands. This function should be
  141. // called any time a new Compaction is created, and its inputs_[0] are
  142. // populated.
  143. //
  144. // Will return false if it is impossible to apply this compaction.
  145. bool ExpandInputsToCleanCut(const std::string& cf_name,
  146. VersionStorageInfo* vstorage,
  147. CompactionInputFiles* inputs,
  148. InternalKey** next_smallest = nullptr);
  149. // Returns true if any one of the parent files are being compacted
  150. bool IsRangeInCompaction(VersionStorageInfo* vstorage,
  151. const InternalKey* smallest,
  152. const InternalKey* largest, int level, int* index);
  153. // Returns true if the key range that `inputs` files cover overlap with the
  154. // key range of a currently running compaction.
  155. bool FilesRangeOverlapWithCompaction(
  156. const std::vector<CompactionInputFiles>& inputs, int level) const;
  157. bool SetupOtherInputs(const std::string& cf_name,
  158. const MutableCFOptions& mutable_cf_options,
  159. VersionStorageInfo* vstorage,
  160. CompactionInputFiles* inputs,
  161. CompactionInputFiles* output_level_inputs,
  162. int* parent_index, int base_index);
  163. void GetGrandparents(VersionStorageInfo* vstorage,
  164. const CompactionInputFiles& inputs,
  165. const CompactionInputFiles& output_level_inputs,
  166. std::vector<FileMetaData*>* grandparents);
  167. void PickFilesMarkedForCompaction(const std::string& cf_name,
  168. VersionStorageInfo* vstorage,
  169. int* start_level, int* output_level,
  170. CompactionInputFiles* start_level_inputs);
  171. bool GetOverlappingL0Files(VersionStorageInfo* vstorage,
  172. CompactionInputFiles* start_level_inputs,
  173. int output_level, int* parent_index);
  174. // Register this compaction in the set of running compactions
  175. void RegisterCompaction(Compaction* c);
  176. // Remove this compaction from the set of running compactions
  177. void UnregisterCompaction(Compaction* c);
  178. std::set<Compaction*>* level0_compactions_in_progress() {
  179. return &level0_compactions_in_progress_;
  180. }
  181. std::unordered_set<Compaction*>* compactions_in_progress() {
  182. return &compactions_in_progress_;
  183. }
  184. protected:
  185. const ImmutableCFOptions& ioptions_;
  186. // A helper function to SanitizeCompactionInputFiles() that
  187. // sanitizes "input_files" by adding necessary files.
  188. #ifndef ROCKSDB_LITE
  189. virtual Status SanitizeCompactionInputFilesForAllLevels(
  190. std::unordered_set<uint64_t>* input_files,
  191. const ColumnFamilyMetaData& cf_meta, const int output_level) const;
  192. #endif // ROCKSDB_LITE
  193. // Keeps track of all compactions that are running on Level0.
  194. // Protected by DB mutex
  195. std::set<Compaction*> level0_compactions_in_progress_;
  196. // Keeps track of all compactions that are running.
  197. // Protected by DB mutex
  198. std::unordered_set<Compaction*> compactions_in_progress_;
  199. const InternalKeyComparator* const icmp_;
  200. };
  201. #ifndef ROCKSDB_LITE
  202. // A dummy compaction that never triggers any automatic
  203. // compaction.
  204. class NullCompactionPicker : public CompactionPicker {
  205. public:
  206. NullCompactionPicker(const ImmutableCFOptions& ioptions,
  207. const InternalKeyComparator* icmp)
  208. : CompactionPicker(ioptions, icmp) {}
  209. virtual ~NullCompactionPicker() {}
  210. // Always return "nullptr"
  211. Compaction* PickCompaction(
  212. const std::string& /*cf_name*/,
  213. const MutableCFOptions& /*mutable_cf_options*/,
  214. VersionStorageInfo* /*vstorage*/, LogBuffer* /* log_buffer */,
  215. SequenceNumber /* earliest_memtable_seqno */) override {
  216. return nullptr;
  217. }
  218. // Always return "nullptr"
  219. Compaction* CompactRange(const std::string& /*cf_name*/,
  220. const MutableCFOptions& /*mutable_cf_options*/,
  221. VersionStorageInfo* /*vstorage*/,
  222. int /*input_level*/, int /*output_level*/,
  223. const CompactRangeOptions& /*compact_range_options*/,
  224. const InternalKey* /*begin*/,
  225. const InternalKey* /*end*/,
  226. InternalKey** /*compaction_end*/,
  227. bool* /*manual_conflict*/,
  228. uint64_t /*max_file_num_to_ignore*/) override {
  229. return nullptr;
  230. }
  231. // Always returns false.
  232. virtual bool NeedsCompaction(
  233. const VersionStorageInfo* /*vstorage*/) const override {
  234. return false;
  235. }
  236. };
  237. #endif // !ROCKSDB_LITE
  238. // Attempts to find an intra L0 compaction conforming to the given parameters.
  239. //
  240. // @param level_files Metadata for L0 files.
  241. // @param min_files_to_compact Minimum number of files required to
  242. // do the compaction.
  243. // @param max_compact_bytes_per_del_file Maximum average size in bytes per
  244. // file that is going to get deleted by
  245. // the compaction.
  246. // @param max_compaction_bytes Maximum total size in bytes (in terms
  247. // of compensated file size) for files
  248. // to be compacted.
  249. // @param [out] comp_inputs If a compaction was found, will be
  250. // initialized with corresponding input
  251. // files. Cannot be nullptr.
  252. //
  253. // @return true iff compaction was found.
  254. bool FindIntraL0Compaction(
  255. const std::vector<FileMetaData*>& level_files, size_t min_files_to_compact,
  256. uint64_t max_compact_bytes_per_del_file, uint64_t max_compaction_bytes,
  257. CompactionInputFiles* comp_inputs,
  258. SequenceNumber earliest_mem_seqno = kMaxSequenceNumber);
  259. CompressionType GetCompressionType(const ImmutableCFOptions& ioptions,
  260. const VersionStorageInfo* vstorage,
  261. const MutableCFOptions& mutable_cf_options,
  262. int level, int base_level,
  263. const bool enable_compression = true);
  264. CompressionOptions GetCompressionOptions(const ImmutableCFOptions& ioptions,
  265. const VersionStorageInfo* vstorage,
  266. int level,
  267. const bool enable_compression = true);
  268. } // namespace ROCKSDB_NAMESPACE