2016-02-10 00:12:00 +01:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2017-07-16 01:03:42 +02:00
|
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
|
|
// (found in the LICENSE.Apache file in the root directory).
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
|
|
|
|
#ifndef ROCKSDB_LITE
|
|
|
|
#ifndef __STDC_FORMAT_MACROS
|
|
|
|
#define __STDC_FORMAT_MACROS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <inttypes.h>
|
|
|
|
|
|
|
|
#include <cctype>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
2017-04-06 04:02:00 +02:00
|
|
|
#include "options/options_parser.h"
|
2015-11-13 01:52:51 +01:00
|
|
|
#include "rocksdb/db.h"
|
|
|
|
#include "rocksdb/table.h"
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
#include "rocksdb/utilities/options_util.h"
|
|
|
|
#include "util/random.h"
|
|
|
|
#include "util/testharness.h"
|
|
|
|
#include "util/testutil.h"
|
|
|
|
|
|
|
|
#ifndef GFLAGS
|
|
|
|
bool FLAGS_enable_print = false;
|
|
|
|
#else
|
2017-12-01 19:40:45 +01:00
|
|
|
#include "util/gflags_compat.h"
|
|
|
|
using GFLAGS_NAMESPACE::ParseCommandLineFlags;
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
DEFINE_bool(enable_print, false, "Print options generated to console.");
|
|
|
|
#endif // GFLAGS
|
|
|
|
|
|
|
|
namespace rocksdb {
|
|
|
|
class OptionsUtilTest : public testing::Test {
|
|
|
|
public:
|
2015-11-13 01:52:51 +01:00
|
|
|
OptionsUtilTest() : rnd_(0xFB) {
|
|
|
|
env_.reset(new test::StringEnv(Env::Default()));
|
|
|
|
dbname_ = test::TmpDir() + "/options_util_test";
|
|
|
|
}
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
std::unique_ptr<test::StringEnv> env_;
|
2015-11-13 01:52:51 +01:00
|
|
|
std::string dbname_;
|
|
|
|
Random rnd_;
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
bool IsBlockBasedTableFactory(TableFactory* tf) {
|
|
|
|
return tf->Name() == BlockBasedTableFactory().Name();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(OptionsUtilTest, SaveAndLoad) {
|
|
|
|
const size_t kCFCount = 5;
|
|
|
|
|
|
|
|
DBOptions db_opt;
|
|
|
|
std::vector<std::string> cf_names;
|
|
|
|
std::vector<ColumnFamilyOptions> cf_opts;
|
2015-11-13 01:52:51 +01:00
|
|
|
test::RandomInitDBOptions(&db_opt, &rnd_);
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
for (size_t i = 0; i < kCFCount; ++i) {
|
|
|
|
cf_names.push_back(i == 0 ? kDefaultColumnFamilyName
|
2015-11-13 01:52:51 +01:00
|
|
|
: test::RandomName(&rnd_, 10));
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
cf_opts.emplace_back();
|
2015-11-13 01:52:51 +01:00
|
|
|
test::RandomInitCFOptions(&cf_opts.back(), &rnd_);
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const std::string kFileName = "OPTIONS-123456";
|
|
|
|
PersistRocksDBOptions(db_opt, cf_names, cf_opts, kFileName, env_.get());
|
|
|
|
|
|
|
|
DBOptions loaded_db_opt;
|
|
|
|
std::vector<ColumnFamilyDescriptor> loaded_cf_descs;
|
|
|
|
ASSERT_OK(LoadOptionsFromFile(kFileName, env_.get(), &loaded_db_opt,
|
|
|
|
&loaded_cf_descs));
|
|
|
|
|
|
|
|
ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(db_opt, loaded_db_opt));
|
2015-11-13 01:52:51 +01:00
|
|
|
test::RandomInitDBOptions(&db_opt, &rnd_);
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
ASSERT_NOK(RocksDBOptionsParser::VerifyDBOptions(db_opt, loaded_db_opt));
|
|
|
|
|
|
|
|
for (size_t i = 0; i < kCFCount; ++i) {
|
|
|
|
ASSERT_EQ(cf_names[i], loaded_cf_descs[i].name);
|
|
|
|
ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
|
|
|
|
cf_opts[i], loaded_cf_descs[i].options));
|
|
|
|
if (IsBlockBasedTableFactory(cf_opts[i].table_factory.get())) {
|
|
|
|
ASSERT_OK(RocksDBOptionsParser::VerifyTableFactory(
|
|
|
|
cf_opts[i].table_factory.get(),
|
|
|
|
loaded_cf_descs[i].options.table_factory.get()));
|
|
|
|
}
|
2015-11-13 01:52:51 +01:00
|
|
|
test::RandomInitCFOptions(&cf_opts[i], &rnd_);
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
|
|
|
|
cf_opts[i], loaded_cf_descs[i].options));
|
|
|
|
}
|
2015-11-12 23:12:27 +01:00
|
|
|
|
|
|
|
for (size_t i = 0; i < kCFCount; ++i) {
|
|
|
|
if (cf_opts[i].compaction_filter) {
|
|
|
|
delete cf_opts[i].compaction_filter;
|
|
|
|
}
|
|
|
|
}
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
}
|
|
|
|
|
2015-11-13 01:52:51 +01:00
|
|
|
namespace {
|
|
|
|
class DummyTableFactory : public TableFactory {
|
|
|
|
public:
|
|
|
|
DummyTableFactory() {}
|
|
|
|
virtual ~DummyTableFactory() {}
|
|
|
|
|
2017-07-29 01:23:50 +02:00
|
|
|
virtual const char* Name() const override { return "DummyTableFactory"; }
|
2015-11-13 01:52:51 +01:00
|
|
|
|
2017-07-29 01:23:50 +02:00
|
|
|
virtual Status NewTableReader(
|
2018-03-05 22:08:17 +01:00
|
|
|
const TableReaderOptions& /*table_reader_options*/,
|
|
|
|
unique_ptr<RandomAccessFileReader>&& /*file*/, uint64_t /*file_size*/,
|
|
|
|
unique_ptr<TableReader>* /*table_reader*/,
|
|
|
|
bool /*prefetch_index_and_filter_in_cache*/) const override {
|
2015-11-13 01:52:51 +01:00
|
|
|
return Status::NotSupported();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual TableBuilder* NewTableBuilder(
|
2018-03-05 22:08:17 +01:00
|
|
|
const TableBuilderOptions& /*table_builder_options*/,
|
|
|
|
uint32_t /*column_family_id*/,
|
|
|
|
WritableFileWriter* /*file*/) const override {
|
2015-11-13 01:52:51 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-07-29 01:23:50 +02:00
|
|
|
virtual Status SanitizeOptions(
|
2018-03-05 22:08:17 +01:00
|
|
|
const DBOptions& /*db_opts*/,
|
|
|
|
const ColumnFamilyOptions& /*cf_opts*/) const override {
|
2015-11-13 01:52:51 +01:00
|
|
|
return Status::NotSupported();
|
|
|
|
}
|
|
|
|
|
2017-07-29 01:23:50 +02:00
|
|
|
virtual std::string GetPrintableTableOptions() const override { return ""; }
|
|
|
|
|
2018-03-05 22:08:17 +01:00
|
|
|
Status GetOptionString(std::string* /*opt_string*/,
|
|
|
|
const std::string& /*delimiter*/) const override {
|
2017-07-29 01:23:50 +02:00
|
|
|
return Status::OK();
|
|
|
|
}
|
2015-11-13 01:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class DummyMergeOperator : public MergeOperator {
|
|
|
|
public:
|
|
|
|
DummyMergeOperator() {}
|
|
|
|
virtual ~DummyMergeOperator() {}
|
|
|
|
|
2018-03-05 22:08:17 +01:00
|
|
|
virtual bool FullMergeV2(const MergeOperationInput& /*merge_in*/,
|
|
|
|
MergeOperationOutput* /*merge_out*/) const override {
|
2015-11-13 01:52:51 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-05 22:08:17 +01:00
|
|
|
virtual bool PartialMergeMulti(const Slice& /*key*/,
|
|
|
|
const std::deque<Slice>& /*operand_list*/,
|
|
|
|
std::string* /*new_value*/,
|
|
|
|
Logger* /*logger*/) const override {
|
2015-11-13 01:52:51 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Introduce FullMergeV2 (eliminate memcpy from merge operators)
Summary:
This diff update the code to pin the merge operator operands while the merge operation is done, so that we can eliminate the memcpy cost, to do that we need a new public API for FullMerge that replace the std::deque<std::string> with std::vector<Slice>
This diff is stacked on top of D56493 and D56511
In this diff we
- Update FullMergeV2 arguments to be encapsulated in MergeOperationInput and MergeOperationOutput which will make it easier to add new arguments in the future
- Replace std::deque<std::string> with std::vector<Slice> to pass operands
- Replace MergeContext std::deque with std::vector (based on a simple benchmark I ran https://gist.github.com/IslamAbdelRahman/78fc86c9ab9f52b1df791e58943fb187)
- Allow FullMergeV2 output to be an existing operand
```
[Everything in Memtable | 10K operands | 10 KB each | 1 operand per key]
DEBUG_LEVEL=0 make db_bench -j64 && ./db_bench --benchmarks="mergerandom,readseq,readseq,readseq,readseq,readseq" --merge_operator="max" --merge_keys=10000 --num=10000 --disable_auto_compactions --value_size=10240 --write_buffer_size=1000000000
[FullMergeV2]
readseq : 0.607 micros/op 1648235 ops/sec; 16121.2 MB/s
readseq : 0.478 micros/op 2091546 ops/sec; 20457.2 MB/s
readseq : 0.252 micros/op 3972081 ops/sec; 38850.5 MB/s
readseq : 0.237 micros/op 4218328 ops/sec; 41259.0 MB/s
readseq : 0.247 micros/op 4043927 ops/sec; 39553.2 MB/s
[master]
readseq : 3.935 micros/op 254140 ops/sec; 2485.7 MB/s
readseq : 3.722 micros/op 268657 ops/sec; 2627.7 MB/s
readseq : 3.149 micros/op 317605 ops/sec; 3106.5 MB/s
readseq : 3.125 micros/op 320024 ops/sec; 3130.1 MB/s
readseq : 4.075 micros/op 245374 ops/sec; 2400.0 MB/s
```
```
[Everything in Memtable | 10K operands | 10 KB each | 10 operand per key]
DEBUG_LEVEL=0 make db_bench -j64 && ./db_bench --benchmarks="mergerandom,readseq,readseq,readseq,readseq,readseq" --merge_operator="max" --merge_keys=1000 --num=10000 --disable_auto_compactions --value_size=10240 --write_buffer_size=1000000000
[FullMergeV2]
readseq : 3.472 micros/op 288018 ops/sec; 2817.1 MB/s
readseq : 2.304 micros/op 434027 ops/sec; 4245.2 MB/s
readseq : 1.163 micros/op 859845 ops/sec; 8410.0 MB/s
readseq : 1.192 micros/op 838926 ops/sec; 8205.4 MB/s
readseq : 1.250 micros/op 800000 ops/sec; 7824.7 MB/s
[master]
readseq : 24.025 micros/op 41623 ops/sec; 407.1 MB/s
readseq : 18.489 micros/op 54086 ops/sec; 529.0 MB/s
readseq : 18.693 micros/op 53495 ops/sec; 523.2 MB/s
readseq : 23.621 micros/op 42335 ops/sec; 414.1 MB/s
readseq : 18.775 micros/op 53262 ops/sec; 521.0 MB/s
```
```
[Everything in Block cache | 10K operands | 10 KB each | 1 operand per key]
[FullMergeV2]
$ DEBUG_LEVEL=0 make db_bench -j64 && ./db_bench --benchmarks="readseq,readseq,readseq,readseq,readseq" --merge_operator="max" --num=100000 --db="/dev/shm/merge-random-10K-10KB" --cache_size=1000000000 --use_existing_db --disable_auto_compactions
readseq : 14.741 micros/op 67837 ops/sec; 663.5 MB/s
readseq : 1.029 micros/op 971446 ops/sec; 9501.6 MB/s
readseq : 0.974 micros/op 1026229 ops/sec; 10037.4 MB/s
readseq : 0.965 micros/op 1036080 ops/sec; 10133.8 MB/s
readseq : 0.943 micros/op 1060657 ops/sec; 10374.2 MB/s
[master]
readseq : 16.735 micros/op 59755 ops/sec; 584.5 MB/s
readseq : 3.029 micros/op 330151 ops/sec; 3229.2 MB/s
readseq : 3.136 micros/op 318883 ops/sec; 3119.0 MB/s
readseq : 3.065 micros/op 326245 ops/sec; 3191.0 MB/s
readseq : 3.014 micros/op 331813 ops/sec; 3245.4 MB/s
```
```
[Everything in Block cache | 10K operands | 10 KB each | 10 operand per key]
DEBUG_LEVEL=0 make db_bench -j64 && ./db_bench --benchmarks="readseq,readseq,readseq,readseq,readseq" --merge_operator="max" --num=100000 --db="/dev/shm/merge-random-10-operands-10K-10KB" --cache_size=1000000000 --use_existing_db --disable_auto_compactions
[FullMergeV2]
readseq : 24.325 micros/op 41109 ops/sec; 402.1 MB/s
readseq : 1.470 micros/op 680272 ops/sec; 6653.7 MB/s
readseq : 1.231 micros/op 812347 ops/sec; 7945.5 MB/s
readseq : 1.091 micros/op 916590 ops/sec; 8965.1 MB/s
readseq : 1.109 micros/op 901713 ops/sec; 8819.6 MB/s
[master]
readseq : 27.257 micros/op 36687 ops/sec; 358.8 MB/s
readseq : 4.443 micros/op 225073 ops/sec; 2201.4 MB/s
readseq : 5.830 micros/op 171526 ops/sec; 1677.7 MB/s
readseq : 4.173 micros/op 239635 ops/sec; 2343.8 MB/s
readseq : 4.150 micros/op 240963 ops/sec; 2356.8 MB/s
```
Test Plan: COMPILE_WITH_ASAN=1 make check -j64
Reviewers: yhchiang, andrewkr, sdong
Reviewed By: sdong
Subscribers: lovro, andrewkr, dhruba
Differential Revision: https://reviews.facebook.net/D57075
2016-07-20 18:49:03 +02:00
|
|
|
virtual const char* Name() const override { return "DummyMergeOperator"; }
|
2015-11-13 01:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class DummySliceTransform : public SliceTransform {
|
|
|
|
public:
|
|
|
|
DummySliceTransform() {}
|
|
|
|
virtual ~DummySliceTransform() {}
|
|
|
|
|
|
|
|
// Return the name of this transformation.
|
|
|
|
virtual const char* Name() const { return "DummySliceTransform"; }
|
|
|
|
|
|
|
|
// transform a src in domain to a dst in the range
|
|
|
|
virtual Slice Transform(const Slice& src) const { return src; }
|
|
|
|
|
|
|
|
// determine whether this is a valid src upon the function applies
|
2018-03-05 22:08:17 +01:00
|
|
|
virtual bool InDomain(const Slice& /*src*/) const { return false; }
|
2015-11-13 01:52:51 +01:00
|
|
|
|
|
|
|
// determine whether dst=Transform(src) for some src
|
2018-03-05 22:08:17 +01:00
|
|
|
virtual bool InRange(const Slice& /*dst*/) const { return false; }
|
2015-11-13 01:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_F(OptionsUtilTest, SanityCheck) {
|
|
|
|
DBOptions db_opt;
|
|
|
|
std::vector<ColumnFamilyDescriptor> cf_descs;
|
|
|
|
const size_t kCFCount = 5;
|
|
|
|
for (size_t i = 0; i < kCFCount; ++i) {
|
|
|
|
cf_descs.emplace_back();
|
|
|
|
cf_descs.back().name =
|
|
|
|
(i == 0) ? kDefaultColumnFamilyName : test::RandomName(&rnd_, 10);
|
|
|
|
|
|
|
|
cf_descs.back().options.table_factory.reset(NewBlockBasedTableFactory());
|
2016-02-19 23:42:24 +01:00
|
|
|
// Assign non-null values to prefix_extractors except the first cf.
|
2015-11-13 01:52:51 +01:00
|
|
|
cf_descs.back().options.prefix_extractor.reset(
|
2016-02-19 23:42:24 +01:00
|
|
|
i != 0 ? test::RandomSliceTransform(&rnd_) : nullptr);
|
2015-11-13 01:52:51 +01:00
|
|
|
cf_descs.back().options.merge_operator.reset(
|
|
|
|
test::RandomMergeOperator(&rnd_));
|
|
|
|
}
|
|
|
|
|
|
|
|
db_opt.create_missing_column_families = true;
|
|
|
|
db_opt.create_if_missing = true;
|
|
|
|
|
|
|
|
DestroyDB(dbname_, Options(db_opt, cf_descs[0].options));
|
|
|
|
DB* db;
|
|
|
|
std::vector<ColumnFamilyHandle*> handles;
|
|
|
|
// open and persist the options
|
|
|
|
ASSERT_OK(DB::Open(db_opt, dbname_, cf_descs, &handles, &db));
|
|
|
|
|
|
|
|
// close the db
|
|
|
|
for (auto* handle : handles) {
|
|
|
|
delete handle;
|
|
|
|
}
|
|
|
|
delete db;
|
|
|
|
|
|
|
|
// perform sanity check
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
ASSERT_GE(kCFCount, 5);
|
|
|
|
// merge operator
|
|
|
|
{
|
|
|
|
std::shared_ptr<MergeOperator> merge_op =
|
|
|
|
cf_descs[0].options.merge_operator;
|
|
|
|
|
|
|
|
ASSERT_NE(merge_op.get(), nullptr);
|
|
|
|
cf_descs[0].options.merge_operator.reset();
|
|
|
|
ASSERT_NOK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[0].options.merge_operator.reset(new DummyMergeOperator());
|
|
|
|
ASSERT_NOK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[0].options.merge_operator = merge_op;
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
}
|
|
|
|
|
|
|
|
// prefix extractor
|
|
|
|
{
|
|
|
|
std::shared_ptr<const SliceTransform> prefix_extractor =
|
|
|
|
cf_descs[1].options.prefix_extractor;
|
|
|
|
|
2016-02-19 23:42:24 +01:00
|
|
|
// It's okay to set prefix_extractor to nullptr.
|
2015-11-13 01:52:51 +01:00
|
|
|
ASSERT_NE(prefix_extractor, nullptr);
|
|
|
|
cf_descs[1].options.prefix_extractor.reset();
|
2016-02-19 23:42:24 +01:00
|
|
|
ASSERT_OK(
|
2015-11-13 01:52:51 +01:00
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[1].options.prefix_extractor.reset(new DummySliceTransform());
|
2017-06-23 01:16:19 +02:00
|
|
|
ASSERT_OK(
|
2015-11-13 01:52:51 +01:00
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[1].options.prefix_extractor = prefix_extractor;
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
}
|
|
|
|
|
2016-02-19 23:42:24 +01:00
|
|
|
// prefix extractor nullptr case
|
|
|
|
{
|
|
|
|
std::shared_ptr<const SliceTransform> prefix_extractor =
|
|
|
|
cf_descs[0].options.prefix_extractor;
|
|
|
|
|
|
|
|
// It's okay to set prefix_extractor to nullptr.
|
|
|
|
ASSERT_EQ(prefix_extractor, nullptr);
|
|
|
|
cf_descs[0].options.prefix_extractor.reset();
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
// It's okay to change prefix_extractor from nullptr to non-nullptr
|
|
|
|
cf_descs[0].options.prefix_extractor.reset(new DummySliceTransform());
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[0].options.prefix_extractor = prefix_extractor;
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
}
|
|
|
|
|
2015-11-13 01:52:51 +01:00
|
|
|
// comparator
|
|
|
|
{
|
|
|
|
test::SimpleSuffixReverseComparator comparator;
|
|
|
|
|
|
|
|
auto* prev_comparator = cf_descs[2].options.comparator;
|
|
|
|
cf_descs[2].options.comparator = &comparator;
|
|
|
|
ASSERT_NOK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[2].options.comparator = prev_comparator;
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
}
|
|
|
|
|
|
|
|
// table factory
|
|
|
|
{
|
|
|
|
std::shared_ptr<TableFactory> table_factory =
|
|
|
|
cf_descs[3].options.table_factory;
|
|
|
|
|
|
|
|
ASSERT_NE(table_factory, nullptr);
|
|
|
|
cf_descs[3].options.table_factory.reset(new DummyTableFactory());
|
|
|
|
ASSERT_NOK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
|
|
|
|
cf_descs[3].options.table_factory = table_factory;
|
|
|
|
ASSERT_OK(
|
|
|
|
CheckOptionsCompatibility(dbname_, Env::Default(), db_opt, cf_descs));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 15:52:43 +01:00
|
|
|
} // namespace rocksdb
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
#ifdef GFLAGS
|
|
|
|
ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
#endif // GFLAGS
|
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
#include <cstdio>
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
printf("Skipped in RocksDBLite as utilities are not supported.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif // !ROCKSDB_LITE
|