Regression test for empty dedicated range deletion file
Summary: Issue: #2478 Fix: #2503 The bug happened when all of these conditions were satisfied: - A subcompaction generates no keys - `RangeDelAggregator::ShouldAddTombstones()` returns true because there's at least one non-obsoleted range deletion in its map - None of the non-obsolete tombstones overlap with the subcompaction key-range Under those conditions, we were creating a dedicated file for range deletions which was left empty, thus causing an error in VersionEdit. I verified this test case fails before the #2503 fix and passes after. Closes https://github.com/facebook/rocksdb/pull/2521 Differential Revision: D5352568 Pulled By: ajkr fbshipit-source-id: f619cae39984ce9bb9b7a4e7a9ac0f2bb2ce43e9
This commit is contained in:
parent
e9f91a5176
commit
d310e0f339
@ -821,8 +821,55 @@ TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
|||||||
}
|
}
|
||||||
db_->ReleaseSnapshot(snapshot);
|
db_->ReleaseSnapshot(snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !ROCKSDB_UBSAN_RUN
|
#endif // !ROCKSDB_UBSAN_RUN
|
||||||
|
|
||||||
|
TEST_F(DBRangeDelTest, SubcompactionHasEmptyDedicatedRangeDelFile) {
|
||||||
|
const int kNumFiles = 2, kNumKeysPerFile = 4;
|
||||||
|
Options options = CurrentOptions();
|
||||||
|
options.compression = kNoCompression;
|
||||||
|
options.disable_auto_compactions = true;
|
||||||
|
options.level0_file_num_compaction_trigger = kNumFiles;
|
||||||
|
options.max_subcompactions = 2;
|
||||||
|
options.num_levels = 2;
|
||||||
|
options.target_file_size_base = 4096;
|
||||||
|
Reopen(options);
|
||||||
|
|
||||||
|
// need a L1 file for subcompaction to be triggered
|
||||||
|
ASSERT_OK(
|
||||||
|
db_->Put(WriteOptions(), db_->DefaultColumnFamily(), Key(0), "val"));
|
||||||
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
MoveFilesToLevel(1);
|
||||||
|
|
||||||
|
// put enough keys to fill up the first subcompaction, and later range-delete
|
||||||
|
// them so that the first subcompaction outputs no key-values. In that case
|
||||||
|
// it'll consider making an SST file dedicated to range deletions.
|
||||||
|
for (int i = 0; i < kNumKeysPerFile; ++i) {
|
||||||
|
ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), Key(i),
|
||||||
|
std::string(1024, 'a')));
|
||||||
|
}
|
||||||
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||||
|
Key(kNumKeysPerFile)));
|
||||||
|
|
||||||
|
// the above range tombstone can be dropped, so that one alone won't cause a
|
||||||
|
// dedicated file to be opened. We can make one protected by snapshot that
|
||||||
|
// must be considered. Make its range outside the first subcompaction's range
|
||||||
|
// to exercise the tricky part of the code.
|
||||||
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
|
Key(kNumKeysPerFile + 1),
|
||||||
|
Key(kNumKeysPerFile + 2)));
|
||||||
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
|
||||||
|
ASSERT_EQ(kNumFiles, NumTableFilesAtLevel(0));
|
||||||
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
|
|
||||||
|
db_->EnableAutoCompaction({db_->DefaultColumnFamily()});
|
||||||
|
dbfull()->TEST_WaitForCompact();
|
||||||
|
db_->ReleaseSnapshot(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
|
|
||||||
} // namespace rocksdb
|
} // namespace rocksdb
|
||||||
|
Loading…
Reference in New Issue
Block a user