diff --git a/include/leveldb/env.h b/include/leveldb/env.h index 7d70ef8f5..352ad7dba 100644 --- a/include/leveldb/env.h +++ b/include/leveldb/env.h @@ -360,6 +360,16 @@ class WritableFile { return Status::OK(); } + // Sync a file range with disk. + // offset is the starting byte of the file range to be synchronized. + // nbytes specifies the length of the range to be synchronized. + // This asks the OS to initiate flushing the cached data to disk, + // without waiting for completion. + // Default implementation does nothing. + virtual Status RangeSync(off64_t offset, off64_t nbytes) { + return Status::OK(); + } + private: size_t last_preallocated_block_; size_t preallocation_block_size_; diff --git a/util/env_posix.cc b/util/env_posix.cc index 1388566c5..1745165c6 100644 --- a/util/env_posix.cc +++ b/util/env_posix.cc @@ -22,6 +22,7 @@ #include #if defined(OS_LINUX) #include +#include #endif #if defined(LEVELDB_PLATFORM_ANDROID) #include @@ -503,6 +504,7 @@ class PosixWritableFile : public WritableFile { uint64_t filesize_; bool pending_sync_; bool pending_fsync_; + uint64_t last_sync_size_; public: PosixWritableFile(const std::string& fname, int fd, size_t capacity, @@ -514,7 +516,8 @@ class PosixWritableFile : public WritableFile { buf_(new char[capacity]), filesize_(0), pending_sync_(false), - pending_fsync_(false) { + pending_fsync_(false), + last_sync_size_(0) { assert(!options.use_mmap_writes); } @@ -601,6 +604,13 @@ class PosixWritableFile : public WritableFile { src += done; } cursize_ = 0; + + // sync OS cache to disk for every 2MB written + if (filesize_ - last_sync_size_ >= 2 * 1024 * 1024) { + RangeSync(last_sync_size_, filesize_ - last_sync_size_); + last_sync_size_ = filesize_; + } + return Status::OK(); } @@ -638,6 +648,14 @@ class PosixWritableFile : public WritableFile { return IOError(filename_, errno); } } + + virtual Status RangeSync(off64_t offset, off64_t nbytes) { + if (sync_file_range(fd_, offset, nbytes, SYNC_FILE_RANGE_WRITE) == 0) { + return Status::OK(); + } else { + return IOError(filename_, errno); + } + } #endif };