Skip to content

Commit

Permalink
Do not attempt to rename non-existent info log (facebook#8622)
Browse files Browse the repository at this point in the history
Summary:
Previously we attempted to rename "LOG" to "LOG.old.*" without checking
its existence first. "LOG" had no reason to exist in a new DB.

Errors in renaming a non-existent "LOG" were swallowed via
`PermitUncheckedError()` so things worked. However the storage service's
error monitoring was detecting all these benign rename failures. So it
is better to fix it. Also with this PR we can now distinguish rename failure
for other reasons and return them.

Pull Request resolved: facebook#8622

Test Plan: new unit test

Reviewed By: akankshamahajan15

Differential Revision: D30115189

Pulled By: ajkr

fbshipit-source-id: e2f337ffb2bd171be0203172abc8e16e7809b170
  • Loading branch information
ajkr authored and facebook-github-bot committed Aug 5, 2021
1 parent a074d46 commit a685a70
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 6 deletions.
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Bug Fixes
* If the primary's CURRENT file is missing or inaccessible, the secondary instance should not hang repeatedly trying to switch to a new MANIFEST. It should instead return the error code encountered while accessing the file.
* Fixed a race related to the destruction of `ColumnFamilyData` objects. The earlier logic unlocked the DB mutex before destroying the thread-local `SuperVersion` pointers, which could result in a process crash if another thread managed to get a reference to the `ColumnFamilyData` object.
* Removed a call to `RenameFile()` on a non-existent info log file ("LOG") when opening a new DB. Such a call was guaranteed to fail though did not impact applications since we swallowed the error. Now we also stopped swallowing errors in renaming "LOG" file.

### New Features
* Made the EventListener extend the Customizable class.
Expand Down
13 changes: 13 additions & 0 deletions db/db_test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,14 @@ class SpecialEnv : public EnvWrapper {
}
}

Status RenameFile(const std::string& src, const std::string& dest) override {
rename_count_.fetch_add(1);
if (rename_error_.load(std::memory_order_acquire)) {
return Status::NotSupported("Simulated `RenameFile()` error.");
}
return target()->RenameFile(src, dest);
}

// Something to return when mocking current time
const int64_t maybe_starting_time_;

Expand Down Expand Up @@ -702,6 +710,9 @@ class SpecialEnv : public EnvWrapper {
// Force write to log files to fail while this pointer is non-nullptr
std::atomic<bool> log_write_error_;

// Force `RenameFile()` to fail while this pointer is non-nullptr
std::atomic<bool> rename_error_{false};

// Slow down every log write, in micro-seconds.
std::atomic<int> log_write_slowdown_;

Expand Down Expand Up @@ -745,6 +756,8 @@ class SpecialEnv : public EnvWrapper {

std::atomic<int> delete_count_;

std::atomic<int> rename_count_{0};

std::atomic<bool> is_wal_sync_thread_safe_{true};

std::atomic<size_t> compaction_readahead_size_{};
Expand Down
19 changes: 13 additions & 6 deletions logging/auto_roll_logger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,19 @@ Status CreateLoggerFromOptions(const std::string& dbname,
}
#endif // !ROCKSDB_LITE
// Open a log file in the same directory as the db
env->RenameFile(
fname, OldInfoLogFileName(dbname, clock->NowMicros(), db_absolute_path,
options.db_log_dir))
.PermitUncheckedError();
s = env->NewLogger(fname, logger);
if (logger->get() != nullptr) {
s = env->FileExists(fname);
if (s.ok()) {
s = env->RenameFile(
fname, OldInfoLogFileName(dbname, clock->NowMicros(), db_absolute_path,
options.db_log_dir));
} else if (s.IsNotFound()) {
// "LOG" is not required to exist since this could be a new DB.
s = Status::OK();
}
if (s.ok()) {
s = env->NewLogger(fname, logger);
}
if (s.ok() && logger->get() != nullptr) {
(*logger)->SetInfoLogLevel(options.info_log_level);
}
return s;
Expand Down
45 changes: 45 additions & 0 deletions logging/auto_roll_logger_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <thread>
#include <vector>

#include "db/db_test_util.h"
#include "logging/logging.h"
#include "port/port.h"
#include "rocksdb/db.h"
Expand Down Expand Up @@ -686,6 +687,50 @@ TEST_F(AutoRollLoggerTest, FileCreateFailure) {
ASSERT_NOK(CreateLoggerFromOptions("", options, &logger));
ASSERT_TRUE(!logger);
}

TEST_F(AutoRollLoggerTest, RenameOnlyWhenExists) {
InitTestDb();
SpecialEnv env(Env::Default());
Options options;
options.env = &env;

// Originally no LOG exists. Should not see a rename.
{
std::shared_ptr<Logger> logger;
ASSERT_OK(CreateLoggerFromOptions(kTestDir, options, &logger));
ASSERT_EQ(0, env.rename_count_);
}

// Now a LOG exists. Create a new one should see a rename.
{
std::shared_ptr<Logger> logger;
ASSERT_OK(CreateLoggerFromOptions(kTestDir, options, &logger));
ASSERT_EQ(1, env.rename_count_);
}
}

TEST_F(AutoRollLoggerTest, RenameError) {
InitTestDb();
SpecialEnv env(Env::Default());
env.rename_error_ = true;
Options options;
options.env = &env;

// Originally no LOG exists. Should not be impacted by rename error.
{
std::shared_ptr<Logger> logger;
ASSERT_OK(CreateLoggerFromOptions(kTestDir, options, &logger));
ASSERT_TRUE(logger != nullptr);
}

// Now a LOG exists. Rename error should cause failure.
{
std::shared_ptr<Logger> logger;
ASSERT_NOK(CreateLoggerFromOptions(kTestDir, options, &logger));
ASSERT_TRUE(logger == nullptr);
}
}

} // namespace ROCKSDB_NAMESPACE

int main(int argc, char** argv) {
Expand Down

0 comments on commit a685a70

Please sign in to comment.