diff --git a/tools/db_crashtest.py b/tools/db_crashtest.py index 7d76e5c26..07f87df5f 100644 --- a/tools/db_crashtest.py +++ b/tools/db_crashtest.py @@ -103,9 +103,8 @@ simple_default_params = { "max_background_compactions": 1, "max_bytes_for_level_base": 67108864, "memtablerep": "skip_list", - "prefix_size": 0, - "prefixpercent": 0, - "readpercent": 50, + "prefixpercent": 25, + "readpercent": 25, "target_file_size_base": 16777216, "target_file_size_multiplier": 1, "test_batches_snapshots": 0, diff --git a/tools/db_stress.cc b/tools/db_stress.cc index 9be1bcbc3..b0612ad2e 100644 --- a/tools/db_stress.cc +++ b/tools/db_stress.cc @@ -579,6 +579,23 @@ enum RepFactory StringToRepFactory(const char* ctype) { fprintf(stdout, "Cannot parse memreptable %s\n", ctype); return kSkipList; } + +bool GetNextPrefix(const rocksdb::Slice& src, std::string* v) { + std::string ret = src.ToString(); + for (int i = static_cast(ret.size()) - 1; i >= 0; i--) { + if (ret[i] != static_cast(255)) { + ret[i] = ret[i] + 1; + break; + } else if (i != 0) { + ret[i] = 0; + } else { + // all FF. No next prefix + return false; + } + } + *v = ret; + return true; +} } // namespace static enum RepFactory FLAGS_rep_factory; @@ -2022,6 +2039,30 @@ class StressTest { const Snapshot* snapshot = db_->GetSnapshot(); ReadOptions readoptionscopy = read_opts; readoptionscopy.snapshot = snapshot; + + std::string upper_bound_str; + Slice upper_bound; + if (thread->rand.OneIn(16)) { + // in 1/16 chance, set a iterator upper bound + int64_t rand_upper_key = GenerateOneKey(thread, FLAGS_ops_per_thread); + upper_bound_str = Key(rand_upper_key); + upper_bound = Slice(upper_bound_str); + // uppder_bound can be smaller than seek key, but the query itself + // should not crash either. + readoptionscopy.iterate_upper_bound = &upper_bound; + } + std::string lower_bound_str; + Slice lower_bound; + if (thread->rand.OneIn(16)) { + // in 1/16 chance, set a iterator lower bound + int64_t rand_lower_key = GenerateOneKey(thread, FLAGS_ops_per_thread); + lower_bound_str = Key(rand_lower_key); + lower_bound = Slice(lower_bound_str); + // uppder_bound can be smaller than seek key, but the query itself + // should not crash either. + readoptionscopy.iterate_lower_bound = &lower_bound; + } + auto cfh = column_families_[rand_column_families[0]]; std::unique_ptr iter(db_->NewIterator(readoptionscopy, cfh)); @@ -2564,7 +2605,17 @@ class NonBatchedOpsStressTest : public StressTest { std::string key_str = Key(rand_keys[0]); Slice key = key_str; Slice prefix = Slice(key.data(), FLAGS_prefix_size); - Iterator* iter = db_->NewIterator(read_opts, cfh); + + std::string upper_bound; + Slice ub_slice; + ReadOptions ro_copy = read_opts; + if (thread->rand.OneIn(2) && GetNextPrefix(prefix, &upper_bound)) { + // For half of the time, set the upper bound to the next prefix + ub_slice = Slice(upper_bound); + ro_copy.iterate_upper_bound = &ub_slice; + } + + Iterator* iter = db_->NewIterator(ro_copy, cfh); int64_t count = 0; for (iter->Seek(prefix); iter->Valid() && iter->key().starts_with(prefix); iter->Next()) { @@ -3085,6 +3136,8 @@ class BatchedOpsStressTest : public StressTest { ReadOptions readoptionscopy[10]; const Snapshot* snapshot = db_->GetSnapshot(); Iterator* iters[10]; + std::string upper_bounds[10]; + Slice ub_slices[10]; Status s = Status::OK(); for (int i = 0; i < 10; i++) { prefixes[i] += key.ToString(); @@ -3092,6 +3145,12 @@ class BatchedOpsStressTest : public StressTest { prefix_slices[i] = Slice(prefixes[i]); readoptionscopy[i] = readoptions; readoptionscopy[i].snapshot = snapshot; + if (thread->rand.OneIn(2) && + GetNextPrefix(prefix_slices[i], &(upper_bounds[i]))) { + // For half of the time, set the upper bound to the next prefix + ub_slices[i] = Slice(upper_bounds[i]); + readoptionscopy[i].iterate_upper_bound = &(ub_slices[i]); + } iters[i] = db_->NewIterator(readoptionscopy[i], cfh); iters[i]->Seek(prefix_slices[i]); }