1 /* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
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 also distributed 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 included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22    02110-1301 USA */
23 
24 
25 #ifndef RPL_GTID_H_INCLUDED
26 #define RPL_GTID_H_INCLUDED
27 
28 
29 #include <m_string.h>
30 #include <mysqld_error.h>
31 #include <my_global.h>
32 #ifdef MYSQL_SERVER
33 #include <mysqld.h>
34 #endif
35 /**
36   Report an error from code that can be linked into either the server
37   or mysqlbinlog.  There is no common error reporting mechanism, so we
38   have to duplicate the error message (write it out in the source file
39   for mysqlbinlog, write it in share/errmsg-utf8.txt for the server).
40 
41   @param MYSQLBINLOG_ERROR arguments to mysqlbinlog's 'error'
42   function, including the function call parentheses
43   @param SERVER_ERROR arguments to my_error, including the function
44   call parentheses.
45 */
46 #ifdef MYSQL_CLIENT
47 #define BINLOG_ERROR(MYSQLBINLOG_ERROR, SERVER_ERROR) error MYSQLBINLOG_ERROR
48 #else
49 #define BINLOG_ERROR(MYSQLBINLOG_ERROR, SERVER_ERROR) my_error SERVER_ERROR
50 #endif
51 
52 
53 #include "hash.h"
54 #include "lf.h"
55 #include "my_atomic.h"
56 
57 /**
58   This macro is used to check that the given character, pointed to by the
59   character pointer, is a space or not.
60 */
61 #define SKIP_WHITESPACE() while (my_isspace(&my_charset_utf8_general_ci, *s)) s++
62 /*
63   This macro must be used to filter out parts of the code that
64   is not used now but may be useful in future. In other words,
65   we want to keep such code until we make up our minds on whether
66   it should be removed or not.
67 */
68 #undef NON_DISABLED_GTID
69 
70 /*
71   This macro must be used to filter out parts of the code that
72   is not used now but we are not sure if there is a bug around
73   them. In other words, we want to keep such code until we have
74   time to investigate it.
75 */
76 #undef NON_ERROR_GTID
77 
78 #ifndef MYSQL_CLIENT
79 class String;
80 class THD;
81 #endif // ifndef MYSQL_CLIENT
82 
83 
84 /// Type of SIDNO (source ID number, first component of GTID)
85 typedef int32 rpl_sidno;
86 /// Type for GNO (group number, second component of GTID)
87 typedef int64 rpl_gno;
88 /// Type of binlog_pos (positions in binary log)
89 typedef int64 rpl_binlog_pos;
90 
91 
92 /**
93   Generic return type for many functions that can succeed or fail.
94 
95   This is used in conjuction with the macros below for functions where
96   the return status either indicates "success" or "failure".  It
97   provides the following features:
98 
99    - The macros can be used to conveniently propagate errors from
100      called functions back to the caller.
101 
102    - If a function is expected to print an error using my_error before
103      it returns an error status, then the macros assert that my_error
104      has been called.
105 
106    - Does a DBUG_PRINT before returning failure.
107 */
108 enum enum_return_status
109 {
110   /// The function completed successfully.
111   RETURN_STATUS_OK= 0,
112   /// The function completed with error but did not report it.
113   RETURN_STATUS_UNREPORTED_ERROR= 1,
114   /// The function completed with error and has called my_error.
115   RETURN_STATUS_REPORTED_ERROR= 2
116 };
117 
118 /**
119   Lowest level macro used in the PROPAGATE_* and RETURN_* macros
120   below.
121 
122   If DBUG_OFF is defined, does nothing. Otherwise, if STATUS is
123   RETURN_STATUS_OK, does nothing; otherwise, make a dbug printout and
124   (if ALLOW_UNREPORTED==0) assert that STATUS !=
125   RETURN_STATUS_UNREPORTED.
126 
127   @param STATUS The status to return.
128   @param ACTION A text that describes what we are doing: either
129   "Returning" or "Propagating" (used in DBUG_PRINT macros)
130   @param STATUS_NAME The stringified version of the STATUS (used in
131   DBUG_PRINT macros).
132   @param ALLOW_UNREPORTED If false, the macro asserts that STATUS is
133   not RETURN_STATUS_UNREPORTED_ERROR.
134 */
135 #ifdef DBUG_OFF
136 #define __CHECK_RETURN_STATUS(STATUS, ACTION, STATUS_NAME, ALLOW_UNREPORTED)
137 #else
138 extern void check_return_status(enum_return_status status,
139                                 const char *action, const char *status_name,
140                                 int allow_unreported);
141 #define __CHECK_RETURN_STATUS(STATUS, ACTION, STATUS_NAME, ALLOW_UNREPORTED) \
142   check_return_status(STATUS, ACTION, STATUS_NAME, ALLOW_UNREPORTED);
143 #endif
144 /**
145   Low-level macro that checks if STATUS is RETURN_STATUS_OK; if it is
146   not, then RETURN_VALUE is returned.
147   @see __DO_RETURN_STATUS
148 */
149 #define __PROPAGATE_ERROR(STATUS, RETURN_VALUE, ALLOW_UNREPORTED)       \
150   do                                                                    \
151   {                                                                     \
152     enum_return_status __propagate_error_status= STATUS;                \
153     if (__propagate_error_status != RETURN_STATUS_OK) {                 \
154       __CHECK_RETURN_STATUS(__propagate_error_status, "Propagating",    \
155                             #STATUS, ALLOW_UNREPORTED);                 \
156       DBUG_RETURN(RETURN_VALUE);                                        \
157     }                                                                   \
158   } while (0)
159 /// Low-level macro that returns STATUS. @see __DO_RETURN_STATUS
160 #define __RETURN_STATUS(STATUS, ALLOW_UNREPORTED)                       \
161   do                                                                    \
162   {                                                                     \
163     enum_return_status __return_status_status= STATUS;                  \
164     __CHECK_RETURN_STATUS(__return_status_status, "Returning",          \
165                           #STATUS, ALLOW_UNREPORTED);                   \
166     DBUG_RETURN(__return_status_status);                                \
167   } while (0)
168 /**
169   If STATUS (of type enum_return_status) returns RETURN_STATUS_OK,
170   does nothing; otherwise, does a DBUG_PRINT and returns STATUS.
171 */
172 #define PROPAGATE_ERROR(STATUS)                                 \
173   __PROPAGATE_ERROR(STATUS, __propagate_error_status, true)
174 /**
175   If STATUS (of type enum_return_status) returns RETURN_STATUS_OK,
176   does nothing; otherwise asserts that STATUS ==
177   RETURN_STATUS_REPORTED_ERROR, does a DBUG_PRINT, and returns STATUS.
178 */
179 #define PROPAGATE_REPORTED_ERROR(STATUS)                        \
180   __PROPAGATE_ERROR(STATUS, __propagate_error_status, false)
181 /**
182   If STATUS (of type enum_return_status) returns RETURN_STATUS_OK,
183   does nothing; otherwise asserts that STATUS ==
184   RETURN_STATUS_REPORTED_ERROR, does a DBUG_PRINT, and returns 1.
185 */
186 #define PROPAGATE_REPORTED_ERROR_INT(STATUS)    \
187   __PROPAGATE_ERROR(STATUS, 1, false)
188 /**
189   If STATUS returns something else than RETURN_STATUS_OK, does a
190   DBUG_PRINT.  Then, returns STATUS.
191 */
192 #define RETURN_STATUS(STATUS) __RETURN_STATUS(STATUS, true)
193 /**
194   Asserts that STATUS is not RETURN_STATUS_UNREPORTED_ERROR.  Then, if
195   STATUS is RETURN_STATUS_REPORTED_ERROR, does a DBUG_PRINT.  Then,
196   returns STATUS.
197 */
198 #define RETURN_REPORTED_STATUS(STATUS) __RETURN_STATUS(STATUS, false)
199 /// Returns RETURN_STATUS_OK.
200 #define RETURN_OK DBUG_RETURN(RETURN_STATUS_OK)
201 /// Does a DBUG_PRINT and returns RETURN_STATUS_REPORTED_ERROR.
202 #define RETURN_REPORTED_ERROR RETURN_STATUS(RETURN_STATUS_REPORTED_ERROR)
203 /// Does a DBUG_PRINT and returns RETURN_STATUS_UNREPORTED_ERROR.
204 #define RETURN_UNREPORTED_ERROR RETURN_STATUS(RETURN_STATUS_UNREPORTED_ERROR)
205 
206 
207 /// The maximum value of GNO
208 const rpl_gno MAX_GNO= LONGLONG_MAX;
209 /// The length of MAX_GNO when printed in decimal.
210 const int MAX_GNO_TEXT_LENGTH= 19;
211 /// The maximal possible length of thread_id when printed in decimal.
212 const int MAX_THREAD_ID_TEXT_LENGTH= 19;
213 
214 
215 /**
216   Parse a GNO from a string.
217 
218   @param s Pointer to the string. *s will advance to the end of the
219   parsed GNO, if a correct GNO is found.
220   @retval GNO if a correct GNO (i.e., 0 or positive number) was found.
221   @retval -1 otherwise.
222 */
223 rpl_gno parse_gno(const char **s);
224 /**
225   Formats a GNO as a string.
226 
227   @param s The buffer.
228   @param gno The GNO.
229   @return Length of the generated string.
230 */
231 int format_gno(char *s, rpl_gno gno);
232 
233 
234 /**
235   Represents a UUID.
236 
237   This is a POD.  It has to be a POD because it is a member of
238   Sid_map::Node which is stored in both HASH and DYNAMIC_ARRAY.
239 */
240 struct Uuid
241 {
242   /**
243     Stores the UUID represented by a string on the form
244     XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX in this object.
245     @return RETURN_STATUS_OK or RETURN_STATUS_UNREPORTED_ERROR.
246   */
247   enum_return_status parse(const char *string);
248   /// Set to all zeros.
clearUuid249   void clear() { memset(bytes, 0, BYTE_LENGTH); }
250   /// Copies the given 16-byte data to this UUID.
copy_fromUuid251   void copy_from(const uchar *data) { memcpy(bytes, data, BYTE_LENGTH); }
252   /// Copies the given UUID object to this UUID.
copy_fromUuid253   void copy_from(const Uuid &data) { copy_from(data.bytes); }
254   /// Copies the given UUID object to this UUID.
copy_toUuid255   void copy_to(uchar *data) const { memcpy(data, bytes, BYTE_LENGTH); }
256   /// Returns true if this UUID is equal the given UUID.
equalsUuid257   bool equals(const Uuid &other) const
258   { return memcmp(bytes, other.bytes, BYTE_LENGTH) == 0; }
259   /**
260     Generates a 36+1 character long representation of this UUID object
261     in the given string buffer.
262 
263     @retval 36 - the length of the resulting string.
264   */
265   size_t to_string(char *buf) const;
266   /// Convert the given binary buffer to a UUID
267   static size_t to_string(const uchar* bytes_arg, char *buf);
268 #ifndef DBUG_OFF
269   /// Debugging only: Print this Uuid to stdout.
printUuid270   void print() const
271   {
272     char buf[TEXT_LENGTH + 1];
273     to_string(buf);
274     printf("%s\n", buf);
275   }
276 #endif
277   /// Print this Uuid to the trace file if debug is enabled; no-op otherwise.
278   void dbug_print(const char *text= "") const
279   {
280 #ifndef DBUG_OFF
281     char buf[TEXT_LENGTH + 1];
282     to_string(buf);
283     DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", buf));
284 #endif
285   }
286   /**
287     Return true if parse() would return succeed, but don't actually
288     store the result anywhere.
289   */
290   static bool is_valid(const char *string);
291   /// The number of bytes in the textual representation of a Uuid.
292   static const size_t TEXT_LENGTH= 36;
293   /// The number of bytes in the data of a Uuid.
294   static const size_t BYTE_LENGTH= 16;
295   /// The number of bits in the data of a Uuid.
296   static const size_t BIT_LENGTH= 128;
297   /// The data for this Uuid.
298   uchar bytes[BYTE_LENGTH];
299 private:
300   static const int NUMBER_OF_SECTIONS= 5;
301   static const int bytes_per_section[NUMBER_OF_SECTIONS];
302   static const int hex_to_byte[256];
303 };
304 
305 
306 typedef Uuid rpl_sid;
307 
308 
309 /**
310   This has the functionality of mysql_rwlock_t, with two differences:
311   1. It has additional operations to check if the read and/or write lock
312      is held at the moment.
313   2. It is wrapped in an object-oriented interface.
314 
315   Note that the assertions do not check whether *this* thread has
316   taken the lock (that would be more complicated as it would require a
317   dynamic data structure).  Luckily, it is still likely that the
318   assertions find bugs where a thread forgot to take a lock, because
319   most of the time most locks are only used by one thread at a time.
320 
321   The assertions are no-ops when DBUG is off.
322 */
323 class Checkable_rwlock
324 {
325 public:
326   /// Initialize this Checkable_rwlock.
Checkable_rwlock()327   Checkable_rwlock()
328   {
329 #ifndef DBUG_OFF
330     my_atomic_rwlock_init(&atomic_lock);
331     lock_state= 0;
332 #else
333     is_write_lock= false;
334 #endif
335 #ifdef MYSQL_SERVER
336     mysql_rwlock_init(key_rwlock_global_sid_lock, &rwlock);
337 #else
338     mysql_rwlock_init(0, &rwlock);
339 #endif
340   }
341   /// Destroy this Checkable_lock.
~Checkable_rwlock()342   ~Checkable_rwlock()
343   {
344 #ifndef DBUG_OFF
345     my_atomic_rwlock_destroy(&atomic_lock);
346 #endif
347     mysql_rwlock_destroy(&rwlock);
348   }
349 
350   /// Acquire the read lock.
rdlock()351   inline void rdlock()
352   {
353     mysql_rwlock_rdlock(&rwlock);
354     assert_no_wrlock();
355 #ifndef DBUG_OFF
356     my_atomic_rwlock_wrlock(&atomic_lock);
357     my_atomic_add32(&lock_state, 1);
358     my_atomic_rwlock_wrunlock(&atomic_lock);
359 #endif
360   }
361   /// Acquire the write lock.
wrlock()362   inline void wrlock()
363   {
364     mysql_rwlock_wrlock(&rwlock);
365     assert_no_lock();
366 #ifndef DBUG_OFF
367     my_atomic_rwlock_wrlock(&atomic_lock);
368     my_atomic_store32(&lock_state, -1);
369     my_atomic_rwlock_wrunlock(&atomic_lock);
370 #else
371     is_write_lock= true;
372 #endif
373   }
374   /// Release the lock (whether it is a write or read lock).
unlock()375   inline void unlock()
376   {
377     assert_some_lock();
378 #ifndef DBUG_OFF
379     my_atomic_rwlock_wrlock(&atomic_lock);
380     int val= my_atomic_load32(&lock_state);
381     if (val > 0)
382       my_atomic_add32(&lock_state, -1);
383     else if (val == -1)
384       my_atomic_store32(&lock_state, 0);
385     else
386       DBUG_ASSERT(0);
387     my_atomic_rwlock_wrunlock(&atomic_lock);
388 #else
389     is_write_lock= false;
390 #endif
391     mysql_rwlock_unlock(&rwlock);
392   }
393   /**
394     Return true if the write lock is held. Must only be called by
395     threads that hold a lock.
396   */
is_wrlock()397   inline bool is_wrlock()
398   {
399     assert_some_lock();
400 #ifndef DBUG_OFF
401     return get_state() == -1;
402 #else
403     return is_write_lock;
404 #endif
405   }
406 
407   /// Assert that some thread holds either the read or the write lock.
assert_some_lock()408   inline void assert_some_lock() const
409   { DBUG_ASSERT(get_state() != 0); }
410   /// Assert that some thread holds the read lock.
assert_some_rdlock()411   inline void assert_some_rdlock() const
412   { DBUG_ASSERT(get_state() > 0); }
413   /// Assert that some thread holds the write lock.
assert_some_wrlock()414   inline void assert_some_wrlock() const
415   { DBUG_ASSERT(get_state() == -1); }
416   /// Assert that no thread holds the write lock.
assert_no_wrlock()417   inline void assert_no_wrlock() const
418   { DBUG_ASSERT(get_state() >= 0); }
419   /// Assert that no thread holds the read lock.
assert_no_rdlock()420   inline void assert_no_rdlock() const
421   { DBUG_ASSERT(get_state() <= 0); }
422   /// Assert that no thread holds read or write lock.
assert_no_lock()423   inline void assert_no_lock() const
424   { DBUG_ASSERT(get_state() == 0); }
425 
426 private:
427 #ifndef DBUG_OFF
428   /**
429     The state of the lock:
430     0 - not locked
431     -1 - write locked
432     >0 - read locked by that many threads
433   */
434   volatile int32 lock_state;
435   /// Lock to protect my_atomic_* operations on lock_state.
436   mutable my_atomic_rwlock_t atomic_lock;
437   /// Read lock_state atomically and return the value.
get_state()438   inline int32 get_state() const
439   {
440     int32 ret;
441     my_atomic_rwlock_rdlock(&atomic_lock);
442     ret= my_atomic_load32(const_cast<volatile int32*>(&lock_state));
443     my_atomic_rwlock_rdunlock(&atomic_lock);
444     return ret;
445   }
446 #else
447   bool is_write_lock;
448 #endif
449   /// The rwlock.
450   mysql_rwlock_t rwlock;
451 };
452 
453 
454 /// Protects Gtid_state.  See comment above gtid_state for details.
455 extern Checkable_rwlock *global_sid_lock;
456 
457 
458 /**
459   Represents a bidirectional map between SID and SIDNO.
460 
461   SIDNOs are always numbers greater or equal to 1.
462 
463   This data structure OPTIONALLY knows of a read-write lock that
464   protects the number of SIDNOs.  The lock is provided by the invoker
465   of the constructor and it is generally the caller's responsibility
466   to acquire the read lock.  If the lock is not NULL, access methods
467   assert that the caller already holds the read (or write) lock.  If
468   the lock is not NULL and a method of this class grows the number of
469   SIDNOs, then the method temporarily upgrades this lock to a write
470   lock and then degrades it to a read lock again; there will be a
471   short period when the lock is not held at all.
472 */
473 class Sid_map
474 {
475 public:
476   /**
477     Create this Sid_map.
478 
479     @param sid_lock Read-write lock that protects updates to the
480     number of SIDNOs.
481   */
482   Sid_map(Checkable_rwlock *sid_lock);
483   /// Destroy this Sid_map.
484   ~Sid_map();
485 #ifdef NON_DISABLED_GTID
486   /**
487     Clears this Sid_map (for RESET MASTER)
488 
489     @return RETURN_STATUS_OK or RETURN_STAUTS_REPORTED_ERROR
490   */
491   enum_return_status clear();
492 #endif
493   /**
494     Add the given SID to this map if it does not already exist.
495 
496     The caller must hold the read lock or write lock on sid_lock
497     before invoking this function.  If the SID does not exist in this
498     map, it will release the read lock, take a write lock, update the
499     map, release the write lock, and take the read lock again.
500 
501     @param sid The SID.
502     @retval SIDNO The SIDNO for the SID (a new SIDNO if the SID did
503     not exist, an existing if it did exist).
504     @retval negative Error. This function calls my_error.
505   */
506   rpl_sidno add_sid(const rpl_sid &sid);
507   /**
508     Get the SIDNO for a given SID
509 
510     The caller must hold the read lock on sid_lock before invoking
511     this function.
512 
513     @param sid The SID.
514     @retval SIDNO if the given SID exists in this map.
515     @retval 0 if the given SID does not exist in this map.
516   */
sid_to_sidno(const rpl_sid & sid)517   rpl_sidno sid_to_sidno(const rpl_sid &sid) const
518   {
519     if (sid_lock != NULL)
520       sid_lock->assert_some_lock();
521     Node *node= (Node *)my_hash_search(&_sid_to_sidno, sid.bytes,
522                                        rpl_sid::BYTE_LENGTH);
523     if (node == NULL)
524       return 0;
525     return node->sidno;
526   }
527   /**
528     Get the SID for a given SIDNO.
529 
530     An assertion is raised if the caller does not hold a lock on
531     sid_lock, or if the SIDNO is not valid.
532 
533     @param sidno The SIDNO.
534     @retval NULL The SIDNO does not exist in this map.
535     @retval pointer Pointer to the SID.  The data is shared with this
536     Sid_map, so should not be modified.  It is safe to read the data
537     even after this Sid_map is modified, but not if this Sid_map is
538     destroyed.
539   */
sidno_to_sid(rpl_sidno sidno)540   const rpl_sid &sidno_to_sid(rpl_sidno sidno) const
541   {
542     if (sid_lock != NULL)
543       sid_lock->assert_some_lock();
544     DBUG_ASSERT(sidno >= 1 && sidno <= get_max_sidno());
545     return (*dynamic_element(&_sidno_to_sid, sidno - 1, Node **))->sid;
546   }
547   /**
548     Return the n'th smallest sidno, in the order of the SID's UUID.
549 
550     The caller must hold the read or write lock on sid_lock before
551     invoking this function.
552 
553     @param n A number in the interval [0, get_max_sidno()-1], inclusively.
554   */
get_sorted_sidno(rpl_sidno n)555   rpl_sidno get_sorted_sidno(rpl_sidno n) const
556   {
557     if (sid_lock != NULL)
558       sid_lock->assert_some_lock();
559     rpl_sidno ret= *dynamic_element(&_sorted, n, rpl_sidno *);
560     return ret;
561   }
562   /**
563     Return the biggest sidno in this Sid_map.
564 
565     The caller must hold the read or write lock on sid_lock before
566     invoking this function.
567   */
get_max_sidno()568   rpl_sidno get_max_sidno() const
569   {
570     if (sid_lock != NULL)
571       sid_lock->assert_some_lock();
572     return _sidno_to_sid.elements;
573   }
574 
575 private:
576   /// Node pointed to by both the hash and the array.
577   struct Node
578   {
579     rpl_sidno sidno;
580     rpl_sid sid;
581   };
582 
583   /**
584     Create a Node from the given SIDNO and SID and add it to
585     _sidno_to_sid, _sid_to_sidno, and _sorted.
586 
587     The caller must hold the write lock on sid_lock before invoking
588     this function.
589 
590     @param sidno The SIDNO to add.
591     @param sid The SID to add.
592     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
593   */
594   enum_return_status add_node(rpl_sidno sidno, const rpl_sid &sid);
595 
596   /// Read-write lock that protects updates to the number of SIDNOs.
597   mutable Checkable_rwlock *sid_lock;
598 
599   /**
600     Array that maps SIDNO to SID; the element at index N points to a
601     Node with SIDNO N-1.
602   */
603   DYNAMIC_ARRAY _sidno_to_sid;
604   /**
605     Hash that maps SID to SIDNO.  The keys in this array are of type
606     rpl_sid.
607   */
608   HASH _sid_to_sidno;
609   /**
610     Array that maps numbers in the interval [0, get_max_sidno()-1] to
611     SIDNOs, in order of increasing SID.
612 
613     @see Sid_map::get_sorted_sidno.
614   */
615   DYNAMIC_ARRAY _sorted;
616 };
617 
618 
619 extern Sid_map *global_sid_map;
620 
621 
622 /**
623   Represents a growable array where each element contains a mutex and
624   a condition variable.
625 
626   Each element can be locked, unlocked, broadcast, or waited for, and
627   it is possible to call "THD::enter_cond" for the condition.  The
628   allowed indexes range from 0, inclusive, to get_max_index(),
629   inclusive.  Initially there are zero elements (and get_max_index()
630   returns -1); more elements can be allocated by calling
631   ensure_index().
632 
633   This data structure has a read-write lock that protects the number
634   of elements.  The lock is provided by the invoker of the constructor
635   and it is generally the caller's responsibility to acquire the read
636   lock.  Access methods assert that the caller already holds the read
637   (or write) lock.  If a method of this class grows the number of
638   elements, then the method temporarily upgrades this lock to a write
639   lock and then degrades it to a read lock again; there will be a
640   short period when the lock is not held at all.
641 */
642 class Mutex_cond_array
643 {
644 public:
645   /**
646     Create a new Mutex_cond_array.
647 
648     @param global_lock Read-write lock that protects updates to the
649     number of elements.
650   */
651   Mutex_cond_array(Checkable_rwlock *global_lock);
652   /// Destroy this object.
653   ~Mutex_cond_array();
654   /// Lock the n'th mutex.
lock(int n)655   inline void lock(int n) const
656   {
657     assert_not_owner(n);
658     mysql_mutex_lock(&get_mutex_cond(n)->mutex);
659   }
660   /// Unlock the n'th mutex.
unlock(int n)661   inline void unlock(int n) const
662   {
663     assert_owner(n);
664     mysql_mutex_unlock(&get_mutex_cond(n)->mutex);
665   }
666   /// Broadcast the n'th condition.
broadcast(int n)667   inline void broadcast(int n) const
668   {
669     mysql_cond_broadcast(&get_mutex_cond(n)->cond);
670   }
671   /**
672     Assert that this thread owns the n'th mutex.
673     This is a no-op if DBUG_OFF is on.
674   */
assert_owner(int n)675   inline void assert_owner(int n) const
676   {
677 #ifndef DBUG_OFF
678     mysql_mutex_assert_owner(&get_mutex_cond(n)->mutex);
679 #endif
680   }
681   /**
682     Assert that this thread does not own the n'th mutex.
683     This is a no-op if DBUG_OFF is on.
684   */
assert_not_owner(int n)685   inline void assert_not_owner(int n) const
686   {
687 #ifndef DBUG_OFF
688     mysql_mutex_assert_not_owner(&get_mutex_cond(n)->mutex);
689 #endif
690   }
691   /**
692     Wait for signal on the n'th condition variable.
693 
694     The caller must hold the read lock or write lock on sid_lock, as
695     well as the nth mutex lock, before invoking this function.  The
696     sid_lock will be released, whereas the mutex will be released
697     during the wait and (atomically) re-acquired when the wait ends.
698   */
wait(int n)699   inline void wait(int n) const
700   {
701     DBUG_ENTER("Mutex_cond_array::wait");
702     Mutex_cond *mutex_cond= get_mutex_cond(n);
703     global_lock->unlock();
704     mysql_mutex_assert_owner(&mutex_cond->mutex);
705     mysql_cond_wait(&mutex_cond->cond, &mutex_cond->mutex);
706     mysql_mutex_assert_owner(&mutex_cond->mutex);
707     DBUG_VOID_RETURN;
708   }
709 #ifndef MYSQL_CLIENT
710   /// Execute THD::enter_cond for the n'th condition variable.
711   void enter_cond(THD *thd, int n, PSI_stage_info *stage,
712                   PSI_stage_info *old_stage) const;
713 #endif // ifndef MYSQL_CLIENT
714   /// Return the greatest addressable index in this Mutex_cond_array.
get_max_index()715   inline int get_max_index() const
716   {
717     global_lock->assert_some_lock();
718     return array.elements - 1;
719   }
720   /**
721     Grows the array so that the given index fits.
722 
723     If the array is grown, the global_lock is temporarily upgraded to
724     a write lock and then degraded again; there will be a
725     short period when the lock is not held at all.
726 
727     @param n The index.
728     @return RETURN_OK or RETURN_REPORTED_ERROR
729   */
730   enum_return_status ensure_index(int n);
731 private:
732   /// A mutex/cond pair.
733   struct Mutex_cond
734   {
735     mysql_mutex_t mutex;
736     mysql_cond_t cond;
737   };
738   /// Return the Nth Mutex_cond object
get_mutex_cond(int n)739   inline Mutex_cond *get_mutex_cond(int n) const
740   {
741     global_lock->assert_some_lock();
742     DBUG_ASSERT(n <= get_max_index());
743     Mutex_cond *ret= *dynamic_element(&array, n, Mutex_cond **);
744     DBUG_ASSERT(ret);
745     return ret;
746   }
747   /// Read-write lock that protects updates to the number of elements.
748   mutable Checkable_rwlock *global_lock;
749   DYNAMIC_ARRAY array;
750 };
751 
752 
753 /**
754   Holds information about a GTID: the sidno and the gno.
755 
756   This is a POD. It has to be a POD because it is part of
757   Gtid_specification, which has to be a POD because it is used in
758   THD::variables.
759 */
760 struct Gtid
761 {
762   /// SIDNO of this Gtid.
763   rpl_sidno sidno;
764   /// GNO of this Gtid.
765   rpl_gno gno;
766 
767   /// Set both components to 0.
clearGtid768   void clear() { sidno= 0; gno= 0; }
769   // Set both components to input values.
setGtid770   void set(rpl_sidno sno, rpl_gno gtidno) { sidno= sno; gno= gtidno; }
771   // check if both components are zero or not.
emptyGtid772   bool empty() const { return (sidno == 0) && (gno == 0); }
773   /**
774     The maximal length of the textual representation of a SID, not
775     including the terminating '\0'.
776   */
777   static const int MAX_TEXT_LENGTH= Uuid::TEXT_LENGTH + 1 + MAX_GNO_TEXT_LENGTH;
778   /**
779     Return true if parse() would succeed, but don't store the
780     result anywhere.
781   */
782   static bool is_valid(const char *text);
783   /**
784     Convert a Gtid to a string.
785     @param sid the sid to use. This overrides the sidno of this Gtid.
786     @param[out] buf Buffer to store the Gtid in (normally
787     MAX_TEXT_LENGTH+1 bytes long).
788     @return Length of the string, not counting '\0'.
789   */
790   int to_string(const rpl_sid &sid, char *buf) const;
791   /**
792     Convert this Gtid to a string.
793     @param sid_map sid_map to use when converting sidno to a SID.
794     @param[out] buf Buffer to store the Gtid in (normally
795     MAX_TEXT_LENGTH+1 bytes long).
796     @return Length of the string, not counting '\0'.
797   */
798   int to_string(const Sid_map *sid_map, char *buf) const;
799   /// Returns true if this Gtid has the same sid and gno as 'other'.
equalsGtid800   bool equals(const Gtid &other) const
801   { return sidno == other.sidno && gno == other.gno; }
802   /**
803     Parses the given string and stores in this Gtid.
804 
805     @param text The text to parse
806     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
807   */
808   enum_return_status parse(Sid_map *sid_map, const char *text);
809 
810 #ifndef DBUG_OFF
811   /// Debug only: print this Gtid to stdout.
printGtid812   void print(const Sid_map *sid_map) const
813   {
814     char buf[MAX_TEXT_LENGTH + 1];
815     to_string(sid_map, buf);
816     printf("%s\n", buf);
817   }
818 #endif
819   /// Print this Gtid to the trace file if debug is enabled; no-op otherwise.
820   void dbug_print(const Sid_map *sid_map, const char *text= "") const
821   {
822 #ifndef DBUG_OFF
823     char buf[MAX_TEXT_LENGTH + 1];
824     to_string(sid_map, buf);
825     DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", buf));
826 #endif
827   }
828 };
829 
830 
831 /**
832   Represents a set of GTIDs.
833 
834   This is structured as an array, indexed by SIDNO, where each element
835   contains a linked list of intervals.
836 
837   This data structure OPTIONALLY knows of a Sid_map that gives a
838   correspondence between SIDNO and SID.  If the Sid_map is NULL, then
839   operations that require a Sid_map - printing and parsing - raise an
840   assertion.
841 
842   This data structure OPTIONALLY knows of a read-write lock that
843   protects the number of SIDNOs.  The lock is provided by the invoker
844   of the constructor and it is generally the caller's responsibility
845   to acquire the read lock.  If the lock is not NULL, access methods
846   assert that the caller already holds the read (or write) lock.  If
847   the lock is not NULL and a method of this class grows the number of
848   SIDNOs, then the method temporarily upgrades this lock to a write
849   lock and then degrades it to a read lock again; there will be a
850   short period when the lock is not held at all.
851 */
852 class Gtid_set
853 {
854 public:
855   /**
856     Constructs a new, empty Gtid_set.
857 
858     @param sid_map The Sid_map to use, or NULL if this Gtid_set
859     should not have a Sid_map.
860     @param sid_lock Read-write lock that protects updates to the
861     number of SIDs. This may be NULL if such changes do not need to be
862     protected.
863   */
864   Gtid_set(Sid_map *sid_map, Checkable_rwlock *sid_lock= NULL);
865   /**
866     Constructs a new Gtid_set that contains the groups in the given string, in the same format as add_gtid_text(char *).
867 
868     @param sid_map The Sid_map to use for SIDs.
869     @param text The text to parse.
870     @param status Will be set GS_SUCCESS or GS_ERROR_PARSE or
871     GS_ERROR_OUT_OF_MEMORY.
872     @param sid_lock Read/write lock to protect changes in the number
873     of SIDs with. This may be NULL if such changes do not need to be
874     protected.
875 
876     If sid_lock != NULL, then the read lock on sid_lock must be held
877     before calling this function. If the array is grown, sid_lock is
878     temporarily upgraded to a write lock and then degraded again;
879     there will be a short period when the lock is not held at all.
880   */
881   Gtid_set(Sid_map *sid_map, const char *text, enum_return_status *status,
882            Checkable_rwlock *sid_lock= NULL);
883 private:
884   /// Worker for the constructor.
885   void init();
886 public:
887   /// Destroy this Gtid_set.
888   ~Gtid_set();
889   /**
890     Removes all groups from this Gtid_set.
891 
892     This does not deallocate anything: if groups are added later,
893     existing allocated memory will be re-used.
894   */
895   void clear();
896   /**
897     Adds the given GTID to this Gtid_set.
898 
899     The SIDNO must exist in the Gtid_set before this function is called.
900 
901     @param sidno SIDNO of the group to add.
902     @param gno GNO of the group to add.
903     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
904   */
_add_gtid(rpl_sidno sidno,rpl_gno gno)905   enum_return_status _add_gtid(rpl_sidno sidno, rpl_gno gno)
906   {
907     DBUG_ENTER("Gtid_set::_add_gtid(sidno, gno)");
908     Interval_iterator ivit(this, sidno);
909     Free_intervals_lock lock(this);
910     enum_return_status ret= add_gno_interval(&ivit, gno, gno + 1, &lock);
911     DBUG_RETURN(ret);
912   }
913   /**
914     Removes the given GTID from this Gtid_set.
915 
916     @param sidno SIDNO of the group to remove.
917     @param gno GNO of the group to remove.
918     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
919   */
_remove_gtid(rpl_sidno sidno,rpl_gno gno)920   enum_return_status _remove_gtid(rpl_sidno sidno, rpl_gno gno)
921   {
922     DBUG_ENTER("Gtid_set::_remove_gtid(rpl_sidno, rpl_gno)");
923     if (sidno <= get_max_sidno())
924     {
925       Interval_iterator ivit(this, sidno);
926       Free_intervals_lock lock(this);
927       enum_return_status ret= remove_gno_interval(&ivit, gno, gno + 1, &lock);
928       DBUG_RETURN(ret);
929     }
930     RETURN_OK;
931   }
932   /**
933     Adds the given GTID to this Gtid_set.
934 
935     The SIDNO must exist in the Gtid_set before this function is called.
936 
937     @param gtid Gtid to add.
938     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
939   */
_add_gtid(const Gtid & gtid)940   enum_return_status _add_gtid(const Gtid &gtid)
941   { return _add_gtid(gtid.sidno, gtid.gno); }
942   /**
943     Removes the given GTID from this Gtid_set.
944 
945     @param gtid Gtid to remove.
946     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
947    */
_remove_gtid(const Gtid & gtid)948   enum_return_status _remove_gtid(const Gtid &gtid)
949   {
950     return _remove_gtid(gtid.sidno, gtid.gno);
951   }
952   /**
953     Adds all groups from the given Gtid_set to this Gtid_set.
954 
955     If sid_lock != NULL, then the read lock must be held before
956     calling this function. If a new sidno is added so that the array
957     of lists of intervals is grown, sid_lock is temporarily upgraded
958     to a write lock and then degraded again; there will be a short
959     period when the lock is not held at all.
960 
961     @param other The Gtid_set to add.
962     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
963   */
964   enum_return_status add_gtid_set(const Gtid_set *other);
965   /**
966     Removes all groups in the given Gtid_set from this Gtid_set.
967 
968     @param other The Gtid_set to remove.
969     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
970   */
971   enum_return_status remove_gtid_set(const Gtid_set *other);
972   /**
973     Adds the set of GTIDs represented by the given string to this Gtid_set.
974 
975     The string must have the format of a comma-separated list of zero
976     or more of the following:
977 
978        XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX(:NUMBER+(-NUMBER)?)*
979        | ANONYMOUS
980 
981        Each X is a hexadecimal digit (upper- or lowercase).
982        NUMBER is a decimal, 0xhex, or 0oct number.
983 
984        The start of an interval must be greater than 0. The end of an
985        interval may be 0, but any interval that has an endpoint that
986        is smaller than the start is discarded.
987 
988     If sid_lock != NULL, then the read lock on sid_lock must be held
989     before calling this function. If a new sidno is added so that the
990     array of lists of intervals is grown, sid_lock is temporarily
991     upgraded to a write lock and then degraded again; there will be a
992     short period when the lock is not held at all.
993 
994     @param text The string to parse.
995     @param anonymous[in,out] If this is NULL, ANONYMOUS is not
996     allowed.  If this is not NULL, it will be set to true if the
997     anonymous group was found; false otherwise.
998     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
999   */
1000   enum_return_status add_gtid_text(const char *text, bool *anonymous= NULL);
1001   /**
1002     Decodes a Gtid_set from the given string.
1003 
1004     @param string The string to parse.
1005     @param length The number of bytes.
1006     @param actual_length If this is not NULL, it is set to the number
1007     of bytes used by the encoding (which may be less than 'length').
1008     If this is NULL, an error is generated if the encoding is shorter
1009     than the given 'length'.
1010     @return GS_SUCCESS or GS_ERROR_PARSE or GS_ERROR_OUT_OF_MEMORY
1011   */
1012   enum_return_status add_gtid_encoding(const uchar *encoded, size_t length,
1013                                        size_t *actual_length= NULL);
1014   /// Return true iff the given GTID exists in this set.
1015   bool contains_gtid(rpl_sidno sidno, rpl_gno gno) const;
1016   /// Return true iff the given GTID exists in this set.
contains_gtid(const Gtid & gtid)1017   bool contains_gtid(const Gtid &gtid) const
1018   { return contains_gtid(gtid.sidno, gtid.gno); }
1019   /// Returns the maximal sidno that this Gtid_set currently has space for.
get_max_sidno()1020   rpl_sidno get_max_sidno() const
1021   {
1022     if (sid_lock)
1023       sid_lock->assert_some_lock();
1024     return intervals.elements;
1025   }
1026   /**
1027     Allocates space for all sidnos up to the given sidno in the array of intervals.
1028     The sidno must exist in the Sid_map associated with this Gtid_set.
1029 
1030     If sid_lock != NULL, then the read lock on sid_lock must be held
1031     before calling this function. If the array is grown, sid_lock is
1032     temporarily upgraded to a write lock and then degraded again;
1033     there will be a short period when the lock is not held at all.
1034 
1035     @param sidno The SIDNO.
1036     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1037   */
1038   enum_return_status ensure_sidno(rpl_sidno sidno);
1039   /// Returns true if this Gtid_set is a subset of the other Gtid_set.
1040   bool is_subset(const Gtid_set *super) const;
1041 
1042   /**
1043     Returns true if this Gtid_set is a subset of the given gtid_set
1044     on the given superset_sidno and subset_sidno.
1045 
1046     @param super          Gtid_set with which 'this'::gtid_set needs to be
1047                            compared
1048     @param superset_sidno The sidno that will be compared, relative to
1049                            super->sid_map.
1050     @param subset_sidno   The sidno that will be compared, relative to
1051                            this->sid_map.
1052     @return true          If 'this' Gtid_set is subset of given
1053                            'super' Gtid_set.
1054             false         If 'this' Gtid_set is *not* subset of given
1055                            'super' Gtid_set.
1056   */
1057   bool is_subset_for_sid(const Gtid_set *super, rpl_sidno superset_sidno,
1058                          rpl_sidno subset_sidno) const;
1059   /// Returns true if there is a least one element of this Gtid_set in
1060   /// the other Gtid_set.
1061   bool is_intersection_nonempty(const Gtid_set *other) const;
1062   /**
1063     Add the intersection of this Gtid_set and the other Gtid_set to result.
1064 
1065     @param other The Gtid_set to intersect with this Gtid_set
1066     @param result Gtid_set where the result will be stored.
1067     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1068   */
1069   enum_return_status intersection(const Gtid_set *other, Gtid_set *result);
1070   /// Returns true if this Gtid_set is empty.
is_empty()1071   bool is_empty() const
1072   {
1073     Gtid_iterator git(this);
1074     return git.get().sidno == 0;
1075   }
1076   /**
1077     Returns true if this Gtid_set contains at least one GTID with
1078     the given SIDNO.
1079 
1080     @param sidno The SIDNO to test.
1081     @retval true The SIDNO is less than or equal to the max SIDNO, and
1082     there is at least one group with this SIDNO.
1083     @retval false The SIDNO is greater than the max SIDNO, or there is
1084     no group with this SIDNO.
1085   */
contains_sidno(rpl_sidno sidno)1086   bool contains_sidno(rpl_sidno sidno) const
1087   {
1088     DBUG_ASSERT(sidno >= 1);
1089     if (sidno > get_max_sidno())
1090       return false;
1091     Const_interval_iterator ivit(this, sidno);
1092     return ivit.get() != NULL;
1093   }
1094   /**
1095     Returns true if the given string is a valid specification of a
1096     Gtid_set, false otherwise.
1097   */
1098   static bool is_valid(const char *text);
1099   /**
1100     Return a newly allocated string containing this Gtid_set, or NULL
1101     on out of memory.
1102   */
to_string()1103   char *to_string() const
1104   {
1105     char *str= (char *)my_malloc(get_string_length() + 1, MYF(MY_WME));
1106     if (str != NULL)
1107       to_string(str);
1108     return str;
1109   }
1110 #ifndef DBUG_OFF
1111   /// Debug only: Print this Gtid_set to stdout.
print()1112   void print() const
1113   {
1114     char *str= to_string();
1115     printf("%s\n", str);
1116     my_free(str);
1117   }
1118 #endif
1119   /**
1120     Print this Gtid_set to the trace file if debug is enabled; no-op
1121     otherwise.
1122   */
1123   void dbug_print(const char *text= "") const
1124   {
1125 #ifndef DBUG_OFF
1126     char *str= to_string();
1127     DBUG_PRINT("info", ("%s%s'%s'", text, *text ? ": " : "", str));
1128     my_free(str);
1129 #endif
1130   }
1131 
1132   /**
1133     Class Gtid_set::String_format defines the separators used by
1134     Gtid_set::to_string.
1135   */
1136   struct String_format
1137   {
1138     /// The generated string begins with this.
1139     const char *begin;
1140     /// The generated string begins with this.
1141     const char *end;
1142     /// In 'SID:GNO', this is the ':'
1143     const char *sid_gno_separator;
1144     /// In 'SID:GNO-GNO', this is the '-'
1145     const char *gno_start_end_separator;
1146     /// In 'SID:GNO:GNO', this is the second ':'
1147     const char *gno_gno_separator;
1148     /// In 'SID:GNO,SID:GNO', this is the ','
1149     const char *gno_sid_separator;
1150     /// If the set is empty and this is not NULL, then this string is generated.
1151     const char *empty_set_string;
1152     /// The following fields are the lengths of each field above.
1153     const int begin_length;
1154     const int end_length;
1155     const int sid_gno_separator_length;
1156     const int gno_start_end_separator_length;
1157     const int gno_gno_separator_length;
1158     const int gno_sid_separator_length;
1159     const int empty_set_string_length;
1160   };
1161   /**
1162     Returns the length of the output from to_string.
1163 
1164     @warning This does not include the trailing '\0', so your buffer
1165     needs space for get_string_length() + 1 characters.
1166 
1167     @param string_format String_format object that specifies
1168     separators in the resulting text.
1169     @return The length.
1170   */
1171   int get_string_length(const String_format *string_format= NULL) const;
1172   /**
1173     Formats this Gtid_set as a string and saves in a given buffer.
1174 
1175     @param[out] buf Pointer to the buffer where the string should be
1176     stored. This should have size at least get_string_length()+1.
1177     @param string_format String_format object that specifies
1178     separators in the resulting text.
1179     @return Length of the generated string.
1180   */
1181   int to_string(char *buf, const String_format *string_format= NULL) const;
1182 
1183   /**
1184     Formats a Gtid_set as a string and saves in a newly allocated buffer.
1185     @param[out] buf Pointer to pointer to string. The function will
1186     set it to point to the newly allocated buffer, or NULL on out of memory.
1187     @param string_format Specifies how to format the string.
1188     @retval Length of the generated string, or -1 on out of memory.
1189   */
1190   int to_string(char **buf, const String_format *string_format= NULL) const;
1191 
1192   /**
1193     The default String_format: the format understood by
1194     add_gtid_text(const char *).
1195   */
1196   static const String_format default_string_format;
1197   /**
1198     String_format useful to generate an SQL string: the string is
1199     wrapped in single quotes and there is a newline between SIDs.
1200   */
1201   static const String_format sql_string_format;
1202   /**
1203     String_format for printing the Gtid_set commented: the string is
1204     not quote-wrapped, and every SID is on a new line with a leading '# '.
1205   */
1206   static const String_format commented_string_format;
1207 
1208   /// Return the Sid_map associated with this Gtid_set.
get_sid_map()1209   Sid_map *get_sid_map() const { return sid_map; }
1210 
1211   /**
1212     Represents one element in the linked list of intervals associated
1213     with a SIDNO.
1214   */
1215   struct Interval
1216   {
1217   public:
1218     /// The first GNO of this interval.
1219     rpl_gno start;
1220     /// The first GNO after this interval.
1221     rpl_gno end;
1222     /// Return true iff this interval is equal to the given interval.
equalsInterval1223     bool equals(const Interval &other) const
1224     {
1225       return start == other.start && end == other.end;
1226     }
1227     /// Pointer to next interval in list.
1228     Interval *next;
1229   };
1230 
1231   /**
1232     Provides an array of Intervals that this Gtid_set can use when
1233     groups are subsequently added.  This can be used as an
1234     optimization, to reduce allocation for sets that have a known
1235     number of intervals.
1236 
1237     @param n_intervals The number of intervals to add.
1238     @param intervals Array of n_intervals intervals.
1239   */
add_interval_memory(int n_intervals,Interval * intervals_param)1240   void add_interval_memory(int n_intervals, Interval *intervals_param)
1241   {
1242     if (sid_lock != NULL)
1243       mysql_mutex_lock(&free_intervals_mutex);
1244     add_interval_memory_lock_taken(n_intervals, intervals_param);
1245     if (sid_lock != NULL)
1246       mysql_mutex_unlock(&free_intervals_mutex);
1247   }
1248 
1249 
1250   /**
1251     Iterator over intervals for a given SIDNO.
1252 
1253     This is an abstract template class, used as a common base class
1254     for Const_interval_iterator and Interval_iterator.
1255 
1256     The iterator always points to an interval pointer.  The interval
1257     pointer is either the initial pointer into the list, or the next
1258     pointer of one of the intervals in the list.
1259   */
1260   template<typename Gtid_set_p, typename Interval_p> class Interval_iterator_base
1261   {
1262   public:
1263     /**
1264       Construct a new iterator over the GNO intervals for a given Gtid_set.
1265 
1266       @param gtid_set The Gtid_set.
1267       @param sidno The SIDNO.
1268     */
Interval_iterator_base(Gtid_set_p gtid_set,rpl_sidno sidno)1269     Interval_iterator_base(Gtid_set_p gtid_set, rpl_sidno sidno)
1270     {
1271       DBUG_ASSERT(sidno >= 1 && sidno <= gtid_set->get_max_sidno());
1272       init(gtid_set, sidno);
1273     }
1274     /// Construct a new iterator over the free intervals of a Gtid_set.
Interval_iterator_base(Gtid_set_p gtid_set)1275     Interval_iterator_base(Gtid_set_p gtid_set)
1276     { p= const_cast<Interval_p *>(&gtid_set->free_intervals); }
1277     /// Reset this iterator.
init(Gtid_set_p gtid_set,rpl_sidno sidno)1278     inline void init(Gtid_set_p gtid_set, rpl_sidno sidno)
1279     { p= dynamic_element(&gtid_set->intervals, sidno - 1, Interval_p *); }
1280     /// Advance current_elem one step.
next()1281     inline void next()
1282     {
1283       DBUG_ASSERT(*p != NULL);
1284       p= const_cast<Interval_p *>(&(*p)->next);
1285     }
1286     /// Return current_elem.
get()1287     inline Interval_p get() const { return *p; }
1288   protected:
1289     /**
1290       Holds the address of the 'next' pointer of the previous element,
1291       or the address of the initial pointer into the list, if the
1292       current element is the first element.
1293     */
1294     Interval_p *p;
1295   };
1296 
1297   /**
1298     Iterator over intervals of a const Gtid_set.
1299   */
1300   class Const_interval_iterator
1301     : public Interval_iterator_base<const Gtid_set *, const Interval *>
1302   {
1303   public:
1304     /// Create this Const_interval_iterator.
Const_interval_iterator(const Gtid_set * gtid_set,rpl_sidno sidno)1305     Const_interval_iterator(const Gtid_set *gtid_set, rpl_sidno sidno)
1306       : Interval_iterator_base<const Gtid_set *, const Interval *>(gtid_set, sidno) {}
1307     /// Create this Const_interval_iterator.
Const_interval_iterator(const Gtid_set * gtid_set)1308     Const_interval_iterator(const Gtid_set *gtid_set)
1309       : Interval_iterator_base<const Gtid_set *, const Interval *>(gtid_set) {}
1310   };
1311 
1312   /**
1313     Iterator over intervals of a non-const Gtid_set, with additional
1314     methods to modify the Gtid_set.
1315   */
1316   class Interval_iterator
1317     : public Interval_iterator_base<Gtid_set *, Interval *>
1318   {
1319   public:
1320     /// Create this Interval_iterator.
Interval_iterator(Gtid_set * gtid_set,rpl_sidno sidno)1321     Interval_iterator(Gtid_set *gtid_set, rpl_sidno sidno)
1322       : Interval_iterator_base<Gtid_set *, Interval *>(gtid_set, sidno) {}
1323     /// Destroy this Interval_iterator.
Interval_iterator(Gtid_set * gtid_set)1324     Interval_iterator(Gtid_set *gtid_set)
1325       : Interval_iterator_base<Gtid_set *, Interval *>(gtid_set) {}
1326   private:
1327     /**
1328       Set current_elem to the given Interval but do not touch the
1329       next pointer of the given Interval.
1330     */
set(Interval * iv)1331     inline void set(Interval *iv) { *p= iv; }
1332     /// Insert the given element before current_elem.
insert(Interval * iv)1333     inline void insert(Interval *iv) { iv->next= *p; set(iv); }
1334     /// Remove current_elem.
remove(Gtid_set * gtid_set)1335     inline void remove(Gtid_set *gtid_set)
1336     {
1337       DBUG_ASSERT(get() != NULL);
1338       Interval *next= (*p)->next;
1339       gtid_set->put_free_interval(*p);
1340       set(next);
1341     }
1342     /**
1343       Only Gtid_set is allowed to use set/insert/remove.
1344 
1345       They are not safe to use from other code because: (1) very easy
1346       to make a mistakes (2) they don't clear cached_string_format or
1347       cached_string_length.
1348     */
1349     friend class Gtid_set;
1350   };
1351 
1352 
1353   /**
1354     Iterator over all groups in a Gtid_set.  This is a const
1355     iterator; it does not allow modification of the Gtid_set.
1356   */
1357   class Gtid_iterator
1358   {
1359   public:
Gtid_iterator(const Gtid_set * gs)1360     Gtid_iterator(const Gtid_set *gs)
1361       : gtid_set(gs), sidno(0), ivit(gs)
1362     {
1363       if (gs->sid_lock != NULL)
1364         gs->sid_lock->assert_some_wrlock();
1365       next_sidno();
1366     }
1367     /// Advance to next group.
next()1368     inline void next()
1369     {
1370       DBUG_ASSERT(gno > 0 && sidno > 0);
1371       // go to next group in current interval
1372       gno++;
1373       // end of interval? then go to next interval for this sidno
1374       if (gno == ivit.get()->end)
1375       {
1376         ivit.next();
1377         const Interval *iv= ivit.get();
1378         // last interval for this sidno? then go to next sidno
1379         if (iv == NULL)
1380         {
1381           next_sidno();
1382           // last sidno? then don't try more
1383           if (sidno == 0)
1384             return;
1385           iv= ivit.get();
1386         }
1387         gno= iv->start;
1388       }
1389     }
1390     /// Return next group, or {0,0} if we reached the end.
get()1391     inline Gtid get() const
1392     {
1393       Gtid ret= { sidno, gno };
1394       return ret;
1395     }
1396   private:
1397     /// Find the next sidno that has one or more intervals.
next_sidno()1398     inline void next_sidno()
1399     {
1400       const Interval *iv;
1401       do
1402       {
1403         sidno++;
1404         if (sidno > gtid_set->get_max_sidno())
1405         {
1406           sidno= 0;
1407           gno= 0;
1408           return;
1409         }
1410         ivit.init(gtid_set, sidno);
1411         iv= ivit.get();
1412       } while (iv == NULL);
1413       gno= iv->start;
1414     }
1415     /// The Gtid_set we iterate over.
1416     const Gtid_set *gtid_set;
1417     /**
1418       The SIDNO of the current element, or 0 if the iterator is past
1419       the last element.
1420     */
1421     rpl_sidno sidno;
1422     /**
1423       The GNO of the current element, or 0 if the iterator is past the
1424       last element.
1425     */
1426     rpl_gno gno;
1427     /// Iterator over the intervals for the current SIDNO.
1428     Const_interval_iterator ivit;
1429   };
1430 
1431 public:
1432 
1433   /**
1434     Encodes this Gtid_set as a binary string.
1435   */
1436   void encode(uchar *buf) const;
1437   /**
1438     Returns the length of this Gtid_set when encoded using the
1439     encode() function.
1440   */
1441   size_t get_encoded_length() const;
1442 
1443 private:
1444   /**
1445     Contains a list of intervals allocated by this Gtid_set.  When a
1446     method of this class needs a new interval and there are no more
1447     free intervals, a new Interval_chunk is allocated and the
1448     intervals of it are added to the list of free intervals.
1449   */
1450   struct Interval_chunk
1451   {
1452     Interval_chunk *next;
1453     Interval intervals[1];
1454   };
1455   /// The default number of intervals in an Interval_chunk.
1456   static const int CHUNK_GROW_SIZE= 8;
1457 
1458 /*
1459   Functions sidno_equals() and equals() are only used by unitests
1460 */
1461 #ifdef NON_DISABLED_UNITTEST_GTID
1462   /**
1463     Return true if the given sidno of this Gtid_set contains the same
1464     intervals as the given sidno of the other Gtid_set.
1465 
1466     @param sidno SIDNO to check for this Gtid_set.
1467     @param other Other Gtid_set
1468     @param other_sidno SIDNO to check in other.
1469     @return true if equal, false is not equal.
1470   */
1471   bool sidno_equals(rpl_sidno sidno,
1472                     const Gtid_set *other, rpl_sidno other_sidno) const;
1473   /// Returns true if this Gtid_set is equal to the other Gtid_set.
1474   bool equals(const Gtid_set *other) const;
1475 #endif
1476 
1477   /// Return the number of intervals for the given sidno.
get_n_intervals(rpl_sidno sidno)1478   int get_n_intervals(rpl_sidno sidno) const
1479   {
1480     Const_interval_iterator ivit(this, sidno);
1481     int ret= 0;
1482     while (ivit.get() != NULL)
1483     {
1484       ret++;
1485       ivit.next();
1486     }
1487     return ret;
1488   }
1489   /// Return the number of intervals in this Gtid_set.
get_n_intervals()1490   int get_n_intervals() const
1491   {
1492     if (sid_lock != NULL)
1493       sid_lock->assert_some_wrlock();
1494     rpl_sidno max_sidno= get_max_sidno();
1495     int ret= 0;
1496     for (rpl_sidno sidno= 1; sidno < max_sidno; sidno++)
1497       ret+= get_n_intervals(sidno);
1498     return ret;
1499   }
1500   /**
1501     Allocates a new chunk of Intervals and adds them to the list of
1502     unused intervals.
1503 
1504     @param size The number of intervals in this chunk
1505     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1506   */
1507   enum_return_status create_new_chunk(int size);
1508   /**
1509     Returns a fresh new Interval object.
1510 
1511     This usually does not require any real allocation, it only pops
1512     the first interval from the list of free intervals.  If there are
1513     no free intervals, it calls create_new_chunk.
1514 
1515     @param out The resulting Interval* will be stored here.
1516     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1517   */
1518   enum_return_status get_free_interval(Interval **out);
1519   /**
1520     Puts the given interval in the list of free intervals.  Does not
1521     unlink it from its place in any other list.
1522   */
1523   void put_free_interval(Interval *iv);
1524   /**
1525     Like add_interval_memory, but does not acquire
1526     free_intervals_mutex.
1527     @see Gtid_set::add_interval_memory
1528   */
1529   void add_interval_memory_lock_taken(int n_ivs, Interval *ivs);
1530 
1531   /// Read-write lock that protects updates to the number of SIDs.
1532   mutable Checkable_rwlock *sid_lock;
1533   /**
1534     Lock protecting the list of free intervals.  This lock is only
1535     used if sid_lock is not NULL.
1536   */
1537   mysql_mutex_t free_intervals_mutex;
1538   /**
1539     Class representing a lock on free_intervals_mutex.
1540 
1541     This is used by the add_* and remove_* functions.  The lock is
1542     declared by the top-level function and a pointer to the lock is
1543     passed down to low-level functions. If the low-level function
1544     decides to access the free intervals list, then it acquires the
1545     lock.  The lock is then automatically released by the destructor
1546     when the top-level function returns.
1547 
1548     The lock is not taken if Gtid_set->sid_lock == NULL; such
1549     Gtid_sets are assumed to be thread-local.
1550   */
1551   class Free_intervals_lock
1552   {
1553   public:
1554     /// Create a new lock, but do not acquire it.
Free_intervals_lock(Gtid_set * _gtid_set)1555     Free_intervals_lock(Gtid_set *_gtid_set)
1556       : gtid_set(_gtid_set), locked(false) {}
1557     /// Lock the lock if it is not already locked.
lock_if_not_locked()1558     void lock_if_not_locked()
1559     {
1560       if (gtid_set->sid_lock && !locked)
1561       {
1562         mysql_mutex_lock(&gtid_set->free_intervals_mutex);
1563         locked= true;
1564       }
1565     }
1566     /// Lock the lock if it is locked.
unlock_if_locked()1567     void unlock_if_locked()
1568     {
1569       if (gtid_set->sid_lock && locked)
1570       {
1571         mysql_mutex_unlock(&gtid_set->free_intervals_mutex);
1572         locked= false;
1573       }
1574     }
1575     /// Destroy this object and unlock the lock if it is locked.
~Free_intervals_lock()1576     ~Free_intervals_lock()
1577     {
1578       unlock_if_locked();
1579     }
1580   private:
1581     Gtid_set *gtid_set;
1582     bool locked;
1583   };
assert_free_intervals_locked()1584   void assert_free_intervals_locked()
1585   {
1586     if (sid_lock != NULL)
1587       mysql_mutex_assert_owner(&free_intervals_mutex);
1588   }
1589 
1590   /**
1591     Adds the interval (start, end) to the given Interval_iterator.
1592 
1593     This is the lowest-level function that adds groups; this is where
1594     Interval objects are added, grown, or merged.
1595 
1596     @param ivitp Pointer to iterator.  After this function returns,
1597     the current_element of the iterator will be the interval that
1598     contains start and end.
1599     @param start The first GNO in the interval.
1600     @param end The first GNO after the interval.
1601     @param lock If this function has to add or remove an interval,
1602     then this lock will be taken unless it is already taken.  This
1603     mechanism means that the lock will be taken lazily by
1604     e.g. add_gtid_set() the first time that the list of free intervals
1605     is accessed, and automatically released when add_gtid_set()
1606     returns.
1607     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1608   */
1609   enum_return_status add_gno_interval(Interval_iterator *ivitp,
1610                                       rpl_gno start, rpl_gno end,
1611                                       Free_intervals_lock *lock);
1612   /**
1613     Removes the interval (start, end) from the given
1614     Interval_iterator. This is the lowest-level function that removes
1615     groups; this is where Interval objects are removed, truncated, or
1616     split.
1617 
1618     It is not required that the groups in the interval exist in this
1619     Gtid_set.
1620 
1621     @param ivitp Pointer to iterator.  After this function returns,
1622     the current_element of the iterator will be the next interval
1623     after end.
1624     @param start The first GNO in the interval.
1625     @param end The first GNO after the interval.
1626     @param lock If this function has to add or remove an interval,
1627     then this lock will be taken unless it is already taken.  This
1628     mechanism means that the lock will be taken lazily by
1629     e.g. add_gtid_set() the first time that the list of free intervals
1630     is accessed, and automatically released when add_gtid_set()
1631     returns.
1632     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1633   */
1634   enum_return_status remove_gno_interval(Interval_iterator *ivitp,
1635                                          rpl_gno start, rpl_gno end,
1636                                          Free_intervals_lock *lock);
1637   /**
1638     Adds a list of intervals to the given SIDNO.
1639 
1640     The SIDNO must exist in the Gtid_set before this function is called.
1641 
1642     @param sidno The SIDNO to which intervals will be added.
1643     @param ivit Iterator over the intervals to add. This is typically
1644     an iterator over some other Gtid_set.
1645     @param lock If this function has to add or remove an interval,
1646     then this lock will be taken unless it is already taken.  This
1647     mechanism means that the lock will be taken lazily by
1648     e.g. add_gtid_set() the first time that the list of free intervals
1649     is accessed, and automatically released when add_gtid_set()
1650     returns.
1651     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1652   */
1653   enum_return_status add_gno_intervals(rpl_sidno sidno,
1654                                        Const_interval_iterator ivit,
1655                                        Free_intervals_lock *lock);
1656   /**
1657     Removes a list of intervals from the given SIDNO.
1658 
1659     It is not required that the intervals exist in this Gtid_set.
1660 
1661     @param sidno The SIDNO from which intervals will be removed.
1662     @param ivit Iterator over the intervals to remove. This is typically
1663     an iterator over some other Gtid_set.
1664     @param lock If this function has to add or remove an interval,
1665     then this lock will be taken unless it is already taken.  This
1666     mechanism means that the lock will be taken lazily by
1667     e.g. add_gtid_set() the first time that the list of free intervals
1668     is accessed, and automatically released when add_gtid_set()
1669     returns.
1670     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1671   */
1672   enum_return_status remove_gno_intervals(rpl_sidno sidno,
1673                                           Const_interval_iterator ivit,
1674                                           Free_intervals_lock *lock);
1675 
1676   /// Returns true if every interval of sub is a subset of some
1677   /// interval of super.
1678   static bool is_interval_subset(Const_interval_iterator *sub,
1679                                  Const_interval_iterator *super);
1680   /// Returns true if at least one sidno in ivit1 is also in ivit2.
1681   static bool is_interval_intersection_nonempty(Const_interval_iterator *ivit1,
1682                                                 Const_interval_iterator *ivit2);
1683 
1684   /// Sid_map associated with this Gtid_set.
1685   Sid_map *sid_map;
1686   /**
1687     Array where the N'th element contains the head pointer to the
1688     intervals of SIDNO N+1.
1689   */
1690   DYNAMIC_ARRAY intervals;
1691   /// Linked list of free intervals.
1692   Interval *free_intervals;
1693   /// Linked list of chunks.
1694   Interval_chunk *chunks;
1695   /// The string length.
1696   mutable int cached_string_length;
1697   /// The String_format that was used when cached_string_length was computed.
1698   mutable const String_format *cached_string_format;
1699 #ifndef DBUG_OFF
1700   /**
1701     The number of chunks.  Used only to check some invariants when
1702     DBUG is on.
1703   */
1704   int n_chunks;
1705 #endif
1706 
1707   /// Used by unit tests that need to access private members.
1708 #ifdef FRIEND_OF_GTID_SET
1709   friend FRIEND_OF_GTID_SET;
1710 #endif
1711   /// Only Free_intervals_lock is allowed to access free_intervals_mutex.
1712   friend class Gtid_set::Free_intervals_lock;
1713 };
1714 
1715 
1716 /**
1717   Holds information about a Gtid_set.  Can also be NULL.
1718 
1719   This is used as backend storage for @@session.gtid_next_list.  The
1720   idea is that we allow the user to set this to NULL, but we keep the
1721   Gtid_set object so that we can re-use the allocated memory and
1722   avoid costly allocations later.
1723 
1724   This is stored in struct system_variables (defined in sql_class.h),
1725   which is cleared using memset(0); hence the negated form of
1726   is_non_null.
1727 
1728   The convention is: if is_non_null is false, then the value of the
1729   session variable is NULL, and the field gtid_set may be NULL or
1730   non-NULL.  If is_non_null is true, then the value of the session
1731   variable is not NULL, and the field gtid_set has to be non-NULL.
1732 
1733   This is a POD. It has to be a POD because it is stored in
1734   THD::variables.
1735 */
1736 struct Gtid_set_or_null
1737 {
1738   /// Pointer to the Gtid_set.
1739   Gtid_set *gtid_set;
1740   /// True if this Gtid_set is NULL.
1741   bool is_non_null;
1742   /// Return NULL if this is NULL, otherwise return the Gtid_set.
get_gtid_setGtid_set_or_null1743   inline Gtid_set *get_gtid_set() const
1744   {
1745     DBUG_ASSERT(!(is_non_null && gtid_set == NULL));
1746     return is_non_null ? gtid_set : NULL;
1747   }
1748   /**
1749     Do nothing if this object is non-null; set to empty set otherwise.
1750 
1751     @return NULL if out of memory; Gtid_set otherwise.
1752   */
set_non_nullGtid_set_or_null1753   Gtid_set *set_non_null(Sid_map *sm)
1754   {
1755     if (!is_non_null)
1756     {
1757       if (gtid_set == NULL)
1758         gtid_set= new Gtid_set(sm);
1759       else
1760         gtid_set->clear();
1761     }
1762     is_non_null= (gtid_set != NULL);
1763     return gtid_set;
1764   }
1765   /// Set this Gtid_set to NULL.
set_nullGtid_set_or_null1766   inline void set_null() { is_non_null= false; }
1767 };
1768 
1769 
1770 /**
1771   Represents the set of GTIDs that are owned by some thread.
1772 
1773   This data structure has a read-write lock that protects the number
1774   of SIDNOs.  The lock is provided by the invoker of the constructor
1775   and it is generally the caller's responsibility to acquire the read
1776   lock.  Access methods assert that the caller already holds the read
1777   (or write) lock.  If a method of this class grows the number of
1778   SIDNOs, then the method temporarily upgrades this lock to a write
1779   lock and then degrades it to a read lock again; there will be a
1780   short period when the lock is not held at all.
1781 
1782   The internal representation is a DYNAMIC_ARRAY that maps SIDNO to
1783   HASH, where each HASH maps GNO to my_thread_id.
1784 */
1785 class Owned_gtids
1786 {
1787 public:
1788   /**
1789     Constructs a new, empty Owned_gtids object.
1790 
1791     @param sid_lock Read-write lock that protects updates to the
1792     number of SIDs.
1793   */
1794   Owned_gtids(Checkable_rwlock *sid_lock);
1795   /// Destroys this Owned_gtids.
1796   ~Owned_gtids();
1797   /**
1798     Add a GTID to this Owned_gtids.
1799 
1800     @param gtid The Gtid to add.
1801     @param owner The my_thread_id of the group to add.
1802     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1803   */
1804   enum_return_status add_gtid_owner(const Gtid &gtid, my_thread_id owner);
1805   /**
1806     Returns the owner of the given GTID, or 0 if the GTID is not owned.
1807 
1808     @param Gtid The Gtid to query.
1809     @return my_thread_id of the thread that owns the group, or
1810     0 if the group is not owned.
1811   */
1812   my_thread_id get_owner(const Gtid &gtid) const;
1813   /**
1814     Removes the given GTID.
1815 
1816     If the group does not exist in this Owned_gtids object, does
1817     nothing.
1818 
1819     @param gtid The Gtid.
1820   */
1821   void remove_gtid(const Gtid &gtid);
1822   /**
1823     Ensures that this Owned_gtids object can accomodate SIDNOs up to
1824     the given SIDNO.
1825 
1826     If this Owned_gtids object needs to be resized, then the lock
1827     will be temporarily upgraded to a write lock and then degraded to
1828     a read lock again; there will be a short period when the lock is
1829     not held at all.
1830 
1831     @param sidno The SIDNO.
1832     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
1833   */
1834   enum_return_status ensure_sidno(rpl_sidno sidno);
1835   /// Returns true if there is a least one element of this Owned_gtids
1836   /// set in the other Gtid_set.
1837   bool is_intersection_nonempty(const Gtid_set *other) const;
1838   /// Returns true if this Owned_gtids is empty.
is_empty()1839   bool is_empty() const
1840   {
1841     Gtid_iterator git(this);
1842     return git.get().sidno == 0;
1843   }
1844   /// Returns the maximal sidno that this Owned_gtids currently has space for.
get_max_sidno()1845   rpl_sidno get_max_sidno() const
1846   {
1847     sid_lock->assert_some_lock();
1848     return sidno_to_hash.elements;
1849   }
1850 
1851   /**
1852     Write a string representation of this Owned_groups to the given buffer.
1853 
1854     @param out Buffer to write to.
1855     @return Number of characters written.
1856   */
to_string(char * out)1857   int to_string(char *out) const
1858   {
1859     char *p= out;
1860     rpl_sidno max_sidno= get_max_sidno();
1861     rpl_sidno sid_map_max_sidno= global_sid_map->get_max_sidno();
1862     for (rpl_sidno sid_i= 0; sid_i < sid_map_max_sidno; sid_i++)
1863     {
1864       rpl_sidno sidno= global_sid_map->get_sorted_sidno(sid_i);
1865       if (sidno > max_sidno)
1866         continue;
1867       HASH *hash= get_hash(sidno);
1868       bool printed_sid= false;
1869       for (uint i= 0; i < hash->records; i++)
1870       {
1871         Node *node= (Node *)my_hash_element(hash, i);
1872         DBUG_ASSERT(node != NULL);
1873         if (!printed_sid)
1874         {
1875           p+= global_sid_map->sidno_to_sid(sidno).to_string(p);
1876           printed_sid= true;
1877         }
1878         p+= sprintf(p, ":%lld#%lu", node->gno, node->owner);
1879       }
1880     }
1881     *p= 0;
1882     return (int)(p - out);
1883   }
1884 
1885   /**
1886     Return an upper bound on the length of the string representation
1887     of this Owned_groups.  The actual length may be smaller.  This
1888     includes the trailing '\0'.
1889   */
get_max_string_length()1890   size_t get_max_string_length() const
1891   {
1892     rpl_sidno max_sidno= get_max_sidno();
1893     size_t ret= 0;
1894     for (rpl_sidno sidno= 1; sidno <= max_sidno; sidno++)
1895     {
1896       HASH *hash= get_hash(sidno);
1897       if (hash->records > 0)
1898         ret+= rpl_sid::TEXT_LENGTH +
1899           hash->records * (1 + MAX_GNO_TEXT_LENGTH +
1900                            1 + MAX_THREAD_ID_TEXT_LENGTH);
1901     }
1902     return 1 + ret;
1903   }
1904 
1905   /**
1906     Return true if the given thread is the owner of any groups.
1907   */
thread_owns_anything(my_thread_id thd_id)1908   bool thread_owns_anything(my_thread_id thd_id) const
1909   {
1910     Gtid_iterator git(this);
1911     Node *node= git.get_node();
1912     while (node != NULL)
1913     {
1914       if (node->owner == thd_id)
1915         return true;
1916       git.next();
1917       node= git.get_node();
1918     }
1919     return false;
1920   }
1921 
1922 #ifndef DBUG_OFF
1923   /**
1924     Debug only: return a newly allocated string representation of
1925     this Owned_gtids.
1926   */
to_string()1927   char *to_string() const
1928   {
1929     char *str= (char *)my_malloc(get_max_string_length(), MYF(MY_WME));
1930     DBUG_ASSERT(str != NULL);
1931     to_string(str);
1932     return str;
1933   }
1934   /// Debug only: print this Owned_gtids to stdout.
print()1935   void print() const
1936   {
1937     char *str= to_string();
1938     printf("%s\n", str);
1939     my_free(str);
1940   }
1941 #endif
1942   /**
1943     Print this Owned_gtids to the trace file if debug is enabled; no-op
1944     otherwise.
1945   */
1946   void dbug_print(const char *text= "") const
1947   {
1948 #ifndef DBUG_OFF
1949     char *str= to_string();
1950     DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", str));
1951     my_free(str);
1952 #endif
1953   }
1954 private:
1955   /// Represents one owned group.
1956   struct Node
1957   {
1958     /// GNO of the group.
1959     rpl_gno gno;
1960     /// Owner of the group.
1961     my_thread_id owner;
1962   };
1963   /// Read-write lock that protects updates to the number of SIDs.
1964   mutable Checkable_rwlock *sid_lock;
1965   /// Returns the HASH for the given SIDNO.
get_hash(rpl_sidno sidno)1966   HASH *get_hash(rpl_sidno sidno) const
1967   {
1968     DBUG_ASSERT(sidno >= 1 && sidno <= get_max_sidno());
1969     sid_lock->assert_some_lock();
1970     return *dynamic_element(&sidno_to_hash, sidno - 1, HASH **);
1971   }
1972   /**
1973     Returns the Node for the given HASH and GNO, or NULL if the GNO
1974     does not exist in the HASH.
1975   */
get_node(const HASH * hash,rpl_gno gno)1976   Node *get_node(const HASH *hash, rpl_gno gno) const
1977   {
1978     sid_lock->assert_some_lock();
1979     return (Node *)my_hash_search(hash, (const uchar *)&gno, sizeof(rpl_gno));
1980   }
1981   /**
1982     Returns the Node for the given group, or NULL if the group does
1983     not exist in this Owned_gtids object.
1984   */
get_node(const Gtid & gtid)1985   Node *get_node(const Gtid &gtid) const
1986   { return get_node(get_hash(gtid.sidno), gtid.gno); };
1987   /// Return true iff this Owned_gtids object contains the given group.
contains_gtid(const Gtid & gtid)1988   bool contains_gtid(const Gtid &gtid) const { return get_node(gtid) != NULL; }
1989   /// Growable array of hashes.
1990   DYNAMIC_ARRAY sidno_to_hash;
1991 
1992 public:
1993   /**
1994     Iterator over all groups in a Owned_gtids set.  This is a const
1995     iterator; it does not allow modification of the set.
1996   */
1997   class Gtid_iterator
1998   {
1999   public:
Gtid_iterator(const Owned_gtids * og)2000     Gtid_iterator(const Owned_gtids* og)
2001       : owned_gtids(og), sidno(1), hash(NULL), node_index(0), node(NULL)
2002     {
2003       max_sidno= owned_gtids->get_max_sidno();
2004       if (sidno <= max_sidno)
2005         hash= owned_gtids->get_hash(sidno);
2006       next();
2007     }
2008     /// Advance to next group.
next()2009     inline void next()
2010     {
2011 #ifndef DBUG_OFF
2012       if (owned_gtids->sid_lock)
2013         owned_gtids->sid_lock->assert_some_wrlock();
2014 #endif
2015 
2016       while (sidno <= max_sidno)
2017       {
2018         DBUG_ASSERT(hash != NULL);
2019         if (node_index < hash->records)
2020         {
2021           node= (Node *)my_hash_element(hash, node_index);
2022           DBUG_ASSERT(node != NULL);
2023           // Jump to next node on next iteration.
2024           node_index++;
2025           return;
2026         }
2027 
2028         node_index= 0;
2029         // hash is initialized on constructor or in previous iteration
2030         // for current SIDNO, so we must increment for next iteration.
2031         sidno++;
2032         if (sidno <= max_sidno)
2033           hash= owned_gtids->get_hash(sidno);
2034       }
2035       node= NULL;
2036     }
2037     /// Return next group, or {0,0} if we reached the end.
get()2038     inline Gtid get() const
2039     {
2040       Gtid ret= { 0, 0 };
2041       if (node)
2042       {
2043         ret.sidno= sidno;
2044         ret.gno= node->gno;
2045       }
2046       return ret;
2047     }
2048     /// Return next group Node, or NULL if we reached the end.
get_node()2049     inline Node* get_node() const
2050     {
2051       return node;
2052     }
2053   private:
2054     /// The Owned_gtids set we iterate over.
2055     const Owned_gtids *owned_gtids;
2056     /// The SIDNO of the current element, or 1 in the initial iteration.
2057     rpl_sidno sidno;
2058     /// Max SIDNO of the current iterator.
2059     rpl_sidno max_sidno;
2060     /// Current SIDNO hash.
2061     HASH *hash;
2062     /// Current node index on current SIDNO hash.
2063     uint node_index;
2064     /// Current node on current SIDNO hash.
2065     Node *node;
2066   };
2067 };
2068 
2069 
2070 /**
2071   Represents the state of the group log: the set of logged groups, the
2072   set of lost groups, the set of owned groups, the owner of each owned
2073   group, and a Mutex_cond_array that protects updates to groups of
2074   each SIDNO.
2075 
2076   Locking:
2077 
2078   This data structure has a read-write lock that protects the number
2079   of SIDNOs, and a Mutex_cond_array that contains one mutex per SIDNO.
2080   The rwlock is always the global_sid_lock.
2081 
2082   Access methods generally assert that the caller already holds the
2083   appropriate lock:
2084 
2085    - before accessing any global data, hold at least the rdlock.
2086 
2087    - before accessing a specific SIDNO in a Gtid_set or Owned_gtids
2088      (e.g., calling Gtid_set::_add_gtid(Gtid)), hold either the rdlock
2089      and the SIDNO's mutex lock; or the wrlock.  If you need to hold
2090      multiple mutexes, they must be acquired in order of increasing
2091      SIDNO.
2092 
2093    - before starting an operation that needs to access all SIDs
2094      (e.g. Gtid_set::to_string()), hold the wrlock.
2095 
2096   The access type (read/write) does not matter; the write lock only
2097   implies that the entire data structure is locked whereas the read
2098   lock implies that everything except SID-specific data is locked.
2099 */
2100 class Gtid_state
2101 {
2102 public:
2103   /**
2104     Constructs a new Gtid_state object.
2105 
2106     @param _sid_lock Read-write lock that protects updates to the
2107     number of SIDs.
2108     @param _sid_map Sid_map used by this group log.
2109   */
Gtid_state(Checkable_rwlock * _sid_lock,Sid_map * _sid_map)2110   Gtid_state(Checkable_rwlock *_sid_lock, Sid_map *_sid_map)
2111     : sid_lock(_sid_lock),
2112     sid_map(_sid_map),
2113     sid_locks(sid_lock),
2114     logged_gtids(sid_map, sid_lock),
2115     lost_gtids(sid_map, sid_lock),
2116     owned_gtids(sid_lock) {}
2117   /**
2118     Add @@GLOBAL.SERVER_UUID to this binlog's Sid_map.
2119 
2120     This can't be done in the constructor because the constructor is
2121     invoked at server startup before SERVER_UUID is initialized.
2122 
2123     The caller must hold the read lock or write lock on sid_locks
2124     before invoking this function.
2125 
2126     @retval 0 Success
2127     @retval 1 Error (out of memory or IO error).
2128   */
2129   int init();
2130   /**
2131     Reset the state after RESET MASTER: remove all logged and lost
2132     groups, but keep owned groups as they are.
2133 
2134     The caller must hold the write lock on sid_lock before calling
2135     this function.
2136   */
2137   void clear();
2138   /**
2139     Returns true if the given GTID is logged.
2140 
2141     @param gtid The Gtid to check.
2142 
2143     @retval true The group is logged in the binary log.
2144     @retval false The group is not logged in the binary log.
2145   */
is_logged(const Gtid & gtid)2146   bool is_logged(const Gtid &gtid) const
2147   {
2148     DBUG_ENTER("Gtid_state::is_logged");
2149     bool ret= logged_gtids.contains_gtid(gtid);
2150     DBUG_RETURN(ret);
2151   }
2152   /**
2153     Returns the owner of the given GTID, or 0 if the group is not owned.
2154 
2155     @param gtid The Gtid to check.
2156     @return my_thread_id of the thread that owns the group, or
2157     0 if the group is not owned.
2158   */
get_owner(const Gtid & gtid)2159   my_thread_id get_owner(const Gtid &gtid) const
2160   { return owned_gtids.get_owner(gtid); }
2161 #ifndef MYSQL_CLIENT
2162   /**
2163     Acquires ownership of the given GTID, on behalf of the given thread.
2164 
2165     The caller must lock the SIDNO before invoking this function.
2166 
2167     @param thd The thread that will own the GTID.
2168     @param gtid The Gtid to acquire ownership of.
2169     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2170   */
2171   enum_return_status acquire_ownership(THD *thd, const Gtid &gtid);
2172   /**
2173     Update the state after the given thread has flushed cache to binlog.
2174 
2175     This will:
2176      - release ownership of all GTIDs owned by the THD;
2177      - add all GTIDs in the Group_cache to
2178        logged_gtids;
2179      - send a broadcast on the condition variable for every sidno for
2180        which we released ownership.
2181 
2182     @param thd Thread for which owned groups are updated.
2183   */
2184   enum_return_status update_on_flush(THD *thd);
2185   /**
2186     Remove the GTID owned by thread from owned GTIDs, stating that
2187     thd->owned_gtid was committed.
2188 
2189     This will:
2190      - remove owned GTID from owned_gtids;
2191      - remove all owned GTIDS from thd->owned_gtid and thd->owned_gtid_set;
2192 
2193     @param thd Thread for which owned groups are updated.
2194   */
2195   void update_on_commit(THD *thd);
2196   /**
2197     Update the state after the given thread has rollbacked.
2198 
2199     This will:
2200      - release ownership of all GTIDs owned by the THD;
2201      - remove owned GTID from owned_gtids;
2202      - remove all owned GTIDS from thd->owned_gtid and thd->owned_gtid_set;
2203      - send a broadcast on the condition variable for every sidno for
2204        which we released ownership.
2205 
2206     @param thd Thread for which owned groups are updated.
2207   */
2208   void update_on_rollback(THD *thd);
2209 #endif // ifndef MYSQL_CLIENT
2210   /**
2211     Allocates a GNO for an automatically numbered group.
2212 
2213     @param sidno The group's SIDNO.
2214 
2215     @retval negative the numeric value of GS_ERROR_OUT_OF_MEMORY
2216     @retval other The GNO for the group.
2217   */
2218   rpl_gno get_automatic_gno(rpl_sidno sidno) const;
2219   /// Locks a mutex for the given SIDNO.
lock_sidno(rpl_sidno sidno)2220   void lock_sidno(rpl_sidno sidno) { sid_locks.lock(sidno); }
2221   /// Unlocks a mutex for the given SIDNO.
unlock_sidno(rpl_sidno sidno)2222   void unlock_sidno(rpl_sidno sidno) { sid_locks.unlock(sidno); }
2223   /// Broadcasts updates for the given SIDNO.
broadcast_sidno(rpl_sidno sidno)2224   void broadcast_sidno(rpl_sidno sidno) { sid_locks.broadcast(sidno); }
2225   /// Assert that we own the given SIDNO.
assert_sidno_lock_owner(rpl_sidno sidno)2226   void assert_sidno_lock_owner(rpl_sidno sidno)
2227   { sid_locks.assert_owner(sidno); }
2228 #ifndef MYSQL_CLIENT
2229   /**
2230     Waits until the given GTID is not owned by any other thread.
2231 
2232     This requires that the caller holds a read lock on sid_lock.  It
2233     will release the lock before waiting; neither global_sid_lock nor
2234     the mutex lock on SIDNO will not be held when this function
2235     returns.
2236 
2237     @param thd THD object of the caller.
2238     @param g Gtid to wait for.
2239   */
2240   void wait_for_gtid(THD *thd, const Gtid &gtid);
2241 #endif // ifndef MYSQL_CLIENT
2242 #ifdef HAVE_NDB_BINLOG
2243   /**
2244     Locks one mutex for each SIDNO where the given Gtid_set has at
2245     least one GTID.  Locks are acquired in order of increasing SIDNO.
2246   */
2247   void lock_sidnos(const Gtid_set *set);
2248   /**
2249     Unlocks the mutex for each SIDNO where the given Gtid_set has at
2250     least one GTID.
2251   */
2252   void unlock_sidnos(const Gtid_set *set);
2253   /**
2254     Broadcasts the condition variable for each SIDNO where the given
2255     Gtid_set has at least one GTID.
2256   */
2257   void broadcast_sidnos(const Gtid_set *set);
2258 #endif // ifdef HAVE_NDB_BINLOG
2259   /**
2260     Ensure that owned_gtids, logged_gtids, lost_gtids, and sid_locks
2261     have room for at least as many SIDNOs as sid_map.
2262 
2263     This function must only be called in one place:
2264     Sid_map::add_sid().
2265 
2266     Requires that the write lock on sid_locks is held.  If any object
2267     needs to be resized, then the lock will be temporarily upgraded to
2268     a write lock and then degraded to a read lock again; there will be
2269     a short period when the lock is not held at all.
2270 
2271     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2272   */
2273   enum_return_status ensure_sidno();
2274   /**
2275     Adds the given Gtid_set that contains the groups in the given
2276     string to lost_gtids and logged_gtids, since lost_gtids must
2277     be a subset of executed_gtids.
2278     Requires that the write lock on sid_locks is held.
2279 
2280     @param text The string to parse, see Gtid_set:add_gtid_text(const
2281     char *, bool) for format details.
2282     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2283    */
2284   enum_return_status add_lost_gtids(const char *text);
2285   /// Return a pointer to the Gtid_set that contains the logged groups.
get_logged_gtids()2286   const Gtid_set *get_logged_gtids() const { return &logged_gtids; }
2287   /// Return a pointer to the Gtid_set that contains the lost groups.
get_lost_gtids()2288   const Gtid_set *get_lost_gtids() const { return &lost_gtids; }
2289   /// Return a pointer to the Owned_gtids that contains the owned groups.
get_owned_gtids()2290   const Owned_gtids *get_owned_gtids() const { return &owned_gtids; }
2291   /// Return the server's SID's SIDNO
get_server_sidno()2292   rpl_sidno get_server_sidno() const { return server_sidno; }
2293   /// Return the server's SID
get_server_sid()2294   const rpl_sid &get_server_sid() const
2295   {
2296     return global_sid_map->sidno_to_sid(server_sidno);
2297   }
2298 #ifndef DBUG_OFF
2299   /**
2300     Debug only: Returns an upper bound on the length of the string
2301     generated by to_string(), not counting '\0'.  The actual length
2302     may be shorter.
2303   */
get_max_string_length()2304   size_t get_max_string_length() const
2305   {
2306     return owned_gtids.get_max_string_length() +
2307       logged_gtids.get_string_length() +
2308       lost_gtids.get_string_length() +
2309       100;
2310   }
2311   /// Debug only: Generate a string in the given buffer and return the length.
to_string(char * buf)2312   int to_string(char *buf) const
2313   {
2314     char *p= buf;
2315     p+= sprintf(p, "Logged GTIDs:\n");
2316     p+= logged_gtids.to_string(p);
2317     p+= sprintf(p, "\nOwned GTIDs:\n");
2318     p+= owned_gtids.to_string(p);
2319     p+= sprintf(p, "\nLost GTIDs:\n");
2320     p+= lost_gtids.to_string(p);
2321     return (int)(p - buf);
2322   }
2323   /// Debug only: return a newly allocated string, or NULL on out-of-memory.
to_string()2324   char *to_string() const
2325   {
2326     char *str= (char *)my_malloc(get_max_string_length(), MYF(MY_WME));
2327     to_string(str);
2328     return str;
2329   }
2330   /// Debug only: print this Gtid_state to stdout.
print()2331   void print() const
2332   {
2333     char *str= to_string();
2334     printf("%s", str);
2335     my_free(str);
2336   }
2337 #endif
2338   /**
2339     Print this Gtid_state to the trace file if debug is enabled; no-op
2340     otherwise.
2341   */
2342   void dbug_print(const char *text= "") const
2343   {
2344 #ifndef DBUG_OFF
2345     sid_lock->assert_some_wrlock();
2346     char *str= to_string();
2347     DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", str));
2348     my_free(str);
2349 #endif
2350   }
2351 private:
2352 #ifdef HAVE_NDB_BINLOG
2353   /// Lock all SIDNOs owned by the given THD.
2354   void lock_owned_sidnos(const THD *thd);
2355 #endif
2356   /// Unlock all SIDNOs owned by the given THD.
2357   void unlock_owned_sidnos(const THD *thd);
2358   /// Broadcast the condition for all SIDNOs owned by the given THD.
2359   void broadcast_owned_sidnos(const THD *thd);
2360   /**
2361     Remove the GTID owned by thread from owned GTIDs.
2362 
2363     @param thd Thread for which owned groups are updated.
2364     @param is_commit send a broadcast on the condition variable for
2365            every sidno for which we released ownership.
2366   */
2367   void update_owned_gtids_impl(THD *thd, bool is_commit);
2368 
2369 
2370   /// Read-write lock that protects updates to the number of SIDs.
2371   mutable Checkable_rwlock *sid_lock;
2372   /// The Sid_map used by this Gtid_state.
2373   mutable Sid_map *sid_map;
2374   /// Contains one mutex/cond pair for every SIDNO.
2375   Mutex_cond_array sid_locks;
2376   /// The set of GTIDs that have been executed and logged (and possibly purged).
2377   Gtid_set logged_gtids;
2378   /**
2379     The set of GTIDs that existed in some previously purged binary log.
2380     This is always a subset of logged_gtids.
2381   */
2382   Gtid_set lost_gtids;
2383   /// The set of GTIDs that are owned by some thread.
2384   Owned_gtids owned_gtids;
2385   /// The SIDNO for this server.
2386   rpl_sidno server_sidno;
2387 
2388   /// Used by unit tests that need to access private members.
2389 #ifdef FRIEND_OF_GTID_STATE
2390   friend FRIEND_OF_GTID_STATE;
2391 #endif
2392 };
2393 
2394 
2395 /// Global state of GTIDs.
2396 extern Gtid_state *gtid_state;
2397 
2398 
2399 /**
2400   Enumeration of group types.
2401 */
2402 enum enum_group_type
2403 {
2404   /**
2405     It is important that AUTOMATIC_GROUP==0 so that the default value
2406     for thd->variables->gtid_next.type is AUTOMATIC_GROUP.
2407   */
2408   AUTOMATIC_GROUP= 0, GTID_GROUP, ANONYMOUS_GROUP, INVALID_GROUP, UNDEFINED_GROUP
2409 };
2410 
2411 
2412 /**
2413   This struct represents a specification of a GTID for a statement to
2414   be executed: either "AUTOMATIC", "ANONYMOUS", or "SID:GNO".
2415 
2416   This is a POD. It has to be a POD because it is used in THD::variables.
2417 */
2418 struct Gtid_specification
2419 {
2420   /// The type of this GTID
2421   enum_group_type type;
2422   /**
2423     The GTID:
2424     { SIDNO, GNO } if type == GTID;
2425     { 0, 0 } if type == AUTOMATIC or ANONYMOUS.
2426   */
2427   Gtid gtid;
2428   /// Set the type to GTID_GROUP and SID, GNO to the given values.
setGtid_specification2429   void set(rpl_sidno sidno, rpl_gno gno)
2430   { type= GTID_GROUP; gtid.sidno= sidno; gtid.gno= gno; }
2431   /// Set the type to GTID_GROUP and SID, GNO to the given Gtid.
setGtid_specification2432   void set(const Gtid &gtid_param) { set(gtid_param.sidno, gtid_param.gno); }
2433   /// Set the type to ANONYMOUS_GROUP and SID, GNO to 0, 0.
set_anonymousGtid_specification2434   void set_anonymous()
2435   { type= ANONYMOUS_GROUP; gtid.sidno= 0; gtid.gno= 0; }
2436   /// Set the type to AUTOMATIC_GROUP.
set_automaticGtid_specification2437   void set_automatic()
2438   {
2439     type= AUTOMATIC_GROUP;
2440   }
2441   /// Set to undefined if the current type is GTID_GROUP.
set_undefinedGtid_specification2442   void set_undefined()
2443   {
2444     if (type == GTID_GROUP)
2445       type= UNDEFINED_GROUP;
2446   }
2447   /// Set the type to GTID_GROUP and SID, GNO to 0, 0.
clearGtid_specification2448   void clear() { set(0, 0); }
2449   /// Return true if this Gtid_specification is equal to 'other'.
equalsGtid_specification2450   bool equals(const Gtid_specification &other) const
2451   {
2452     return (type == other.type &&
2453             (type != GTID_GROUP || gtid.equals(other.gtid)));
2454   }
2455   /**
2456     Return true if this Gtid_specification is a GTID_GROUP with the
2457     same SID, GNO as 'other_gtid'.
2458   */
equalsGtid_specification2459   bool equals(const Gtid &other_gtid) const
2460   { return type == GTID_GROUP && gtid.equals(other_gtid); }
2461 #ifndef MYSQL_CLIENT
2462   /**
2463     Parses the given string and stores in this Gtid_specification.
2464 
2465     @param text The text to parse
2466     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2467   */
2468   enum_return_status parse(Sid_map *sid_map, const char *text);
2469   /**
2470     Returns the type of the group, if the given string is a valid Gtid_specification; INVALID otherwise.
2471   */
2472   static enum_group_type get_type(const char *text);
2473   /// Returns true if the given string is a valid Gtid_specification.
is_validGtid_specification2474   static bool is_valid(const char *text)
2475   { return Gtid_specification::get_type(text) != INVALID_GROUP; }
2476 #endif
2477   static const int MAX_TEXT_LENGTH= Uuid::TEXT_LENGTH + 1 + MAX_GNO_TEXT_LENGTH;
2478   /**
2479     Writes this Gtid_specification to the given string buffer.
2480 
2481     @param sid_map Sid_map to use if the type of this
2482     Gtid_specification is GTID_GROUP.
2483     @param buf[out] The buffer
2484     @retval The number of characters written.
2485   */
2486   int to_string(const Sid_map *sid_map, char *buf) const;
2487   /**
2488     Writes this Gtid_specification to the given string buffer.
2489 
2490     @param sid SID to use if the type of this Gtid_specification is
2491     GTID_GROUP.  Can be NULL if this Gtid_specification is
2492     ANONYMOUS_GROUP or AUTOMATIC_GROUP.
2493     @param buf[out] The buffer
2494     @retval The number of characters written.
2495     @buf[out]
2496   */
2497   int to_string(const rpl_sid *sid, char *buf) const;
2498 #ifndef DBUG_OFF
2499   /// Debug only: print this Gtid_specification to stdout.
printGtid_specification2500   void print() const
2501   {
2502     char buf[MAX_TEXT_LENGTH + 1];
2503     to_string(global_sid_map, buf);
2504     printf("%s\n", buf);
2505   }
2506 #endif
2507   /**
2508     Print this Gtid_specificatoin to the trace file if debug is
2509     enabled; no-op otherwise.
2510   */
2511   void dbug_print(const char *text= "") const
2512   {
2513 #ifndef DBUG_OFF
2514     char buf[MAX_TEXT_LENGTH + 1];
2515     to_string(global_sid_map, buf);
2516     DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", buf));
2517 #endif
2518   }
2519 };
2520 
2521 
2522 /**
2523   Represents a group in the group cache.
2524 
2525   Groups in the group cache are slightly different from other groups,
2526   because not all information about them is known.
2527 
2528   Automatic groups are marked as such by setting gno<=0.
2529 */
2530 struct Cached_group
2531 {
2532   /// The gtid for this group.
2533   Gtid_specification spec;
2534   /**
2535     The position of this GTID in the cache, i.e., the total size of
2536     all previous groups.
2537   */
2538   rpl_binlog_pos binlog_offset;
2539 };
2540 
2541 
2542 /**
2543   Represents a group cache: either the statement group cache or the
2544   transaction group cache.
2545 */
2546 class Group_cache
2547 {
2548 public:
2549   /// Constructs a new Group_cache.
2550   Group_cache();
2551   /// Deletes a Group_cache.
2552   ~Group_cache();
2553   /// Removes all groups from this cache.
2554   void clear();
2555   /// Return the number of groups in this group cache.
get_n_groups()2556   inline int get_n_groups() const { return groups.elements; }
2557   /// Return true iff the group cache contains zero groups.
is_empty()2558   inline bool is_empty() const { return get_n_groups() == 0; }
2559   /**
2560     Adds a group to this Group_cache.  The group should
2561     already have been written to the stmt or trx cache.  The SIDNO and
2562     GNO fields are taken from @@SESSION.GTID_NEXT.
2563 
2564     @param thd The THD object from which we read session variables.
2565     @param binlog_length Length of group in binary log.
2566     @retval EXTEND_EXISTING_GROUP The last existing group had the same GTID
2567     and has been extended to include this group too.
2568     @retval APPEND_NEW_GROUP The group has been appended to this cache.
2569     @retval ERROR An error (out of memory) occurred.
2570     The error has been reported.
2571   */
2572   enum enum_add_group_status
2573   {
2574     EXTEND_EXISTING_GROUP, APPEND_NEW_GROUP, ERROR
2575   };
2576 #ifndef MYSQL_CLIENT
2577   enum_add_group_status
2578     add_logged_group(const THD *thd, my_off_t binlog_offset);
2579 #endif // ifndef MYSQL_CLIENT
2580 #ifdef NON_DISABLED_GTID
2581   /**
2582     Adds an empty group with the given (SIDNO, GNO) to this cache.
2583 
2584     @param gtid The GTID of the group.
2585 
2586     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2587   */
2588   enum_add_group_status add_empty_group(const Gtid &gtid);
2589 #endif // ifdef NON_DISABLED_GTID
2590 #ifndef MYSQL_CLIENT
2591   /**
2592     Write all gtids in this cache to the global Gtid_state.
2593     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2594   */
2595   enum_return_status write_to_gtid_state() const;
2596   /**
2597     Generates GNO for all groups that are committed for the first time
2598     in this Group_cache.
2599 
2600     This acquires ownership of all groups.  After this call, this
2601     Group_cache does not contain any Cached_groups that have
2602     type==GTID_GROUP and gno<=0.
2603 
2604     @param thd The THD that this Gtid_state belongs to.
2605     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR
2606   */
2607   enum_return_status generate_automatic_gno(THD *thd);
2608 #endif // ifndef MYSQL_CLIENT
2609   /**
2610     Return true if this Group_cache contains the given GTID.
2611 
2612     @param gtid The Gtid to check.
2613     @retval true The group exists in this cache.
2614     @retval false The group does not exist in this cache.
2615   */
2616   bool contains_gtid(const Gtid &gtid) const;
2617   /**
2618     Add all GTIDs that exist in this Group_cache to the given Gtid_set.
2619 
2620     @param gs The Gtid_set to which groups are added.
2621     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2622   */
2623   enum_return_status get_gtids(Gtid_set *gs) const;
2624 
2625 #ifndef DBUG_OFF
2626   /**
2627     Debug only: store a textual representation of this Group_cache in
2628     the given buffer and return the length.
2629   */
to_string(const Sid_map * sm,char * buf)2630   size_t to_string(const Sid_map *sm, char *buf) const
2631   {
2632     int n_groups= get_n_groups();
2633     char *s= buf;
2634 
2635     s += sprintf(s, "%d groups = {\n", n_groups);
2636     for (int i= 0; i < n_groups; i++)
2637     {
2638       Cached_group *group= get_unsafe_pointer(i);
2639       char uuid[Uuid::TEXT_LENGTH + 1]= "[]";
2640       if (group->spec.gtid.sidno)
2641         sm->sidno_to_sid(group->spec.gtid.sidno).to_string(uuid);
2642       s += sprintf(s, "  %s:%lld [offset %lld] %s\n",
2643                    uuid, group->spec.gtid.gno, group->binlog_offset,
2644                    group->spec.type == GTID_GROUP ? "GTID" :
2645                    group->spec.type == ANONYMOUS_GROUP ? "ANONYMOUS" :
2646                    group->spec.type == AUTOMATIC_GROUP ? "AUTOMATIC" :
2647                    "INVALID-GROUP-TYPE");
2648     }
2649     sprintf(s, "}\n");
2650     return s - buf;
2651   }
2652   /**
2653     Debug only: return an upper bound on the length of the string
2654     generated by to_string(). The actual length may be shorter.
2655   */
get_max_string_length()2656   size_t get_max_string_length() const
2657   {
2658     return (2 + Uuid::TEXT_LENGTH + 1 + MAX_GNO_TEXT_LENGTH + 4 + 2 +
2659             40 + 10 + 21 + 1 + 100/*margin*/) * get_n_groups() + 100/*margin*/;
2660   }
2661   /**
2662     Debug only: generate a textual representation of this Group_cache
2663     and store in a newly allocated string. Return the string, or NULL
2664     on out of memory.
2665   */
to_string(const Sid_map * sm)2666   char *to_string(const Sid_map *sm) const
2667   {
2668     char *str= (char *)my_malloc(get_max_string_length(), MYF(MY_WME));
2669     if (str)
2670       to_string(sm, str);
2671     return str;
2672   }
2673   /// Debug only: print this Group_cache to stdout.
print(const Sid_map * sm)2674   void print(const Sid_map *sm) const
2675   {
2676     char *str= to_string(sm);
2677     printf("%s\n", str);
2678     my_free(str);
2679   }
2680 #endif
2681   /**
2682     Print this Gtid_cache to the trace file if debug is enabled; no-op
2683     otherwise.
2684   */
2685   void dbug_print(const Sid_map *sid_map, const char *text= "") const
2686   {
2687 #ifndef DBUG_OFF
2688     char *str= to_string(sid_map);
2689     DBUG_PRINT("info", ("%s%s%s", text, *text ? ": " : "", str));
2690     my_free(str);
2691 #endif
2692   }
2693 
2694   /**
2695     Returns a pointer to the given group.  The pointer is only valid
2696     until the next time a group is added or removed.
2697 
2698     @param index Index of the element: 0 <= index < get_n_groups().
2699   */
get_unsafe_pointer(int index)2700   inline Cached_group *get_unsafe_pointer(int index) const
2701   {
2702     DBUG_ASSERT(index >= 0 && index < get_n_groups());
2703     return dynamic_element(&groups, index, Cached_group *);
2704   }
2705 
2706 private:
2707   /// List of all groups in this cache, of type Cached_group.
2708   DYNAMIC_ARRAY groups;
2709 
2710   /**
2711     Return a pointer to the last group, or NULL if this Group_cache is
2712     empty.
2713   */
get_last_group()2714   Cached_group *get_last_group()
2715   {
2716     int n_groups= get_n_groups();
2717     return n_groups == 0 ? NULL : get_unsafe_pointer(n_groups - 1);
2718   }
2719 
2720   /**
2721     Allocate space for one more group and return a pointer to it, or
2722     NULL on error.
2723   */
allocate_group()2724   Cached_group *allocate_group()
2725   {
2726     Cached_group *ret= (Cached_group *)alloc_dynamic(&groups);
2727     if (ret == NULL)
2728       BINLOG_ERROR(("Out of memory."), (ER_OUT_OF_RESOURCES, MYF(0)));
2729     return ret;
2730   }
2731 
2732   /**
2733     Adds the given group to this group cache, or merges it with the
2734     last existing group in the cache if they are compatible.
2735 
2736     @param group The group to add.
2737     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2738   */
2739   enum_return_status add_group(const Cached_group *group);
2740   /**
2741     Prepare the cache to be written to the group log.
2742 
2743     @todo The group log is not yet implemented. /Sven
2744 
2745     @param trx_group_cache @see write_to_log.
2746     @return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
2747   */
2748   enum_return_status
2749     write_to_log_prepare(Group_cache *trx_group_cache,
2750                          rpl_binlog_pos offset_after_last_statement,
2751                          Cached_group **last_non_empty_group);
2752 
2753   /// Used by unit tests that need to access private members.
2754 #ifdef FRIEND_OF_GROUP_CACHE
2755   friend FRIEND_OF_GROUP_CACHE;
2756 #endif
2757 };
2758 
2759 /**
2760   Indicates if a statement should be skipped or not. Used as return
2761   value from gtid_before_statement.
2762 */
2763 enum enum_gtid_statement_status
2764 {
2765   /// Statement can execute.
2766   GTID_STATEMENT_EXECUTE,
2767   /// Statement should be cancelled.
2768   GTID_STATEMENT_CANCEL,
2769   /**
2770     Statement should be skipped, but there may be an implicit commit
2771     after the statement if gtid_commit is set.
2772   */
2773   GTID_STATEMENT_SKIP
2774 };
2775 
2776 
2777 #ifndef MYSQL_CLIENT
2778 /**
2779   Before a loggable statement begins, this function:
2780 
2781    - checks that the various @@session.gtid_* variables are consistent
2782      with each other
2783 
2784    - starts the super-group (if no super-group is active) and acquires
2785      ownership of all groups in the super-group
2786 
2787    - starts the group (if no group is active)
2788 */
2789 enum_gtid_statement_status
2790 gtid_before_statement(THD *thd, Group_cache *gsc, Group_cache *gtc);
2791 
2792 /**
2793   Check that the current statement does not contradict
2794   enforce_gtid_consistency, that there is no implicit commit in
2795   a transaction when GTID_NEXT!=AUTOMATIC, and whether the statement
2796   should be cancelled.
2797 
2798   @param thd THD object for the session.
2799 */
2800 enum_gtid_statement_status gtid_pre_statement_checks(const THD *thd);
2801 
2802 /**
2803   Check if the current statement terminates a transaction, and if so
2804   set GTID_NEXT.type to UNDEFINED_GROUP.
2805 
2806   @param thd THD object for the session.
2807 */
2808 void gtid_post_statement_checks(THD *thd);
2809 
2810 /**
2811   When a transaction is rolled back, this function releases ownership
2812   of any GTIDs that the transaction owns.
2813 */
2814 int gtid_rollback(THD *thd);
2815 
2816 int gtid_acquire_ownership_single(THD *thd);
2817 #ifdef HAVE_NDB_BINLOG
2818 int gtid_acquire_ownership_multiple(THD *thd);
2819 #endif
2820 
2821 #endif // ifndef MYSQL_CLIENT
2822 
2823 #endif /* RPL_GTID_H_INCLUDED */
2824