fsync directory after creating current file in NewDB()

Summary: One of our users reported current file corruption. The machine was rebooted during the time. This is the only think I can think of which could cause current file corruption. Just add this paranoid check.

Test Plan: make all check

Reviewers: haobo, igor

Reviewed By: haobo

CC: yhchiang, dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D18495
This commit is contained in:
sdong 2014-05-06 14:51:33 -07:00
parent 3a171dcb51
commit 9efbd85ac9
5 changed files with 14 additions and 9 deletions

View File

@ -487,7 +487,7 @@ Status DBImpl::NewDB() {
} }
if (s.ok()) { if (s.ok()) {
// Make "CURRENT" file that points to the new manifest file. // Make "CURRENT" file that points to the new manifest file.
s = SetCurrentFile(env_, dbname_, 1); s = SetCurrentFile(env_, dbname_, 1, db_directory_.get());
} else { } else {
env_->DeleteFile(manifest); env_->DeleteFile(manifest);
} }

View File

@ -226,7 +226,8 @@ bool ParseFileName(const std::string& fname,
} }
Status SetCurrentFile(Env* env, const std::string& dbname, Status SetCurrentFile(Env* env, const std::string& dbname,
uint64_t descriptor_number) { uint64_t descriptor_number,
Directory* directory_to_fsync) {
// Remove leading "dbname/" and add newline to manifest file name // Remove leading "dbname/" and add newline to manifest file name
std::string manifest = DescriptorFileName(dbname, descriptor_number); std::string manifest = DescriptorFileName(dbname, descriptor_number);
Slice contents = manifest; Slice contents = manifest;
@ -237,7 +238,11 @@ Status SetCurrentFile(Env* env, const std::string& dbname,
if (s.ok()) { if (s.ok()) {
s = env->RenameFile(tmp, CurrentFileName(dbname)); s = env->RenameFile(tmp, CurrentFileName(dbname));
} }
if (!s.ok()) { if (s.ok()) {
if (directory_to_fsync != nullptr) {
directory_to_fsync->Fsync();
}
} else {
env->DeleteFile(tmp); env->DeleteFile(tmp);
} }
return s; return s;

View File

@ -20,6 +20,7 @@
namespace rocksdb { namespace rocksdb {
class Env; class Env;
class Directory;
enum FileType { enum FileType {
kLogFile, kLogFile,
@ -100,7 +101,8 @@ extern bool ParseFileName(const std::string& filename,
// Make the CURRENT file point to the descriptor file with the // Make the CURRENT file point to the descriptor file with the
// specified number. // specified number.
extern Status SetCurrentFile(Env* env, const std::string& dbname, extern Status SetCurrentFile(Env* env, const std::string& dbname,
uint64_t descriptor_number); uint64_t descriptor_number,
Directory* directory_to_fsync);
// Make the IDENTITY file for the db // Make the IDENTITY file for the db
extern Status SetIdentityFile(Env* env, const std::string& dbname); extern Status SetIdentityFile(Env* env, const std::string& dbname);

View File

@ -363,7 +363,7 @@ class Repairer {
// Install new manifest // Install new manifest
status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1));
if (status.ok()) { if (status.ok()) {
status = SetCurrentFile(env_, dbname_, 1); status = SetCurrentFile(env_, dbname_, 1, nullptr);
} else { } else {
env_->DeleteFile(tmp); env_->DeleteFile(tmp);
} }

View File

@ -1731,7 +1731,8 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
// If we just created a new descriptor file, install it by writing a // If we just created a new descriptor file, install it by writing a
// new CURRENT file that points to it. // new CURRENT file that points to it.
if (s.ok() && new_descriptor_log) { if (s.ok() && new_descriptor_log) {
s = SetCurrentFile(env_, dbname_, pending_manifest_file_number_); s = SetCurrentFile(env_, dbname_, pending_manifest_file_number_,
db_directory);
if (s.ok() && pending_manifest_file_number_ > manifest_file_number_) { if (s.ok() && pending_manifest_file_number_ > manifest_file_number_) {
// delete old manifest file // delete old manifest file
Log(options_->info_log, Log(options_->info_log,
@ -1741,9 +1742,6 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
// of it later // of it later
env_->DeleteFile(DescriptorFileName(dbname_, manifest_file_number_)); env_->DeleteFile(DescriptorFileName(dbname_, manifest_file_number_));
} }
if (!options_->disableDataSync && db_directory != nullptr) {
db_directory->Fsync();
}
} }
if (s.ok()) { if (s.ok()) {