support OnCompactionBegin (#4431)

Summary:
fix #4288

Add `OnCompactionBegin` support to `rocksdb::EventListener`.

Currently, we only have these three callbacks:

- OnFlushBegin
- OnFlushCompleted
- OnCompactionCompleted

As paolococchi requested in #4288 , and ajkr agreed, we should also support `OnCompactionBegin`.

This PR is a try to implement the support of `OnCompactionBegin`.

Hope it is useful to you.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4431

Differential Revision: D10055515

Pulled By: yiwu-arbug

fbshipit-source-id: 39c0f95f8e9ff1c7ca3a10787502a17f258d2334
This commit is contained in:
Peter Pei 2018-10-10 17:30:22 -07:00 committed by Facebook Github Bot
parent f8c1de4c7c
commit 09814f2cfc
4 changed files with 104 additions and 2 deletions

View File

@ -735,6 +735,11 @@ class DBImpl : public DB {
const MutableCFOptions& mutable_cf_options, const MutableCFOptions& mutable_cf_options,
int job_id, TableProperties prop); int job_id, TableProperties prop);
void NotifyOnCompactionBegin(ColumnFamilyData* cfd,
Compaction *c, const Status &st,
const CompactionJobStats& job_stats,
int job_id);
void NotifyOnCompactionCompleted(ColumnFamilyData* cfd, void NotifyOnCompactionCompleted(ColumnFamilyData* cfd,
Compaction *c, const Status &st, Compaction *c, const Status &st,
const CompactionJobStats& job_stats, const CompactionJobStats& job_stats,

View File

@ -744,6 +744,69 @@ Status DBImpl::ContinueBackgroundWork() {
return Status::OK(); return Status::OK();
} }
void DBImpl::NotifyOnCompactionBegin(ColumnFamilyData* cfd,
Compaction *c, const Status &st,
const CompactionJobStats& job_stats,
int job_id) {
#ifndef ROCKSDB_LITE
if (immutable_db_options_.listeners.empty()) {
return;
}
mutex_.AssertHeld();
if (shutting_down_.load(std::memory_order_acquire)) {
return;
}
Version* current = cfd->current();
current->Ref();
// release lock while notifying events
mutex_.Unlock();
TEST_SYNC_POINT("DBImpl::NotifyOnCompactionBegin::UnlockMutex");
{
CompactionJobInfo info;
info.cf_name = cfd->GetName();
info.status = st;
info.thread_id = env_->GetThreadID();
info.job_id = job_id;
info.base_input_level = c->start_level();
info.output_level = c->output_level();
info.stats = job_stats;
info.table_properties = c->GetOutputTableProperties();
info.compaction_reason = c->compaction_reason();
info.compression = c->output_compression();
for (size_t i = 0; i < c->num_input_levels(); ++i) {
for (const auto fmd : *c->inputs(i)) {
auto fn = TableFileName(c->immutable_cf_options()->cf_paths,
fmd->fd.GetNumber(), fmd->fd.GetPathId());
info.input_files.push_back(fn);
if (info.table_properties.count(fn) == 0) {
std::shared_ptr<const TableProperties> tp;
auto s = current->GetTableProperties(&tp, fmd, &fn);
if (s.ok()) {
info.table_properties[fn] = tp;
}
}
}
}
for (const auto newf : c->edit()->GetNewFiles()) {
info.output_files.push_back(TableFileName(
c->immutable_cf_options()->cf_paths, newf.second.fd.GetNumber(),
newf.second.fd.GetPathId()));
}
for (auto listener : immutable_db_options_.listeners) {
listener->OnCompactionBegin(this, info);
}
}
mutex_.Lock();
current->Unref();
#else
(void)cfd;
(void)c;
(void)st;
(void)job_stats;
(void)job_id;
#endif // ROCKSDB_LITE
}
void DBImpl::NotifyOnCompactionCompleted( void DBImpl::NotifyOnCompactionCompleted(
ColumnFamilyData* cfd, Compaction* c, const Status& st, ColumnFamilyData* cfd, Compaction* c, const Status& st,
const CompactionJobStats& compaction_job_stats, const int job_id) { const CompactionJobStats& compaction_job_stats, const int job_id) {
@ -1945,6 +2008,9 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
compaction_job_stats.num_input_files = c->num_input_files(0); compaction_job_stats.num_input_files = c->num_input_files(0);
NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
compaction_job_stats, job_context->job_id);
for (const auto& f : *c->inputs(0)) { for (const auto& f : *c->inputs(0)) {
c->edit()->DeleteFile(c->level(), f->fd.GetNumber()); c->edit()->DeleteFile(c->level(), f->fd.GetNumber());
} }
@ -1969,6 +2035,9 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
compaction_job_stats.num_input_files = c->num_input_files(0); compaction_job_stats.num_input_files = c->num_input_files(0);
NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
compaction_job_stats, job_context->job_id);
// Move files to next level // Move files to next level
int32_t moved_files = 0; int32_t moved_files = 0;
int64_t moved_bytes = 0; int64_t moved_bytes = 0;
@ -2068,6 +2137,9 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
&compaction_job_stats); &compaction_job_stats);
compaction_job.Prepare(); compaction_job.Prepare();
NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
compaction_job_stats, job_context->job_id);
mutex_.Unlock(); mutex_.Unlock();
compaction_job.Run(); compaction_job.Run();
TEST_SYNC_POINT("DBImpl::BackgroundCompaction:NonTrivial:AfterRun"); TEST_SYNC_POINT("DBImpl::BackgroundCompaction:NonTrivial:AfterRun");

