diff --git a/.clang-format b/.clang-format index c7e9c50..6a6c06f 100644 --- a/.clang-format +++ b/.clang-format @@ -10,11 +10,9 @@ AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: false AllowShortLambdasOnASingleLine: false AllowShortLoopsOnASingleLine: false -AllowAllConstructorInitializersOnNextLine: false BreakBeforeBraces: Custom DerivePointerAlignment: false FixNamespaceComments: true -IndentCaseLabels: false IndentPPDirectives: None IndentWidth: 2 PointerAlignment: Left diff --git a/conanfile.py b/conanfile.py index 919851c..0b6c173 100644 --- a/conanfile.py +++ b/conanfile.py @@ -69,7 +69,7 @@ def configure(self): def requirements(self): - self.requires("batteries/0.52.1", **VISIBLE) + self.requires("batteries/0.52.4", **VISIBLE) self.requires("boost/1.83.0", **VISIBLE) self.requires("cli11/2.3.2", **VISIBLE) self.requires("glog/0.6.0", **VISIBLE) diff --git a/src/llfs/basic_log_storage_driver.hpp b/src/llfs/basic_log_storage_driver.hpp index 024a74b..b2980be 100644 --- a/src/llfs/basic_log_storage_driver.hpp +++ b/src/llfs/basic_log_storage_driver.hpp @@ -43,17 +43,17 @@ class BasicLogStorageDriver // Status set_trim_pos(slot_offset_type trim_pos) { - return impl_.set_trim_pos(trim_pos); + return this->impl_.set_trim_pos(trim_pos); } slot_offset_type get_trim_pos() const { - return impl_.get_trim_pos(); + return this->impl_.get_trim_pos(); } StatusOr await_trim_pos(slot_offset_type trim_pos) { - return impl_.await_trim_pos(trim_pos); + return this->impl_.await_trim_pos(trim_pos); } //---- @@ -63,41 +63,51 @@ class BasicLogStorageDriver slot_offset_type get_flush_pos() const { - return impl_.get_flush_pos(); + return this->impl_.get_flush_pos(); } StatusOr await_flush_pos(slot_offset_type flush_pos) { - return impl_.await_flush_pos(flush_pos); + return this->impl_.await_flush_pos(flush_pos); } //---- Status set_commit_pos(slot_offset_type commit_pos) { - return impl_.set_commit_pos(commit_pos); + return this->impl_.set_commit_pos(commit_pos); } slot_offset_type get_commit_pos() const { - return impl_.get_commit_pos(); + return this->impl_.get_commit_pos(); } StatusOr await_commit_pos(slot_offset_type commit_pos) { - return impl_.await_commit_pos(commit_pos); + return this->impl_.await_commit_pos(commit_pos); } //---- Status open() { - return impl_.open(); + return this->impl_.open(); } Status close() { - return impl_.close(); + return this->impl_.close(); + } + + void halt() + { + this->impl_.halt(); + } + + void join() + { + this->impl_.join(); } // //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - diff --git a/src/llfs/basic_ring_buffer_log_device.hpp b/src/llfs/basic_ring_buffer_log_device.hpp index f2420d4..308deed 100644 --- a/src/llfs/basic_ring_buffer_log_device.hpp +++ b/src/llfs/basic_ring_buffer_log_device.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace llfs { @@ -62,6 +63,16 @@ class BasicRingBufferLogDevice Status close() override; + void halt() override + { + this->driver_.halt(); + } + + void join() override + { + this->driver_.join(); + } + Status sync(LogReadMode mode, SlotUpperBoundAt event) override; driver_type& driver() @@ -222,8 +233,6 @@ class BasicRingBufferLogDevice::WriterImpl : public LogDevice::Writer StatusOr prepare(usize byte_count, usize head_room) override { - BATT_CHECK(!this->prepared_offset_); - if (this->device_->closed_.load()) { return ::llfs::make_status(StatusCode::kPrepareFailedLogClosed); } diff --git a/src/llfs/data_reader.hpp b/src/llfs/data_reader.hpp index 18049ae..e9ae482 100644 --- a/src/llfs/data_reader.hpp +++ b/src/llfs/data_reader.hpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -98,6 +99,22 @@ class DataReader at_end_ = false; } + /** \brief Tries to consume a prefix of the remaining input that exactly matches `token`. + * + * \return true iff the unread data begins with token and this prefix is successfully consumed. + */ + bool read_token(const batt::Slice& token) noexcept + { + if (this->bytes_available() < token.size()) { + return false; + } + if (std::memcmp(this->unread_.begin(), token.begin(), token.size()) != 0) { + return false; + } + this->unread_.advance_begin(token.size()); + return true; + } + template [[nodiscard]] const T* read_record(batt::StaticType = {}) { @@ -240,6 +257,13 @@ class DataReader return ConstBuffer{this->unread_.begin(), this->unread_.size()}; } + /** \brief Returns a pointer to the start of unread data. + */ + const u8* unread_begin() const + { + return this->unread_.begin(); + } + private: bool at_end_ = false; ConstBuffer buffer_; diff --git a/src/llfs/file_log_driver.cpp b/src/llfs/file_log_driver.cpp index 337e90e..16b9589 100644 --- a/src/llfs/file_log_driver.cpp +++ b/src/llfs/file_log_driver.cpp @@ -341,9 +341,24 @@ StatusOr FileLogDriver::await_commit_pos(slot_offset_type min_ //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - // Status FileLogDriver::close() +{ + this->halt(); + this->join(); + + return OkStatus(); +} + +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +void FileLogDriver::halt() { this->shared_state_.halt(); +} +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +void FileLogDriver::join() +{ if (this->trim_task_) { this->trim_task_->join(); this->trim_task_ = None; @@ -352,8 +367,6 @@ Status FileLogDriver::close() this->flush_task_->join(); this->flush_task_ = None; } - - return OkStatus(); } //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - diff --git a/src/llfs/file_log_driver.hpp b/src/llfs/file_log_driver.hpp index f266896..a5ce821 100644 --- a/src/llfs/file_log_driver.hpp +++ b/src/llfs/file_log_driver.hpp @@ -189,6 +189,10 @@ class FileLogDriver Status close(); + void halt(); + + void join(); + private: // See // diff --git a/src/llfs/ioring_file.cpp b/src/llfs/ioring_file.cpp index 04562d5..16a1c50 100644 --- a/src/llfs/ioring_file.cpp +++ b/src/llfs/ioring_file.cpp @@ -19,13 +19,15 @@ namespace llfs { //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - // -IoRing::File::File(const IoRing& io_ring, int fd) noexcept : io_ring_{&io_ring}, fd_{fd} +IoRing::File::File(const IoRing& io_ring, int fd) noexcept + : io_ring_impl_{io_ring.impl_.get()} + , fd_{fd} { } //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - // -IoRing::File::File(File&& that) noexcept : io_ring_{that.io_ring_}, fd_{that.fd_} +IoRing::File::File(File&& that) noexcept : io_ring_impl_{that.io_ring_impl_}, fd_{that.fd_} { that.fd_ = -1; that.registered_fd_ = -1; @@ -37,7 +39,7 @@ auto IoRing::File::operator=(File&& that) noexcept -> File& { File copy{std::move(that)}; - std::swap(this->io_ring_, copy.io_ring_); + std::swap(this->io_ring_impl_, copy.io_ring_impl_); std::swap(this->fd_, copy.fd_); std::swap(this->registered_fd_, copy.registered_fd_); @@ -155,7 +157,7 @@ Status IoRing::File::register_fd() return OkStatus(); } - StatusOr rfd = this->io_ring_->register_fd(this->fd_); + StatusOr rfd = this->io_ring_impl_->register_fd(this->fd_); if (!rfd.ok()) { LLFS_LOG_ERROR() << "register_fd failed! " << BATT_INSPECT(rfd.status()); } @@ -174,7 +176,7 @@ Status IoRing::File::unregister_fd() return OkStatus(); } - Status status = this->io_ring_->unregister_fd(this->registered_fd_); + Status status = this->io_ring_impl_->unregister_fd(this->registered_fd_); BATT_REQUIRE_OK(status); this->registered_fd_ = -1; diff --git a/src/llfs/ioring_file.hpp b/src/llfs/ioring_file.hpp index f15a9e5..8fe9605 100644 --- a/src/llfs/ioring_file.hpp +++ b/src/llfs/ioring_file.hpp @@ -47,9 +47,9 @@ class IoRing::File ~File() noexcept; - const IoRing& get_io_ring() const + IoRing::Impl* get_io_ring_impl() const { - return *this->io_ring_; + return this->io_ring_impl_; } // Returns the OS-native file descriptor currently owned by this object. Returns -1 if no file is @@ -158,7 +158,7 @@ class IoRing::File } private: - const IoRing* io_ring_; + IoRing::Impl* io_ring_impl_ = nullptr; int fd_ = -1; int registered_fd_ = -1; bool raw_io_ = true; @@ -173,16 +173,16 @@ inline void IoRing::File::async_read_some(i64 offset, MutableBufferSequence&& bu Handler&& handler) { LLFS_DVLOG(1) << "async_read_some(mulitple buffers)"; - this->io_ring_->submit(BATT_FORWARD(buffers), BATT_FORWARD(handler), - [offset, this](struct io_uring_sqe* sqe, auto& op) { - if (this->registered_fd_ == -1) { - io_uring_prep_readv(sqe, this->fd_, op.iov_, op.iov_count_, offset); - } else { - io_uring_prep_readv(sqe, this->registered_fd_, op.iov_, op.iov_count_, - offset); - sqe->flags |= IOSQE_FIXED_FILE; - } - }); + this->io_ring_impl_->submit( + BATT_FORWARD(buffers), BATT_FORWARD(handler), + [offset, this](struct io_uring_sqe* sqe, auto& op) { + if (this->registered_fd_ == -1) { + io_uring_prep_readv(sqe, this->fd_, op.iov_, op.iov_count_, offset); + } else { + io_uring_prep_readv(sqe, this->registered_fd_, op.iov_, op.iov_count_, offset); + sqe->flags |= IOSQE_FIXED_FILE; + } + }); } //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - @@ -194,7 +194,7 @@ inline void IoRing::File::async_read_some(i64 offset, const MutableBuffer& buffe static const std::vector empty; LLFS_DVLOG(1) << "async_read_some(single buffer)"; - this->io_ring_->submit( + this->io_ring_impl_->submit( empty, BATT_FORWARD(handler), [&buffer, offset, this](struct io_uring_sqe* sqe, auto& /*op*/) { if (this->registered_fd_ == -1) { @@ -217,7 +217,7 @@ inline void IoRing::File::async_read_some_fixed(i64 offset, const MutableBuffer& static const std::vector empty; LLFS_DVLOG(1) << "async_read_some(single buffer)"; - this->io_ring_->submit( + this->io_ring_impl_->submit( empty, BATT_FORWARD(handler), [&buffer, offset, buf_index, this](struct io_uring_sqe* sqe, auto& /*op*/) { if (this->registered_fd_ == -1) { @@ -238,16 +238,16 @@ template inline void IoRing::File::async_write_some(i64 offset, ConstBufferSequence&& buffers, Handler&& handler) { - this->io_ring_->submit(BATT_FORWARD(buffers), BATT_FORWARD(handler), - [offset, this](struct io_uring_sqe* sqe, auto& op) { - if (this->registered_fd_ == -1) { - io_uring_prep_writev(sqe, this->fd_, op.iov_, op.iov_count_, offset); - } else { - io_uring_prep_writev(sqe, this->registered_fd_, op.iov_, op.iov_count_, - offset); - sqe->flags |= IOSQE_FIXED_FILE; - } - }); + this->io_ring_impl_->submit( + BATT_FORWARD(buffers), BATT_FORWARD(handler), + [offset, this](struct io_uring_sqe* sqe, auto& op) { + if (this->registered_fd_ == -1) { + io_uring_prep_writev(sqe, this->fd_, op.iov_, op.iov_count_, offset); + } else { + io_uring_prep_writev(sqe, this->registered_fd_, op.iov_, op.iov_count_, offset); + sqe->flags |= IOSQE_FIXED_FILE; + } + }); } //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - @@ -257,7 +257,7 @@ inline void IoRing::File::async_write_some(i64 offset, const ConstBuffer& buffer { static const std::vector empty; - this->io_ring_->submit( + this->io_ring_impl_->submit( empty, BATT_FORWARD(handler), [&buffer, offset, this](struct io_uring_sqe* sqe, auto& /*op*/) { if (this->registered_fd_ == -1) { @@ -277,7 +277,7 @@ inline void IoRing::File::async_write_some_fixed(i64 offset, const ConstBuffer& { static const std::vector empty; - this->io_ring_->submit( + this->io_ring_impl_->submit( empty, BATT_FORWARD(handler), [&buffer, buf_index, offset, this](struct io_uring_sqe* sqe, auto& /*op*/) { if (this->registered_fd_ == -1) { diff --git a/src/llfs/ioring_log_config.cpp b/src/llfs/ioring_log_config.cpp index 4378f49..a7d8328 100644 --- a/src/llfs/ioring_log_config.cpp +++ b/src/llfs/ioring_log_config.cpp @@ -11,6 +11,7 @@ #ifndef LLFS_DISABLE_IO_URING +#include #include namespace llfs { @@ -28,6 +29,26 @@ namespace llfs { }; } +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +/*static*/ IoRingLogConfig IoRingLogConfig::from_logical_size(u64 logical_size, + Optional opt_block_size, + Optional opt_physical_offset) +{ + const usize block_size = opt_block_size.value_or(IoRingLogConfig::kDefaultBlockSize); + const i32 block_size_log2 = batt::log2_ceil(block_size); + + BATT_CHECK_GE(block_size_log2, kLogPageSizeLog2); + + return IoRingLogConfig{ + .logical_size = logical_size, + .physical_offset = opt_physical_offset.value_or(0), + .physical_size = + LogBlockCalculator::disk_size_required_for_log_size(logical_size, block_size), + .pages_per_block_log2 = block_size_log2 - kLogPageSizeLog2, + }; +} + } // namespace llfs #endif // LLFS_DISABLE_IO_URING diff --git a/src/llfs/ioring_log_config.hpp b/src/llfs/ioring_log_config.hpp index 69ce6f8..fe3c49f 100644 --- a/src/llfs/ioring_log_config.hpp +++ b/src/llfs/ioring_log_config.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace llfs { @@ -44,7 +45,8 @@ struct IoRingLogConfig { u64 physical_size; // Specifies the size of a "flush block," the size of a single write operation while flushing, - // in number of 4kb pages, log2. For example: + // in number of kLogAtomicWriteSize (default=512; see llfs/config.hpp) byte pages, log2. For + // example: // // | flush_block_pages_log2 | flush write buffer size | // |--------------------------|---------------------------| @@ -64,6 +66,17 @@ struct IoRingLogConfig { static IoRingLogConfig from_packed( const FileOffsetPtr& packed_config); + /** \brief Constructs and returns a config based on a given logical size. + * + * The block size defaults to IoRingLogConfig::kDefaultBlockSize. + * The physical offset defaults to 0. + * In all cases physical size is derived from logical size and block size. + * + * \return the new IoRingLogConfig + */ + static IoRingLogConfig from_logical_size(u64 logical_size, Optional opt_block_size = None, + Optional opt_physical_offset = None); + //+++++++++++-+-+--+----- --- -- - - - - usize pages_per_block() const diff --git a/src/llfs/ioring_log_device.hpp b/src/llfs/ioring_log_device.hpp index 51032fd..ccf79b2 100644 --- a/src/llfs/ioring_log_device.hpp +++ b/src/llfs/ioring_log_device.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -64,12 +65,25 @@ class IoRingLogDeviceFactory : public LogDeviceFactory StatusOr> open_ioring_log_device() { - auto instance = std::make_unique( - RingBuffer::TempFile{.byte_size = this->config_.logical_size}, this->task_scheduler_, - this->fd_, this->config_, this->options_); + LogBlockCalculator calculate{this->config_, this->options_}; + + BATT_ASSIGN_OK_RESULT(DefaultIoRingLogDeviceStorage storage, + DefaultIoRingLogDeviceStorage::make_new( + MaxQueueDepth{ + calculate.queue_depth() * 2 + // + // Double the number of flush ops, to give us some margin so the + // rings don't ever run out of space (TODO [tastolfi 2024-05-14] + // this seems excessive; investigate lowering this) + }, + this->fd_)); this->fd_ = -1; + auto instance = std::make_unique( + RingBuffer::TempFile{.byte_size = this->config_.logical_size}, this->task_scheduler_, + std::move(storage), this->config_, this->options_); + Status open_status = instance->open(); BATT_REQUIRE_OK(open_status); diff --git a/src/llfs/ioring_log_device_storage.cpp b/src/llfs/ioring_log_device_storage.cpp new file mode 100644 index 0000000..ab36b2c --- /dev/null +++ b/src/llfs/ioring_log_device_storage.cpp @@ -0,0 +1,71 @@ +//#=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++ +// +// Part of the LLFS Project, under Apache License v2.0. +// See https://www.apache.org/licenses/LICENSE-2.0 for license information. +// SPDX short identifier: Apache-2.0 +// +//+++++++++++-+-+--+----- --- -- - - - - + +#include +// + +namespace llfs { + +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +/*static*/ StatusOr DefaultIoRingLogDeviceStorage::make_new( + MaxQueueDepth entries, int fd) +{ + BATT_ASSIGN_OK_RESULT(IoRing io_ring, IoRing::make_new(entries)); + BATT_ASSIGN_OK_RESULT(IoRing::File file, IoRing::File::open(io_ring, fd)); + + return DefaultIoRingLogDeviceStorage{std::move(io_ring), std::move(file)}; +} + +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +/*explicit*/ DefaultIoRingLogDeviceStorage::DefaultIoRingLogDeviceStorage( + IoRing&& io_ring, IoRing::File&& file) noexcept + : io_ring_{std::move(io_ring)} + , file_{std::move(file)} +{ +} + +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +/*explicit*/ DefaultIoRingLogDeviceStorage::EventLoopTask::EventLoopTask( + DefaultIoRingLogDeviceStorage& storage, std::string_view caller) noexcept + : storage_{storage} + , caller_{caller} + , thread_{[this] { + LLFS_VLOG(1) << "(" << this->caller_ << ") invoking IoRing::run()"; + + Status io_status = this->storage_.io_ring_.run(); + if (!io_status.ok()) { + LLFS_LOG_WARNING() << "(" << this->caller_ << ") IoRing::run() returned: " << io_status; + } + this->done_.set_value(true); + + LLFS_VLOG(1) << "(" << this->caller_ << ") IoRing::run() returned; exiting event loop thread"; + }} +{ +} + +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +DefaultIoRingLogDeviceStorage::EventLoopTask::~EventLoopTask() noexcept +{ + BATT_CHECK(this->join_called_); + BATT_CHECK(this->done_.get_value()); +} + +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +void DefaultIoRingLogDeviceStorage::EventLoopTask::join() +{ + this->join_called_ = true; + BATT_CHECK_OK(this->done_.await_equal(true)); + this->thread_.join(); +} + +} //namespace llfs diff --git a/src/llfs/ioring_log_device_storage.hpp b/src/llfs/ioring_log_device_storage.hpp new file mode 100644 index 0000000..6572031 --- /dev/null +++ b/src/llfs/ioring_log_device_storage.hpp @@ -0,0 +1,150 @@ +//#=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++ +// +// Part of the LLFS Project, under Apache License v2.0. +// See https://www.apache.org/licenses/LICENSE-2.0 for license information. +// SPDX short identifier: Apache-2.0 +// +//+++++++++++-+-+--+----- --- -- - - - - + +#pragma once +#ifndef LLFS_IORING_LOG_DEVICE_STORAGE_HPP +#define LLFS_IORING_LOG_DEVICE_STORAGE_HPP + +#include +// +#include +#include +#include +#include + +#include + +#include + +namespace llfs { + +class DefaultIoRingLogDeviceStorage +{ + public: + /** \brief Creates a new IoRing with the specified queue depth, wraps it in a + * DefaultIoRingLogDeviceStorage, and returns the result. + * + * The returned object should be used by an IoRingLogDriver/IoRingLogDevice for the low-level file + * I/O. + */ + static StatusOr make_new(MaxQueueDepth entries, int fd); + + /** \brief A background thread or task that runs the IoRing event loop for a given + * DefaultIoRingLogDeviceStorage object. + */ + class EventLoopTask; + + //+++++++++++-+-+--+----- --- -- - - - - + + DefaultIoRingLogDeviceStorage(const DefaultIoRingLogDeviceStorage&) = delete; + DefaultIoRingLogDeviceStorage& operator=(const DefaultIoRingLogDeviceStorage&) = delete; + + DefaultIoRingLogDeviceStorage(DefaultIoRingLogDeviceStorage&&) = default; + DefaultIoRingLogDeviceStorage& operator=(DefaultIoRingLogDeviceStorage&&) = default; + + //+++++++++++-+-+--+----- --- -- - - - - + + Status register_fd() + { + return this->file_.register_fd(); + } + + StatusOr register_buffers(batt::BoxedSeq&& buffers, + bool update = false) const noexcept + { + return this->io_ring_.register_buffers(std::move(buffers), update); + } + + Status close() + { + return this->file_.close(); + } + + void on_work_started() const noexcept + { + this->io_ring_.on_work_started(); + } + + void on_work_finished() const noexcept + { + this->io_ring_.on_work_finished(); + } + + void reset_event_loop() const noexcept + { + this->io_ring_.reset(); + } + + template )> + void post_to_event_loop(Handler&& handler) const noexcept + { + this->io_ring_.post(BATT_FORWARD(handler)); + } + + void stop_event_loop() const noexcept + { + this->io_ring_.stop(); + } + + Status read_all(i64 offset, MutableBuffer buffer) + { + return this->file_.read_all(offset, buffer); + } + + template + void async_write_some_fixed(i64 file_offset, const ConstBuffer& data, i32 buf_index, + Handler&& handler); + + //+++++++++++-+-+--+----- --- -- - - - - + private: + explicit DefaultIoRingLogDeviceStorage(IoRing&& io_ring, IoRing::File&& file) noexcept; + + //+++++++++++-+-+--+----- --- -- - - - -- + + IoRing io_ring_; + IoRing::File file_; +}; + +//=#=#==#==#===============+=+=+=+=++=++++++++++++++-++-+--+-+----+--------------- + +template +inline void DefaultIoRingLogDeviceStorage::async_write_some_fixed(i64 file_offset, + const ConstBuffer& data, + i32 buf_index, Handler&& handler) +{ + this->file_.async_write_some_fixed(file_offset, data, buf_index, BATT_FORWARD(handler)); +} + +//=#=#==#==#===============+=+=+=+=++=++++++++++++++-++-+--+-+----+--------------- + +class DefaultIoRingLogDeviceStorage::EventLoopTask +{ + public: + explicit EventLoopTask(DefaultIoRingLogDeviceStorage& storage, std::string_view caller) noexcept; + + EventLoopTask(const EventLoopTask&) = delete; + EventLoopTask& operator=(const EventLoopTask&) = delete; + + ~EventLoopTask() noexcept; + + //+++++++++++-+-+--+----- --- -- - - - - + + void join(); + + //+++++++++++-+-+--+----- --- -- - - - - + private: + DefaultIoRingLogDeviceStorage& storage_; + std::string_view caller_; + std::thread thread_; + batt::Watch done_{false}; + bool join_called_ = false; +}; + +} //namespace llfs + +#endif // LLFS_IORING_LOG_DEVICE_FILE_HPP diff --git a/src/llfs/ioring_log_driver.cpp b/src/llfs/ioring_log_driver.cpp index 98434ca..2544b2e 100644 --- a/src/llfs/ioring_log_driver.cpp +++ b/src/llfs/ioring_log_driver.cpp @@ -15,7 +15,7 @@ namespace llfs { -template class BasicIoRingLogDriver; +template class BasicIoRingLogDriver; } // namespace llfs diff --git a/src/llfs/ioring_log_driver.hpp b/src/llfs/ioring_log_driver.hpp index f851d8e..25a32fb 100644 --- a/src/llfs/ioring_log_driver.hpp +++ b/src/llfs/ioring_log_driver.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -40,14 +42,11 @@ BATT_UNSUPPRESS() namespace llfs { -template