version_set.h 13.6 KB
Newer Older
J
jorlow@chromium.org 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
// 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.
//
// The representation of a DBImpl consists of a set of Versions.  The
// newest version is called "current".  Older versions may be kept
// around to provide a consistent view to live iterators.
//
// Each Version keeps track of a set of Table files per level.  The
// entire set of versions is maintained in a VersionSet.
//
// Version,VersionSet are thread-compatible, but require external
// synchronization on all accesses.

#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_
#define STORAGE_LEVELDB_DB_VERSION_SET_H_

#include <map>
#include <set>
#include <vector>
#include "db/dbformat.h"
#include "db/version_edit.h"
#include "port/port.h"

namespace leveldb {

namespace log { class Writer; }

class Compaction;
class Iterator;
class MemTable;
class TableBuilder;
class TableCache;
class Version;
class VersionSet;
class WritableFile;

38 39 40 41 42 43 44
// Return the smallest index i such that files[i]->largest >= key.
// Return files.size() if there is no such file.
// REQUIRES: "files" contains a sorted list of non-overlapping files.
extern int FindFile(const InternalKeyComparator& icmp,
                    const std::vector<FileMetaData*>& files,
                    const Slice& key);

45
// Returns true iff some file in "files" overlaps the user key range
G
Gabor Cselle 已提交
46 47 48 49 50
// [*smallest,*largest].
// smallest==NULL represents a key smaller than all keys in the DB.
// largest==NULL represents a key largest than all keys in the DB.
// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges
//           in sorted order.
51 52
extern bool SomeFileOverlapsRange(
    const InternalKeyComparator& icmp,
G
Gabor Cselle 已提交
53
    bool disjoint_sorted_files,
54
    const std::vector<FileMetaData*>& files,
G
Gabor Cselle 已提交
55 56
    const Slice* smallest_user_key,
    const Slice* largest_user_key);
57

J
jorlow@chromium.org 已提交
58 59 60 61 62 63 64
class Version {
 public:
  // Append to *iters a sequence of iterators that will
  // yield the contents of this Version when merged together.
  // REQUIRES: This version has been saved (see VersionSet::SaveTo)
  void AddIterators(const ReadOptions&, std::vector<Iterator*>* iters);

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  // Lookup the value for key.  If found, store it in *val and
  // return OK.  Else return a non-OK status.  Fills *stats.
  // REQUIRES: lock is not held
  struct GetStats {
    FileMetaData* seek_file;
    int seek_file_level;
  };
  Status Get(const ReadOptions&, const LookupKey& key, std::string* val,
             GetStats* stats);

  // Adds "stats" into the current state.  Returns true if a new
  // compaction may need to be triggered, false otherwise.
  // REQUIRES: lock is held
  bool UpdateStats(const GetStats& stats);

J
jorlow@chromium.org 已提交
80 81 82 83 84
  // Reference count management (so Versions do not disappear out from
  // under live iterators)
  void Ref();
  void Unref();

G
Gabor Cselle 已提交
85 86 87 88 89 90
  void GetOverlappingInputs(
      int level,
      const InternalKey* begin,         // NULL means before all keys
      const InternalKey* end,           // NULL means after all keys
      std::vector<FileMetaData*>* inputs);

91
  // Returns true iff some file in the specified level overlaps
G
Gabor Cselle 已提交
92 93 94
  // some part of [*smallest_user_key,*largest_user_key].
  // smallest_user_key==NULL represents a key smaller than all keys in the DB.
  // largest_user_key==NULL represents a key largest than all keys in the DB.
95
  bool OverlapInLevel(int level,
G
Gabor Cselle 已提交
96 97 98 99 100 101 102
                      const Slice* smallest_user_key,
                      const Slice* largest_user_key);

  // Return the level at which we should place a new memtable compaction
  // result that covers the range [smallest_user_key,largest_user_key].
  int PickLevelForMemTableOutput(const Slice& smallest_user_key,
                                 const Slice& largest_user_key);
103 104 105

