Verify columns in NonBatchedOpsStressTest::VerifyDb (#10783)

Summary:
As the first step of covering the wide-column functionality of iterators
in our stress tests, the patch adds verification logic to
`NonBatchedOpsStressTest::VerifyDb` that checks whether the
iterator's value and columns are in sync. Note: I plan to update the other
types of stress tests and add similar verification for prefix scans etc.
in separate PRs.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10783

Test Plan: Ran some simple blackbox crash tests.

Reviewed By: riversand963

Differential Revision: D40152370

Pulled By: riversand963

fbshipit-source-id: 8f9d17d7af5da58ccf1bd2057cab53cc9645ac35
This commit is contained in:
Levi Tamasi 2022-10-06 15:07:16 -07:00 committed by Facebook GitHub Bot
parent b205c6d029
commit d6d8c007ff
7 changed files with 86 additions and 4 deletions

View File

@ -15,10 +15,6 @@
namespace ROCKSDB_NAMESPACE {
const Slice kDefaultWideColumnName;
const WideColumns kNoWideColumns;
Status WideColumnSerialization::Serialize(const WideColumns& columns,
std::string& output) {
if (columns.size() >

View File

@ -9,6 +9,10 @@
namespace ROCKSDB_NAMESPACE {
const Slice kDefaultWideColumnName;
const WideColumns kNoWideColumns;
Status PinnableWideColumns::CreateIndexForWideColumns() {
Slice value_copy = value_;

View File

@ -263,6 +263,11 @@ WideColumns GenerateWideColumns(uint32_t value_base, const Slice& slice) {
WideColumns GenerateExpectedWideColumns(uint32_t value_base,
const Slice& slice) {
if (FLAGS_use_put_entity_one_in == 0 ||
(value_base % FLAGS_use_put_entity_one_in) != 0) {
return WideColumns{{kDefaultWideColumnName, slice}};
}
WideColumns columns = GenerateWideColumns(value_base, slice);
std::sort(columns.begin(), columns.end(),

View File

@ -8,6 +8,8 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
#include <ios>
#include "util/compression.h"
#ifdef GFLAGS
#include "cache/fast_lru_cache.h"
@ -438,6 +440,53 @@ void StressTest::VerificationAbort(SharedState* shared, std::string msg, int cf,
shared->SetVerificationFailure();
}
void StressTest::VerificationAbort(SharedState* shared, int cf, int64_t key,
const Slice& value,
const WideColumns& columns,
const WideColumns& expected_columns) const {
assert(shared);
auto key_str = Key(key);
fprintf(stderr,
"Verification failed for column family %d key %s (%" PRIi64
"): Value and columns inconsistent: %s\n",
cf, Slice(key_str).ToString(/* hex */ true).c_str(), key,
DebugString(value, columns, expected_columns).c_str());
shared->SetVerificationFailure();
}
std::string StressTest::DebugString(const Slice& value,
const WideColumns& columns,
const WideColumns& expected_columns) {
std::ostringstream oss;
oss << "value: " << value.ToString(/* hex */ true);
auto dump = [](const WideColumns& cols, std::ostream& os) {
if (cols.empty()) {
return;
}
os << std::hex;
auto it = cols.begin();
os << *it;
for (++it; it != cols.end(); ++it) {
os << ' ' << *it;
}
};
oss << ", columns: ";
dump(columns, oss);
oss << ", expected_columns: ";
dump(expected_columns, oss);
return oss.str();
}
void StressTest::PrintStatistics() {
if (dbstats) {
fprintf(stdout, "STATISTICS:\n%s\n", dbstats->ToString().c_str());

View File

@ -9,6 +9,9 @@
#ifdef GFLAGS
#pragma once
#include <ostream>
#include "db_stress_tool/db_stress_common.h"
#include "db_stress_tool/db_stress_shared_state.h"
@ -231,6 +234,13 @@ class StressTest {
int64_t key, Slice value_from_db,
Slice value_from_expected) const;
void VerificationAbort(SharedState* shared, int cf, int64_t key,
const Slice& value, const WideColumns& columns,
const WideColumns& expected_columns) const;
static std::string DebugString(const Slice& value, const WideColumns& columns,
const WideColumns& expected_columns);
void PrintEnv() const;
void Open(SharedState* shared);

View File

@ -101,6 +101,15 @@ class NonBatchedOpsStressTest : public StressTest {
if (diff > 0) {
s = Status::NotFound();
} else if (diff == 0) {
const WideColumns expected_columns = GenerateExpectedWideColumns(
GetValueBase(iter->value()), iter->value());
if (iter->columns() != expected_columns) {
VerificationAbort(shared, static_cast<int>(cf), i,
iter->value(), iter->columns(),
expected_columns);
break;
}
from_db = iter->value().ToString();
iter->Next();
} else {

View File

@ -5,6 +5,7 @@
#pragma once
#include <ostream>
#include <tuple>
#include <utility>
#include <vector>
@ -70,6 +71,14 @@ inline bool operator!=(const WideColumn& lhs, const WideColumn& rhs) {
return !(lhs == rhs);
}
inline std::ostream& operator<<(std::ostream& os, const WideColumn& column) {
const bool hex =
(os.flags() & std::ios_base::basefield) == std::ios_base::hex;
os << column.name().ToString(hex) << ':' << column.value().ToString(hex);
return os;
}
// A collection of wide columns.
using WideColumns = std::vector<WideColumn>;