diff --git a/include/rocksdb/env.h b/include/rocksdb/env.h index 57c60f0c9ac3209be493194ba01ae007f6103144..1dfd0f997b3d02fff4f325e65bd4c555943feb0f 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 effa7f55217aec15e07663a29f8019bde29718e4..df45d9804d6a0a0878925ade7e4464d8c4595e1e 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 3c264e1cf0002451f5d9bcb26d23525ec8965692..fb4c41f35e1e57a0d14e357ff73bad94e9a0d002 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();