MySQL 26.7.0
Source Code Documentation
rpl_gtid.h
Go to the documentation of this file.
1/* Copyright (c) 2011, 2026, 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 RPL_GTID_H_INCLUDED
25#define RPL_GTID_H_INCLUDED
26
27#include <atomic>
28#include <cinttypes>
29#include <list>
30#include <mutex> // std::adopt_lock_t
31#include <optional>
32#include <vector>
33
34#include "map_helpers.h"
35#include "my_dbug.h"
36#include "my_thread_local.h"
37#include "mysql/binlog/event/compression/base.h" // mysql::binlog::event::compression::type
38#include "mysql/gtid/global.h"
39#include "mysql/gtid/gtid.h"
40#include "mysql/gtid/tsid.h"
42#include "mysql/gtid/uuid.h"
44#include "mysql/psi/mysql_rwlock.h" // mysql_rwlock_t
45#include "mysql/strings/m_ctype.h" // my_isspace
47#include "prealloced_array.h" // Prealloced_array
48#include "sql/changestreams/index/locked_sidno_set.h" // Locked_sidno_set
50#include "sql/rpl_reporting.h" // MAX_SLAVE_ERRMSG
51#include "template_utils.h"
52
53class Table_ref;
54class THD;
55
56/**
57 Report an error from code that can be linked into either the server
58 or mysqlbinlog. There is no common error reporting mechanism, so we
59 have to duplicate the error message (write it out in the source file
60 for mysqlbinlog, write it in share/messages_to_clients.txt for the
61 server).
62
63 @param MYSQLBINLOG_ERROR arguments to mysqlbinlog's 'error'
64 function, including the function call parentheses
65 @param SERVER_ERROR arguments to my_error, including the function
66 call parentheses.
67*/
68#ifndef MYSQL_SERVER
69#define BINLOG_ERROR(MYSQLBINLOG_ERROR, SERVER_ERROR) error MYSQLBINLOG_ERROR
70#else
71#define BINLOG_ERROR(MYSQLBINLOG_ERROR, SERVER_ERROR) my_error SERVER_ERROR
72#endif
73
80
81/**
82 This macro is used to check that the given character, pointed to by the
83 character pointer, is a space or not.
84*/
85#define SKIP_WHITESPACE() \
86 while (my_isspace(&my_charset_utf8mb3_general_ci, *s)) s++
87
88/*
89 This macro must be used to filter out parts of the code that
90 is not used now but may be useful in future. In other words,
91 we want to keep such code until we make up our minds on whether
92 it should be removed or not.
93*/
94#undef NON_DISABLED_GTID
95
96/*
97 This macro must be used to filter out parts of the code that
98 is not used now but we are not sure if there is a bug around
99 them. In other words, we want to keep such code until we have
100 time to investigate it.
101*/
102#undef NON_ERROR_GTID
103
104#ifdef MYSQL_SERVER
105class String;
106class THD;
107#endif // ifdef MYSQL_SERVER
108
109/// Type of SIDNO (source ID number, first component of GTID)
111
112/// GNO, the second (numeric) component of a GTID, is an alias of
113/// mysql::gtid::gno_t
116
117namespace cs::index {
118
119class Locked_sidno_set;
120
121} // namespace cs::index
122
123/**
124 Generic return type for many functions that can succeed or fail.
125
126 This is used in conjunction with the macros below for functions where
127 the return status either indicates "success" or "failure". It
128 provides the following features:
129
130 - The macros can be used to conveniently propagate errors from
131 called functions back to the caller.
132
133 - If a function is expected to print an error using my_error before
134 it returns an error status, then the macros assert that my_error
135 has been called.
136
137 - Does a DBUG_PRINT before returning failure.
138*/
140 /// The function completed successfully.
142 /// The function completed with error but did not report it.
144 /// The function completed with error and has called my_error.
147
148/**
149 @def __CHECK_RETURN_STATUS
150 Lowest level macro used in the PROPAGATE_* and RETURN_* macros
151 below.
152
153 If NDEBUG is defined, does nothing. Otherwise, if STATUS is
154 RETURN_STATUS_OK, does nothing; otherwise, make a dbug printout and
155 (if ALLOW_UNREPORTED==0) assert that STATUS !=
156 RETURN_STATUS_UNREPORTED.
157
158 @param STATUS The status to return.
159 @param ACTION A text that describes what we are doing: either
160 "Returning" or "Propagating" (used in DBUG_PRINT macros)
161 @param STATUS_NAME The stringified version of the STATUS (used in
162 DBUG_PRINT macros).
163 @param ALLOW_UNREPORTED If false, the macro asserts that STATUS is
164 not RETURN_STATUS_UNREPORTED_ERROR.
165*/
166#ifdef NDEBUG
167#define __CHECK_RETURN_STATUS(STATUS, ACTION, STATUS_NAME, ALLOW_UNREPORTED)
168#else
169extern void check_return_status(enum_return_status status, const char *action,
170 const char *status_name, int allow_unreported);
171#define __CHECK_RETURN_STATUS(STATUS, ACTION, STATUS_NAME, ALLOW_UNREPORTED) \
172 check_return_status(STATUS, ACTION, STATUS_NAME, ALLOW_UNREPORTED);
173#endif
174/**
175 Low-level macro that checks if STATUS is RETURN_STATUS_OK; if it is
176 not, then RETURN_VALUE is returned.
177 @see __DO_RETURN_STATUS
178*/
179#define __PROPAGATE_ERROR(STATUS, RETURN_VALUE, ALLOW_UNREPORTED) \
180 do { \
181 enum_return_status __propagate_error_status = STATUS; \
182 if (__propagate_error_status != RETURN_STATUS_OK) { \
183 __CHECK_RETURN_STATUS(__propagate_error_status, "Propagating", #STATUS, \
184 ALLOW_UNREPORTED); \
185 return RETURN_VALUE; \
186 } \
187 } while (0)
188/// Low-level macro that returns STATUS. @see __DO_RETURN_STATUS
189#define __RETURN_STATUS(STATUS, ALLOW_UNREPORTED) \
190 do { \
191 enum_return_status __return_status_status = STATUS; \
192 __CHECK_RETURN_STATUS(__return_status_status, "Returning", #STATUS, \
193 ALLOW_UNREPORTED); \
194 return __return_status_status; \
195 } while (0)
196/**
197 If STATUS (of type enum_return_status) returns RETURN_STATUS_OK,
198 does nothing; otherwise, does a DBUG_PRINT and returns STATUS.
199*/
200#define PROPAGATE_ERROR(STATUS) \
201 __PROPAGATE_ERROR(STATUS, __propagate_error_status, true)
202/**
203 If STATUS (of type enum_return_status) returns RETURN_STATUS_OK,
204 does nothing; otherwise asserts that STATUS ==
205 RETURN_STATUS_REPORTED_ERROR, does a DBUG_PRINT, and returns STATUS.
206*/
207#define PROPAGATE_REPORTED_ERROR(STATUS) \
208 __PROPAGATE_ERROR(STATUS, __propagate_error_status, false)
209/**
210 If STATUS (of type enum_return_status) returns RETURN_STATUS_OK,
211 does nothing; otherwise asserts that STATUS ==
212 RETURN_STATUS_REPORTED_ERROR, does a DBUG_PRINT, and returns 1.
213*/
214#define PROPAGATE_REPORTED_ERROR_INT(STATUS) __PROPAGATE_ERROR(STATUS, 1, false)
215/**
216 If STATUS returns something else than RETURN_STATUS_OK, does a
217 DBUG_PRINT. Then, returns STATUS.
218*/
219#define RETURN_STATUS(STATUS) __RETURN_STATUS(STATUS, true)
220/**
221 Asserts that STATUS is not RETURN_STATUS_UNREPORTED_ERROR. Then, if
222 STATUS is RETURN_STATUS_REPORTED_ERROR, does a DBUG_PRINT. Then,
223 returns STATUS.
224*/
225#define RETURN_REPORTED_STATUS(STATUS) __RETURN_STATUS(STATUS, false)
226/// Returns RETURN_STATUS_OK.
227#define RETURN_OK return RETURN_STATUS_OK
228/// Does a DBUG_PRINT and returns RETURN_STATUS_REPORTED_ERROR.
229#define RETURN_REPORTED_ERROR RETURN_STATUS(RETURN_STATUS_REPORTED_ERROR)
230/// Does a DBUG_PRINT and returns RETURN_STATUS_UNREPORTED_ERROR.
231#define RETURN_UNREPORTED_ERROR RETURN_STATUS(RETURN_STATUS_UNREPORTED_ERROR)
232
233/**
234 enum to map the result of Uuid::parse to the above Macros
235*/
238 if (status == 0)
239 RETURN_OK;
240 else
242}
243
244/**
245 Possible values for ENFORCE_GTID_CONSISTENCY.
246*/
252/**
253 Strings holding the enumeration values for
254 gtid_consistency_mode_names. Use get_gtid_consistency_mode_string
255 instead of accessing this directly.
256*/
257extern const char *gtid_consistency_mode_names[];
258/**
259 Current value for ENFORCE_GTID_CONSISTENCY.
260 Don't use this directly; use get_gtid_consistency_mode.
261*/
262extern ulong _gtid_consistency_mode;
263/**
264 Return the current value of ENFORCE_GTID_CONSISTENCY.
265
266 Caller must hold global_tsid_lock.rdlock.
267*/
269/// Return the given GTID_CONSISTENCY_MODE as a string.
273}
274/**
275 Return the current value of ENFORCE_GTID_CONSISTENCY as a string.
276
277 Caller must hold global_tsid_lock.rdlock.
278*/
281}
282
283/// One-past-the-max value of GNO
284const rpl_gno GNO_END = INT64_MAX;
285/// If the GNO goes above the number, generate a warning.
287/// The length of MAX_GNO when printed in decimal.
288const int MAX_GNO_TEXT_LENGTH = 19;
289/// The maximal possible length of thread_id when printed in decimal.
291
292/**
293 Parse a GNO from a string.
294
295 @param s Pointer to the string. *s will advance to the end of the
296 parsed GNO, if a correct GNO is found.
297 @retval GNO if a correct GNO (i.e., 0 or positive number) was found.
298 @retval -1 otherwise.
299*/
300rpl_gno parse_gno(const char **s);
301/**
302 Formats a GNO as a string.
303
304 @param s The buffer.
305 @param gno The GNO.
306 @return Length of the generated string.
307*/
308int format_gno(char *s, rpl_gno gno);
309
311
312/**
313 This has the functionality of mysql_rwlock_t, with two differences:
314 1. It has additional operations to check if the read and/or write lock
315 is held at the moment.
316 2. It is wrapped in an object-oriented interface.
317
318 Note that the assertions do not check whether *this* thread has
319 taken the lock (that would be more complicated as it would require a
320 dynamic data structure). Luckily, it is still likely that the
321 assertions find bugs where a thread forgot to take a lock, because
322 most of the time most locks are only used by one thread at a time.
323
324 The assertions are no-ops when DBUG is off.
325*/
327 public:
328 /// Initialize this Checkable_rwlock.
330#if defined(HAVE_PSI_INTERFACE)
331 PSI_rwlock_key psi_key [[maybe_unused]] = 0
332#endif
333 ) {
334#ifndef NDEBUG
335 m_lock_state.store(0);
336 m_dbug_trace = true;
337#else
338 m_is_write_lock = false;
339#endif
340#if defined(HAVE_PSI_INTERFACE)
341 mysql_rwlock_init(psi_key, &m_rwlock);
342#else
344#endif
345 }
346 /// Destroy this Checkable_lock.
348
355 };
356
357 /**
358 RAII class to acquire a lock for the duration of a block.
359 */
360 class Guard {
363
364 public:
365 /**
366 Create a guard, and optionally acquire a lock on it.
367 */
371 switch (lock_type) {
372 case READ_LOCK:
373 rdlock();
374 break;
375 case WRITE_LOCK:
376 wrlock();
377 break;
378 case TRY_READ_LOCK:
379 tryrdlock();
380 break;
381 case TRY_WRITE_LOCK:
382 trywrlock();
383 break;
384 case NO_LOCK:
385 break;
386 }
387 }
388
389 /**
390 Create a guard, assuming the caller already holds a lock on it.
391 */
393 std::adopt_lock_t t [[maybe_unused]])
394 : m_lock(lock), m_lock_type(lock_type) {
396 switch (lock_type) {
397 case READ_LOCK:
398 lock.assert_some_rdlock();
399 break;
400 case WRITE_LOCK:
401 lock.assert_some_wrlock();
402 break;
403 case TRY_READ_LOCK:
404 case TRY_WRITE_LOCK:
405 case NO_LOCK:
406 break;
407 }
408 }
409
410 /// Objects of this class should not be copied or moved.
411 Guard(Guard const &copy) = delete;
412 Guard(Guard const &&copy) = delete;
413
414 /// Unlock on destruct.
418 }
419
420 /// Acquire the read lock.
421 void rdlock() {
423 assert(m_lock_type == NO_LOCK);
424 m_lock.rdlock();
426 }
427
428 /// Acquire the write lock.
429 void wrlock() {
431 assert(m_lock_type == NO_LOCK);
432 m_lock.wrlock();
434 }
435
436 /**
437 Try to acquire the write lock, and fail if it cannot be
438 immediately granted.
439 */
440 int trywrlock() {
442 assert(m_lock_type == NO_LOCK);
443 int ret = m_lock.trywrlock();
444 if (ret == 0) m_lock_type = WRITE_LOCK;
445 return ret;
446 }
447
448 /**
449 Try to acquire a read lock, and fail if it cannot be
450 immediately granted.
451 */
452 int tryrdlock() {
454 assert(m_lock_type == NO_LOCK);
455 int ret = m_lock.tryrdlock();
456 if (ret == 0) m_lock_type = READ_LOCK;
457 return ret;
458 }
459
460 /// Unlock the lock.
461 void unlock() {
463 assert(m_lock_type != NO_LOCK);
464 m_lock.unlock();
465 }
466
467 /// Unlock the lock, if it was acquired by this guard.
470 if (m_lock_type != NO_LOCK) unlock();
471 }
472
473 /// Return the underlying Checkable_rwlock object.
474 Checkable_rwlock &get_lock() const { return m_lock; }
475
476 /// Return true if this object is read locked.
477 bool is_rdlocked() const { return m_lock_type == READ_LOCK; }
478
479 /// Return true if this object is write locked.
480 bool is_wrlocked() const { return m_lock_type == WRITE_LOCK; }
481
482 /// Return true if this object is either read locked or write locked.
483 bool is_locked() const { return m_lock_type != NO_LOCK; }
484 };
485
486 /// Acquire the read lock.
487 inline void rdlock() {
490#ifndef NDEBUG
491 if (m_dbug_trace) DBUG_PRINT("info", ("%p.rdlock()", this));
492 ++m_lock_state;
493#endif
494 }
495 /// Acquire the write lock.
496 inline void wrlock() {
499#ifndef NDEBUG
500 if (m_dbug_trace) DBUG_PRINT("info", ("%p.wrlock()", this));
501 m_lock_state.store(-1);
502#else
503 m_is_write_lock = true;
504#endif
505 }
506 /// Release the lock (whether it is a write or read lock).
507 inline void unlock() {
509#ifndef NDEBUG
510 if (m_dbug_trace) DBUG_PRINT("info", ("%p.unlock()", this));
511 int val = m_lock_state.load();
512 if (val > 0)
513 --m_lock_state;
514 else if (val == -1)
515 m_lock_state.store(0);
516 else
517 assert(0);
518#else
519 m_is_write_lock = false;
520#endif
522 }
523 /**
524 Return true if the write lock is held. Must only be called by
525 threads that hold a lock.
526 */
527 inline bool is_wrlock() {
529#ifndef NDEBUG
530 return get_state() == -1;
531#else
532 return m_is_write_lock;
533#endif
534 }
535
536 /**
537 Return 0 if the write lock is held, otherwise an error will be returned.
538 */
539 inline int trywrlock() {
541
542 if (ret == 0) {
544#ifndef NDEBUG
545 if (m_dbug_trace) DBUG_PRINT("info", ("%p.wrlock()", this));
546 m_lock_state.store(-1);
547#else
548 m_is_write_lock = true;
549#endif
550 }
551
552 return ret;
553 }
554
555 /**
556 Return 0 if the read lock is held, otherwise an error will be returned.
557 */
558 inline int tryrdlock() {
560
561 if (ret == 0) {
563#ifndef NDEBUG
564 if (m_dbug_trace) DBUG_PRINT("info", ("%p.rdlock()", this));
565 ++m_lock_state;
566#endif
567 }
568
569 return ret;
570 }
571
572 /// Assert that some thread holds either the read or the write lock.
573 inline void assert_some_lock() const { assert(get_state() != 0); }
574 /// Assert that some thread holds the read lock.
575 inline void assert_some_rdlock() const { assert(get_state() > 0); }
576 /// Assert that some thread holds the write lock.
577 inline void assert_some_wrlock() const { assert(get_state() == -1); }
578 /// Assert that no thread holds the write lock.
579 inline void assert_no_wrlock() const { assert(get_state() >= 0); }
580 /// Assert that no thread holds the read lock.
581 inline void assert_no_rdlock() const { assert(get_state() <= 0); }
582 /// Assert that no thread holds read or write lock.
583 inline void assert_no_lock() const { assert(get_state() == 0); }
584
585#ifndef NDEBUG
586
587 /// If enabled, print any lock/unlock operations to the DBUG trace.
589
590 private:
591 /**
592 The state of the lock:
593 0 - not locked
594 -1 - write locked
595 >0 - read locked by that many threads
596 */
597 std::atomic<int32> m_lock_state;
598 /// Read lock_state atomically and return the value.
599 inline int32 get_state() const { return m_lock_state.load(); }
600
601#else
602
603 private:
604 bool m_is_write_lock;
605
606#endif
607 /// The rwlock.
609};
610
611/// Protects Gtid_state. See comment above gtid_state for details.
613
614/**
615 Class to access the value of @@global.gtid_mode in an efficient and
616 thread-safe manner.
617*/
619 private:
620 std::atomic<int> m_atomic_mode;
621
622 public:
624
625 /**
626 The sys_var framework needs a variable of type ulong to store the
627 value in. The sys_var framework takes the value from there, but
628 we copy it (in the methods of sys_var_gtid_mode) to the atomic
629 value Gtid_mode::mode, and use only that in all other places.
630 */
631 static ulong sysvar_mode;
632
633 /// Possible values for @@global.gtid_mode.
635 /**
636 New transactions are anonymous. Replicated transactions must be
637 anonymous; replicated GTID-transactions generate an error.
638 */
639 OFF = 0,
640 /**
641 New transactions are anonyomus. Replicated transactions can be
642 either anonymous or GTID-transactions.
643 */
645 /**
646 New transactions are GTID-transactions. Replicated transactions
647 can be either anonymous or GTID-transactions.
648 */
650 /**
651 New transactions are GTID-transactions. Replicated transactions
652 must be GTID-transactions; replicated anonymous transactions
653 generate an error.
654 */
655 ON = 3,
657 };
658
659 /**
660 Strings holding the enumeration values for gtid_mode. Use
661 Gtid_mode::get_string instead of accessing this directly.
662 */
663 static const char *names[];
664
665 /**
666 Protects updates to @@global.gtid_mode.
667
668 SET @@global.gtid_mode will try to take the write lock. If the
669 lock is not granted immediately, SET will fail.
670
671 Thus, any other operation can block updates to
672 @@global.gtid_mode by acquiring the read lock.
673 */
675
676 /**
677 Set a new value for @@global.gtid_mode.
678
679 This should only be called from Sys_var_gtid_mode::global_update
680 and gtid_server_init.
681 */
682 void set(value_type value);
683
684 public:
685 /**
686 Return the current gtid_mode as an enumeration value.
687 */
688 value_type get() const;
689
690#ifndef NDEBUG
691 /**
692 Return the current gtid_mode as a string.
693
694 Used only for debugging. Non-debug code typically reads and acts
695 on the enum value before printing it. Then it is better to print
696 the enum value.
697 */
698 const char *get_string() const;
699#endif // ifndef NDEBUG
700
701 /**
702 Return the given string gtid_mode as an enumeration value.
703
704 @param s The string to decode.
705
706 @return A pair, where the first component indicates failure and
707 the second component is the GTID_MODE. Specifically, the first
708 component is false if the string is a valid GTID_MODE, and true if
709 it is not.
710 */
711 static std::pair<bool, value_type> from_string(std::string s);
712
713 /// Return the given gtid_mode as a string.
714 static const char *to_string(value_type value);
715};
716
717std::ostream &operator<<(std::ostream &oss, Gtid_mode::value_type const &mode);
718#ifndef NDEBUG
719/**
720 Typically, code will print Gtid_mode only after reading and acting
721 on the enum value. Then it is better to print the enum value than to
722 read the shared resource again. Hence we enable this only in debug
723 mode, since it makes more sense to just get the string when doing a
724 debug printout.
725*/
726std::ostream &operator<<(std::ostream &oss, Gtid_mode const &mode);
727#endif
728
729/**
730 The one and only instance of Gtid_mode.
731
732 All access to @@global.gtid_mode should use this object.
733*/
735
736/**
737 Represents a bidirectional map between TSID and SIDNO.
738
739 SIDNOs are always numbers greater or equal to 1.
740
741 This data structure OPTIONALLY knows of a read-write lock that
742 protects the number of SIDNOs. The lock is provided by the invoker
743 of the constructor and it is generally the caller's responsibility
744 to acquire the read lock. If the lock is not NULL, access methods
745 assert that the caller already holds the read (or write) lock. If
746 the lock is not NULL and a method of this class grows the number of
747 SIDNOs, then the method temporarily upgrades this lock to a write
748 lock and then degrades it to a read lock again; there will be a
749 short period when the lock is not held at all.
750*/
751class Tsid_map {
752 public:
753 /**
754 Create this Tsid_map.
755
756 @param tsid_lock Read-write lock that protects updates to the
757 number of SIDNOs.
758 */
760
761 /// Destroy this Tsid_map.
762 ~Tsid_map();
763 /**
764 Clears this Tsid_map (for RESET REPLICA)
765
766 @return RETURN_STATUS_OK or RETURN_STAUTS_REPORTED_ERROR
767 */
769
775 using Tsid_to_sidno_it = Tsid_to_sidno_map::const_iterator;
776 using Tsid_ref = std::reference_wrapper<const Tsid>;
777 using Sidno_to_tsid_cont = std::vector<Tsid_ref, Malloc_allocator<Tsid_ref>>;
778
779 /**
780 Add the given TSID to this map if it does not already exist.
781
782 The caller must hold the read lock or write lock on tsid_lock
783 before invoking this function. If the TSID does not exist in this
784 map, it will release the read lock, take a write lock, update the
785 map, release the write lock, and take the read lock again.
786
787 @param tsid The TSID.
788 @retval SIDNO The SIDNO for the TSID (a new SIDNO if the TSID did
789 not exist, an existing if it did exist).
790 @retval negative Error. This function calls my_error.
791 */
792 [[nodiscard]] rpl_sidno add_tsid(const Tsid &tsid);
793 /**
794 Get the SIDNO for a given TSID
795
796 The caller must hold the read lock on tsid_lock before invoking
797 this function.
798
799 @param tsid The TSID.
800 @retval SIDNO if the given TSID exists in this map.
801 @retval 0 if the given TSID does not exist in this map.
802 */
803 rpl_sidno tsid_to_sidno(const Tsid &tsid) const {
804 if (tsid_lock != nullptr) tsid_lock->assert_some_lock();
805 const auto it = _tsid_to_sidno.find(tsid);
806 if (it == _tsid_to_sidno.end()) return 0;
807 return it->second;
808 }
809 /**
810 Get the TSID for a given SIDNO.
811
812 Raises an assertion if the SIDNO is not valid.
813
814 If need_lock is true, acquires tsid_lock->rdlock; otherwise asserts
815 that it is held already.
816
817 @param sidno The SIDNO.
818 @param need_lock If true, and tsid_lock!=NULL, this function will
819 acquire tsid_lock before looking up the sid, and then release
820 it. If false, and tsid_lock!=NULL, this function will assert the
821 tsid_lock is already held. If tsid_lock==NULL, nothing is done
822 w.r.t. locking.
823 @retval NULL The SIDNO does not exist in this map.
824 @retval ref Reference to the TSID. The data is shared with this
825 Tsid_map, so should not be modified. It is safe to read the data
826 even after this Tsid_map is modified, but not if this Tsid_map is
827 destroyed.
828 */
829 const Tsid &sidno_to_tsid(rpl_sidno sidno, bool need_lock = false) const {
830 if (tsid_lock != nullptr) {
831 if (need_lock)
832 tsid_lock->rdlock();
833 else
835 }
836 assert(sidno >= 1 && sidno <= get_max_sidno());
837 const auto &ret = (_sidno_to_tsid[sidno - 1]);
838 if (tsid_lock != nullptr && need_lock) tsid_lock->unlock();
839 return ret.get();
840 }
841
842 /**
843 Returns TSID to SID map
844
845 The caller must hold the read or write lock on tsid_lock before
846 invoking this function.
847
848 @return constant reference to sid_to_sidno container
849 */
850 const Tsid_to_sidno_map &get_sorted_sidno() const { return _sorted; }
851
852 const rpl_sidno &get_sidno(const Tsid_to_sidno_it &it) const {
853 if (tsid_lock != nullptr) tsid_lock->assert_some_lock();
854 return it->second;
855 }
856
857 const Tsid &get_tsid(const Tsid_to_sidno_it &it) const {
858 if (tsid_lock != nullptr) tsid_lock->assert_some_lock();
859 return it->first;
860 }
861
862 /**
863 Return the biggest sidno in this Tsid_map.
864
865 The caller must hold the read or write lock on tsid_lock before
866 invoking this function.
867 */
869 if (tsid_lock != nullptr) tsid_lock->assert_some_lock();
870 return static_cast<rpl_sidno>(_sidno_to_tsid.size());
871 }
872
873 /// Return the tsid_lock.
875
876 /**
877 Deep copy this Tsid_map to dest.
878
879 The caller must hold:
880 * the read lock on this tsid_lock
881 * the write lock on the dest tsid_lock
882 before invoking this function.
883
884 @param[out] dest The Tsid_map to which the tsids and sidnos will
885 be copied.
886 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
887 */
889
890 private:
891 /**
892 Create a Node from the given SIDNO and a TSID and add it to
893 _sidno_to_tsid, _tsid_to_sidno, and _sorted.
894
895 The caller must hold the write lock on tsid_lock before invoking
896 this function.
897
898 @param sidno The SIDNO to add.
899 @param tsid The TSID to add.
900 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
901 */
902 [[nodiscard]] enum_return_status add_node(rpl_sidno sidno, const Tsid &tsid);
903
904 /// Read-write lock that protects updates to the number of SIDNOs.
906
907 /**
908 Array that maps SIDNO to TSID; the element at index N points to a
909 Node with SIDNO N-1.
910 */
913
914 /**
915 Hash that maps TSID to SIDNO.
916 */
918 /**
919 Data structure that maps numbers in the interval [0, get_max_sidno()-1] to
920 SIDNOs, in order of increasing TSID.
921
922 @see Tsid_map::get_sorted_sidno.
923 */
925};
926
928
929/**
930 Represents a growable array where each element contains a mutex and
931 a condition variable.
932
933 Each element can be locked, unlocked, broadcast, or waited for, and
934 it is possible to call "THD::enter_cond" for the condition. The
935 allowed indexes range from 0, inclusive, to get_max_index(),
936 inclusive. Initially there are zero elements (and get_max_index()
937 returns -1); more elements can be allocated by calling
938 ensure_index().
939
940 This data structure has a read-write lock that protects the number
941 of elements. The lock is provided by the invoker of the constructor
942 and it is generally the caller's responsibility to acquire the read
943 lock. Access methods assert that the caller already holds the read
944 (or write) lock. If a method of this class grows the number of
945 elements, then the method temporarily upgrades this lock to a write
946 lock and then degrades it to a read lock again; there will be a
947 short period when the lock is not held at all.
948*/
950 public:
951 /**
952 Create a new Mutex_cond_array.
953
954 @param global_lock Read-write lock that protects updates to the
955 number of elements.
956 */
958 /// Destroy this object.
960 /// Lock the n'th mutex.
961 inline void lock(int n) const {
964 }
965 /// Unlock the n'th mutex.
966 inline void unlock(int n) const {
969 }
970 /// Broadcast the n'th condition.
971 inline void broadcast(int n) const {
973 }
974 /**
975 Assert that this thread owns the n'th mutex.
976 This is a no-op if NDEBUG is on.
977 */
978 inline void assert_owner(int n [[maybe_unused]]) const {
979#ifndef NDEBUG
981#endif
982 }
983 /**
984 Assert that this thread does not own the n'th mutex.
985 This is a no-op if NDEBUG is on.
986 */
987 inline void assert_not_owner(int n [[maybe_unused]]) const {
988#ifndef NDEBUG
990#endif
991 }
992
993 /**
994 Wait for signal on the n'th condition variable.
995
996 The caller must hold the read lock or write lock on tsid_lock, as
997 well as the nth mutex lock, before invoking this function. The
998 tsid_lock will be released, whereas the mutex will be released
999 during the wait and (atomically) re-acquired when the wait ends
1000 or the timeout is reached.
1001
1002 @param[in] thd THD object for the calling thread.
1003 @param[in] sidno Condition variable to wait for.
1004 @param[in] abstime The absolute point in time when the wait times
1005 out and stops, or NULL to wait indefinitely.
1006
1007 @retval false Success.
1008 @retval true Failure: either timeout or thread was killed. If
1009 thread was killed, the error has been generated.
1010 */
1011 inline bool wait(const THD *thd, int sidno, struct timespec *abstime) const {
1012 DBUG_TRACE;
1013 int error = 0;
1014 Mutex_cond *mutex_cond = get_mutex_cond(sidno);
1016 mysql_mutex_assert_owner(&mutex_cond->mutex);
1017 if (is_thd_killed(thd)) return true;
1018 if (abstime != nullptr)
1019 error =
1020 mysql_cond_timedwait(&mutex_cond->cond, &mutex_cond->mutex, abstime);
1021 else
1022 mysql_cond_wait(&mutex_cond->cond, &mutex_cond->mutex);
1023 mysql_mutex_assert_owner(&mutex_cond->mutex);
1024 return is_timeout(error);
1025 }
1026#ifdef MYSQL_SERVER
1027 /// Execute THD::enter_cond for the n'th condition variable.
1028 void enter_cond(THD *thd, int n, PSI_stage_info *stage,
1029 PSI_stage_info *old_stage) const;
1030#endif // ifdef MYSQL_SERVER
1031 /// Return the greatest addressable index in this Mutex_cond_array.
1032 inline int get_max_index() const {
1034 return static_cast<int>(m_array.size() - 1);
1035 }
1036 /**
1037 Grows the array so that the given index fits.
1038
1039 If the array is grown, the global_lock is temporarily upgraded to
1040 a write lock and then degraded again; there will be a
1041 short period when the lock is not held at all.
1042
1043 @param n The index.
1044 @return RETURN_OK or RETURN_REPORTED_ERROR
1045 */
1046 enum_return_status ensure_index(int n);
1047
1048 private:
1049 /**
1050 Return true if the given THD is killed.
1051
1052 @param[in] thd - The thread object
1053 @retval true - thread is killed
1054 false - thread not killed
1055 */
1056 bool is_thd_killed(const THD *thd) const;
1057 /// A mutex/cond pair.
1058 struct Mutex_cond {
1061 };
1062 /// Return the Nth Mutex_cond object
1063 inline Mutex_cond *get_mutex_cond(int n) const {
1064 global_lock->assert_some_lock();
1065 assert(n <= get_max_index());
1066 Mutex_cond *ret = m_array[n];
1067 assert(ret);
1068 return ret;
1069 }
1070 /// Read-write lock that protects updates to the number of elements.
1073};
1074
1075/**
1076 Holds information about a GTID interval: the sidno, the first gno
1077 and the last gno of this interval.
1078*/
1080 /* SIDNO of this Gtid interval. */
1082 /* The first GNO of this Gtid interval. */
1084 /* The last GNO of this Gtid interval. */
1087 sidno = sid_no;
1088 gno_start = start;
1089 gno_end = end;
1090 }
1091};
1092
1093/**
1094 TODO: Move this structure to mysql/binlog/event/control_events.h
1095 when we start using C++11.
1096 Holds information about a GTID: the sidno and the gno.
1097
1098 This is a POD. It has to be a POD because it is part of
1099 Gtid_specification, which has to be a POD because it is used in
1100 THD::variables.
1101*/
1102struct Gtid {
1105 /// SIDNO of this Gtid.
1107 /// GNO of this Gtid.
1109
1110 /// Set both components to 0.
1111 void clear() {
1112 sidno = 0;
1113 gno = 0;
1114 }
1115 /// Set both components to the given, positive values.
1116 void set(rpl_sidno sidno_arg, rpl_gno gno_arg) {
1117 assert(sidno_arg > 0);
1118 assert(gno_arg > 0);
1119 assert(gno_arg < GNO_END);
1120 sidno = sidno_arg;
1121 gno = gno_arg;
1122 }
1123 /**
1124 Return true if sidno is zero (and assert that gno is zero too in
1125 this case).
1126 */
1127 bool is_empty() const {
1128 // check that gno is not set inconsistently
1129 if (sidno <= 0)
1130 assert(gno == 0);
1131 else
1132 assert(gno > 0);
1133 return sidno == 0;
1134 }
1135 /**
1136 The maximal length of the textual representation of a TSID, not
1137 including the terminating '\0'.
1138 */
1139 static const int MAX_TEXT_LENGTH =
1141 /**
1142 Returns true if parse() would succeed, but doesn't store the
1143 result anywhere
1144 */
1145 static bool is_valid(const char *text);
1146 /**
1147 Convert a Gtid to a string.
1148 @param tsid the TSID to use. This overrides the sidno of this Gtid.
1149 @param[out] buf Buffer to store the Gtid in (normally
1150 MAX_TEXT_LENGTH+1 bytes long).
1151 @return Length of the string, not counting '\0'.
1152 */
1153 int to_string(const Tsid &tsid, char *buf) const;
1154
1155 /**
1156 Convert this Gtid to a string.
1157 @param tsid_map tsid_map to use when converting sidno to a TSID.
1158 @param[out] buf Buffer to store the Gtid in (normally
1159 MAX_TEXT_LENGTH+1 bytes long).
1160 @param need_lock If true, the function will acquire tsid_map->tsid_lock;
1161 otherwise it will assert that the lock is held.
1162 @return Length of the string, not counting '\0'.
1163 */
1164 int to_string(const Tsid_map *tsid_map, char *buf,
1165 bool need_lock = false) const;
1166 /// Returns true if this Gtid has the same sid and gno as 'other'.
1167 bool equals(const Gtid &other) const {
1168 return sidno == other.sidno && gno == other.gno;
1169 }
1170 /**
1171 Parses the given string and stores in this Gtid.
1172
1173 @param tsid_map tsid_map to use when converting TSID to a sidno.
1174 @param text The text to parse
1175 @return status of operation
1176 */
1177 [[nodiscard]] mysql::utils::Return_status parse(Tsid_map *tsid_map,
1178 const char *text);
1179
1180 /// @brief Parses TAG from a textual representation of the GTID (text)
1181 /// @param[in] text String with full GTID specification
1182 /// @param[in] pos Current position within a text
1183 /// @return Parsed tag
1184 /// Updated position within text
1185 static std::pair<Tag, std::size_t> parse_tag_str(const char *text,
1186 std::size_t pos);
1187
1188 /// @brief Helper used to report BINLOG error
1189 /// @param[in] text String with full GTID specification
1190 static void report_parsing_error(const char *text);
1191
1192 /// @brief Parses GTID from text. In case GTID is valid, it will return
1193 /// "ok" status code and a valid mysql::gtid::Gtid object. Otherwise,
1194 /// it will return an empty Gtid and error
1195 /// @param[in] text Text containing textual representation of a GTID
1196 static std::pair<mysql::utils::Return_status, mysql::gtid::Gtid>
1197 parse_gtid_from_cstring(const char *text);
1198
1199 /// @brief Definition of GTID separator (colon) which separates UUID and GNO
1200 static constexpr auto gtid_separator = ':';
1201
1202#ifndef NDEBUG
1203 /// Debug only: print this Gtid to stdout.
1204 void print(const Tsid_map *tsid_map) const {
1205 char buf[MAX_TEXT_LENGTH + 1];
1206 to_string(tsid_map, buf);
1207 printf("%s\n", buf);
1208 }
1209#endif
1210 /// Print this Gtid to the trace file if debug is enabled; no-op otherwise.
1211 void dbug_print(const Tsid_map *tsid_map [[maybe_unused]],
1212 const char *text [[maybe_unused]] = "",
1213 bool need_lock [[maybe_unused]] = false) const {
1214#ifndef NDEBUG
1215 char buf[MAX_TEXT_LENGTH + 1];
1216 to_string(tsid_map, buf, need_lock);
1217 DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", buf));
1218#endif
1219 }
1220
1221 protected:
1222 /// @brief Converts internal gno into the string
1223 /// @param[out] buf Buffer to store the GNO in
1224 /// @return Length of the string
1225 int to_string_gno(char *buf) const;
1226
1227 /// @brief Helper function used to skip whitespaces in GTID specification
1228 /// @param[in] text String with full GTID specification
1229 /// @param[in] pos Current position within a text
1230 /// @return Updated position in text
1231 static std::size_t skip_whitespace(const char *text, std::size_t pos);
1232
1233 /// @brief Parses SID from a textual representation of the GTID.
1234 /// @param[in] text String with full GTID specification
1235 /// @param[in] pos Current position within a text
1236 /// @return operation status;
1237 /// Parsed sidno in case status is equal to true,
1238 /// 0 otherwise;
1239 /// Updated position within text up to which characters has
1240 /// been accepted
1241 static std::tuple<mysql::utils::Return_status, rpl_sid, std::size_t>
1242 parse_sid_str(const char *text, std::size_t pos);
1243
1244 /// @brief Parses GNO from a textual representation of the GTID (text)
1245 /// @param[in] text String with full GTID specification
1246 /// @param[in] pos Current position within a text
1247 /// @return operation status;
1248 /// Parsed gno in case status is equal to true or 0;
1249 /// Updated position within text
1250 static std::tuple<mysql::utils::Return_status, rpl_gno, std::size_t>
1251 parse_gno_str(const char *text, std::size_t pos);
1252
1253 /// @brief Parses GTID separator from a textual representation of the GTID
1254 /// (text)
1255 /// @param[in] text String with full GTID specification
1256 /// @param[in] pos Current position within a text
1257 /// @return parsing status, error in case separator could not have been parsed
1258 /// Updated position within text
1259 static std::pair<mysql::utils::Return_status, std::size_t>
1260 parse_gtid_separator(const char *text, std::size_t pos);
1261};
1262
1263/// Structure to store the GTID and timing information.
1265 /// GTID being monitored.
1267 /// OCT of the GTID being monitored.
1269 /// ICT of the GTID being monitored.
1271 /// When the GTID transaction started to be processed.
1273 /// When the GTID transaction finished to be processed.
1275 /// True if the GTID is being applied but will be skipped.
1277 /// True when this information contains useful data.
1279 /// Number of the last transient error of this transaction
1281 /// Message of the last transient error of this transaction
1283 /// Timestamp in microseconds of the last transient error of this transaction
1285 /// Number of times this transaction was retried
1287 /// True when the transaction is retrying
1289 /// The compression type
1291 /// The compressed bytes
1293 /// The uncompressed bytes
1295
1296 /// Constructor
1298 /// Copy constructor
1300
1302
1303 /// Clear all fields of the structure.
1304 void clear();
1305
1306 /**
1307 Copies this transaction monitoring information to the output parameters
1308 passed as input, which are the corresponding fields in a replication
1309 performance schema table.
1310
1311 @param[in] tsid_map The TSID map for the GTID.
1312 @param[out] gtid_arg GTID field in the PS table.
1313 @param[out] gtid_length_arg Length of the GTID as string.
1314 @param[out] original_commit_ts_arg The original commit timestamp.
1315 @param[out] immediate_commit_ts_arg The immediate commit timestamp.
1316 @param[out] start_time_arg The start time field.
1317 */
1318 void copy_to_ps_table(Tsid_map *tsid_map, char *gtid_arg,
1319 uint *gtid_length_arg,
1320 ulonglong *original_commit_ts_arg,
1321 ulonglong *immediate_commit_ts_arg,
1322 ulonglong *start_time_arg) const;
1323
1324 /**
1325 Copies this transaction monitoring information to the output parameters
1326 passed as input, which are the corresponding fields in a replication
1327 performance schema table.
1328
1329 @param[in] tsid_map The TSID map for the GTID.
1330 @param[out] gtid_arg GTID field in the PS table.
1331 @param[out] gtid_length_arg Length of the GTID as string.
1332 @param[out] original_commit_ts_arg The original commit timestamp.
1333 @param[out] immediate_commit_ts_arg The immediate commit timestamp.
1334 @param[out] start_time_arg The start time field.
1335 @param[out] end_time_arg The end time field. This can be null
1336 when the PS table fields are for the
1337 "still processing" information.
1338 */
1339 void copy_to_ps_table(Tsid_map *tsid_map, char *gtid_arg,
1340 uint *gtid_length_arg,
1341 ulonglong *original_commit_ts_arg,
1342 ulonglong *immediate_commit_ts_arg,
1343 ulonglong *start_time_arg,
1344 ulonglong *end_time_arg) const;
1345
1346 /**
1347 Copies this transaction monitoring information to the output parameters
1348 passed as input, which are the corresponding fields in a replication
1349 performance schema table.
1350
1351 @param[in] tsid_map The TSID map for the GTID.
1352 @param[out] gtid_arg GTID field in the PS table.
1353 @param[out] gtid_length_arg Length of the GTID as string.
1354 @param[out] original_commit_ts_arg The original commit timestamp.
1355 @param[out] immediate_commit_ts_arg The immediate commit timestamp.
1356 @param[out] start_time_arg The start time field.
1357 @param[out] last_transient_errno_arg The last transient error
1358 number.
1359 @param[out] last_transient_errmsg_arg The last transient error
1360 message.
1361 @param[out] last_transient_errmsg_length_arg Length of the last transient
1362 error message.
1363 @param[out] last_transient_timestamp_arg The last transient error
1364 timestamp.
1365 @param[out] retries_count_arg The total number of retries for
1366 this transaction.
1367 */
1368 void copy_to_ps_table(
1369 Tsid_map *tsid_map, char *gtid_arg, uint *gtid_length_arg,
1370 ulonglong *original_commit_ts_arg, ulonglong *immediate_commit_ts_arg,
1371 ulonglong *start_time_arg, uint *last_transient_errno_arg,
1372 char *last_transient_errmsg_arg, uint *last_transient_errmsg_length_arg,
1373 ulonglong *last_transient_timestamp_arg, ulong *retries_count_arg) const;
1374
1375 /**
1376 Copies this transaction monitoring information to the output parameters
1377 passed as input, which are the corresponding fields in a replication
1378 performance schema table.
1379
1380 @param[in] tsid_map The TSID map for the GTID.
1381 @param[out] gtid_arg GTID field in the PS table.
1382 @param[out] gtid_length_arg Length of the GTID as string.
1383 @param[out] original_commit_ts_arg The original commit timestamp.
1384 @param[out] immediate_commit_ts_arg The immediate commit timestamp.
1385 @param[out] start_time_arg The start time field.
1386 @param[out] end_time_arg The end time field. This can be
1387 null when the PS table fields
1388 are for the "still processing"
1389 information.
1390 @param[out] last_transient_errno_arg The last transient error
1391 number.
1392 @param[out] last_transient_errmsg_arg The last transient error
1393 message.
1394 @param[out] last_transient_errmsg_length_arg Length of the last transient
1395 error message.
1396 @param[out] last_transient_timestamp_arg The last transient error
1397 timestamp.
1398 @param[out] retries_count_arg The total number of retries for
1399 this transaction.
1400 */
1401 void copy_to_ps_table(
1402 Tsid_map *tsid_map, char *gtid_arg, uint *gtid_length_arg,
1403 ulonglong *original_commit_ts_arg, ulonglong *immediate_commit_ts_arg,
1404 ulonglong *start_time_arg, ulonglong *end_time_arg,
1405 uint *last_transient_errno_arg, char *last_transient_errmsg_arg,
1406 uint *last_transient_errmsg_length_arg,
1407 ulonglong *last_transient_timestamp_arg, ulong *retries_count_arg) const;
1408};
1409
1410/**
1411 Stores information to monitor a transaction during the different replication
1412 stages.
1413*/
1415 public:
1416 /**
1417 Create this GTID monitoring info object.
1418
1419 @param atomic_mutex_arg When specified, this object will rely on the mutex
1420 to arbitrate the read/update access to object data.
1421 This will be used by the receiver thread, relying
1422 on mi->data_lock. When no mutex is specified, the
1423 object will rely on its own atomic mechanism.
1424 */
1425 Gtid_monitoring_info(mysql_mutex_t *atomic_mutex_arg = nullptr);
1426
1427 /// Destroy this GTID monitoring info object.
1429
1430 protected:
1431 /// Holds information about transaction being processed.
1433 /// Holds information about the last processed transaction.
1435
1436 private:
1437 /**
1438 Mutex arbitrating the atomic access to the object.
1439
1440 Some Gtid_monitoring_info will rely on replication thread locks
1441 (i.e.: the Master_info's one rely on mi->data_lock, that is already
1442 acquired every time the Gtid_monitoring_info needs to be updated).
1443
1444 Other Gtid_monitoring_info will rely on an atomic lock implemented
1445 in this class to avoid overlapped reads and writes over the information.
1446 (i.e.: the Relay_log_info's one sometimes is updated without rli locks).
1447
1448 When atomic_mutex is NULL, the object will rely on its own atomic
1449 mechanism.
1450 */
1452
1453 /// The atomic locked flag.
1454 std::atomic<bool> atomic_locked{false};
1455#ifndef NDEBUG
1456 /// Flag to assert the atomic lock behavior.
1457 bool is_locked = false;
1458#endif
1459
1460 public:
1461 /**
1462 Lock this object when no thread mutex is used to arbitrate the access.
1463 */
1464 void atomic_lock();
1465 /**
1466 Unlock this object when no thread mutex is used to arbitrate the access.
1467 */
1468 void atomic_unlock();
1469 /**
1470 Clear all monitoring information.
1471 */
1472 void clear();
1473 /**
1474 Clear only the processing_trx monitoring info.
1475 */
1476 void clear_processing_trx();
1477 /**
1478 Clear only the last_processed_trx monitoring info.
1479 */
1481
1482 /**
1483 Sets the initial monitoring information.
1484 @param gtid_arg The Gtid to be stored.
1485 @param original_ts_arg The original commit timestamp of the GTID.
1486 @param immediate_ts_arg The immediate commit timestamp of the GTID.
1487 @param skipped_arg True if the GTID was already applied.
1488 This only make sense for applier threads.
1489 That's why it is false by default.
1490 */
1491 void start(Gtid gtid_arg, ulonglong original_ts_arg,
1492 ulonglong immediate_ts_arg, bool skipped_arg = false);
1493
1494 void update(mysql::binlog::event::compression::type t, size_t payload_size,
1495 size_t uncompressed_size);
1496
1497 /**
1498 Sets the final information, copy processing info to last_processed
1499 and clears processing info.
1500 */
1501 void finish();
1502 /**
1503 Copies both processing_trx and last_processed_trx info to other
1504 Trx_monitoring_info structures.
1505
1506 @param[out] processing_dest The destination of processing_trx.
1507 @param[out] last_processed_dest The destination of last_processed_trx.
1508 */
1509 void copy_info_to(Trx_monitoring_info *processing_dest,
1510 Trx_monitoring_info *last_processed_dest);
1511 /**
1512 Copies all monitoring info to other Gtid_monitoring_info object.
1513
1514 @param[out] dest The destination Gtid_monitoring_info.
1515 */
1517 /// Returns true if the processing_trx is set, false otherwise.
1518 bool is_processing_trx_set();
1519 /// Returns the GTID of the processing_trx.
1521 /**
1522 Stores the information about the last transient error in the current
1523 transaction, namely: the error number, message and total number of retries.
1524 It also sets the timestamp for this error.
1525
1526 @param transient_errno_arg The number of the transient error in this
1527 transaction.
1528 @param transient_err_message_arg The message of this transient error.
1529 @param trans_retries_arg The number of times this transaction has
1530 been retried.
1531 */
1532 void store_transient_error(uint transient_errno_arg,
1533 const char *transient_err_message_arg,
1534 ulong trans_retries_arg);
1535};
1536
1537/**
1538 Represents a set of GTIDs.
1539
1540 This is structured as an array, indexed by SIDNO, where each element
1541 contains a linked list of intervals.
1542
1543 This data structure OPTIONALLY knows of a Tsid_map that gives a
1544 correspondence between SIDNO and TSID. If the Tsid_map is NULL, then
1545 operations that require a Tsid_map - printing and parsing - raise an
1546 assertion.
1547
1548 This data structure OPTIONALLY knows of a read-write lock that
1549 protects the number of SIDNOs. The lock is provided by the invoker
1550 of the constructor and it is generally the caller's responsibility
1551 to acquire the read lock. If the lock is not NULL, access methods
1552 assert that the caller already holds the read (or write) lock. If
1553 the lock is not NULL and a method of this class grows the number of
1554 SIDNOs, then the method temporarily upgrades this lock to a write
1555 lock and then degrades it to a read lock again; there will be a
1556 short period when the lock is not held at all.
1557*/
1559 public:
1561 /**
1562 Constructs a new, empty Gtid_set.
1563
1564 @param tsid_map The Tsid_map to use, or NULL if this Gtid_set
1565 should not have a Tsid_map.
1566 @param tsid_lock Read-write lock that protects updates to the
1567 number of TSIDs. This may be NULL if such changes do not need to be
1568 protected.
1569 */
1571 /**
1572 Constructs a new Gtid_set that contains the gtids in the given
1573 string, in the same format as add_gtid_text(char *).
1574
1575 @param tsid_map The Tsid_map to use for TSIDs.
1576 @param text The text to parse.
1577 @param status Will be set to RETURN_STATUS_OK on success or
1578 RETURN_STATUS_REPORTED_ERROR on error.
1579 @param tsid_lock Read/write lock to protect changes in the number
1580 of SIDs with. This may be NULL if such changes do not need to be
1581 protected.
1582 If tsid_lock != NULL, then the read lock on tsid_lock must be held
1583 before calling this function. If the array is grown, tsid_lock is
1584 temporarily upgraded to a write lock and then degraded again;
1585 there will be a short period when the lock is not held at all.
1586 */
1587 Gtid_set(Tsid_map *tsid_map, const char *text, enum_return_status *status,
1588 Checkable_rwlock *tsid_lock = nullptr);
1589
1590 private:
1591 /// Worker for the constructor.
1592 void init();
1593
1594 public:
1595 /// Destroy this Gtid_set.
1596 ~Gtid_set();
1597
1598 /**
1599 Claim ownership of memory.
1600
1601 @param claim claim ownership of memory.
1602 */
1603 void claim_memory_ownership(bool claim);
1604
1605 /**
1606 Removes all gtids from this Gtid_set.
1607
1608 This does not deallocate anything: if gtids are added later,
1609 existing allocated memory will be re-used.
1610 */
1611 void clear();
1612 /**
1613 Removes all gtids from this Gtid_set and clear all the sidnos
1614 used by the Gtid_set and it's TSID map.
1615
1616 This does not deallocate anything: if gtids are added later,
1617 existing allocated memory will be re-used.
1618 */
1620 /**
1621 Adds the given GTID to this Gtid_set.
1622
1623 The SIDNO must exist in the Gtid_set before this function is called.
1624
1625 @param sidno SIDNO of the GTID to add.
1626 @param gno GNO of the GTID to add.
1627 */
1628 void _add_gtid(rpl_sidno sidno, rpl_gno gno) {
1629 DBUG_TRACE;
1630 assert(sidno > 0);
1631 assert(gno > 0);
1632 assert(gno < GNO_END);
1633 Interval_iterator ivit(this, sidno);
1635 add_gno_interval(&ivit, gno, gno + 1, &lock);
1636 return;
1637 }
1638 /**
1639 Removes the given GTID from this Gtid_set.
1640
1641 @param sidno SIDNO of the GTID to remove.
1642 @param gno GNO of the GTID to remove.
1643 */
1644 void _remove_gtid(rpl_sidno sidno, rpl_gno gno) {
1645 DBUG_TRACE;
1646 if (sidno <= get_max_sidno()) {
1647 Interval_iterator ivit(this, sidno);
1649 remove_gno_interval(&ivit, gno, gno + 1, &lock);
1650 }
1651 return;
1652 }
1653 /**
1654 Adds the given GTID to this Gtid_set.
1655
1656 The SIDNO must exist in the Gtid_set before this function is called.
1657
1658 @param gtid Gtid to add.
1659 */
1660 void _add_gtid(const Gtid &gtid) { _add_gtid(gtid.sidno, gtid.gno); }
1661 /**
1662 Removes the given GTID from this Gtid_set.
1663
1664 @param gtid Gtid to remove.
1665 */
1666 void _remove_gtid(const Gtid &gtid) { _remove_gtid(gtid.sidno, gtid.gno); }
1667 /**
1668 Adds all gtids from the given Gtid_set to this Gtid_set.
1669
1670 If tsid_lock != NULL, then the read lock must be held before
1671 calling this function. If a new sidno is added so that the array
1672 of lists of intervals is grown, tsid_lock is temporarily upgraded
1673 to a write lock and then degraded again; there will be a short
1674 period when the lock is not held at all.
1675
1676 @param other The Gtid_set to add.
1677 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1678 */
1680 /**
1681 Removes all gtids in the given Gtid_set from this Gtid_set.
1682
1683 @param other The Gtid_set to remove.
1684 */
1685 void remove_gtid_set(const Gtid_set *other);
1686 /**
1687 Removes all intervals of 'other' for a given SIDNO, from 'this'.
1688
1689 Example:
1690 this = A:1-100, B:1-100
1691 other = A:1-100, B:1-50, C:1-100
1692 this.remove_intervals_for_sidno(other, B) = A:1-100, B:51-100
1693
1694 It is not required that the intervals exist in this Gtid_set.
1695
1696 @param other The set to remove.
1697 @param sidno The sidno to remove.
1698 */
1699 void remove_intervals_for_sidno(Gtid_set *other, rpl_sidno sidno);
1700 /**
1701 Adds the set of GTIDs represented by the given string to this Gtid_set.
1702
1703 The string must have the format of a comma-separated list of zero
1704 or more of the following items:
1705
1706 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX(:NUMBER+(-NUMBER)?)*
1707 | ANONYMOUS
1708
1709 Each X is a hexadecimal digit (upper- or lowercase).
1710 NUMBER is a decimal, 0xhex, or 0oct number.
1711
1712 The start of an interval must be greater than 0. The end of an
1713 interval may be 0, but any interval that has an endpoint that
1714 is smaller than the start is discarded.
1715
1716 The string can start with an optional '+' appender qualifier
1717 which triggers @c executed_gtids and @c lost_gtids set examination
1718 on the matter of disjointness with the one being added.
1719
1720 If tsid_lock != NULL, then the read lock on tsid_lock must be held
1721 before calling this function. If a new sidno is added so that the
1722 array of lists of intervals is grown, tsid_lock is temporarily
1723 upgraded to a write lock and then degraded again; there will be a
1724 short period when the lock is not held at all.
1725
1726 @param text The string to parse.
1727 @param [in,out] anonymous If this is NULL, ANONYMOUS is not
1728 allowed. If this is not NULL, it will be set to true if the
1729 anonymous GTID was found; false otherwise.
1730 @param[in,out] starts_with_plus If this is not NULL, the string may
1731 optionally begin with a '+' character, and *starts_with_plus will
1732 be set to true if the plus character is present. If this is NULL,
1733 no plus is allowed at the begin of the string.
1734
1735 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1736 */
1737 enum_return_status add_gtid_text(const char *text, bool *anonymous = nullptr,
1738 bool *starts_with_plus = nullptr);
1739
1740 /// @brief Adds specified GTID (TSID+GNO) to this Gtid_set.
1741 /// @param gtid mysql::gtid::Gtid object
1742 /// @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1743 [[nodiscard]] enum_return_status add_gtid(const mysql::gtid::Gtid &gtid);
1744
1745 /**
1746 Decodes a Gtid_set from the given string.
1747
1748 @param encoded The string to parse.
1749 @param length The number of bytes.
1750 @param actual_length If this is not NULL, it is set to the number
1751 of bytes used by the encoding (which may be less than 'length').
1752 If this is NULL, an error is generated if the encoding is shorter
1753 than the given 'length'.
1754 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1755 */
1756 enum_return_status add_gtid_encoding(const uchar *encoded, size_t length,
1757 size_t *actual_length = nullptr);
1758 /// Return true iff the given GTID exists in this set.
1759 bool contains_gtid(rpl_sidno sidno, rpl_gno gno) const;
1760 /// Return true iff the given GTID exists in this set.
1761 bool contains_gtid(const Gtid &gtid) const {
1762 return contains_gtid(gtid.sidno, gtid.gno);
1763 }
1764 // Get last gno or 0 if this set is empty.
1765 rpl_gno get_last_gno(rpl_sidno sidno) const;
1766 /// Returns the maximal sidno that this Gtid_set currently has space for.
1769 return static_cast<rpl_sidno>(m_intervals.size());
1770 }
1771 /**
1772 Allocates space for all sidnos up to the given sidno in the array of
1773 intervals. The sidno must exist in the Tsid_map associated with this
1774 Gtid_set.
1775
1776 If tsid_lock != NULL, then the read lock on tsid_lock must be held
1777 before calling this function. If the array is grown, tsid_lock is
1778 temporarily upgraded to a write lock and then degraded again;
1779 there will be a short period when the lock is not held at all.
1780
1781 @param sidno The SIDNO.
1782 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1783 */
1785 /// Returns true if this Gtid_set is a subset of the other Gtid_set.
1786 bool is_subset(const Gtid_set *super) const;
1787 /// Returns true if this Gtid_set is a non equal subset of the other Gtid_set.
1788 bool is_subset_not_equals(const Gtid_set *super) const {
1789 return (is_subset(super) && !equals(super));
1790 }
1791
1792 /**
1793 Returns true if this Gtid_set is a subset of the given gtid_set
1794 on the given superset_sidno and subset_sidno.
1795
1796 @param super Gtid_set with which this->gtid_set needs to be
1797 compared
1798 @param superset_sidno The sidno that will be compared, relative to
1799 super->tsid_map.
1800 @param subset_sidno The sidno that will be compared, relative to
1801 this->tsid_map.
1802 @return true If 'this' Gtid_set is subset of given
1803 'super' Gtid_set.
1804 false If 'this' Gtid_set is *not* subset of given
1805 'super' Gtid_set.
1806 */
1807 bool is_subset_for_sidno(const Gtid_set *super, rpl_sidno superset_sidno,
1808 rpl_sidno subset_sidno) const;
1809
1810 /// @brief Returns true if this Gtid_set is a subset of the given gtid_set
1811 /// with respect to the given sid
1812 /// @details This function will traverse all TSIDs with SID equal
1813 /// to "sid" parameter (all registered tags for a given SID)
1814 /// @param super Gtid_set with which this->gtid_set needs to be compared
1815 /// @param sid Sid for which we will do the testing
1816 /// @return True in case super is a superset for this gtid set w.r.t. the
1817 /// given sid; false otherwise
1818 bool is_subset_for_sid(const Gtid_set *super, const rpl_sid &sid) const;
1819
1820 /// Returns true if there is a least one element of this Gtid_set in
1821 /// the other Gtid_set.
1822 bool is_intersection_nonempty(const Gtid_set *other) const;
1823 /**
1824 Add the intersection of this Gtid_set and the other Gtid_set to result.
1825
1826 @param other The Gtid_set to intersect with this Gtid_set
1827 @param result Gtid_set where the result will be stored.
1828 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1829 */
1831 /// Returns true if this Gtid_set is empty.
1832 bool is_empty() const {
1833 Gtid_iterator git(this);
1834 return git.get().sidno == 0;
1835 }
1836
1837 /**
1838 Return true if the size of the set is greater than or equal to the given
1839 number. The size is measure in number of GTIDs, i.e., total length of all
1840 intervals.
1841
1842 @param num Number to compare with
1843 @retval true if the set contains >= num GTIDs.
1844 @retval false if the set contains < num GTIDs.
1845 */
1847
1848 /**
1849 What is the count of all the GTIDs in all intervals for a sidno
1850
1851 @param sidno The sidno that contains the intervals
1852
1853 @return the number of all GTIDs in all intervals
1854 */
1856 Const_interval_iterator ivit(this, sidno);
1857 ulonglong ret = 0;
1858 while (ivit.get() != nullptr) {
1859 ret += ivit.get()->end - ivit.get()->start;
1860 ivit.next();
1861 }
1862 return ret;
1863 }
1864
1865 /// @brief Returns the number of GTIDs
1866 /// @returns the number of GTIDs on this set
1867 std::size_t get_count() const {
1868 if (tsid_lock != nullptr) tsid_lock->assert_some_wrlock();
1869 rpl_sidno max_sidno = get_max_sidno();
1870 std::size_t count{0};
1871
1872 for (rpl_sidno sidno = 1; sidno <= max_sidno; sidno++) {
1873 count += get_gtid_count(sidno);
1874 }
1875 return count;
1876 }
1877
1878 /**
1879 Returns true if this Gtid_set contains at least one GTID with
1880 the given SIDNO.
1881
1882 @param sidno The SIDNO to test.
1883 @retval true The SIDNO is less than or equal to the max SIDNO, and
1884 there is at least one GTID with this SIDNO.
1885 @retval false The SIDNO is greater than the max SIDNO, or there is
1886 no GTID with this SIDNO.
1887 */
1888 bool contains_sidno(rpl_sidno sidno) const {
1889 assert(sidno >= 1);
1890 if (sidno > get_max_sidno()) return false;
1891 Const_interval_iterator ivit(this, sidno);
1892 return ivit.get() != nullptr;
1893 }
1894 /**
1895 Returns true if the given string is a valid specification of a
1896 Gtid_set, false otherwise.
1897 */
1898 static bool is_valid(const char *text);
1899
1900 /**
1901 Class Gtid_set::String_format defines the separators used by
1902 Gtid_set::to_string.
1903 */
1905 /// The generated string begins with this.
1906 const char *begin;
1907 /// The generated string begins with this.
1908 const char *end;
1909 /// In 'SID:TAG', this is the ':'
1911 /// In 'TSID:GNO', this is the ':'
1913 /// In 'SID:GNO-GNO', this is the '-'
1915 /// In 'SID:GNO:GNO', this is the second ':'
1917 /// In 'SID:GNO,SID:GNO', this is the ','
1919 /// If the set is empty and this is not NULL, then this string is generated.
1920 const char *empty_set_string;
1921 /// The following fields are the lengths of each field above.
1922 const int begin_length;
1923 const int end_length;
1930 };
1931
1932 /// @brief Checks if this Gtid set contains any tagged GTIDs
1933 /// @retval true This gtid set contains tagged GTIDs
1934 /// @retval false This gtid set contains only untagged GTIDs
1935 bool contains_tags() const;
1936 /**
1937 Returns the length of the output from to_string.
1938
1939 @warning This does not include the trailing '\0', so your buffer
1940 needs space for get_string_length() + 1 characters.
1941
1942 @param string_format String_format object that specifies
1943 separators in the resulting text.
1944 @return The length.
1945 */
1946 size_t get_string_length(const String_format *string_format = nullptr) const;
1947 /**
1948 Formats this Gtid_set as a string and saves in a given buffer.
1949
1950 @param[out] buf Pointer to the buffer where the string should be
1951 stored. This should have size at least get_string_length()+1.
1952 @param need_lock If this Gtid_set has a tsid_lock, then the write
1953 lock must be held while generating the string. If this parameter
1954 is true, then this function acquires and releases the lock;
1955 otherwise it asserts that the caller holds the lock.
1956 @param string_format String_format object that specifies
1957 separators in the resulting text.
1958 @return Length of the generated string.
1959 */
1960 size_t to_string(char *buf, bool need_lock = false,
1961 const String_format *string_format = nullptr) const;
1962
1963 /**
1964 Formats a Gtid_set as a string and saves in a newly allocated buffer.
1965 @param[out] buf Pointer to pointer to string. The function will
1966 set it to point to the newly allocated buffer, or NULL on out of memory.
1967 @param need_lock If this Gtid_set has a tsid_lock, then the write
1968 lock must be held while generating the string. If this parameter
1969 is true, then this function acquires and releases the lock;
1970 otherwise it asserts that the caller holds the lock.
1971 @param string_format Specifies how to format the string.
1972 @retval Length of the generated string, or -1 on out of memory.
1973 */
1974 long to_string(char **buf, bool need_lock = false,
1975 const String_format *string_format = nullptr) const;
1976#ifndef NDEBUG
1977 /// Debug only: Print this Gtid_set to stdout.
1978
1979 /// For use with C `printf`
1980 void print(bool need_lock = false,
1981 const Gtid_set::String_format *sf = nullptr) const {
1982 char *str;
1983 to_string(&str, need_lock, sf);
1984 printf("%s\n", str ? str : "out of memory in Gtid_set::print");
1985 my_free(str);
1986 }
1987
1988 /// For use with C++ `std::ostream`
1989 inline friend std::ostream &operator<<(std::ostream &os, const Gtid_set &in) {
1990 char *str;
1991 in.to_string(&str, true, nullptr);
1992 os << std::string(str) << std::flush;
1993 my_free(str);
1994 return os;
1995 }
1996#endif
1997 /**
1998 Print this Gtid_set to the trace file if debug is enabled; no-op
1999 otherwise.
2000 */
2001 void dbug_print(const char *text [[maybe_unused]] = "",
2002 bool need_lock [[maybe_unused]] = false,
2003 const Gtid_set::String_format *sf
2004 [[maybe_unused]] = nullptr) const {
2005#ifndef NDEBUG
2006 char *str;
2007 to_string(&str, need_lock, sf);
2008 DBUG_PRINT("info", ("%s%s'%s'", text, *text ? ": " : "",
2009 str ? str : "out of memory in Gtid_set::dbug_print"));
2010 my_free(str);
2011#endif
2012 }
2013 /**
2014 Gets all gtid intervals from this Gtid_set.
2015
2016 @param[out] gtid_intervals Store all gtid intervals from this Gtid_set.
2017 */
2018 void get_gtid_intervals(std::list<Gtid_interval> *gtid_intervals) const;
2019 /**
2020 The default String_format: the format understood by
2021 add_gtid_text(const char *).
2022 */
2024 /**
2025 String_format useful to generate an SQL string: the string is
2026 wrapped in single quotes and there is a newline between SIDs.
2027 */
2029 /**
2030 String_format for printing the Gtid_set commented: the string is
2031 not quote-wrapped, and every TSID is on a new line with a leading '# '.
2032 */
2034
2035 /// Return the Tsid_map associated with this Gtid_set.
2036 Tsid_map *get_tsid_map() const { return tsid_map; }
2037
2038 /**
2039 Represents one element in the linked list of intervals associated
2040 with a SIDNO.
2041 */
2042 struct Interval {
2043 public:
2044 /// The first GNO of this interval.
2046 /// The first GNO after this interval.
2048 /// Return true iff this interval is equal to the given interval.
2049 bool equals(const Interval &other) const {
2050 return start == other.start && end == other.end;
2051 }
2052 /// Pointer to next interval in list.
2054 };
2055
2056 /**
2057 Provides an array of Intervals that this Gtid_set can use when
2058 gtids are subsequently added. This can be used as an
2059 optimization, to reduce allocation for sets that have a known
2060 number of intervals.
2061
2062 @param n_intervals The number of intervals to add.
2063 @param intervals_param Array of n_intervals intervals.
2064 */
2065 void add_interval_memory(int n_intervals, Interval *intervals_param) {
2067 add_interval_memory_lock_taken(n_intervals, intervals_param);
2069 }
2070
2071 /**
2072 Iterator over intervals for a given SIDNO.
2073
2074 This is an abstract template class, used as a common base class
2075 for Const_interval_iterator and Interval_iterator.
2076
2077 The iterator always points to an interval pointer. The interval
2078 pointer is either the initial pointer into the list, or the next
2079 pointer of one of the intervals in the list.
2080 */
2081 template <typename Gtid_set_p, typename Interval_p>
2083 public:
2084 /**
2085 Construct a new iterator over the GNO intervals for a given Gtid_set.
2086
2087 @param gtid_set The Gtid_set.
2088 @param sidno The SIDNO.
2089 */
2090 Interval_iterator_base(Gtid_set_p gtid_set, rpl_sidno sidno) {
2091 assert(sidno >= 1 && sidno <= gtid_set->get_max_sidno());
2092 init(gtid_set, sidno);
2093 }
2094 /// Construct a new iterator over the free intervals of a Gtid_set.
2095 Interval_iterator_base(Gtid_set_p gtid_set) {
2096 p = const_cast<Interval_p *>(&gtid_set->free_intervals);
2097 }
2098 /// Reset this iterator.
2099 inline void init(Gtid_set_p gtid_set, rpl_sidno sidno) {
2100 p = const_cast<Interval_p *>(&gtid_set->m_intervals[sidno - 1]);
2101 }
2102 /// Advance current_elem one step.
2103 inline void next() {
2104 assert(*p != nullptr);
2105 p = const_cast<Interval_p *>(&(*p)->next);
2106 }
2107 /// Return current_elem.
2108 inline Interval_p get() const { return *p; }
2109
2110 protected:
2111 /**
2112 Holds the address of the 'next' pointer of the previous element,
2113 or the address of the initial pointer into the list, if the
2114 current element is the first element.
2115 */
2116 Interval_p *p;
2117 };
2118
2119 /**
2120 Iterator over intervals of a const Gtid_set.
2121 */
2123 : public Interval_iterator_base<const Gtid_set *, const Interval *> {
2124 public:
2125 /// Create this Const_interval_iterator.
2127 : Interval_iterator_base<const Gtid_set *, const Interval *>(gtid_set,
2128 sidno) {}
2129 /// Create this Const_interval_iterator.
2131 : Interval_iterator_base<const Gtid_set *, const Interval *>(gtid_set) {
2132 }
2133 };
2134
2135 /**
2136 Iterator over intervals of a non-const Gtid_set, with additional
2137 methods to modify the Gtid_set.
2138 */
2140 : public Interval_iterator_base<Gtid_set *, Interval *> {
2141 public:
2142 /// Create this Interval_iterator.
2144 : Interval_iterator_base<Gtid_set *, Interval *>(gtid_set, sidno) {}
2145 /// Destroy this Interval_iterator.
2147 : Interval_iterator_base<Gtid_set *, Interval *>(gtid_set) {}
2148
2149 private:
2150 /**
2151 Set current_elem to the given Interval but do not touch the
2152 next pointer of the given Interval.
2153 */
2154 inline void set(Interval *iv) { *p = iv; }
2155 /// Insert the given element before current_elem.
2156 inline void insert(Interval *iv) {
2157 iv->next = *p;
2158 set(iv);
2159 }
2160 /// Remove current_elem.
2161 inline void remove(Gtid_set *gtid_set) {
2162 assert(get() != nullptr);
2163 Interval *next = (*p)->next;
2164 gtid_set->put_free_interval(*p);
2165 set(next);
2166 }
2167 /**
2168 Only Gtid_set is allowed to use set/insert/remove.
2169
2170 They are not safe to use from other code because: (1) very easy
2171 to make a mistakes (2) they don't clear cached_string_format or
2172 cached_string_length.
2173 */
2174 friend class Gtid_set;
2175 };
2176
2177 /**
2178 Iterator over all gtids in a Gtid_set. This is a const
2179 iterator; it does not allow modification of the Gtid_set.
2180 */
2182 public:
2183 Gtid_iterator(const Gtid_set *gs) : gtid_set(gs), sidno(0), ivit(gs) {
2184 if (gs->tsid_lock != nullptr) gs->tsid_lock->assert_some_wrlock();
2185 next_sidno();
2186 }
2187 /// Advance to next gtid.
2188 inline void next() {
2189 assert(gno > 0 && sidno > 0);
2190 // go to next GTID in current interval
2191 gno++;
2192 // end of interval? then go to next interval for this sidno
2193 if (gno == ivit.get()->end) {
2194 ivit.next();
2195 const Interval *iv = ivit.get();
2196 // last interval for this sidno? then go to next sidno
2197 if (iv == nullptr) {
2198 next_sidno();
2199 // last sidno? then don't try more
2200 if (sidno == 0) return;
2201 iv = ivit.get();
2202 }
2203 gno = iv->start;
2204 }
2205 }
2206 /// Return next gtid, or {0,0} if we reached the end.
2207 inline Gtid get() const {
2208 Gtid ret = {sidno, gno};
2209 return ret;
2210 }
2211
2212 private:
2213 /// Find the next sidno that has one or more intervals.
2214 inline void next_sidno() {
2215 const Interval *iv;
2216 do {
2217 sidno++;
2218 if (sidno > gtid_set->get_max_sidno()) {
2219 sidno = 0;
2220 gno = 0;
2221 return;
2222 }
2224 iv = ivit.get();
2225 } while (iv == nullptr);
2226 gno = iv->start;
2227 }
2228 /// The Gtid_set we iterate over.
2230 /**
2231 The SIDNO of the current element, or 0 if the iterator is past
2232 the last element.
2233 */
2235 /**
2236 The GNO of the current element, or 0 if the iterator is past the
2237 last element.
2238 */
2240 /// Iterator over the intervals for the current SIDNO.
2242 };
2243
2244 public:
2245 /// Bit layout of the encoded n_sids + format header used by Gtid_set.
2246 static constexpr uint64_t k_gtid_format_byte_mask = 0xffULL;
2247 static constexpr uint64_t k_gtid_format_high_shift = 56;
2248 static constexpr uint64_t k_gtid_format_low_shift = 8;
2249 static constexpr uint64_t k_gtid_format_high_mask =
2252 static constexpr uint64_t k_tagged_n_sids_mask =
2254
2255 /// @brief Encodes this Gtid_set as a binary string.
2256 /// @param buf Buffer to write into
2257 /// @param skip_tagged_gtids When true, tagged GTIDS will be filtered out
2258 void encode(uchar *buf, bool skip_tagged_gtids = false) const;
2259
2260 /// @brief Returns the length of this Gtid_set when encoded using the
2261 /// encode() function. Before calculation, analyzes GTID set format
2262 /// @param skip_tagged_gtids When true, tagged GTIDS will be filtered out
2263 /// @return length of Gtid_set encoding
2264 size_t get_encoded_length(bool skip_tagged_gtids = false) const;
2265
2266 /// Returns the length of this Gtid_set when encoded using the
2267 /// encode() function. Uses already analyzed GTID set format (faster version)
2268 /// @param format Gtid format
2269 /// @param skip_tagged_gtids When true, tagged GTIDS will be filtered out
2270 /// @return Encoded gtid_set length
2272 bool skip_tagged_gtids) const;
2273
2274 /// Returns true if this Gtid_set is equal to the other Gtid_set.
2275 /// @param[in] other Gtid set to compare against
2276 /// @return true in case gtid sets contain the same GTIDs
2277 bool equals(const Gtid_set *other) const;
2278
2279 /// Return the number of intervals for the given sidno.
2280 int get_n_intervals(rpl_sidno sidno) const {
2281 Const_interval_iterator ivit(this, sidno);
2282 int ret = 0;
2283 while (ivit.get() != nullptr) {
2284 ret++;
2285 ivit.next();
2286 }
2287 return ret;
2288 }
2289
2290 /// Return the number of intervals in this Gtid_set.
2291 int get_n_intervals() const {
2292 if (tsid_lock != nullptr) tsid_lock->assert_some_wrlock();
2293 rpl_sidno max_sidno = get_max_sidno();
2294 int ret = 0;
2295 for (rpl_sidno sidno = 1; sidno < max_sidno; sidno++)
2296 ret += get_n_intervals(sidno);
2297 return ret;
2298 }
2299
2300 private:
2301 /**
2302 Contains a list of intervals allocated by this Gtid_set. When a
2303 method of this class needs a new interval and there are no more
2304 free intervals, a new Interval_chunk is allocated and the
2305 intervals of it are added to the list of free intervals.
2306 */
2310 };
2311 /// The default number of intervals in an Interval_chunk.
2312 static const int CHUNK_GROW_SIZE = 8;
2313
2314 /**
2315 Return true if the given sidno of this Gtid_set contains the same
2316 intervals as the given sidno of the other Gtid_set.
2317
2318 @param sidno SIDNO to check for this Gtid_set.
2319 @param other Other Gtid_set
2320 @param other_sidno SIDNO to check in other.
2321 @return true if equal, false is not equal.
2322 */
2323 bool sidno_equals(rpl_sidno sidno, const Gtid_set *other,
2324 rpl_sidno other_sidno) const;
2325
2326 /// @brief Goes through recorded tsids. In case any of the TSIDs has a tag,
2327 /// this function will return Gtid_format::tagged. Otherwise, it will
2328 /// return Gtid_format::untagged
2329 /// @param skip_tagged_gtids When true, function will always return
2330 /// Gtid_format::untagged
2331 /// @returns Gtid encoding format
2333 bool skip_tagged_gtids) const;
2334
2335 /**
2336 Allocates a new chunk of Intervals and adds them to the list of
2337 unused intervals.
2338
2339 @param size The number of intervals in this chunk
2340 */
2341 void create_new_chunk(int size);
2342 /**
2343 Returns a fresh new Interval object.
2344
2345 This usually does not require any real allocation, it only pops
2346 the first interval from the list of free intervals. If there are
2347 no free intervals, it calls create_new_chunk.
2348
2349 @param out The resulting Interval* will be stored here.
2350 */
2351 void get_free_interval(Interval **out);
2352 /**
2353 Puts the given interval in the list of free intervals. Does not
2354 unlink it from its place in any other list.
2355 */
2356 void put_free_interval(Interval *iv);
2357 /**
2358 Like add_interval_memory, but does not acquire
2359 free_intervals_mutex.
2360 @see Gtid_set::add_interval_memory
2361 */
2362 void add_interval_memory_lock_taken(int n_ivs, Interval *ivs);
2363
2364 /// Read-write lock that protects updates to the number of TSIDs.
2366 /**
2367 Lock protecting the list of free intervals. This lock is only
2368 used if tsid_lock is not NULL.
2369 */
2371 /**
2372 Class representing a lock on free_intervals_mutex.
2373
2374 This is used by the add_* and remove_* functions. The lock is
2375 declared by the top-level function and a pointer to the lock is
2376 passed down to low-level functions. If the low-level function
2377 decides to access the free intervals list, then it acquires the
2378 lock. The lock is then automatically released by the destructor
2379 when the top-level function returns.
2380
2381 The lock is not taken if Gtid_set->tsid_lock == NULL; such
2382 Gtid_sets are assumed to be thread-local.
2383 */
2385 public:
2386 /// Create a new lock, but do not acquire it.
2388 : gtid_set(_gtid_set), locked(false) {}
2389 /// Lock the lock if it is not already locked.
2391 if (gtid_set->tsid_lock && !locked) {
2393 locked = true;
2394 }
2395 }
2396 /// Lock the lock if it is locked.
2398 if (gtid_set->tsid_lock && locked) {
2400 locked = false;
2401 }
2402 }
2403 /// Destroy this object and unlock the lock if it is locked.
2405
2406 private:
2409 };
2412 }
2413
2414 /**
2415 Adds the interval (start, end) to the given Interval_iterator.
2416
2417 This is the lowest-level function that adds gtids; this is where
2418 Interval objects are added, grown, or merged.
2419
2420 @param ivitp Pointer to iterator. After this function returns,
2421 the current_element of the iterator will be the interval that
2422 contains start and end.
2423 @param start The first GNO in the interval.
2424 @param end The first GNO after the interval.
2425 @param lock If this function has to add or remove an interval,
2426 then this lock will be taken unless it is already taken. This
2427 mechanism means that the lock will be taken lazily by
2428 e.g. add_gtid_set() the first time that the list of free intervals
2429 is accessed, and automatically released when add_gtid_set()
2430 returns.
2431 */
2432 void add_gno_interval(Interval_iterator *ivitp, rpl_gno start, rpl_gno end,
2433 Free_intervals_lock *lock);
2434 /**
2435 Removes the interval (start, end) from the given
2436 Interval_iterator. This is the lowest-level function that removes
2437 gtids; this is where Interval objects are removed, truncated, or
2438 split.
2439
2440 It is not required that the gtids in the interval exist in this
2441 Gtid_set.
2442
2443 @param ivitp Pointer to iterator. After this function returns,
2444 the current_element of the iterator will be the next interval
2445 after end.
2446 @param start The first GNO in the interval.
2447 @param end The first GNO after the interval.
2448 @param lock If this function has to add or remove an interval,
2449 then this lock will be taken unless it is already taken. This
2450 mechanism means that the lock will be taken lazily by
2451 e.g. add_gtid_set() the first time that the list of free intervals
2452 is accessed, and automatically released when add_gtid_set()
2453 returns.
2454 */
2455 void remove_gno_interval(Interval_iterator *ivitp, rpl_gno start, rpl_gno end,
2456 Free_intervals_lock *lock);
2457 /**
2458 Adds a list of intervals to the given SIDNO.
2459
2460 The SIDNO must exist in the Gtid_set before this function is called.
2461
2462 @param sidno The SIDNO to which intervals will be added.
2463 @param ivit Iterator over the intervals to add. This is typically
2464 an iterator over some other Gtid_set.
2465 @param lock If this function has to add or remove an interval,
2466 then this lock will be taken unless it is already taken. This
2467 mechanism means that the lock will be taken lazily by
2468 e.g. add_gtid_set() the first time that the list of free intervals
2469 is accessed, and automatically released when add_gtid_set()
2470 returns.
2471 */
2472 void add_gno_intervals(rpl_sidno sidno, Const_interval_iterator ivit,
2473 Free_intervals_lock *lock);
2474 /**
2475 Removes a list of intervals from the given SIDNO.
2476
2477 It is not required that the intervals exist in this Gtid_set.
2478
2479 @param sidno The SIDNO from which intervals will be removed.
2480 @param ivit Iterator over the intervals to remove. This is typically
2481 an iterator over some other Gtid_set.
2482 @param lock If this function has to add or remove an interval,
2483 then this lock will be taken unless it is already taken. This
2484 mechanism means that the lock will be taken lazily by
2485 e.g. add_gtid_set() the first time that the list of free intervals
2486 is accessed, and automatically released when add_gtid_set()
2487 returns.
2488 */
2489 void remove_gno_intervals(rpl_sidno sidno, Const_interval_iterator ivit,
2490 Free_intervals_lock *lock);
2491
2492 /// Returns true if every interval of sub is a subset of some
2493 /// interval of super.
2494 static bool is_interval_subset(Const_interval_iterator *sub,
2495 Const_interval_iterator *super);
2496 /// Returns true if at least one sidno in ivit1 is also in ivit2.
2497 static bool is_interval_intersection_nonempty(Const_interval_iterator *ivit1,
2498 Const_interval_iterator *ivit2);
2499
2500 /// Tsid_map associated with this Gtid_set.
2502 /**
2503 Array where the N'th element contains the head pointer to the
2504 intervals of SIDNO N+1.
2505 */
2507 /// Linked list of free intervals.
2509 /// Linked list of chunks.
2511 /// If the string is cached.
2513 /// The string length.
2514 mutable size_t cached_string_length;
2515 /// The String_format that was used when cached_string_length was computed.
2517#ifndef NDEBUG
2518 /**
2519 The number of chunks. Used only to check some invariants when
2520 DBUG is on.
2521 */
2523#endif
2524 /// Used by unit tests that need to access private members.
2525#ifdef FRIEND_OF_GTID_SET
2526 friend FRIEND_OF_GTID_SET;
2527#endif
2528 /// Only Free_intervals_lock is allowed to access free_intervals_mutex.
2530};
2531
2532/**
2533 Holds information about a Gtid_set. Can also be NULL.
2534
2535 This is used as backend storage for @@session.gtid_next_list. The
2536 idea is that we allow the user to set this to NULL, but we keep the
2537 Gtid_set object so that we can re-use the allocated memory and
2538 avoid costly allocations later.
2539
2540 This is stored in struct system_variables (defined in sql_class.h),
2541 which is cleared using memset(0); hence the negated form of
2542 is_non_null.
2543
2544 The convention is: if is_non_null is false, then the value of the
2545 session variable is NULL, and the field gtid_set may be NULL or
2546 non-NULL. If is_non_null is true, then the value of the session
2547 variable is not NULL, and the field gtid_set has to be non-NULL.
2548
2549 This is a POD. It has to be a POD because it is stored in
2550 THD::variables.
2551*/
2553 /// Pointer to the Gtid_set.
2555 /// True if this Gtid_set is NULL.
2557 /// Return NULL if this is NULL, otherwise return the Gtid_set.
2558 inline Gtid_set *get_gtid_set() const {
2559 assert(!(is_non_null && gtid_set == nullptr));
2560 return is_non_null ? gtid_set : nullptr;
2561 }
2562 /**
2563 Do nothing if this object is non-null; set to empty set otherwise.
2564
2565 @return NULL if out of memory; Gtid_set otherwise.
2566 */
2568 if (!is_non_null) {
2569 if (gtid_set == nullptr)
2570 gtid_set = new Gtid_set(sm);
2571 else
2572 gtid_set->clear();
2573 }
2574 is_non_null = (gtid_set != nullptr);
2575 return gtid_set;
2576 }
2577 /// Set this Gtid_set to NULL.
2578 inline void set_null() { is_non_null = false; }
2579};
2580
2581/**
2582 Represents the set of GTIDs that are owned by some thread.
2583
2584 This data structure has a read-write lock that protects the number
2585 of SIDNOs. The lock is provided by the invoker of the constructor
2586 and it is generally the caller's responsibility to acquire the read
2587 lock. Access methods assert that the caller already holds the read
2588 (or write) lock. If a method of this class grows the number of
2589 SIDNOs, then the method temporarily upgrades this lock to a write
2590 lock and then degrades it to a read lock again; there will be a
2591 short period when the lock is not held at all.
2592
2593 The internal representation is a multi-valued map from GTIDs to
2594 threads, mapping GTIDs to one or more threads that owns it.
2595
2596 In Group Replication multiple threads can own a GTID whereas if GR
2597 is disabeld there is at most one owner per GTID.
2598*/
2600 public:
2601 /**
2602 Constructs a new, empty Owned_gtids object.
2603
2604 @param tsid_lock Read-write lock that protects updates to the
2605 number of TSIDs.
2606 */
2608 /// Destroys this Owned_gtids.
2609 ~Owned_gtids();
2610 /**
2611 Add a GTID to this Owned_gtids.
2612
2613 @param gtid The Gtid to add.
2614 @param owner The my_thread_id of the gtid to add.
2615 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2616 */
2618
2619 /*
2620 Fill all gtids into the given Gtid_set object. It doesn't clear the given
2621 gtid set before filling its owned gtids into it.
2622 */
2623 void get_gtids(Gtid_set &gtid_set) const;
2624 /**
2625 Removes the given GTID.
2626
2627 If the gtid does not exist in this Owned_gtids object, does
2628 nothing.
2629
2630 @param gtid The Gtid.
2631 @param owner thread_id of the owner thread
2632 */
2633 void remove_gtid(const Gtid &gtid, const my_thread_id owner);
2634 /**
2635 Ensures that this Owned_gtids object can accommodate SIDNOs up to
2636 the given SIDNO.
2637
2638 If this Owned_gtids object needs to be resized, then the lock
2639 will be temporarily upgraded to a write lock and then degraded to
2640 a read lock again; there will be a short period when the lock is
2641 not held at all.
2642
2643 @param sidno The SIDNO.
2644 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2645 */
2647 /// Returns true if there is a least one element of this Owned_gtids
2648 /// set in the other Gtid_set.
2649 bool is_intersection_nonempty(const Gtid_set *other) const;
2650 /// Returns true if this Owned_gtids is empty.
2651 bool is_empty() const {
2652 Gtid_iterator git(this);
2653 return git.get().sidno == 0;
2654 }
2655 /// Returns the maximal sidno that this Owned_gtids currently has space for.
2657 if (tsid_lock != nullptr) {
2659 }
2660 return static_cast<rpl_sidno>(sidno_to_hash.size());
2661 }
2662
2663 /**
2664 Write a string representation of this Owned_gtids to the given buffer.
2665
2666 @param out Buffer to write to.
2667 @return Number of characters written.
2668 */
2669 int to_string(char *out) const {
2670 char *p = out;
2671 rpl_sidno max_sidno = get_max_sidno();
2672 for (const auto &sid_it : global_tsid_map->get_sorted_sidno()) {
2673 rpl_sidno sidno = sid_it.second;
2674 if (sidno > max_sidno) continue;
2675 bool printed_sid = false;
2676 for (const auto &key_and_value : *get_hash(sidno)) {
2677 Node *node = key_and_value.second.get();
2678 assert(node != nullptr);
2679 if (!printed_sid) {
2681 printed_sid = true;
2682 }
2683 p += sprintf(p, ":%" PRId64 "#%u", node->gno, node->owner);
2684 }
2685 }
2686 *p = 0;
2687 return (int)(p - out);
2688 }
2689
2690 /**
2691 Return an upper bound on the length of the string representation
2692 of this Owned_gtids. The actual length may be smaller. This
2693 includes the trailing '\0'.
2694 */
2695 size_t get_max_string_length() const {
2696 rpl_sidno max_sidno = get_max_sidno();
2697 size_t ret = 0;
2698 for (rpl_sidno sidno = 1; sidno <= max_sidno; sidno++) {
2699 size_t records = get_hash(sidno)->size();
2700 if (records > 0)
2701 ret +=
2703 records * (1 + MAX_GNO_TEXT_LENGTH + 1 + MAX_THREAD_ID_TEXT_LENGTH);
2704 }
2705 return 1 + ret;
2706 }
2707
2708 /**
2709 Return true if the given thread is the owner of any gtids.
2710 */
2712 Gtid_iterator git(this);
2713 Node *node = git.get_node();
2714 while (node != nullptr) {
2715 if (node->owner == thd_id) return true;
2716 git.next();
2717 node = git.get_node();
2718 }
2719 return false;
2720 }
2721
2722#ifndef NDEBUG
2723 /**
2724 Debug only: return a newly allocated string representation of
2725 this Owned_gtids.
2726 */
2727 char *to_string() const {
2730 assert(str != nullptr);
2731 to_string(str);
2732 return str;
2733 }
2734 /// Debug only: print this Owned_gtids to stdout.
2735 void print() const {
2736 char *str = to_string();
2737 printf("%s\n", str);
2738 my_free(str);
2739 }
2740#endif
2741 /**
2742 Print this Owned_gtids to the trace file if debug is enabled; no-op
2743 otherwise.
2744 */
2745 void dbug_print(const char *text [[maybe_unused]] = "") const {
2746#ifndef NDEBUG
2747 char *str = to_string();
2748 DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", str));
2749 my_free(str);
2750#endif
2751 }
2752
2753 /**
2754 If thd_id==0, returns true when gtid is not owned by any thread.
2755 If thd_id!=0, returns true when gtid is owned by that thread.
2756 */
2757 bool is_owned_by(const Gtid &gtid, const my_thread_id thd_id) const;
2758
2759 /**
2760 Returns true iff the given GTID is owned by exactly the given thread ID.
2761
2762 Unlike is_owned_by(), this does not treat thd_id==0 as a special
2763 "unowned" query.
2764 */
2765 bool has_owner(const Gtid &gtid, const my_thread_id thd_id) const;
2766
2767 private:
2768 /// Represents one owned GTID.
2769 struct Node {
2770 /// GNO of the GTID.
2772 /// Owner of the GTID.
2774 };
2775 /// Read-write lock that protects updates to the number of TSIDs.
2777 /// Returns the hash for the given SIDNO.
2779 rpl_sidno sidno) const {
2780 assert(sidno >= 1 && sidno <= get_max_sidno());
2781 if (tsid_lock != nullptr) {
2783 }
2784 return sidno_to_hash[sidno - 1];
2785 }
2786 /// Return true iff this Owned_gtids object contains the given gtid.
2787 bool contains_gtid(const Gtid &gtid) const;
2788
2789 /// Growable array of hashes.
2793
2794 public:
2795 /**
2796 Iterator over all gtids in a Owned_gtids set. This is a const
2797 iterator; it does not allow modification of the set.
2798 */
2800 public:
2802 : owned_gtids(og), sidno(1), hash(nullptr), node(nullptr) {
2804 if (sidno <= max_sidno) {
2806 node_it = hash->begin();
2807 }
2808 next();
2809 }
2810 /// Advance to next GTID.
2811 inline void next() {
2812#ifndef NDEBUG
2814#endif
2815
2816 while (sidno <= max_sidno) {
2817 assert(hash != nullptr);
2818 if (node_it != hash->end()) {
2819 node = node_it->second.get();
2820 assert(node != nullptr);
2821 // Jump to next node on next iteration.
2822 ++node_it;
2823 return;
2824 }
2825
2826 // hash is initialized on constructor or in previous iteration
2827 // for current SIDNO, so we must increment for next iteration.
2828 sidno++;
2829 if (sidno <= max_sidno) {
2831 node_it = hash->begin();
2832 }
2833 }
2834 node = nullptr;
2835 }
2836 /// Return next GTID, or {0,0} if we reached the end.
2837 inline Gtid get() const {
2838 Gtid ret = {0, 0};
2839 if (node) {
2840 ret.sidno = sidno;
2841 ret.gno = node->gno;
2842 }
2843 return ret;
2844 }
2845 /// Return the current GTID Node, or NULL if we reached the end.
2846 inline Node *get_node() const { return node; }
2847
2848 private:
2849 /// The Owned_gtids set we iterate over.
2851 /// The SIDNO of the current element, or 1 in the initial iteration.
2853 /// Max SIDNO of the current iterator.
2855 /// Current SIDNO hash.
2857 /// Current node iterator on current SIDNO hash.
2860 /// Current node on current SIDNO hash.
2862 };
2863};
2864
2865/**
2866 Represents the server's GTID state: the set of committed GTIDs, the
2867 set of lost gtids, the set of owned gtids, the owner of each owned
2868 gtid, and a Mutex_cond_array that protects updates to gtids of
2869 each SIDNO.
2870
2871 Locking:
2872
2873 This data structure has a read-write lock that protects the number
2874 of SIDNOs, and a Mutex_cond_array that contains one mutex per SIDNO.
2875 The rwlock is always the global_tsid_lock.
2876
2877 Access methods generally assert that the caller already holds the
2878 appropriate lock:
2879
2880 - before accessing any global data, hold at least the rdlock.
2881
2882 - before accessing a specific SIDNO in a Gtid_set or Owned_gtids
2883 (e.g., calling Gtid_set::_add_gtid(Gtid)), hold either the rdlock
2884 and the SIDNO's mutex lock; or the wrlock. If you need to hold
2885 multiple mutexes, they must be acquired in order of increasing
2886 SIDNO.
2887
2888 - before starting an operation that needs to access all SIDs
2889 (e.g. Gtid_set::to_string()), hold the wrlock.
2890
2891 The access type (read/write) does not matter; the write lock only
2892 implies that the entire data structure is locked whereas the read
2893 lock implies that everything except TSID-specific data is locked.
2894*/
2896 public:
2897 /**
2898 Constructs a new Gtid_state object.
2899
2900 @param _tsid_lock Read-write lock that protects updates to the
2901 number of TSIDs.
2902 @param _tsid_map Tsid_map used by this Gtid_state.
2903 */
2904 Gtid_state(Checkable_rwlock *_tsid_lock, Tsid_map *_tsid_map)
2905 : tsid_lock(_tsid_lock),
2906 tsid_map(_tsid_map),
2914 /**
2915 Add @@GLOBAL.SERVER_UUID to this binlog's Tsid_map.
2916
2917 This can't be done in the constructor because the constructor is
2918 invoked at server startup before SERVER_UUID is initialized.
2919
2920 The caller must hold the read lock or write lock on tsid_locks
2921 before invoking this function.
2922
2923 @retval 0 Success
2924 @retval 1 Error (out of memory or IO error).
2925 */
2926 int init();
2927 /**
2928 Reset the state and persistor after RESET BINARY LOGS AND GTIDS:
2929 remove all logged and lost gtids, but keep owned gtids as they are.
2930
2931 The caller must hold the write lock on tsid_lock before calling
2932 this function.
2933
2934 @param thd Thread requesting to reset the persistor
2935
2936 @retval 0 Success
2937 @retval -1 Error
2938 */
2939 int clear(THD *thd);
2940 /**
2941 Returns true if the given GTID is logged.
2942
2943 @param gtid The Gtid to check.
2944
2945 @retval true The gtid is logged in the binary log.
2946 @retval false The gtid is not logged in the binary log.
2947 */
2948 bool is_executed(const Gtid &gtid) const {
2949 DBUG_TRACE;
2951 bool ret = executed_gtids.contains_gtid(gtid);
2952 return ret;
2953 }
2954 /**
2955 Returns true if GTID is owned, otherwise returns 0.
2956
2957 @param gtid The Gtid to check.
2958 @return true if some thread owns the gtid, false if the gtid is
2959 not owned
2960 */
2961 bool is_owned(const Gtid &gtid) const {
2962 return !owned_gtids.is_owned_by(gtid, 0);
2963 }
2964#ifdef MYSQL_SERVER
2965 /**
2966 Acquires ownership of the given GTID, on behalf of the given thread.
2967
2968 The caller must lock the SIDNO before invoking this function.
2969
2970 @param thd The thread that will own the GTID.
2971 @param gtid The Gtid to acquire ownership of.
2972 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2973 */
2974 enum_return_status acquire_ownership(THD *thd, const Gtid &gtid);
2975 /**
2976 This function updates both the THD and the Gtid_state to reflect that
2977 the transaction set of transactions has ended, and it does this for the
2978 whole commit group (by following the thd->next_to_commit pointer).
2979
2980 It will:
2981
2982 - Clean up the thread state when a thread owned GTIDs is empty.
2983 - Release ownership of all GTIDs owned by the THDs. This removes
2984 the GTIDs from Owned_gtids and clears the ownership status in the
2985 THDs object.
2986 - Add the owned GTIDs to executed_gtids when the thread is committing.
2987 - Decrease counters of GTID-violating transactions.
2988 - Send a broadcast on the condition variable for every sidno for
2989 which we released ownership.
2990
2991 @param first_thd The first thread of the group commit that needs GTIDs to
2992 be updated.
2993 */
2994 void update_commit_group(THD *first_thd);
2995 /**
2996 Remove the GTID owned by thread from owned GTIDs, stating that
2997 thd->owned_gtid was committed.
2998
2999 This will:
3000 - remove owned GTID from owned_gtids;
3001 - remove all owned GTIDS from thd->owned_gtid and thd->owned_gtid_set;
3002
3003 @param thd Thread for which owned gtids are updated.
3004 */
3005 void update_on_commit(THD *thd);
3006 /**
3007 Update the state after the given thread has rollbacked.
3008
3009 This will:
3010 - release ownership of all GTIDs owned by the THD;
3011 - remove owned GTID from owned_gtids;
3012 - remove all owned GTIDS from thd->owned_gtid and thd->owned_gtid_set;
3013 - send a broadcast on the condition variable for every sidno for
3014 which we released ownership.
3015
3016 @param thd Thread for which owned gtids are updated.
3017 */
3018 void update_on_rollback(THD *thd);
3019
3020 /**
3021 Acquire anonymous ownership.
3022
3023 The caller must hold either tsid_lock.rdlock or
3024 tsid_lock.wrlock. (The caller must have taken the lock and checked
3025 that gtid_mode!=ON before calling this function, or else the
3026 gtid_mode could have changed to ON by a concurrent SET GTID_MODE.)
3027 */
3029 DBUG_TRACE;
3031 assert(global_gtid_mode.get() != Gtid_mode::ON);
3032#ifndef NDEBUG
3033 int32 new_value =
3034#endif
3036 DBUG_PRINT("info",
3037 ("atomic_anonymous_gtid_count increased to %d", new_value));
3038 assert(new_value >= 1);
3039 return;
3040 }
3041
3042 /// Release anonymous ownership.
3044 DBUG_TRACE;
3046 assert(global_gtid_mode.get() != Gtid_mode::ON);
3047#ifndef NDEBUG
3048 int32 new_value =
3049#endif
3051 DBUG_PRINT("info",
3052 ("atomic_anonymous_gtid_count decreased to %d", new_value));
3053 assert(new_value >= 0);
3054 return;
3055 }
3056
3057 /// Return the number of clients that hold anonymous ownership.
3059
3060 /**
3061 Increase the global counter when starting a GTID-violating
3062 transaction having GTID_NEXT=AUTOMATIC.
3063 */
3065 DBUG_TRACE;
3068#ifndef NDEBUG
3069 int32 new_value =
3070#endif
3072 DBUG_PRINT(
3073 "info",
3074 ("ongoing_automatic_gtid_violating_transaction_count increased to %d",
3075 new_value));
3076 assert(new_value >= 1);
3077 return;
3078 }
3079
3080 /**
3081 Decrease the global counter when ending a GTID-violating
3082 transaction having GTID_NEXT=AUTOMATIC.
3083 */
3085 DBUG_TRACE;
3086#ifndef NDEBUG
3091 int32 new_value =
3092#endif
3094 DBUG_PRINT(
3095 "info",
3096 ("ongoing_automatic_gtid_violating_transaction_count decreased to %d",
3097 new_value));
3098 assert(new_value >= 0);
3099 return;
3100 }
3101
3102 /**
3103 Return the number of ongoing GTID-violating transactions having
3104 GTID_NEXT=AUTOMATIC.
3105 */
3108 }
3109
3110 /**
3111 Increase the global counter when starting a GTID-violating
3112 transaction having GTID_NEXT=ANONYMOUS.
3113 */
3115 DBUG_TRACE;
3116 assert(global_gtid_mode.get() != Gtid_mode::ON);
3118#ifndef NDEBUG
3119 int32 new_value =
3120#endif
3122 DBUG_PRINT("info", ("atomic_anonymous_gtid_violation_count increased to %d",
3123 new_value));
3124 assert(new_value >= 1);
3125 return;
3126 }
3127
3128 /**
3129 Decrease the global counter when ending a GTID-violating
3130 transaction having GTID_NEXT=ANONYMOUS.
3131 */
3133 DBUG_TRACE;
3134#ifndef NDEBUG
3136 assert(global_gtid_mode.get() != Gtid_mode::ON);
3139 int32 new_value =
3140#endif
3142 DBUG_PRINT(
3143 "info",
3144 ("ongoing_anonymous_gtid_violating_transaction_count decreased to %d",
3145 new_value));
3146 assert(new_value >= 0);
3147 return;
3148 }
3149
3151
3152 /**
3153 Return the number of ongoing GTID-violating transactions having
3154 GTID_NEXT=AUTOMATIC.
3155 */
3158 }
3159
3160 /**
3161 Increase the global counter when starting a call to
3162 WAIT_FOR_EXECUTED_GTID_SET.
3163 */
3165 DBUG_TRACE;
3166 assert(global_gtid_mode.get() != Gtid_mode::OFF);
3167#ifndef NDEBUG
3168 int32 new_value =
3169#endif
3171 DBUG_PRINT("info", ("atomic_gtid_wait_count changed from %d to %d",
3172 new_value - 1, new_value));
3173 assert(new_value >= 1);
3174 return;
3175 }
3176
3177 /**
3178 Decrease the global counter when ending a call to
3179 WAIT_FOR_EXECUTED_GTID_SET.
3180 */
3182 DBUG_TRACE;
3183 assert(global_gtid_mode.get() != Gtid_mode::OFF);
3184#ifndef NDEBUG
3185 int32 new_value =
3186#endif
3188 DBUG_PRINT("info", ("atomic_gtid_wait_count changed from %d to %d",
3189 new_value + 1, new_value));
3190 assert(new_value >= 0);
3191 return;
3192 }
3193
3194 /**
3195 Return the number of clients that have an ongoing call to
3196 WAIT_FOR_EXECUTED_GTID_SET.
3197 */
3199
3200#endif // ifdef MYSQL_SERVER
3201 /**
3202 Computes the next available GNO.
3203
3204 @param sidno The GTID's SIDNO.
3205
3206 @retval -1 The range of GNOs was exhausted (i.e., more than 1<<63-1
3207 GTIDs with the same UUID have been generated).
3208 @retval >0 The GNO for the GTID.
3209 */
3210 rpl_gno get_automatic_gno(rpl_sidno sidno) const;
3211
3212 private:
3213 /**
3214 The next_free_gno map contains next_free_gno for recorded sidnos.
3215 The next_free_gno variable will be set with the supposed next free GNO
3216 every time a new GNO is delivered automatically or when a transaction is
3217 rolled back, releasing a GNO smaller than the last one delivered.
3218 It was introduced in an optimization of Gtid_state::get_automatic_gno and
3219 Gtid_state::generate_automatic_gtid functions.
3220
3221 Locking scheme
3222
3223 This variable can be read and modified in four places:
3224 - During server startup, holding global_tsid_lock.wrlock;
3225 - By a client thread holding global_tsid_lock.wrlock
3226 when executing RESET BINARY LOGS AND GTIDS
3227 - By a client thread calling MYSQL_BIN_LOG::write_transaction function
3228 (often the group commit FLUSH stage leader). It will call
3229 Gtid_state::generate_automatic_gtid, that will acquire
3230 global_tsid_lock.rdlock and lock_sidno(get_server_sidno()) when getting a
3231 new automatically generated GTID;
3232 - By a client thread rolling back, holding global_tsid_lock.rdlock
3233 and lock_sidno(get_server_sidno()).
3234 */
3235 std::unordered_map<rpl_sidno, rpl_gno> next_free_gno_map;
3236
3237 public:
3240 /**
3241 Return the last executed GNO for a given SIDNO, e.g.
3242 for the following set: UUID:1-10, UUID:12, UUID:15-20
3243 20 will be returned.
3244
3245 @param sidno The GTID's SIDNO.
3246
3247 @retval The GNO or 0 if set is empty.
3248 */
3250
3251 /**
3252 Generates the GTID (or ANONYMOUS, if GTID_MODE = OFF or
3253 OFF_PERMISSIVE) for the THD, and acquires ownership.
3254 Before this function, the caller needs to assign sidnos for automatic
3255 transactions and lock sidno_set (see specify_transaction_sidno).
3256
3257 @param thd The thread.
3258 @param specified_sidno Externally generated sidno.
3259 @param specified_gno Externally generated gno.
3260 @see Locked_sidno_set
3261
3262 @return RETURN_STATUS_OK or RETURN_STATUS_ERROR. Error can happen
3263 in case of out of memory or if the range of GNOs was exhausted.
3264 */
3266 rpl_sidno specified_sidno = 0,
3267 rpl_gno specified_gno = 0);
3268
3269 /// @brief Determines sidno for thd transaction. In case transaction
3270 /// is automatic, sidno is generated and added to sidno_set for future
3271 /// locking (after all transactions from binlog commit group have been added)
3272 /// @details The usage scheme is as follows: transaction for the binlog
3273 /// commit group are assigned a sidno. Sidnos are added to sidno_set in this
3274 /// function.
3275 /// Afterwards, sidno_set must be locked by the caller. This operation must
3276 /// be performed before the call to generate_automatic_gtid
3277 /// @returns sidno specified for thd transaction
3279 Gtid_state::Locked_sidno_set &sidno_set);
3280
3281 /// Locks a mutex for the given SIDNO.
3282 void lock_sidno(rpl_sidno sidno) { tsid_locks.lock(sidno); }
3283 /// Unlocks a mutex for the given SIDNO.
3284 void unlock_sidno(rpl_sidno sidno) { tsid_locks.unlock(sidno); }
3285 /// Broadcasts updates for the given SIDNO.
3287 /// Assert that we own the given SIDNO.
3289 tsid_locks.assert_owner(sidno);
3290 }
3291#ifdef MYSQL_SERVER
3292 /**
3293 Wait for a signal on the given SIDNO.
3294
3295 NOTE: This releases a lock!
3296
3297 This requires that the caller holds a read lock on tsid_lock. It
3298 will release the lock before waiting; neither global_tsid_lock nor
3299 the mutex lock on SIDNO will not be held when this function
3300 returns.
3301
3302 @param thd THD object of the caller.
3303 @param sidno Sidno to wait for.
3304 @param[in] abstime The absolute point in time when the wait times
3305 out and stops, or NULL to wait indefinitely.
3306 @param[in] update_thd_status when true updates the stage info with
3307 the new wait condition, when false keeps the current stage info.
3308
3309 @retval false Success.
3310 @retval true Failure: either timeout or thread was killed. If
3311 thread was killed, the error has been generated.
3312 */
3313 bool wait_for_sidno(THD *thd, rpl_sidno sidno, struct timespec *abstime,
3314 bool update_thd_status = true);
3315 /**
3316 This is only a shorthand for wait_for_sidno, which contains
3317 additional debug printouts and assertions for the case when the
3318 caller waits for one specific GTID.
3319 */
3320 bool wait_for_gtid(THD *thd, const Gtid &gtid,
3321 struct timespec *abstime = nullptr);
3322 /**
3323 Wait until the given Gtid_set is included in @@GLOBAL.GTID_EXECUTED.
3324
3325 @param thd The calling thread.
3326 @param gtid_set Gtid_set to wait for.
3327 @param[in] timeout The maximum number of milliseconds that the
3328 function should wait, or 0 to wait indefinitely.
3329 @param[in] update_thd_status when true updates the stage info with
3330 the new wait condition, when false keeps the current stage info.
3331
3332 @retval false Success.
3333 @retval true Failure: either timeout or thread was killed. If
3334 thread was killed, the error has been generated.
3335 */
3336 bool wait_for_gtid_set(THD *thd, Gtid_set *gtid_set, double timeout,
3337 bool update_thd_status = true);
3338#endif // ifdef MYSQL_SERVER
3339 /**
3340 Locks one mutex for each SIDNO where the given Gtid_set has at
3341 least one GTID. Locks are acquired in order of increasing SIDNO.
3342 */
3343 void lock_sidnos(const Gtid_set *set);
3344 /**
3345 Unlocks the mutex for each SIDNO where the given Gtid_set has at
3346 least one GTID.
3347 */
3348 void unlock_sidnos(const Gtid_set *set);
3349 /**
3350 Broadcasts the condition variable for each SIDNO where the given
3351 Gtid_set has at least one GTID.
3352 */
3353 void broadcast_sidnos(const Gtid_set *set);
3354 /**
3355 Ensure that owned_gtids, executed_gtids, lost_gtids, gtids_only_in_table,
3356 previous_gtids_logged and tsid_locks have room for at least as many SIDNOs
3357 as tsid_map.
3358
3359 This function must only be called in one place:
3360 Tsid_map::add_tsid().
3361
3362 Requires that the write lock on tsid_locks is held. If any object
3363 needs to be resized, then the lock will be temporarily upgraded to
3364 a write lock and then degraded to a read lock again; there will be
3365 a short period when the lock is not held at all.
3366
3367 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
3368 */
3370
3371 /**
3372 Adds the given Gtid_set to lost_gtids and executed_gtids.
3373 lost_gtids must be a subset of executed_gtids.
3374 purged_gtid and executed_gtid sets are appended with the argument set
3375 provided the latter is disjoint with gtid_executed owned_gtids.
3376
3377 Requires that the caller holds global_tsid_lock.wrlock.
3378
3379 @param[in,out] gtid_set The gtid_set to add. If the gtid_set
3380 does not start with a plus sign (starts_with_plus is false),
3381 @@GLOBAL.GTID_PURGED will be removed from the gtid_set.
3382 @param starts_with_plus If true, the gtid_set passed is required to
3383 be disjoint from @@GLOBAL.GTID_PURGED; if false, the gtid_set passed
3384 is required to be a superset of @@GLOBAL.GTID_PURGED.
3385 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
3386 */
3387 enum_return_status add_lost_gtids(Gtid_set *gtid_set, bool starts_with_plus);
3388
3389 /** Updates previously logged GTID set before writing to table. */
3390 void update_prev_gtids(Gtid_set *write_gtid_set);
3391
3392 /// Return a pointer to the Gtid_set that contains the lost gtids.
3393 const Gtid_set *get_lost_gtids() const { return &lost_gtids; }
3394 /*
3395 Return a pointer to the Gtid_set that contains the stored gtids
3396 in gtid_executed table.
3397 */
3398 const Gtid_set *get_executed_gtids() const { return &executed_gtids; }
3399 /*
3400 Return a pointer to the Gtid_set that contains the stored gtids
3401 only in gtid_executed table, not in binlog files.
3402 */
3404 return &gtids_only_in_table;
3405 }
3406 /*
3407 Return a pointer to the Gtid_set that contains the previous stored
3408 gtids in the last binlog file.
3409 */
3411 return &previous_gtids_logged;
3412 }
3413 /// Return a pointer to the Owned_gtids that contains the owned gtids.
3414 const Owned_gtids *get_owned_gtids() const { return &owned_gtids; }
3415 /// Return the server's SIDNO
3417 /// Return the server's TSID
3418 const Tsid &get_server_tsid() const {
3420 }
3421
3422 /// Return the featured uuid TSID
3425 }
3426 /// Set the featured uuid, adding it to the global sid map and
3427 /// generating a sidno to it.
3428 ///
3429 /// @param uuid The uuid value.
3430 /// @return No value on success, error message otherwise.
3431 [[nodiscard]] std::optional<std::string> set_featured_uuid(const char *uuid);
3432
3433 /// @brief Increments atomic_automatic_tagged_gtid_session_count
3436 }
3437
3438 /// @brief Decrements atomic_automatic_tagged_gtid_session_count
3441 }
3442
3443 /// @brief Checks whether there are ongoing sessions executing transactions
3444 /// with GTID_NEXT set to AUTOMATIC:tag
3445 /// @return true in case there are ongoing sessions with GTID_NEXT set
3446 /// to automatic, tagged
3449 }
3450
3451#ifndef NDEBUG
3452 /**
3453 Debug only: Returns an upper bound on the length of the string
3454 generated by to_string(), not counting '\0'. The actual length
3455 may be shorter.
3456 */
3457 size_t get_max_string_length() const {
3462 }
3463 /// Debug only: Generate a string in the given buffer and return the length.
3464 int to_string(char *buf) const {
3465 char *p = buf;
3466 p += sprintf(p, "Executed GTIDs:\n");
3468 p += sprintf(p, "\nOwned GTIDs:\n");
3470 p += sprintf(p, "\nLost GTIDs:\n");
3471 p += lost_gtids.to_string(p);
3472 p += sprintf(p, "\nGTIDs only_in_table:\n");
3473 p += lost_gtids.to_string(p);
3474 return (int)(p - buf);
3475 }
3476 /// Debug only: return a newly allocated string, or NULL on out-of-memory.
3477 char *to_string() const {
3480 to_string(str);
3481 return str;
3482 }
3483 /// Debug only: print this Gtid_state to stdout.
3484 void print() const {
3485 char *str = to_string();
3486 printf("%s", str);
3487 my_free(str);
3488 }
3489#endif
3490 /**
3491 Print this Gtid_state to the trace file if debug is enabled; no-op
3492 otherwise.
3493 */
3494 void dbug_print(const char *text [[maybe_unused]] = "") const {
3495#ifndef NDEBUG
3497 char *str = to_string();
3498 DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", str));
3499 my_free(str);
3500#endif
3501 }
3502 /**
3503 Save gtid owned by the thd into executed_gtids variable
3504 and gtid_executed table.
3505
3506 @param thd Session to commit
3507 @retval
3508 0 OK
3509 @retval
3510 -1 Error
3511 */
3512 int save(THD *thd);
3513 /**
3514 Insert the gtid set into table.
3515
3516 @param gtid_set contains a set of gtid, which holds
3517 the sidno and the gno.
3518
3519 @retval
3520 0 OK
3521 @retval
3522 -1 Error
3523 */
3524 int save(const Gtid_set *gtid_set);
3525 /**
3526 Save the set of gtids logged in the last binlog into gtid_executed table.
3527
3528 @retval
3529 0 OK
3530 @retval
3531 -1 Error
3532 */
3534 /**
3535 Fetch gtids from gtid_executed table and store them into
3536 gtid_executed set.
3537
3538 @retval
3539 0 OK
3540 @retval
3541 1 The table was not found.
3542 @retval
3543 -1 Error
3544 */
3546 /**
3547 Compress the gtid_executed table, read each row by the PK(sid, gno_start)
3548 in increasing order, compress the first consecutive gtids range
3549 (delete consecutive gtids from the second consecutive gtid, then
3550 update the first gtid) within a single transaction.
3551
3552 @param thd Thread requesting to compress the table
3553
3554 @retval
3555 0 OK
3556 @retval
3557 1 The table was not found.
3558 @retval
3559 -1 Error
3560 */
3561 int compress(THD *thd);
3562#ifdef MYSQL_SERVER
3563 /**
3564 Push a warning to client if user is modifying the gtid_executed
3565 table explicitly by a non-XA transaction. Push an error to client
3566 if user is modifying it explicitly by a XA transaction.
3567
3568 @param thd Thread requesting to access the table
3569 @param table The table is being accessed.
3570
3571 @retval 0 No warning or error was pushed to the client.
3572 @retval 1 Push a warning to client.
3573 @retval 2 Push an error to client.
3574 */
3576#endif
3577
3578 private:
3579 /**
3580 Remove the GTID owned by thread from owned GTIDs.
3581
3582 This will:
3583
3584 - Clean up the thread state if the thread owned GTIDs is empty.
3585 - Release ownership of all GTIDs owned by the THD. This removes
3586 the GTID from Owned_gtids and clears the ownership status in the
3587 THD object.
3588 - Add the owned GTID to executed_gtids if the is_commit flag is
3589 set.
3590 - Decrease counters of GTID-violating transactions.
3591 - Send a broadcast on the condition variable for every sidno for
3592 which we released ownership.
3593
3594 @param[in] thd Thread for which owned gtids are updated.
3595 @param[in] is_commit If true, the update is for a commit (not a rollback).
3596 */
3597 void update_gtids_impl(THD *thd, bool is_commit);
3598#ifdef HAVE_GTID_NEXT_LIST
3599 /// Lock all SIDNOs owned by the given THD.
3600 void lock_owned_sidnos(const THD *thd);
3601#endif
3602 /// Unlock all SIDNOs owned by the given THD.
3603 void unlock_owned_sidnos(const THD *thd);
3604 /// Broadcast the condition for all SIDNOs owned by the given THD.
3605 void broadcast_owned_sidnos(const THD *thd);
3606 /// Read-write lock that protects updates to the number of TSIDs.
3608 /// The Tsid_map used by this Gtid_state.
3610 /// Contains one mutex/cond pair for every SIDNO.
3612 /**
3613 The set of GTIDs that existed in some previously purged binary log.
3614 This is always a subset of executed_gtids.
3615 */
3617 /*
3618 The set of GTIDs that has been executed and
3619 stored into gtid_executed table.
3620 */
3622 /*
3623 The set of GTIDs that exists only in gtid_executed table, not in
3624 binlog files.
3625 */
3627 /* The previous GTIDs in the last binlog. */
3629 /// The set of GTIDs that are owned by some thread.
3631 /// The SIDNO for this server.
3633 /// When featured_uuid_sidno is defined, greater than 0, the
3634 /// featured uuid is used as the originating server uuid on the
3635 /// automatic transaction identifier instead of the server_uuid.
3637
3638 /// The number of anonymous transactions owned by any client.
3639 std::atomic<int32> atomic_anonymous_gtid_count{0};
3640 /// The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC.
3642 /// The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC.
3644 /// The number of clients that are executing
3645 /// WAIT_FOR_EXECUTED_GTID_SET.
3646 std::atomic<int32> atomic_gtid_wait_count{0};
3647 /// The number of sessions that have GTID_NEXT set to AUTOMATIC with tag
3648 /// assigned
3650
3651 /// Used by unit tests that need to access private members.
3652#ifdef FRIEND_OF_GTID_STATE
3653 friend FRIEND_OF_GTID_STATE;
3654#endif
3655
3656 /**
3657 This is a sub task of update_on_rollback responsible only to handle
3658 the case of a thread that needs to skip GTID operations when it has
3659 "failed to commit".
3660
3661 Administrative commands [CHECK|REPAIR|OPTIMIZE|ANALYZE] TABLE
3662 are written to the binary log even when they fail. When the
3663 commands fail, they will call update_on_rollback; later they will
3664 write the binary log. But we must not do any of the things in
3665 update_gtids_impl if we are going to write the binary log. So
3666 these statements set the skip_gtid_rollback flag, which tells
3667 update_on_rollback to return early. When the statements are
3668 written to the binary log they will call update_on_commit as
3669 usual.
3670
3671 @param[in] thd - Thread to be evaluated.
3672
3673 @retval true The transaction should skip the rollback, false otherwise.
3674 */
3676 /**
3677 This is a sub task of update_gtids_impl responsible only to handle
3678 the case of a thread that owns nothing and does not violate GTID
3679 consistency.
3680
3681 If the THD does not own anything, there is nothing to do, so we can do an
3682 early return of the update process. Except if there is a GTID consistency
3683 violation; then we need to decrease the counter, so then we can continue
3684 executing inside update_gtids_impl.
3685
3686 @param[in] thd - Thread to be evaluated.
3687 @retval true The transaction can be skipped because it owns nothing and
3688 does not violate GTID consistency, false otherwise.
3689 */
3691 /**
3692 This is a sub task of update_gtids_impl responsible only to evaluate
3693 if the thread is committing in the middle of a statement by checking
3694 THD's is_commit_in_middle_of_statement flag.
3695
3696 This flag is true for anonymous transactions, when the
3697 'transaction' has been split into multiple transactions in the
3698 binlog, and the present transaction is not the last one.
3699
3700 This means two things:
3701
3702 - We should not release anonymous ownership in case
3703 gtid_next=anonymous. If we did, it would be possible for user
3704 to set GTID_MODE=ON from a concurrent transaction, making it
3705 impossible to commit the current transaction.
3706
3707 - We should not decrease the counters for GTID-violating
3708 statements. If we did, it would be possible for a concurrent
3709 client to set ENFORCE_GTID_CONSISTENCY=ON despite there is an
3710 ongoing transaction that violates GTID consistency.
3711
3712 The flag is set in two cases:
3713
3714 1. We are committing the statement cache when there are more
3715 changes in the transaction cache.
3716
3717 This happens either because a single statement in the
3718 beginning of a transaction updates both transactional and
3719 non-transactional tables, or because we are committing a
3720 non-transactional update in the middle of a transaction when
3721 binlog_direct_non_transactional_updates=1.
3722
3723 In this case, the flag is set further down in this function.
3724
3725 2. The statement is one of the special statements that may
3726 generate multiple transactions: CREATE...SELECT, DROP TABLE,
3727 DROP DATABASE. See comment for THD::owned_gtid in
3728 sql/sql_class.h.
3729
3730 In this case, the THD::is_commit_in_middle_of_statement flag
3731 is set by the caller and the flag becomes true here.
3732
3733 @param[in] thd - Thread to be evaluated.
3734 @return The value of thread's is_commit_in_middle_of_statement flag.
3735 */
3736 bool update_gtids_impl_begin(THD *thd);
3737 /**
3738 Handle the case that the thread own a set of GTIDs.
3739
3740 This is a sub task of update_gtids_impl responsible only to handle
3741 the case of a thread with a set of GTIDs being updated.
3742
3743 - Release ownership of the GTIDs owned by the THD. This removes
3744 the GTID from Owned_gtids and clears the ownership status in the
3745 THD object.
3746 - Add the owned GTIDs to executed_gtids if the is_commit flag is set.
3747 - Send a broadcast on the condition variable for the sidno which we
3748 released ownership.
3749
3750 @param[in] thd - Thread for which owned GTID set should be updated.
3751 @param[in] is_commit - If the thread is being updated by a commit.
3752 */
3753 void update_gtids_impl_own_gtid_set(THD *thd, bool is_commit);
3754 /**
3755 Lock a given sidno of a transaction being updated.
3756
3757 This is a sub task of update_gtids_impl responsible only to lock the
3758 sidno of the GTID being updated.
3759
3760 @param[in] sidno - The sidno to be locked.
3761 */
3763 /**
3764
3765 Locks the sidnos of all the GTIDs of the commit group starting on the
3766 transaction passed as parameter.
3767
3768 This is a sub task of update_commit_group responsible only to lock the
3769 sidno(s) of the GTID(s) being updated.
3770
3771 The function should follow thd->next_to_commit to lock all sidnos of all
3772 transactions being updated in a group.
3773
3774 @param[in] thd - Thread that owns the GTID(s) to be updated or leader
3775 of the commit group in the case of a commit group
3776 update.
3777 */
3779 /**
3780 Handle the case that the thread own a single non-anonymous GTID.
3781
3782 This is a sub task of update_gtids_impl responsible only to handle
3783 the case of a thread with a single non-anonymous GTID being updated
3784 either for commit or rollback.
3785
3786 - Release ownership of the GTID owned by the THD. This removes
3787 the GTID from Owned_gtids and clears the ownership status in the
3788 THD object.
3789 - Add the owned GTID to executed_gtids if the is_commit flag is set.
3790 - Send a broadcast on the condition variable for the sidno which we
3791 released ownership.
3792
3793 @param[in] thd - Thread to be updated that owns single non-anonymous GTID.
3794 @param[in] is_commit - If the thread is being updated by a commit.
3795 */
3796 void update_gtids_impl_own_gtid(THD *thd, bool is_commit);
3797 /**
3798 Unlock a given sidno after broadcasting its changes.
3799
3800 This is a sub task of update_gtids_impl responsible only to
3801 unlock the sidno of the GTID being updated after broadcasting
3802 its changes.
3803
3804 @param[in] sidno - The sidno to be broadcasted and unlocked.
3805 */
3807 /**
3808 Unlocks all locked sidnos after broadcasting their changes.
3809
3810 This is a sub task of update_commit_group responsible only to
3811 unlock the sidno(s) of the GTID(s) being updated after broadcasting
3812 their changes.
3813 */
3815 /**
3816 Handle the case that the thread owns ANONYMOUS GTID.
3817
3818 This is a sub task of update_gtids_impl responsible only to handle
3819 the case of a thread with an ANONYMOUS GTID being updated.
3820
3821 - Release ownership of the anonymous GTID owned by the THD and clears
3822 the ownership status in the THD object.
3823 - Decrease counters of GTID-violating transactions.
3824
3825 @param[in] thd - Thread to be updated that owns anonymous GTID.
3826 @param[in,out] more_trx - If the 'transaction' has been split into
3827 multiple transactions in the binlog.
3828 This is firstly assigned with the return of
3829 Gtid_state::update_gtids_impl_begin function, and
3830 its value can be set to true when
3831 Gtid_state::update_gtids_impl_anonymous_gtid
3832 detects more content on the transaction cache.
3833 */
3834 void update_gtids_impl_own_anonymous(THD *thd, bool *more_trx);
3835 /**
3836 Handle the case that the thread owns nothing.
3837
3838 This is a sub task of update_gtids_impl responsible only to handle
3839 the case of a thread that owns nothing being updated.
3840
3841 There are two cases when this happens:
3842 - Normally, it is a rollback of an automatic transaction, so
3843 the is_commit is false and gtid_next=automatic.
3844 - There is also a corner case. This case may happen for a transaction
3845 that uses GTID_NEXT=AUTOMATIC, and violates GTID_CONSISTENCY, and
3846 commits changes to the database, but does not write to the binary log,
3847 so that no GTID is generated. An example is CREATE TEMPORARY TABLE
3848 inside a transaction when binlog_format=row. Despite the thread does
3849 not own anything, the GTID consistency violation makes it necessary to
3850 call end_gtid_violating_transaction. Therefore
3851 MYSQL_BIN_LOG::gtid_end_transaction will call
3852 gtid_state->update_on_commit in this case, and subsequently we will
3853 reach this case.
3854
3855 @param[in] thd - Thread to be updated that owns anonymous GTID.
3856 */
3858 /**
3859 Handle the final part of update_gtids_impl.
3860
3861 This is a sub task of update_gtids_impl responsible only to handle
3862 the call to end_gtid_violating_transaction function when there is no
3863 more transactions split after the current transaction.
3864
3865 @param[in] thd - Thread for which owned GTID is updated.
3866 @param[in] more_trx - This is the value returned from
3867 Gtid_state::update_gtids_impl_begin and can be
3868 changed for transactions owning anonymous GTID at
3869 Gtid_state::update_gtids_impl_own_anonymous.
3870 */
3871 void update_gtids_impl_end(THD *thd, bool more_trx);
3872 /**
3873 This array is used by Gtid_state_update_gtids_impl* functions.
3874
3875 The array items (one per sidno of the tsid_map) will be set as true for
3876 each sidno that requires to be locked when updating a set of GTIDs
3877 (at Gtid_set::update_gtids_impl_lock_sidnos).
3878
3879 The array items will be set false at
3880 Gtid_set::update_gtids_impl_broadcast_and_unlock_sidnos.
3881
3882 It is used to so that lock, unlock, and broadcast operations are only
3883 called once per sidno per commit group, instead of once per transaction.
3884
3885 Its access is protected by:
3886 - global_tsid_lock->wrlock when growing and cleaning up;
3887 - MYSQL_BIN_LOG::LOCK_commit when setting true/false on array items.
3888 */
3890 /**
3891 Ensure that commit_group_sidnos have room for the SIDNO passed as
3892 parameter.
3893
3894 This function must only be called in one place:
3895 Gtid_state::ensure_sidno().
3896
3897 @param sidno The SIDNO.
3898 @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
3899 */
3901};
3902
3903/*
3904 BUG# #18089914 - REFACTORING: RENAME GROUP TO GTID
3905 changed AUTOMATIC_GROUP to AUTOMATIC_GTID
3906 changed ANONYMOUS_GROUP to ANONYMOUS_GTID
3907 changed INVALID_GROUP to INVALID_GTID
3908 changed UNDEFINED_GROUP to UNDEFINED_GTID
3909 changed GTID_GROUPto ASSIGNED_GTID
3910 changed NOT_YET_DETERMINED_GROUP to NOT_YET_DETERMINED_GTID
3911*/
3912
3913/**
3914 Enumeration of different types of values for Gtid_specification,
3915 i.e, the different internal states that @@session.gtid_next can be in.
3916*/
3918 /**
3919 Specifies that the GTID has not been generated yet; it will be
3920 generated on commit. It will depend on the GTID_MODE: if
3921 GTID_MODE<=OFF_PERMISSIVE, then the transaction will be anonymous;
3922 if GTID_MODE>=ON_PERMISSIVE, then the transaction will be assigned
3923 a new GTID.
3924
3925 In the latter case, the Gtid_specification may hold a tag. Then,
3926 the new GTID will be generated with that tag.
3927
3928 AUTOMATIC_GTID with an empty tag is the default value:
3929 thd->variables.gtid_next has this state when GTID_NEXT="AUTOMATIC".
3930
3931 It is important that AUTOMATIC_GTID==0 so that the default value
3932 for thd->variables->gtid_next.type is AUTOMATIC_GTID.
3933 */
3935 /**
3936 Specifies that the transaction has been assigned a GTID (UUID:NUMBER).
3937
3938 thd->variables.gtid_next has this state when GTID_NEXT="UUID:NUMBER".
3939
3940 This is the state of GTID-transactions replicated to the slave.
3941 */
3943 /**
3944 Specifies that the transaction is anonymous, i.e., it does not
3945 have a GTID and will never be assigned one.
3946
3947 thd->variables.gtid_next has this state when GTID_NEXT="ANONYMOUS".
3948
3949 This is the state of any transaction generated on a pre-GTID
3950 server, or on a server with GTID_MODE==OFF.
3951 */
3953 /**
3954 GTID_NEXT is set to this state after a transaction with
3955 GTID_NEXT=='UUID:NUMBER' is committed.
3956
3957 This is used to protect against a special case of unsafe
3958 non-transactional updates.
3959
3960 Background: Non-transactional updates are allowed as long as they
3961 are sane. Non-transactional updates must be single-statement
3962 transactions; they must not be mixed with transactional updates in
3963 the same statement or in the same transaction. Since
3964 non-transactional updates must be logged separately from
3965 transactional updates, a single mixed statement would generate two
3966 different transactions.
3967
3968 Problematic case: Consider a transaction, Tx1, that updates two
3969 transactional tables on the master, t1 and t2. Then slave (s1) later
3970 replays Tx1. However, t2 is a non-transactional table at s1. As such, s1
3971 will report an error because it cannot split Tx1 into two different
3972 transactions. Had no error been reported, then Tx1 would be split into Tx1
3973 and Tx2, potentially causing severe harm in case some form of fail-over
3974 procedure is later engaged by s1.
3975
3976 To detect this case on the slave and generate an appropriate error
3977 message rather than causing an inconsistency in the GTID state, we
3978 do as follows. When committing a transaction that has
3979 GTID_NEXT==UUID:NUMBER, we set GTID_NEXT to UNDEFINED_GTID. When
3980 the next part of the transaction is being processed, an error is
3981 generated, because it is not allowed to execute a transaction when
3982 GTID_NEXT==UNDEFINED. In the normal case, the error is not
3983 generated, because there will always be a Gtid_log_event after the
3984 next transaction.
3985 */
3987 /**
3988 GTID_NEXT is set to this state by the slave applier thread when it
3989 reads a Format_description_log_event that does not originate from
3990 this server.
3991
3992 Background: when the slave applier thread reads a relay log that
3993 comes from a pre-GTID master, it must preserve the transactions as
3994 anonymous transactions, even if GTID_MODE>=ON_PERMISSIVE. This
3995 may happen, e.g., if the relay log was received when master and
3996 slave had GTID_MODE=OFF or when master and slave were old, and the
3997 relay log is applied when slave has GTID_MODE>=ON_PERMISSIVE.
3998
3999 So the slave thread should set GTID_NEXT=ANONYMOUS for the next
4000 transaction when it starts to process an old binary log. However,
4001 there is no way for the slave to tell if the binary log is old,
4002 until it sees the first transaction. If the first transaction
4003 begins with a Gtid_log_event, we have the GTID there; if it begins
4004 with query_log_event, row events, etc, then this is an old binary
4005log. So at the time the binary log begins, we just set
4006 GTID_NEXT=NOT_YET_DETERMINED_GTID. If it remains
4007 NOT_YET_DETERMINED when the next transaction begins,
4008 gtid_pre_statement_checks will automatically turn it into an
4009 anonymous transaction. If a Gtid_log_event comes across before
4010 the next transaction starts, then the Gtid_log_event will just set
4011 GTID_NEXT='UUID:NUMBER' accordingly.
4012 */
4014 /**
4015 The applier sets GTID_NEXT this state internally, when it
4016 processes an Anonymous_gtid_log_event on a channel having
4017 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS, before it calls
4018 set_gtid_next. This tells set_gtid_next to generate a new,
4019 sequential GTID, and acquire ownership for it. Thus, this state
4020 is only used for a very brief period of time. It is not
4021 user-visible.
4022 */
4024};
4025/// Global state of GTIDs.
4026extern Gtid_state *gtid_state;
4027
4028/**
4029 This struct represents a specification of a GTID for a statement to
4030 be executed: either "AUTOMATIC", "AUTOMATIC:<tag>", "ANONYMOUS" or "TSID:GNO".
4031
4032 This is a POD. It has to be a POD because it is used in THD::variables.
4033*/
4035 // Constants used in gtid specification
4036 static constexpr auto str_automatic = "AUTOMATIC";
4037 static constexpr auto str_automatic_tagged = "AUTOMATIC:";
4038 static constexpr auto str_automatic_sep = ":";
4039 static constexpr auto str_pre_generated = "PRE_GENERATE_GTID";
4040 static constexpr auto str_not_yet_determined = "NOT_YET_DETERMINED";
4041 static constexpr auto str_anonymous = "ANONYMOUS";
4042
4046 /// The type of this GTID
4048 /**
4049 The GTID:
4050 { SIDNO, GNO } if type == GTID;
4051 { 0, 0 } if type == AUTOMATIC or ANONYMOUS.
4052 */
4054
4055 /// @brief Tag defined by the user while specifying GTID_NEXT="AUTOMATIC:TAG".
4056 /// We must store here the information about tag, because automatic
4057 /// tagged GTID does not have sidno assigned
4059
4060 /// @brief Prints automatic tag specification to the given buffer
4061 /// @param[in,out] buf Buffer to write to, must be allocated
4062 /// @return The number of bytes written to the buffer
4063 std::size_t automatic_to_string(char *buf) const;
4064
4065 /// Set the type to ASSIGNED_GTID and SIDNO, GNO to the given values.
4066 void set(rpl_sidno sidno, rpl_gno gno) {
4067 gtid.set(sidno, gno);
4070 }
4071
4072 /// @brief Helper function indicating whether this is to-be-generated GTID
4073 /// @param[in] type Type of the GTID
4074 /// @retval true This GTID will be generated
4075 /// @retval false Other type of the GTID
4076 static bool is_automatic(const enum_gtid_type &type) {
4077 return type == AUTOMATIC_GTID;
4078 }
4079 /// @brief Helper function indicating whether this is to-be-generated GTID
4080 /// @retval true This GTID will be generated
4081 /// @retval false Other type of the GTID
4082 bool is_automatic() const { return is_automatic(type); }
4083
4084 /// @brief Helper function indicating whether this is an undefined GTID
4085 /// @return Returns true for undefined GTIDs
4086 bool is_undefined() const { return type == UNDEFINED_GTID; }
4087
4088 /// @brief Helper function indicating whether this is an assigned GTID
4089 /// @return Returns true for assigned GTIDs
4090 bool is_assigned() const { return type == ASSIGNED_GTID; }
4091
4092 /// @brief Returns tag object generated from internal tag data
4093 /// @return Tag object
4094 Tag generate_tag() const;
4095
4096 /// @brief Helper function indicating whether this is to-be-generated GTID
4097 /// with a tag assigned
4098 /// @retval true This GTID will be generated with assigned tag
4099 /// @retval false Other type of the GTID
4100 bool is_automatic_tagged() const;
4101
4102 /// Set the type to ASSIGNED_GTID and TSID, GNO to the given Gtid.
4103 /// @brief gtid_param GTID to copy from
4104 void set(const Gtid &gtid_param) { set(gtid_param.sidno, gtid_param.gno); }
4105 /// @brief Set the type to AUTOMATIC_GTID.
4109 }
4110 /// @brief Copy spec from other
4111 /// @param[in] other Pattern to copy from
4112 void set(const Gtid_specification &other);
4113
4114 /// Set the type to ANONYMOUS_GTID.
4118 }
4119 /// Set the type to NOT_YET_DETERMINED_GTID.
4123 }
4124 /// Set to undefined. Must only be called if the type is ASSIGNED_GTID.
4126 assert(type == ASSIGNED_GTID);
4129 }
4130 /// Return true if this Gtid_specification is equal to 'other'.
4131 bool equals(const Gtid_specification &other) const {
4132 return (type == other.type &&
4133 (type != ASSIGNED_GTID || gtid.equals(other.gtid)));
4134 }
4135 /**
4136 Return true if this Gtid_specification is a ASSIGNED_GTID with the
4137 same TSID, GNO as 'other_gtid'.
4138 */
4139 bool equals(const Gtid &other_gtid) const {
4140 return type == ASSIGNED_GTID && gtid.equals(other_gtid);
4141 }
4142#ifdef MYSQL_SERVER
4143 /**
4144 Parses the given string and stores in this Gtid_specification.
4145
4146 @param tsid_map tsid_map to use when converting TSID to a sidno.
4147 @param text The text to parse
4148 @return operation status
4149 */
4150 [[nodiscard]] mysql::utils::Return_status parse(Tsid_map *tsid_map,
4151 const char *text);
4152
4153 /// @brief Returns true if the given string is a valid Gtid_specification.
4154 /// @param[in] text Textual representation of the GTID specification
4155 static bool is_valid(const char *text);
4156
4157 /// @brief Returns true if the given string is a tagged Gtid_specification.
4158 /// @param[in] text Textual representation of the GTID specification
4159 static bool is_tagged(const char *text);
4160#endif
4162 /**
4163 Writes this Gtid_specification to the given string buffer.
4164
4165 @param tsid_map Tsid_map to use if the type of this
4166 Gtid_specification is ASSIGNED_GTID.
4167 @param [out] buf The buffer
4168 @param need_lock If true, this function acquires global_tsid_lock
4169 before looking up the sidno in tsid_map, and then releases it. If
4170 false, this function asserts that the lock is held by the caller.
4171 @retval The number of characters written.
4172 */
4173 int to_string(const Tsid_map *tsid_map, char *buf,
4174 bool need_lock = false) const;
4175 /**
4176 Writes this Gtid_specification to the given string buffer.
4177
4178 @param tsid TSID to use if the type of this Gtid_specification is
4179 ASSIGNED_GTID. Can be NULL if this Gtid_specification is
4180 ANONYMOUS_GTID or AUTOMATIC_GTID.
4181 @param[out] buf The buffer
4182 @retval The number of characters written.
4183 */
4184 int to_string(const Tsid &tsid, char *buf) const;
4185
4186#ifndef NDEBUG
4187 /// Debug only: print this Gtid_specification to stdout.
4188 void print() const {
4189 char buf[MAX_TEXT_LENGTH + 1];
4191 printf("%s\n", buf);
4192 }
4193#endif
4194 /**
4195 Print this Gtid_specification to the trace file if debug is
4196 enabled; no-op otherwise.
4197 */
4198 void dbug_print(const char *text [[maybe_unused]] = "",
4199 bool need_lock [[maybe_unused]] = false) const {
4200#ifndef NDEBUG
4201 char buf[MAX_TEXT_LENGTH + 1];
4202 to_string(global_tsid_map, buf, need_lock);
4203 DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", buf));
4204#endif
4205 }
4206};
4207
4208static_assert(std::is_trivial_v<Gtid_specification>);
4209static_assert(std::is_standard_layout_v<Gtid_specification>);
4210
4211/**
4212 Indicates if a statement should be skipped or not. Used as return
4213 value from gtid_before_statement.
4214*/
4216 /// Statement can execute.
4218 /// Statement should be cancelled.
4220 /**
4221 Statement should be skipped, but there may be an implicit commit
4222 after the statement if gtid_commit is set.
4223 */
4226
4227#ifdef MYSQL_SERVER
4228
4229/**
4230 Check if current transaction should be skipped, that is, if GTID_NEXT
4231 was already logged.
4232
4233 @param thd The calling thread.
4234
4235 @retval true Transaction was already logged.
4236 @retval false Transaction must be executed.
4237*/
4238bool is_already_logged_transaction(const THD *thd);
4239
4240/**
4241 Perform GTID-related checks before executing a statement:
4242
4243 - Check that the current statement does not contradict
4244 enforce_gtid_consistency.
4245
4246 - Check that there is no implicit commit in a transaction when
4247 GTID_NEXT==UUID:NUMBER.
4248
4249 - Change thd->variables.gtid_next.type to ANONYMOUS_GTID if it is
4250 currently NOT_YET_DETERMINED_GTID.
4251
4252 - Check whether the statement should be cancelled.
4253
4254 @param thd THD object for the session.
4255
4256 @retval GTID_STATEMENT_EXECUTE The normal case: the checks
4257 succeeded, and statement can execute.
4258
4259 @retval GTID_STATEMENT_CANCEL The checks failed; an
4260 error has be generated and the statement must stop.
4261
4262 @retval GTID_STATEMENT_SKIP The checks succeeded, but the GTID has
4263 already been executed (exists in GTID_EXECUTED). So the statement
4264 must not execute; however, if there are implicit commits, then the
4265 implicit commits must execute.
4266*/
4268
4269/**
4270 Perform GTID-related checks before executing a statement, but after
4271 executing an implicit commit before the statement, if any:
4272
4273 If gtid_next=anonymous, but the thread does not hold anonymous
4274 ownership, then acquire anonymous ownership. (Do this only if this
4275 is not an 'innocent' statement, i.e., SET/SHOW/DO/SELECT that does
4276 not invoke a stored function.)
4277
4278 It is important that this is done after the implicit commit, because
4279 the implicit commit may release anonymous ownership.
4280
4281 @param thd THD object for the session
4282
4283 @retval false Success.
4284
4285 @retval true Error. Error can happen if GTID_MODE=ON. The error has
4286 been reported by (a function called by) this function.
4287*/
4289
4290/**
4291 Acquire ownership of the given Gtid_specification.
4292
4293 The Gtid_specification must be of type ASSIGNED_GTID or ANONYMOUS_GTID.
4294
4295 The caller must hold global_tsid_lock (normally the rdlock). The
4296 lock may be temporarily released and acquired again. In the end,
4297 the lock will be released, so the caller should *not* release the
4298 lock.
4299
4300 The function will try to acquire ownership of the GTID and update
4301 both THD::gtid_next, Gtid_state::owned_gtids, and
4302 THD::owned_gtid / THD::owned_sid.
4303
4304 @param thd The thread that acquires ownership.
4305
4306 @param spec The Gtid_specification.
4307
4308 @retval false Success: either we have acquired ownership of the
4309 GTID, or it is already included in GTID_EXECUTED and will be
4310 skipped.
4311
4312 @retval true Failure; the thread was killed or an error occurred.
4313 The error has been reported using my_error.
4314*/
4315bool set_gtid_next(THD *thd, const Gtid_specification &spec);
4316#ifdef HAVE_GTID_NEXT_LIST
4317int gtid_acquire_ownership_multiple(THD *thd);
4318#endif
4319
4320/**
4321 Return sidno for a given tsid, see Tsid_map::add_sid() for details.
4322*/
4324
4325/**
4326 Return Tsid for a given sidno on the global_tsid_map.
4327 See Tsid_map::sidno_to_tsid() for details.
4328*/
4330
4331/**
4332 Return last gno for a given sidno, see
4333 Gtid_state::get_last_executed_gno() for details.
4334*/
4336
4338
4339/**
4340 If gtid_next=ANONYMOUS or NOT_YET_DETERMINED, but the thread does
4341 not hold anonymous ownership, acquire anonymous ownership.
4342
4343 @param thd Thread.
4344
4345 @retval true Error (can happen if gtid_mode=ON and
4346 gtid_next=anonymous). The error has already been reported using
4347 my_error.
4348
4349 @retval false Success.
4350*/
4352
4353/**
4354 The function commits or rolls back the gtid state if it needs to.
4355 It's supposed to be invoked at the end of transaction commit or
4356 rollback, as well as as at the end of XA prepare.
4357
4358 @param thd Thread context
4359 @param needs_to The actual work will be done when the parameter is true
4360 @param do_commit When true the gtid state changes are committed, otherwise
4361 they are rolled back.
4362*/
4363
4364inline void gtid_state_commit_or_rollback(THD *thd, bool needs_to,
4365 bool do_commit) {
4366 if (needs_to) {
4367 if (do_commit)
4369 else
4371 }
4372}
4373
4374#endif // ifdef MYSQL_SERVER
4375
4376#endif /* RPL_GTID_H_INCLUDED */
Kerberos Client Authentication nullptr
Definition: auth_kerberos_client_plugin.cc:247
RAII class to acquire a lock for the duration of a block.
Definition: rpl_gtid.h:360
void unlock_if_locked()
Unlock the lock, if it was acquired by this guard.
Definition: rpl_gtid.h:468
Guard(Checkable_rwlock &lock, enum_lock_type lock_type)
Create a guard, and optionally acquire a lock on it.
Definition: rpl_gtid.h:368
Checkable_rwlock & m_lock
Definition: rpl_gtid.h:361
Guard(Checkable_rwlock &lock, enum_lock_type lock_type, std::adopt_lock_t t)
Create a guard, assuming the caller already holds a lock on it.
Definition: rpl_gtid.h:392
bool is_locked() const
Return true if this object is either read locked or write locked.
Definition: rpl_gtid.h:483
bool is_wrlocked() const
Return true if this object is write locked.
Definition: rpl_gtid.h:480
int tryrdlock()
Try to acquire a read lock, and fail if it cannot be immediately granted.
Definition: rpl_gtid.h:452
enum_lock_type m_lock_type
Definition: rpl_gtid.h:362
Guard(Guard const &copy)=delete
Objects of this class should not be copied or moved.
void unlock()
Unlock the lock.
Definition: rpl_gtid.h:461
void rdlock()
Acquire the read lock.
Definition: rpl_gtid.h:421
Guard(Guard const &&copy)=delete
bool is_rdlocked() const
Return true if this object is read locked.
Definition: rpl_gtid.h:477
~Guard()
Unlock on destruct.
Definition: rpl_gtid.h:415
Checkable_rwlock & get_lock() const
Return the underlying Checkable_rwlock object.
Definition: rpl_gtid.h:474
int trywrlock()
Try to acquire the write lock, and fail if it cannot be immediately granted.
Definition: rpl_gtid.h:440
void wrlock()
Acquire the write lock.
Definition: rpl_gtid.h:429
This has the functionality of mysql_rwlock_t, with two differences:
Definition: rpl_gtid.h:326
int32 get_state() const
Read lock_state atomically and return the value.
Definition: rpl_gtid.h:599
void assert_no_rdlock() const
Assert that no thread holds the read lock.
Definition: rpl_gtid.h:581
int trywrlock()
Return 0 if the write lock is held, otherwise an error will be returned.
Definition: rpl_gtid.h:539
enum_lock_type
Definition: rpl_gtid.h:349
@ TRY_READ_LOCK
Definition: rpl_gtid.h:353
@ TRY_WRITE_LOCK
Definition: rpl_gtid.h:354
@ WRITE_LOCK
Definition: rpl_gtid.h:352
@ READ_LOCK
Definition: rpl_gtid.h:351
@ NO_LOCK
Definition: rpl_gtid.h:350
void rdlock()
Acquire the read lock.
Definition: rpl_gtid.h:487
void wrlock()
Acquire the write lock.
Definition: rpl_gtid.h:496
std::atomic< int32 > m_lock_state
The state of the lock: 0 - not locked -1 - write locked >0 - read locked by that many threads.
Definition: rpl_gtid.h:597
void assert_no_lock() const
Assert that no thread holds read or write lock.
Definition: rpl_gtid.h:583
int tryrdlock()
Return 0 if the read lock is held, otherwise an error will be returned.
Definition: rpl_gtid.h:558
~Checkable_rwlock()
Destroy this Checkable_lock.
Definition: rpl_gtid.h:347
void assert_no_wrlock() const
Assert that no thread holds the write lock.
Definition: rpl_gtid.h:579
void assert_some_lock() const
Assert that some thread holds either the read or the write lock.
Definition: rpl_gtid.h:573
Checkable_rwlock(PSI_rwlock_key psi_key=0)
Initialize this Checkable_rwlock.
Definition: rpl_gtid.h:329
void assert_some_rdlock() const
Assert that some thread holds the read lock.
Definition: rpl_gtid.h:575
void unlock()
Release the lock (whether it is a write or read lock).
Definition: rpl_gtid.h:507
bool m_dbug_trace
If enabled, print any lock/unlock operations to the DBUG trace.
Definition: rpl_gtid.h:588
bool is_wrlock()
Return true if the write lock is held.
Definition: rpl_gtid.h:527
void assert_some_wrlock() const
Assert that some thread holds the write lock.
Definition: rpl_gtid.h:577
mysql_rwlock_t m_rwlock
The rwlock.
Definition: rpl_gtid.h:608
Class to access the value of @global.gtid_mode in an efficient and thread-safe manner.
Definition: rpl_gtid.h:618
static std::pair< bool, value_type > from_string(std::string s)
Return the given string gtid_mode as an enumeration value.
Definition: rpl_gtid_mode.cc:56
static ulong sysvar_mode
The sys_var framework needs a variable of type ulong to store the value in.
Definition: rpl_gtid.h:631
std::atomic< int > m_atomic_mode
Definition: rpl_gtid.h:620
const char * get_string() const
Return the current gtid_mode as a string.
Definition: rpl_gtid_mode.cc:53
Gtid_mode()
Definition: rpl_gtid.h:623
static const char * names[]
Strings holding the enumeration values for gtid_mode.
Definition: rpl_gtid.h:663
void set(value_type value)
Set a new value for @global.gtid_mode.
Definition: rpl_gtid_mode.cc:44
value_type get() const
Return the current gtid_mode as an enumeration value.
Definition: rpl_gtid_mode.cc:48
static const char * to_string(value_type value)
Return the given gtid_mode as a string.
Definition: rpl_gtid_mode.cc:68
static Checkable_rwlock lock
Protects updates to @global.gtid_mode.
Definition: rpl_gtid.h:674
value_type
Possible values for @global.gtid_mode.
Definition: rpl_gtid.h:634
@ ON_PERMISSIVE
New transactions are GTID-transactions.
Definition: rpl_gtid.h:649
@ OFF
New transactions are anonymous.
Definition: rpl_gtid.h:639
@ OFF_PERMISSIVE
New transactions are anonyomus.
Definition: rpl_gtid.h:644
@ ON
New transactions are GTID-transactions.
Definition: rpl_gtid.h:655
@ DEFAULT
Definition: rpl_gtid.h:656
Stores information to monitor a transaction during the different replication stages.
Definition: rpl_gtid.h:1414
Trx_monitoring_info * last_processed_trx
Holds information about the last processed transaction.
Definition: rpl_gtid.h:1434
const Gtid * get_processing_trx_gtid()
Returns the GTID of the processing_trx.
Definition: rpl_gtid_misc.cc:602
void update(mysql::binlog::event::compression::type t, size_t payload_size, size_t uncompressed_size)
Definition: rpl_gtid_misc.cc:515
void clear()
Clear all monitoring information.
Definition: rpl_gtid_misc.cc:496
void finish()
Sets the final information, copy processing info to last_processed and clears processing info.
Definition: rpl_gtid_misc.cc:563
void start(Gtid gtid_arg, ulonglong original_ts_arg, ulonglong immediate_ts_arg, bool skipped_arg=false)
Sets the initial monitoring information.
Definition: rpl_gtid_misc.cc:523
~Gtid_monitoring_info()
Destroy this GTID monitoring info object.
Definition: rpl_gtid_misc.cc:455
Trx_monitoring_info * processing_trx
Holds information about transaction being processed.
Definition: rpl_gtid.h:1432
void atomic_lock()
Lock this object when no thread mutex is used to arbitrate the access.
Definition: rpl_gtid_misc.cc:460
void atomic_unlock()
Unlock this object when no thread mutex is used to arbitrate the access.
Definition: rpl_gtid_misc.cc:485
mysql_mutex_t * atomic_mutex
Mutex arbitrating the atomic access to the object.
Definition: rpl_gtid.h:1451
void copy_info_to(Trx_monitoring_info *processing_dest, Trx_monitoring_info *last_processed_dest)
Copies both processing_trx and last_processed_trx info to other Trx_monitoring_info structures.
Definition: rpl_gtid_misc.cc:580
std::atomic< bool > atomic_locked
The atomic locked flag.
Definition: rpl_gtid.h:1454
bool is_processing_trx_set()
Returns true if the processing_trx is set, false otherwise.
Definition: rpl_gtid_misc.cc:593
bool is_locked
Flag to assert the atomic lock behavior.
Definition: rpl_gtid.h:1457
void store_transient_error(uint transient_errno_arg, const char *transient_err_message_arg, ulong trans_retries_arg)
Stores the information about the last transient error in the current transaction, namely: the error n...
Definition: rpl_gtid_misc.cc:611
Gtid_monitoring_info(mysql_mutex_t *atomic_mutex_arg=nullptr)
Create this GTID monitoring info object.
Definition: rpl_gtid_misc.cc:449
void clear_last_processed_trx()
Clear only the last_processed_trx monitoring info.
Definition: rpl_gtid_misc.cc:509
void clear_processing_trx()
Clear only the processing_trx monitoring info.
Definition: rpl_gtid_misc.cc:503
Iterator over intervals of a const Gtid_set.
Definition: rpl_gtid.h:2123
Const_interval_iterator(const Gtid_set *gtid_set)
Create this Const_interval_iterator.
Definition: rpl_gtid.h:2130
Const_interval_iterator(const Gtid_set *gtid_set, rpl_sidno sidno)
Create this Const_interval_iterator.
Definition: rpl_gtid.h:2126
Class representing a lock on free_intervals_mutex.
Definition: rpl_gtid.h:2384
bool locked
Definition: rpl_gtid.h:2408
void unlock_if_locked()
Lock the lock if it is locked.
Definition: rpl_gtid.h:2397
Free_intervals_lock(Gtid_set *_gtid_set)
Create a new lock, but do not acquire it.
Definition: rpl_gtid.h:2387
~Free_intervals_lock()
Destroy this object and unlock the lock if it is locked.
Definition: rpl_gtid.h:2404
void lock_if_not_locked()
Lock the lock if it is not already locked.
Definition: rpl_gtid.h:2390
Gtid_set * gtid_set
Definition: rpl_gtid.h:2407
Iterator over all gtids in a Gtid_set.
Definition: rpl_gtid.h:2181
Gtid get() const
Return next gtid, or {0,0} if we reached the end.
Definition: rpl_gtid.h:2207
rpl_sidno sidno
The SIDNO of the current element, or 0 if the iterator is past the last element.
Definition: rpl_gtid.h:2234
const Gtid_set * gtid_set
The Gtid_set we iterate over.
Definition: rpl_gtid.h:2229
void next()
Advance to next gtid.
Definition: rpl_gtid.h:2188
rpl_gno gno
The GNO of the current element, or 0 if the iterator is past the last element.
Definition: rpl_gtid.h:2239
Const_interval_iterator ivit
Iterator over the intervals for the current SIDNO.
Definition: rpl_gtid.h:2241
Gtid_iterator(const Gtid_set *gs)
Definition: rpl_gtid.h:2183
void next_sidno()
Find the next sidno that has one or more intervals.
Definition: rpl_gtid.h:2214
Iterator over intervals for a given SIDNO.
Definition: rpl_gtid.h:2082
Interval_p get() const
Return current_elem.
Definition: rpl_gtid.h:2108
void init(Gtid_set_p gtid_set, rpl_sidno sidno)
Reset this iterator.
Definition: rpl_gtid.h:2099
Interval_iterator_base(Gtid_set_p gtid_set, rpl_sidno sidno)
Construct a new iterator over the GNO intervals for a given Gtid_set.
Definition: rpl_gtid.h:2090
Interval_p * p
Holds the address of the 'next' pointer of the previous element, or the address of the initial pointe...
Definition: rpl_gtid.h:2116
Interval_iterator_base(Gtid_set_p gtid_set)
Construct a new iterator over the free intervals of a Gtid_set.
Definition: rpl_gtid.h:2095
void next()
Advance current_elem one step.
Definition: rpl_gtid.h:2103
Iterator over intervals of a non-const Gtid_set, with additional methods to modify the Gtid_set.
Definition: rpl_gtid.h:2140
Interval_iterator(Gtid_set *gtid_set)
Destroy this Interval_iterator.
Definition: rpl_gtid.h:2146
void set(Interval *iv)
Set current_elem to the given Interval but do not touch the next pointer of the given Interval.
Definition: rpl_gtid.h:2154
void insert(Interval *iv)
Insert the given element before current_elem.
Definition: rpl_gtid.h:2156
void remove(Gtid_set *gtid_set)
Remove current_elem.
Definition: rpl_gtid.h:2161
Interval_iterator(Gtid_set *gtid_set, rpl_sidno sidno)
Create this Interval_iterator.
Definition: rpl_gtid.h:2143
Represents a set of GTIDs.
Definition: rpl_gtid.h:1558
void put_free_interval(Interval *iv)
Puts the given interval in the list of free intervals.
Definition: rpl_gtid_set.cc:268
static constexpr uint64_t k_gtid_format_low_shift
Definition: rpl_gtid.h:2248
rpl_gno get_last_gno(rpl_sidno sidno) const
Definition: rpl_gtid_set.cc:770
bool is_size_greater_than_or_equal(ulonglong num) const
Return true if the size of the set is greater than or equal to the given number.
Definition: rpl_gtid_set.cc:1337
bool is_intersection_nonempty(const Gtid_set *other) const
Returns true if there is a least one element of this Gtid_set in the other Gtid_set.
Definition: rpl_gtid_set.cc:1257
bool is_subset(const Gtid_set *super) const
Returns true if this Gtid_set is a subset of the other Gtid_set.
Definition: rpl_gtid_set.cc:1177
void add_interval_memory(int n_intervals, Interval *intervals_param)
Provides an array of Intervals that this Gtid_set can use when gtids are subsequently added.
Definition: rpl_gtid.h:2065
bool contains_sidno(rpl_sidno sidno) const
Returns true if this Gtid_set contains at least one GTID with the given SIDNO.
Definition: rpl_gtid.h:1888
void encode(uchar *buf, bool skip_tagged_gtids=false) const
Encodes this Gtid_set as a binary string.
Definition: rpl_gtid_set.cc:1391
static constexpr uint64_t k_tagged_n_sids_mask
Definition: rpl_gtid.h:2252
Gtid_set(Tsid_map *tsid_map, Checkable_rwlock *tsid_lock=nullptr)
Constructs a new, empty Gtid_set.
Definition: rpl_gtid_set.cc:87
int get_n_intervals() const
Return the number of intervals in this Gtid_set.
Definition: rpl_gtid.h:2291
bool sidno_equals(rpl_sidno sidno, const Gtid_set *other, rpl_sidno other_sidno) const
Return true if the given sidno of this Gtid_set contains the same intervals as the given sidno of the...
Definition: rpl_gtid_set.cc:1000
friend std::ostream & operator<<(std::ostream &os, const Gtid_set &in)
For use with C++ std::ostream
Definition: rpl_gtid.h:1989
void add_gno_intervals(rpl_sidno sidno, Const_interval_iterator ivit, Free_intervals_lock *lock)
Adds a list of intervals to the given SIDNO.
Definition: rpl_gtid_set.cc:660
static constexpr uint64_t k_gtid_format_low_mask
Definition: rpl_gtid.h:2251
std::size_t get_count() const
Returns the number of GTIDs.
Definition: rpl_gtid.h:1867
static bool is_interval_subset(Const_interval_iterator *sub, Const_interval_iterator *super)
Returns true if every interval of sub is a subset of some interval of super.
Definition: rpl_gtid_set.cc:1073
void init()
Worker for the constructor.
Definition: rpl_gtid_set.cc:115
static const int CHUNK_GROW_SIZE
The default number of intervals in an Interval_chunk.
Definition: rpl_gtid.h:2312
static constexpr uint64_t k_gtid_format_high_mask
Definition: rpl_gtid.h:2249
Interval_chunk * chunks
Linked list of chunks.
Definition: rpl_gtid.h:2510
static const String_format commented_string_format
String_format for printing the Gtid_set commented: the string is not quote-wrapped,...
Definition: rpl_gtid.h:2033
bool contains_gtid(rpl_sidno sidno, rpl_gno gno) const
Return true iff the given GTID exists in this set.
Definition: rpl_gtid_set.cc:752
enum_return_status ensure_sidno(rpl_sidno sidno)
Allocates space for all sidnos up to the given sidno in the array of intervals.
Definition: rpl_gtid_set.cc:145
Tsid_map * tsid_map
Tsid_map associated with this Gtid_set.
Definition: rpl_gtid.h:2501
int get_n_intervals(rpl_sidno sidno) const
Return the number of intervals for the given sidno.
Definition: rpl_gtid.h:2280
bool contains_tags() const
Checks if this Gtid set contains any tagged GTIDs.
Definition: rpl_gtid_set.cc:925
void clear_set_and_tsid_map()
Removes all gtids from this Gtid_set and clear all the sidnos used by the Gtid_set and it's TSID map.
Definition: rpl_gtid_set.cc:301
enum_return_status add_gtid_set(const Gtid_set *other)
Adds all gtids from the given Gtid_set to this Gtid_set.
Definition: rpl_gtid_set.cc:695
Interval * free_intervals
Linked list of free intervals.
Definition: rpl_gtid.h:2508
bool contains_gtid(const Gtid &gtid) const
Return true iff the given GTID exists in this set.
Definition: rpl_gtid.h:1761
static const String_format default_string_format
The default String_format: the format understood by add_gtid_text(const char *).
Definition: rpl_gtid.h:2023
void add_interval_memory_lock_taken(int n_ivs, Interval *ivs)
Like add_interval_memory, but does not acquire free_intervals_mutex.
Definition: rpl_gtid_set.cc:193
void remove_gtid_set(const Gtid_set *other)
Removes all gtids in the given Gtid_set from this Gtid_set.
Definition: rpl_gtid_set.cc:726
void print(bool need_lock=false, const Gtid_set::String_format *sf=nullptr) const
Debug only: Print this Gtid_set to stdout.
Definition: rpl_gtid.h:1980
Prealloced_array< Interval *, 8 > m_intervals
Array where the N'th element contains the head pointer to the intervals of SIDNO N+1.
Definition: rpl_gtid.h:2506
mysql_mutex_t free_intervals_mutex
Lock protecting the list of free intervals.
Definition: rpl_gtid.h:2370
void dbug_print(const char *text="", bool need_lock=false, const Gtid_set::String_format *sf=nullptr) const
Print this Gtid_set to the trace file if debug is enabled; no-op otherwise.
Definition: rpl_gtid.h:2001
int n_chunks
The number of chunks.
Definition: rpl_gtid.h:2522
void remove_gno_intervals(rpl_sidno sidno, Const_interval_iterator ivit, Free_intervals_lock *lock)
Removes a list of intervals from the given SIDNO.
Definition: rpl_gtid_set.cc:673
static bool is_valid(const char *text)
Returns true if the given string is a valid specification of a Gtid_set, false otherwise.
Definition: rpl_gtid_set.cc:607
void clear()
Removes all gtids from this Gtid_set.
Definition: rpl_gtid_set.cc:276
static constexpr uint64_t k_gtid_format_high_shift
Definition: rpl_gtid.h:2247
static bool is_interval_intersection_nonempty(Const_interval_iterator *ivit1, Const_interval_iterator *ivit2)
Returns true if at least one sidno in ivit1 is also in ivit2.
Definition: rpl_gtid_set.cc:1220
bool is_subset_for_sid(const Gtid_set *super, const rpl_sid &sid) const
Returns true if this Gtid_set is a subset of the given gtid_set with respect to the given sid.
Definition: rpl_gtid_set.cc:1114
enum_return_status intersection(const Gtid_set *other, Gtid_set *result)
Add the intersection of this Gtid_set and the other Gtid_set to result.
Definition: rpl_gtid_set.cc:1311
void remove_gno_interval(Interval_iterator *ivitp, rpl_gno start, rpl_gno end, Free_intervals_lock *lock)
Removes the interval (start, end) from the given Interval_iterator.
Definition: rpl_gtid_set.cc:363
static constexpr uint64_t k_gtid_format_byte_mask
Bit layout of the encoded n_sids + format header used by Gtid_set.
Definition: rpl_gtid.h:2246
void get_gtid_intervals(std::list< Gtid_interval > *gtid_intervals) const
Gets all gtid intervals from this Gtid_set.
Definition: rpl_gtid_set.cc:884
bool is_subset_not_equals(const Gtid_set *super) const
Returns true if this Gtid_set is a non equal subset of the other Gtid_set.
Definition: rpl_gtid.h:1788
enum_return_status add_gtid(const mysql::gtid::Gtid &gtid)
Adds specified GTID (TSID+GNO) to this Gtid_set.
Definition: rpl_gtid_set.cc:437
size_t get_string_length(const String_format *string_format=nullptr) const
Returns the length of the output from to_string.
Definition: rpl_gtid_set.cc:942
size_t cached_string_length
The string length.
Definition: rpl_gtid.h:2514
enum_return_status add_gtid_text(const char *text, bool *anonymous=nullptr, bool *starts_with_plus=nullptr)
Adds the set of GTIDs represented by the given string to this Gtid_set.
Definition: rpl_gtid_set.cc:451
void add_gno_interval(Interval_iterator *ivitp, rpl_gno start, rpl_gno end, Free_intervals_lock *lock)
Adds the interval (start, end) to the given Interval_iterator.
Definition: rpl_gtid_set.cc:314
size_t get_encoded_length(bool skip_tagged_gtids=false) const
Returns the length of this Gtid_set when encoded using the encode() function.
Definition: rpl_gtid_set.cc:1581
void _add_gtid(rpl_sidno sidno, rpl_gno gno)
Adds the given GTID to this Gtid_set.
Definition: rpl_gtid.h:1628
bool is_empty() const
Returns true if this Gtid_set is empty.
Definition: rpl_gtid.h:1832
static PSI_mutex_key key_gtid_executed_free_intervals_mutex
Definition: rpl_gtid.h:1560
static const String_format sql_string_format
String_format useful to generate an SQL string: the string is wrapped in single quotes and there is a...
Definition: rpl_gtid.h:2028
bool equals(const Gtid_set *other) const
Returns true if this Gtid_set is equal to the other Gtid_set.
Definition: rpl_gtid_set.cc:1018
enum_return_status add_gtid_encoding(const uchar *encoded, size_t length, size_t *actual_length=nullptr)
Decodes a Gtid_set from the given string.
Definition: rpl_gtid_set.cc:1442
void remove_intervals_for_sidno(Gtid_set *other, rpl_sidno sidno)
Removes all intervals of 'other' for a given SIDNO, from 'this'.
Definition: rpl_gtid_set.cc:687
bool is_subset_for_sidno(const Gtid_set *super, rpl_sidno superset_sidno, rpl_sidno subset_sidno) const
Returns true if this Gtid_set is a subset of the given gtid_set on the given superset_sidno and subse...
Definition: rpl_gtid_set.cc:1139
~Gtid_set()
Destroy this Gtid_set.
Definition: rpl_gtid_set.cc:130
void claim_memory_ownership(bool claim)
Claim ownership of memory.
Definition: rpl_gtid_set.cc:104
bool has_cached_string_length
If the string is cached.
Definition: rpl_gtid.h:2512
const String_format * cached_string_format
The String_format that was used when cached_string_length was computed.
Definition: rpl_gtid.h:2516
void get_free_interval(Interval **out)
Returns a fresh new Interval object.
Definition: rpl_gtid_set.cc:255
size_t to_string(char *buf, bool need_lock=false, const String_format *string_format=nullptr) const
Formats this Gtid_set as a string and saves in a given buffer.
Definition: rpl_gtid_set.cc:807
void _remove_gtid(const Gtid &gtid)
Removes the given GTID from this Gtid_set.
Definition: rpl_gtid.h:1666
Checkable_rwlock * tsid_lock
Read-write lock that protects updates to the number of TSIDs.
Definition: rpl_gtid.h:2365
mysql::gtid::Gtid_format analyze_encoding_format(bool skip_tagged_gtids) const
Goes through recorded tsids.
Definition: rpl_gtid_set.cc:1545
void _remove_gtid(rpl_sidno sidno, rpl_gno gno)
Removes the given GTID from this Gtid_set.
Definition: rpl_gtid.h:1644
Tsid_map * get_tsid_map() const
Return the Tsid_map associated with this Gtid_set.
Definition: rpl_gtid.h:2036
void create_new_chunk(int size)
Allocates a new chunk of Intervals and adds them to the list of unused intervals.
Definition: rpl_gtid_set.cc:204
void _add_gtid(const Gtid &gtid)
Adds the given GTID to this Gtid_set.
Definition: rpl_gtid.h:1660
rpl_sidno get_max_sidno() const
Returns the maximal sidno that this Gtid_set currently has space for.
Definition: rpl_gtid.h:1767
void assert_free_intervals_locked()
Definition: rpl_gtid.h:2410
ulonglong get_gtid_count(rpl_sidno sidno) const
What is the count of all the GTIDs in all intervals for a sidno.
Definition: rpl_gtid.h:1855
Represents the server's GTID state: the set of committed GTIDs, the set of lost gtids,...
Definition: rpl_gtid.h:2895
bool update_gtids_impl_check_skip_gtid_rollback(THD *thd)
Used by unit tests that need to access private members.
Definition: rpl_gtid_state.cc:804
int init()
Add @GLOBAL.SERVER_UUID to this binlog's Tsid_map.
Definition: rpl_gtid_state.cc:666
Tsid_map * tsid_map
The Tsid_map used by this Gtid_state.
Definition: rpl_gtid.h:3609
bool update_gtids_impl_do_nothing(THD *thd)
This is a sub task of update_gtids_impl responsible only to handle the case of a thread that owns not...
Definition: rpl_gtid_state.cc:816
void end_automatic_gtid_violating_transaction()
Decrease the global counter when ending a GTID-violating transaction having GTID_NEXT=AUTOMATIC.
Definition: rpl_gtid.h:3084
void broadcast_owned_sidnos(const THD *thd)
Broadcast the condition for all SIDNOs owned by the given THD.
Definition: rpl_gtid_state.cc:146
const Gtid_set * get_executed_gtids() const
Definition: rpl_gtid.h:3398
void unlock_sidnos(const Gtid_set *set)
Unlocks the mutex for each SIDNO where the given Gtid_set has at least one GTID.
Definition: rpl_gtid_state.cc:562
void print() const
Debug only: print this Gtid_state to stdout.
Definition: rpl_gtid.h:3484
const Gtid_set * get_lost_gtids() const
Return a pointer to the Gtid_set that contains the lost gtids.
Definition: rpl_gtid.h:3393
enum_return_status ensure_sidno()
Ensure that owned_gtids, executed_gtids, lost_gtids, gtids_only_in_table, previous_gtids_logged and t...
Definition: rpl_gtid_state.cc:576
void decrease_gtid_automatic_tagged_count()
Decrements atomic_automatic_tagged_gtid_session_count.
Definition: rpl_gtid.h:3439
void begin_anonymous_gtid_violating_transaction()
Increase the global counter when starting a GTID-violating transaction having GTID_NEXT=ANONYMOUS.
Definition: rpl_gtid.h:3114
const Tsid & get_server_tsid() const
Return the server's TSID.
Definition: rpl_gtid.h:3418
rpl_sidno server_sidno
The SIDNO for this server.
Definition: rpl_gtid.h:3632
bool wait_for_gtid_set(THD *thd, Gtid_set *gtid_set, double timeout, bool update_thd_status=true)
Wait until the given Gtid_set is included in @GLOBAL.GTID_EXECUTED.
Definition: rpl_gtid_state.cc:305
enum_return_status acquire_ownership(THD *thd, const Gtid &gtid)
Acquires ownership of the given GTID, on behalf of the given thread.
Definition: rpl_gtid_state.cc:80
void update_gtids_impl_own_nothing(THD *thd)
Handle the case that the thread owns nothing.
Definition: rpl_gtid_state.cc:992
void update_gtids_impl_lock_sidno(rpl_sidno sidno)
Lock a given sidno of a transaction being updated.
Definition: rpl_gtid_state.cc:867
std::atomic< int32 > atomic_anonymous_gtid_count
The number of anonymous transactions owned by any client.
Definition: rpl_gtid.h:3639
int save_gtids_of_last_binlog_into_table()
Save the set of gtids logged in the last binlog into gtid_executed table.
Definition: rpl_gtid_state.cc:739
void end_gtid_wait()
Decrease the global counter when ending a call to WAIT_FOR_EXECUTED_GTID_SET.
Definition: rpl_gtid.h:3181
bool is_any_session_assigning_automatic_tagged_gtids()
Checks whether there are ongoing sessions executing transactions with GTID_NEXT set to AUTOMATIC:tag.
Definition: rpl_gtid.h:3447
Gtid_set lost_gtids
The set of GTIDs that existed in some previously purged binary log.
Definition: rpl_gtid.h:3616
const Owned_gtids * get_owned_gtids() const
Return a pointer to the Owned_gtids that contains the owned gtids.
Definition: rpl_gtid.h:3414
void unlock_owned_sidnos(const THD *thd)
Unlock all SIDNOs owned by the given THD.
Definition: rpl_gtid_state.cc:134
Owned_gtids owned_gtids
The set of GTIDs that are owned by some thread.
Definition: rpl_gtid.h:3630
rpl_sidno get_server_sidno() const
Return the server's SIDNO.
Definition: rpl_gtid.h:3416
const Gtid_set * get_previous_gtids_logged() const
Definition: rpl_gtid.h:3410
void update_gtids_impl_broadcast_and_unlock_sidno(rpl_sidno sidno)
Unlock a given sidno after broadcasting its changes.
Definition: rpl_gtid_state.cc:956
Gtid_state(Checkable_rwlock *_tsid_lock, Tsid_map *_tsid_map)
Constructs a new Gtid_state object.
Definition: rpl_gtid.h:2904
int32 get_gtid_wait_count()
Return the number of clients that have an ongoing call to WAIT_FOR_EXECUTED_GTID_SET.
Definition: rpl_gtid.h:3198
char * to_string() const
Debug only: return a newly allocated string, or NULL on out-of-memory.
Definition: rpl_gtid.h:3477
rpl_sidno featured_uuid_sidno
When featured_uuid_sidno is defined, greater than 0, the featured uuid is used as the originating ser...
Definition: rpl_gtid.h:3636
int read_gtid_executed_from_table()
Fetch gtids from gtid_executed table and store them into gtid_executed set.
Definition: rpl_gtid_state.cc:789
Mutex_cond_array tsid_locks
Contains one mutex/cond pair for every SIDNO.
Definition: rpl_gtid.h:3611
Gtid_set previous_gtids_logged
Definition: rpl_gtid.h:3628
std::atomic< int64_t > atomic_automatic_tagged_gtid_session_count
The number of sessions that have GTID_NEXT set to AUTOMATIC with tag assigned.
Definition: rpl_gtid.h:3649
enum_return_status add_lost_gtids(Gtid_set *gtid_set, bool starts_with_plus)
Adds the given Gtid_set to lost_gtids and executed_gtids.
Definition: rpl_gtid_state.cc:622
bool wait_for_sidno(THD *thd, rpl_sidno sidno, struct timespec *abstime, bool update_thd_status=true)
Wait for a signal on the given SIDNO.
Definition: rpl_gtid_state.cc:270
const Gtid_set * get_gtids_only_in_table() const
Definition: rpl_gtid.h:3403
int compress(THD *thd)
Compress the gtid_executed table, read each row by the PK(sid, gno_start) in increasing order,...
Definition: rpl_gtid_state.cc:793
std::unordered_map< rpl_sidno, rpl_gno > next_free_gno_map
The next_free_gno map contains next_free_gno for recorded sidnos.
Definition: rpl_gtid.h:3235
std::optional< std::string > set_featured_uuid(const char *uuid)
Set the featured uuid, adding it to the global sid map and generating a sidno to it.
Definition: rpl_gtid_state.cc:682
int32 get_anonymous_gtid_violating_transaction_count()
Return the number of ongoing GTID-violating transactions having GTID_NEXT=AUTOMATIC.
Definition: rpl_gtid.h:3156
void lock_sidnos(const Gtid_set *set)
Locks one mutex for each SIDNO where the given Gtid_set has at least one GTID.
Definition: rpl_gtid_state.cc:555
void assert_sidno_lock_owner(rpl_sidno sidno) const
Assert that we own the given SIDNO.
Definition: rpl_gtid.h:3288
enum_return_status ensure_commit_group_sidnos(rpl_sidno sidno)
Ensure that commit_group_sidnos have room for the SIDNO passed as parameter.
Definition: rpl_gtid_state.cc:1002
void update_gtids_impl_own_anonymous(THD *thd, bool *more_trx)
Handle the case that the thread owns ANONYMOUS GTID.
Definition: rpl_gtid_state.cc:970
bool wait_for_gtid(THD *thd, const Gtid &gtid, struct timespec *abstime=nullptr)
This is only a shorthand for wait_for_sidno, which contains additional debug printouts and assertions...
Definition: rpl_gtid_state.cc:293
void acquire_anonymous_ownership()
Acquire anonymous ownership.
Definition: rpl_gtid.h:3028
int warn_or_err_on_modify_gtid_table(THD *thd, Table_ref *table)
Push a warning to client if user is modifying the gtid_executed table explicitly by a non-XA transact...
Definition: rpl_gtid_state.cc:797
void update_on_rollback(THD *thd)
Update the state after the given thread has rollbacked.
Definition: rpl_gtid_state.cc:214
Gtid_set gtids_only_in_table
Definition: rpl_gtid.h:3626
rpl_gno get_automatic_gno(rpl_sidno sidno) const
Computes the next available GNO.
Definition: rpl_gtid_state.cc:416
Gtid_set executed_gtids
Definition: rpl_gtid.h:3621
void update_gtids_impl_own_gtid(THD *thd, bool is_commit)
Handle the case that the thread own a single non-anonymous GTID.
Definition: rpl_gtid_state.cc:894
int32 get_automatic_gtid_violating_transaction_count()
Return the number of ongoing GTID-violating transactions having GTID_NEXT=AUTOMATIC.
Definition: rpl_gtid.h:3106
void dbug_print(const char *text="") const
Print this Gtid_state to the trace file if debug is enabled; no-op otherwise.
Definition: rpl_gtid.h:3494
void update_commit_group(THD *first_thd)
This function updates both the THD and the Gtid_state to reflect that the transaction set of transact...
Definition: rpl_gtid_state.cc:158
void unlock_sidno(rpl_sidno sidno)
Unlocks a mutex for the given SIDNO.
Definition: rpl_gtid.h:3284
bool is_owned(const Gtid &gtid) const
Returns true if GTID is owned, otherwise returns 0.
Definition: rpl_gtid.h:2961
int to_string(char *buf) const
Debug only: Generate a string in the given buffer and return the length.
Definition: rpl_gtid.h:3464
bool is_executed(const Gtid &gtid) const
Returns true if the given GTID is logged.
Definition: rpl_gtid.h:2948
Prealloced_array< bool, 8 > commit_group_sidnos
This array is used by Gtid_state_update_gtids_impl* functions.
Definition: rpl_gtid.h:3889
void update_prev_gtids(Gtid_set *write_gtid_set)
Updates previously logged GTID set before writing to table.
Definition: rpl_gtid_state.cc:603
Checkable_rwlock * tsid_lock
Read-write lock that protects updates to the number of TSIDs.
Definition: rpl_gtid.h:3607
const Tsid & get_featured_uuid_tsid() const
Return the featured uuid TSID.
Definition: rpl_gtid.h:3423
void end_gtid_violating_transaction(THD *thd)
Definition: rpl_gtid_state.cc:257
void begin_automatic_gtid_violating_transaction()
Increase the global counter when starting a GTID-violating transaction having GTID_NEXT=AUTOMATIC.
Definition: rpl_gtid.h:3064
rpl_sidno specify_transaction_sidno(THD *thd, Gtid_state::Locked_sidno_set &sidno_set)
Determines sidno for thd transaction.
Definition: rpl_gtid_state.cc:480
void update_gtids_impl_broadcast_and_unlock_sidnos()
Unlocks all locked sidnos after broadcasting their changes.
Definition: rpl_gtid_state.cc:962
void lock_sidno(rpl_sidno sidno)
Locks a mutex for the given SIDNO.
Definition: rpl_gtid.h:3282
void update_gtids_impl_own_gtid_set(THD *thd, bool is_commit)
Handle the case that the thread own a set of GTIDs.
Definition: rpl_gtid_state.cc:839
void broadcast_sidnos(const Gtid_set *set)
Broadcasts the condition variable for each SIDNO where the given Gtid_set has at least one GTID.
Definition: rpl_gtid_state.cc:569
size_t get_max_string_length() const
Debug only: Returns an upper bound on the length of the string generated by to_string(),...
Definition: rpl_gtid.h:3457
std::atomic< int32 > atomic_automatic_gtid_violation_count
The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC.
Definition: rpl_gtid.h:3641
std::atomic< int32 > atomic_gtid_wait_count
The number of clients that are executing WAIT_FOR_EXECUTED_GTID_SET.
Definition: rpl_gtid.h:3646
void end_anonymous_gtid_violating_transaction()
Decrease the global counter when ending a GTID-violating transaction having GTID_NEXT=ANONYMOUS.
Definition: rpl_gtid.h:3132
rpl_gno get_last_executed_gno(rpl_sidno sidno) const
Return the last executed GNO for a given SIDNO, e.g.
Definition: rpl_gtid_state.cc:469
int clear(THD *thd)
Reset the state and persistor after RESET BINARY LOGS AND GTIDS: remove all logged and lost gtids,...
Definition: rpl_gtid_state.cc:58
std::atomic< int32 > atomic_anonymous_gtid_violation_count
The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC.
Definition: rpl_gtid.h:3643
void update_on_commit(THD *thd)
Remove the GTID owned by thread from owned GTIDs, stating that thd->owned_gtid was committed.
Definition: rpl_gtid_state.cc:207
void update_gtids_impl_lock_sidnos(THD *thd)
Locks the sidnos of all the GTIDs of the commit group starting on the transaction passed as parameter...
Definition: rpl_gtid_state.cc:873
int32 get_anonymous_ownership_count()
Return the number of clients that hold anonymous ownership.
Definition: rpl_gtid.h:3058
void update_gtids_impl_end(THD *thd, bool more_trx)
Handle the final part of update_gtids_impl.
Definition: rpl_gtid_state.cc:998
int save(THD *thd)
Save gtid owned by the thd into executed_gtids variable and gtid_executed table.
Definition: rpl_gtid_state.cc:712
bool update_gtids_impl_begin(THD *thd)
This is a sub task of update_gtids_impl responsible only to evaluate if the thread is committing in t...
Definition: rpl_gtid_state.cc:829
void broadcast_sidno(rpl_sidno sidno)
Broadcasts updates for the given SIDNO.
Definition: rpl_gtid.h:3286
enum_return_status generate_automatic_gtid(THD *thd, rpl_sidno specified_sidno=0, rpl_gno specified_gno=0)
Generates the GTID (or ANONYMOUS, if GTID_MODE = OFF or OFF_PERMISSIVE) for the THD,...
Definition: rpl_gtid_state.cc:514
void release_anonymous_ownership()
Release anonymous ownership.
Definition: rpl_gtid.h:3043
void begin_gtid_wait()
Increase the global counter when starting a call to WAIT_FOR_EXECUTED_GTID_SET.
Definition: rpl_gtid.h:3164
void increase_gtid_automatic_tagged_count()
Increments atomic_automatic_tagged_gtid_session_count.
Definition: rpl_gtid.h:3434
void update_gtids_impl(THD *thd, bool is_commit)
Remove the GTID owned by thread from owned GTIDs.
Definition: rpl_gtid_state.cc:221
Malloc_allocator is a C++ STL memory allocator based on my_malloc/my_free.
Definition: malloc_allocator.h:63
Represents a growable array where each element contains a mutex and a condition variable.
Definition: rpl_gtid.h:949
Prealloced_array< Mutex_cond *, 8 > m_array
Definition: rpl_gtid.h:1072
bool is_thd_killed(const THD *thd) const
Return true if the given THD is killed.
Definition: rpl_gtid_mutex_cond_array.cc:96
void enter_cond(THD *thd, int n, PSI_stage_info *stage, PSI_stage_info *old_stage) const
Execute THD::enter_cond for the n'th condition variable.
Definition: rpl_gtid_mutex_cond_array.cc:66
Checkable_rwlock * global_lock
Read-write lock that protects updates to the number of elements.
Definition: rpl_gtid.h:1071
bool wait(const THD *thd, int sidno, struct timespec *abstime) const
Wait for signal on the n'th condition variable.
Definition: rpl_gtid.h:1011
Mutex_cond_array(Checkable_rwlock *global_lock)
Create a new Mutex_cond_array.
Definition: rpl_gtid_mutex_cond_array.cc:42
void broadcast(int n) const
Broadcast the n'th condition.
Definition: rpl_gtid.h:971
void assert_not_owner(int n) const
Assert that this thread does not own the n'th mutex.
Definition: rpl_gtid.h:987
~Mutex_cond_array()
Destroy this object.
Definition: rpl_gtid_mutex_cond_array.cc:48
void assert_owner(int n) const
Assert that this thread owns the n'th mutex.
Definition: rpl_gtid.h:978
void unlock(int n) const
Unlock the n'th mutex.
Definition: rpl_gtid.h:966
void lock(int n) const
Lock the n'th mutex.
Definition: rpl_gtid.h:961
Mutex_cond * get_mutex_cond(int n) const
Return the Nth Mutex_cond object.
Definition: rpl_gtid.h:1063
Iterator over all gtids in a Owned_gtids set.
Definition: rpl_gtid.h:2799
rpl_sidno max_sidno
Max SIDNO of the current iterator.
Definition: rpl_gtid.h:2854
Node * node
Current node on current SIDNO hash.
Definition: rpl_gtid.h:2861
malloc_unordered_multimap< rpl_gno, unique_ptr_my_free< Node > >::const_iterator node_it
Current node iterator on current SIDNO hash.
Definition: rpl_gtid.h:2859
const Owned_gtids * owned_gtids
The Owned_gtids set we iterate over.
Definition: rpl_gtid.h:2850
Node * get_node() const
Return the current GTID Node, or NULL if we reached the end.
Definition: rpl_gtid.h:2846
Gtid_iterator(const Owned_gtids *og)
Definition: rpl_gtid.h:2801
Gtid get() const
Return next GTID, or {0,0} if we reached the end.
Definition: rpl_gtid.h:2837
void next()
Advance to next GTID.
Definition: rpl_gtid.h:2811
rpl_sidno sidno
The SIDNO of the current element, or 1 in the initial iteration.
Definition: rpl_gtid.h:2852
malloc_unordered_multimap< rpl_gno, unique_ptr_my_free< Node > > * hash
Current SIDNO hash.
Definition: rpl_gtid.h:2856
Represents the set of GTIDs that are owned by some thread.
Definition: rpl_gtid.h:2599
size_t get_max_string_length() const
Return an upper bound on the length of the string representation of this Owned_gtids.
Definition: rpl_gtid.h:2695
Checkable_rwlock * tsid_lock
Read-write lock that protects updates to the number of TSIDs.
Definition: rpl_gtid.h:2776
char * to_string() const
Debug only: return a newly allocated string representation of this Owned_gtids.
Definition: rpl_gtid.h:2727
bool thread_owns_anything(my_thread_id thd_id) const
Return true if the given thread is the owner of any gtids.
Definition: rpl_gtid.h:2711
enum_return_status add_gtid_owner(const Gtid &gtid, my_thread_id owner)
Add a GTID to this Owned_gtids.
Definition: rpl_gtid_owned.cc:70
bool is_intersection_nonempty(const Gtid_set *other) const
Returns true if there is a least one element of this Owned_gtids set in the other Gtid_set.
Definition: rpl_gtid_owned.cc:104
bool is_owned_by(const Gtid &gtid, const my_thread_id thd_id) const
If thd_id==0, returns true when gtid is not owned by any thread.
Definition: rpl_gtid_owned.cc:138
bool is_empty() const
Returns true if this Owned_gtids is empty.
Definition: rpl_gtid.h:2651
int to_string(char *out) const
Write a string representation of this Owned_gtids to the given buffer.
Definition: rpl_gtid.h:2669
rpl_sidno get_max_sidno() const
Returns the maximal sidno that this Owned_gtids currently has space for.
Definition: rpl_gtid.h:2656
malloc_unordered_multimap< rpl_gno, unique_ptr_my_free< Node > > * get_hash(rpl_sidno sidno) const
Returns the hash for the given SIDNO.
Definition: rpl_gtid.h:2778
Prealloced_array< malloc_unordered_multimap< rpl_gno, unique_ptr_my_free< Node > > *, 8 > sidno_to_hash
Growable array of hashes.
Definition: rpl_gtid.h:2792
bool has_owner(const Gtid &gtid, const my_thread_id thd_id) const
Returns true iff the given GTID is owned by exactly the given thread ID.
Definition: rpl_gtid_owned.cc:152
Owned_gtids(Checkable_rwlock *tsid_lock)
Constructs a new, empty Owned_gtids object.
Definition: rpl_gtid_owned.cc:39
void dbug_print(const char *text="") const
Print this Owned_gtids to the trace file if debug is enabled; no-op otherwise.
Definition: rpl_gtid.h:2745
void get_gtids(Gtid_set &gtid_set) const
Definition: rpl_gtid_owned.cc:117
bool contains_gtid(const Gtid &gtid) const
Return true iff this Owned_gtids object contains the given gtid.
Definition: rpl_gtid_owned.cc:131
~Owned_gtids()
Destroys this Owned_gtids.
Definition: rpl_gtid_owned.cc:43
void print() const
Debug only: print this Owned_gtids to stdout.
Definition: rpl_gtid.h:2735
enum_return_status ensure_sidno(rpl_sidno sidno)
Ensures that this Owned_gtids object can accommodate SIDNOs up to the given SIDNO.
Definition: rpl_gtid_owned.cc:56
void remove_gtid(const Gtid &gtid, const my_thread_id owner)
Removes the given GTID.
Definition: rpl_gtid_owned.cc:89
A typesafe replacement for DYNAMIC_ARRAY.
Definition: prealloced_array.h:71
Using this class is fraught with peril, and you need to be very careful when doing so.
Definition: sql_string.h:169
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
Definition: table.h:2958
Represents a bidirectional map between TSID and SIDNO.
Definition: rpl_gtid.h:751
rpl_sidno add_tsid(const Tsid &tsid)
Add the given TSID to this map if it does not already exist.
Definition: rpl_gtid_tsid_map.cc:61
enum_return_status copy(Tsid_map *dest)
Deep copy this Tsid_map to dest.
Definition: rpl_gtid_tsid_map.cc:145
Tsid_to_sidno_map::const_iterator Tsid_to_sidno_it
Definition: rpl_gtid.h:775
~Tsid_map()
Destroy this Tsid_map.
Definition: rpl_gtid_tsid_map.cc:51
Tsid_map(Checkable_rwlock *tsid_lock)
Create this Tsid_map.
Definition: rpl_gtid_tsid_map.cc:46
rpl_sidno get_max_sidno() const
Return the biggest sidno in this Tsid_map.
Definition: rpl_gtid.h:868
Checkable_rwlock * get_tsid_lock() const
Return the tsid_lock.
Definition: rpl_gtid.h:874
Tsid_to_sidno_umap _tsid_to_sidno
Hash that maps TSID to SIDNO.
Definition: rpl_gtid.h:917
rpl_sidno tsid_to_sidno(const Tsid &tsid) const
Get the SIDNO for a given TSID.
Definition: rpl_gtid.h:803
Tsid_to_sidno_map _sorted
Data structure that maps numbers in the interval [0, get_max_sidno()-1] to SIDNOs,...
Definition: rpl_gtid.h:924
Sidno_to_tsid_cont _sidno_to_tsid
Array that maps SIDNO to TSID; the element at index N points to a Node with SIDNO N-1.
Definition: rpl_gtid.h:911
enum_return_status clear()
Clears this Tsid_map (for RESET REPLICA)
Definition: rpl_gtid_tsid_map.cc:53
const rpl_sidno & get_sidno(const Tsid_to_sidno_it &it) const
Definition: rpl_gtid.h:852
Checkable_rwlock * tsid_lock
Read-write lock that protects updates to the number of SIDNOs.
Definition: rpl_gtid.h:905
const Tsid & get_tsid(const Tsid_to_sidno_it &it) const
Definition: rpl_gtid.h:857
const Tsid & sidno_to_tsid(rpl_sidno sidno, bool need_lock=false) const
Get the TSID for a given SIDNO.
Definition: rpl_gtid.h:829
std::vector< Tsid_ref, Malloc_allocator< Tsid_ref > > Sidno_to_tsid_cont
Definition: rpl_gtid.h:777
std::reference_wrapper< const Tsid > Tsid_ref
Definition: rpl_gtid.h:776
enum_return_status add_node(rpl_sidno sidno, const Tsid &tsid)
Create a Node from the given SIDNO and a TSID and add it to _sidno_to_tsid, _tsid_to_sidno,...
Definition: rpl_gtid_tsid_map.cc:101
Map_myalloc< Tsid, rpl_sidno > Tsid_to_sidno_map
Definition: rpl_gtid.h:774
const Tsid_to_sidno_map & get_sorted_sidno() const
Returns TSID to SID map.
Definition: rpl_gtid.h:850
Set that keeps track of TSID locks taken in the current scope.
Definition: locked_sidno_set.h:45
std::unordered_multimap, but with my_malloc, so that you can track the memory used using PSI memory k...
Definition: map_helpers.h:198
Represents a MySQL Global Transaction Identifier.
Definition: gtid.h:47
Representation of the GTID tag.
Definition: tag.h:49
Represents Transaction Source Identifier which is composed of source UUID and transaction tag.
Definition: tsid.h:44
std::string to_string() const
Returns textual representation of Transaction Source Identifier.
Definition: tsid.cpp:34
#define mysql_cond_wait(C, M)
Definition: mysql_cond.h:48
#define mysql_cond_timedwait(C, M, T)
Definition: mysql_cond.h:51
#define mysql_mutex_lock(M)
Definition: mysql_mutex.h:50
#define mysql_mutex_unlock(M)
Definition: mysql_mutex.h:57
#define mysql_rwlock_rdlock(T)
Definition: mysql_rwlock.h:61
#define mysql_rwlock_unlock(T)
Definition: mysql_rwlock.h:91
#define mysql_rwlock_init(K, T)
Definition: mysql_rwlock.h:41
#define mysql_rwlock_tryrdlock(T)
Definition: mysql_rwlock.h:81
#define mysql_rwlock_destroy(T)
Definition: mysql_rwlock.h:51
#define mysql_rwlock_trywrlock(T)
Definition: mysql_rwlock.h:86
#define mysql_rwlock_wrlock(T)
Definition: mysql_rwlock.h:71
static char buf[MAX_BUF]
Definition: conf_to_src.cc:74
const char * p
Definition: ctype-mb.cc:1227
#define MY_WME
Definition: my_sys.h:136
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
unsigned int PSI_mutex_key
Instrumented mutex key.
Definition: psi_mutex_bits.h:52
unsigned int PSI_rwlock_key
Instrumented rwlock key.
Definition: psi_rwlock_bits.h:44
#define mysql_mutex_assert_not_owner(M)
Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes.
Definition: mysql_mutex.h:126
#define mysql_mutex_assert_owner(M)
Wrapper, to use safe_mutex_assert_owner with instrumented mutexes.
Definition: mysql_mutex.h:112
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
A better implementation of the UNIX ctype(3) library.
std::map< Key, Value, Compare, Map_allocator_type< Key, Value > > Map_myalloc
Map using custom Malloc_allocator allocator.
Definition: map_helpers.h:147
#define DBUG_PRINT(keyword, arglist)
Definition: my_dbug.h:181
#define DBUG_TRACE
Definition: my_dbug.h:146
unsigned long long int ulonglong
Definition: my_inttypes.h:56
unsigned char uchar
Definition: my_inttypes.h:52
int64_t int64
Definition: my_inttypes.h:68
#define MYF(v)
Definition: my_inttypes.h:97
int32_t int32
Definition: my_inttypes.h:66
void * my_malloc(PSI_memory_key key, size_t size, int flags)
Allocates size bytes of memory.
Definition: my_memory.cc:57
void my_free(void *ptr)
Frees the memory pointed by the ptr.
Definition: my_memory.cc:81
#define HAVE_PSI_INTERFACE
Definition: my_psi_config.h:39
static bool is_timeout(int e)
Definition: my_thread.h:57
uint32 my_thread_id
Definition: my_thread_local.h:34
static int count
Definition: myisam_ftdump.cc:45
int(* mysql_cond_broadcast)(mysql_cond_t *that, const char *src_file, unsigned int src_line)
Definition: mysql_cond_service.h:52
void copy(Shards< COUNT > &dst, const Shards< COUNT > &src) noexcept
Copy the counters, overwrite destination.
Definition: ut0counter.h:354
Type sub(Shards< COUNT > &shards, size_t id, size_t n)
Decrement the counter for a shard by n.
Definition: ut0counter.h:280
std::string str(const mysqlrouter::ConfigGenerator::Options::Endpoint &ep)
Definition: config_generator.cc:1077
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
static PFS_engine_table_share_proxy table
Definition: pfs.cc:61
Definition: buf0block_hint.cc:30
Definition: locked_sidno_set.cc:26
int rpl_sidno
Type of SIDNO (source ID number, first component of GTID)
Definition: sidno.h:27
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
static bool timeout(bool(*wait_condition)())
Timeout function.
Definition: log0meb.cc:499
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
constexpr auto tsid_max_length
Maximum TSID text length (without null character)
Definition: tsid.h:38
Gtid_format
Gtid binary format indicator.
Definition: gtid_format.h:39
std::int64_t gno_t
Definition: global.h:37
Return_status
Simple, strongly-typed enumeration to indicate internal status: ok, error.
Definition: return_status.h:40
HARNESS_EXPORT std::string string_format(const char *format,...)
Definition: utilities.cc:64
size_t size(const char *const c)
Definition: base64.h:46
static mysql_service_status_t flush(reference_caching_cache cache) noexcept
Definition: component.cc:114
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
mode
Definition: file_handle.h:61
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2732
static std::mutex lock
Definition: net_ns.cc:56
Instrumentation helpers for conditions.
Instrumentation helpers for rwlock.
PSI_memory_key key_memory_tsid_map_Node
Definition: rpl_gtid_tsid_map.cc:44
required uint32 status
Definition: replication_asynchronous_connection_failover.proto:61
repeated Action action
Definition: replication_group_member_actions.proto:43
Experimental API header.
rpl_gno get_last_executed_gno(rpl_sidno sidno)
Return last gno for a given sidno, see Gtid_state::get_last_executed_gno() for details.
Definition: rpl_gtid_misc.cc:303
const int MAX_THREAD_ID_TEXT_LENGTH
The maximal possible length of thread_id when printed in decimal.
Definition: rpl_gtid.h:290
const rpl_gno GNO_WARNING_THRESHOLD
If the GNO goes above the number, generate a warning.
Definition: rpl_gtid.h:286
ulong _gtid_consistency_mode
Current value for ENFORCE_GTID_CONSISTENCY.
Definition: rpl_gtid_misc.cc:63
const rpl_gno GNO_END
One-past-the-max value of GNO.
Definition: rpl_gtid.h:284
enum_return_status map_macro_enum(int status)
enum to map the result of Uuid::parse to the above Macros
Definition: rpl_gtid.h:236
enum_gtid_consistency_mode get_gtid_consistency_mode()
Return the current value of ENFORCE_GTID_CONSISTENCY.
Definition: rpl_gtid_misc.cc:70
void gtid_state_commit_or_rollback(THD *thd, bool needs_to, bool do_commit)
The function commits or rolls back the gtid state if it needs to.
Definition: rpl_gtid.h:4364
PSI_memory_key key_memory_Gtid_cache_to_string
mysql::gtid::gno_t rpl_gno
GNO, the second (numeric) component of a GTID, is an alias of mysql::gtid::gno_t.
Definition: rpl_gtid.h:114
enum_return_status
Generic return type for many functions that can succeed or fail.
Definition: rpl_gtid.h:139
@ RETURN_STATUS_OK
The function completed successfully.
Definition: rpl_gtid.h:141
@ RETURN_STATUS_UNREPORTED_ERROR
The function completed with error but did not report it.
Definition: rpl_gtid.h:143
@ RETURN_STATUS_REPORTED_ERROR
The function completed with error and has called my_error.
Definition: rpl_gtid.h:145
bool set_gtid_next(THD *thd, const Gtid_specification &spec)
Acquire ownership of the given Gtid_specification.
Definition: rpl_gtid_execution.cc:46
const char * gtid_consistency_mode_names[]
Strings holding the enumeration values for gtid_consistency_mode_names.
Definition: rpl_gtid_misc.cc:64
const mysql::gtid::Tsid & get_tsid_from_global_tsid_map(rpl_sidno sidno)
Return Tsid for a given sidno on the global_tsid_map.
Definition: rpl_gtid_misc.cc:297
int format_gno(char *s, rpl_gno gno)
Formats a GNO as a string.
Definition: rpl_gtid_set.cc:433
mysql::gtid::Uuid rpl_sid
Definition: rpl_gtid.h:310
Gtid_mode global_gtid_mode
The one and only instance of Gtid_mode.
Definition: rpl_gtid_mode.cc:31
const int MAX_GNO_TEXT_LENGTH
The length of MAX_GNO when printed in decimal.
Definition: rpl_gtid.h:288
PSI_memory_key key_memory_Gtid_state_group_commit_sidno
Definition: rpl_gtid_state.cc:52
bool is_already_logged_transaction(const THD *thd)
Check if current transaction should be skipped, that is, if GTID_NEXT was already logged.
Definition: rpl_gtid_execution.cc:332
void gtid_set_performance_schema_values(const THD *thd)
Definition: rpl_gtid_execution.cc:607
bool gtid_reacquire_ownership_if_anonymous(THD *thd)
If gtid_next=ANONYMOUS or NOT_YET_DETERMINED, but the thread does not hold anonymous ownership,...
Definition: rpl_gtid_execution.cc:391
enum_gtid_statement_status
Indicates if a statement should be skipped or not.
Definition: rpl_gtid.h:4215
@ GTID_STATEMENT_CANCEL
Statement should be cancelled.
Definition: rpl_gtid.h:4219
@ GTID_STATEMENT_EXECUTE
Statement can execute.
Definition: rpl_gtid.h:4217
@ GTID_STATEMENT_SKIP
Statement should be skipped, but there may be an implicit commit after the statement if gtid_commit i...
Definition: rpl_gtid.h:4224
bool gtid_pre_statement_post_implicit_commit_checks(THD *thd)
Perform GTID-related checks before executing a statement, but after executing an implicit commit befo...
Definition: rpl_gtid_execution.cc:577
int64 rpl_binlog_pos
Definition: rpl_gtid.h:115
rpl_gno parse_gno(const char **s)
Parse a GNO from a string.
Definition: rpl_gtid_set.cc:425
PSI_memory_key key_memory_Gtid_set_Interval_chunk
Definition: rpl_gtid_set.cc:68
Tsid_map * global_tsid_map
Definition: mysqld.cc:1866
const char * get_gtid_consistency_mode_string(enum_gtid_consistency_mode mode)
Return the given GTID_CONSISTENCY_MODE as a string.
Definition: rpl_gtid.h:270
Gtid_state * gtid_state
Global state of GTIDs.
Definition: mysqld.cc:1867
PSI_memory_key key_memory_Gtid_set_to_string
Definition: rpl_gtid_set.cc:67
#define RETURN_OK
Returns RETURN_STATUS_OK.
Definition: rpl_gtid.h:227
std::ostream & operator<<(std::ostream &oss, Gtid_mode::value_type const &mode)
Definition: rpl_gtid_mode.cc:72
enum_gtid_consistency_mode
Possible values for ENFORCE_GTID_CONSISTENCY.
Definition: rpl_gtid.h:247
@ GTID_CONSISTENCY_MODE_ON
Definition: rpl_gtid.h:249
@ GTID_CONSISTENCY_MODE_WARN
Definition: rpl_gtid.h:250
@ GTID_CONSISTENCY_MODE_OFF
Definition: rpl_gtid.h:248
PSI_memory_key key_memory_Owned_gtids_to_string
Definition: psi_memory_key.cc:67
rpl_sidno get_sidno_from_global_tsid_map(const mysql::gtid::Tsid &tsid)
Return sidno for a given tsid, see Tsid_map::add_sid() for details.
Definition: rpl_gtid_misc.cc:287
Checkable_rwlock * global_tsid_lock
Protects Gtid_state. See comment above gtid_state for details.
Definition: mysqld.cc:1865
enum_gtid_type
Enumeration of different types of values for Gtid_specification, i.e, the different internal states t...
Definition: rpl_gtid.h:3917
@ UNDEFINED_GTID
GTID_NEXT is set to this state after a transaction with GTID_NEXT=='UUID:NUMBER' is committed.
Definition: rpl_gtid.h:3986
@ ANONYMOUS_GTID
Specifies that the transaction is anonymous, i.e., it does not have a GTID and will never be assigned...
Definition: rpl_gtid.h:3952
@ ASSIGNED_GTID
Specifies that the transaction has been assigned a GTID (UUID:NUMBER).
Definition: rpl_gtid.h:3942
@ PRE_GENERATE_GTID
The applier sets GTID_NEXT this state internally, when it processes an Anonymous_gtid_log_event on a ...
Definition: rpl_gtid.h:4023
@ NOT_YET_DETERMINED_GTID
Definition: rpl_gtid.h:4013
@ AUTOMATIC_GTID
Specifies that the GTID has not been generated yet; it will be generated on commit.
Definition: rpl_gtid.h:3934
void check_return_status(enum_return_status status, const char *action, const char *status_name, int allow_unreported)
Definition: rpl_gtid_misc.cc:260
enum_gtid_statement_status gtid_pre_statement_checks(THD *thd)
Perform GTID-related checks before executing a statement:
Definition: rpl_gtid_execution.cc:469
cs::index::rpl_sidno rpl_sidno
Type of SIDNO (source ID number, first component of GTID)
Definition: rpl_gtid.h:110
#define RETURN_UNREPORTED_ERROR
Does a DBUG_PRINT and returns RETURN_STATUS_UNREPORTED_ERROR.
Definition: rpl_gtid.h:231
PSI_memory_key key_memory_Gtid_state_to_string
Definition: psi_memory_key.cc:50
mysql::gtid::Tsid Tsid
Definition: rpl_gtid_state.cc:56
#define MAX_SLAVE_ERRMSG
Maximum size of an error message from a slave thread.
Definition: rpl_reporting.h:43
Holds information about a GTID interval: the sidno, the first gno and the last gno of this interval.
Definition: rpl_gtid.h:1079
rpl_gno gno_start
Definition: rpl_gtid.h:1083
rpl_gno gno_end
Definition: rpl_gtid.h:1085
void set(rpl_sidno sid_no, rpl_gno start, rpl_gno end)
Definition: rpl_gtid.h:1086
rpl_sidno sidno
Definition: rpl_gtid.h:1081
Contains a list of intervals allocated by this Gtid_set.
Definition: rpl_gtid.h:2307
Interval intervals[1]
Definition: rpl_gtid.h:2309
Interval_chunk * next
Definition: rpl_gtid.h:2308
Represents one element in the linked list of intervals associated with a SIDNO.
Definition: rpl_gtid.h:2042
rpl_gno start
The first GNO of this interval.
Definition: rpl_gtid.h:2045
rpl_gno end
The first GNO after this interval.
Definition: rpl_gtid.h:2047
bool equals(const Interval &other) const
Return true iff this interval is equal to the given interval.
Definition: rpl_gtid.h:2049
Interval * next
Pointer to next interval in list.
Definition: rpl_gtid.h:2053
Class Gtid_set::String_format defines the separators used by Gtid_set::to_string.
Definition: rpl_gtid.h:1904
const char * end
The generated string begins with this.
Definition: rpl_gtid.h:1908
const int begin_length
The following fields are the lengths of each field above.
Definition: rpl_gtid.h:1922
const int gno_start_end_separator_length
Definition: rpl_gtid.h:1926
const char * gno_sid_separator
In 'SID:GNO,SID:GNO', this is the ','.
Definition: rpl_gtid.h:1918
const char * tsid_gno_separator
In 'TSID:GNO', this is the ':'.
Definition: rpl_gtid.h:1912
const int empty_set_string_length
Definition: rpl_gtid.h:1929
const int gno_gno_separator_length
Definition: rpl_gtid.h:1927
const char * begin
The generated string begins with this.
Definition: rpl_gtid.h:1906
const char * empty_set_string
If the set is empty and this is not NULL, then this string is generated.
Definition: rpl_gtid.h:1920
const char * gno_gno_separator
In 'SID:GNO:GNO', this is the second ':'.
Definition: rpl_gtid.h:1916
const char * gno_start_end_separator
In 'SID:GNO-GNO', this is the '-'.
Definition: rpl_gtid.h:1914
const int tsid_gno_separator_length
Definition: rpl_gtid.h:1925
const int gno_sid_separator_length
Definition: rpl_gtid.h:1928
const int end_length
Definition: rpl_gtid.h:1923
const char * tag_sid_separator
In 'SID:TAG', this is the ':'.
Definition: rpl_gtid.h:1910
const int tag_sid_separator_length
Definition: rpl_gtid.h:1924
Holds information about a Gtid_set.
Definition: rpl_gtid.h:2552
Gtid_set * gtid_set
Pointer to the Gtid_set.
Definition: rpl_gtid.h:2554
Gtid_set * set_non_null(Tsid_map *sm)
Do nothing if this object is non-null; set to empty set otherwise.
Definition: rpl_gtid.h:2567
Gtid_set * get_gtid_set() const
Return NULL if this is NULL, otherwise return the Gtid_set.
Definition: rpl_gtid.h:2558
void set_null()
Set this Gtid_set to NULL.
Definition: rpl_gtid.h:2578
bool is_non_null
True if this Gtid_set is NULL.
Definition: rpl_gtid.h:2556
This struct represents a specification of a GTID for a statement to be executed: either "AUTOMATIC",...
Definition: rpl_gtid.h:4034
static constexpr auto str_anonymous
Definition: rpl_gtid.h:4041
void set_not_yet_determined()
Set the type to NOT_YET_DETERMINED_GTID.
Definition: rpl_gtid.h:4120
mysql::utils::Return_status parse(Tsid_map *tsid_map, const char *text)
Parses the given string and stores in this Gtid_specification.
Definition: rpl_gtid_specification.cc:62
static constexpr auto str_automatic_tagged
Definition: rpl_gtid.h:4037
static constexpr auto str_automatic
Definition: rpl_gtid.h:4036
enum_gtid_type type
The type of this GTID.
Definition: rpl_gtid.h:4047
bool is_undefined() const
Helper function indicating whether this is an undefined GTID.
Definition: rpl_gtid.h:4086
static bool is_valid(const char *text)
Returns true if the given string is a valid Gtid_specification.
Definition: rpl_gtid_specification.cc:98
Gtid gtid
The GTID: { SIDNO, GNO } if type == GTID; { 0, 0 } if type == AUTOMATIC or ANONYMOUS.
Definition: rpl_gtid.h:4053
bool is_assigned() const
Helper function indicating whether this is an assigned GTID.
Definition: rpl_gtid.h:4090
static constexpr auto str_pre_generated
Definition: rpl_gtid.h:4039
static constexpr auto str_automatic_sep
Definition: rpl_gtid.h:4038
bool equals(const Gtid_specification &other) const
Return true if this Gtid_specification is equal to 'other'.
Definition: rpl_gtid.h:4131
Tag_plain automatic_tag
Tag defined by the user while specifying GTID_NEXT="AUTOMATIC:TAG".
Definition: rpl_gtid.h:4058
bool is_automatic_tagged() const
Helper function indicating whether this is to-be-generated GTID with a tag assigned.
Definition: rpl_gtid_specification.cc:58
static bool is_tagged(const char *text)
Returns true if the given string is a tagged Gtid_specification.
Definition: rpl_gtid_specification.cc:116
void set(const Gtid &gtid_param)
Set the type to ASSIGNED_GTID and TSID, GNO to the given Gtid.
Definition: rpl_gtid.h:4104
mysql::gtid::Tag Tag
Definition: rpl_gtid.h:4044
bool is_automatic() const
Helper function indicating whether this is to-be-generated GTID.
Definition: rpl_gtid.h:4082
static const int MAX_TEXT_LENGTH
Definition: rpl_gtid.h:4161
void dbug_print(const char *text="", bool need_lock=false) const
Print this Gtid_specification to the trace file if debug is enabled; no-op otherwise.
Definition: rpl_gtid.h:4198
std::size_t automatic_to_string(char *buf) const
Prints automatic tag specification to the given buffer.
Definition: rpl_gtid_specification.cc:133
void set_anonymous()
Set the type to ANONYMOUS_GTID.
Definition: rpl_gtid.h:4115
void set_undefined()
Set to undefined. Must only be called if the type is ASSIGNED_GTID.
Definition: rpl_gtid.h:4125
int to_string(const Tsid_map *tsid_map, char *buf, bool need_lock=false) const
Writes this Gtid_specification to the given string buffer.
Definition: rpl_gtid_specification.cc:180
void set_automatic()
Set the type to AUTOMATIC_GTID.
Definition: rpl_gtid.h:4106
void set(rpl_sidno sidno, rpl_gno gno)
Set the type to ASSIGNED_GTID and SIDNO, GNO to the given values.
Definition: rpl_gtid.h:4066
static constexpr auto str_not_yet_determined
Definition: rpl_gtid.h:4040
bool equals(const Gtid &other_gtid) const
Return true if this Gtid_specification is a ASSIGNED_GTID with the same TSID, GNO as 'other_gtid'.
Definition: rpl_gtid.h:4139
static bool is_automatic(const enum_gtid_type &type)
Helper function indicating whether this is to-be-generated GTID.
Definition: rpl_gtid.h:4076
void print() const
Debug only: print this Gtid_specification to stdout.
Definition: rpl_gtid.h:4188
Tag generate_tag() const
Returns tag object generated from internal tag data.
Definition: rpl_gtid_specification.cc:56
TODO: Move this structure to mysql/binlog/event/control_events.h when we start using C++11.
Definition: rpl_gtid.h:1102
static const int MAX_TEXT_LENGTH
The maximal length of the textual representation of a TSID, not including the terminating '\0'.
Definition: rpl_gtid.h:1139
mysql::utils::Return_status parse(Tsid_map *tsid_map, const char *text)
Parses the given string and stores in this Gtid.
Definition: rpl_gtid_misc.cc:186
bool is_empty() const
Return true if sidno is zero (and assert that gno is zero too in this case).
Definition: rpl_gtid.h:1127
int to_string_gno(char *buf) const
Converts internal gno into the string.
Definition: rpl_gtid_misc.cc:205
void set(rpl_sidno sidno_arg, rpl_gno gno_arg)
Set both components to the given, positive values.
Definition: rpl_gtid.h:1116
void clear()
Set both components to 0.
Definition: rpl_gtid.h:1111
void print(const Tsid_map *tsid_map) const
Debug only: print this Gtid to stdout.
Definition: rpl_gtid.h:1204
void dbug_print(const Tsid_map *tsid_map, const char *text="", bool need_lock=false) const
Print this Gtid to the trace file if debug is enabled; no-op otherwise.
Definition: rpl_gtid.h:1211
rpl_gno gno
GNO of this Gtid.
Definition: rpl_gtid.h:1108
static std::tuple< mysql::utils::Return_status, rpl_sid, std::size_t > parse_sid_str(const char *text, std::size_t pos)
Parses SID from a textual representation of the GTID.
Definition: rpl_gtid_misc.cc:84
static constexpr auto gtid_separator
Definition of GTID separator (colon) which separates UUID and GNO.
Definition: rpl_gtid.h:1200
static void report_parsing_error(const char *text)
Helper used to report BINLOG error.
Definition: rpl_gtid_misc.cc:136
static std::pair< mysql::utils::Return_status, std::size_t > parse_gtid_separator(const char *text, std::size_t pos)
Parses GTID separator from a textual representation of the GTID (text)
Definition: rpl_gtid_misc.cc:142
static std::pair< mysql::utils::Return_status, mysql::gtid::Gtid > parse_gtid_from_cstring(const char *text)
Parses GTID from text.
Definition: rpl_gtid_misc.cc:156
static std::pair< Tag, std::size_t > parse_tag_str(const char *text, std::size_t pos)
Parses TAG from a textual representation of the GTID (text)
Definition: rpl_gtid_misc.cc:101
rpl_sidno sidno
SIDNO of this Gtid.
Definition: rpl_gtid.h:1106
static std::size_t skip_whitespace(const char *text, std::size_t pos)
Helper function used to skip whitespaces in GTID specification.
Definition: rpl_gtid_misc.cc:76
bool equals(const Gtid &other) const
Returns true if this Gtid has the same sid and gno as 'other'.
Definition: rpl_gtid.h:1167
static std::tuple< mysql::utils::Return_status, rpl_gno, std::size_t > parse_gno_str(const char *text, std::size_t pos)
Parses GNO from a textual representation of the GTID (text)
Definition: rpl_gtid_misc.cc:111
static bool is_valid(const char *text)
Returns true if parse() would succeed, but doesn't store the result anywhere.
Definition: rpl_gtid_misc.cc:252
int to_string(const Tsid &tsid, char *buf) const
Convert a Gtid to a string.
Definition: rpl_gtid_misc.cc:214
A mutex/cond pair.
Definition: rpl_gtid.h:1058
mysql_mutex_t mutex
Definition: rpl_gtid.h:1059
mysql_cond_t cond
Definition: rpl_gtid.h:1060
Represents one owned GTID.
Definition: rpl_gtid.h:2769
my_thread_id owner
Owner of the GTID.
Definition: rpl_gtid.h:2773
rpl_gno gno
GNO of the GTID.
Definition: rpl_gtid.h:2771
Stage instrument information.
Definition: psi_stage_bits.h:74
Structure to store the GTID and timing information.
Definition: rpl_gtid.h:1264
Trx_monitoring_info & operator=(const Trx_monitoring_info &)=default
uint last_transient_error_number
Number of the last transient error of this transaction.
Definition: rpl_gtid.h:1280
ulonglong last_transient_error_timestamp
Timestamp in microseconds of the last transient error of this transaction.
Definition: rpl_gtid.h:1284
Gtid gtid
GTID being monitored.
Definition: rpl_gtid.h:1266
ulonglong end_time
When the GTID transaction finished to be processed.
Definition: rpl_gtid.h:1274
void copy_to_ps_table(Tsid_map *tsid_map, char *gtid_arg, uint *gtid_length_arg, ulonglong *original_commit_ts_arg, ulonglong *immediate_commit_ts_arg, ulonglong *start_time_arg) const
Copies this transaction monitoring information to the output parameters passed as input,...
Definition: rpl_gtid_misc.cc:352
ulonglong immediate_commit_timestamp
ICT of the GTID being monitored.
Definition: rpl_gtid.h:1270
bool is_retrying
True when the transaction is retrying.
Definition: rpl_gtid.h:1288
mysql::binlog::event::compression::type compression_type
The compression type.
Definition: rpl_gtid.h:1290
bool skipped
True if the GTID is being applied but will be skipped.
Definition: rpl_gtid.h:1276
void clear()
Clear all fields of the structure.
Definition: rpl_gtid_misc.cc:334
ulonglong original_commit_timestamp
OCT of the GTID being monitored.
Definition: rpl_gtid.h:1268
ulong transaction_retries
Number of times this transaction was retried.
Definition: rpl_gtid.h:1286
Trx_monitoring_info()
Constructor.
Definition: rpl_gtid_misc.cc:313
ulonglong uncompressed_bytes
The uncompressed bytes.
Definition: rpl_gtid.h:1294
ulonglong compressed_bytes
The compressed bytes.
Definition: rpl_gtid.h:1292
char last_transient_error_message[MAX_SLAVE_ERRMSG]
Message of the last transient error of this transaction.
Definition: rpl_gtid.h:1282
bool is_info_set
True when this information contains useful data.
Definition: rpl_gtid.h:1278
ulonglong start_time
When the GTID transaction started to be processed.
Definition: rpl_gtid.h:1272
Tag representation so that:
Definition: tag_plain.h:48
void clear()
Clear this tag.
Definition: tag_plain.cpp:38
Uuid is a trivial and of standard layout The structure contains the following components.
Definition: uuid.h:64
An instrumented cond structure.
Definition: mysql_cond_bits.h:50
An instrumented mutex structure.
Definition: mysql_mutex_bits.h:50
An instrumented rwlock structure.
Definition: mysql_rwlock_bits.h:51
Definition: result.h:30
int n
Definition: xcom_base.cc:509