compaction.h 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  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.
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#pragma once
F
Feng Zhu 已提交
11 12
#include "util/arena.h"
#include "util/autovector.h"
13
#include "util/mutable_cf_options.h"
14 15 16 17
#include "db/version_set.h"

namespace rocksdb {

18 19
// The structure that manages compaction input files associated
// with the same physical level.
20 21 22 23 24 25
struct CompactionInputFiles {
  int level;
  std::vector<FileMetaData*> files;
  inline bool empty() const { return files.empty(); }
  inline size_t size() const { return files.size(); }
  inline void clear() { files.clear(); }
26
  inline FileMetaData* operator[](size_t i) const { return files[i]; }
27 28
};

29
class Version;
I
Igor Canadi 已提交
30
class ColumnFamilyData;
S
sdong 已提交
31
class VersionStorageInfo;
32 33
class CompactionFilter;
class CompactionFilterV2;
34 35 36 37

// A Compaction encapsulates information about a compaction.
class Compaction {
 public:
38
  Compaction(VersionStorageInfo* input_version,
39 40 41 42 43 44 45
             const MutableCFOptions& mutable_cf_options,
             std::vector<CompactionInputFiles> inputs, int output_level,
             uint64_t target_file_size, uint64_t max_grandparent_overlap_bytes,
             uint32_t output_path_id, CompressionType compression,
             std::vector<FileMetaData*> grandparents,
             bool manual_compaction = false, double score = -1,
             bool deletion_compaction = false);
46

F
Feng Zhu 已提交
47 48 49 50
  // No copying allowed
  Compaction(const Compaction&) = delete;
  void operator=(const Compaction&) = delete;

51 52
  ~Compaction();

53
  // Returns the level associated to the specified compaction input level.
54
  // If compaction_input_level is not specified, then input_level is set to 0.
55
  int level(size_t compaction_input_level = 0) const {
56 57
    return inputs_[compaction_input_level].level;
  }
58

59 60
  int start_level() const { return start_level_; }

61
  // Outputs will go to this level
62 63 64
  int output_level() const { return output_level_; }

  // Returns the number of input levels in this compaction.
65
  size_t num_input_levels() const { return inputs_.size(); }
66 67 68

  // Return the object that holds the edits to the descriptor done
  // by this compaction.
69
  VersionEdit* edit() { return &edit_; }
70

71 72 73 74
  // Returns the number of input files associated to the specified
  // compaction input level.
  // The function will return 0 if when "compaction_input_level" < 0
  // or "compaction_input_level" >= "num_input_levels()".
75
  size_t num_input_files(size_t compaction_input_level) const {
76
    if (compaction_input_level < inputs_.size()) {
77 78 79 80
      return inputs_[compaction_input_level].size();
    }
    return 0;
  }
81

I
Igor Canadi 已提交
82 83 84
  // Returns input version of the compaction
  Version* input_version() const { return input_version_; }

85
  // Returns the ColumnFamilyData associated with the compaction.
I
Igor Canadi 已提交
86 87
  ColumnFamilyData* column_family_data() const { return cfd_; }

88 89 90 91
  // Returns the file meta data of the 'i'th input file at the
  // specified compaction input level.
  // REQUIREMENT: "compaction_input_level" must be >= 0 and
  //              < "input_levels()"
92
  FileMetaData* input(size_t compaction_input_level, size_t i) const {
93
    assert(compaction_input_level < inputs_.size());
94 95
    return inputs_[compaction_input_level][i];
  }
96

97 98 99 100
  // Returns the list of file meta data of the specified compaction
  // input level.
  // REQUIREMENT: "compaction_input_level" must be >= 0 and
  //              < "input_levels()"
101
  const std::vector<FileMetaData*>* inputs(size_t compaction_input_level) {
102
    assert(compaction_input_level < inputs_.size());
103
    return &inputs_[compaction_input_level].files;
104
  }
I
Igor Canadi 已提交
105

106
  // Returns the LevelFilesBrief of the specified compaction input level.
107
  LevelFilesBrief* input_levels(size_t compaction_input_level) {
108 109
    return &input_levels_[compaction_input_level];
  }
F
Feng Zhu 已提交
110

111
  // Maximum size of files to build during this compaction.
112
  uint64_t max_output_file_size() const { return max_output_file_size_; }
113

114
  // What compression for output
115
  CompressionType output_compression() const { return output_compression_; }
116

117
  // Whether need to write output file to second DB path.
118
  uint32_t output_path_id() const { return output_path_id_; }
119

F
Feng Zhu 已提交
120
  // Is this a trivial compaction that can be implemented by just
121 122 123
  // moving a single input file to the next level (no merging or splitting)
  bool IsTrivialMove() const;

124
  // If true, then the compaction can be done by simply deleting input files.
125
  bool deletion_compaction() const {
126 127
    return deletion_compaction_;
  }
I
Igor Canadi 已提交
128

129 130 131
  // Add all inputs to this compaction as delete operations to *edit.
  void AddInputDeletions(VersionEdit* edit);

132 133 134
  // Returns true if the available information we have guarantees that
  // the input "user_key" does not exist in any level beyond "output_level()".
  bool KeyNotExistsBeyondOutputLevel(const Slice& user_key);
135 136 137 138 139

  // Returns true iff we should stop building the current output
  // before processing "internal_key".
  bool ShouldStopBefore(const Slice& internal_key);

I
Igor Canadi 已提交
140 141 142 143
  // Clear all files to indicate that they are not being compacted
  // Delete this compaction from the list of running compactions.
  void ReleaseCompactionFiles(Status status);

144 145 146
  // Returns the summary of the compaction in "output" with maximum "len"
  // in bytes.  The caller is responsible for the memory management of
  // "output".
147 148 149 150 151 152
  void Summary(char* output, int len);

