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