From 9f1e5a0b87fb1eb50b3c580a0ab7ce7956f1a655 Mon Sep 17 00:00:00 2001 From: sdong Date: Wed, 23 Oct 2019 16:55:43 -0700 Subject: [PATCH] CfConsistencyStressTest to validate key consistent across CFs in TestGet() (#5863) Summary: Right now in CF consitency stres test's TestGet(), keys are just fetched without validation. With this change, in 1/2 the time, compare all the CFs share the same value with the same key. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5863 Test Plan: Run "make crash_test_with_atomic_flush" and see tests pass. Hack the code to generate some inconsistency and observe the test fails as expected. Differential Revision: D17934206 fbshipit-source-id: 00ba1a130391f28785737b677f80f366fb83cced --- tools/db_stress_tool.cc | 72 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/tools/db_stress_tool.cc b/tools/db_stress_tool.cc index fba2d0150..7e1fa3f3a 100644 --- a/tools/db_stress_tool.cc +++ b/tools/db_stress_tool.cc @@ -4228,12 +4228,72 @@ class CfConsistencyStressTest : public StressTest { const std::vector& rand_keys) { std::string key_str = Key(rand_keys[0]); Slice key = key_str; - auto cfh = - column_families_[rand_column_families[thread->rand.Next() % - rand_column_families.size()]]; - std::string from_db; - Status s = db_->Get(readoptions, cfh, key, &from_db); - if (s.ok()) { + Status s; + bool is_consistent = true; + + if (thread->rand.OneIn(2)) { + // 1/2 chance, does a random read from random CF + auto cfh = + column_families_[rand_column_families[thread->rand.Next() % + rand_column_families.size()]]; + std::string from_db; + s = db_->Get(readoptions, cfh, key, &from_db); + } else { + // 1/2 chance, comparing one key is the same across all CFs + const Snapshot* snapshot = db_->GetSnapshot(); + ReadOptions readoptionscopy = readoptions; + readoptionscopy.snapshot = snapshot; + + std::string value0; + s = db_->Get(readoptionscopy, column_families_[rand_column_families[0]], + key, &value0); + if (s.ok() || s.IsNotFound()) { + bool found = s.ok(); + for (size_t i = 1; i < rand_column_families.size(); i++) { + std::string value1; + s = db_->Get(readoptionscopy, + column_families_[rand_column_families[i]], key, &value1); + if (!s.ok() && !s.IsNotFound()) { + break; + } + if (!found && s.ok()) { + fprintf(stderr, "Get() return different results with key %s\n", + key_str.c_str()); + fprintf(stderr, "CF %s is not found\n", + column_family_names_[0].c_str()); + fprintf(stderr, "CF %s returns value %s\n", + column_family_names_[i].c_str(), value1.c_str()); + is_consistent = false; + } else if (found && s.IsNotFound()) { + fprintf(stderr, "Get() return different results with key %s\n", + key_str.c_str()); + fprintf(stderr, "CF %s returns value %s\n", + column_family_names_[0].c_str(), value0.c_str()); + fprintf(stderr, "CF %s is not found\n", + column_family_names_[i].c_str()); + is_consistent = false; + } else if (s.ok() && value0 != value1) { + fprintf(stderr, "Get() return different results with key %s\n", + key_str.c_str()); + fprintf(stderr, "CF %s returns value %s\n", + column_family_names_[0].c_str(), value0.c_str()); + fprintf(stderr, "CF %s returns value %s\n", + column_family_names_[i].c_str(), value1.c_str()); + is_consistent = false; + } + if (!is_consistent) { + break; + } + } + } + + db_->ReleaseSnapshot(snapshot); + } + if (!is_consistent) { + thread->stats.AddErrors(1); + // Fail fast to preserve the DB state. + thread->shared->SetVerificationFailure(); + } else if (s.ok()) { thread->stats.AddGets(1, 1); } else if (s.IsNotFound()) { thread->stats.AddGets(1, 0);