From 47a263d18efb80aa6442fddf9dee66259f70b73f Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Mon, 31 Mar 2025 15:46:03 +0200 Subject: [PATCH] feat: add `block_cache_byte_buffer_factory` --- cmake/libdwarfs.cmake | 1 + .../reader/block_cache_byte_buffer_factory.h | 33 +++++ include/dwarfs/vector_byte_buffer_factory.h | 1 - .../block_cache_byte_buffer_factory.cpp | 139 ++++++++++++++++++ src/reader/internal/block_cache.cpp | 4 +- src/reader/internal/cached_block.cpp | 1 + src/vector_byte_buffer_factory.cpp | 1 + 7 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 include/dwarfs/reader/block_cache_byte_buffer_factory.h create mode 100644 src/reader/block_cache_byte_buffer_factory.cpp diff --git a/cmake/libdwarfs.cmake b/cmake/libdwarfs.cmake index e84b838d..786902b9 100644 --- a/cmake/libdwarfs.cmake +++ b/cmake/libdwarfs.cmake @@ -75,6 +75,7 @@ add_library( add_library( dwarfs_reader + src/reader/block_cache_byte_buffer_factory.cpp src/reader/block_cache_options.cpp src/reader/block_range.cpp src/reader/filesystem_options.cpp diff --git a/include/dwarfs/reader/block_cache_byte_buffer_factory.h b/include/dwarfs/reader/block_cache_byte_buffer_factory.h new file mode 100644 index 00000000..c02c53f0 --- /dev/null +++ b/include/dwarfs/reader/block_cache_byte_buffer_factory.h @@ -0,0 +1,33 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#pragma once + +#include + +namespace dwarfs::reader { + +class block_cache_byte_buffer_factory { + public: + static byte_buffer_factory create(); +}; + +} // namespace dwarfs::reader diff --git a/include/dwarfs/vector_byte_buffer_factory.h b/include/dwarfs/vector_byte_buffer_factory.h index 22a56cba..d75b0988 100644 --- a/include/dwarfs/vector_byte_buffer_factory.h +++ b/include/dwarfs/vector_byte_buffer_factory.h @@ -22,7 +22,6 @@ #pragma once #include -#include namespace dwarfs { diff --git a/src/reader/block_cache_byte_buffer_factory.cpp b/src/reader/block_cache_byte_buffer_factory.cpp new file mode 100644 index 00000000..474601bf --- /dev/null +++ b/src/reader/block_cache_byte_buffer_factory.cpp @@ -0,0 +1,139 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include + +namespace dwarfs::reader { + +namespace { + +#ifndef _WIN32 +class mmap_file { + public: + mmap_file(size_t size) + : data_{::mmap(nullptr, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)} + , size_{size} { + if (data_ == MAP_FAILED) { + throw std::runtime_error("mmap failed"); + } + } + + size_t size() const { return size_; } + + uint8_t* data() { return static_cast(data_); } + uint8_t const* data() const { return static_cast(data_); } + + ~mmap_file() { + auto rv [[maybe_unused]] = ::munmap(data_, size_); + assert(rv == 0); + } + + private: + void* data_; + size_t size_; +}; + +class mmap_byte_buffer_impl : public mutable_byte_buffer_interface { + public: + explicit mmap_byte_buffer_impl(size_t size) + : data_{size} {} + + size_t size() const override { return size_; } + + size_t capacity() const override { return data_.size(); } + + uint8_t const* data() const override { return data_.data(); } + + uint8_t* mutable_data() override { return data_.data(); } + + std::span span() const override { + return {data_.data(), size_}; + } + + std::span mutable_span() override { return {data_.data(), size_}; } + + void clear() override { frozen_error("clear"); } + + void reserve(size_t size) override { + if (size > data_.size()) { + frozen_error("reserve"); + } + } + + void resize(size_t size) override { + if (size > data_.size()) { + frozen_error("resize beyond capacity"); + } + size_ = size; + } + + void shrink_to_fit() override { frozen_error("shrink_to_fit"); } + + void freeze_location() override { + // always frozen + } + + std::vector& raw_vector() override { + throw std::runtime_error( + "operation not allowed on mmap buffer: raw_vector"); + } + + private: + void frozen_error(std::string_view what) const { + throw std::runtime_error("operation not allowed on mmap buffer: " + + std::string{what}); + } + + mmap_file data_; + size_t size_{0}; +}; +#endif + +class block_cache_byte_buffer_factory_impl + : public byte_buffer_factory_interface { + public: + mutable_byte_buffer create_mutable_fixed_reserve(size_t size) const override { +#ifdef _WIN32 + return vector_byte_buffer::create_reserve(size); +#else + return mutable_byte_buffer{std::make_shared(size)}; +#endif + } +}; + +} // namespace + +byte_buffer_factory block_cache_byte_buffer_factory::create() { + return byte_buffer_factory{ + std::make_shared()}; +} + +} // namespace dwarfs::reader diff --git a/src/reader/internal/block_cache.cpp b/src/reader/internal/block_cache.cpp index 14dc6c8f..4e50e387 100644 --- a/src/reader/internal/block_cache.cpp +++ b/src/reader/internal/block_cache.cpp @@ -44,11 +44,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -224,7 +224,7 @@ class block_cache_ final : public block_cache::impl { [[maybe_unused]]) : cache_(0) , mm_(std::move(mm)) - , buffer_factory_{vector_byte_buffer_factory::create()} + , buffer_factory_{block_cache_byte_buffer_factory::create()} , LOG_PROXY_INIT(lgr) // clang-format off PERFMON_CLS_PROXY_INIT(perfmon, "block_cache") diff --git a/src/reader/internal/cached_block.cpp b/src/reader/internal/cached_block.cpp index 81ed088d..fab16ad0 100644 --- a/src/reader/internal/cached_block.cpp +++ b/src/reader/internal/cached_block.cpp @@ -19,6 +19,7 @@ * along with dwarfs. If not, see . */ +#include #include #ifndef _WIN32 diff --git a/src/vector_byte_buffer_factory.cpp b/src/vector_byte_buffer_factory.cpp index 876e35a4..5369ed25 100644 --- a/src/vector_byte_buffer_factory.cpp +++ b/src/vector_byte_buffer_factory.cpp @@ -19,6 +19,7 @@ * along with dwarfs. If not, see . */ +#include #include namespace dwarfs {