  int NumFiles(int level) const { return files_[level].size(); }

J
jorlow@chromium.org 已提交
106 107 108 109 110 111 112 113 114 115 116 117
  // Return a human readable string that describes this version's contents.
  std::string DebugString() const;

 private:
  friend class Compaction;
  friend class VersionSet;

  class LevelFileNumIterator;
  Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const;

  VersionSet* vset_;            // VersionSet to which this Version belongs
  Version* next_;               // Next version in linked list
118
  Version* prev_;               // Previous version in linked list
J
jorlow@chromium.org 已提交
119 120 121
  int refs_;                    // Number of live refs to this version

  // List of files per level
122
  std::vector<FileMetaData*>* files_;
J
jorlow@chromium.org 已提交
123

124 125 126 127
  // Next file to compact based on seek stats.
  FileMetaData* file_to_compact_;
  int file_to_compact_level_;

J
jorlow@chromium.org 已提交
128 129 130 131 132 133
  // Level that should be compacted next and its compaction score.
  // Score < 1 means compaction is not strictly needed.  These fields
  // are initialized by Finalize().
  double compaction_score_;
  int compaction_level_;

134
  explicit Version(VersionSet* vset);
J
jorlow@chromium.org 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

  ~Version();

  // No copying allowed
  Version(const Version&);
  void operator=(const Version&);
};

class VersionSet {
 public:
  VersionSet(const std::string& dbname,
             const Options* options,
             TableCache* table_cache,
             const InternalKeyComparator*);
  ~VersionSet();

  // Apply *edit to the current version to form a new descriptor that
  // is both saved to persistent state and installed as the new
153 154 155 156
  // current version.  Will release *mu while actually writing to the file.
  // REQUIRES: *mu is held on entry.
  // REQUIRES: no other thread concurrently calls LogAndApply()
  Status LogAndApply(VersionEdit* edit, port::Mutex* mu);
J
jorlow@chromium.org 已提交
157 158

  // Recover the last saved descriptor from persistent storage.
159
  Status Recover();
J
jorlow@chromium.org 已提交
160 161 162 163 164 165 166 167 168 169

  // Return the current version.
  Version* current() const { return current_; }

  // Return the current manifest file number
  uint64_t ManifestFileNumber() const { return manifest_file_number_; }

  // Allocate and return a new file number
  uint64_t NewFileNumber() { return next_file_number_++; }

H
heyongqiang 已提交
170 171 172 173 174 175 176 177 178
  // Arrange to reuse "file_number" unless a newer file number has
  // already been allocated.
  // REQUIRES: "file_number" was returned by a call to NewFileNumber().
  void ReuseFileNumber(uint64_t file_number) {
    if (next_file_number_ == file_number + 1) {
      next_file_number_ = file_number;
    }
  }

J
jorlow@chromium.org 已提交
179 180 181
  // Return the number of Table files at the specified level.
  int NumLevelFiles(int level) const;

182 183 184 185 186 187 188 189 190 191 192 193
  // Return the combined file size of all files at the specified level.
  int64_t NumLevelBytes(int level) const;

  // Return the last sequence number.
  uint64_t LastSequence() const { return last_sequence_; }

  // Set the last sequence number to s.
  void SetLastSequence(uint64_t s) {
    assert(s >= last_sequence_);
    last_sequence_ = s;
  }

194 195 196
  // Mark the specified file number as used.
  void MarkFileNumberUsed(uint64_t number);

197 198 199 200 201 202 203
  // Return the current log file number.
  uint64_t LogNumber() const { return log_number_; }

  // Return the log file number for the log file that is currently
  // being compacted, or zero if there is no such log file.
  uint64_t PrevLogNumber() const { return prev_log_number_; }

204 205
  int NumberLevels() const { return options_->num_levels; }

J
jorlow@chromium.org 已提交
206 207 208 209 210 211 212 213 214 215 216 217
  // Pick level and inputs for a new compaction.
  // Returns NULL if there is no compaction to be done.
  // Otherwise returns a pointer to a heap-allocated object that
  // describes the compaction.  Caller should delete the result.
  Compaction* PickCompaction();

