Fix bugs in FilePickerMultiGet (#5292)
Summary: This PR fixes a couple of bugs in FilePickerMultiGet that were causing db_stress test failures. The failures were caused by - 1. Improper handling of a key that matches the user key portion of an L0 file's largest key. In this case, the curr_index_in_curr_level file index in L0 for that key was getting incremented, but batch_iter_ was not advanced. By design, all keys in a batch are supposed to be checked against an L0 file before advancing to the next L0 file. Not advancing to the next key in the batch was causing a double increment of curr_index_in_curr_level due to the same key being processed again 2. Improper handling of a key that matches the user key portion of the largest key in the last file of L1 and higher. This was resulting in a premature end to the processing of the batch for that level when the next key in the batch is a duplicate. Typically, the keys in MultiGet will not be duplicates, but its good to handle that case correctly Test - asan_crash make check Pull Request resolved: https://github.com/facebook/rocksdb/pull/5292 Differential Revision: D15282530 Pulled By: anand1976 fbshipit-source-id: d1a6a86e0af273169c3632db22a44d79c66a581f
This commit is contained in:
parent
25d81e4577
commit
181bb43f08
@ -416,6 +416,18 @@ class FilePickerMultiGet {
|
||||
bool file_hit = false;
|
||||
int cmp_largest = -1;
|
||||
if (curr_file_index >= curr_file_level_->num_files) {
|
||||
// In the unlikely case the next key is a duplicate of the current key,
|
||||
// and the current key is the last in the level and the internal key
|
||||
// was not found, we need to skip lookup for the remaining keys and
|
||||
// reset the search bounds
|
||||
if (batch_iter_ != current_level_range_.end()) {
|
||||
++batch_iter_;
|
||||
for (; batch_iter_ != current_level_range_.end(); ++batch_iter_) {
|
||||
struct FilePickerContext& fp_ctx = fp_ctx_array_[batch_iter_.index()];
|
||||
fp_ctx.search_left_bound = 0;
|
||||
fp_ctx.search_right_bound = FileIndexer::kLevelMaxIndex;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Loops over keys in the MultiGet batch until it finds a file with
|
||||
@ -533,7 +545,10 @@ class FilePickerMultiGet {
|
||||
// any further for that key, so advance batch_iter_. Else, keep
|
||||
// batch_iter_ positioned on that key so we look it up again in
|
||||
// the next file
|
||||
if (current_level_range_.CheckKeyDone(batch_iter_)) {
|
||||
// For L0, always advance the key because we will look in the next
|
||||
// file regardless for all keys not found yet
|
||||
if (current_level_range_.CheckKeyDone(batch_iter_) ||
|
||||
curr_level_ == 0) {
|
||||
++batch_iter_;
|
||||
}
|
||||
}
|
||||
@ -601,7 +616,8 @@ class FilePickerMultiGet {
|
||||
unsigned int start_index_in_curr_level;
|
||||
|
||||
FilePickerContext(int32_t left, int32_t right)
|
||||
: search_left_bound(left), search_right_bound(right) {}
|
||||
: search_left_bound(left), search_right_bound(right),
|
||||
curr_index_in_curr_level(0), start_index_in_curr_level(0) {}
|
||||
|
||||
FilePickerContext() = default;
|
||||
};
|
||||
|
@ -65,7 +65,7 @@ default_params = {
|
||||
"writepercent": 35,
|
||||
"format_version": lambda: random.randint(2, 4),
|
||||
"index_block_restart_interval": lambda: random.choice(range(1, 16)),
|
||||
"use_multiget" : 0,
|
||||
"use_multiget" : lambda: random.randint(0, 1),
|
||||
}
|
||||
|
||||
_TEST_DIR_ENV_VAR = 'TEST_TMPDIR'
|
||||
|
Loading…
Reference in New Issue
Block a user