Summary: Add a CompactedDBImpl that will enabled when calling OpenForReadOnly() and the DB only has one level (>0) of files. As a performan comparison, CuckooTable performs 2.1M/s with CompactedDBImpl vs. 1.78M/s with ReadOnlyDBImpl. Test Plan: db_bench Reviewers: yhchiang, igor, sdong Reviewed By: sdong Subscribers: leveldb Differential Revision: https://reviews.facebook.net/D23553main
parent
f7375f39fd
commit
3c68006109
@ -0,0 +1,132 @@ |
||||
// Copyright (c) 2014, 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.
|
||||
|
||||
#ifndef ROCKSDB_LITE |
||||
#include "utilities/compacted_db/compacted_db_impl.h" |
||||
#include "db/db_impl.h" |
||||
#include "db/version_set.h" |
||||
#include "db/merge_context.h" |
||||
|
||||
namespace rocksdb { |
||||
|
||||
extern void MarkKeyMayExist(void* arg); |
||||
extern bool SaveValue(void* arg, const ParsedInternalKey& parsed_key, |
||||
const Slice& v); |
||||
|
||||
CompactedDBImpl::CompactedDBImpl( |
||||
const DBOptions& options, const std::string& dbname) |
||||
: DBImpl(options, dbname) { |
||||
} |
||||
|
||||
CompactedDBImpl::~CompactedDBImpl() { |
||||
} |
||||
|
||||
Status CompactedDBImpl::Get(const ReadOptions& options, |
||||
ColumnFamilyHandle*, const Slice& key, std::string* value) { |
||||
size_t left = 0; |
||||
size_t right = files_.num_files - 1; |
||||
while (left < right) { |
||||
size_t mid = (left + right) >> 1; |
||||
const FdWithKeyRange& f = files_.files[mid]; |
||||
if (user_comparator_->Compare(ExtractUserKey(f.largest_key), key) < 0) { |
||||
// Key at "mid.largest" is < "target". Therefore all
|
||||
// files at or before "mid" are uninteresting.
|
||||
left = mid + 1; |
||||
} else { |
||||
// Key at "mid.largest" is >= "target". Therefore all files
|
||||
// after "mid" are uninteresting.
|
||||
right = mid; |
||||
} |
||||
} |
||||
const FdWithKeyRange& f = files_.files[right]; |
||||
|
||||
bool value_found; |
||||
MergeContext merge_context; |
||||
Version::Saver saver; |
||||
saver.state = Version::kNotFound; |
||||
saver.ucmp = user_comparator_; |
||||
saver.user_key = key; |
||||
saver.value_found = &value_found; |
||||
saver.value = value; |
||||
saver.merge_operator = nullptr; |
||||
saver.merge_context = &merge_context; |
||||
saver.logger = info_log_; |
||||
saver.statistics = statistics_; |
||||
LookupKey lkey(key, kMaxSequenceNumber); |
||||
f.fd.table_reader->Get(options, lkey.internal_key(), |
||||
reinterpret_cast<void*>(&saver), SaveValue, |
||||
MarkKeyMayExist); |
||||
if (saver.state == Version::kFound) { |
||||
return Status::OK(); |
||||
} |
||||
return Status::NotFound(); |
||||
} |
||||
|
||||
Status CompactedDBImpl::Init(const Options& options) { |
||||
mutex_.Lock(); |
||||
ColumnFamilyDescriptor cf(kDefaultColumnFamilyName, |
||||
ColumnFamilyOptions(options)); |
||||
Status s = Recover({ cf }, true /* read only */, false); |
||||
if (s.ok()) { |
||||
cfd_ = reinterpret_cast<ColumnFamilyHandleImpl*>( |
||||
DefaultColumnFamily())->cfd(); |
||||
delete cfd_->InstallSuperVersion(new SuperVersion(), &mutex_); |
||||
} |
||||
mutex_.Unlock(); |
||||
if (!s.ok()) { |
||||
return s; |
||||
} |
||||
version_ = cfd_->GetSuperVersion()->current; |
||||
user_comparator_ = cfd_->user_comparator(); |
||||
statistics_ = cfd_->ioptions()->statistics; |
||||
info_log_ = cfd_->ioptions()->info_log; |
||||
// L0 should not have files
|
||||
if (version_->file_levels_[0].num_files > 1) { |
||||
return Status::NotSupported("L0 contain more than 1 file"); |
||||
} |
||||
if (version_->file_levels_[0].num_files == 1) { |
||||
if (version_->num_non_empty_levels_ > 1) { |
||||
return Status::NotSupported("Both L0 and other level contain files"); |
||||
} |
||||
files_ = version_->file_levels_[0]; |
||||
return Status::OK(); |
||||
} |
||||
|
||||
for (int i = 1; i < version_->num_non_empty_levels_ - 1; ++i) { |
||||
if (version_->file_levels_[i].num_files > 0) { |
||||
return Status::NotSupported("Other levels also contain files"); |
||||
} |
||||
} |
||||
|
||||
int level = version_->num_non_empty_levels_ - 1; |
||||
if (version_->file_levels_[level].num_files > 0) { |
||||
files_ = version_->file_levels_[version_->num_non_empty_levels_ - 1]; |
||||
return Status::OK(); |
||||
} |
||||
return Status::NotSupported("no file exists"); |
||||
} |
||||
|
||||
Status CompactedDBImpl::Open(const Options& options, |
||||
const std::string& dbname, DB** dbptr) { |
||||
*dbptr = nullptr; |
||||
|
||||
if (options.max_open_files != -1) { |
||||
return Status::InvalidArgument("require max_open_files = -1"); |
||||
} |
||||
if (options.merge_operator.get() != nullptr) { |
||||
return Status::InvalidArgument("merge operator is not supported"); |
||||
} |
||||
DBOptions db_options(options); |
||||
std::unique_ptr<CompactedDBImpl> db(new CompactedDBImpl(db_options, dbname)); |
||||
Status s = db->Init(options); |
||||
if (s.ok()) { |
||||
*dbptr = db.release(); |
||||
Log(options.info_log, "Opened the db as fully compacted mode"); |
||||
} |
||||
return s; |
||||
} |
||||
|
||||
} // namespace rocksdb
|
||||
#endif // ROCKSDB_LITE
|
@ -0,0 +1,92 @@ |
||||
// Copyright (c) 2014, 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.
|
||||
|
||||
#pragma once |
||||
#ifndef ROCKSDB_LITE |
||||
#include "db/db_impl.h" |
||||
#include <vector> |
||||
#include <string> |
||||
|
||||
namespace rocksdb { |
||||
|
||||
class CompactedDBImpl : public DBImpl { |
||||
public: |
||||
CompactedDBImpl(const DBOptions& options, const std::string& dbname); |
||||
virtual ~CompactedDBImpl(); |
||||
|
||||
static Status Open(const Options& options, const std::string& dbname, |
||||
DB** dbptr); |
||||
|
||||
// Implementations of the DB interface
|
||||
using DB::Get; |
||||
virtual Status Get(const ReadOptions& options, |
||||
ColumnFamilyHandle* column_family, const Slice& key, |
||||
std::string* value) override; |
||||
|
||||
using DBImpl::Put; |
||||
virtual Status Put(const WriteOptions& options, |
||||
ColumnFamilyHandle* column_family, const Slice& key, |
||||
const Slice& value) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
using DBImpl::Merge; |
||||
virtual Status Merge(const WriteOptions& options, |
||||
ColumnFamilyHandle* column_family, const Slice& key, |
||||
const Slice& value) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
using DBImpl::Delete; |
||||
virtual Status Delete(const WriteOptions& options, |
||||
ColumnFamilyHandle* column_family, |
||||
const Slice& key) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
virtual Status Write(const WriteOptions& options, |
||||
WriteBatch* updates) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
using DBImpl::CompactRange; |
||||
virtual Status CompactRange(ColumnFamilyHandle* column_family, |
||||
const Slice* begin, const Slice* end, |
||||
bool reduce_level = false, int target_level = -1, |
||||
uint32_t target_path_id = 0) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
|
||||
virtual Status DisableFileDeletions() override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
virtual Status EnableFileDeletions(bool force) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
virtual Status GetLiveFiles(std::vector<std::string>&, |
||||
uint64_t* manifest_file_size, |
||||
bool flush_memtable = true) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
using DBImpl::Flush; |
||||
virtual Status Flush(const FlushOptions& options, |
||||
ColumnFamilyHandle* column_family) override { |
||||
return Status::NotSupported("Not supported in compacted db mode."); |
||||
} |
||||
|
||||
private: |
||||
friend class DB; |
||||
Status Init(const Options& options); |
||||
|
||||
ColumnFamilyData* cfd_; |
||||
Version* version_; |
||||
const Comparator* user_comparator_; |
||||
FileLevel files_; |
||||
|
||||
Statistics* statistics_; |
||||
Logger* info_log_; |
||||
|
||||
// No copying allowed
|
||||
CompactedDBImpl(const CompactedDBImpl&); |
||||
void operator=(const CompactedDBImpl&); |
||||
}; |
||||
} |
||||
#endif // ROCKSDB_LITE
|
Loading…
Reference in new issue