From 1bcafb62f4aa7c0b2b3786a958220411347f27b8 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 7 Oct 2015 22:11:09 -0400 Subject: [PATCH] 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 --- include/rocksdb/env.h | 6 ++++++ util/env.cc | 11 +++++++++++ util/env_posix.cc | 44 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/include/rocksdb/env.h b/include/rocksdb/env.h index 57c60f0c9..1dfd0f997 100644 --- a/include/rocksdb/env.h +++ b/include/rocksdb/env.h @@ -139,6 +139,12 @@ class Env { unique_ptr* 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* 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. diff --git a/util/env.cc b/util/env.cc index effa7f552..df45d9804 100644 --- a/util/env.cc +++ b/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* result, + const EnvOptions& options) { + Status s = RenameFile(old_fname, fname); + if (!s.ok()) { + return s; + } + return NewWritableFile(fname, result, options); +} + SequentialFile::~SequentialFile() { } diff --git a/util/env_posix.cc b/util/env_posix.cc index 3c264e1cf..fb4c41f35 100644 --- a/util/env_posix.cc +++ b/util/env_posix.cc @@ -933,6 +933,50 @@ class PosixEnv : public Env { return s; } + virtual Status ReuseWritableFile(const std::string& fname, + const std::string& old_fname, + unique_ptr* 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* result) override { result->reset();