Skip to content

Commit 9fe3a53

Browse files
jay-zhuangajkr
authored andcommitted
DisableManualCompaction may fail to cancel an unscheduled task (#9659)
Summary: #9625 didn't change the unschedule condition which was waiting for the background thread to clean-up the compaction. make sure we only unschedule the task when it's scheduled. Pull Request resolved: #9659 Reviewed By: ajkr Differential Revision: D34651820 Pulled By: jay-zhuang fbshipit-source-id: 23f42081b15ec8886cd81cbf131b116e0c74dc2f
1 parent 22e011f commit 9fe3a53

File tree

6 files changed

+189
-66
lines changed

6 files changed

+189
-66
lines changed

HISTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Rocksdb Change Log
2+
## Unreleased
3+
* Fixed a bug that DisableManualCompaction may assert when disable an unscheduled manual compaction.
4+
25
## 7.0.1 (03/02/2022)
36
### Bug Fixes
47
* Fix a race condition when cancel manual compaction with `DisableManualCompaction`. Also DB close can cancel the manual compaction thread.

db/column_family.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,6 @@ WriteStallCondition ColumnFamilyData::RecalculateWriteStallConditions(
989989
GetL0ThresholdSpeedupCompaction(
990990
mutable_cf_options.level0_file_num_compaction_trigger,
991991
mutable_cf_options.level0_slowdown_writes_trigger)) {
992-
fprintf(stdout, "JJJ2\n");
993992
write_controller_token_ =
994993
write_controller->GetCompactionPressureToken();
995994
ROCKS_LOG_INFO(

db/compaction/compaction_picker_universal.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ Compaction* UniversalCompactionBuilder::PickCompaction() {
372372
const int kLevel0 = 0;
373373
score_ = vstorage_->CompactionScore(kLevel0);
374374
sorted_runs_ = CalculateSortedRuns(*vstorage_);
375-
fprintf(stdout, "JJJ1\n");
376375

377376
if (sorted_runs_.size() == 0 ||
378377
(vstorage_->FilesMarkedForPeriodicCompaction().empty() &&

db/db_compaction_test.cc

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6889,6 +6889,112 @@ TEST_F(DBCompactionTest, FIFOWarm) {
68896889
Destroy(options);
68906890
}
68916891

6892+
TEST_F(DBCompactionTest, DisableMultiManualCompaction) {
6893+
const int kNumL0Files = 10;
6894+
6895+
Options options = CurrentOptions();
6896+
options.level0_file_num_compaction_trigger = kNumL0Files;
6897+
Reopen(options);
6898+
6899+
// Generate 2 levels of file to make sure the manual compaction is not skipped
6900+
for (int i = 0; i < 10; i++) {
6901+
ASSERT_OK(Put(Key(i), "value"));
6902+
if (i % 2) {
6903+
ASSERT_OK(Flush());
6904+
}
6905+
}
6906+
MoveFilesToLevel(2);
6907+
6908+
for (int i = 0; i < 10; i++) {
6909+
ASSERT_OK(Put(Key(i), "value"));
6910+
if (i % 2) {
6911+
ASSERT_OK(Flush());
6912+
}
6913+
}
6914+
MoveFilesToLevel(1);
6915+
6916+
// Block compaction queue
6917+
test::SleepingBackgroundTask sleeping_task_low;
6918+
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask, &sleeping_task_low,
6919+
Env::Priority::LOW);
6920+
6921+
port::Thread compact_thread1([&]() {
6922+
CompactRangeOptions cro;
6923+
cro.exclusive_manual_compaction = false;
6924+
std::string begin_str = Key(0);
6925+
std::string end_str = Key(3);
6926+
Slice b = begin_str;
6927+
Slice e = end_str;
6928+
auto s = db_->CompactRange(cro, &b, &e);
6929+
ASSERT_TRUE(s.IsIncomplete());
6930+
});
6931+
6932+
port::Thread compact_thread2([&]() {
6933+
CompactRangeOptions cro;
6934+
cro.exclusive_manual_compaction = false;
6935+
std::string begin_str = Key(4);
6936+
std::string end_str = Key(7);
6937+
Slice b = begin_str;
6938+
Slice e = end_str;
6939+
auto s = db_->CompactRange(cro, &b, &e);
6940+
ASSERT_TRUE(s.IsIncomplete());
6941+
});
6942+
6943+
// Disable manual compaction should cancel both manual compactions and both
6944+
// compaction should return incomplete.
6945+
db_->DisableManualCompaction();
6946+
6947+
compact_thread1.join();
6948+
compact_thread2.join();
6949+
6950+
sleeping_task_low.WakeUp();
6951+
sleeping_task_low.WaitUntilDone();
6952+
ASSERT_OK(dbfull()->TEST_WaitForCompact(true));
6953+
}
6954+
6955+
TEST_F(DBCompactionTest, DisableJustStartedManualCompaction) {
6956+
const int kNumL0Files = 4;
6957+
6958+
Options options = CurrentOptions();
6959+
options.level0_file_num_compaction_trigger = kNumL0Files;
6960+
Reopen(options);
6961+
6962+
// generate files, but avoid trigger auto compaction
6963+
for (int i = 0; i < kNumL0Files / 2; i++) {
6964+
ASSERT_OK(Put(Key(1), "value1"));
6965+
ASSERT_OK(Put(Key(2), "value2"));
6966+
ASSERT_OK(Flush());
6967+
}
6968+
6969+
// make sure the manual compaction background is started but not yet set the
6970+
// status to in_progress, then cancel the manual compaction, which should not
6971+
// result in segfault
6972+
SyncPoint::GetInstance()->LoadDependency(
6973+
{{"DBImpl::BGWorkCompaction",
6974+
"DBCompactionTest::DisableJustStartedManualCompaction:"
6975+
"PreDisableManualCompaction"},
6976+
{"DBCompactionTest::DisableJustStartedManualCompaction:"
6977+
"ManualCompactionReturn",
6978+
"BackgroundCallCompaction:0"}});
6979+
SyncPoint::GetInstance()->EnableProcessing();
6980+
6981+
port::Thread compact_thread([&]() {
6982+
CompactRangeOptions cro;
6983+
cro.exclusive_manual_compaction = true;
6984+
auto s = db_->CompactRange(cro, nullptr, nullptr);
6985+
ASSERT_TRUE(s.IsIncomplete());
6986+
TEST_SYNC_POINT(
6987+
"DBCompactionTest::DisableJustStartedManualCompaction:"
6988+
"ManualCompactionReturn");
6989+
});
6990+
TEST_SYNC_POINT(
6991+
"DBCompactionTest::DisableJustStartedManualCompaction:"
6992+
"PreDisableManualCompaction");
6993+
db_->DisableManualCompaction();
6994+
6995+
compact_thread.join();
6996+
}
6997+
68926998
TEST_F(DBCompactionTest, DisableManualCompactionThreadQueueFull) {
68936999
const int kNumL0Files = 4;
68947000

db/db_impl/db_impl.h

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,19 +1514,31 @@ class DBImpl : public DB {
15141514

15151515
// Information for a manual compaction
15161516
struct ManualCompactionState {
1517+
ManualCompactionState(ColumnFamilyData* _cfd, int _input_level,
1518+
int _output_level, uint32_t _output_path_id,
1519+
bool _exclusive, bool _disallow_trivial_move,
1520+
std::atomic<bool>* _canceled)
1521+
: cfd(_cfd),
1522+
input_level(_input_level),
1523+
output_level(_output_level),
1524+
output_path_id(_output_path_id),
1525+
exclusive(_exclusive),
1526+
disallow_trivial_move(_disallow_trivial_move),
1527+
canceled(_canceled) {}
1528+
15171529
ColumnFamilyData* cfd;
15181530
int input_level;
15191531
int output_level;
15201532
uint32_t output_path_id;
15211533
Status status;
1522-
bool done;
1523-
bool in_progress; // compaction request being processed?
1524-
bool incomplete; // only part of requested range compacted
1525-
bool exclusive; // current behavior of only one manual
1526-
bool disallow_trivial_move; // Force actual compaction to run
1527-
const InternalKey* begin; // nullptr means beginning of key range
1528-
const InternalKey* end; // nullptr means end of key range
1529-
InternalKey* manual_end; // how far we are compacting
1534+
bool done = false;
1535+
bool in_progress = false; // compaction request being processed?
1536+
bool incomplete = false; // only part of requested range compacted
1537+
bool exclusive; // current behavior of only one manual
1538+
bool disallow_trivial_move; // Force actual compaction to run
1539+
const InternalKey* begin = nullptr; // nullptr means beginning of key range
1540+
const InternalKey* end = nullptr; // nullptr means end of key range
1541+
InternalKey* manual_end = nullptr; // how far we are compacting
15301542
InternalKey tmp_storage; // Used to keep track of compaction progress
15311543
InternalKey tmp_storage1; // Used to keep track of compaction progress
15321544
std::atomic<bool>* canceled; // Compaction canceled by the user?
@@ -1536,7 +1548,8 @@ class DBImpl : public DB {
15361548
Compaction* compaction;
15371549
// caller retains ownership of `manual_compaction_state` as it is reused
15381550
// across background compactions.
1539-
ManualCompactionState* manual_compaction_state; // nullptr if non-manual
1551+
std::shared_ptr<ManualCompactionState>
1552+
manual_compaction_state; // nullptr if non-manual
15401553
// task limiter token is requested during compaction picking.
15411554
std::unique_ptr<TaskLimiterToken> task_token;
15421555
};

0 commit comments

Comments
 (0)