From 921eeb480b3d1bc08d49971867782cac7b574c46 Mon Sep 17 00:00:00 2001 From: Tony Astolfi Date: Wed, 3 Apr 2024 17:10:59 -0400 Subject: [PATCH] Ioring stream buffer enhancements (#148) * Add Fragment::push(Fragment) overloads. * Remove -march=native, -mtune=native for better compatibility. * Fix compile error. * Add new test case for IoRingStreamBufferFragment::as_seq. * Added Fragment::push unit tests. --- conanfile.py | 2 +- src/llfs/ioring_buffer_view.test.cpp | 41 ++-------------- src/llfs/ioring_buffer_view.test.hpp | 66 ++++++++++++++++++++++++++ src/llfs/ioring_stream_buffer.cpp | 1 + src/llfs/ioring_stream_buffer.test.cpp | 57 ++++++++++++++++++++++ 5 files changed, 128 insertions(+), 39 deletions(-) create mode 100644 src/llfs/ioring_buffer_view.test.hpp diff --git a/conanfile.py b/conanfile.py index 2b77892..919851c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -69,7 +69,7 @@ def configure(self): def requirements(self): - self.requires("batteries/0.51.0", **VISIBLE) + self.requires("batteries/0.52.1", **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/ioring_buffer_view.test.cpp b/src/llfs/ioring_buffer_view.test.cpp index 92f207f..d79d693 100644 --- a/src/llfs/ioring_buffer_view.test.cpp +++ b/src/llfs/ioring_buffer_view.test.cpp @@ -10,6 +10,8 @@ // #include +#include + #include #include @@ -39,44 +41,7 @@ namespace { using namespace llfs::int_types; -usize kTestBufferCount = 4; -usize kTestBufferSize = 4096; - -class IoringBufferViewTest : public ::testing::Test -{ - public: - void SetUp() override - { - this->scoped_io_ring = - llfs::ScopedIoRing::make_new(llfs::MaxQueueDepth{8}, llfs::ThreadPoolSize{1}); - - ASSERT_TRUE(this->scoped_io_ring.ok()) << BATT_INSPECT(this->scoped_io_ring.status()); - - this->io_ring = std::addressof(this->scoped_io_ring->get_io_ring()); - - this->status_or_buffer_pool = llfs::IoRingBufferPool::make_new( - *this->io_ring, llfs::BufferCount{kTestBufferCount}, llfs::BufferSize{kTestBufferSize}); - - ASSERT_TRUE(this->status_or_buffer_pool.ok()) - << BATT_INSPECT(this->status_or_buffer_pool.status()); - - this->buffer_pool = this->status_or_buffer_pool->get(); - - this->buffer_1 = this->buffer_pool->await_allocate(); - - ASSERT_TRUE(this->buffer_1.ok()) << BATT_INSPECT(this->buffer_1.status()); - } - - llfs::StatusOr scoped_io_ring; - - const llfs::IoRing* io_ring = nullptr; - - llfs::StatusOr> status_or_buffer_pool; - - llfs::IoRingBufferPool* buffer_pool = nullptr; - - llfs::StatusOr buffer_1; -}; +using llfs::testing::IoringBufferViewTest; //+++++++++++-+-+--+----- --- -- - - - - // 1. Construct with empty buffer/slice. diff --git a/src/llfs/ioring_buffer_view.test.hpp b/src/llfs/ioring_buffer_view.test.hpp new file mode 100644 index 0000000..33e209b --- /dev/null +++ b/src/llfs/ioring_buffer_view.test.hpp @@ -0,0 +1,66 @@ +//#=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++ +// +// 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_BUFFER_VIEW_TEST_HPP +#define LLFS_IORING_BUFFER_VIEW_TEST_HPP + +#include +// +#include +#include + +#include +#include + +namespace llfs { +namespace testing { + +class IoringBufferViewTest : public ::testing::Test +{ + public: + static constexpr usize kTestBufferCount = 4; + static constexpr usize kTestBufferSize = 4096; + + void SetUp() override + { + this->scoped_io_ring = + llfs::ScopedIoRing::make_new(llfs::MaxQueueDepth{8}, llfs::ThreadPoolSize{1}); + + ASSERT_TRUE(this->scoped_io_ring.ok()) << BATT_INSPECT(this->scoped_io_ring.status()); + + this->io_ring = std::addressof(this->scoped_io_ring->get_io_ring()); + + this->status_or_buffer_pool = llfs::IoRingBufferPool::make_new( + *this->io_ring, llfs::BufferCount{kTestBufferCount}, llfs::BufferSize{kTestBufferSize}); + + ASSERT_TRUE(this->status_or_buffer_pool.ok()) + << BATT_INSPECT(this->status_or_buffer_pool.status()); + + this->buffer_pool = this->status_or_buffer_pool->get(); + + this->buffer_1 = this->buffer_pool->await_allocate(); + + ASSERT_TRUE(this->buffer_1.ok()) << BATT_INSPECT(this->buffer_1.status()); + } + + llfs::StatusOr scoped_io_ring; + + const llfs::IoRing* io_ring = nullptr; + + llfs::StatusOr> status_or_buffer_pool; + + llfs::IoRingBufferPool* buffer_pool = nullptr; + + llfs::StatusOr buffer_1; +}; + +} //namespace testing +} //namespace llfs + +#endif // LLFS_IORING_BUFFER_VIEW_TEST_HPP diff --git a/src/llfs/ioring_stream_buffer.cpp b/src/llfs/ioring_stream_buffer.cpp index 3bd98c9..a387dc9 100644 --- a/src/llfs/ioring_stream_buffer.cpp +++ b/src/llfs/ioring_stream_buffer.cpp @@ -253,6 +253,7 @@ void IoRingStreamBuffer::Fragment::push(Fragment&& fragment) for (BufferView& part : fragment.views_) { this->push(std::move(part)); } + fragment.views_.clear(); } //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - diff --git a/src/llfs/ioring_stream_buffer.test.cpp b/src/llfs/ioring_stream_buffer.test.cpp index f4e07d7..93f79b7 100644 --- a/src/llfs/ioring_stream_buffer.test.cpp +++ b/src/llfs/ioring_stream_buffer.test.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -22,6 +23,7 @@ namespace { using namespace llfs::int_types; +using llfs::testing::IoringBufferViewTest; using llfs::testing::IoringStreamBufferClosedEmptyTest; using llfs::testing::IoringStreamBufferEmptyTest; using llfs::testing::IoringStreamBufferFullTest; @@ -396,4 +398,59 @@ TEST_F(IoringStreamBufferFullTest, PrepareWaitOk2) EXPECT_TRUE(view.ok()) << BATT_INSPECT(view.ok()); } +//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - - +// +TEST_F(IoringBufferViewTest, FragmentSeqTest) +{ + const std::string_view kTestDataPrefix = "hello, world"; + + std::memset(this->buffer_1->data(), 'a', this->buffer_1->size()); + std::memcpy(this->buffer_1->data(), kTestDataPrefix.data(), kTestDataPrefix.size()); + + const auto verify_data_in_fragment = [this](const llfs::IoRingStreamBuffer::Fragment& f) { + std::variant> storage; + + batt::ConstBuffer cb = f.gather(storage); + + ASSERT_EQ(cb.size(), this->buffer_1->size()); + ASSERT_EQ(std::memcmp(cb.data(), this->buffer_1->data(), cb.size()), 0); + }; + + // Build Fragment f1 using a single buffer view. + // + llfs::IoRingConstBufferView view1{ + *this->buffer_1, + this->buffer_1->get(), + }; + + llfs::IoRingStreamBuffer::Fragment f1; + f1.push(std::move(view1)); + + ASSERT_NO_FATAL_FAILURE(verify_data_in_fragment(f1)); + + // Now create Fragment f2 by copying views from f1. + // + llfs::IoRingStreamBuffer::Fragment f2; + + f1.as_seq() | batt::seq::for_each([&f2](const llfs::IoRingConstBufferView& view) { + f2.push(batt::make_copy(view)); + }); + + EXPECT_EQ(f1.byte_size(), f2.byte_size()); + ASSERT_NO_FATAL_FAILURE(verify_data_in_fragment(f2)); + + // Use push overloads. + // + llfs::IoRingStreamBuffer::Fragment f3; + f3.push(f2); + EXPECT_EQ(f1.byte_size(), f3.byte_size()); + ASSERT_NO_FATAL_FAILURE(verify_data_in_fragment(f3)); + + llfs::IoRingStreamBuffer::Fragment f4; + f4.push(std::move(f1)); + EXPECT_EQ(f2.byte_size(), f4.byte_size()); + EXPECT_TRUE(f1.empty()); + ASSERT_NO_FATAL_FAILURE(verify_data_in_fragment(f4)); +} + } // namespace