Make max_background_compactions and base_background_compactions dynamic changeable

Summary:
Add DB::SetDBOptions to dynamic change max_background_compactions and base_background_compactions.
I'll add more dynamic changeable options soon.

Test Plan: unit test.

Reviewers: yhchiang, IslamAbdelRahman, sdong

Reviewed By: sdong

Subscribers: andrewkr, dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D64749
main
Yi Wu 8 years ago
parent 21e8daced5
commit e29d3b67c2
  1. 3
      HISTORY.md
  2. 48
      db/column_family_test.cc
  3. 93
      db/db_impl.cc
  4. 10
      db/db_impl.h
  5. 5
      db/db_impl_debug.cc
  6. 52
      db/db_options_test.cc
  7. 6
      db/db_test.cc
  8. 3
      include/rocksdb/db.h
  9. 6
      include/rocksdb/utilities/stackable_db.h
  10. 24
      util/db_options.cc
  11. 6
      util/db_options.h
  12. 34
      util/options_helper.cc
  13. 11
      util/options_helper.h

@ -4,6 +4,9 @@
* DB::GetOptions() reflect dynamic changed options (i.e. through DB::SetOptions()) and return copy of options instead of reference. * DB::GetOptions() reflect dynamic changed options (i.e. through DB::SetOptions()) and return copy of options instead of reference.
* Added Statistics::getAndResetTickerCount(). * Added Statistics::getAndResetTickerCount().
### New Features
* Add DB::SetDBOptions() to dynamic change base_background_compactions and max_background_compactions.
## 4.12.0 (9/12/2016) ## 4.12.0 (9/12/2016)
### Public API Change ### Public API Change
* CancelAllBackgroundWork() flushes all memtables for databases containing writes that have bypassed the WAL (writes issued with WriteOptions::disableWAL=true) before shutting down background threads. * CancelAllBackgroundWork() flushes all memtables for databases containing writes that have bypassed the WAL (writes issued with WriteOptions::disableWAL=true) before shutting down background threads.

@ -2458,7 +2458,7 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
ASSERT_TRUE(!dbfull()->TEST_write_controler().IsStopped()); ASSERT_TRUE(!dbfull()->TEST_write_controler().IsStopped());
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay()); ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
ASSERT_EQ(kBaseRate, dbfull()->TEST_write_controler().delayed_write_rate()); ASSERT_EQ(kBaseRate, dbfull()->TEST_write_controler().delayed_write_rate());
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(400); vstorage->TEST_set_estimated_compaction_needed_bytes(400);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
@ -2466,7 +2466,7 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay()); ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
ASSERT_EQ(kBaseRate / 1.2, ASSERT_EQ(kBaseRate / 1.2,
dbfull()->TEST_write_controler().delayed_write_rate()); dbfull()->TEST_write_controler().delayed_write_rate());
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(500); vstorage->TEST_set_estimated_compaction_needed_bytes(500);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
@ -2522,7 +2522,7 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped()); ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped());
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay()); ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(3001); vstorage->TEST_set_estimated_compaction_needed_bytes(3001);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
@ -2547,7 +2547,7 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay()); ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
ASSERT_EQ(kBaseRate / 1.2, ASSERT_EQ(kBaseRate / 1.2,
dbfull()->TEST_write_controler().delayed_write_rate()); dbfull()->TEST_write_controler().delayed_write_rate());
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(101); vstorage->set_l0_delay_trigger_count(101);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
@ -2641,31 +2641,31 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
vstorage->TEST_set_estimated_compaction_needed_bytes(40); vstorage->TEST_set_estimated_compaction_needed_bytes(40);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(50); vstorage->TEST_set_estimated_compaction_needed_bytes(50);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(300); vstorage->TEST_set_estimated_compaction_needed_bytes(300);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(45); vstorage->TEST_set_estimated_compaction_needed_bytes(45);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(7); vstorage->set_l0_delay_trigger_count(7);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(9); vstorage->set_l0_delay_trigger_count(9);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(6); vstorage->set_l0_delay_trigger_count(6);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
// Speed up threshold = min(4 * 2, 4 + (12 - 4)/4) = 6 // Speed up threshold = min(4 * 2, 4 + (12 - 4)/4) = 6
mutable_cf_options.level0_file_num_compaction_trigger = 4; mutable_cf_options.level0_file_num_compaction_trigger = 4;
@ -2674,15 +2674,15 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
vstorage->set_l0_delay_trigger_count(5); vstorage->set_l0_delay_trigger_count(5);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(7); vstorage->set_l0_delay_trigger_count(7);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(3); vstorage->set_l0_delay_trigger_count(3);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
} }
TEST_F(ColumnFamilyTest, WriteStallTwoColumnFamilies) { TEST_F(ColumnFamilyTest, WriteStallTwoColumnFamilies) {
@ -2794,41 +2794,41 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
vstorage->TEST_set_estimated_compaction_needed_bytes(40); vstorage->TEST_set_estimated_compaction_needed_bytes(40);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(60); vstorage->TEST_set_estimated_compaction_needed_bytes(60);
cfd1->RecalculateWriteStallConditions(mutable_cf_options); cfd1->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage1->TEST_set_estimated_compaction_needed_bytes(30); vstorage1->TEST_set_estimated_compaction_needed_bytes(30);
cfd1->RecalculateWriteStallConditions(mutable_cf_options); cfd1->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage1->TEST_set_estimated_compaction_needed_bytes(70); vstorage1->TEST_set_estimated_compaction_needed_bytes(70);
cfd1->RecalculateWriteStallConditions(mutable_cf_options); cfd1->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->TEST_set_estimated_compaction_needed_bytes(20); vstorage->TEST_set_estimated_compaction_needed_bytes(20);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage1->TEST_set_estimated_compaction_needed_bytes(3); vstorage1->TEST_set_estimated_compaction_needed_bytes(3);
cfd1->RecalculateWriteStallConditions(mutable_cf_options); cfd1->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(9); vstorage->set_l0_delay_trigger_count(9);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage1->set_l0_delay_trigger_count(2); vstorage1->set_l0_delay_trigger_count(2);
cfd1->RecalculateWriteStallConditions(mutable_cf_options); cfd1->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
vstorage->set_l0_delay_trigger_count(0); vstorage->set_l0_delay_trigger_count(0);
cfd->RecalculateWriteStallConditions(mutable_cf_options); cfd->RecalculateWriteStallConditions(mutable_cf_options);
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed()); ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
} }
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE

