mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-27 11:43:49 +00:00
677fee27c6
Summary: A lot of our code implicitly assumes number_levels to be static. ReduceNumberOfLevels() breaks that assumption. For example, after calling ReduceNumberOfLevels(), DBImpl::NumberLevels() will be different from VersionSet::NumberLevels(). This is dangerous. Thankfully, it's not in public headers and is only used from LDB cmd tool. LDB tool is only using it statically, i.e. it never calls it with running DB instance. With this diff, we make it explicitly static. This way, we can assume number_levels to be immutable and not break assumption that lot of our code is relying upon. LDB tool can still use the method. Also, I removed the method from a separate file since it breaks filename completition. version_se<TAB> now completes to "version_set." instead of "version_set" (without the dot). I don't see a big reason that the function should be in a different file. Test Plan: reduce_levels_test Reviewers: dhruba, haobo, kailiu, sdong Reviewed By: kailiu CC: leveldb Differential Revision: https://reviews.facebook.net/D15303
158 lines
6 KiB
C++
158 lines
6 KiB
C++
// 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
|
|
#include "db/version_set.h"
|
|
#include "db/compaction.h"
|
|
#include "rocksdb/status.h"
|
|
#include "rocksdb/options.h"
|
|
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <set>
|
|
|
|
namespace rocksdb {
|
|
|
|
class Compaction;
|
|
class Version;
|
|
|
|
class CompactionPicker {
|
|
public:
|
|
CompactionPicker(const Options* options, const InternalKeyComparator* icmp);
|
|
virtual ~CompactionPicker();
|
|
|
|
// Pick level and inputs for a new compaction.
|
|
// Returns nullptr 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.
|
|
virtual Compaction* PickCompaction(Version* version) = 0;
|
|
|
|
// Return a compaction object for compacting the range [begin,end] in
|
|
// the specified level. Returns nullptr if there is nothing in that
|
|
// level that overlaps the specified range. Caller should delete
|
|
// the result.
|
|
//
|
|
// The returned Compaction might not include the whole requested range.
|
|
// In that case, compaction_end will be set to the next key that needs
|
|
// compacting. In case the compaction will compact the whole range,
|
|
// compaction_end will be set to nullptr.
|
|
// Client is responsible for compaction_end storage -- when called,
|
|
// *compaction_end should point to valid InternalKey!
|
|
Compaction* CompactRange(Version* version, int input_level, int output_level,
|
|
const InternalKey* begin, const InternalKey* end,
|
|
InternalKey** compaction_end);
|
|
|
|
// Free up the files that participated in a compaction
|
|
void ReleaseCompactionFiles(Compaction* c, Status status);
|
|
|
|
// Return the total amount of data that is undergoing
|
|
// compactions per level
|
|
void SizeBeingCompacted(std::vector<uint64_t>& sizes);
|
|
|
|
// Returns maximum total overlap bytes with grandparent
|
|
// level (i.e., level+2) before we stop building a single
|
|
// file in level->level+1 compaction.
|
|
uint64_t MaxGrandParentOverlapBytes(int level);
|
|
|
|
// Returns maximum total bytes of data on a given level.
|
|
double MaxBytesForLevel(int level);
|
|
|
|
// Get the max file size in a given level.
|
|
uint64_t MaxFileSizeForLevel(int level) const;
|
|
|
|
protected:
|
|
int NumberLevels() const { return num_levels_; }
|
|
|
|
// Stores the minimal range that covers all entries in inputs in
|
|
// *smallest, *largest.
|
|
// REQUIRES: inputs is not empty
|
|
void GetRange(const std::vector<FileMetaData*>& inputs, InternalKey* smallest,
|
|
InternalKey* largest);
|
|
|
|
// Stores the minimal range that covers all entries in inputs1 and inputs2
|
|
// in *smallest, *largest.
|
|
// REQUIRES: inputs is not empty
|
|
void GetRange(const std::vector<FileMetaData*>& inputs1,
|
|
const std::vector<FileMetaData*>& inputs2,
|
|
InternalKey* smallest, InternalKey* largest);
|
|
|
|
// Add more files to the inputs on "level" to make sure that
|
|
// no newer version of a key is compacted to "level+1" while leaving an older
|
|
// version in a "level". Otherwise, any Get() will search "level" first,
|
|
// and will likely return an old/stale value for the key, since it always
|
|
// searches in increasing order of level to find the value. This could
|
|
// also scramble the order of merge operands. This function should be
|
|
// called any time a new Compaction is created, and its inputs_[0] are
|
|
// populated.
|
|
//
|
|
// Will return false if it is impossible to apply this compaction.
|
|
bool ExpandWhileOverlapping(Compaction* c);
|
|
|
|
uint64_t ExpandedCompactionByteSizeLimit(int level);
|
|
|
|
// Returns true if any one of the specified files are being compacted
|
|
bool FilesInCompaction(std::vector<FileMetaData*>& files);
|
|
|
|
// Returns true if any one of the parent files are being compacted
|
|
bool ParentRangeInCompaction(Version* version, const InternalKey* smallest,
|
|
const InternalKey* largest, int level,
|
|
int* index);
|
|
|
|
void SetupOtherInputs(Compaction* c);
|
|
|
|
// record all the ongoing compactions for all levels
|
|
std::vector<std::set<Compaction*>> compactions_in_progress_;
|
|
|
|
// Per-level target file size.
|
|
std::unique_ptr<uint64_t[]> max_file_size_;
|
|
|
|
// Per-level max bytes
|
|
std::unique_ptr<uint64_t[]> level_max_bytes_;
|
|
|
|
const Options* const options_;
|
|
private:
|
|
int num_levels_;
|
|
|
|
const InternalKeyComparator* const icmp_;
|
|
};
|
|
|
|
class UniversalCompactionPicker : public CompactionPicker {
|
|
public:
|
|
UniversalCompactionPicker(const Options* options,
|
|
const InternalKeyComparator* icmp)
|
|
: CompactionPicker(options, icmp) {}
|
|
virtual Compaction* PickCompaction(Version* version) override;
|
|
|
|
private:
|
|
// Pick Universal compaction to limit read amplification
|
|
Compaction* PickCompactionUniversalReadAmp(Version* version, double score,
|
|
unsigned int ratio,
|
|
unsigned int num_files);
|
|
|
|
// Pick Universal compaction to limit space amplification.
|
|
Compaction* PickCompactionUniversalSizeAmp(Version* version, double score);
|
|
};
|
|
|
|
class LevelCompactionPicker : public CompactionPicker {
|
|
public:
|
|
LevelCompactionPicker(const Options* options,
|
|
const InternalKeyComparator* icmp)
|
|
: CompactionPicker(options, icmp) {}
|
|
virtual Compaction* PickCompaction(Version* version) override;
|
|
|
|
private:
|
|
// For the specfied level, pick a compaction.
|
|
// Returns nullptr if there is no compaction to be done.
|
|
// If level is 0 and there is already a compaction on that level, this
|
|
// function will return nullptr.
|
|
Compaction* PickCompactionBySize(Version* version, int level, double score);
|
|
};
|
|
|
|
} // namespace rocksdb
|