  // Return the score that was used to pick this compaction run.
  double score() const { return score_; }

  // Is this compaction creating a file in the bottom most level?
153
  bool bottommost_level() { return bottommost_level_; }
154 155

  // Does this compaction include all sst files?
156
  bool is_full_compaction() { return is_full_compaction_; }
157

158
  // Was this compaction triggered manually by the client?
159
  bool is_manual_compaction() { return is_manual_compaction_; }
160

161 162 163 164 165 166 167 168 169 170 171 172 173
  // Used when allow_trivial_move option is set in
  // Universal compaction. If all the input files are
  // non overlapping, then is_trivial_move_ variable
  // will be set true, else false
  void set_is_trivial_move(bool trivial_move) {
    is_trivial_move_ = trivial_move;
  }

  // Used when allow_trivial_move option is set in
  // Universal compaction. Returns true, if the input files
  // are non-overlapping and can be trivially moved.
  bool is_trivial_move() { return is_trivial_move_; }

174 175 176 177
  // Return the MutableCFOptions that should be used throughout the compaction
  // procedure
  const MutableCFOptions* mutable_cf_options() { return &mutable_cf_options_; }

178
  // Returns the size in bytes that the output file should be preallocated to.
179
  // In level compaction, that is max_file_size_. In universal compaction, that
180
  // is the sum of all input file sizes.
I
Igor Canadi 已提交
181
  uint64_t OutputFilePreallocationSize();
182

S
sdong 已提交
183 184
  void SetInputVersion(Version* input_version);

185 186 187 188 189 190
  struct InputLevelSummaryBuffer {
    char buffer[128];
  };

  const char* InputLevelSummary(InputLevelSummaryBuffer* scratch) const;

191 192
  uint64_t CalculateTotalInputSize() const;

193 194 195 196
  // In case of compaction error, reset the nextIndex that is used
  // to pick up the next file to be compacted from files_by_size_
  void ResetNextCompactionIndex();

197 198 199 200 201 202
  // Create a CompactionFilter from compaction_filter_factory
  std::unique_ptr<CompactionFilter> CreateCompactionFilter() const;

  // Create a CompactionFilterV2 from compaction_filter_factory_v2
  std::unique_ptr<CompactionFilterV2> CreateCompactionFilterV2() const;

203
 private:
204 205
  // mark (or clear) all files that are being compacted
  void MarkFilesBeingCompacted(bool mark_as_compacted);
206

207 208 209 210 211 212 213
  // helper function to determine if compaction with inputs and storage is
  // bottommost
  static bool IsBottommostLevel(
      int output_level, VersionStorageInfo* vstorage,
      const std::vector<CompactionInputFiles>& inputs);
  static bool IsFullCompaction(VersionStorageInfo* vstorage,
                               const std::vector<CompactionInputFiles>& inputs);
214

215 216
  const int start_level_;    // the lowest level to be compacted
  const int output_level_;  // levels to which output files are stored
217
  uint64_t max_output_file_size_;
I
Igor Canadi 已提交
218
  uint64_t max_grandparent_overlap_bytes_;
219
  MutableCFOptions mutable_cf_options_;
220
  Version* input_version_;
221 222
  VersionEdit edit_;
  const int number_levels_;
I
Igor Canadi 已提交
223
  ColumnFamilyData* cfd_;
F
Feng Zhu 已提交
224
  Arena arena_;          // Arena used to allocate space for file_levels_
225

226
  const uint32_t output_path_id_;
227
  CompressionType output_compression_;
228
  // If true, then the comaction can be done by simply deleting input files.
229
  const bool deletion_compaction_;
230

231 232
  // Compaction input files organized by level. Constant after construction
  const std::vector<CompactionInputFiles> inputs_;
233

F
Feng Zhu 已提交
234
  // A copy of inputs_, organized more closely in memory
235
  autovector<LevelFilesBrief, 2> input_levels_;
F
Feng Zhu 已提交
236

237
  // State used to check for number of of overlapping grandparent files
238
  // (grandparent == "output_level_ + 1")
239
  std::vector<FileMetaData*> grandparents_;
240 241
  size_t grandparent_index_;   // Index in grandparent_starts_
  bool seen_key_;              // Some output key has been seen
242
  uint64_t overlapped_bytes_;  // Bytes of overlap between current output
243
                               // and grandparent files
244
  const double score_;         // score that was used to pick this compaction.
245 246

  // Is this compaction creating a file in the bottom most level?
247
  const bool bottommost_level_;
248
  // Does this compaction include all sst files?
249
  const bool is_full_compaction_;
250

251
  // Is this compaction requested by the client?
252
  const bool is_manual_compaction_;
253

254 255 256 257 258
  // True if we can do trivial move in Universal multi level
  // compaction

  bool is_trivial_move_;

259 260 261 262 263
  // "level_ptrs_" holds indices into "input_version_->levels_", where each
  // index remembers which file of an associated level we are currently used
  // to check KeyNotExistsBeyondOutputLevel() for deletion operation.
  // As it is for checking KeyNotExistsBeyondOutputLevel(), it only
  // records indices for all levels beyond "output_level_".
264 265
  std::vector<size_t> level_ptrs_;

266 267
  // Does input compression match the output compression?
  bool InputCompressionMatchesOutput() const;
268 269
};

M
miguelportilla 已提交
270 271 272
// Utility function
extern uint64_t TotalFileSize(const std::vector<FileMetaData*>& files);

273
}  // namespace rocksdb