Skip to content

Commit 0b426ff

Browse files
cbi42facebook-github-bot
authored andcommitted
Enable multiscan in crash test (facebook#13888)
Summary: I ran multiple runs of crash test jobs internally, so far I've seen one iterator mismatch and one assertion failure. I've added relevant logging improvements to help debugging them. use_multiscan will be stable within a crash test run to make it easier to triage. Pull Request resolved: facebook#13888 Test Plan: `python3 tools/db_crashtest.py whitebox --prefix_size=-1 --test_batches_snapshots=0 --use_multiscan=1 --read_fault_one_in=0 --kill_random_test=88888` Reviewed By: anand1976 Differential Revision: D80627399 Pulled By: cbi42 fbshipit-source-id: 2fa3f77e730f5bc7d1d200dc122cf84e3558c588
1 parent 618f660 commit 0b426ff

3 files changed

Lines changed: 60 additions & 6 deletions

File tree

db_stress_tool/db_stress_test_base.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1701,7 +1701,7 @@ Status StressTest::TestMultiScan(ThreadState* thread,
17011701
iter.reset(db_->NewIterator(ro, column_families_[rand_column_families[0]]));
17021702
iter->Prepare(scan_opts);
17031703

1704-
constexpr size_t kOpLogsLimit = 10000;
1704+
constexpr size_t kOpLogsLimit = 50000;
17051705

17061706
auto verify_func = [](Iterator* iterator) {
17071707
if (!VerifyWideColumns(iterator->value(), iterator->columns())) {
@@ -1801,11 +1801,24 @@ Status StressTest::TestMultiScan(ThreadState* thread,
18011801

18021802
VerifyIterator(thread, cmp_cfh, ro, iter.get(), cmp_iter.get(), last_op,
18031803
key, op_logs, verify_func, &diverged);
1804+
1805+
if (diverged) {
1806+
const std::vector<ScanOptions>& scanoptions = scan_opts.GetScanRanges();
1807+
for (const auto& t : scanoptions) {
1808+
fprintf(stdout, "Multiscan options: %s to %s \n",
1809+
t.range.start.value().ToString(true).c_str(),
1810+
t.range.limit.value().ToString(true).c_str());
1811+
}
1812+
break;
1813+
}
18041814
}
18051815

18061816
thread->stats.AddIterations(1);
18071817

18081818
op_logs += "; ";
1819+
if (diverged) {
1820+
break;
1821+
}
18091822
}
18101823

18111824
return Status::OK();

table/block_based/block_based_table_iterator.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,37 @@ void BlockBasedTableIterator::Prepare(const MultiScanArgs* multiscan_opts) {
11061106
const auto start_offset = first_block.offset();
11071107
const auto end_offset = last_block.offset() +
11081108
BlockBasedTable::BlockSizeWithTrailer(last_block);
1109+
#ifndef NDEBUG
1110+
// Debug print for failing the assertion below.
1111+
if (start_offset >= end_offset) {
1112+
fprintf(stderr, "blocks_to_prepare: ");
1113+
for (const auto& block : blocks_to_prepare) {
1114+
fprintf(stderr, "offset: %" PRIu64 ", size: %" PRIu64 "; ",
1115+
block.offset(), block.size());
1116+
}
1117+
fprintf(stderr,
1118+
"\nfirst block - offset: %" PRIu64 ", size: %" PRIu64 "\n",
1119+
first_block.offset(), first_block.size());
1120+
fprintf(stderr, "last block - offset: %" PRIu64 ", size: %" PRIu64 "\n",
1121+
last_block.offset(), last_block.size());
1122+
1123+
fprintf(stderr, "collapsed_blocks_to_read: ");
1124+
for (const auto& b : collapsed_blocks_to_read) {
1125+
fprintf(stderr, "[");
1126+
for (const auto& block_idx : b) {
1127+
fprintf(stderr, "%zu ", block_idx);
1128+
}
1129+
fprintf(stderr, "] ");
1130+
}
1131+
fprintf(stderr, "\ncurrent blocks: ");
1132+
for (const auto& block_idx : blocks) {
1133+
fprintf(stderr, "offset: %" PRIu64 ", size: %" PRIu64 "; ",
1134+
blocks_to_prepare[block_idx].offset(),
1135+
blocks_to_prepare[block_idx].size());
1136+
}
1137+
fprintf(stderr, "\n");
1138+
}
1139+
#endif // NDEBUG
11091140
assert(end_offset > start_offset);
11101141
FSReadRequest read_req;
11111142
read_req.offset = start_offset;

tools/db_crashtest.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@
181181
"format_version": lambda: random.choice([2, 3, 4, 5, 6, 7, 7]),
182182
"index_block_restart_interval": lambda: random.choice(range(1, 16)),
183183
"use_multiget": lambda: random.randint(0, 1),
184-
"use_multiscan": 0,
185184
"use_get_entity": lambda: random.choice([0] * 7 + [1]),
186185
"use_multi_get_entity": lambda: random.choice([0] * 7 + [1]),
187186
"periodic_compaction_seconds": lambda: random.choice([0, 0, 1, 2, 10, 100, 1000]),
@@ -360,6 +359,9 @@
360359
+ ["randommixed"] * 2
361360
+ ["custom"] * 3
362361
),
362+
# fixed within a run for easier debugging
363+
# actual frequency is lower after option sanitization
364+
"use_multiscan": random.choice([1] + [0] * 3),
363365
}
364366

365367
_TEST_DIR_ENV_VAR = "TEST_TMPDIR"
@@ -757,7 +759,7 @@ def finalize_and_sanitize(src_params):
757759
if (
758760
dest_params.get("test_batches_snapshots") == 1
759761
or dest_params.get("use_txn") == 1
760-
or dest_params.get("user_timestamp_size") > 0
762+
or dest_params.get("user_timestamp_size", 0) > 0
761763
):
762764
dest_params["ingest_external_file_one_in"] = 0
763765
if (
@@ -785,7 +787,7 @@ def finalize_and_sanitize(src_params):
785787
if (
786788
dest_params.get("sync_fault_injection") == 1
787789
or dest_params.get("disable_wal") == 1
788-
or dest_params.get("manual_wal_flush_one_in") > 0
790+
or dest_params.get("manual_wal_flush_one_in", 0) > 0
789791
):
790792
# File ingestion does not guarantee prefix-recoverability when unsynced
791793
# data can be lost. Ingesting a file syncs data immediately that is
@@ -992,7 +994,7 @@ def finalize_and_sanitize(src_params):
992994
dest_params["check_multiget_entity_consistency"] = 0
993995
if dest_params.get("disable_wal") == 0:
994996
if (
995-
dest_params.get("reopen") > 0
997+
dest_params.get("reopen", 0) > 0
996998
or (
997999
dest_params.get("manual_wal_flush_one_in")
9981000
and dest_params.get("column_families") != 1
@@ -1061,7 +1063,7 @@ def finalize_and_sanitize(src_params):
10611063
if dest_params.get("use_put_entity_one_in") == 1:
10621064
dest_params["use_timed_put_one_in"] = 0
10631065
elif (
1064-
dest_params.get("use_put_entity_one_in") > 1
1066+
dest_params.get("use_put_entity_one_in", 0) > 1
10651067
and dest_params.get("use_timed_put_one_in") == 1
10661068
):
10671069
dest_params["use_timed_put_one_in"] = 3
@@ -1102,6 +1104,14 @@ def finalize_and_sanitize(src_params):
11021104
# Continuous verification fails with secondaries inside NonBatchedOpsStressTest
11031105
if dest_params.get("test_secondary") == 1:
11041106
dest_params["continuous_verification_interval"] = 0
1107+
if (
1108+
dest_params.get("prefix_size", 0) > 0
1109+
or dest_params.get("read_fault_one_in", 0) > 0
1110+
):
1111+
dest_params["use_multiscan"] = 0
1112+
if dest_params.get("use_multiscan") == 1:
1113+
dest_params["fill_cache"] = 1
1114+
dest_params["async_io"] = 0
11051115
return dest_params
11061116

11071117

0 commit comments

Comments
 (0)