Skip to content

Commit

Permalink
MMAPFile: Support acquire/release of MMAP-buffer.
Browse files Browse the repository at this point in the history
Signed-off-by: Pascal Spörri <[email protected]>
  • Loading branch information
pspoerri committed Mar 28, 2023
1 parent 6db219f commit d500781
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 27 deletions.
4 changes: 3 additions & 1 deletion src/libgeds/GEDSLocalFileHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@

#include "GEDSAbstractFileHandle.h"
#include "LocalFile.h"
#include "MMAPFile.h"

using GEDSLocalFileHandle = GEDSAbstractFileHandle<geds::filesystem::LocalFile>;
// using GEDSLocalFileHandle = GEDSAbstractFileHandle<geds::filesystem::LocalFile>;
using GEDSLocalFileHandle = GEDSAbstractFileHandle<geds::filesystem::MMAPFile>;
4 changes: 4 additions & 0 deletions src/libgeds/LocalFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ LocalFile::~LocalFile() {
_fd = -1;
}

void LocalFile::notifyUnused() {
// NOOP.
}

absl::StatusOr<size_t> LocalFile::fileSize() const {
CHECK_FILE_OPEN

Expand Down
2 changes: 1 addition & 1 deletion src/libgeds/LocalFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
72 changes: 60 additions & 12 deletions src/libgeds/MMAPFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -90,18 +112,29 @@ absl::StatusOr<size_t> 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<const uint8_t *> MMAPFile::rawPtr() const {
if (_mmapPtr == nullptr) {
return absl::UnknownError("Memory Mapped file is null.");
absl::StatusOr<uint8_t *> MMAPFile::rawPtr() {
auto status = reopen();
if (!status.ok()) {
return status;
}
return _mmapPtr;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -188,8 +221,7 @@ absl::StatusOr<size_t> 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) {
Expand All @@ -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<uint8_t *>(m);
_mmapSize = mmapSize;
}
return absl::OkStatus();
}

void MMAPFile::notifyUnused() {
auto lock = getWriteLock();
release();
}

} // namespace geds::filesystem
30 changes: 17 additions & 13 deletions src/libgeds/MMAPFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef GEDS_MMAP_FILE_H
#define GEDS_MMAP_FILE_H

#include <absl/status/status.h>
#include <absl/status/statusor.h>
#pragma once

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <istream>
Expand All @@ -18,13 +15,14 @@
#include <string>
#include <vector>

namespace geds::filesystem {
#include <absl/status/status.h>
#include <absl/status/statusor.h>

class MMAPFile {
std::shared_mutex _mutex;
auto getReadLock() { return std::shared_lock<std::shared_mutex>(_mutex); }
auto getWriteLock() { return std::unique_lock<std::shared_mutex>(_mutex); }
#include "RWConcurrentObjectAdaptor.h"

namespace geds::filesystem {

class MMAPFile : public utility::RWConcurrentObjectAdaptor {
const std::string _path;

int _fd{-1};
Expand All @@ -33,8 +31,13 @@ class MMAPFile {
size_t _mmapSize{0};
uint8_t *_mmapPtr{nullptr};

std::atomic<size_t> _ioProcesses;

absl::Status increaseMmap(size_t requestSize);

absl::Status reopen();
void release();

public:
MMAPFile() = delete;
MMAPFile(MMAPFile &) = delete;
Expand All @@ -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<const uint8_t *> rawPtr() const;

absl::StatusOr<uint8_t *> rawPtr();

absl::StatusOr<int> rawFd() const;

Expand All @@ -62,5 +68,3 @@ class MMAPFile {
};

} // namespace geds::filesystem

#endif

0 comments on commit d500781

Please sign in to comment.