env: add ReuseWritableFile
Add an environment method to reuse an existing file. Provide a generic implementation that does a simple rename + open (writeable), and also a posix variant that is more careful about error handling (if we fail to open, do not rename, etc.). Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
parent
e1a09a7703
commit
1bcafb62f4
@ -139,6 +139,12 @@ class Env {
|
||||
unique_ptr<WritableFile>* result,
|
||||
const EnvOptions& options) = 0;
|
||||
|
||||
// Reuse an existing file by renaming it and opening it as writable.
|
||||
virtual Status ReuseWritableFile(const std::string& fname,
|
||||
const std::string& old_fname,
|
||||
unique_ptr<WritableFile>* result,
|
||||
const EnvOptions& options);
|
||||
|
||||
// Create an object that represents a directory. Will fail if directory
|
||||
// doesn't exist. If the directory exists, it will open the directory
|
||||
// and create a new Directory object.
|
||||
|
11
util/env.cc
11
util/env.cc
@ -27,6 +27,17 @@ uint64_t Env::GetThreadID() const {
|
||||
return hasher(std::this_thread::get_id());
|
||||
}
|
||||
|
||||
Status Env::ReuseWritableFile(const std::string& fname,
|
||||
const std::string& old_fname,
|
||||
unique_ptr<WritableFile>* result,
|
||||
const EnvOptions& options) {
|
||||
Status s = RenameFile(old_fname, fname);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
return NewWritableFile(fname, result, options);
|
||||
}
|
||||
|
||||
SequentialFile::~SequentialFile() {
|
||||
}
|
||||
|
||||
|
@ -933,6 +933,50 @@ class PosixEnv : public Env {
|
||||
return s;
|
||||
}
|
||||
|
||||
virtual Status ReuseWritableFile(const std::string& fname,
|
||||
const std::string& old_fname,
|
||||
unique_ptr<WritableFile>* result,
|
||||
const EnvOptions& options) override {
|
||||
result->reset();
|
||||
Status s;
|
||||
int fd = -1;
|
||||
do {
|
||||
IOSTATS_TIMER_GUARD(open_nanos);
|
||||
fd = open(old_fname.c_str(), O_RDWR, 0644);
|
||||
} while (fd < 0 && errno == EINTR);
|
||||
if (fd < 0) {
|
||||
s = IOError(fname, errno);
|
||||
} else {
|
||||
SetFD_CLOEXEC(fd, &options);
|
||||
// rename into place
|
||||
if (rename(old_fname.c_str(), fname.c_str()) != 0) {
|
||||
Status r = IOError(old_fname, errno);
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
||||
if (options.use_mmap_writes) {
|
||||
if (!checkedDiskForMmap_) {
|
||||
// this will be executed once in the program's lifetime.
|
||||
// do not use mmapWrite on non ext-3/xfs/tmpfs systems.
|
||||
if (!SupportsFastAllocate(fname)) {
|
||||
forceMmapOff = true;
|
||||
}
|
||||
checkedDiskForMmap_ = true;
|
||||
}
|
||||
}
|
||||
if (options.use_mmap_writes && !forceMmapOff) {
|
||||
result->reset(new PosixMmapFile(fname, fd, page_size_, options));
|
||||
} else {
|
||||
// disable mmap writes
|
||||
EnvOptions no_mmap_writes_options = options;
|
||||
no_mmap_writes_options.use_mmap_writes = false;
|
||||
|
||||
result->reset(new PosixWritableFile(fname, fd, no_mmap_writes_options));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
virtual Status NewDirectory(const std::string& name,
|
||||
unique_ptr<Directory>* result) override {
|
||||
result->reset();
|
||||
|
Loading…
Reference in New Issue
Block a user