Add a unit test to detect infinite loops with reseek optimizations (#5727)
Summary: Iterators reseek to the target key after iterating over max_sequential_skip_in_iterations invalid values. The logic is susceptible to an infinite loop bug, which has been present with WritePrepared Transactions up until 6.2 release. Although the bug is not present on master, the patch adds a unit test to prevent it from resurfacing again. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5727 Differential Revision: D16952759 Pulled By: maysamyabandeh fbshipit-source-id: d0d973dddc8dfabd5a794931232aa4c862c74f51
This commit is contained in:
parent
229e6fbe0e
commit
f9fb9f1421
@ -5969,6 +5969,55 @@ TEST_P(TransactionTest, DuplicateKeys) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the reseek optimization in iterators will not result in an infinite
|
||||
// loop if there are too many uncommitted entries before the snapshot.
|
||||
TEST_P(TransactionTest, ReseekOptimization) {
|
||||
WriteOptions write_options;
|
||||
write_options.sync = true;
|
||||
write_options.disableWAL = false;
|
||||
ColumnFamilyDescriptor cfd;
|
||||
db->DefaultColumnFamily()->GetDescriptor(&cfd);
|
||||
auto max_skip = cfd.options.max_sequential_skip_in_iterations;
|
||||
|
||||
ASSERT_OK(db->Put(write_options, Slice("foo0"), Slice("initv")));
|
||||
|
||||
TransactionOptions txn_options;
|
||||
Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
|
||||
ASSERT_OK(txn0->SetName("xid"));
|
||||
// Duplicate keys will result into separate sequence numbers in WritePrepared
|
||||
// and WriteUnPrepared
|
||||
for (size_t i = 0; i < 2 * max_skip; i++) {
|
||||
ASSERT_OK(txn0->Put(Slice("foo1"), Slice("bar")));
|
||||
}
|
||||
ASSERT_OK(txn0->Prepare());
|
||||
ASSERT_OK(db->Put(write_options, Slice("foo2"), Slice("initv")));
|
||||
|
||||
ReadOptions read_options;
|
||||
// To avoid loops
|
||||
read_options.max_skippable_internal_keys = 10 * max_skip;
|
||||
Iterator* iter = db->NewIterator(read_options);
|
||||
ASSERT_OK(iter->status());
|
||||
size_t cnt = 0;
|
||||
iter->SeekToFirst();
|
||||
while (iter->Valid()) {
|
||||
iter->Next();
|
||||
ASSERT_OK(iter->status());
|
||||
cnt++;
|
||||
}
|
||||
ASSERT_EQ(cnt, 2);
|
||||
cnt = 0;
|
||||
iter->SeekToLast();
|
||||
while (iter->Valid()) {
|
||||
iter->Prev();
|
||||
ASSERT_OK(iter->status());
|
||||
cnt++;
|
||||
}
|
||||
ASSERT_EQ(cnt, 2);
|
||||
delete iter;
|
||||
txn0->Rollback();
|
||||
delete txn0;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
Loading…
Reference in New Issue
Block a user