Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions file/prefetch_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,62 @@ TEST_P(PrefetchTrimReadaheadTestParam, PrefixSameAsStart) {
Close();
}

TEST_P(PrefetchTrimReadaheadTestParam, IterateUpperBoundAtEndOfIndex) {
if (mem_env_ || encrypted_env_) {
ROCKSDB_GTEST_SKIP("Test requires non-mem or non-encrypted environment");
return;
}
const bool auto_readahead_size = std::get<1>(GetParam());

std::shared_ptr<MockFS> fs = std::make_shared<MockFS>(
FileSystem::Default(), false /* support_prefetch */,
true /* small_buffer_alignment */);
std::unique_ptr<Env> env(new CompositeEnvWrapper(env_, fs));
Options options;
SetGenericOptions(env.get(), options);
options.prefix_extractor.reset();
BlockBasedTableOptions table_options;
SetBlockBasedTableOptions(table_options);
options.table_factory.reset(NewBlockBasedTableFactory(table_options));

ASSERT_OK(TryReopen(options));

for (int i = 0; i < 64; ++i) {
ASSERT_OK(db_->Put(WriteOptions(), "key" + std::to_string(i),
rnd.RandomString(100)));
}
ASSERT_OK(db_->Flush(FlushOptions()));

ReadOptions ro;
ro.async_io = true;
ro.auto_readahead_size = auto_readahead_size;
ro.readahead_size = 1024 * 1024;
const Slice upper_bound("keyz");
ro.iterate_upper_bound = &upper_bound;

ASSERT_OK(options.statistics->Reset());
int num_keys = 0;
Status iter_status;
{
auto iter = std::unique_ptr<Iterator>(db_->NewIterator(ro));
for (iter->Seek("key0"); iter->Valid(); iter->Next()) {
++num_keys;
}
iter_status = iter->status();
}
auto readahead_trimmed =
options.statistics->getTickerCount(READAHEAD_TRIMMED);

Close();
ASSERT_OK(iter_status);
ASSERT_EQ(num_keys, 64);
if (auto_readahead_size) {
ASSERT_GT(readahead_trimmed, 0);
} else {
ASSERT_EQ(readahead_trimmed, 0);
}
}

// This test verifies the functionality of ReadOptions.adaptive_readahead.
TEST_P(PrefetchTest, DBIterLevelReadAhead) {
const int kNumKeys = 1000;
Expand Down
8 changes: 8 additions & 0 deletions table/block_based/block_based_table_iterator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,14 @@ void BlockBasedTableIterator::BlockCacheLookupForReadAheadSize(
return;
}

// Readahead lookup may advance index_iter_ to the end of the file while the
// current block is still being consumed. In that case there is no next block
// boundary to inspect, so skip further tuning instead of dereferencing an
// exhausted index iterator.
if (!index_iter_->Valid()) {
return;
}

size_t footer = table_->get_rep()->footer.GetBlockTrailerSize();
if (read_curr_block && !DoesContainBlockHandles() &&
IsNextBlockOutOfReadaheadBound()) {
Expand Down
1 change: 1 addition & 0 deletions table/block_based/block_based_table_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
}

bool IsNextBlockOutOfReadaheadBound() {
assert(index_iter_->Valid());
const Slice& index_iter_user_key = index_iter_->user_key();
// If curr block's index key >= iterate_upper_bound, it means all the keys
// in next block or above are out of bound.
Expand Down
Loading