mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
write dirstate file atomically
Summary: Write the dirstate data using the new folly::writeFileAtomic() function. This ensures that the dirstate file will always contain full, valid contents, even if we crash or run out of disk space partway through writing out the data. This diff also includes a couple other minor tweaks: - Update Dirstate to store the DirstatePersistence object directly inline, rather than allocating it separately on the heap. - Update the DirstatePersistenceTest code to prefix temporary directories with "eden_test". This just makes it easier to tell if the tests fail to clean up after themselves for any reason. Reviewed By: bolinfest Differential Revision: D4254027 fbshipit-source-id: 6b6601b65aeacdee998a6c4260e972d5fb2426ac
This commit is contained in:
parent
aaa3332644
commit
87c2d46ce3
@ -8,10 +8,12 @@
|
||||
*
|
||||
*/
|
||||
#include "Dirstate.h"
|
||||
|
||||
#include <folly/Format.h>
|
||||
#include <folly/io/Cursor.h>
|
||||
#include <folly/io/IOBuf.h>
|
||||
#include "eden/fs/config/ClientConfig.h"
|
||||
#include "eden/fs/inodes/DirstatePersistence.h"
|
||||
#include "eden/fs/inodes/EdenMount.h"
|
||||
#include "eden/fs/inodes/EdenMounts.h"
|
||||
#include "eden/fs/inodes/FileInode.h"
|
||||
@ -123,10 +125,10 @@ void processRemovedFile(
|
||||
|
||||
Dirstate::Dirstate(EdenMount* mount)
|
||||
: mountPoint_(mount->getMountPoint()),
|
||||
objectStore_(mount->getObjectStore()) {
|
||||
auto dirstateStoragePath = mount->getConfig()->getDirstateStoragePath();
|
||||
persistence_ = std::make_unique<DirstatePersistence>(dirstateStoragePath);
|
||||
*(userDirectives_.wlock()) = persistence_->load();
|
||||
objectStore_(mount->getObjectStore()),
|
||||
persistence_(mount->getConfig()->getDirstateStoragePath()) {
|
||||
auto loadedData = persistence_.load();
|
||||
userDirectives_.wlock()->swap(loadedData);
|
||||
}
|
||||
|
||||
Dirstate::~Dirstate() {}
|
||||
@ -449,12 +451,12 @@ void Dirstate::add(RelativePathPiece path) {
|
||||
break;
|
||||
case overlay::UserStatusDirective::Remove:
|
||||
userDirectives->erase(path.copy());
|
||||
persistence_->save(*userDirectives);
|
||||
persistence_.save(*userDirectives);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
(*userDirectives)[path.copy()] = overlay::UserStatusDirective::Add;
|
||||
persistence_->save(*userDirectives);
|
||||
persistence_.save(*userDirectives);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -593,7 +595,7 @@ void Dirstate::remove(RelativePathPiece path, bool force) {
|
||||
}
|
||||
}
|
||||
(*userDirectives)[path.copy()] = overlay::UserStatusDirective::Remove;
|
||||
persistence_->save(*userDirectives);
|
||||
persistence_.save(*userDirectives);
|
||||
} else {
|
||||
switch (result->second) {
|
||||
case overlay::UserStatusDirective::Remove:
|
||||
@ -607,7 +609,7 @@ void Dirstate::remove(RelativePathPiece path, bool force) {
|
||||
path.stringPiece()));
|
||||
} else {
|
||||
userDirectives->erase(path.copy());
|
||||
persistence_->save(*userDirectives);
|
||||
persistence_.save(*userDirectives);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ class Dirstate {
|
||||
|
||||
fusell::MountPoint* mountPoint_;
|
||||
ObjectStore* objectStore_;
|
||||
std::unique_ptr<DirstatePersistence> persistence_;
|
||||
DirstatePersistence persistence_;
|
||||
/**
|
||||
* Manifest of files in the working copy whose status is not CLEAN. These are
|
||||
* also referred to as "nonnormal" files.
|
||||
|
@ -8,6 +8,7 @@
|
||||
*
|
||||
*/
|
||||
#include "DirstatePersistence.h"
|
||||
|
||||
#include <folly/FileUtil.h>
|
||||
#include <thrift/lib/cpp2/protocol/Serializer.h>
|
||||
|
||||
@ -26,12 +27,8 @@ void DirstatePersistence::save(
|
||||
}
|
||||
dirstateData.directives = directives;
|
||||
auto serializedData = CompactSerializer::serialize<std::string>(dirstateData);
|
||||
auto wrote = folly::writeFile(serializedData, storageFile_.c_str());
|
||||
|
||||
if (!wrote) {
|
||||
throw std::runtime_error(folly::to<std::string>(
|
||||
"Failed to persist Dirstate to file ", storageFile_));
|
||||
}
|
||||
folly::writeFileAtomic(storageFile_.stringPiece(), serializedData, 0644);
|
||||
}
|
||||
|
||||
std::unordered_map<RelativePath, overlay::UserStatusDirective>
|
||||
|
@ -19,7 +19,7 @@ using apache::thrift::CompactSerializer;
|
||||
using folly::test::TemporaryFile;
|
||||
|
||||
TEST(DirstatePersistence, saveAndReadDirectivesBackOut) {
|
||||
TemporaryFile storageFile;
|
||||
TemporaryFile storageFile("eden_test");
|
||||
|
||||
AbsolutePath storageFilePath(storageFile.path().c_str());
|
||||
DirstatePersistence persistence(storageFilePath);
|
||||
@ -35,7 +35,7 @@ TEST(DirstatePersistence, saveAndReadDirectivesBackOut) {
|
||||
}
|
||||
|
||||
TEST(DirstatePersistence, loadFromFileWithWellFormattedData) {
|
||||
TemporaryFile storageFile;
|
||||
TemporaryFile storageFile("eden_test");
|
||||
|
||||
overlay::DirstateData dirstateData;
|
||||
dirstateData.directives = {
|
||||
@ -59,7 +59,7 @@ TEST(DirstatePersistence, loadFromFileWithWellFormattedData) {
|
||||
TEST(DirstatePersistence, attemptLoadFromNonExistentFile) {
|
||||
AbsolutePath storageFilePath;
|
||||
{
|
||||
TemporaryFile storageFile;
|
||||
TemporaryFile storageFile("eden_test");
|
||||
storageFilePath = AbsolutePath(storageFile.path().c_str());
|
||||
}
|
||||
DirstatePersistence persistence(storageFilePath);
|
||||
|
Loading…
Reference in New Issue
Block a user