Skip to content

Commit bfee64e

Browse files
PS-10243 feature: Add data structures for GTID set operations (part 1) (#76)
https://perconadev.atlassian.net/browse/PS-10243 Changed the definition of the 'util::bounded_string_storage' - instead of being 'std::array<std::byte, N>', it is now 'boost::container::static_vector<std::byte, N>' which is more appropriate because it holds real size in one of its members eliminating the necessity to do 'strlen()' every time we want to use this data as a string. This affected 'server_version' member in the FORMAT_DESCRIPTION event post header and 'tag' in the the GTID_TAGGED_LOG event body. In addition, changed the underlying container for storing 'binlog' member (file name) in the ROTATE event body: instead of 'std::string', we now use 'boost::container::small_vector<std::byte, 64> which will let us avoid dynamic allocations for file names up to 64 bytes.
1 parent f5aaf4c commit bfee64e

7 files changed

Lines changed: 44 additions & 29 deletions

src/binsrv/event/format_description_post_header_impl.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include <stdexcept>
2222
#include <string>
2323
#include <string_view>
24-
#include <tuple>
2524

2625
#include <boost/align/align_up.hpp>
2726

@@ -64,24 +63,27 @@ generic_post_header_impl<code_type::format_description>::
6463
*/
6564

6665
static_assert(server_version_length ==
67-
std::tuple_size_v<decltype(server_version_)>,
66+
decltype(server_version_)::static_capacity,
6867
"mismatch in "
6968
"generic_post_header_impl<code_type::format_description>::"
7069
"server_version_length");
7170

7271
// TODO: initialize size_in_bytes directly based on the sum of fields
7372
// widths instead of this static_assert
7473
static_assert(
75-
sizeof binlog_version_ + std::tuple_size_v<decltype(server_version_)> +
74+
sizeof binlog_version_ + decltype(server_version_)::static_capacity +
7675
sizeof create_timestamp_ + sizeof common_header_length_ +
77-
std::tuple_size_v<decltype(post_header_lengths_)> ==
76+
sizeof post_header_lengths_ ==
7877
get_size_in_bytes(latest_known_protocol_server_version),
7978
"mismatch in "
8079
"generic_post_header_impl<code_type::format_description>::size_in_bytes");
8180
// make sure we did OK with data members reordering
8281
static_assert(sizeof *this ==
8382
boost::alignment::align_up(
84-
get_size_in_bytes(latest_known_protocol_server_version),
83+
sizeof binlog_version_ + sizeof server_version_ +
84+
sizeof create_timestamp_ +
85+
sizeof common_header_length_ +
86+
sizeof post_header_lengths_,
8587
alignof(decltype(*this))),
8688
"inefficient data member reordering in "
8789
"generic_post_header_impl<code_type::format_description>");
@@ -93,7 +95,10 @@ generic_post_header_impl<code_type::format_description>::
9395

9496
auto remainder = portion;
9597
util::extract_fixed_int_from_byte_span(remainder, binlog_version_);
96-
util::extract_byte_array_from_byte_span(remainder, server_version_);
98+
server_version_.resize(decltype(server_version_)::capacity());
99+
util::extract_byte_span_from_byte_span(remainder,
100+
util::byte_span{server_version_});
101+
util::normalize_for_c_str(server_version_);
97102
util::extract_fixed_int_from_byte_span(remainder, create_timestamp_);
98103
util::extract_fixed_int_from_byte_span(remainder, common_header_length_);
99104
const auto expected_subrange_length{

src/binsrv/event/gtid_log_post_header.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ gtid_log_post_header::gtid_log_post_header(util::const_byte_span portion) {
8484

8585
// TODO: initialize size_in_bytes directly based on the sum of fields
8686
// widths instead of this static_assert
87-
static_assert(sizeof flags_ + std::tuple_size_v<decltype(uuid_)> +
88-
sizeof gno_ + sizeof logical_ts_code_ +
89-
sizeof last_committed_ + sizeof sequence_number_ ==
87+
static_assert(sizeof flags_ + sizeof uuid_ + sizeof gno_ +
88+
sizeof logical_ts_code_ + sizeof last_committed_ +
89+
sizeof sequence_number_ ==
9090
size_in_bytes,
9191
"mismatch in gtid_log_event_post_header::size_in_bytes");
9292
// make sure we did OK with data members reordering

src/binsrv/event/gtid_tagged_log_body_impl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ generic_body_impl<code_type::gtid_tagged_log>::generic_body_impl(
5959
static_assert(
6060
sizeof *this ==
6161
boost::alignment::align_up(
62-
sizeof flags_ + std::tuple_size_v<decltype(uuid_)> + sizeof gno_ +
63-
std::tuple_size_v<decltype(tag_)> + sizeof last_committed_ +
64-
sizeof sequence_number_ + sizeof immediate_commit_timestamp_ +
62+
sizeof flags_ + sizeof uuid_ + sizeof gno_ + sizeof tag_ +
63+
sizeof last_committed_ + sizeof sequence_number_ +
64+
sizeof immediate_commit_timestamp_ +
6565
sizeof original_commit_timestamp_ +
6666
sizeof transaction_length_ + sizeof original_server_version_ +
6767
sizeof immediate_server_version_ +
@@ -297,6 +297,7 @@ void generic_body_impl<code_type::gtid_tagged_log>::process_field_data(
297297
// Extracting tag (length encoded as varlent int and raw character array)
298298
std::size_t extracted_tag_length{};
299299
varlen_int_extractor(remainder, extracted_tag_length, "tag length");
300+
tag_.resize(extracted_tag_length);
300301
const std::span<tag_storage::value_type> tag_subrange{std::data(tag_),
301302
extracted_tag_length};
302303
if (!util::extract_byte_span_from_byte_span_checked(remainder,

src/binsrv/event/rotate_body_impl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "binsrv/event/rotate_body_impl.hpp"
1717

18+
#include <iterator>
1819
#include <ostream>
1920

2021
#include "binsrv/event/code_type.hpp"
@@ -30,7 +31,7 @@ generic_body_impl<code_type::rotate>::generic_body_impl(
3031
// no need to check if member reordering is OK as this class has
3132
// only one member for holding data of varying length
3233

33-
binlog_.assign(util::as_string_view(portion));
34+
binlog_.assign(std::begin(portion), std::end(portion));
3435
}
3536

3637
std::ostream &operator<<(std::ostream &output,

src/binsrv/event/rotate_body_impl.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,19 @@
2121
#include <string>
2222
#include <string_view>
2323

24-
#include "util/byte_span_fwd.hpp"
24+
#include <boost/container/small_vector.hpp>
25+
26+
#include "util/byte_span.hpp"
2527

2628
namespace binsrv::event {
2729

2830
template <> class [[nodiscard]] generic_body_impl<code_type::rotate> {
2931
public:
30-
// TODO: change this to a container with larger buffer for SBO to avoid
31-
// memory allocations (e.g. boost::container::small_vector)
32-
using binlog_storage = std::string;
32+
static constexpr std::size_t expected_max_binlog_name_length{64U};
33+
// TODO: in c++26 change to std::inplace_vector
34+
using binlog_storage =
35+
boost::container::small_vector<std::byte,
36+
expected_max_binlog_name_length>;
3337

3438
explicit generic_body_impl(util::const_byte_span portion);
3539

@@ -38,7 +42,7 @@ template <> class [[nodiscard]] generic_body_impl<code_type::rotate> {
3842
}
3943

4044
[[nodiscard]] std::string_view get_binlog() const noexcept {
41-
return {binlog_};
45+
return util::as_string_view(binlog_);
4246
}
4347

4448
private:

src/util/bounded_string_storage.hpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,20 @@
2525
namespace util {
2626

2727
template <std::size_t N>
28-
std::string_view
28+
[[nodiscard]] std::string_view
2929
to_string_view(const bounded_string_storage<N> &storage) noexcept {
30-
// in case when every byte of the array is significant (non-zero)
31-
// we cannot rely on std::string_view::string_view(const char*)
32-
// constructor as '\0' character will never be found
33-
auto result{util::as_string_view(storage)};
34-
auto position{result.find('\0')};
35-
if (position != std::string_view::npos) {
36-
result.remove_suffix(std::size(result) - position);
30+
return util::as_string_view(storage);
31+
}
32+
33+
template <std::size_t N>
34+
void normalize_for_c_str(bounded_string_storage<N> &storage) {
35+
// in case when every byte of the container is significant (non-zero)
36+
// we do not change the size of the container
37+
if (const auto begin_it{std::cbegin(storage)}, end_it{std::cend(storage)},
38+
zero_it{std::find(begin_it, end_it, std::byte{})};
39+
zero_it != end_it) {
40+
storage.resize(static_cast<std::size_t>(std::distance(begin_it, zero_it)));
3741
}
38-
return result;
3942
}
4043

4144
} // namespace util

src/util/bounded_string_storage_fwd.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
#ifndef UTIL_BOUNDED_STRING_STORAGE_FWD_HPP
1717
#define UTIL_BOUNDED_STRING_STORAGE_FWD_HPP
1818

19-
#include <array>
2019
#include <cstddef>
2120

21+
#include <boost/container/static_vector.hpp>
22+
2223
namespace util {
2324

2425
template <std::size_t N>
25-
using bounded_string_storage = std::array<std::byte, N>;
26+
using bounded_string_storage = boost::container::static_vector<std::byte, N>;
2627

2728
} // namespace util
2829

0 commit comments

Comments
 (0)