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