Skip to content

Commit d567357

Browse files
committed
Compute NeedCompact() after table builder Finish() (facebook#7627)
Summary: In `BuildTable()`, we call `builder->Finish()` before evaluating `builder->NeedCompact()`. However, we call `builder->NeedCompact()` before `builder->Finish()` in compaction job. This can be wrong because the table properties collectors may rely on the success of `Finish()` to provide correct result for `NeedCompact()`. Test plan (on devserver): make check Pull Request resolved: facebook#7627 Reviewed By: ajkr Differential Revision: D24728741 Pulled By: riversand963 fbshipit-source-id: 5a0dce244e14eb1106c4f87021e6bebca82b486e
1 parent d4b8274 commit d567357

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

db/compaction/compaction_job.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,6 @@ Status CompactionJob::FinishCompactionOutputFile(
13521352
ExtractInternalKeyFooter(meta->smallest.Encode()) !=
13531353
PackSequenceAndType(0, kTypeRangeDeletion));
13541354
}
1355-
meta->marked_for_compaction = sub_compact->builder->NeedCompact();
13561355
}
13571356
const uint64_t current_entries = sub_compact->builder->NumEntries();
13581357
if (s.ok()) {
@@ -1367,6 +1366,7 @@ Status CompactionJob::FinishCompactionOutputFile(
13671366
const uint64_t current_bytes = sub_compact->builder->FileSize();
13681367
if (s.ok()) {
13691368
meta->fd.file_size = current_bytes;
1369+
meta->marked_for_compaction = sub_compact->builder->NeedCompact();
13701370
}
13711371
sub_compact->current_output()->finished = true;
13721372
sub_compact->total_bytes += current_bytes;

db/db_table_properties_test.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,54 @@ TEST_P(DBTablePropertiesTest, DeletionTriggeredCompactionMarking) {
370370
ASSERT_LT(0, opts.statistics->getTickerCount(COMPACT_READ_BYTES_MARKED));
371371
}
372372

373+
TEST_P(DBTablePropertiesTest, RatioBasedDeletionTriggeredCompactionMarking) {
374+
constexpr int kNumKeys = 1000;
375+
constexpr int kWindowSize = 0;
376+
constexpr int kNumDelsTrigger = 0;
377+
constexpr double kDeletionRatio = 0.1;
378+
std::shared_ptr<TablePropertiesCollectorFactory> compact_on_del =
379+
NewCompactOnDeletionCollectorFactory(kWindowSize, kNumDelsTrigger,
380+
kDeletionRatio);
381+
382+
Options opts = CurrentOptions();
383+
opts.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
384+
opts.table_properties_collector_factories.emplace_back(compact_on_del);
385+
386+
Reopen(opts);
387+
388+
// Add an L2 file to prevent tombstones from dropping due to obsolescence
389+
// during flush
390+
Put(Key(0), "val");
391+
Flush();
392+
MoveFilesToLevel(2);
393+
394+
auto* listener = new DeletionTriggeredCompactionTestListener();
395+
opts.listeners.emplace_back(listener);
396+
Reopen(opts);
397+
398+
// Generate one L0 with kNumKeys Put.
399+
for (int i = 0; i < kNumKeys; ++i) {
400+
ASSERT_OK(Put(Key(i), "not important"));
401+
}
402+
ASSERT_OK(Flush());
403+
404+
// Generate another L0 with kNumKeys Delete.
405+
// This file, due to deletion ratio, will trigger compaction: 2@0 files to L1.
406+
// The resulting L1 file has only one tombstone for user key 'Key(0)'.
407+
// Again, due to deletion ratio, a compaction will be triggered: 1@1 + 1@2
408+
// files to L2. However, the resulting file is empty because the tombstone
409+
// and value are both dropped.
410+
for (int i = 0; i < kNumKeys; ++i) {
411+
ASSERT_OK(Delete(Key(i)));
412+
}
413+
ASSERT_OK(Flush());
414+
415+
ASSERT_OK(dbfull()->TEST_WaitForCompact());
416+
for (int i = 0; i < 3; ++i) {
417+
ASSERT_EQ(0, NumTableFilesAtLevel(i));
418+
}
419+
}
420+
373421
INSTANTIATE_TEST_CASE_P(
374422
DBTablePropertiesTest,
375423
DBTablePropertiesTest,

0 commit comments

Comments
 (0)