@ -307,8 +307,9 @@ void DumpSupportInfo(Logger* logger) {
DBImpl::DBImpl(const DBOptions& options, const std::string& dbname) DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
: env_(options.env), : env_(options.env),
dbname_(dbname), dbname_(dbname),
immutable_db_options_(SanitizeOptions(dbname, options)), initial_db_options_(SanitizeOptions(dbname, options)),
mutable_db_options_(options), immutable_db_options_(initial_db_options_),
mutable_db_options_(initial_db_options_),
stats_(immutable_db_options_.statistics.get()), stats_(immutable_db_options_.statistics.get()),
db_lock_(nullptr), db_lock_(nullptr),
mutex_(stats_, env_, DB_MUTEX_WAIT_MICROS, mutex_(stats_, env_, DB_MUTEX_WAIT_MICROS,
@ -2434,13 +2435,7 @@ Status DBImpl::SetOptions(ColumnFamilyHandle* column_family,
InstallSuperVersionAndScheduleWork(cfd, nullptr, new_options); InstallSuperVersionAndScheduleWork(cfd, nullptr, new_options);
delete old_sv; delete old_sv;
// Persist RocksDB options under the single write thread persist_options_status = PersistOptions();
WriteThread::Writer w;
write_thread_.EnterUnbatched(&w, &mutex_);
persist_options_status = WriteOptionsFile();
write_thread_.ExitUnbatched(&w);
} }
} }
@ -2452,12 +2447,12 @@ Status DBImpl::SetOptions(ColumnFamilyHandle* column_family,
} }
if (s.ok()) { if (s.ok()) {
Log(InfoLogLevel::INFO_LEVEL, immutable_db_options_.info_log, Log(InfoLogLevel::INFO_LEVEL, immutable_db_options_.info_log,
"[%s] SetOptions succeeded", cfd->GetName().c_str()); "[%s] SetOptions() succeeded", cfd->GetName().c_str());
new_options.Dump(immutable_db_options_.info_log.get()); new_options.Dump(immutable_db_options_.info_log.get());
if (!persist_options_status.ok()) { if (!persist_options_status.ok()) {
if (immutable_db_options_.fail_if_options_file_error) { if (immutable_db_options_.fail_if_options_file_error) {
s = Status::IOError( s = Status::IOError(
"SetOptions succeeded, but unable to persist options", "SetOptions() succeeded, but unable to persist options",
persist_options_status.ToString()); persist_options_status.ToString());
} }
Warn(immutable_db_options_.info_log, Warn(immutable_db_options_.info_log,
@ -2466,13 +2461,82 @@ Status DBImpl::SetOptions(ColumnFamilyHandle* column_family,
} }
} else { } else {
Log(InfoLogLevel::WARN_LEVEL, immutable_db_options_.info_log, Log(InfoLogLevel::WARN_LEVEL, immutable_db_options_.info_log,
"[%s] SetOptions failed", cfd->GetName().c_str()); "[%s] SetOptions() failed", cfd->GetName().c_str());
} }
LogFlush(immutable_db_options_.info_log); LogFlush(immutable_db_options_.info_log);
return s; return s;
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
} }
Status DBImpl::SetDBOptions(
const std::unordered_map<std::string, std::string>& options_map) {
#ifdef ROCKSDB_LITE
return Status::NotSupported("Not supported in ROCKSDB LITE");
#else
if (options_map.empty()) {
Log(InfoLogLevel::WARN_LEVEL, immutable_db_options_.info_log,
"SetDBOptions(), empty input.");
return Status::InvalidArgument("empty input");
}
MutableDBOptions new_options;
Status s;
Status persist_options_status;
{
InstrumentedMutexLock l(&mutex_);
s = GetMutableDBOptionsFromStrings(mutable_db_options_, options_map,
&new_options);
if (s.ok()) {
if (new_options.max_background_compactions >
mutable_db_options_.max_background_compactions) {
env_->IncBackgroundThreadsIfNeeded(
new_options.max_background_compactions, Env::Priority::LOW);
MaybeScheduleFlushOrCompaction();
}
mutable_db_options_ = new_options;
persist_options_status = PersistOptions();
}
}
Log(InfoLogLevel::INFO_LEVEL, immutable_db_options_.info_log,
"SetDBOptions(), inputs:");
for (const auto& o : options_map) {
Log(InfoLogLevel::INFO_LEVEL, immutable_db_options_.info_log, "%s: %s\n",
o.first.c_str(), o.second.c_str());
}
if (s.ok()) {
Log(InfoLogLevel::INFO_LEVEL, immutable_db_options_.info_log,
"SetDBOptions() succeeded");
new_options.Dump(immutable_db_options_.info_log.get());
if (!persist_options_status.ok()) {
if (immutable_db_options_.fail_if_options_file_error) {
s = Status::IOError(
"SetDBOptions() succeeded, but unable to persist options",
persist_options_status.ToString());
}
Warn(immutable_db_options_.info_log,
"Unable to persist options in SetDBOptions() -- %s",
persist_options_status.ToString().c_str());
}
} else {
Log(InfoLogLevel::WARN_LEVEL, immutable_db_options_.info_log,
"SetDBOptions failed");
}
LogFlush(immutable_db_options_.info_log);
return s;
#endif // ROCKSDB_LITE
}
Status DBImpl::PersistOptions() {
mutex_.AssertHeld();
WriteThread::Writer w;
write_thread_.EnterUnbatched(&w, &mutex_);
Status s = WriteOptionsFile();
write_thread_.ExitUnbatched(&w);
return s;
}
// return the same level if it cannot be moved // return the same level if it cannot be moved
int DBImpl::FindMinimumEmptyLevelFitting(ColumnFamilyData* cfd, int DBImpl::FindMinimumEmptyLevelFitting(ColumnFamilyData* cfd,
const MutableCFOptions& mutable_cf_options, int level) { const MutableCFOptions& mutable_cf_options, int level) {
@ -2957,10 +3021,11 @@ void DBImpl::SchedulePurge() {
} }
int DBImpl::BGCompactionsAllowed() const { int DBImpl::BGCompactionsAllowed() const {
mutex_.AssertHeld();
if (write_controller_.NeedSpeedupCompaction()) { if (write_controller_.NeedSpeedupCompaction()) {
return immutable_db_options_.max_background_compactions; return mutable_db_options_.max_background_compactions;
} else { } else {
return immutable_db_options_.base_background_compactions; return mutable_db_options_.base_background_compactions;
} }
} }

@ -156,6 +156,9 @@ class DBImpl : public DB {
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,
const std::unordered_map<std::string, std::string>& options_map) override; const std::unordered_map<std::string, std::string>& options_map) override;
virtual Status SetDBOptions(
const std::unordered_map<std::string, std::string>& options_map) override;
using DB::NumberLevels; using DB::NumberLevels;
virtual int NumberLevels(ColumnFamilyHandle* column_family) override; virtual int NumberLevels(ColumnFamilyHandle* column_family) override;
using DB::MaxMemCompactionLevel; using DB::MaxMemCompactionLevel;
@ -360,6 +363,8 @@ class DBImpl : public DB {
uint64_t TEST_FindMinLogContainingOutstandingPrep(); uint64_t TEST_FindMinLogContainingOutstandingPrep();
uint64_t TEST_FindMinPrepLogReferencedByMemTable(); uint64_t TEST_FindMinPrepLogReferencedByMemTable();
int TEST_BGCompactionsAllowed() const;
#endif // NDEBUG #endif // NDEBUG
// Return maximum background compaction allowed to be scheduled based on // Return maximum background compaction allowed to be scheduled based on
@ -508,6 +513,7 @@ class DBImpl : public DB {
Env* const env_; Env* const env_;
const std::string dbname_; const std::string dbname_;
unique_ptr<VersionSet> versions_; unique_ptr<VersionSet> versions_;
const DBOptions initial_db_options_;
const ImmutableDBOptions immutable_db_options_; const ImmutableDBOptions immutable_db_options_;
MutableDBOptions mutable_db_options_; MutableDBOptions mutable_db_options_;
Statistics* stats_; Statistics* stats_;
@ -716,6 +722,10 @@ class DBImpl : public DB {
const Snapshot* GetSnapshotImpl(bool is_write_conflict_boundary); const Snapshot* GetSnapshotImpl(bool is_write_conflict_boundary);
// Persist RocksDB options under the single write thread
// REQUIRES: mutex locked
Status PersistOptions();
// table_cache_ provides its own synchronization // table_cache_ provides its own synchronization
std::shared_ptr<Cache> table_cache_; std::shared_ptr<Cache> table_cache_;

@ -178,5 +178,10 @@ Status DBImpl::TEST_GetLatestMutableCFOptions(
return Status::OK(); return Status::OK();
} }
int DBImpl::TEST_BGCompactionsAllowed() const {
InstrumentedMutexLock l(&mutex_);
return BGCompactionsAllowed();
}
} // namespace rocksdb } // namespace rocksdb
#endif // NDEBUG #endif // NDEBUG

@ -11,6 +11,7 @@
#include <unordered_map> #include <unordered_map>
#include "db/column_family.h" #include "db/column_family.h"
#include "db/db_impl.h"
#include "db/db_test_util.h" #include "db/db_test_util.h"
#include "port/stack_trace.h" #include "port/stack_trace.h"
#include "rocksdb/convenience.h" #include "rocksdb/convenience.h"
@ -26,6 +27,22 @@ class DBOptionsTest : public DBTestBase {
DBOptionsTest() : DBTestBase("/db_options_test") {} DBOptionsTest() : DBTestBase("/db_options_test") {}
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
std::unordered_map<std::string, std::string> GetMutableDBOptionsMap(
const DBOptions& options) {
std::string options_str;
GetStringFromDBOptions(&options_str, options);
std::unordered_map<std::string, std::string> options_map;
StringToMap(options_str, &options_map);
std::unordered_map<std::string, std::string> mutable_map;
for (const auto opt : db_options_type_info) {
if (opt.second.is_mutable &&
opt.second.verification != OptionVerificationType::kDeprecated) {
mutable_map[opt.first] = options_map[opt.first];
}
}
return mutable_map;
}
std::unordered_map<std::string, std::string> GetMutableCFOptionsMap( std::unordered_map<std::string, std::string> GetMutableCFOptionsMap(
const ColumnFamilyOptions& options) { const ColumnFamilyOptions& options) {
std::string options_str; std::string options_str;
@ -52,13 +69,32 @@ class DBOptionsTest : public DBTestBase {
delete options.compaction_filter; delete options.compaction_filter;
return opt_map; return opt_map;
} }
std::unordered_map<std::string, std::string> GetRandomizedMutableDBOptionsMap(
Random* rnd) {
DBOptions db_options;
test::RandomInitDBOptions(&db_options, rnd);
auto sanitized_options = SanitizeOptions(dbname_, db_options);
return GetMutableDBOptionsMap(sanitized_options);
}
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
}; };
// RocksDB lite don't support dynamic options. // RocksDB lite don't support dynamic options.
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
TEST_F(DBOptionsTest, GetLatestOptions) { TEST_F(DBOptionsTest, GetLatestDBOptions) {
// GetOptions should be able to get latest option changed by SetOptions.
Options options;
options.create_if_missing = true;
Random rnd(228);
Reopen(options);
auto new_options = GetRandomizedMutableDBOptionsMap(&rnd);
ASSERT_OK(dbfull()->SetDBOptions(new_options));
ASSERT_EQ(new_options, GetMutableDBOptionsMap(dbfull()->GetDBOptions()));
}
TEST_F(DBOptionsTest, GetLatestCFOptions) {
// GetOptions should be able to get latest option changed by SetOptions. // GetOptions should be able to get latest option changed by SetOptions.
Options options; Options options;
options.create_if_missing = true; options.create_if_missing = true;
@ -206,6 +242,20 @@ TEST_F(DBOptionsTest, SetOptionsMayTriggerCompaction) {
ASSERT_EQ("0,1", FilesPerLevel()); ASSERT_EQ("0,1", FilesPerLevel());
} }
TEST_F(DBOptionsTest, SetBackgroundCompactionThreads) {
Options options;
options.create_if_missing = true;
options.base_background_compactions = 1; // default value
options.max_background_compactions = 1; // default value
Reopen(options);
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
ASSERT_OK(dbfull()->SetDBOptions({{"base_background_compactions", "2"},
{"max_background_compactions", "3"}}));
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
auto stop_token = dbfull()->TEST_write_controler().GetStopToken();
ASSERT_EQ(3, dbfull()->TEST_BGCompactionsAllowed());
}
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
} // namespace rocksdb } // namespace rocksdb

@ -2762,6 +2762,12 @@ class ModelDB : public DB {
return Status::NotSupported("Not supported operation."); return Status::NotSupported("Not supported operation.");
} }
virtual Status SetDBOptions(
const std::unordered_map<std::string, std::string>& new_options)
override {
return Status::NotSupported("Not supported operation.");
}
using DB::CompactFiles; using DB::CompactFiles;
virtual Status CompactFiles(const CompactionOptions& compact_options, virtual Status CompactFiles(const CompactionOptions& compact_options,
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,

@ -629,6 +629,9 @@ class DB {
return SetOptions(DefaultColumnFamily(), new_options); return SetOptions(DefaultColumnFamily(), new_options);
} }
virtual Status SetDBOptions(
const std::unordered_map<std::string, std::string>& new_options) = 0;
// CompactFiles() inputs a list of files specified by file numbers and // CompactFiles() inputs a list of files specified by file numbers and
// compacts them to the specified level. Note that the behavior is different // compacts them to the specified level. Note that the behavior is different
// from CompactRange() in that CompactFiles() performs the compaction job // from CompactRange() in that CompactFiles() performs the compaction job

@ -289,6 +289,12 @@ class StackableDB : public DB {
return db_->SetOptions(column_family_handle, new_options); return db_->SetOptions(column_family_handle, new_options);
} }
virtual Status SetDBOptions(
const std::unordered_map<std::string, std::string>& new_options)
override {
return db_->SetDBOptions(new_options);
}
using DB::GetPropertiesOfAllTables; using DB::GetPropertiesOfAllTables;
virtual Status GetPropertiesOfAllTables( virtual Status GetPropertiesOfAllTables(
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,

@ -42,8 +42,6 @@ ImmutableDBOptions::ImmutableDBOptions(const DBOptions& options)
wal_dir(options.wal_dir), wal_dir(options.wal_dir),
delete_obsolete_files_period_micros( delete_obsolete_files_period_micros(
options.delete_obsolete_files_period_micros), options.delete_obsolete_files_period_micros),
base_background_compactions(options.base_background_compactions),
max_background_compactions(options.max_background_compactions),
max_subcompactions(options.max_subcompactions), max_subcompactions(options.max_subcompactions),
max_background_flushes(options.max_background_flushes), max_background_flushes(options.max_background_flushes),
max_log_file_size(options.max_log_file_size), max_log_file_size(options.max_log_file_size),
@ -144,10 +142,6 @@ void ImmutableDBOptions::Dump(Logger* log) const {
table_cache_numshardbits); table_cache_numshardbits);
Header(log, " Options.delete_obsolete_files_period_micros: %" PRIu64, Header(log, " Options.delete_obsolete_files_period_micros: %" PRIu64,
delete_obsolete_files_period_micros); delete_obsolete_files_period_micros);
Header(log, " Options.base_background_compactions: %d",
base_background_compactions);
Header(log, " Options.max_background_compactions: %d",
max_background_compactions);
Header(log, " Options.max_subcompactions: %" PRIu32, Header(log, " Options.max_subcompactions: %" PRIu32,
max_subcompactions); max_subcompactions);
Header(log, " Options.max_background_flushes: %d", Header(log, " Options.max_background_flushes: %d",
@ -202,8 +196,8 @@ void ImmutableDBOptions::Dump(Logger* log) const {
wal_recovery_mode); wal_recovery_mode);
Header(log, " Options.enable_thread_tracking: %d", Header(log, " Options.enable_thread_tracking: %d",
enable_thread_tracking); enable_thread_tracking);
Log(log, " Options.delayed_write_rate : %" PRIu64, Header(log, " Options.delayed_write_rate : %" PRIu64,
delayed_write_rate); delayed_write_rate);
Header(log, " Options.allow_concurrent_memtable_write: %d", Header(log, " Options.allow_concurrent_memtable_write: %d",
allow_concurrent_memtable_write); allow_concurrent_memtable_write);
Header(log, " Options.enable_write_thread_adaptive_yield: %d", Header(log, " Options.enable_write_thread_adaptive_yield: %d",
@ -226,8 +220,18 @@ void ImmutableDBOptions::Dump(Logger* log) const {
avoid_flush_during_recovery); avoid_flush_during_recovery);
} }
MutableDBOptions::MutableDBOptions(const DBOptions& options) {} MutableDBOptions::MutableDBOptions()
: base_background_compactions(1), max_background_compactions(1) {}
MutableDBOptions::MutableDBOptions(const DBOptions& options)
: base_background_compactions(options.base_background_compactions),
max_background_compactions(options.max_background_compactions) {}
void MutableDBOptions::Dump(Logger* log) const {} void MutableDBOptions::Dump(Logger* log) const {
Header(log, " Options.base_background_compactions: %d",
base_background_compactions);
Header(log, " Options.max_background_compactions: %d",
max_background_compactions);
}
} // namespace rocksdb } // namespace rocksdb

@ -37,8 +37,6 @@ struct ImmutableDBOptions {
std::string db_log_dir; std::string db_log_dir;
std::string wal_dir; std::string wal_dir;
uint64_t delete_obsolete_files_period_micros; uint64_t delete_obsolete_files_period_micros;
int base_background_compactions;
int max_background_compactions;
uint32_t max_subcompactions; uint32_t max_subcompactions;
int max_background_flushes; int max_background_flushes;
size_t max_log_file_size; size_t max_log_file_size;
@ -87,10 +85,14 @@ struct ImmutableDBOptions {
}; };
struct MutableDBOptions { struct MutableDBOptions {
MutableDBOptions();
explicit MutableDBOptions(const MutableDBOptions& options) = default; explicit MutableDBOptions(const MutableDBOptions& options) = default;
explicit MutableDBOptions(const DBOptions& options); explicit MutableDBOptions(const DBOptions& options);
void Dump(Logger* log) const; void Dump(Logger* log) const;
int base_background_compactions;
int max_background_compactions;
}; };
} // namespace rocksdb } // namespace rocksdb

