tools/scylla-sstable: scrub: don't qurantine sstables after validate

Scylla sstable promises to *never* mutate its input sstables. This
promise was broken by `scylla sstable scrub --scrub-mode=validate`,
because validate moves invalid input sstables into qurantine. This is
unexpected and caused occasional failures in the scrub tests in
test_tools.py. Fix by propagating a flag down to
`scrub_sstables_validate_mode()` in `compaction.cc`, specifying whether
validate should qurantine invalid sstables, then set this flag to false
in `scylla-sstable.cc`. The existing test for validate-mode scrub is
ammended to check that the sstable is not mutated. The test now fails
before the fix and passes afterwards.

Fixes: #14309

Closes #15139
This commit is contained in:
Botond Dénes
2023-08-23 07:51:58 -04:00
committed by Avi Kivity
parent 93be4c0cb0
commit 1609c76d62
4 changed files with 19 additions and 4 deletions

View File

@@ -1733,7 +1733,8 @@ static future<compaction_result> scrub_sstables_validate_mode(sstables::compacti
clogger.info("Finished scrubbing in validate mode {} - sstable is {}", sst->get_filename(), validation_errors == 0 ? "valid" : "invalid");
}
if (validation_errors != 0) {
using scrub = sstables::compaction_type_options::scrub;
if (validation_errors != 0 && descriptor.options.as<scrub>().quarantine_sstables == scrub::quarantine_invalid_sstables::yes) {
for (auto& sst : descriptor.sstables) {
co_await sst->change_state(sstables::sstable_state::quarantine);
}

View File

@@ -72,6 +72,12 @@ public:
only, // scrub only quarantined sstables
};
quarantine_mode quarantine_operation_mode = quarantine_mode::include;
using quarantine_invalid_sstables = bool_class<class quarantine_invalid_sstables_tag>;
// Should invalid sstables be moved into quarantine.
// Only applies to validate-mode.
quarantine_invalid_sstables quarantine_sstables = quarantine_invalid_sstables::yes;
};
struct reshard {
};
@@ -108,8 +114,8 @@ public:
return compaction_type_options(upgrade{});
}
static compaction_type_options make_scrub(scrub::mode mode) {
return compaction_type_options(scrub{mode});
static compaction_type_options make_scrub(scrub::mode mode, scrub::quarantine_invalid_sstables quarantine_sstables = scrub::quarantine_invalid_sstables::yes) {
return compaction_type_options(scrub{.operation_mode = mode, .quarantine_sstables = quarantine_sstables});
}
template <typename... Visitor>
@@ -117,6 +123,11 @@ public:
return std::visit(std::forward<Visitor>(visitor)..., _options);
}
template <typename OptionType>
const auto& as() const {
return std::get<OptionType>(_options);
}
const options_variant& options() const { return _options; }
compaction_type type() const;

View File

@@ -832,3 +832,6 @@ def test_scrub_validate_mode(scylla_path, scrub_schema_file, scrub_good_sstable,
subprocess.check_call([scylla_path, "sstable", "scrub", "--schema-file", scrub_schema_file, "--scrub-mode", "validate", "--output-dir", tmp_dir, scrub_bad_sstable])
check_scrub_output_dir(tmp_dir, 0)
# Check that validate did not move the bad sstable into qurantine
assert os.path.exists(scrub_bad_sstable)

View File

@@ -916,7 +916,7 @@ void scrub_operation(schema_ptr schema, reader_permit permit, const std::vector<
scylla_sstable_table_state table_state(schema, permit, sst_man, output_dir);
auto compaction_descriptor = sstables::compaction_descriptor(std::move(sstables));
compaction_descriptor.options = sstables::compaction_type_options::make_scrub(scrub_mode);
compaction_descriptor.options = sstables::compaction_type_options::make_scrub(scrub_mode, sstables::compaction_type_options::scrub::quarantine_invalid_sstables::no);
compaction_descriptor.creator = [&table_state] (shard_id) { return table_state.make_sstable(); };
compaction_descriptor.replacer = [] (sstables::compaction_completion_desc) { };