From 181bb43f08c77be7af72ceea12b9c66b8ab5fd7d Mon Sep 17 00:00:00 2001 From: anand76 Date: Thu, 9 May 2019 13:03:37 -0700 Subject: [PATCH] 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 --- db/version_set.cc | 20 ++++++++++++++++++-- tools/db_crashtest.py | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/db/version_set.cc b/db/version_set.cc index 6d4fb7315..8463a5aa7 100644 --- a/db/version_set.cc +++ b/db/version_set.cc @@ -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; }; diff --git a/tools/db_crashtest.py b/tools/db_crashtest.py index 780c987e9..6487562d8 100644 --- a/tools/db_crashtest.py +++ b/tools/db_crashtest.py @@ -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'