Fix corruption error in stress test for auto_readahead_size enabled (#11961)

Summary:
Fix corruption error - "Corruption: first key in index doesn't match first key in block". when auto_readahead_size is enabled. Error is because of bug when index_iter_ moves forward, first_internal_key of that index_iter_ is not copied. So the Slice points to a different key resulting in wrong comparison when doing comparison.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/11961

Test Plan: Ran stress test which reproduced this error.

Reviewed By: anand1976

Differential Revision: D50310589

Pulled By: akankshamahajan15

fbshipit-source-id: 95d8320b8388f1e3822c32024f84754f3a20a631
This commit is contained in:
akankshamahajan 2023-10-17 12:21:08 -07:00 committed by Facebook GitHub Bot
parent 2296c624fa
commit 9135a61ec6
3 changed files with 25 additions and 10 deletions

View file

@ -318,7 +318,7 @@ void BlockBasedTableIterator::InitDataBlock() {
bool use_block_cache_for_lookup = true;
if (DoesContainBlockHandles()) {
data_block_handle = block_handles_.front().index_val_.handle;
data_block_handle = block_handles_.front().handle_;
is_in_cache = block_handles_.front().is_cache_hit_;
use_block_cache_for_lookup = false;
} else {
@ -483,15 +483,15 @@ bool BlockBasedTableIterator::MaterializeCurrentBlock() {
// handles placed in blockhandle. So index_ will be pointing to current block.
// After InitDataBlock, index_iter_ can point to different block if
// BlockCacheLookupForReadAheadSize is called.
IndexValue index_val;
Slice first_internal_key;
if (DoesContainBlockHandles()) {
index_val = block_handles_.front().index_val_;
first_internal_key = block_handles_.front().first_internal_key_;
} else {
index_val = index_iter_->value();
first_internal_key = index_iter_->value().first_internal_key;
}
if (!block_iter_.Valid() ||
icomp_.Compare(block_iter_.key(), index_val.first_internal_key) != 0) {
icomp_.Compare(block_iter_.key(), first_internal_key) != 0) {
block_iter_.Invalidate(Status::Corruption(
"first key in index doesn't match first key in block"));
return false;
@ -701,7 +701,9 @@ void BlockBasedTableIterator::BlockCacheLookupForReadAheadSize(
// Add the current block to block_handles_.
{
BlockHandleInfo block_handle_info;
block_handle_info.index_val_ = index_iter_->value();
block_handle_info.handle_ = index_iter_->value().handle;
block_handle_info.SetFirstInternalKey(
index_iter_->value().first_internal_key);
block_handles_.emplace_back(std::move(block_handle_info));
}
@ -726,7 +728,9 @@ void BlockBasedTableIterator::BlockCacheLookupForReadAheadSize(
// For current data block, do the lookup in the cache. Lookup should pin the
// data block and add the placeholder for cache.
BlockHandleInfo block_handle_info;
block_handle_info.index_val_ = index_iter_->value();
block_handle_info.handle_ = index_iter_->value().handle;
block_handle_info.SetFirstInternalKey(
index_iter_->value().first_internal_key);
Status s = table_->LookupAndPinBlocksInCache<Block_kData>(
read_options_, block_handle,
@ -758,7 +762,7 @@ void BlockBasedTableIterator::BlockCacheLookupForReadAheadSize(
// update the readahead_size.
for (auto it = block_handles_.rbegin();
it != block_handles_.rend() && (*it).is_cache_hit_ == true; ++it) {
current_readahead_size -= (*it).index_val_.handle.size();
current_readahead_size -= (*it).handle_.size();
current_readahead_size -= footer;
}
updated_readahead_size = current_readahead_size;

View file

@ -250,11 +250,21 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
// BlockHandleInfo is used to store the info needed when block cache lookup
// ahead is enabled to tune readahead_size.
struct BlockHandleInfo {
BlockHandleInfo() {}
void SetFirstInternalKey(const Slice& key) {
if (key.empty()) {
return;
}
size_t size = key.size();
buf_ = std::unique_ptr<char[]>(new char[size]);
memcpy(buf_.get(), key.data(), size);
first_internal_key_ = Slice(buf_.get(), size);
}
IndexValue index_val_;
BlockHandle handle_;
bool is_cache_hit_ = false;
CachableEntry<Block> cachable_entry_;
Slice first_internal_key_;
std::unique_ptr<char[]> buf_;
};
bool IsIndexAtCurr() const { return is_index_at_curr_block_; }

View file

@ -0,0 +1 @@
Fix a bug in auto_readahead_size where first_internal_key of index blocks wasn't copied properly resulting in corruption error when first_internal_key was used for comparison.