Fix tombstone scans in SeekForPrev outside prefix
Summary: When doing a Seek() or SeekForPrev() we should stop the moment we see a key with a different prefix as start if ReadOptions:: prefix_same_as_start was set to true Right now we don't stop if we encounter a tombstone outside the prefix while executing SeekForPrev() Closes https://github.com/facebook/rocksdb/pull/3067 Differential Revision: D6149638 Pulled By: IslamAbdelRahman fbshipit-source-id: 7f659862d2bf552d3c9104a360c79439ceba2f18
This commit is contained in:
parent
386a57e6ef
commit
addfe1ef4b
@ -715,6 +715,14 @@ void DBIter::PrevInternal() {
|
||||
ExtractUserKey(iter_->key()),
|
||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||
|
||||
if (prefix_extractor_ && prefix_same_as_start_ &&
|
||||
prefix_extractor_->Transform(saved_key_.GetUserKey())
|
||||
.compare(prefix_start_key_) != 0) {
|
||||
// Current key does not have the same prefix as start
|
||||
valid_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (FindValueForCurrentKey()) {
|
||||
if (!iter_->Valid()) {
|
||||
return;
|
||||
@ -723,11 +731,6 @@ void DBIter::PrevInternal() {
|
||||
if (user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||
FindPrevUserKey();
|
||||
}
|
||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_ &&
|
||||
prefix_extractor_->Transform(saved_key_.GetUserKey())
|
||||
.compare(prefix_start_key_) != 0) {
|
||||
valid_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2813,6 +2813,42 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace8) {
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(DBIteratorTest, SeekPrefixTombstones) {
|
||||
ReadOptions ro;
|
||||
Options options;
|
||||
options.prefix_extractor.reset(NewNoopTransform());
|
||||
TestIterator* internal_iter = new TestIterator(BytewiseComparator());
|
||||
internal_iter->AddDeletion("b");
|
||||
internal_iter->AddDeletion("c");
|
||||
internal_iter->AddDeletion("d");
|
||||
internal_iter->AddDeletion("e");
|
||||
internal_iter->AddDeletion("f");
|
||||
internal_iter->AddDeletion("g");
|
||||
internal_iter->Finish();
|
||||
|
||||
ro.prefix_same_as_start = true;
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations,
|
||||
nullptr /*read_callback*/));
|
||||
|
||||
int skipped_keys = 0;
|
||||
|
||||
get_perf_context()->Reset();
|
||||
db_iter->SeekForPrev("z");
|
||||
skipped_keys =
|
||||
static_cast<int>(get_perf_context()->internal_key_skipped_count);
|
||||
ASSERT_EQ(skipped_keys, 0);
|
||||
|
||||
get_perf_context()->Reset();
|
||||
db_iter->Seek("a");
|
||||
skipped_keys =
|
||||
static_cast<int>(get_perf_context()->internal_key_skipped_count);
|
||||
ASSERT_EQ(skipped_keys, 0);
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
Loading…
Reference in New Issue
Block a user