Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,35 +64,41 @@ jobs:
- {
name: "GCC 14 Debug",
label: "debug_gcc14",
run_mtr: true
run_mtr: true,
run_ctest: true
}
- {
name: "GCC 14 RelWithDebInfo",
label: "release_gcc14",
run_mtr: true
run_mtr: true,
run_ctest: true
}
- {
name: "GCC 14 ASan",
label: "asan_gcc14",
run_mtr: true,
mtr_options: "--sanitize"
mtr_options: "--sanitize",
run_ctest: true
}
- {
name: "Clang 19 Debug",
label: "debug_clang19",
run_clang_tidy: true
run_clang_tidy: true,
run_ctest: true
}
- {
name: "Clang 19 RelWithDebInfo",
label: "release_clang19",
run_clang_tidy: true
run_clang_tidy: true,
run_ctest: true
}
- {
name: "Clang 19 ASan",
label: "asan_clang19"
# TODO: re-enable running MTR under this "Clang XX ASan"
# run_mtr: true,
# mtr_options: "--sanitize"
# mtr_options: "--sanitize",
# run_ctest: true
# when "-stdlib=libc++ -fsanitize=address" alloc-dealloc-mismatch issue is fixed
# (https://github.com/llvm/llvm-project/issues/59432)
# or CI is upgraded to Clang 20
Expand Down Expand Up @@ -309,6 +315,7 @@ jobs:
--suite=binlog_streaming ${{matrix.config.mtr_options}}

- name: CTest
if: matrix.config.run_ctest
working-directory: ${{github.workspace}}/src-build-${{matrix.config.label}}
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
Expand Down
16 changes: 15 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,16 @@ set(source_files
src/binsrv/event/unknown_post_header.cpp

# gtid data structure files
src/binsrv/gtid/common_types.hpp
src/binsrv/gtids/common_types.hpp
src/binsrv/gtids/gtid_fwd.hpp
src/binsrv/gtids/gtid.hpp
src/binsrv/gtids/gtid.cpp
src/binsrv/gtids/gtid_set_fwd.hpp
src/binsrv/gtids/gtid_set.hpp
src/binsrv/gtids/gtid_set.cpp
src/binsrv/gtids/tag_fwd.hpp
src/binsrv/gtids/tag.hpp
src/binsrv/gtids/tag.cpp

# binlog files
src/binsrv/basic_logger_fwd.hpp
Expand Down Expand Up @@ -348,3 +357,8 @@ set_target_properties(binlog_server PROPERTIES
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)

include(CTest)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
3 changes: 2 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"cacheVariables": {
"CMAKE_PREFIX_PATH": "${sourceParentDir}/aws-sdk-cpp-install-${presetName};${sourceParentDir}/boost-install-${presetName}",
"CPP_STANDARD": "20",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"BUILD_TESTING": "ON"
}
},

Expand Down
6 changes: 3 additions & 3 deletions src/binsrv/event/gtid_log_post_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#include "binsrv/event/gtid_log_flag_type.hpp"

#include "binsrv/gtid/common_types.hpp"
#include "binsrv/gtids/common_types.hpp"

#include "util/byte_span.hpp"
#include "util/byte_span_extractors.hpp"
Expand Down Expand Up @@ -127,8 +127,8 @@ gtid_log_post_header::get_flags() const noexcept {
return to_string(get_flags());
}

[[nodiscard]] gtid::uuid gtid_log_post_header::get_uuid() const noexcept {
gtid::uuid result;
[[nodiscard]] gtids::uuid gtid_log_post_header::get_uuid() const noexcept {
gtids::uuid result;
const auto &uuid_raw{get_uuid_raw()};
static_assert(std::tuple_size_v<decltype(uuid_)> ==
boost::uuids::uuid::static_size());
Expand Down
8 changes: 4 additions & 4 deletions src/binsrv/event/gtid_log_post_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include "binsrv/event/gtid_log_flag_type_fwd.hpp"

#include "binsrv/gtid/common_types.hpp"
#include "binsrv/gtids/common_types.hpp"

#include "util/byte_span_fwd.hpp"

Expand All @@ -43,10 +43,10 @@ class [[nodiscard]] gtid_log_post_header {
[[nodiscard]] gtid_log_flag_set get_flags() const noexcept;
[[nodiscard]] std::string get_readable_flags() const;

[[nodiscard]] const gtid::uuid_storage &get_uuid_raw() const noexcept {
[[nodiscard]] const gtids::uuid_storage &get_uuid_raw() const noexcept {
return uuid_;
}
[[nodiscard]] gtid::uuid get_uuid() const noexcept;
[[nodiscard]] gtids::uuid get_uuid() const noexcept;
[[nodiscard]] std::string get_readable_uuid() const;

[[nodiscard]] std::int64_t get_gno_raw() const noexcept { return gno_; }
Expand All @@ -67,7 +67,7 @@ class [[nodiscard]] gtid_log_post_header {
// the members are deliberately reordered for better packing
std::uint8_t flags_{}; // 0
std::uint8_t logical_ts_code_{}; // 3
gtid::uuid_storage uuid_{}; // 1
gtids::uuid_storage uuid_{}; // 1
std::int64_t gno_{}; // 2
std::int64_t last_committed_{}; // 4
std::int64_t sequence_number_{}; // 5
Expand Down
10 changes: 5 additions & 5 deletions src/binsrv/event/gtid_tagged_log_body_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include "binsrv/event/code_type.hpp"
#include "binsrv/event/gtid_log_flag_type.hpp"

#include "binsrv/gtid/common_types.hpp"
#include "binsrv/gtids/common_types.hpp"

#include "util/bounded_string_storage.hpp"
#include "util/byte_span.hpp"
Expand Down Expand Up @@ -152,9 +152,9 @@ generic_body_impl<code_type::gtid_tagged_log>::get_readable_flags() const {
return to_string(get_flags());
}

[[nodiscard]] gtid::uuid
[[nodiscard]] gtids::uuid
generic_body_impl<code_type::gtid_tagged_log>::get_uuid() const noexcept {
gtid::uuid result;
gtids::uuid result;
const auto &uuid_raw{get_uuid_raw()};
static_assert(std::tuple_size_v<decltype(uuid_)> ==
boost::uuids::uuid::static_size());
Expand Down Expand Up @@ -298,8 +298,8 @@ void generic_body_impl<code_type::gtid_tagged_log>::process_field_data(
std::size_t extracted_tag_length{};
varlen_int_extractor(remainder, extracted_tag_length, "tag length");
tag_.resize(extracted_tag_length);
const std::span<tag_storage::value_type> tag_subrange{std::data(tag_),
extracted_tag_length};
const std::span<gtids::tag_storage::value_type> tag_subrange{
std::data(tag_), extracted_tag_length};
if (!util::extract_byte_span_from_byte_span_checked(remainder,
tag_subrange)) {
util::exception_location().raise<std::invalid_argument>(
Expand Down
18 changes: 8 additions & 10 deletions src/binsrv/event/gtid_tagged_log_body_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@

#include "binsrv/event/gtid_log_flag_type_fwd.hpp"

#include "binsrv/gtid/common_types.hpp"
#include "binsrv/gtids/common_types.hpp"

#include "util/bounded_string_storage_fwd.hpp"
#include "util/byte_span_fwd.hpp"
#include "util/semantic_version_fwd.hpp"

Expand All @@ -35,24 +34,23 @@ template <> class [[nodiscard]] generic_body_impl<code_type::gtid_tagged_log> {
public:
// https://github.com/mysql/mysql-server/blob/mysql-8.4.6/libs/mysql/binlog/event/control_events.h#L1111

static constexpr std::size_t tag_length{32U};
using tag_storage = util::bounded_string_storage<tag_length>;

explicit generic_body_impl(util::const_byte_span portion);

[[nodiscard]] std::uint8_t get_flags_raw() const noexcept { return flags_; }
[[nodiscard]] gtid_log_flag_set get_flags() const noexcept;
[[nodiscard]] std::string get_readable_flags() const;

[[nodiscard]] const gtid::uuid_storage &get_uuid_raw() const noexcept {
[[nodiscard]] const gtids::uuid_storage &get_uuid_raw() const noexcept {
return uuid_;
}
[[nodiscard]] gtid::uuid get_uuid() const noexcept;
[[nodiscard]] gtids::uuid get_uuid() const noexcept;
[[nodiscard]] std::string get_readable_uuid() const;

[[nodiscard]] std::int64_t get_gno_raw() const noexcept { return gno_; }

[[nodiscard]] const tag_storage &get_tag_raw() const noexcept { return tag_; }
[[nodiscard]] const gtids::tag_storage &get_tag_raw() const noexcept {
return tag_;
}
[[nodiscard]] std::string_view get_tag() const noexcept;

[[nodiscard]] std::int64_t get_last_committed_raw() const noexcept {
Expand Down Expand Up @@ -132,9 +130,9 @@ template <> class [[nodiscard]] generic_body_impl<code_type::gtid_tagged_log> {

// the members are deliberately reordered for better packing
std::uint8_t flags_{}; // 0
gtid::uuid_storage uuid_{}; // 1
gtids::uuid_storage uuid_{}; // 1
std::int64_t gno_{}; // 2
tag_storage tag_{}; // 3
gtids::tag_storage tag_{}; // 3
std::int64_t last_committed_{}; // 4
std::int64_t sequence_number_{}; // 5
std::uint64_t immediate_commit_timestamp_{unset_commit_timestamp}; // 6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,34 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef BINSRV_GTID_COMMON_TYPES_HPP
#define BINSRV_GTID_COMMON_TYPES_HPP
#ifndef BINSRV_GTIDS_COMMON_TYPES_HPP
#define BINSRV_GTIDS_COMMON_TYPES_HPP

#include <array>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <type_traits>

#include <boost/uuid/uuid.hpp>

namespace binsrv::gtid {
#include "util/bounded_string_storage_fwd.hpp"

namespace binsrv::gtids {

using uuid = boost::uuids::uuid;
inline constexpr std::size_t uuid_length{boost::uuids::uuid::static_size()};
using uuid_storage = std::array<std::byte, uuid_length>;

} // namespace binsrv::gtid
using uuid = boost::uuids::uuid;

inline constexpr std::size_t tag_max_length{32U};
using tag_storage = util::bounded_string_storage<tag_max_length>;

using gno_t = std::uint64_t;
inline constexpr gno_t min_gno{1ULL};
inline constexpr gno_t max_gno{
std::numeric_limits<std::make_signed_t<gno_t>>::max()};

} // namespace binsrv::gtids

#endif // BINSRV_GTID_COMMON_TYPES_HPP
#endif // BINSRV_GTIDS_COMMON_TYPES_HPP
49 changes: 49 additions & 0 deletions src/binsrv/gtids/gtid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2023-2024 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "binsrv/gtids/gtid.hpp"

#include <ostream>
#include <stdexcept>

#include <boost/uuid/uuid_io.hpp>

#include "binsrv/gtids/common_types.hpp"

#include "util/exception_location_helpers.hpp"

namespace binsrv::gtids {

void gtid::validate_components() {
if (uuid_.is_nil()) {
util::exception_location().raise<std::invalid_argument>(
"uuid must not be nil");
}
if (gno_ < min_gno || gno_ > max_gno) {
util::exception_location().raise<std::invalid_argument>(
"gno is out of range");
}
}

std::ostream &operator<<(std::ostream &output, const gtid &obj) {
output << obj.get_uuid();
if (obj.has_tag()) {
output << gtid::tag_separator << obj.get_tag();
}
output << gtid::gno_separator << obj.get_gno();
return output;
}

} // namespace binsrv::gtids
67 changes: 67 additions & 0 deletions src/binsrv/gtids/gtid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2023-2024 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef BINSRV_GTIDS_GTID_HPP
#define BINSRV_GTIDS_GTID_HPP

#include "binsrv/gtids/gtid_fwd.hpp" // IWYU pragma: export

#include "binsrv/gtids/common_types.hpp"
#include "binsrv/gtids/tag.hpp"

namespace binsrv::gtids {

class gtid {
public:
static constexpr char tag_separator{':'};
static constexpr char gno_separator{':'};

gtid() = default;

// NOLINTNEXTLINE(modernize-pass-by-value)
gtid(const uuid &uuid_component, const tag &tag_component,
gno_t gno_component)
: uuid_{uuid_component}, tag_{tag_component}, gno_{gno_component} {
validate_components();
}

gtid(const uuid &uuid_component, gno_t gno_component)
: uuid_{uuid_component}, tag_{}, gno_{gno_component} {
validate_components();
}

[[nodiscard]] bool is_empty() const noexcept { return gno_ == 0ULL; }

[[nodiscard]] const uuid &get_uuid() const noexcept { return uuid_; }

[[nodiscard]] bool has_tag() const noexcept { return !tag_.is_empty(); }
[[nodiscard]] const tag &get_tag() const noexcept { return tag_; }

[[nodiscard]] gno_t get_gno() const noexcept { return gno_; }

[[nodiscard]] friend bool operator==(const gtid &first,
const gtid &second) noexcept = default;

private:
uuid uuid_{};
tag tag_{};
gno_t gno_{};

void validate_components();
};

} // namespace binsrv::gtids

#endif // BINSRV_GTIDS_GTID_HPP
Loading