Fix a regression bug on total order seek with prefix enabled and range delete (#6028)
Summary: Recent change https://github.com/facebook/rocksdb/pull/5861 mistakely use "prefix_extractor_ != nullptr" as the condition to determine whehter prefix bloom filter isused. It fails to consider read_options.total_order_seek, so it is wrong. The result is that an optimization for non-total-order seek is mistakely applied to total order seek, and introduces a bug in following corner case: Because of RangeDelete(), a file's largest key is extended. Seek key falls into the range deleted file, so level iterator seeks into the previous file without getting any key. The correct behavior is to place the iterator to the first key of the next file. However, an optimization is triggered and invalidates the iterator because it is out of the prefix range, causing wrong results. This behavior is reproduced in the unit test added. Fix the bug by setting prefix_extractor to be null if total order seek is used. Pull Request resolved: https://github.com/facebook/rocksdb/pull/6028 Test Plan: Add a unit test which fails without the fix. Differential Revision: D18479063 fbshipit-source-id: ac075f013029fcf69eb3a598f14c98cce3e810b3
This commit is contained in:
parent
42b5494ec8
commit
bb23bfe63c
@ -4177,6 +4177,39 @@ TEST_F(DBTest2, CrashInRecoveryMultipleCF) {
|
||||
options));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBTest2, SeekFileRangeDeleteTail) {
|
||||
Options options = CurrentOptions();
|
||||
options.prefix_extractor.reset(NewCappedPrefixTransform(1));
|
||||
options.num_levels = 3;
|
||||
DestroyAndReopen(options);
|
||||
|
||||
ASSERT_OK(Put("a", "a"));
|
||||
const Snapshot* s1 = db_->GetSnapshot();
|
||||
ASSERT_OK(
|
||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "f"));
|
||||
ASSERT_OK(Put("b", "a"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ASSERT_OK(Put("x", "a"));
|
||||
ASSERT_OK(Put("z", "a"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
CompactRangeOptions cro;
|
||||
cro.change_level = true;
|
||||
cro.target_level = 2;
|
||||
ASSERT_OK(db_->CompactRange(cro, nullptr, nullptr));
|
||||
|
||||
{
|
||||
ReadOptions ro;
|
||||
ro.total_order_seek = true;
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(ro));
|
||||
iter->Seek("e");
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ("x", iter->key().ToString());
|
||||
}
|
||||
db_->ReleaseSnapshot(s1);
|
||||
}
|
||||
} // namespace rocksdb
|
||||
|
||||
#ifdef ROCKSDB_UNITTESTS_WITH_CUSTOM_OBJECTS_FROM_STATIC_LIBS
|
||||
|
@ -867,7 +867,8 @@ class LevelIterator final : public InternalIterator {
|
||||
icomparator_(icomparator),
|
||||
user_comparator_(icomparator.user_comparator()),
|
||||
flevel_(flevel),
|
||||
prefix_extractor_(prefix_extractor),
|
||||
prefix_extractor_(read_options.total_order_seek ? nullptr
|
||||
: prefix_extractor),
|
||||
file_read_hist_(file_read_hist),
|
||||
should_sample_(should_sample),
|
||||
caller_(caller),
|
||||
|
Loading…
Reference in New Issue
Block a user