@ -53,9 +53,9 @@ DBOptions BuildDBOptions(const ImmutableDBOptions& immutable_db_options,
options.delete_obsolete_files_period_micros = options.delete_obsolete_files_period_micros =
immutable_db_options.delete_obsolete_files_period_micros; immutable_db_options.delete_obsolete_files_period_micros;
options.base_background_compactions = options.base_background_compactions =
immutable_db_options.base_background_compactions; mutable_db_options.base_background_compactions;
options.max_background_compactions = options.max_background_compactions =
immutable_db_options.max_background_compactions; mutable_db_options.max_background_compactions;
options.max_subcompactions = immutable_db_options.max_subcompactions; options.max_subcompactions = immutable_db_options.max_subcompactions;
options.max_background_flushes = immutable_db_options.max_background_flushes; options.max_background_flushes = immutable_db_options.max_background_flushes;
options.max_log_file_size = immutable_db_options.max_log_file_size; options.max_log_file_size = immutable_db_options.max_log_file_size;
@ -754,6 +754,36 @@ Status GetMutableOptionsFromStrings(
return Status::OK(); return Status::OK();
} }
Status GetMutableDBOptionsFromStrings(
const MutableDBOptions& base_options,
const std::unordered_map<std::string, std::string>& options_map,
MutableDBOptions* new_options) {
assert(new_options);
*new_options = base_options;
for (const auto& o : options_map) {
try {
auto iter = db_options_type_info.find(o.first);
if (iter == db_options_type_info.end()) {
return Status::InvalidArgument("Unrecognized option: " + o.first);
}
const auto& opt_info = iter->second;
if (!opt_info.is_mutable) {
return Status::InvalidArgument("Option not changeable: " + o.first);
}
bool is_ok = ParseOptionHelper(
reinterpret_cast<char*>(new_options) + opt_info.mutable_offset,
opt_info.type, o.second);
if (!is_ok) {
return Status::InvalidArgument("Error parsing " + o.first);
}
} catch (std::exception& e) {
return Status::InvalidArgument("Error parsing " + o.first + ":" +
std::string(e.what()));
}
}
return Status::OK();
}
Status StringToMap(const std::string& opts_str, Status StringToMap(const std::string& opts_str,
std::unordered_map<std::string, std::string>* opts_map) { std::unordered_map<std::string, std::string>* opts_map) {
assert(opts_map); assert(opts_map);

@ -69,6 +69,11 @@ Status GetMutableOptionsFromStrings(
const std::unordered_map<std::string, std::string>& options_map, const std::unordered_map<std::string, std::string>& options_map,
MutableCFOptions* new_options); MutableCFOptions* new_options);
Status GetMutableDBOptionsFromStrings(
const MutableDBOptions& base_options,
const std::unordered_map<std::string, std::string>& options_map,
MutableDBOptions* new_options);
Status GetTableFactoryFromMap( Status GetTableFactoryFromMap(
const std::string& factory_name, const std::string& factory_name,
const std::unordered_map<std::string, std::string>& opt_map, const std::unordered_map<std::string, std::string>& opt_map,
@ -234,10 +239,12 @@ static std::unordered_map<std::string, OptionTypeInfo> db_options_type_info = {
OptionVerificationType::kNormal, false, 0}}, OptionVerificationType::kNormal, false, 0}},
{"max_background_compactions", {"max_background_compactions",
{offsetof(struct DBOptions, max_background_compactions), OptionType::kInt, {offsetof(struct DBOptions, max_background_compactions), OptionType::kInt,
OptionVerificationType::kNormal, false, 0}}, OptionVerificationType::kNormal, true,
offsetof(struct MutableDBOptions, max_background_compactions)}},
{"base_background_compactions", {"base_background_compactions",
{offsetof(struct DBOptions, base_background_compactions), OptionType::kInt, {offsetof(struct DBOptions, base_background_compactions), OptionType::kInt,
OptionVerificationType::kNormal, false, 0}}, OptionVerificationType::kNormal, true,
offsetof(struct MutableDBOptions, base_background_compactions)}},
{"max_background_flushes", {"max_background_flushes",
{offsetof(struct DBOptions, max_background_flushes), OptionType::kInt, {offsetof(struct DBOptions, max_background_flushes), OptionType::kInt,
OptionVerificationType::kNormal, false, 0}}, OptionVerificationType::kNormal, false, 0}},

Loading…
Cancel
Save