View File

@ -1228,7 +1228,14 @@ TEST_F(DBTest2, CompressionOptions) {
class CompactionStallTestListener : public EventListener { class CompactionStallTestListener : public EventListener {
public: public:
CompactionStallTestListener() : compacted_files_cnt_(0) {} CompactionStallTestListener() : compacting_files_cnt_(0), compacted_files_cnt_(0) {}
void OnCompactionBegin(DB* /*db*/, const CompactionJobInfo& ci) override {
ASSERT_EQ(ci.cf_name, "default");
ASSERT_EQ(ci.base_input_level, 0);
ASSERT_EQ(ci.compaction_reason, CompactionReason::kLevelL0FilesNum);
compacting_files_cnt_ += ci.input_files.size();
}
void OnCompactionCompleted(DB* /*db*/, const CompactionJobInfo& ci) override { void OnCompactionCompleted(DB* /*db*/, const CompactionJobInfo& ci) override {
ASSERT_EQ(ci.cf_name, "default"); ASSERT_EQ(ci.cf_name, "default");
@ -1236,6 +1243,8 @@ class CompactionStallTestListener : public EventListener {
ASSERT_EQ(ci.compaction_reason, CompactionReason::kLevelL0FilesNum); ASSERT_EQ(ci.compaction_reason, CompactionReason::kLevelL0FilesNum);
compacted_files_cnt_ += ci.input_files.size(); compacted_files_cnt_ += ci.input_files.size();
} }
std::atomic<size_t> compacting_files_cnt_;
std::atomic<size_t> compacted_files_cnt_; std::atomic<size_t> compacted_files_cnt_;
}; };
@ -1244,6 +1253,8 @@ TEST_F(DBTest2, CompactionStall) {
{{"DBImpl::BGWorkCompaction", "DBTest2::CompactionStall:0"}, {{"DBImpl::BGWorkCompaction", "DBTest2::CompactionStall:0"},
{"DBImpl::BGWorkCompaction", "DBTest2::CompactionStall:1"}, {"DBImpl::BGWorkCompaction", "DBTest2::CompactionStall:1"},
{"DBTest2::CompactionStall:2", {"DBTest2::CompactionStall:2",
"DBImpl::NotifyOnCompactionBegin::UnlockMutex"},
{"DBTest2::CompactionStall:3",
"DBImpl::NotifyOnCompactionCompleted::UnlockMutex"}}); "DBImpl::NotifyOnCompactionCompleted::UnlockMutex"}});
rocksdb::SyncPoint::GetInstance()->EnableProcessing(); rocksdb::SyncPoint::GetInstance()->EnableProcessing();
@ -1285,14 +1296,18 @@ TEST_F(DBTest2, CompactionStall) {
// Wait for another compaction to be triggered // Wait for another compaction to be triggered
TEST_SYNC_POINT("DBTest2::CompactionStall:1"); TEST_SYNC_POINT("DBTest2::CompactionStall:1");
// Hold NotifyOnCompactionCompleted in the unlock mutex section // Hold NotifyOnCompactionBegin in the unlock mutex section
TEST_SYNC_POINT("DBTest2::CompactionStall:2"); TEST_SYNC_POINT("DBTest2::CompactionStall:2");
// Hold NotifyOnCompactionCompleted in the unlock mutex section
TEST_SYNC_POINT("DBTest2::CompactionStall:3");
dbfull()->TEST_WaitForCompact(); dbfull()->TEST_WaitForCompact();
ASSERT_LT(NumTableFilesAtLevel(0), ASSERT_LT(NumTableFilesAtLevel(0),
options.level0_file_num_compaction_trigger); options.level0_file_num_compaction_trigger);
ASSERT_GT(listener->compacted_files_cnt_.load(), ASSERT_GT(listener->compacted_files_cnt_.load(),
10 - options.level0_file_num_compaction_trigger); 10 - options.level0_file_num_compaction_trigger);
ASSERT_EQ(listener->compacting_files_cnt_.load(), listener->compacted_files_cnt_.load());
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
} }

View File

@ -299,6 +299,16 @@ class EventListener {
// returned value. // returned value.
virtual void OnTableFileDeleted(const TableFileDeletionInfo& /*info*/) {} virtual void OnTableFileDeleted(const TableFileDeletionInfo& /*info*/) {}
// A callback function to RocksDB which will be called before a
// RocksDB starts to compact. The default implementation is
// no-op.
//
// Note that the this function must be implemented in a way such that
// it should not run for an extended period of time before the function
// returns. Otherwise, RocksDB may be blocked.
virtual void OnCompactionBegin(DB* /*db*/,
const CompactionJobInfo& /*ci*/) {}
// A callback function for RocksDB which will be called whenever // A callback function for RocksDB which will be called whenever
// a registered RocksDB compacts a file. The default implementation // a registered RocksDB compacts a file. The default implementation
// is a no-op. // is a no-op.