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,
|
unique_ptr<WritableFile>* result,
|
||||||
const EnvOptions& options) = 0;
|
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
|
// Create an object that represents a directory. Will fail if directory
|
||||||
// doesn't exist. If the directory exists, it will open the directory
|
// doesn't exist. If the directory exists, it will open the directory
|
||||||
// and create a new Directory object.
|
// 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());
|
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() {
|
SequentialFile::~SequentialFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,6 +933,50 @@ class PosixEnv : public Env {
|
|||||||
return s;
|
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,
|
virtual Status NewDirectory(const std::string& name,
|
||||||
unique_ptr<Directory>* result) override {
|
unique_ptr<Directory>* result) override {
|
||||||
result->reset();
|
result->reset();
|
||||||
|
Loading…
Reference in New Issue
Block a user