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 >id) 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 >id) 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 >id) 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 *>(>id_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(>id_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(>id_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(>id_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 >id, 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 >id) 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 >id); 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 >id) 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 >id) 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 >id) 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 >id) 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 >id); 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 >id); 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 >id_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 >id); 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 >id) 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