  // Return a compaction object for compacting the range [begin,end] in
  // the specified level.  Returns NULL if there is nothing in that
  // level that overlaps the specified range.  Caller should delete
  // the result.
  Compaction* CompactRange(
      int level,
G
Gabor Cselle 已提交
218 219
      const InternalKey* begin,
      const InternalKey* end);
J
jorlow@chromium.org 已提交
220

221 222
  // Return the maximum overlapping data (in bytes) at next level for any
  // file at a level >= 1.
J
jorlow@chromium.org 已提交
223
  int64_t MaxNextLevelOverlappingBytes();
224

J
jorlow@chromium.org 已提交
225 226 227 228 229
  // Create an iterator that reads over the compaction inputs for "*c".
  // The caller should delete the iterator when no longer needed.
  Iterator* MakeInputIterator(Compaction* c);

  // Returns true iff some level needs a compaction.
230 231 232 233
  bool NeedsCompaction() const {
    Version* v = current_;
    return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL);
  }
J
jorlow@chromium.org 已提交
234 235 236 237 238

  // Add all files listed in any live version to *live.
  // May also mutate some internal state.
  void AddLiveFiles(std::set<uint64_t>* live);

239 240 241
  // Add all files listed in the current version to *live.
  void AddLiveFilesCurrentVersion(std::set<uint64_t>* live);

J
jorlow@chromium.org 已提交
242 243 244 245
  // Return the approximate offset in the database of the data for
  // "key" as of version "v".
  uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key);

246 247 248 249 250 251 252
  // Return a human-readable short (single-line) summary of the number
  // of files per level.  Uses *scratch as backing store.
  struct LevelSummaryStorage {
    char buffer[100];
  };
  const char* LevelSummary(LevelSummaryStorage* scratch) const;

253 254 255
  // printf contents (for debugging)
  Status DumpManifest(Options& options, std::string& manifestFileName);

256 257 258 259
  // Return a human-readable short (single-line) summary of the data size
  // of files per level.  Uses *scratch as backing store.
  const char* LevelDataSizeSummary(LevelSummaryStorage* scratch) const;

J
jorlow@chromium.org 已提交
260 261 262 263 264 265
 private:
  class Builder;

  friend class Compaction;
  friend class Version;

266
  void Finalize(Version* v);
J
jorlow@chromium.org 已提交
267 268 269 270 271

  void GetRange(const std::vector<FileMetaData*>& inputs,
                InternalKey* smallest,
                InternalKey* largest);

272 273 274 275 276 277 278
  void GetRange2(const std::vector<FileMetaData*>& inputs1,
                 const std::vector<FileMetaData*>& inputs2,
                 InternalKey* smallest,
                 InternalKey* largest);

  void SetupOtherInputs(Compaction* c);

279 280 281
  // Save current contents to *log
  Status WriteSnapshot(log::Writer* log);

282 283
  void AppendVersion(Version* v);

284 285 286 287
  double MaxBytesForLevel(int level);

  uint64_t MaxFileSizeForLevel(int level);

288
  int64_t ExpandedCompactionByteSizeLimit(int level);
289

290
  int64_t MaxGrandParentOverlapBytes(int level);
291

J
jorlow@chromium.org 已提交
292 293 294 295 296 297 298
  Env* const env_;
  const std::string dbname_;
  const Options* const options_;
  TableCache* const table_cache_;
  const InternalKeyComparator icmp_;
  uint64_t next_file_number_;
  uint64_t manifest_file_number_;
299 300 301
  uint64_t last_sequence_;
  uint64_t log_number_;
  uint64_t prev_log_number_;  // 0 or backing store for memtable being compacted
J
jorlow@chromium.org 已提交
302 303 304 305

  // Opened lazily
  WritableFile* descriptor_file_;
  log::Writer* descriptor_log_;
306 307
  Version dummy_versions_;  // Head of circular doubly-linked list of versions.
  Version* current_;        // == dummy_versions_.prev_
