summaryrefslogtreecommitdiff
path: root/db/version_set.h
diff options
context:
space:
mode:
authorjorlow@chromium.org <jorlow@chromium.org@62dab493-f737-651d-591e-8d6aee1b9529>2011-03-18 22:37:00 +0000
committerjorlow@chromium.org <jorlow@chromium.org@62dab493-f737-651d-591e-8d6aee1b9529>2011-03-18 22:37:00 +0000
commitf67e15e50f392625b4097caf22e8be1b0fe96013 (patch)
tree1cb1764c7627f9bac27ed0e0abf27010156e5007 /db/version_set.h
parent54f1fd7eef101db1dfb2bb66a59083c45a38aa4a (diff)
downloadleveldb-f67e15e50f392625b4097caf22e8be1b0fe96013.tar.gz
Initial checkin.
git-svn-id: https://leveldb.googlecode.com/svn/trunk@2 62dab493-f737-651d-591e-8d6aee1b9529
Diffstat (limited to 'db/version_set.h')
-rw-r--r--db/version_set.h290
1 files changed, 290 insertions, 0 deletions
diff --git a/db/version_set.h b/db/version_set.h
new file mode 100644
index 0000000..b8eee3d
--- /dev/null
+++ b/db/version_set.h
@@ -0,0 +1,290 @@
+// 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 {
+
+// Grouping of constants. We may want to make some of these
+// parameters set via options.
+namespace config {
+static const int kNumLevels = 7;
+}
+
+namespace log { class Writer; }
+
+class Compaction;
+class Iterator;
+class MemTable;
+class TableBuilder;
+class TableCache;
+class Version;
+class VersionSet;
+class WritableFile;
+
+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);
+
+ // Reference count management (so Versions do not disappear out from
+ // under live iterators)
+ void Ref();
+ void Unref();
+
+ // 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
+ int refs_; // Number of live refs to this version
+ MemTable* cleanup_mem_; // NULL, or table to delete when version dropped
+
+ // List of files per level
+ std::vector<FileMetaData*> files_[config::kNumLevels];
+
+ // 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_;
+
+ explicit Version(VersionSet* vset)
+ : vset_(vset), next_(NULL), refs_(0),
+ cleanup_mem_(NULL),
+ compaction_score_(-1),
+ compaction_level_(-1) {
+ }
+
+ ~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
+ // current version. Iff Apply() returns OK, arrange to delete
+ // cleanup_mem (if cleanup_mem != NULL) when it is no longer needed
+ // by older versions.
+ Status LogAndApply(VersionEdit* edit, MemTable* cleanup_mem);
+
+ // Recover the last saved descriptor from persistent storage.
+ Status Recover(uint64_t* log_number, SequenceNumber* last_sequence);
+
+ // Save current contents to *log
+ Status WriteSnapshot(log::Writer* log);
+
+ // 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_++; }
+
+ // Return the number of Table files at the specified level.
+ int NumLevelFiles(int level) const;
+
+ // 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,
+ const InternalKey& begin,
+ const InternalKey& end);
+
+ // 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.
+ bool NeedsCompaction() const { return current_->compaction_score_ >= 1; }
+
+ // Add all files listed in any live version to *live.
+ // May also mutate some internal state.
+ void AddLiveFiles(std::set<uint64_t>* live);
+
+ // Return the approximate offset in the database of the data for
+ // "key" as of version "v".
+ uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key);
+
+ // Register a reference to a large value with the specified
+ // large_ref from the specified file number. Returns "true" if this
+ // is the first recorded reference to the "large_ref" value in the
+ // database, and false otherwise.
+ bool RegisterLargeValueRef(const LargeValueRef& large_ref,
+ uint64_t filenum,
+ const InternalKey& internal_key);
+
+ // Cleanup the large value reference state by eliminating any
+ // references from files that are not includes in either "live_tables"
+ // or "log_file".
+ void CleanupLargeValueRefs(const std::set<uint64_t>& live_tables,
+ uint64_t log_file_num);
+
+ // Returns true if a large value with the given reference is live.
+ bool LargeValueIsLive(const LargeValueRef& large_ref);
+
+ private:
+ class Builder;
+
+ friend class Compaction;
+ friend class Version;
+
+ Status Finalize(Version* v);
+
+ // Delete any old versions that are no longer needed.
+ void MaybeDeleteOldVersions();
+
+ struct BySmallestKey;
+ Status SortLevel(Version* v, uint64_t level);
+
+ void GetOverlappingInputs(
+ int level,
+ const InternalKey& begin,
+ const InternalKey& end,
+ std::vector<FileMetaData*>* inputs);
+
+ void GetRange(const std::vector<FileMetaData*>& inputs,
+ InternalKey* smallest,
+ InternalKey* largest);
+
+ 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_;
+
+ // Opened lazily
+ WritableFile* descriptor_file_;
+ log::Writer* descriptor_log_;
+
+ // Versions are kept in a singly linked list that is never empty
+ Version* current_; // Pointer to the last (newest) list entry
+ Version* oldest_; // Pointer to the first (oldest) list entry
+
+ // Map from large value reference to the set of <file numbers,internal_key>
+ // values containing references to the value. We keep the
+ // internal key as a std::string rather than as an InternalKey because
+ // we want to be able to easily use a set.
+ typedef std::set<std::pair<uint64_t, std::string> > LargeReferencesSet;
+ typedef std::map<LargeValueRef, LargeReferencesSet> LargeValueMap;
+ LargeValueMap large_value_refs_;
+
+ // Per-level key at which the next compaction at that level should start.
+ // Either an empty string, or a valid InternalKey.
+ std::string compact_pointer_[config::kNumLevels];
+
+ // 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.
+ VersionEdit* edit() { return &edit_; }
+
+ // "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_; }
+
+ // 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);
+
+ // Release the input version for the compaction, once the compaction
+ // is successful.
+ void ReleaseInputs();
+
+ private:
+ friend class Version;
+ friend class VersionSet;
+
+ explicit Compaction(int level);
+
+ int level_;
+ uint64_t max_output_file_size_;
+ Version* input_version_;
+ VersionEdit edit_;
+
+ // Each compaction reads inputs from "level_" and "level_+1"
+ std::vector<FileMetaData*> inputs_[2]; // The two sets of inputs
+
+ // 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).
+ int level_ptrs_[config::kNumLevels];
+};
+
+}
+
+#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_