Migrate ErrorEnv from EnvWrapper to FileSystemWrapper (#11124)

Summary:
Migrate ErrorEnv from EnvWrapper to FileSystemWrapper so we can eventually deprecate the storage methods in Env.

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

Reviewed By: akankshamahajan15

Differential Revision: D42727791

Pulled By: anand1976

fbshipit-source-id: e8362ad624dc28e55c99fc35eda12866755f62c6
oxigraph-8.1.1
anand76 2 years ago committed by Facebook GitHub Bot
parent 2800aa069a
commit bcbab59c55
  1. 91
      db/corruption_test.cc

@ -43,33 +43,36 @@ namespace ROCKSDB_NAMESPACE {
static constexpr int kValueSize = 1000; static constexpr int kValueSize = 1000;
namespace { namespace {
// A wrapper that allows injection of errors. // A wrapper that allows injection of errors.
class ErrorEnv : public EnvWrapper { class ErrorFS : public FileSystemWrapper {
public: public:
bool writable_file_error_; bool writable_file_error_;
int num_writable_file_errors_; int num_writable_file_errors_;
explicit ErrorEnv(Env* _target) explicit ErrorFS(const std::shared_ptr<FileSystem>& _target)
: EnvWrapper(_target), : FileSystemWrapper(_target),
writable_file_error_(false), writable_file_error_(false),
num_writable_file_errors_(0) {} num_writable_file_errors_(0) {}
const char* Name() const override { return "ErrorEnv"; } const char* Name() const override { return "ErrorEnv"; }
virtual Status NewWritableFile(const std::string& fname, virtual IOStatus NewWritableFile(const std::string& fname,
std::unique_ptr<WritableFile>* result, const FileOptions& opts,
const EnvOptions& soptions) override { std::unique_ptr<FSWritableFile>* result,
IODebugContext* dbg) override {
result->reset(); result->reset();
if (writable_file_error_) { if (writable_file_error_) {
++num_writable_file_errors_; ++num_writable_file_errors_;
return Status::IOError(fname, "fake error"); return IOStatus::IOError(fname, "fake error");
} }
return target()->NewWritableFile(fname, result, soptions); return target()->NewWritableFile(fname, opts, result, dbg);
} }
}; };
} // anonymous namespace } // anonymous namespace
class CorruptionTest : public testing::Test { class CorruptionTest : public testing::Test {
public: public:
std::shared_ptr<Env> env_guard_; std::shared_ptr<Env> env_guard_;
ErrorEnv* env_; std::shared_ptr<ErrorFS> fs_;
std::unique_ptr<Env> env_;
Env* base_env_;
std::string dbname_; std::string dbname_;
std::shared_ptr<Cache> tiny_cache_; std::shared_ptr<Cache> tiny_cache_;
Options options_; Options options_;
@ -80,14 +83,15 @@ class CorruptionTest : public testing::Test {
// set it to 0), test SequenceNumberRecovery will fail, likely because of a // set it to 0), test SequenceNumberRecovery will fail, likely because of a
// bug in recovery code. Keep it 4 for now to make the test passes. // bug in recovery code. Keep it 4 for now to make the test passes.
tiny_cache_ = NewLRUCache(100, 4); tiny_cache_ = NewLRUCache(100, 4);
Env* base_env = Env::Default(); base_env_ = Env::Default();
EXPECT_OK( EXPECT_OK(
test::CreateEnvFromSystem(ConfigOptions(), &base_env, &env_guard_)); test::CreateEnvFromSystem(ConfigOptions(), &base_env_, &env_guard_));
EXPECT_NE(base_env, nullptr); EXPECT_NE(base_env_, nullptr);
env_ = new ErrorEnv(base_env); fs_.reset(new ErrorFS(base_env_->GetFileSystem()));
env_ = NewCompositeEnv(fs_);
options_.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords; options_.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords;
options_.env = env_; options_.env = env_.get();
dbname_ = test::PerThreadDBPath(env_, "corruption_test"); dbname_ = test::PerThreadDBPath(env_.get(), "corruption_test");
Status s = DestroyDB(dbname_, options_); Status s = DestroyDB(dbname_, options_);
EXPECT_OK(s); EXPECT_OK(s);
@ -110,10 +114,9 @@ class CorruptionTest : public testing::Test {
fprintf(stdout, "db is still at %s\n", dbname_.c_str()); fprintf(stdout, "db is still at %s\n", dbname_.c_str());
} else { } else {
Options opts; Options opts;
opts.env = env_->target(); opts.env = base_env_;
EXPECT_OK(DestroyDB(dbname_, opts)); EXPECT_OK(DestroyDB(dbname_, opts));
} }
delete env_;
} }
void CloseDb() { void CloseDb() {
@ -128,7 +131,7 @@ class CorruptionTest : public testing::Test {
if (opt.env == Options().env) { if (opt.env == Options().env) {
// If env is not overridden, replace it with ErrorEnv. // If env is not overridden, replace it with ErrorEnv.
// Otherwise, the test already uses a non-default Env. // Otherwise, the test already uses a non-default Env.
opt.env = env_; opt.env = env_.get();
} }
opt.arena_block_size = 4096; opt.arena_block_size = 4096;
BlockBasedTableOptions table_options; BlockBasedTableOptions table_options;
@ -223,7 +226,7 @@ class CorruptionTest : public testing::Test {
} }
ASSERT_TRUE(!fname.empty()) << filetype; ASSERT_TRUE(!fname.empty()) << filetype;
ASSERT_OK(test::CorruptFile(env_, fname, offset, bytes_to_corrupt, ASSERT_OK(test::CorruptFile(env_.get(), fname, offset, bytes_to_corrupt,
/*verify_checksum*/ filetype == kTableFile)); /*verify_checksum*/ filetype == kTableFile));
} }
@ -234,7 +237,7 @@ class CorruptionTest : public testing::Test {
db_->GetLiveFilesMetaData(&metadata); db_->GetLiveFilesMetaData(&metadata);
for (const auto& m : metadata) { for (const auto& m : metadata) {
if (m.level == level) { if (m.level == level) {
ASSERT_OK(test::CorruptFile(env_, dbname_ + "/" + m.name, offset, ASSERT_OK(test::CorruptFile(env_.get(), dbname_ + "/" + m.name, offset,
bytes_to_corrupt)); bytes_to_corrupt));
return; return;
} }
@ -308,7 +311,7 @@ class CorruptionTest : public testing::Test {
if (bytes_to_truncate == 0) { if (bytes_to_truncate == 0) {
new_size = 0; new_size = 0;
} }
ASSERT_OK(test::TruncateFile(env_, path, new_size)); ASSERT_OK(test::TruncateFile(env_.get(), path, new_size));
} }
}; };
@ -402,14 +405,14 @@ TEST_F(CorruptionTest, PostPITRCorruptionWALsRetained) {
} }
TEST_F(CorruptionTest, RecoverWriteError) { TEST_F(CorruptionTest, RecoverWriteError) {
env_->writable_file_error_ = true; fs_->writable_file_error_ = true;
Status s = TryReopen(); Status s = TryReopen();
ASSERT_TRUE(!s.ok()); ASSERT_TRUE(!s.ok());
} }
TEST_F(CorruptionTest, NewFileErrorDuringWrite) { TEST_F(CorruptionTest, NewFileErrorDuringWrite) {
// Do enough writing to force minor compaction // Do enough writing to force minor compaction
env_->writable_file_error_ = true; fs_->writable_file_error_ = true;
const int num = const int num =
static_cast<int>(3 + (Options().write_buffer_size / kValueSize)); static_cast<int>(3 + (Options().write_buffer_size / kValueSize));
std::string value_storage; std::string value_storage;
@ -425,8 +428,8 @@ TEST_F(CorruptionTest, NewFileErrorDuringWrite) {
ASSERT_TRUE(!failed || !s.ok()); ASSERT_TRUE(!failed || !s.ok());
} }
ASSERT_TRUE(!s.ok()); ASSERT_TRUE(!s.ok());
ASSERT_GE(env_->num_writable_file_errors_, 1); ASSERT_GE(fs_->num_writable_file_errors_, 1);
env_->writable_file_error_ = false; fs_->writable_file_error_ = false;
Reopen(); Reopen();
} }
@ -444,7 +447,7 @@ TEST_F(CorruptionTest, TableFile) {
TEST_F(CorruptionTest, VerifyChecksumReadahead) { TEST_F(CorruptionTest, VerifyChecksumReadahead) {
Options options; Options options;
SpecialEnv senv(env_->target()); SpecialEnv senv(base_env_);
options.env = &senv; options.env = &senv;
// Disable block cache as we are going to check checksum for // Disable block cache as we are going to check checksum for
// the same file twice and measure number of reads. // the same file twice and measure number of reads.
@ -587,8 +590,8 @@ TEST_F(CorruptionTest, TableFileWrongSize) {
// Make the file smaller with truncation. // Make the file smaller with truncation.
// First leaving a partial footer, and then completely removing footer. // First leaving a partial footer, and then completely removing footer.
for (size_t bytes_lost : {8, 100}) { for (size_t bytes_lost : {8, 100}) {
ASSERT_OK( ASSERT_OK(test::TruncateFile(env_.get(), filename,
test::TruncateFile(env_, filename, metadata[0].size - bytes_lost)); metadata[0].size - bytes_lost));
// Reported well with paranoid checks // Reported well with paranoid checks
options_.paranoid_checks = true; options_.paranoid_checks = true;
@ -653,7 +656,7 @@ TEST_F(CorruptionTest, CorruptedDescriptor) {
TEST_F(CorruptionTest, CompactionInputError) { TEST_F(CorruptionTest, CompactionInputError) {
Options options; Options options;
options.env = env_; options.env = env_.get();
Reopen(&options); Reopen(&options);
Build(10); Build(10);
DBImpl* dbi = static_cast_with_check<DBImpl>(db_); DBImpl* dbi = static_cast_with_check<DBImpl>(db_);
@ -674,7 +677,7 @@ TEST_F(CorruptionTest, CompactionInputError) {
TEST_F(CorruptionTest, CompactionInputErrorParanoid) { TEST_F(CorruptionTest, CompactionInputErrorParanoid) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.paranoid_checks = true; options.paranoid_checks = true;
options.write_buffer_size = 131072; options.write_buffer_size = 131072;
options.max_write_buffer_number = 2; options.max_write_buffer_number = 2;
@ -761,7 +764,7 @@ TEST_F(CorruptionTest, RangeDeletionCorrupted) {
ImmutableOptions(options_), kRangeDelBlockName, &range_del_handle)); ImmutableOptions(options_), kRangeDelBlockName, &range_del_handle));
ASSERT_OK(TryReopen()); ASSERT_OK(TryReopen());
ASSERT_OK(test::CorruptFile(env_, filename, ASSERT_OK(test::CorruptFile(env_.get(), filename,
static_cast<int>(range_del_handle.offset()), 1)); static_cast<int>(range_del_handle.offset()), 1));
ASSERT_TRUE(TryReopen().IsCorruption()); ASSERT_TRUE(TryReopen().IsCorruption());
} }
@ -769,7 +772,7 @@ TEST_F(CorruptionTest, RangeDeletionCorrupted) {
TEST_F(CorruptionTest, FileSystemStateCorrupted) { TEST_F(CorruptionTest, FileSystemStateCorrupted) {
for (int iter = 0; iter < 2; ++iter) { for (int iter = 0; iter < 2; ++iter) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.paranoid_checks = true; options.paranoid_checks = true;
options.create_if_missing = true; options.create_if_missing = true;
Reopen(&options); Reopen(&options);
@ -808,7 +811,7 @@ static const auto& corruption_modes = {
TEST_F(CorruptionTest, ParanoidFileChecksOnFlush) { TEST_F(CorruptionTest, ParanoidFileChecksOnFlush) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.check_flush_compaction_key_order = false; options.check_flush_compaction_key_order = false;
options.paranoid_file_checks = true; options.paranoid_file_checks = true;
options.create_if_missing = true; options.create_if_missing = true;
@ -836,7 +839,7 @@ TEST_F(CorruptionTest, ParanoidFileChecksOnFlush) {
TEST_F(CorruptionTest, ParanoidFileChecksOnCompact) { TEST_F(CorruptionTest, ParanoidFileChecksOnCompact) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.paranoid_file_checks = true; options.paranoid_file_checks = true;
options.create_if_missing = true; options.create_if_missing = true;
options.check_flush_compaction_key_order = false; options.check_flush_compaction_key_order = false;
@ -869,7 +872,7 @@ TEST_F(CorruptionTest, ParanoidFileChecksOnCompact) {
TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeFirst) { TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeFirst) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.check_flush_compaction_key_order = false; options.check_flush_compaction_key_order = false;
options.paranoid_file_checks = true; options.paranoid_file_checks = true;
options.create_if_missing = true; options.create_if_missing = true;
@ -905,7 +908,7 @@ TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeFirst) {
TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRange) { TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRange) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.check_flush_compaction_key_order = false; options.check_flush_compaction_key_order = false;
options.paranoid_file_checks = true; options.paranoid_file_checks = true;
options.create_if_missing = true; options.create_if_missing = true;
@ -944,7 +947,7 @@ TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRange) {
TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeLast) { TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeLast) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.check_flush_compaction_key_order = false; options.check_flush_compaction_key_order = false;
options.paranoid_file_checks = true; options.paranoid_file_checks = true;
options.create_if_missing = true; options.create_if_missing = true;
@ -980,7 +983,7 @@ TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeLast) {
TEST_F(CorruptionTest, LogCorruptionErrorsInCompactionIterator) { TEST_F(CorruptionTest, LogCorruptionErrorsInCompactionIterator) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.create_if_missing = true; options.create_if_missing = true;
options.allow_data_in_errors = true; options.allow_data_in_errors = true;
auto mode = mock::MockTableFactory::kCorruptKey; auto mode = mock::MockTableFactory::kCorruptKey;
@ -1009,7 +1012,7 @@ TEST_F(CorruptionTest, LogCorruptionErrorsInCompactionIterator) {
TEST_F(CorruptionTest, CompactionKeyOrderCheck) { TEST_F(CorruptionTest, CompactionKeyOrderCheck) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.paranoid_file_checks = false; options.paranoid_file_checks = false;
options.create_if_missing = true; options.create_if_missing = true;
options.check_flush_compaction_key_order = false; options.check_flush_compaction_key_order = false;
@ -1036,7 +1039,7 @@ TEST_F(CorruptionTest, CompactionKeyOrderCheck) {
TEST_F(CorruptionTest, FlushKeyOrderCheck) { TEST_F(CorruptionTest, FlushKeyOrderCheck) {
Options options; Options options;
options.env = env_; options.env = env_.get();
options.paranoid_file_checks = false; options.paranoid_file_checks = false;
options.create_if_missing = true; options.create_if_missing = true;
ASSERT_OK(db_->SetOptions({{"check_flush_compaction_key_order", "true"}})); ASSERT_OK(db_->SetOptions({{"check_flush_compaction_key_order", "true"}}));
@ -1089,7 +1092,7 @@ TEST_F(CorruptionTest, DisableKeyOrderCheck) {
TEST_F(CorruptionTest, VerifyWholeTableChecksum) { TEST_F(CorruptionTest, VerifyWholeTableChecksum) {
CloseDb(); CloseDb();
Options options; Options options;
options.env = env_; options.env = env_.get();
ASSERT_OK(DestroyDB(dbname_, options)); ASSERT_OK(DestroyDB(dbname_, options));
options.create_if_missing = true; options.create_if_missing = true;
options.file_checksum_gen_factory = options.file_checksum_gen_factory =
@ -1178,7 +1181,7 @@ TEST_P(CrashDuringRecoveryWithCorruptionTest, CrashDuringRecovery) {
track_and_verify_wals_in_manifest_; track_and_verify_wals_in_manifest_;
options.wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery; options.wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery;
options.avoid_flush_during_recovery = false; options.avoid_flush_during_recovery = false;
options.env = env_; options.env = env_.get();
ASSERT_OK(DestroyDB(dbname_, options)); ASSERT_OK(DestroyDB(dbname_, options));
options.create_if_missing = true; options.create_if_missing = true;
options.max_write_buffer_number = 8; options.max_write_buffer_number = 8;
@ -1350,7 +1353,7 @@ TEST_P(CrashDuringRecoveryWithCorruptionTest, TxnDbCrashDuringRecovery) {
options.track_and_verify_wals_in_manifest = options.track_and_verify_wals_in_manifest =
track_and_verify_wals_in_manifest_; track_and_verify_wals_in_manifest_;
options.avoid_flush_during_recovery = false; options.avoid_flush_during_recovery = false;
options.env = env_; options.env = env_.get();
ASSERT_OK(DestroyDB(dbname_, options)); ASSERT_OK(DestroyDB(dbname_, options));
options.create_if_missing = true; options.create_if_missing = true;
options.max_write_buffer_number = 3; options.max_write_buffer_number = 3;
@ -1545,7 +1548,7 @@ TEST_P(CrashDuringRecoveryWithCorruptionTest, CrashDuringRecoveryWithFlush) {
Options options; Options options;
options.wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery; options.wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery;
options.avoid_flush_during_recovery = false; options.avoid_flush_during_recovery = false;
options.env = env_; options.env = env_.get();
options.create_if_missing = true; options.create_if_missing = true;
ASSERT_OK(DestroyDB(dbname_, options)); ASSERT_OK(DestroyDB(dbname_, options));

Loading…
Cancel
Save