J
jorlow@chromium.org 已提交
308 309 310

  // Per-level key at which the next compaction at that level should start.
  // Either an empty string, or a valid InternalKey.
311 312 313 314 315 316 317
  std::string* compact_pointer_;

  // Per-level target file size.
  uint64_t* max_file_size_;

  // Per-level max bytes
  uint64_t* level_max_bytes_;
J
jorlow@chromium.org 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334

  // No copying allowed
  VersionSet(const VersionSet&);
  void operator=(const VersionSet&);
};

// A Compaction encapsulates information about a compaction.
class Compaction {
 public:
  ~Compaction();

  // Return the level that is being compacted.  Inputs from "level"
  // and "level+1" will be merged to produce a set of "level+1" files.
  int level() const { return level_; }

  // Return the object that holds the edits to the descriptor done
  // by this compaction.
335
  VersionEdit* edit() { return edit_; }
J
jorlow@chromium.org 已提交
336 337 338 339 340 341 342 343 344 345

  // "which" must be either 0 or 1
  int num_input_files(int which) const { return inputs_[which].size(); }

  // Return the ith input file at "level()+which" ("which" must be 0 or 1).
  FileMetaData* input(int which, int i) const { return inputs_[which][i]; }

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

346 347 348 349
  // Is this a trivial compaction that can be implemented by just
  // moving a single input file to the next level (no merging or splitting)
  bool IsTrivialMove() const;

J
jorlow@chromium.org 已提交
350 351 352 353 354 355 356 357
  // Add all inputs to this compaction as delete operations to *edit.
  void AddInputDeletions(VersionEdit* edit);

  // Returns true if the information we have available guarantees that
  // the compaction is producing data in "level+1" for which no data exists
  // in levels greater than "level+1".
  bool IsBaseLevelForKey(const Slice& user_key);

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

J
jorlow@chromium.org 已提交
362 363 364 365
  // Release the input version for the compaction, once the compaction
  // is successful.
  void ReleaseInputs();

H
heyongqiang 已提交
366 367
  void Summary(char* output, int len);

J
jorlow@chromium.org 已提交
368 369 370 371
 private:
  friend class Version;
  friend class VersionSet;

372 373
  explicit Compaction(int level, uint64_t target_file_size,
		uint64_t max_grandparent_overlap_bytes, int number_levels);
J
jorlow@chromium.org 已提交
374 375 376

  int level_;
  uint64_t max_output_file_size_;
377
  int64_t maxGrandParentOverlapBytes_;
J
jorlow@chromium.org 已提交
378
  Version* input_version_;
379 380
  VersionEdit* edit_;
  int number_levels_;
J
jorlow@chromium.org 已提交
381 382 383 384

  // Each compaction reads inputs from "level_" and "level_+1"
  std::vector<FileMetaData*> inputs_[2];      // The two sets of inputs

385 386 387
  // State used to check for number of of overlapping grandparent files
  // (parent == level_ + 1, grandparent == level_ + 2)
  std::vector<FileMetaData*> grandparents_;
D
dgrogan@chromium.org 已提交
388
  size_t grandparent_index_;  // Index in grandparent_starts_
J
jorlow@chromium.org 已提交
389 390 391
  bool seen_key_;             // Some output key has been seen
  int64_t overlapped_bytes_;  // Bytes of overlap between current output
                              // and grandparent files
392

J
jorlow@chromium.org 已提交
393 394 395 396 397 398
  // State for implementing IsBaseLevelForKey

  // level_ptrs_ holds indices into input_version_->levels_: our state
  // is that we are positioned at one of the file ranges for each
  // higher level than the ones involved in this compaction (i.e. for
  // all L >= level_ + 2).
399
  size_t* level_ptrs_;
J
jorlow@chromium.org 已提交
400 401
};

H
Hans Wennborg 已提交
402
}  // namespace leveldb
J
jorlow@chromium.org 已提交
403 404

#endif  // STORAGE_LEVELDB_DB_VERSION_SET_H_