Reduce db stress noise (#13447)

Summary:
[Experiment]

This PR is a followup to https://github.com/facebook/rocksdb/pull/13408. Thick bandaid of ignoring all injected read errors in context of periodic iterator auto refreshes in db stress proved to be effective. We confirmed our theory that errors are not a really a consequence / defect related to this new feature but rather due to subtle ways in which downstream code paths handle their respective IO failures. In this change we're replacing a thick 'ignore all IO read errors' bandaid in `no_batched_ops_stress` with a much smaller, targeted patches in obsolete files purge / delete codepaths, table block cache reader, table cache lookup to make sure we don't miss signal and ensure there's a single mechanism for ignoring error injection in db stress tests.

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

Reviewed By: hx235

Differential Revision: D70794787

Pulled By: mszeszko-meta

fbshipit-source-id: c5fcd4780d82357c407f53bf0bb22fc38f7bd277
This commit is contained in:
Maciej Szeszko
2025-03-12 01:13:40 -07:00
committed by Facebook GitHub Bot
parent 22ca6e5e68
commit 8e16f8fecf
7 changed files with 10 additions and 9 deletions
+3
View File
@@ -368,6 +368,7 @@ void DBImpl::DeleteObsoleteFileImpl(int job_id, const std::string& fname,
FileType type, uint64_t number) {
TEST_SYNC_POINT_CALLBACK("DBImpl::DeleteObsoleteFileImpl::BeforeDeletion",
const_cast<std::string*>(&fname));
IGNORE_STATUS_IF_ERROR(Status::IOError());
Status file_deletion_status;
if (type == kTableFile || type == kBlobFile || type == kWalFile) {
@@ -423,6 +424,8 @@ void DBImpl::PurgeObsoleteFiles(JobContext& state, bool schedule_only) {
// FindObsoleteFiles() should've populated this so nonzero
assert(state.manifest_file_number != 0);
IGNORE_STATUS_IF_ERROR(Status::IOError());
// Now, convert lists to unordered sets, WITHOUT mutex held; set is slow.
std::unordered_set<uint64_t> sst_live_set(state.sst_live.begin(),
state.sst_live.end());
+1
View File
@@ -205,6 +205,7 @@ Status TableCache::FindTable(
RecordTick(ioptions_.stats, NO_FILE_ERRORS);
// We do not cache error results so that if the error is transient,
// or somebody repairs the file, we recover automatically.
IGNORE_STATUS_IF_ERROR(s);
} else {
s = cache_.Insert(key, table_reader.get(), 1, handle);
if (s.ok()) {
+1
View File
@@ -283,6 +283,7 @@ void WalManager::ArchiveWALFile(const std::string& fname, uint64_t number) {
// The sync point below is used in (DBTest,TransactionLogIteratorRace)
TEST_SYNC_POINT("WalManager::PurgeObsoleteFiles:1");
Status s = env_->RenameFile(fname, archived_log_name);
IGNORE_STATUS_IF_ERROR(s);
// The sync point below is used in (DBTest,TransactionLogIteratorRace)
TEST_SYNC_POINT("WalManager::PurgeObsoleteFiles:2");
// The sync point below is used in
+1 -1
View File
@@ -137,7 +137,7 @@ class SharedState {
for (int i = 0; i < FLAGS_column_families; ++i) {
key_locks_[i].reset(new port::Mutex[num_locks]);
}
if (FLAGS_read_fault_one_in) {
if (FLAGS_read_fault_one_in || FLAGS_metadata_read_fault_one_in) {
#ifdef NDEBUG
// Unsupported in release mode because it relies on
// `IGNORE_STATUS_IF_ERROR` to distinguish faults not expected to lead to
+1 -8
View File
@@ -1600,12 +1600,6 @@ class NonBatchedOpsStressTest : public StressTest {
Slice ub_slice;
ReadOptions ro_copy = read_opts;
// There is a narrow window in iterator auto refresh run where injected read
// errors are simply untraceable, ex. failure to delete file as a part of
// superversion cleanup callback invoked by the DBIter destructor.
bool ignore_injected_read_error_in_iter =
ro_copy.auto_refresh_iterator_with_snapshot;
// Randomly test with `iterate_upper_bound` and `prefix_same_as_start`
//
// Get the next prefix first and then see if we want to set it to be the
@@ -1698,8 +1692,7 @@ class NonBatchedOpsStressTest : public StressTest {
FaultInjectionIOType::kRead),
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
FaultInjectionIOType::kMetadataRead));
if (!ignore_injected_read_error_in_iter &&
!SharedState::ignore_read_error && injected_error_count > 0 &&
if (!SharedState::ignore_read_error && injected_error_count > 0 &&
s.ok()) {
// Grab mutex so multiple thread don't try to print the
// stack trace at the same time
+2
View File
@@ -130,6 +130,7 @@ Status DeleteScheduler::AddFileToDeletionQueue(const std::string& file_path,
s.ToString().c_str());
if (!s.ok()) {
IGNORE_STATUS_IF_ERROR(s);
ROCKS_LOG_ERROR(info_log_, "Failed to mark %s as trash -- %s",
file_path.c_str(), s.ToString().c_str());
s = fs_->DeleteFile(file_path, IOOptions(), nullptr);
@@ -151,6 +152,7 @@ Status DeleteScheduler::AddFileToDeletionQueue(const std::string& file_path,
if (io_s.ok()) {
total_trash_size_.fetch_add(trash_file_size);
}
IGNORE_STATUS_IF_ERROR(s);
}
//**TODO: What should we do if we failed to
// get the file size?
+1
View File
@@ -320,6 +320,7 @@ void BlockFetcher::ReadBlock(bool retry) {
}
PERF_COUNTER_ADD(block_read_byte, block_size_with_trailer_);
IGNORE_STATUS_IF_ERROR(io_status_);
if (io_status_.ok()) {
if (use_fs_scratch_ && !read_req.status.ok()) {
io_status_ = read_req.status;