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
main
sdong 11 years ago
parent 3a171dcb51
commit 9efbd85ac9
  1. 2
      db/db_impl.cc
  2. 9
      db/filename.cc
  3. 4
      db/filename.h
  4. 2
      db/repair.cc
  5. 6
      db/version_set.cc

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

@ -226,7 +226,8 @@ bool ParseFileName(const std::string& fname,
}
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
std::string manifest = DescriptorFileName(dbname, descriptor_number);
Slice contents = manifest;
@ -237,7 +238,11 @@ Status SetCurrentFile(Env* env, const std::string& dbname,
if (s.ok()) {
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);
}
return s;

@ -20,6 +20,7 @@
namespace rocksdb {
class Env;
class Directory;
enum FileType {
kLogFile,
@ -100,7 +101,8 @@ extern bool ParseFileName(const std::string& filename,
// Make the CURRENT file point to the descriptor file with the
// specified number.
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
extern Status SetIdentityFile(Env* env, const std::string& dbname);

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

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

Loading…
Cancel
Save