Skip to content

Commit

Permalink
Ioring stream buffer enhancements (#148)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
tonyastolfi authored Apr 3, 2024
1 parent d28435f commit 921eeb4
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 39 deletions.
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
41 changes: 3 additions & 38 deletions src/llfs/ioring_buffer_view.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
//
#include <llfs/ioring_buffer_view.hpp>

#include <llfs/ioring_buffer_view.test.hpp>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

Expand Down Expand Up @@ -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<llfs::ScopedIoRing> scoped_io_ring;

const llfs::IoRing* io_ring = nullptr;

llfs::StatusOr<std::unique_ptr<llfs::IoRingBufferPool>> status_or_buffer_pool;

llfs::IoRingBufferPool* buffer_pool = nullptr;

llfs::StatusOr<llfs::IoRingBufferPool::Buffer> buffer_1;
};
using llfs::testing::IoringBufferViewTest;

//+++++++++++-+-+--+----- --- -- - - - -
// 1. Construct with empty buffer/slice.
Expand Down
66 changes: 66 additions & 0 deletions src/llfs/ioring_buffer_view.test.hpp
Original file line number Diff line number Diff line change
@@ -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 <llfs/config.hpp>
//
#include <llfs/int_types.hpp>
#include <llfs/ioring_buffer_view.hpp>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

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<llfs::ScopedIoRing> scoped_io_ring;

const llfs::IoRing* io_ring = nullptr;

llfs::StatusOr<std::unique_ptr<llfs::IoRingBufferPool>> status_or_buffer_pool;

llfs::IoRingBufferPool* buffer_pool = nullptr;

llfs::StatusOr<llfs::IoRingBufferPool::Buffer> buffer_1;
};

} //namespace testing
} //namespace llfs

#endif // LLFS_IORING_BUFFER_VIEW_TEST_HPP
1 change: 1 addition & 0 deletions src/llfs/ioring_stream_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ void IoRingStreamBuffer::Fragment::push(Fragment&& fragment)
for (BufferView& part : fragment.views_) {
this->push(std::move(part));
}
fragment.views_.clear();
}

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
Expand Down
57 changes: 57 additions & 0 deletions src/llfs/ioring_stream_buffer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
#include <llfs/ioring_stream_buffer.hpp>

#include <llfs/ioring_buffer_view.test.hpp>
#include <llfs/ioring_stream_buffer.test.hpp>

#include <gmock/gmock.h>
Expand All @@ -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;
Expand Down Expand Up @@ -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<llfs::IoRingBufferPool::Buffer, std::unique_ptr<u8[]>> 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

0 comments on commit 921eeb4

Please sign in to comment.