MySQL 8.4.0
Source Code Documentation
semisync_source.h
Go to the documentation of this file.
1/* Copyright (C) 2007 Google Inc.
2 Copyright (c) 2008, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License, version 2.0, for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
24
25#ifndef SEMISYNC_SOURCE_H
26#define SEMISYNC_SOURCE_H
27
28#include <assert.h>
29#include <sys/types.h>
30
31#include "my_inttypes.h"
32#include "my_io.h"
33#include "my_psi_config.h"
35
37
38#ifdef HAVE_PSI_INTERFACE
41#endif
42
46
48
49struct TranxNode {
54 struct TranxNode *next_; /* the next node in the sorted list */
55 struct TranxNode *hash_next_; /* the next node during hash collision */
56};
57
58/**
59 @class TranxNodeAllocator
60
61 This class provides memory allocating and freeing methods for
62 TranxNode. The main target is performance.
63
64 @section ALLOCATE How to allocate a node
65 The pointer of the first node after 'last_node' in current_block is
66 returned. current_block will move to the next free Block when all nodes of
67 it are in use. A new Block is allocated and is put into the rear of the
68 Block link table if no Block is free.
69
70 The list starts up empty (ie, there is no allocated Block).
71
72 After some nodes are freed, there probably are some free nodes before
73 the sequence of the allocated nodes, but we do not reuse it. It is better
74 to keep the allocated nodes are in the sequence, for it is more efficient
75 for allocating and freeing TranxNode.
76
77 @section FREENODE How to free nodes
78 There are two methods for freeing nodes. They are free_all_nodes and
79 free_nodes_before.
80
81 'A Block is free' means all of its nodes are free.
82 @subsection free_nodes_before
83 As all allocated nodes are in the sequence, 'Before one node' means all
84 nodes before given node in the same Block and all Blocks before the Block
85 which containing the given node. As such, all Blocks before the given one
86 ('node') are free Block and moved into the rear of the Block link table.
87 The Block containing the given 'node', however, is not. For at least the
88 given 'node' is still in use. This will waste at most one Block, but it is
89 more efficient.
90 */
91#define BLOCK_TRANX_NODES 16
93 public:
94 /**
95 @param reserved_nodes
96 The number of reserved TranxNodes. It is used to set 'reserved_blocks'
97 which can contain at least 'reserved_nodes' number of TranxNodes. When
98 freeing memory, we will reserve at least reserved_blocks of Blocks not
99 freed.
100 */
101 TranxNodeAllocator(uint reserved_nodes)
102 : reserved_blocks(reserved_nodes / BLOCK_TRANX_NODES +
103 (reserved_nodes % BLOCK_TRANX_NODES > 1 ? 2 : 1)),
107 last_node(-1),
108 block_num(0) {}
109
111 Block *block = first_block;
112 while (block != nullptr) {
113 Block *next = block->next;
114 free_block(block);
115 block = next;
116 }
117 }
118
119 /**
120 The pointer of the first node after 'last_node' in current_block is
121 returned. current_block will move to the next free Block when all nodes of
122 it are in use. A new Block is allocated and is put into the rear of the
123 Block link table if no Block is free.
124
125 @return Return a TranxNode *, or NULL if an error occurred.
126 */
128 TranxNode *trx_node;
129 Block *block = current_block;
130
131 if (last_node == BLOCK_TRANX_NODES - 1) {
133 last_node = -1;
134 }
135
136 if (current_block == nullptr && allocate_block()) {
137 current_block = block;
139 return nullptr;
140 }
141
142 trx_node = &(current_block->nodes[++last_node]);
143 trx_node->log_name_[0] = '\0';
144 trx_node->log_pos_ = 0;
145 trx_node->next_ = nullptr;
146 trx_node->hash_next_ = nullptr;
147 trx_node->n_waiters = 0;
148 return trx_node;
149 }
150
151 /**
152 All nodes are freed.
153
154 @return Return 0, or 1 if an error occurred.
155 */
158 last_node = -1;
159 free_blocks();
160 return 0;
161 }
162
163 /**
164 All Blocks before the given 'node' are free Block and moved into the rear
165 of the Block link table.
166
167 @param node All nodes before 'node' will be freed
168
169 @return Return 0, or 1 if an error occurred.
170 */
172 Block *block;
173 Block *prev_block = nullptr;
174
175 block = first_block;
176 while (block != current_block->next) {
177 /* Find the Block containing the given node */
178 if (&(block->nodes[0]) <= node &&
179 &(block->nodes[BLOCK_TRANX_NODES]) >= node) {
180 /* All Blocks before the given node are put into the rear */
181 if (first_block != block) {
183 first_block = block;
184 last_block = prev_block;
185 last_block->next = nullptr;
186 free_blocks();
187 }
188 return 0;
189 }
190 prev_block = block;
191 block = block->next;
192 }
193
194 /* Node does not find should never happen */
195 assert(0);
196 return 1;
197 }
198
199 private:
201
202 /**
203 A sequence memory which contains BLOCK_TRANX_NODES TranxNodes.
204
205 BLOCK_TRANX_NODES The number of TranxNodes which are in a Block.
206
207 next Every Block has a 'next' pointer which points to the next Block.
208 These linking Blocks constitute a Block link table.
209 */
210 struct Block {
213 };
214
215 /**
216 The 'first_block' is the head of the Block link table;
217 */
219 /**
220 The 'last_block' is the rear of the Block link table;
221 */
223
224 /**
225 current_block always points the Block in the Block link table in
226 which the last allocated node is. The Blocks before it are all in use
227 and the Blocks after it are all free.
228 */
230
231 /**
232 It always points to the last node which has been allocated in the
233 current_block.
234 */
236
237 /**
238 How many Blocks are in the Block link table.
239 */
241
242 /**
243 Allocate a block and then assign it to current_block.
244 */
247 sizeof(Block), MYF(0));
248 if (block) {
249 block->next = nullptr;
250
251 if (first_block == nullptr)
252 first_block = block;
253 else
254 last_block->next = block;
255
256 /* New Block is always put into the rear */
257 last_block = block;
258 /* New Block is always the current_block */
259 current_block = block;
260 ++block_num;
261
262 for (int i = 0; i < BLOCK_TRANX_NODES; i++)
265
266 return 0;
267 }
268 return 1;
269 }
270
271 /**
272 Free a given Block.
273 @param block The Block will be freed.
274 */
275 void free_block(Block *block) {
276 for (int i = 0; i < BLOCK_TRANX_NODES; i++)
277 mysql_cond_destroy(&block->nodes[i].cond);
278 my_free(block);
279 --block_num;
280 }
281
282 /**
283 If there are some free Blocks and the total number of the Blocks in the
284 Block link table is larger than the 'reserved_blocks', Some free Blocks
285 will be freed until the total number of the Blocks is equal to the
286 'reserved_blocks' or there is only one free Block behind the
287 'current_block'.
288 */
289 void free_blocks() {
290 if (current_block == nullptr || current_block->next == nullptr) return;
291
292 /* One free Block is always kept behind the current block */
293 Block *block = current_block->next->next;
294 while (block_num > reserved_blocks && block != nullptr) {
295 Block *next = block->next;
296 free_block(block);
297 block = next;
298 }
299 current_block->next->next = block;
300 if (block == nullptr) last_block = current_block->next;
301 }
302};
303
304/**
305 This class manages memory for active transaction list.
306
307 We record each active transaction with a TranxNode, each session
308 can have only one open transaction. Because of EVENT, the total
309 active transaction nodes can exceed the maximum allowed
310 connections.
311*/
312class ActiveTranx : public Trace {
313 private:
315 /* These two record the active transaction list in sort order. */
317
318 TranxNode **trx_htb_; /* A hash table on active transactions. */
319
320 int num_entries_; /* maximum hash table entries */
321 mysql_mutex_t *lock_; /* mutex lock */
322
323 inline void assert_lock_owner();
324
325 inline unsigned int calc_hash(const unsigned char *key, unsigned int length);
326 unsigned int get_hash_value(const char *log_file_name, my_off_t log_file_pos);
327
328 int compare(const char *log_file_name1, my_off_t log_file_pos1,
329 const TranxNode *node2) {
330 return compare(log_file_name1, log_file_pos1, node2->log_name_,
331 node2->log_pos_);
332 }
333 int compare(const TranxNode *node1, const char *log_file_name2,
334 my_off_t log_file_pos2) {
335 return compare(node1->log_name_, node1->log_pos_, log_file_name2,
336 log_file_pos2);
337 }
338 int compare(const TranxNode *node1, const TranxNode *node2) {
339 return compare(node1->log_name_, node1->log_pos_, node2->log_name_,
340 node2->log_pos_);
341 }
342
343 public:
346 my_off_t log_file_pos);
348 my_off_t log_file_pos);
349 ActiveTranx(mysql_mutex_t *lock, unsigned long trace_level);
350 ~ActiveTranx();
351
352 /* Insert an active transaction node with the specified position.
353 *
354 * Return:
355 * 0: success; non-zero: error
356 */
357 int insert_tranx_node(const char *log_file_name, my_off_t log_file_pos);
358
359 /* Clear the active transaction nodes until(inclusive) the specified
360 * position.
361 * If log_file_name is NULL, everything will be cleared: the sorted
362 * list and the hash table will be reset to empty.
363 *
364 * Return:
365 * 0: success; non-zero: error
366 */
368 my_off_t log_file_pos);
369
370 /* Given a position, check to see whether the position is an active
371 * transaction's ending position by probing the hash table.
372 */
373 bool is_tranx_end_pos(const char *log_file_name, my_off_t log_file_pos);
374
375 /* Given two binlog positions, compare which one is bigger based on
376 * (file_name, file_position).
377 */
378 static int compare(const char *log_file_name1, my_off_t log_file_pos1,
379 const char *log_file_name2, my_off_t log_file_pos2);
380
381 /* Find out if active tranx node list is empty or not
382 *
383 * Return:
384 * True : If there are no nodes
385 * False: otherwise
386 */
387 bool is_empty() { return (trx_front_ == nullptr); }
388};
389
390/**
391 AckInfo is a POD. It defines a structure including information related to an
392 ack: server_id - which slave the ack comes from. binlog_name - the binlog
393 file name included in the ack. binlog_pos - the binlog file position
394 included in the ack.
395*/
396struct AckInfo {
399 unsigned long long binlog_pos = 0;
400
401 AckInfo() { clear(); }
402
403 void clear() { binlog_name[0] = '\0'; }
404 bool empty() const { return binlog_name[0] == '\0'; }
405 bool is_server(int server_id) const { return this->server_id == server_id; }
406
407 bool equal_to(const char *log_file_name, my_off_t log_file_pos) const {
409 log_file_pos) == 0);
410 }
411 bool less_than(const char *log_file_name, my_off_t log_file_pos) const {
413 log_file_pos) < 0);
414 }
415
416 void set(int server_id, const char *log_file_name, my_off_t log_file_pos) {
417 this->server_id = server_id;
418 update(log_file_name, log_file_pos);
419 }
420 void update(const char *log_file_name, my_off_t log_file_pos) {
421 strcpy(binlog_name, log_file_name);
422 binlog_pos = log_file_pos;
423 }
424};
425
426/**
427 AckContainer stores received acks internally and tell the caller the
428 ack's position when a transaction is fully acknowledged, so it can wake
429 up the waiting transactions.
430 */
431class AckContainer : public Trace {
432 public:
436 }
437
438 /** Clear the content of the ack array */
439 void clear() {
440 if (m_ack_array) {
441 for (unsigned i = 0; i < m_size; ++i) {
442 m_ack_array[i].clear();
443 m_ack_array[i].server_id = 0;
444 m_ack_array[i].binlog_pos = 0;
445 }
447 }
449 }
450
451 /**
452 Adjust capacity for the container and report the ack to semisync master,
453 if it is full.
454
455 @param[in] size size of the container.
456 @param ackinfo Acknowledgement information
457
458 @return 0 if succeeds, otherwise fails.
459 */
460 int resize(unsigned int size, const AckInfo **ackinfo);
461
462 /**
463 Insert an ack's information into the container and report the minimum
464 ack to semisync master if it is full.
465
466 @param[in] server_id slave server_id of the ack
467 @param[in] log_file_name binlog file name of the ack
468 @param[in] log_file_pos binlog file position of the ack
469
470 @return Pointer of an ack if the ack should be reported to semisync master.
471 Otherwise, NULL is returned.
472 */
473 const AckInfo *insert(int server_id, const char *log_file_name,
474 my_off_t log_file_pos);
475 const AckInfo *insert(const AckInfo &ackinfo) {
476 return insert(ackinfo.server_id, ackinfo.binlog_name, ackinfo.binlog_pos);
477 }
478
479 private:
480 /* The greatest ack of the acks already reported to semisync master. */
482
484 /* size of the array */
485 unsigned int m_size;
486 /* index of an empty slot, it helps improving insert speed. */
487 unsigned int m_empty_slot;
488
489 /* Prohibit to copy AckContainer objects */
492
493 bool full() { return m_empty_slot == m_size; }
494 unsigned int size() { return m_size; }
495
496 /**
497 Remove all acks which equal to the given position.
498
499 @param[in] log_file_name binlog name of the ack that should be removed
500 @param[in] log_file_pos binlog position of the ack that should removed
501 */
502 void remove_all(const char *log_file_name, my_off_t log_file_pos) {
503 unsigned int i = m_size;
504 for (i = 0; i < m_size; i++) {
505 if (m_ack_array[i].equal_to(log_file_name, log_file_pos)) {
506 m_ack_array[i].clear();
507 m_empty_slot = i;
508 }
509 }
510 }
511
512 /**
513 Update a slave's ack into the container if another ack of the
514 slave is already in it.
515
516 @param[in] server_id server_id of the ack
517 @param[in] log_file_name binlog file name of the ack
518 @param[in] log_file_pos binlog file position of the ack
519
520 @return index of the slot that is updated. if it equals to
521 the size of container, then no slot is updated.
522 */
523 unsigned int updateIfExist(int server_id, const char *log_file_name,
524 my_off_t log_file_pos) {
525 unsigned int i;
526
528 for (i = 0; i < m_size; i++) {
529 if (m_ack_array[i].empty())
530 m_empty_slot = i;
531 else if (m_ack_array[i].is_server(server_id)) {
532 m_ack_array[i].update(log_file_name, log_file_pos);
534 LogErr(INFORMATION_LEVEL, ER_SEMISYNC_UPDATE_EXISTING_REPLICA_ACK, i);
535 break;
536 }
537 }
538 return i;
539 }
540
541 /**
542 Find the minimum ack which is smaller than given position. When more than
543 one slots are minimum acks, it returns the one has smallest index.
544
545 @param[in] log_file_name binlog file name
546 @param[in] log_file_pos binlog file position
547
548 @return NULL if no ack is smaller than given position, otherwise
549 return its pointer.
550 */
551 AckInfo *minAck(const char *log_file_name, my_off_t log_file_pos) {
552 unsigned int i;
553 AckInfo *ackinfo = nullptr;
554
555 for (i = 0; i < m_size; i++) {
556 if (m_ack_array[i].less_than(log_file_name, log_file_pos))
557 ackinfo = m_ack_array + i;
558 }
559
560 return ackinfo;
561 }
562};
563
564/**
565 The extension class for the master of semi-synchronous replication
566*/
568 private:
570 /* active transaction list: the list will
571 be cleared when semi-sync switches off. */
572
573 /* True when initObject has been called */
574 bool init_done_ = false;
575
576 /* Mutex that protects the following state variables and the active
577 * transaction list.
578 * Under no circumstances we can acquire mysql_bin_log.LOCK_log if we are
579 * already holding LOCK_binlog_ because it can cause deadlocks.
580 */
582
583 /* This is set to true when reply_file_name_ contains meaningful data. */
585
586 /* The binlog name up to which we have received replies from any slaves. */
588
589 /* The position in that file up to which we have the reply from any slaves. */
591
592 /* This is set to true when we know the 'smallest' wait position. */
594
595 /* NULL, or the 'smallest' filename that a transaction is waiting for
596 * slave replies.
597 */
599
600 /* The smallest position in that file that a trx is waiting for: the trx
601 * can proceed and send an 'ok' to the client when the master has got the
602 * reply from the slave indicating that it already got the binlog events.
603 */
605
606 /* This is set to true when we know the 'largest' transaction commit
607 * position in the binlog file.
608 * We always maintain the position no matter whether semi-sync is switched
609 * on switched off. When a transaction wait timeout occurs, semi-sync will
610 * switch off. Binlog-dump thread can use the three fields to detect when
611 * slaves catch up on replication so that semi-sync can switch on again.
612 */
614
615 /* The 'largest' binlog filename that a commit transaction is seeing. */
617
618 /* The 'largest' position in that file that a commit transaction is seeing. */
620
621 /* All global variables which can be set by parameters. */
622 volatile bool master_enabled_ =
623 false; /* semi-sync is enabled on the master */
624 unsigned long wait_timeout_ = 0; /* timeout period(ms) during tranx wait */
625
626 bool state_ = false; /* whether semi-sync is switched */
627
629
630 void lock();
631 void unlock();
632
633 /* Is semi-sync replication on? */
634 bool is_on() { return (state_); }
635
637
638 /* Switch semi-sync off because of timeout in transaction waiting. */
639 int switch_off();
640
641 void force_switch_on();
642
643 /* Switch semi-sync on when slaves catch up. */
644 int try_switch_on(const char *log_file_name, my_off_t log_file_pos);
645
646 public:
649
651 void setTraceLevel(unsigned long trace_level) {
652 trace_level_ = trace_level;
653 ack_container_.trace_level_ = trace_level;
654 if (active_tranxs_) active_tranxs_->trace_level_ = trace_level;
655 }
656
657 /* Set if the master has to wait for an ack from the salve or not. */
658 void set_wait_no_replica(const void *val);
659
660 /* Set the transaction wait timeout period, in milliseconds. */
661 void setWaitTimeout(unsigned long wait_timeout) {
662 wait_timeout_ = wait_timeout;
663 }
664
665 /* Initialize this class after MySQL parameters are initialized. this
666 * function should be called once at bootstrap time.
667 */
668 int initObject();
669
670 /* Enable the object to enable semi-sync replication inside the master. */
671 int enableMaster();
672
673 /* Enable the object to enable semi-sync replication inside the master. */
674 int disableMaster();
675
676 /* Add a semi-sync replication slave */
677 void add_slave();
678
679 /* Remove a semi-sync replication slave */
680 void remove_slave();
681
682 /* Is the slave servered by the thread requested semi-sync */
683 bool is_semi_sync_slave();
684
685 /* It parses a reply packet and call reportReplyBinlog to handle it. */
686 int reportReplyPacket(uint32 server_id, const uchar *packet,
687 ulong packet_len);
688
689 /* In semi-sync replication, reports up to which binlog position we have
690 * received replies from the slave indicating that it already get the events
691 * or that was skipped in the master.
692 *
693 * Input:
694 * log_file_name - (IN) binlog file name
695 * end_offset - (IN) the offset in the binlog file up to which we have
696 * the replies from the slave or that was skipped
697 */
698 void reportReplyBinlog(const char *log_file_name, my_off_t end_offset);
699
700 /* Commit a transaction in the final step. This function is called from
701 * InnoDB before returning from the low commit. If semi-sync is switch on,
702 * the function will wait to see whether binlog-dump thread get the reply for
703 * the events of the transaction. Remember that this is not a direct wait,
704 * instead, it waits to see whether the binlog-dump thread has reached the
705 * point. If the wait times out, semi-sync status will be switched off and
706 * all other transaction would not wait either.
707 *
708 * Input: (the transaction events' ending binlog position)
709 * trx_wait_binlog_name - (IN) ending position's file name
710 * trx_wait_binlog_pos - (IN) ending position's file offset
711 *
712 * Return:
713 * 0: success; non-zero: error
714 */
715 int commitTrx(const char *trx_wait_binlog_name, my_off_t trx_wait_binlog_pos);
716
717 /* Reserve space in the replication event packet header:
718 * . slave semi-sync off: 1 byte - (0)
719 * . slave semi-sync on: 3 byte - (0, 0xef, 0/1}
720 *
721 * Input:
722 * header - (IN) the header buffer
723 * size - (IN) size of the header buffer
724 *
725 * Return:
726 * size of the bytes reserved for header
727 */
728 int reserveSyncHeader(unsigned char *header, unsigned long size);
729
730 /* Update the sync bit in the packet header to indicate to the slave whether
731 * the master will wait for the reply of the event. If semi-sync is switched
732 * off and we detect that the slave is catching up, we switch semi-sync on.
733 *
734 * Input:
735 * packet - (IN) the packet containing the replication event
736 * log_file_name - (IN) the event ending position's file name
737 * log_file_pos - (IN) the event ending position's file offset
738 * server_id - (IN) master server id number
739 *
740 * Return:
741 * 0: success; non-zero: error
742 */
743 int updateSyncHeader(unsigned char *packet, const char *log_file_name,
744 my_off_t log_file_pos, uint32 server_id);
745
746 /* Called when a transaction finished writing binlog events.
747 * . update the 'largest' transactions' binlog event position
748 * . insert the ending position in the active transaction list if
749 * semi-sync is on
750 *
751 * Input: (the transaction events' ending binlog position)
752 * log_file_name - (IN) transaction ending position's file name
753 * log_file_pos - (IN) transaction ending position's file offset
754 *
755 * Return:
756 * 0: success; non-zero: error
757 */
758 int writeTranxInBinlog(const char *log_file_name, my_off_t log_file_pos);
759
760 /* Read the slave's reply so that we know how much progress the slave makes
761 * on receive replication events.
762 *
763 * Input:
764 * net - (IN) the connection to master
765 * event_buf - (IN) pointer to the event packet
766 *
767 * Return:
768 * 0: success; non-zero: error
769 */
770 int readSlaveReply(NET *net, const char *event_buf);
771
772 /* In semi-sync replication, this method simulates the reception of
773 * an reply and executes reportReplyBinlog directly when a transaction
774 * is skipped in the master.
775 *
776 * Input:
777 * event_buf - (IN) pointer to the event packet
778 * server_id - (IN) master server id numbe
779 * log_file_name - (IN) the event ending position's file name
780 * log_file_pos - (IN) the event ending position's file offset
781 *
782 * Return:
783 * 0: success; non-zero: error
784 */
785 int skipSlaveReply(const char *event_buf, uint32 server_id,
786 const char *log_file_name, my_off_t log_file_pos);
787
788 /* Export internal statistics for semi-sync replication. */
789 void setExportStats();
790
791 /* 'reset master' command is issued from the user and semi-sync need to
792 * go off for that.
793 */
794 int resetMaster();
795
796 /*
797 'SET rpl_semi_sync_source_wait_for_replica_count' command is issued from
798 user and semi-sync need to update
799 rpl_semi_sync_source_wait_for_replica_count and notify ack_container_ to
800 resize itself.
801
802 @param[in] new_value The value users want to set to.
803
804 @return It returns 0 if succeeds, otherwise 1 is returned.
805 */
806 int setWaitSlaveCount(unsigned int new_value);
807
808 /*
809 Update ack_array after receiving an ack from a dump connection. If any
810 binlog pos is already replied by rpl_semi_sync_source_wait_for_replica_count
811 slaves, it will call reportReplyBinlog to increase received binlog
812 position and wake up waiting transactions. It acquires LOCK_binlog_
813 to protect the operation.
814
815 @param[in] server_id slave server_id of the ack
816 @param[in] log_file_name binlog file name of the ack
817 @param[in] log_file_pos binlog file position of the ack
818 */
819 void handleAck(int server_id, const char *log_file_name,
820 my_off_t log_file_pos) {
821 lock();
823 reportReplyBinlog(log_file_name, log_file_pos);
824 else {
825 const AckInfo *ackinfo = nullptr;
826
827 ackinfo = ack_container_.insert(server_id, log_file_name, log_file_pos);
828 if (ackinfo != nullptr)
829 reportReplyBinlog(ackinfo->binlog_name, ackinfo->binlog_pos);
830 }
831 unlock();
832 }
833};
834
835/* System and status variables for the master component */
838extern unsigned long rpl_semi_sync_source_clients;
839extern unsigned long rpl_semi_sync_source_timeout;
840extern unsigned long rpl_semi_sync_source_trace_level;
841extern unsigned long rpl_semi_sync_source_yes_transactions;
842extern unsigned long rpl_semi_sync_source_no_transactions;
843extern unsigned long rpl_semi_sync_source_off_times;
844extern unsigned long rpl_semi_sync_source_wait_timeouts;
845extern unsigned long rpl_semi_sync_source_timefunc_fails;
846extern unsigned long rpl_semi_sync_source_num_timeouts;
847extern unsigned long rpl_semi_sync_source_wait_sessions;
849extern unsigned long rpl_semi_sync_source_avg_trx_wait_time;
850extern unsigned long rpl_semi_sync_source_avg_net_wait_time;
851extern unsigned long long rpl_semi_sync_source_net_wait_num;
852extern unsigned long long rpl_semi_sync_source_trx_wait_num;
853extern unsigned long long rpl_semi_sync_source_net_wait_time;
854extern unsigned long long rpl_semi_sync_source_trx_wait_time;
855
856/*
857 This indicates whether we should keep waiting if no semi-sync slave
858 is available.
859 0 : stop waiting if detected no available semi-sync slave.
860 1 (default) : keep waiting until timeout even no available semi-sync slave.
861*/
863#endif /* SEMISYNC_SOURCE_H */
Kerberos Client Authentication nullptr
Definition: auth_kerberos_client_plugin.cc:251
AckContainer stores received acks internally and tell the caller the ack's position when a transactio...
Definition: semisync_source.h:431
AckContainer & operator=(const AckContainer &container)
const AckInfo * insert(const AckInfo &ackinfo)
Definition: semisync_source.h:475
AckInfo m_greatest_ack
Definition: semisync_source.h:481
bool full()
Definition: semisync_source.h:493
unsigned int m_empty_slot
Definition: semisync_source.h:487
unsigned int m_size
Definition: semisync_source.h:485
unsigned int updateIfExist(int server_id, const char *log_file_name, my_off_t log_file_pos)
Update a slave's ack into the container if another ack of the slave is already in it.
Definition: semisync_source.h:523
void clear()
Clear the content of the ack array.
Definition: semisync_source.h:439
const AckInfo * insert(int server_id, const char *log_file_name, my_off_t log_file_pos)
Insert an ack's information into the container and report the minimum ack to semisync master if it is...
Definition: semisync_source.cc:1194
unsigned int size()
Definition: semisync_source.h:494
~AckContainer()
Definition: semisync_source.h:434
AckInfo * minAck(const char *log_file_name, my_off_t log_file_pos)
Find the minimum ack which is smaller than given position.
Definition: semisync_source.h:551
AckInfo * m_ack_array
Definition: semisync_source.h:483
AckContainer(AckContainer &container)
void remove_all(const char *log_file_name, my_off_t log_file_pos)
Remove all acks which equal to the given position.
Definition: semisync_source.h:502
AckContainer()
Definition: semisync_source.h:433
int resize(unsigned int size, const AckInfo **ackinfo)
Adjust capacity for the container and report the ack to semisync master, if it is full.
Definition: semisync_source.cc:1243
This class manages memory for active transaction list.
Definition: semisync_source.h:312
int compare(const TranxNode *node1, const TranxNode *node2)
Definition: semisync_source.h:338
bool is_tranx_end_pos(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:196
TranxNode * trx_front_
Definition: semisync_source.h:316
int compare(const char *log_file_name1, my_off_t log_file_pos1, const TranxNode *node2)
Definition: semisync_source.h:328
int num_entries_
Definition: semisync_source.h:320
unsigned int get_hash_value(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:116
ActiveTranx(mysql_mutex_t *lock, unsigned long trace_level)
Definition: semisync_source.cc:79
TranxNode * trx_rear_
Definition: semisync_source.h:316
unsigned int calc_hash(const unsigned char *key, unsigned int length)
Definition: semisync_source.cc:103
void assert_lock_owner()
int insert_tranx_node(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:139
TranxNode ** trx_htb_
Definition: semisync_source.h:318
TranxNodeAllocator allocator_
Definition: semisync_source.h:314
mysql_mutex_t * lock_
Definition: semisync_source.h:321
bool is_empty()
Definition: semisync_source.h:387
int compare(const TranxNode *node1, const char *log_file_name2, my_off_t log_file_pos2)
Definition: semisync_source.h:333
int signal_waiting_sessions_all()
Definition: semisync_source.cc:218
~ActiveTranx()
Definition: semisync_source.cc:97
int signal_waiting_sessions_up_to(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:227
int clear_active_tranx_nodes(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:263
TranxNode * find_active_tranx_node(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:246
Base class for semi-sync master and slave classes.
Definition: semisync.h:83
The extension class for the master of semi-synchronous replication.
Definition: semisync_source.h:567
int reserveSyncHeader(unsigned char *header, unsigned long size)
Definition: semisync_source.cc:915
mysql_mutex_t LOCK_binlog_
Definition: semisync_source.h:581
my_off_t wait_file_pos_
Definition: semisync_source.h:604
int initObject()
Definition: semisync_source.cc:407
int reportReplyPacket(uint32 server_id, const uchar *packet, ulong packet_len)
Definition: semisync_source.cc:337
int resetMaster()
Definition: semisync_source.cc:1126
bool is_on()
Definition: semisync_source.h:634
unsigned long wait_timeout_
Definition: semisync_source.h:624
AckContainer ack_container_
Definition: semisync_source.h:628
bool state_
Definition: semisync_source.h:626
int setWaitSlaveCount(unsigned int new_value)
Definition: semisync_source.cc:1174
void force_switch_on()
Definition: semisync_source.cc:846
volatile bool master_enabled_
Definition: semisync_source.h:622
char reply_file_name_[FN_REFLEN]
Definition: semisync_source.h:587
void setTraceLevel(unsigned long trace_level)
Definition: semisync_source.h:651
my_off_t commit_file_pos_
Definition: semisync_source.h:619
int commitTrx(const char *trx_wait_binlog_name, my_off_t trx_wait_binlog_pos)
Definition: semisync_source.cc:636
int switch_off()
Definition: semisync_source.cc:866
void setWaitTimeout(unsigned long wait_timeout)
Definition: semisync_source.h:661
bool wait_file_name_inited_
Definition: semisync_source.h:593
void add_slave()
Definition: semisync_source.cc:517
int updateSyncHeader(unsigned char *packet, const char *log_file_name, my_off_t log_file_pos, uint32 server_id)
Definition: semisync_source.cc:938
ReplSemiSyncMaster()
Definition: semisync_source.cc:401
ActiveTranx * active_tranxs_
Definition: semisync_source.h:569
void set_wait_no_replica(const void *val)
Definition: semisync_source.cc:835
void lock()
Definition: semisync_source.cc:513
void set_master_enabled(bool enabled)
Definition: semisync_source.h:636
my_off_t reply_file_pos_
Definition: semisync_source.h:590
char wait_file_name_[FN_REFLEN]
Definition: semisync_source.h:598
int skipSlaveReply(const char *event_buf, uint32 server_id, const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:1072
int writeTranxInBinlog(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:1018
bool reply_file_name_inited_
Definition: semisync_source.h:584
~ReplSemiSyncMaster()
Definition: semisync_source.cc:505
void setExportStats()
Definition: semisync_source.cc:1156
int try_switch_on(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.cc:883
bool init_done_
Definition: semisync_source.h:574
int readSlaveReply(NET *net, const char *event_buf)
Definition: semisync_source.cc:1096
int disableMaster()
Definition: semisync_source.cc:475
bool is_semi_sync_slave()
Definition: semisync_source.cc:551
char commit_file_name_[FN_REFLEN]
Definition: semisync_source.h:616
void reportReplyBinlog(const char *log_file_name, my_off_t end_offset)
Definition: semisync_source.cc:558
int enableMaster()
Definition: semisync_source.cc:439
void remove_slave()
Definition: semisync_source.cc:523
bool commit_file_name_inited_
Definition: semisync_source.h:613
void handleAck(int server_id, const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.h:819
bool getMasterEnabled()
Definition: semisync_source.h:650
void unlock()
Definition: semisync_source.cc:515
This class is used to trace function calls and other process information.
Definition: semisync.h:43
unsigned long trace_level_
Definition: semisync.h:50
static const unsigned long kTraceDetail
Definition: semisync.h:47
This class provides memory allocating and freeing methods for TranxNode.
Definition: semisync_source.h:92
~TranxNodeAllocator()
Definition: semisync_source.h:110
TranxNodeAllocator(uint reserved_nodes)
Definition: semisync_source.h:101
int last_node
It always points to the last node which has been allocated in the current_block.
Definition: semisync_source.h:235
uint block_num
How many Blocks are in the Block link table.
Definition: semisync_source.h:240
Block * last_block
The 'last_block' is the rear of the Block link table;.
Definition: semisync_source.h:222
int free_nodes_before(TranxNode *node)
All Blocks before the given 'node' are free Block and moved into the rear of the Block link table.
Definition: semisync_source.h:171
TranxNode * allocate_node()
The pointer of the first node after 'last_node' in current_block is returned.
Definition: semisync_source.h:127
Block * current_block
current_block always points the Block in the Block link table in which the last allocated node is.
Definition: semisync_source.h:229
uint reserved_blocks
Definition: semisync_source.h:200
int allocate_block()
Allocate a block and then assign it to current_block.
Definition: semisync_source.h:245
void free_block(Block *block)
Free a given Block.
Definition: semisync_source.h:275
int free_all_nodes()
All nodes are freed.
Definition: semisync_source.h:156
Block * first_block
The 'first_block' is the head of the Block link table;.
Definition: semisync_source.h:218
void free_blocks()
If there are some free Blocks and the total number of the Blocks in the Block link table is larger th...
Definition: semisync_source.h:289
#define mysql_cond_destroy(C)
Definition: mysql_cond.h:45
#define mysql_cond_init(K, C)
Definition: mysql_cond.h:42
MYSQL_PLUGIN_IMPORT ulong server_id
Definition: log_event.h:118
unsigned int PSI_cond_key
Instrumented cond key.
Definition: psi_cond_bits.h:44
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
unsigned int PSI_mutex_key
Instrumented mutex key.
Definition: psi_mutex_bits.h:52
std::string log_file_name(const Log_files_context &ctx, Log_file_id file_id)
Provides name of the log file with the given file id, e.g.
Definition: log0files_io.cc:746
#define LogErr(severity, ecode,...)
Definition: log_builtins.h:843
Some integer typedefs for easier portability.
ulonglong my_off_t
Definition: my_inttypes.h:72
unsigned char uchar
Definition: my_inttypes.h:52
#define MYF(v)
Definition: my_inttypes.h:97
uint32_t uint32
Definition: my_inttypes.h:67
Common #defines and includes for file and socket I/O.
#define FN_REFLEN
Definition: my_io.h:83
@ INFORMATION_LEVEL
Definition: my_loglevel.h:45
void * my_malloc(PSI_memory_key key, size_t size, int flags)
Allocates size bytes of memory.
Definition: my_memory.cc:57
void my_free(void *ptr)
Frees the memory pointed by the ptr.
Definition: my_memory.cc:81
Defines various enable/disable and HAVE_ macros related to the performance schema instrumentation sys...
Definition: atomics_array.h:39
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
bool empty(const Histogram &histogram)
Return true if 'histogram' was built on an empty table.
Definition: histogram.h:693
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
size_t size(const char *const c)
Definition: base64.h:46
Definition: buffer.h:45
required string key
Definition: replication_asynchronous_connection_failover.proto:60
required bool enabled
Definition: replication_group_member_actions.proto:33
unsigned int rpl_semi_sync_source_wait_for_replica_count
Definition: semisync_source.cc:64
PSI_mutex_key key_ss_mutex_LOCK_binlog_
Definition: semisync_source_plugin.cc:490
unsigned long rpl_semi_sync_source_off_times
Definition: semisync_source.cc:51
unsigned long rpl_semi_sync_source_trace_level
Definition: semisync_source.cc:47
bool rpl_semi_sync_source_wait_no_replica
Definition: semisync_source.cc:63
PSI_cond_key key_ss_cond_COND_binlog_send_
Definition: semisync_source_plugin.cc:498
unsigned long long rpl_semi_sync_source_net_wait_time
Definition: semisync_source.cc:61
unsigned long rpl_semi_sync_source_wait_timeouts
Definition: semisync_source.cc:53
PSI_stage_info stage_waiting_for_semi_sync_replica
Definition: semisync_source_plugin.cc:527
unsigned long rpl_semi_sync_source_clients
Definition: semisync_source.cc:60
PSI_stage_info stage_reading_semi_sync_ack
Definition: semisync_source_plugin.cc:530
unsigned long rpl_semi_sync_source_timeout
Definition: semisync_source.cc:46
unsigned long rpl_semi_sync_source_num_timeouts
bool rpl_semi_sync_source_enabled
Definition: semisync_source.cc:45
unsigned long rpl_semi_sync_source_avg_net_wait_time
Definition: semisync_source.cc:58
unsigned long rpl_semi_sync_source_yes_transactions
Definition: semisync_source.cc:49
unsigned long rpl_semi_sync_source_no_transactions
Definition: semisync_source.cc:50
unsigned long rpl_semi_sync_source_wait_sessions
Definition: semisync_source.cc:54
unsigned long rpl_semi_sync_source_wait_pos_backtraverse
Definition: semisync_source.cc:55
unsigned long rpl_semi_sync_source_timefunc_fails
Definition: semisync_source.cc:52
unsigned long long rpl_semi_sync_source_trx_wait_time
Definition: semisync_source.cc:62
unsigned long long rpl_semi_sync_source_net_wait_num
Definition: semisync_source.cc:59
PSI_memory_key key_ss_memory_TranxNodeAllocator_block
Definition: semisync_source_plugin.cc:535
PSI_stage_info stage_waiting_for_semi_sync_ack_from_replica
Definition: semisync_source_plugin.cc:524
#define BLOCK_TRANX_NODES
Definition: semisync_source.h:91
unsigned long long rpl_semi_sync_source_trx_wait_num
Definition: semisync_source.cc:57
char rpl_semi_sync_source_status
Definition: semisync_source.cc:48
unsigned long rpl_semi_sync_source_avg_trx_wait_time
Definition: semisync_source.cc:56
AckInfo is a POD.
Definition: semisync_source.h:396
void update(const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.h:420
int server_id
Definition: semisync_source.h:397
bool is_server(int server_id) const
Definition: semisync_source.h:405
unsigned long long binlog_pos
Definition: semisync_source.h:399
void clear()
Definition: semisync_source.h:403
bool less_than(const char *log_file_name, my_off_t log_file_pos) const
Definition: semisync_source.h:411
void set(int server_id, const char *log_file_name, my_off_t log_file_pos)
Definition: semisync_source.h:416
bool empty() const
Definition: semisync_source.h:404
AckInfo()
Definition: semisync_source.h:401
bool equal_to(const char *log_file_name, my_off_t log_file_pos) const
Definition: semisync_source.h:407
char binlog_name[FN_REFLEN]
Definition: semisync_source.h:398
Definition: mysql_com.h:914
Stage instrument information.
Definition: psi_stage_bits.h:74
A sequence memory which contains BLOCK_TRANX_NODES TranxNodes.
Definition: semisync_source.h:210
Block * next
Definition: semisync_source.h:211
TranxNode nodes[BLOCK_TRANX_NODES]
Definition: semisync_source.h:212
Definition: semisync_source.h:49
struct TranxNode * hash_next_
Definition: semisync_source.h:55
char log_name_[FN_REFLEN]
Definition: semisync_source.h:50
my_off_t log_pos_
Definition: semisync_source.h:51
struct TranxNode * next_
Definition: semisync_source.h:54
mysql_cond_t cond
Definition: semisync_source.h:52
int n_waiters
Definition: semisync_source.h:53
An instrumented cond structure.
Definition: mysql_cond_bits.h:50
An instrumented mutex structure.
Definition: mysql_mutex_bits.h:50