diff --git a/db/db_iterator_test.cc b/db/db_iterator_test.cc index a7b389cf3..7eeb12118 100644 --- a/db/db_iterator_test.cc +++ b/db/db_iterator_test.cc @@ -1035,6 +1035,60 @@ TEST_P(DBIteratorTest, DBIteratorBoundTest) { ASSERT_EQ(static_cast(get_perf_context()->internal_delete_skipped_count), 0); } } + +TEST_P(DBIteratorTest, DBIteratorBoundMultiSeek) { + Options options = CurrentOptions(); + options.env = env_; + options.create_if_missing = true; + options.statistics = rocksdb::CreateDBStatistics(); + options.prefix_extractor = nullptr; + DestroyAndReopen(options); + ASSERT_OK(Put("a", "0")); + ASSERT_OK(Put("z", "0")); + ASSERT_OK(Flush()); + ASSERT_OK(Put("foo1", "bar1")); + ASSERT_OK(Put("foo2", "bar2")); + ASSERT_OK(Put("foo3", "bar3")); + ASSERT_OK(Put("foo4", "bar4")); + + { + std::string up_str = "foo5"; + Slice up(up_str); + ReadOptions ro; + ro.iterate_upper_bound = &up; + std::unique_ptr iter(NewIterator(ro)); + + iter->Seek("foo1"); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ(iter->key().compare(Slice("foo1")), 0); + + uint64_t prev_block_cache_hit = + TestGetTickerCount(options, BLOCK_CACHE_HIT); + uint64_t prev_block_cache_miss = + TestGetTickerCount(options, BLOCK_CACHE_MISS); + + ASSERT_GT(prev_block_cache_hit + prev_block_cache_miss, 0); + + iter->Seek("foo4"); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ(iter->key().compare(Slice("foo4")), 0); + ASSERT_EQ(prev_block_cache_hit, + TestGetTickerCount(options, BLOCK_CACHE_HIT)); + ASSERT_EQ(prev_block_cache_miss, + TestGetTickerCount(options, BLOCK_CACHE_MISS)); + + iter->Seek("foo2"); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ(iter->key().compare(Slice("foo2")), 0); + iter->Next(); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ(iter->key().compare(Slice("foo3")), 0); + ASSERT_EQ(prev_block_cache_hit, + TestGetTickerCount(options, BLOCK_CACHE_HIT)); + ASSERT_EQ(prev_block_cache_miss, + TestGetTickerCount(options, BLOCK_CACHE_MISS)); + } +} #endif TEST_P(DBIteratorTest, DBIteratorBoundOptimizationTest) { diff --git a/table/block_based_table_reader.cc b/table/block_based_table_reader.cc index 6c8a880f7..3d90940e2 100644 --- a/table/block_based_table_reader.cc +++ b/table/block_based_table_reader.cc @@ -2039,7 +2039,6 @@ void BlockBasedTableIterator::FindKeyForward() { &reached_upper_bound); if (reached_upper_bound) { is_out_of_bound_ = true; - ResetDataIter(); return; } } diff --git a/table/block_based_table_reader.h b/table/block_based_table_reader.h index 6c39e567c..cedab053c 100644 --- a/table/block_based_table_reader.h +++ b/table/block_based_table_reader.h @@ -535,7 +535,8 @@ class BlockBasedTableIterator : public InternalIterator { void Next() override; void Prev() override; bool Valid() const override { - return block_iter_points_to_real_block_ && data_block_iter_.Valid(); + return !is_out_of_bound_ && block_iter_points_to_real_block_ && + data_block_iter_.Valid(); } Slice key() const override { assert(Valid());