From d50078163ed3abe18df047e78092407346957b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Spo=CC=88rri?= Date: Tue, 28 Mar 2023 17:27:52 +0200 Subject: [PATCH] MMAPFile: Support acquire/release of MMAP-buffer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal SpoĢˆrri --- src/libgeds/GEDSLocalFileHandle.h | 4 +- src/libgeds/LocalFile.cpp | 4 ++ src/libgeds/LocalFile.h | 2 +- src/libgeds/MMAPFile.cpp | 72 +++++++++++++++++++++++++------ src/libgeds/MMAPFile.h | 30 +++++++------ 5 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/libgeds/GEDSLocalFileHandle.h b/src/libgeds/GEDSLocalFileHandle.h index 1bc1c0fd..4c6b060e 100644 --- a/src/libgeds/GEDSLocalFileHandle.h +++ b/src/libgeds/GEDSLocalFileHandle.h @@ -7,5 +7,7 @@ #include "GEDSAbstractFileHandle.h" #include "LocalFile.h" +#include "MMAPFile.h" -using GEDSLocalFileHandle = GEDSAbstractFileHandle; +// using GEDSLocalFileHandle = GEDSAbstractFileHandle; +using GEDSLocalFileHandle = GEDSAbstractFileHandle; diff --git a/src/libgeds/LocalFile.cpp b/src/libgeds/LocalFile.cpp index 3ba2c50c..44b5c8ff 100644 --- a/src/libgeds/LocalFile.cpp +++ b/src/libgeds/LocalFile.cpp @@ -62,6 +62,10 @@ LocalFile::~LocalFile() { _fd = -1; } +void LocalFile::notifyUnused() { + // NOOP. +} + absl::StatusOr LocalFile::fileSize() const { CHECK_FILE_OPEN diff --git a/src/libgeds/LocalFile.h b/src/libgeds/LocalFile.h index a71615f1..b0870533 100644 --- a/src/libgeds/LocalFile.h +++ b/src/libgeds/LocalFile.h @@ -47,7 +47,7 @@ class LocalFile { [[nodiscard]] const std::string &path() const { return _path; } - void notifyUnused(){}; + void notifyUnused(); [[nodiscard]] size_t size() const { return _size; } diff --git a/src/libgeds/MMAPFile.cpp b/src/libgeds/MMAPFile.cpp index 31c9c846..5ef8fd6e 100644 --- a/src/libgeds/MMAPFile.cpp +++ b/src/libgeds/MMAPFile.cpp @@ -38,6 +38,28 @@ MMAPFile::MMAPFile(std::string pathArg, bool overwrite) : _path(std::move(pathAr } } +MMAPFile::~MMAPFile() { + auto lock = getWriteLock(); + release(); + if (_fd >= 0) { + // Truncate file to size. + int e = ftruncate64(_fd, _size); + if (e < 0) { + int err = errno; + std::string errorMessage = "Unable to ftruncate file " + _path + ": " + strerror(err); + LOG_ERROR(errorMessage); + } + + (void)::close(_fd); + _fd = -1; + + auto removeStatus = removeFile(_path); + if (!removeStatus.ok()) { + LOG_ERROR("Unable to delete ", _path, " reason: ", removeStatus.message()); + } + } +} + absl::Status MMAPFile::increaseMmap(size_t requestSize) { if (_fd < 0) { return absl::UnknownError("No valid file descriptor for " + _path); @@ -90,18 +112,29 @@ absl::StatusOr MMAPFile::readBytes(uint8_t *bytes, size_t position, size return 0; } + // Reopen the file if it has been unmapped. + auto status = reopen(); + if (!status.ok()) { + return status; + } + auto lock = getReadLock(); if (position >= _size) { return 0; } + length = std::min(length, _size - position); + if (length == 0) { + return 0; + } auto n = std::min(_size, position + length) - position; (void)std::memcpy(bytes, _mmapPtr + position, n); // return n; } -absl::StatusOr MMAPFile::rawPtr() const { - if (_mmapPtr == nullptr) { - return absl::UnknownError("Memory Mapped file is null."); +absl::StatusOr MMAPFile::rawPtr() { + auto status = reopen(); + if (!status.ok()) { + return status; } return _mmapPtr; } @@ -134,7 +167,7 @@ absl::Status MMAPFile::writeBytes(const uint8_t *bytes, size_t position, size_t auto newSize = position + length; // Check if the new file size is bigger, if yes, increase the file size. - if (newSize > size()) { + if (newSize > _size) { auto status = increaseMmap(newSize); if (!status.ok()) { return status; @@ -188,8 +221,7 @@ absl::StatusOr MMAPFile::write(std::istream &stream, size_t position, return length; } -MMAPFile::~MMAPFile() { - auto lock = getWriteLock(); +void MMAPFile::release() { if (_mmapPtr != 0) { int err = munmap(_mmapPtr, _mmapSize); if (err != 0) { @@ -199,15 +231,31 @@ MMAPFile::~MMAPFile() { _mmapPtr = nullptr; _mmapSize = 0; } - if (_fd >= 0) { - (void)::close(_fd); - _fd = -1; +} - auto removeStatus = removeFile(_path); - if (!removeStatus.ok()) { - LOG_ERROR("Unable to delete ", _path, " reason: ", removeStatus.message()); +absl::Status MMAPFile::reopen() { + if (_mmapPtr == nullptr) { + auto lock = getWriteLock(); + if (_mmapPtr != nullptr) { + return absl::OkStatus(); + } + size_t nPages = _size / MMAP_pageSize + (_size % MMAP_pageSize > 0 ? 1 : 0); + size_t mmapSize = nPages * MMAP_pageSize; + // fallocate, int mode, __off_t offset, __off_t len) + auto m = mmap(nullptr, mmapSize, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0); + if (m == MAP_FAILED) { // NOLINT + return absl::UnknownError("Failed to map file " + _path + " with requested size " + + std::to_string(_size) + "."); } + _mmapPtr = static_cast(m); + _mmapSize = mmapSize; } + return absl::OkStatus(); +} + +void MMAPFile::notifyUnused() { + auto lock = getWriteLock(); + release(); } } // namespace geds::filesystem diff --git a/src/libgeds/MMAPFile.h b/src/libgeds/MMAPFile.h index 36e4c0cb..15027ef6 100644 --- a/src/libgeds/MMAPFile.h +++ b/src/libgeds/MMAPFile.h @@ -3,12 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef GEDS_MMAP_FILE_H -#define GEDS_MMAP_FILE_H - -#include -#include +#pragma once +#include #include #include #include @@ -18,13 +15,14 @@ #include #include -namespace geds::filesystem { +#include +#include -class MMAPFile { - std::shared_mutex _mutex; - auto getReadLock() { return std::shared_lock(_mutex); } - auto getWriteLock() { return std::unique_lock(_mutex); } +#include "RWConcurrentObjectAdaptor.h" +namespace geds::filesystem { + +class MMAPFile : public utility::RWConcurrentObjectAdaptor { const std::string _path; int _fd{-1}; @@ -33,8 +31,13 @@ class MMAPFile { size_t _mmapSize{0}; uint8_t *_mmapPtr{nullptr}; + std::atomic _ioProcesses; + absl::Status increaseMmap(size_t requestSize); + absl::Status reopen(); + void release(); + public: MMAPFile() = delete; MMAPFile(MMAPFile &) = delete; @@ -43,10 +46,13 @@ class MMAPFile { MMAPFile(std::string path, bool overwrite = true); ~MMAPFile(); + void notifyUnused(); + [[nodiscard]] const std::string &path() const { return _path; } [[nodiscard]] size_t size() const { return _size; } - absl::StatusOr rawPtr() const; + + absl::StatusOr rawPtr(); absl::StatusOr rawFd() const; @@ -62,5 +68,3 @@ class MMAPFile { }; } // namespace geds::filesystem - -#endif