Skip to content

Commit

Permalink
Add more public APIs to crash test (#12617)
Browse files Browse the repository at this point in the history
Summary:
**Context/Summary:**
As titled. Bonus: found that PromoteL0 called with other concurrent PromoteL0 will return non-okay error so clarify the API.

Pull Request resolved: #12617

Test Plan: CI

Reviewed By: ajkr

Differential Revision: D56954428

Pulled By: hx235

fbshipit-source-id: 0e056153c515003fd241ffec59b0d8a27529db4c
  • Loading branch information
hx235 authored and facebook-github-bot committed May 9, 2024
1 parent 97e7090 commit 9bddac0
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 0 deletions.
3 changes: 3 additions & 0 deletions db_stress_tool/db_stress_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,11 @@ DECLARE_int32(ingest_external_file_one_in);
DECLARE_int32(ingest_external_file_width);
DECLARE_int32(compact_files_one_in);
DECLARE_int32(compact_range_one_in);
DECLARE_int32(promote_l0_one_in);
DECLARE_int32(mark_for_compaction_one_file_in);
DECLARE_int32(flush_one_in);
DECLARE_int32(key_may_exist_one_in);
DECLARE_int32(reset_stats_one_in);
DECLARE_int32(pause_background_one_in);
DECLARE_int32(disable_file_deletions_one_in);
DECLARE_int32(disable_manual_compaction_one_in);
Expand Down
12 changes: 12 additions & 0 deletions db_stress_tool/db_stress_gflags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,10 @@ DEFINE_int32(compact_range_one_in, 0,
"If non-zero, then CompactRange() will be called once for every N "
"operations on average. 0 indicates CompactRange() is disabled.");

DEFINE_int32(promote_l0_one_in, 0,
"If non-zero, then PromoteL0() will be called once for every N "
"operations on average. 0 indicates PromoteL0() is disabled.");

DEFINE_int32(mark_for_compaction_one_file_in, 0,
"A `TablePropertiesCollectorFactory` will be registered, which "
"creates a `TablePropertiesCollector` with `NeedCompact()` "
Expand All @@ -766,6 +770,14 @@ DEFINE_int32(flush_one_in, 0,
"If non-zero, then Flush() will be called once for every N ops "
"on average. 0 indicates calls to Flush() are disabled.");

DEFINE_int32(key_may_exist_one_in, 0,
"If non-zero, then KeyMayExist() will be called "
"once for every N ops on average. 0 disables.");

DEFINE_int32(reset_stats_one_in, 0,
"If non-zero, then ResetStats() will be called "
"once for every N ops on average. 0 disables.");

DEFINE_int32(pause_background_one_in, 0,
"If non-zero, then PauseBackgroundWork()+Continue will be called "
"once for every N ops on average. 0 disables.");
Expand Down
38 changes: 38 additions & 0 deletions db_stress_tool/db_stress_test_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,10 @@ void StressTest::OperateDb(ThreadState* thread) {
}
}

if (thread->rand.OneInOpt(FLAGS_promote_l0_one_in)) {
TestPromoteL0(thread, column_family);
}

std::vector<int> rand_column_families =
GenerateColumnFamilies(FLAGS_column_families, rand_column_family);

Expand Down Expand Up @@ -1041,6 +1045,11 @@ void StressTest::OperateDb(ThreadState* thread) {
ProcessStatus(shared, "VerifyGetCurrentWalFile", status);
}

if (thread->rand.OneInOpt(FLAGS_reset_stats_one_in)) {
Status status = TestResetStats();
ProcessStatus(shared, "ResetStats", status);
}

if (thread->rand.OneInOpt(FLAGS_pause_background_one_in)) {
Status status = TestPauseBackground(thread);
ProcessStatus(shared, "Pause/ContinueBackgroundWork", status);
Expand Down Expand Up @@ -1135,6 +1144,10 @@ void StressTest::OperateDb(ThreadState* thread) {
read_opts.timestamp = &read_ts;
}

if (thread->rand.OneInOpt(FLAGS_key_may_exist_one_in)) {
TestKeyMayExist(thread, read_opts, rand_column_families, rand_keys);
}

int prob_op = thread->rand.Uniform(100);
// Reset this in case we pick something other than a read op. We don't
// want to use a stale value when deciding at the beginning of the loop
Expand Down Expand Up @@ -2428,6 +2441,29 @@ void StressTest::TestCompactFiles(ThreadState* thread,
}
}

void StressTest::TestPromoteL0(ThreadState* thread,
ColumnFamilyHandle* column_family) {
int target_level = thread->rand.Next() % options_.num_levels;
Status s = db_->PromoteL0(column_family, target_level);
if (!s.ok()) {
// The second error occurs when another concurrent PromoteL0() moving the
// same files finishes first which is an allowed behavior
bool non_ok_status_allowed =
s.IsInvalidArgument() ||
(s.IsCorruption() &&
s.ToString().find("VersionBuilder: Cannot delete table file") !=
std::string::npos &&
s.ToString().find("since it is on level") != std::string::npos);
fprintf(non_ok_status_allowed ? stdout : stderr,
"Unable to perform PromoteL0(): %s under specified "
"target_level: %d.\n",
s.ToString().c_str(), target_level);
if (!non_ok_status_allowed) {
thread->shared->SafeTerminate();
}
}
}

Status StressTest::TestFlush(const std::vector<int>& rand_column_families) {
FlushOptions flush_opts;
if (FLAGS_atomic_flush) {
Expand All @@ -2439,6 +2475,8 @@ Status StressTest::TestFlush(const std::vector<int>& rand_column_families) {
return db_->Flush(flush_opts, cfhs);
}

Status StressTest::TestResetStats() { return db_->ResetStats(); }

Status StressTest::TestPauseBackground(ThreadState* thread) {
Status status = db_->PauseBackgroundWork();
if (!status.ok()) {
Expand Down
9 changes: 9 additions & 0 deletions db_stress_tool/db_stress_test_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ class StressTest {
return {rand_key};
}

virtual void TestKeyMayExist(ThreadState*, const ReadOptions&,
const std::vector<int>&,
const std::vector<int64_t>&) {}

virtual Status TestGet(ThreadState* thread, const ReadOptions& read_opts,
const std::vector<int>& rand_column_families,
const std::vector<int64_t>& rand_keys) = 0;
Expand Down Expand Up @@ -136,6 +140,9 @@ class StressTest {
const Slice& start_key,
ColumnFamilyHandle* column_family);

virtual void TestPromoteL0(ThreadState* thread,
ColumnFamilyHandle* column_family);

// Calculate a hash value for all keys in range [start_key, end_key]
// at a certain snapshot.
uint32_t GetRangeHash(ThreadState* thread, const Snapshot* snapshot,
Expand Down Expand Up @@ -204,6 +211,8 @@ class StressTest {

Status TestFlush(const std::vector<int>& rand_column_families);

Status TestResetStats();

Status TestPauseBackground(ThreadState* thread);

Status TestDisableFileDeletions(ThreadState* thread);
Expand Down
38 changes: 38 additions & 0 deletions db_stress_tool/no_batched_ops_stress.cc
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,44 @@ class NonBatchedOpsStressTest : public StressTest {

bool IsStateTracked() const override { return true; }

void TestKeyMayExist(ThreadState* thread, const ReadOptions& read_opts,
const std::vector<int>& rand_column_families,
const std::vector<int64_t>& rand_keys) override {
auto cfh = column_families_[rand_column_families[0]];
std::string key_str = Key(rand_keys[0]);
Slice key = key_str;
std::string ignore;
ReadOptions read_opts_copy = read_opts;

std::string read_ts_str;
Slice read_ts_slice;
if (FLAGS_user_timestamp_size > 0) {
read_ts_str = GetNowNanos();
read_ts_slice = read_ts_str;
read_opts_copy.timestamp = &read_ts_slice;
}
bool read_older_ts = MaybeUseOlderTimestampForPointLookup(
thread, read_ts_str, read_ts_slice, read_opts_copy);

const ExpectedValue pre_read_expected_value =
thread->shared->Get(rand_column_families[0], rand_keys[0]);
bool key_may_exist = db_->KeyMayExist(read_opts_copy, cfh, key, &ignore);
const ExpectedValue post_read_expected_value =
thread->shared->Get(rand_column_families[0], rand_keys[0]);

if (!key_may_exist && !FLAGS_skip_verifydb && !read_older_ts) {
if (ExpectedValueHelper::MustHaveExisted(pre_read_expected_value,
post_read_expected_value)) {
thread->shared->SetVerificationFailure();
fprintf(stderr,
"error : inconsistent values for key %s: expected state has "
"the key, TestKeyMayExist() returns false indicating the key "
"must not exist.\n",
key.ToString(true).c_str());
}
}
}

Status TestGet(ThreadState* thread, const ReadOptions& read_opts,
const std::vector<int>& rand_column_families,
const std::vector<int64_t>& rand_keys) override {
Expand Down
2 changes: 2 additions & 0 deletions include/rocksdb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,8 @@ class DB {
return Status::NotSupported("SuggestCompactRange() is not implemented.");
}

// Trivially move L0 files to target level. Should not be called with another
// PromoteL0() concurrently
virtual Status PromoteL0(ColumnFamilyHandle* /*column_family*/,
int /*target_level*/) {
return Status::NotSupported("PromoteL0() is not implemented.");
Expand Down
3 changes: 3 additions & 0 deletions tools/db_crashtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@
"clear_column_family_one_in": 0,
"compact_files_one_in": lambda: random.choice([1000, 1000000]),
"compact_range_one_in": lambda: random.choice([1000, 1000000]),
"promote_l0_one_in": lambda: random.choice([1000, 1000000]),
"compaction_pri": random.randint(0, 4),
"key_may_exist_one_in": lambda: random.choice([100, 100000]),
"data_block_index_type": lambda: random.choice([0, 1]),
"delpercent": 4,
"delrangepercent": 1,
Expand Down Expand Up @@ -116,6 +118,7 @@
"optimize_filters_for_memory": lambda: random.randint(0, 1),
"partition_filters": lambda: random.randint(0, 1),
"partition_pinning": lambda: random.randint(0, 3),
"reset_stats_one_in": lambda: random.choice([10000, 1000000]),
"pause_background_one_in": lambda: random.choice([10000, 1000000]),
"disable_file_deletions_one_in": lambda: random.choice([10000, 1000000]),
"disable_manual_compaction_one_in": lambda: random.choice([10000, 1000000]),
Expand Down

0 comments on commit 9bddac0

Please sign in to comment.