YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense alongwiththisprogram;ifnot,writetotheFreeSoftware
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
struct Tranx_node { char log_name[FN_REFLEN]; bool thd_valid; /* thd is valid for signalling */
my_off_t log_pos;
THD *thd; /* The thread awaiting an ACK */ struct Tranx_node *next; /* the next node in the sorted list */ struct Tranx_node *hash_next; /* the next node during hash collision */
};
block= first_block; while (block != current_block->next)
{ /* Find the Block containing the given node */ if (&(block->nodes[0]) <= node && &(block->nodes[BLOCK_TRANX_NODES]) >= node)
{ /* All Blocks before the given node are put into the rear */ if (first_block != block)
{
last_block->next= first_block;
first_block= block;
last_block= prev_block;
last_block->next= NULL;
free_blocks();
} return0;
}
prev_block= block;
block= block->next;
}
/* Node does not find should never happen */
DBUG_ASSERT(0); return1;
}
/** Allocateablockandthenassignittocurrent_block.
*/ int allocate_block()
{
Block *block= (Block *)my_malloc(PSI_INSTRUMENT_ME, sizeof(Block), MYF(0)); if (block)
{
block->next= NULL;
if (first_block == NULL)
first_block= block; else
last_block->next= block;
/* New Block is always put into the rear */
last_block= block; /* New Block is always the current_block */
current_block= block;
++block_num; return0;
} return1;
}
/* Insert an active transaction node with the specified position. * *Return: *0:success;non-zero:error
*/ int insert_tranx_node(THD *thd_to_wait, constchar *log_file_name,
my_off_t log_file_pos);
/* Clear the active transaction nodes until(inclusive) the specified *position. *Iflog_file_nameisNULL,everythingwillbecleared:thesorted *listandthehashtablewillberesettoempty. * *Thepre_delete_hookparameterisafunctionpointerthatwillbeinvoked *foreachActive_tranxnode,inorder,fromm_trx_fronttom_trx_rear, *e.g.tosignaltheirwakeupcondition.Repl_semi_sync_binlog::LOCK_binlog *isheldwhilethisisinvoked.
*/ void clear_active_tranx_nodes(constchar *log_file_name,
my_off_t log_file_pos,
active_tranx_action pre_delete_hook);
/* Unlinks a thread from a Tranx_node, so it will not be referenced/signalled *ifitisseparatelykilled.NotethatthiskeepstheTranx_nodeitselfin *thecachesoitcanstillbeawaitedbyawait_all_slave_replies(),e.g. *asisdonebySHUTDOWNWAITFORALLSLAVES.
*/ void unlink_thd_as_waiter(constchar *log_file_name, my_off_t log_file_pos);
/* Uses DBUG_ASSERT statements to ensure that the argument thd_to_check *matchesthethreadoftherespectiveTranx_node::thdofthepassedin *log_file_nameandlog_file_pos.
*/
Tranx_node * is_thd_waiter(THD *thd_to_check, constchar *log_file_name,
my_off_t log_file_pos);
/* Given a position, check to see whether the position is an active *transaction'sendingpositionbyprobingthehashtable.
*/ bool is_tranx_end_pos(constchar *log_file_name, my_off_t log_file_pos);
/* Given two binlog positions, compare which one is bigger based on *(file_name,file_position).
*/ staticint compare(constchar *log_file_name1, my_off_t log_file_pos1, constchar *log_file_name2, my_off_t log_file_pos2);
/* Check if there are no transactions actively awaiting ACKs. Returns true *iftheinternallinkedlisthasnoentries,falseotherwise.
*/ bool is_empty() { return m_trx_front == NULL; }
};
/** Theextensionclassforthemasterofsemi-synchronousreplication
*/ class Repl_semi_sync_master
:public Repl_semi_sync_base {
Active_tranx *m_active_tranxs; /* active transaction list: the list will
be cleared when semi-sync switches off. */
/* True when init_object has been called */ bool m_init_done;
/* This cond variable is signaled when enough binlog has been sent to slave, *sothatawaitingtrxcanreturnthe'ok'totheclientforacommit.
*/
mysql_cond_t COND_binlog_send;
/* Mutex that protects the following state variables and the active *transactionlist. *Undernocirumstanceswecanacquiremysql_bin_log.LOCK_logifweare *alreadyholdingm_LOCK_binlogbecauseitcancausedeadlocks.
*/
mysql_mutex_t LOCK_binlog;
/* This is set to true when m_reply_file_name contains meaningful data. */ bool m_reply_file_name_inited;
/* The binlog name up to which we have received replies from any slaves. */ char m_reply_file_name[FN_REFLEN];
/* The position in that file up to which we have the reply from any slaves. */
my_off_t m_reply_file_pos;
/* This is set to true when we know the 'smallest' wait position. */ bool m_wait_file_name_inited;
/* NULL, or the 'smallest' filename that a transaction is waiting for *slavereplies.
*/ char m_wait_file_name[FN_REFLEN];
/* The smallest position in that file that a trx is waiting for: the trx *canproceedandsendan'ok'totheclientwhenthemasterhasgotthe *replyfromtheslaveindicatingthatitalreadygotthebinlogevents.
*/
my_off_t m_wait_file_pos;
/* This is set to true when we know the 'largest' transaction commit *positioninthebinlogfile. *Wealwaysmaintainthepositionnomatterwhethersemi-syncisswitched *onswitchedoff.Whenatransactionwaittimeoutoccurs,semi-syncwill *switchoff.Binlog-dumpthreadcanusethethreefieldstodetectwhen *slavescatchuponreplicationsothatsemi-synccanswitchonagain.
*/ bool m_commit_file_name_inited;
/* The 'largest' binlog filename that a commit transaction is seeing. */ char m_commit_file_name[FN_REFLEN];
/* The 'largest' position in that file that a commit transaction is seeing. */
my_off_t m_commit_file_pos;
/* All global variables which can be set by parameters. */ volatilebool m_master_enabled; /* semi-sync is enabled on the master */ unsignedlong m_wait_timeout; /* timeout period(ms) during tranx wait */
bool m_state; /* whether semi-sync is switched */
/*Waiting for ACK before/after innodb commit*/
ulong m_wait_point;
/*set the ACK point, after binlog sync or after transaction commit*/ void set_wait_point(unsignedlong ack_point)
{
m_wait_point = ack_point;
}
ulong wait_point() //no cover line
{ return m_wait_point; //no cover line
}
/* Initialize this class after MySQL parameters are initialized. this *functionshouldbecalledonceatbootstraptime.
*/ int init_object();
/* Enable the object to enable semi-sync replication inside the master. */ int enable_master();
/* Disable the object to disable semi-sync replication inside the master. */ void disable_master();
/* Add a semi-sync replication slave */ void add_slave();
/* Remove a semi-sync replication slave */ void remove_slave();
/* It parses a reply packet and call report_reply_binlog to handle it. */ int report_reply_packet(uint32 server_id, const uchar *packet,
ulong packet_len);
/* In semi-sync replication, reports up to which binlog position we have *receivedrepliesfromtheslaveindicatingthatitalreadygettheevents. * *Input: *server_id-(IN)masterserveridnumber *log_file_name-(IN)binlogfilename *end_offset-(IN)theoffsetinthebinlogfileuptowhichwehave *therepliesfromtheslave * *Return: *0:success;non-zero:error
*/ int report_reply_binlog(uint32 server_id, constchar* log_file_name,
my_off_t end_offset);
/* Commit a transaction in the final step. This function is called from *InnoDBbeforereturningfromthelowcommit.Ifsemi-syncisswitchon, *thefunctionwillwaittoseewhetherbinlog-dumpthreadgetthereplyfor *theeventsofthetransaction.Rememberthatthisisnotadirectwait, *instead,itwaitstoseewhetherthebinlog-dumpthreadhasreachedthe *point.Ifthewaittimesout,semi-syncstatuswillbeswitchedoffand *allothertransactionwouldnotwaiteither. * *Input:(thetransactionevents'endingbinlogposition) *trx_wait_binlog_name-(IN)endingposition'sfilename *trx_wait_binlog_pos-(IN)endingposition'sfileoffset * *Return: *0:success;non-zero:error
*/ int commit_trx(constchar* trx_wait_binlog_name,
my_off_t trx_wait_binlog_pos);
/*Wait for ACK after writing/sync binlog to file*/ int wait_after_sync(constchar* log_file, my_off_t log_pos);
/*Wait for ACK after committing the transaction*/ int wait_after_commit(THD* thd, bool all);
/*Wait after the transaction is rollback*/ int wait_after_rollback(THD *thd, bool all); /* Store the current binlog position in m_active_tranxs. This position should *beackedbyslave. * *Inputs: *trans_thdThreadofthetransactionwhichisexecutingthe *transaction. *waiter_thdThreadthatwillwaitfortheACKfromtheslave, *whichdependsonthesemi-syncwaitpoint.IfAFTER_SYNC, *andalsousingbinloggroupcommit,thiswillbetheleader *threadofthebinlogcommit.Otherwise,itisthethreadthat *isexecutingthetransaction,i.e.thesameastrans_thd. *log_fileNameofthebinlogfilethatthetransactioniswritteninto *log_posOffsetwithinthebinlogfilethatthetransactioniswritten *at
*/ int report_binlog_update(THD *trans_thd, THD *waiter_thd, constchar *log_file, my_off_t log_pos);
int dump_start(THD* thd, constchar *log_file,
my_off_t log_pos);
void dump_end(THD* thd);
/* Reserve space in the replication event packet header: *.slavesemi-syncoff:1byte-(0) *.slavesemi-syncon:3byte-(0,0xef,0/1} * *Input: *packet-(IN)theheaderbuffer * *Return: *sizeofthebytesreservedforheader
*/ int reserve_sync_header(String* packet);
/* Update the sync bit in the packet header to indicate to the slave whether *themasterwillwaitforthereplyoftheevent.Ifsemi-syncisswitched *offandwedetectthattheslaveiscatchingup,weswitchsemi-syncon. * *Input: *THD-(IN)currentdumpthread *packet-(IN)thepacketcontainingthereplicationevent *log_file_name-(IN)theeventendingposition'sfilename *log_file_pos-(IN)theeventendingposition'sfileoffset *need_sync-(IN)identifyifflush_netisneededtocall. *server_id-(IN)masterserveridnumber * *Return: *0:success;non-zero:error
*/ int update_sync_header(THD* thd, unsignedchar *packet, constchar *log_file_name,
my_off_t log_file_pos, bool* need_sync);
/* Called when a transaction finished writing binlog events. *.updatethe'largest'transactions'binlogeventposition *.inserttheendingpositionintheactivetransactionlistif *semi-syncison * *Input:(thetransactionevents'endingbinlogposition) *THD-(IN)threadthatwillwaitforanACK.Thiscanbethe *binlogleaderthreadwhenusingwait_point *AFTER_SYNCwithbinloggroupcommit.Inallother *cases,thisistheuserthreadexecutingthe *transaction. *log_file_name-(IN)transactionendingposition'sfilename *log_file_pos-(IN)transactionendingposition'sfileoffset * *Return: *0:success;non-zero:error
*/ int write_tranx_in_binlog(THD *thd, constchar *log_file_name,
my_off_t log_file_pos);
/* Read the slave's reply so that we know how much progress the slave makes *onreceivereplicationevents.
*/ int flush_net(THD* thd, constchar *event_buf);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.19Bemerkung:
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.