From 18e79d730eb136ea625e21fe4e8f30b4b5a0422b Mon Sep 17 00:00:00 2001 From: Calle Wilund Date: Wed, 20 Sep 2023 13:44:16 +0000 Subject: [PATCH] commitlog: Add iterator adaptor for doing buffer splitting into sub-page ranges With somewhat less overhead than creating 100+ temporary_buffer proxies --- db/commitlog/commitlog.cc | 41 ++++++++++++++++++++++++ db/commitlog/commitlog_entry.hh | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/db/commitlog/commitlog.cc b/db/commitlog/commitlog.cc index f0c00d8ce7..84eb6ed0d2 100644 --- a/db/commitlog/commitlog.cc +++ b/db/commitlog/commitlog.cc @@ -624,6 +624,47 @@ std::enable_if_t::value, T> read(Input& in) { return net::ntoh(in.template read()); } +detail::sector_split_iterator::sector_split_iterator(const sector_split_iterator&) noexcept = default; + +detail::sector_split_iterator::sector_split_iterator() + : _ptr(nullptr) + , _size(0) + , _sector_size(0) +{} + +detail::sector_split_iterator::sector_split_iterator(base_iterator i, base_iterator e, size_t sector_size) + : _iter(i) + , _end(e) + , _ptr(i != e ? const_cast(i->get()) : nullptr) + , _size(i != e ? sector_size - sector_overhead_size : 0) + , _sector_size(sector_size) +{} + +detail::sector_split_iterator& detail::sector_split_iterator::operator++() { + assert(_iter != _end); + _ptr += _sector_size; + // check if we have more pages in this temp-buffer (in out case they are always aligned + sized in page units) + auto rem = _iter->size() - std::distance(_iter->get(), const_cast(_ptr)); + if (rem == 0) { + if (++_iter == _end) { + _ptr = nullptr; + _size = 0; + return *this; + } + rem = _iter->size(); + assert(rem >= _sector_size); + // booh. ugly. + _ptr = const_cast(_iter->get()); + } + return *this; +} + +detail::sector_split_iterator detail::sector_split_iterator::operator++(int) { + auto res = *this; + ++(*this); + return res; +} + /* * A single commit log file on disk. Manages creation of the file and writing mutations to disk, * as well as tracking the last mutation position of any "dirty" CFs covered by the segment file. Segment diff --git a/db/commitlog/commitlog_entry.hh b/db/commitlog/commitlog_entry.hh index b3c994935b..3ee5716c80 100644 --- a/db/commitlog/commitlog_entry.hh +++ b/db/commitlog/commitlog_entry.hh @@ -13,6 +13,62 @@ #include "commitlog_types.hh" #include "mutation/frozen_mutation.hh" #include "schema/schema_fwd.hh" +#include "replay_position.hh" + +namespace detail { + + using buffer_type = fragmented_temporary_buffer; + using base_iterator = typename std::vector>::const_iterator; + + static constexpr auto sector_overhead_size = sizeof(uint32_t) + sizeof(db::segment_id_type); + + // iterator adaptor to enable splitting normal + // frag-buffer temporary buffer objects into + // sub-disk-page sized chunks. + class sector_split_iterator { + base_iterator _iter, _end; + char* _ptr; + size_t _size; + size_t _sector_size; + public: + sector_split_iterator(const sector_split_iterator&) noexcept; + sector_split_iterator(base_iterator i, base_iterator e, size_t sector_size); + sector_split_iterator(); + + char* get_write() const { + return _ptr; + } + size_t size() const { + return _size; + } + char* begin() { + return _ptr; + } + char* end() { + return _ptr + _size; + } + const char* begin() const { + return _ptr; + } + const char* end() const { + return _ptr + _size; + } + + bool operator==(const sector_split_iterator& rhs) const { + return _iter == rhs._iter && _ptr == rhs._ptr; + } + + auto& operator*() const { + return *this; + } + auto* operator->() const { + return this; + } + + sector_split_iterator& operator++(); + sector_split_iterator operator++(int); + }; +} class commitlog_entry { std::optional _mapping;