MySQL 9.6.0
Source Code Documentation
gtid.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_GTIDS_GTID_H
25#define MYSQL_GTIDS_GTID_H
26
27/// @file
28/// Experimental API header
29
30#include <cassert> // assert
31#include <concepts> // derived_from
32#include <cstddef> // size_t
33#include <stdexcept> // domain_error
34#include <string_view> // hash
35#include "mysql/gtids/sequence_number.h" // Sequence_number
36#include "mysql/gtids/tag.h" // Tag
37#include "mysql/gtids/tsid.h" // Tsid
38#include "mysql/utils/call_and_catch.h" // call_and_catch
39#include "mysql/utils/return_status.h" // Return_status
40#include "mysql/uuids/uuid.h" // Uuid
41
42/// @addtogroup GroupLibsMysqlGtids
43/// @{
44
45namespace mysql::gtids {
46
47namespace detail {
48/// Top of the hierarchy
49class Gtid_base {};
50} // namespace detail
51
52template <class Test>
53concept Is_gtid = std::derived_from<Test, detail::Gtid_base>;
54
55namespace detail {
56
57/// Base class for classes representing a single Gtid, parameterized by the type
58/// of the Tsid.
59template <Is_tsid Tsid_tp>
60class Gtid_interface : public Gtid_base {
61 protected:
62 /// Construct a new object from the given Uuid, Tag, and Sequence_number.
63 ///
64 /// @throw std::domain_error if the given number is out of range.
66 const Is_tag auto &tag,
67 Sequence_number sequence_number)
68 : m_tsid(uuid, tag), m_sequence_number(sequence_number) {
69 assert_sequence_number(sequence_number);
70 }
71
72 /// Construct a new object from the given Uuid and Sequence_number, using an
73 /// empty tag.
74 ///
75 /// @throw std::domain_error if the given number is out of range.
77 Sequence_number sequence_number)
78 : m_tsid(uuid), m_sequence_number(sequence_number) {
79 assert_sequence_number(sequence_number);
80 }
81
82 /// Construct a new object from the given Tsid and Sequence_number.
83 ///
84 /// @throw std::domain_error if the given number is out of range.
85 explicit Gtid_interface(const Is_tsid auto &tsid,
86 Sequence_number sequence_number)
87 : m_tsid(tsid), m_sequence_number(sequence_number) {
88 assert_sequence_number(sequence_number);
89 }
90
91 public:
92 /// Construct a new, uninitialized object. Note that this must not initialize
93 /// any members because we need the subclass Gtid_trivial to satisfy
94 /// std::is_trivially_default_constructible.
95 Gtid_interface() = default;
96
97 /// Construct a new object by copying the given Gtid.
98 explicit Gtid_interface(const Is_gtid auto &gtid)
100
101 /// Return const reference to the Tsid.
102 [[nodiscard]] const auto &tsid() const { return m_tsid; }
103
104 /// Return non-const reference to the Tsid.
105 [[nodiscard]] auto &tsid() { return m_tsid; }
106
107 /// Return const reference to the Uuid.
108 [[nodiscard]] const auto &uuid() const { return m_tsid.uuid(); }
109
110 /// Return non-const reference to the Uuid.
111 [[nodiscard]] auto &uuid() { return m_tsid.uuid(); }
112
113 /// Return const reference to the Tag.
114 [[nodiscard]] const auto &tag() const { return m_tsid.tag(); }
115
116 /// Return non-const reference to the Tag.
117 [[nodiscard]] auto &tag() { return m_tsid.tag(); }
118
119 /// Return the Sequence_number.
120 [[nodiscard]] Sequence_number get_sequence_number() const {
121 return m_sequence_number;
122 }
123
124 /// Set and validate the Sequence_number.
125 ///
126 /// @throw std::domain_error if the given number is out of range.
127 void throwing_set_sequence_number(const Sequence_number &sequence_number) {
128 assert_sequence_number(sequence_number);
129 m_sequence_number = sequence_number;
130 }
131
132 /// Set and validate the Sequence_number.
133 ///
134 /// @return ok on success; error if the given number is out of range.
135 [[nodiscard]] auto set_sequence_number(
136 const Sequence_number &sequence_number) {
137 return mysql::utils::call_and_catch([&sequence_number, this] {
138 this->throwing_set_sequence_number(sequence_number);
139 });
140 }
141
142 /// Copy from other to this.
143 ///
144 /// @return Currently `void`. If we introduce allocating tag types, the
145 /// allocation may fail, in which case this will return Return_status.
146 [[nodiscard]] auto assign(const Is_gtid auto &other) {
147#ifndef NDEBUG
148 assert_sequence_number(other.sequence_number);
149#endif
150 m_sequence_number = other.sequence_number;
151
152 // Assignment may fail if the tag is allocating and an out-of-memory
153 // condition occurs. If the tag is not allocating, other.assign returns void
154 // and then this function returns void.
155 return tsid().assign(other.tsid());
156 }
157
158 private:
159 /// Assert that the sequence number is in range.
160 ///
161 /// @throw std::domain_error if the given number is out of range.
162 void assert_sequence_number(Sequence_number sequence_number) const {
163 if (sequence_number < sequence_number_min) {
164 throw std::domain_error{"Out-of-range: sequence_number < minimum"};
165 }
166 if (sequence_number > sequence_number_max_inclusive) {
167 throw std::domain_error{"Out-of-range: sequence_number > maximum"};
168 }
169 }
170
171 /// The Tsid object.
172 Tsid_tp m_tsid;
173
174 /// The Sequence_number.
175 ///
176 /// This must not be initialized by default, because this is a base class for
177 /// of Gtid_trivial, and initializing it would make Gtid_trivial violate
178 /// std::is_trivially_default_constructible.
180}; // class Gtid_base
181
182} // namespace detail
183
184/// Represents a single Gtid, consisting of a Tsid and a Sequence_number.
185///
186/// The default constructor for this class will initialize the sequence number
187/// to sequence_number_min, the tag to empty, and leave the UUID uninitialized.
188/// Thus, it does not satisfy std::is_trivially_default_constructible.
189class Gtid : public detail::Gtid_interface<Tsid> {
190 private:
192
193 protected:
194 /// Construct a new object from the given Uuid, Tag, and Sequence_number.
195 ///
196 /// @throw std::domain_error if the given number is out of range.
197 explicit Gtid(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag,
198 Sequence_number sequence_number)
199 : Base_t(uuid, tag, sequence_number) {}
200
201 /// Construct a new object from the given Uuid and Sequence_number, using an
202 /// empty tag.
203 ///
204 /// @throw std::domain_error if the given number is out of range.
205 explicit Gtid(const mysql::uuids::Uuid &uuid, Sequence_number sequence_number)
206 : Base_t(uuid, sequence_number) {}
207
208 /// Construct a new object from the given Tsid and Sequence_number.
209 ///
210 /// @throw std::domain_error if the given number is out of range.
211 explicit Gtid(const Is_tsid auto &tsid, Sequence_number sequence_number)
212 : Base_t(tsid, sequence_number) {}
213
214 public:
215 /// Construct a new Gtid, leaving the UUID uninitialized, setting the tag to
216 /// empty, and the sequence number to 1.
218
219 /// Construct a new object by copying the given Gtid.
220 explicit Gtid(const Is_gtid auto &gtid) : Base_t(gtid) {}
221
222 /// Return a new object constructed from the given Uuid, Tag, and
223 /// Sequence_number.
224 ///
225 /// Use in exception-free code only if the sequence_number has been validated
226 /// already.
227 ///
228 /// @throw std::domain_error if the given number is out of range.
230 const Is_tag auto &tag,
231 Sequence_number sequence_number) {
232 return Gtid(uuid, tag, sequence_number);
233 }
234
235 /// Return a new object constructed from the given Uuid and Sequence_number,
236 /// using an empty tag.
237 ///
238 /// Use in exception-free code only if the sequence_number has been validated
239 /// already.
240 ///
241 /// @throw std::domain_error if the given number is out of range.
243 Sequence_number sequence_number) {
244 return Gtid(uuid, sequence_number);
245 }
246
247 /// Return a new object constructed from the given Tsid and Sequence_number.
248 ///
249 /// Use in exception-free code only if the sequence_number has been validated
250 /// already.
251 ///
252 /// @throw std::domain_error if the given number is out of range.
253 static Gtid throwing_make(const Is_tsid auto &tsid,
254 Sequence_number sequence_number) {
255 return Gtid(tsid, sequence_number);
256 }
257};
258
259/// Represents a single Gtid, consisting of a Tsid and a Sequence_number.
260///
261/// The default constructor leaves all fields uninitialized. Thus, it satisfies
262/// std::is_trivially_default_constructible.
263class Gtid_trivial : public detail::Gtid_interface<Tsid_trivial> {
264 private:
266
267 protected:
268 /// Construct a new object from the given Uuid, Tag, and Sequence_number. This
269 /// throws an exception if the sequence number is out of range.
270 explicit Gtid_trivial(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag,
271 Sequence_number sequence_number)
272 : Base_t(uuid, tag, sequence_number) {}
273
274 /// Construct a new object from the given Uuid and Sequence_number, using an
275 /// empty tag. This throws an exception if the sequence number is out of
276 /// range.
278 Sequence_number sequence_number)
279 : Base_t(uuid, sequence_number) {}
280
281 /// Construct a new object from the given Tsid and Sequence_number. This
282 /// throws an exception if the sequence number is out of range.
283 explicit Gtid_trivial(const Is_tsid auto &tsid,
284 Sequence_number sequence_number)
285 : Base_t(tsid, sequence_number) {}
286
287 public:
288 /// Construct a new Gtid with all fields uninitialized.
289 Gtid_trivial() = default;
290
291 /// Construct a new object by copying the given Gtid.
292 explicit Gtid_trivial(const Is_gtid auto &gtid) : Base_t(gtid) {}
293
294 /// Return a new object constructed from the given Uuid, Tag, and
295 /// Sequence_number. This throws an exception if the sequence number is out of
296 /// range: use in exception-free code only if the sequence_number has been
297 /// validated already.
299 const Is_tag auto &tag,
300 Sequence_number sequence_number) {
301 return Gtid_trivial(uuid, tag, sequence_number);
302 }
303
304 /// Return a new object constructed from the given Uuid and Sequence_number,
305 /// using an empty tag. This throws an exception if the sequence number is out
306 /// of range: use in exception-free code only if the sequence_number has been
307 /// validated already.
309 Sequence_number sequence_number) {
310 return Gtid_trivial(uuid, sequence_number);
311 }
312
313 /// Return a new object constructed from the given Tsid and Sequence_number.
314 /// This throws an exception if the sequence number is out of range: use in
315 /// exception-free code only if the sequence_number has been validated
316 /// already.
318 Sequence_number sequence_number) {
319 return Gtid_trivial(tsid, sequence_number);
320 }
321};
322
323bool operator==(const Is_gtid auto &gtid1, const Is_gtid auto &gtid2) {
324 return gtid1.tsid() == gtid2.tsid() &&
325 gtid1.get_sequence_number() == gtid2.get_sequence_number();
326}
327
328bool operator!=(const Is_gtid auto &gtid1, const Is_gtid auto &gtid2) {
329 return !(gtid1 == gtid2);
330}
331
332auto operator<=>(const Is_gtid auto &gtid1, const Is_gtid auto &gtid2) {
333 auto tsid_cmp = gtid1.tsid() <=> gtid2.tsid();
334 if (tsid_cmp != 0) return tsid_cmp;
335 return gtid1.get_sequence_number() <=> gtid2.get_sequence_number();
336}
337
338} // namespace mysql::gtids
339
340/// Define std::hash<Gtid>.
341//
342// The recommended way to do this is to use a syntax that places the namespace
343// as a name qualifier, like `struct std::hash<Gtid_t>`, rather than enclose the
344// entire struct in a namespace block.
345//
346// However, gcc 11.4.0 on ARM has a bug that makes it produce "error:
347// redefinition of 'struct std::hash<_Tp>'" when using that syntax. See
348// https://godbolt.org/z/xo1v8rf6n vs https://godbolt.org/z/GzvrMese1 .
349//
350// Todo: Switch to the recommended syntax once we drop support for compilers
351// having this bug.
352//
353// clang-tidy warns when not using the recommended syntax
354// NOLINTBEGIN(cert-dcl58-cpp)
355namespace std {
356template <mysql::gtids::Is_gtid Gtid_t>
357struct hash<Gtid_t> {
358 std::size_t operator()(const Gtid_t &gtid) const {
359 return std::hash(gtid.tsid()) ^ std::hash(gtid.sequence_number());
360 }
361};
362} // namespace std
363// NOLINTEND(cert-dcl58-cpp)
364
365// addtogroup GroupLibsMysqlGtids
366/// @}
367
368#endif // ifndef MYSQL_GTIDS_GTID_H
Experimental API header.
Represents a single Gtid, consisting of a Tsid and a Sequence_number.
Definition: gtid.h:263
static Gtid_trivial throwing_make(const Is_tsid auto &tsid, Sequence_number sequence_number)
Return a new object constructed from the given Tsid and Sequence_number.
Definition: gtid.h:317
Gtid_trivial(const Is_gtid auto &gtid)
Construct a new object by copying the given Gtid.
Definition: gtid.h:292
Gtid_trivial(const mysql::uuids::Uuid &uuid, Sequence_number sequence_number)
Construct a new object from the given Uuid and Sequence_number, using an empty tag.
Definition: gtid.h:277
static Gtid_trivial throwing_make(const mysql::uuids::Uuid &uuid, Sequence_number sequence_number)
Return a new object constructed from the given Uuid and Sequence_number, using an empty tag.
Definition: gtid.h:308
Gtid_trivial()=default
Construct a new Gtid with all fields uninitialized.
static Gtid_trivial throwing_make(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag, Sequence_number sequence_number)
Return a new object constructed from the given Uuid, Tag, and Sequence_number.
Definition: gtid.h:298
Gtid_trivial(const Is_tsid auto &tsid, Sequence_number sequence_number)
Construct a new object from the given Tsid and Sequence_number.
Definition: gtid.h:283
Gtid_trivial(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag, Sequence_number sequence_number)
Construct a new object from the given Uuid, Tag, and Sequence_number.
Definition: gtid.h:270
Represents a single Gtid, consisting of a Tsid and a Sequence_number.
Definition: gtid.h:189
Gtid(const Is_tsid auto &tsid, Sequence_number sequence_number)
Construct a new object from the given Tsid and Sequence_number.
Definition: gtid.h:211
static Gtid throwing_make(const mysql::uuids::Uuid &uuid, Sequence_number sequence_number)
Return a new object constructed from the given Uuid and Sequence_number, using an empty tag.
Definition: gtid.h:242
static Gtid throwing_make(const Is_tsid auto &tsid, Sequence_number sequence_number)
Return a new object constructed from the given Tsid and Sequence_number.
Definition: gtid.h:253
Gtid(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag, Sequence_number sequence_number)
Construct a new object from the given Uuid, Tag, and Sequence_number.
Definition: gtid.h:197
Gtid(const Is_gtid auto &gtid)
Construct a new object by copying the given Gtid.
Definition: gtid.h:220
Gtid()
Construct a new Gtid, leaving the UUID uninitialized, setting the tag to empty, and the sequence numb...
Definition: gtid.h:217
Gtid(const mysql::uuids::Uuid &uuid, Sequence_number sequence_number)
Construct a new object from the given Uuid and Sequence_number, using an empty tag.
Definition: gtid.h:205
static Gtid throwing_make(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag, Sequence_number sequence_number)
Return a new object constructed from the given Uuid, Tag, and Sequence_number.
Definition: gtid.h:229
Top of the hierarchy.
Definition: gtid.h:49
Base class for classes representing a single Gtid, parameterized by the type of the Tsid.
Definition: gtid.h:60
auto & tsid()
Return non-const reference to the Tsid.
Definition: gtid.h:105
const auto & uuid() const
Return const reference to the Uuid.
Definition: gtid.h:108
void assert_sequence_number(Sequence_number sequence_number) const
Assert that the sequence number is in range.
Definition: gtid.h:162
void throwing_set_sequence_number(const Sequence_number &sequence_number)
Set and validate the Sequence_number.
Definition: gtid.h:127
Gtid_interface(const Is_tsid auto &tsid, Sequence_number sequence_number)
Construct a new object from the given Tsid and Sequence_number.
Definition: gtid.h:85
const auto & tsid() const
Return const reference to the Tsid.
Definition: gtid.h:102
const auto & tag() const
Return const reference to the Tag.
Definition: gtid.h:114
Tsid_tp m_tsid
The Tsid object.
Definition: gtid.h:172
auto & uuid()
Return non-const reference to the Uuid.
Definition: gtid.h:111
auto & tag()
Return non-const reference to the Tag.
Definition: gtid.h:117
Gtid_interface()=default
Construct a new, uninitialized object.
Gtid_interface(const mysql::uuids::Uuid &uuid, Sequence_number sequence_number)
Construct a new object from the given Uuid and Sequence_number, using an empty tag.
Definition: gtid.h:76
Gtid_interface(const mysql::uuids::Uuid &uuid, const Is_tag auto &tag, Sequence_number sequence_number)
Construct a new object from the given Uuid, Tag, and Sequence_number.
Definition: gtid.h:65
auto assign(const Is_gtid auto &other)
Copy from other to this.
Definition: gtid.h:146
Gtid_interface(const Is_gtid auto &gtid)
Construct a new object by copying the given Gtid.
Definition: gtid.h:98
auto set_sequence_number(const Sequence_number &sequence_number)
Set and validate the Sequence_number.
Definition: gtid.h:135
Sequence_number get_sequence_number() const
Return the Sequence_number.
Definition: gtid.h:120
Sequence_number m_sequence_number
The Sequence_number.
Definition: gtid.h:179
Holds data for a UUID.
Definition: uuid.h:49
Definition: gtid.h:53
True if Test is one of the tag classes.
Definition: tag.h:192
Definition: tsid.h:50
Experimental API header.
Experimental API header.
Definition: fts0fts.cc:236
Definition: gtid.h:45
uint64_t Sequence_number
The type of the sequence number component of a GTID.
Definition: sequence_number.h:39
constexpr Sequence_number sequence_number_max_inclusive
The largest allowed value for a GTID sequence number.
Definition: sequence_number.h:46
auto operator<=>(const Is_gtid auto &gtid1, const Is_gtid auto &gtid2)
Definition: gtid.h:332
constexpr Sequence_number sequence_number_min
The smallest allowed value for a GTID sequence number.
Definition: sequence_number.h:50
bool operator!=(const Is_gtid auto &gtid1, const Is_gtid auto &gtid2)
Definition: gtid.h:328
bool operator==(const Is_gtid auto &gtid1, const Is_gtid auto &gtid2)
Definition: gtid.h:323
Define std::hash<Gtid>.
Definition: gtid.h:355
Experimental API header.
Experimental API header.
std::size_t operator()(const Gtid_t &gtid) const
Definition: gtid.h:358
Experimental API header.