1 #ifndef BINLOG_H_INCLUDED
2 /* Copyright (c) 2010, 2021, 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 also distributed 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 included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software Foundation,
22    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23 
24 #define BINLOG_H_INCLUDED
25 
26 #include "sql_class.h"
27 #include "my_global.h"
28 #include "m_string.h"                  // llstr
29 #include "binlog_event.h"              // enum_binlog_checksum_alg
30 #include "mysqld.h"                    // opt_relay_logname
31 #include "tc_log.h"                    // TC_LOG
32 #include "atomic_class.h"
33 #include "rpl_gtid.h"                  // Gtid_set, Sid_map
34 #include "rpl_trx_tracking.h"
35 #include "rpl_constants.h"
36 #include "binlog_crypt_data.h"
37 
38 
39 class Relay_log_info;
40 class Master_info;
41 class Slave_worker;
42 class Format_description_log_event;
43 class Transaction_boundary_parser;
44 class Rows_log_event;
45 class Rows_query_log_event;
46 class Incident_log_event;
47 class Log_event;
48 class Gtid_set;
49 struct Gtid;
50 
51 typedef int64 query_id_t;
52 
53 
54 /**
55   Class for maintaining the commit stages for binary log group commit.
56  */
57 class Stage_manager {
58 public:
59   class Mutex_queue {
60     friend class Stage_manager;
61   public:
Mutex_queue()62     Mutex_queue()
63       : m_first(NULL), m_last(&m_first), m_size(0)
64     {
65     }
66 
init(PSI_mutex_key key_LOCK_queue)67     void init(
68 #ifdef HAVE_PSI_INTERFACE
69               PSI_mutex_key key_LOCK_queue
70 #endif
71               ) {
72       mysql_mutex_init(key_LOCK_queue, &m_lock, MY_MUTEX_INIT_FAST);
73     }
74 
deinit()75     void deinit() {
76       mysql_mutex_destroy(&m_lock);
77     }
78 
is_empty()79     bool is_empty() const {
80       return m_first == NULL;
81     }
82 
83     /**
84       Append a linked list of threads to the queue.
85       @retval true The queue was empty before this operation.
86       @retval false The queue was non-empty before this operation.
87     */
88     bool append(THD *first);
89 
90     /**
91        Fetch the entire queue for a stage.
92 
93        This will fetch the entire queue in one go.
94     */
95     THD *fetch_and_empty();
96 
97     std::pair<bool,THD*> pop_front();
98 
get_size()99     inline int32 get_size()
100     {
101       return my_atomic_load32(&m_size);
102     }
103 
104   private:
lock()105     void lock() { mysql_mutex_lock(&m_lock); }
unlock()106     void unlock() { mysql_mutex_unlock(&m_lock); }
107 
108     /**
109        Pointer to the first thread in the queue, or NULL if the queue is
110        empty.
111     */
112     THD *m_first;
113 
114     /**
115        Pointer to the location holding the end of the queue.
116 
117        This is either @c &first, or a pointer to the @c next_to_commit of
118        the last thread that is enqueued.
119     */
120     THD **m_last;
121 
122     /** size of the queue */
123     int32 m_size;
124 
125     /** Lock for protecting the queue. */
126     mysql_mutex_t m_lock;
127     /*
128       This attribute did not have the desired effect, at least not according
129       to -fsanitize=undefined with gcc 5.2.1
130       Also: it fails to compile with gcc 7.2
131      */
132   }; // MY_ATTRIBUTE((aligned(CPU_LEVEL1_DCACHE_LINESIZE)));
133 
134 public:
Stage_manager()135   Stage_manager()
136   {
137   }
138 
~Stage_manager()139   ~Stage_manager()
140   {
141   }
142 
143   /**
144      Constants for queues for different stages.
145    */
146   enum StageID {
147     FLUSH_STAGE,
148     SYNC_STAGE,
149     COMMIT_STAGE,
150     STAGE_COUNTER
151   };
152 
init(PSI_mutex_key key_LOCK_flush_queue,PSI_mutex_key key_LOCK_sync_queue,PSI_mutex_key key_LOCK_commit_queue,PSI_mutex_key key_LOCK_done,PSI_cond_key key_COND_done)153   void init(
154 #ifdef HAVE_PSI_INTERFACE
155             PSI_mutex_key key_LOCK_flush_queue,
156             PSI_mutex_key key_LOCK_sync_queue,
157             PSI_mutex_key key_LOCK_commit_queue,
158             PSI_mutex_key key_LOCK_done,
159             PSI_cond_key key_COND_done
160 #endif
161             )
162   {
163     mysql_mutex_init(key_LOCK_done, &m_lock_done, MY_MUTEX_INIT_FAST);
164     mysql_cond_init(key_COND_done, &m_cond_done);
165 #ifndef NDEBUG
166     /* reuse key_COND_done 'cos a new PSI object would be wasteful in !NDEBUG */
167     mysql_cond_init(key_COND_done, &m_cond_preempt);
168 #endif
169     m_queue[FLUSH_STAGE].init(
170 #ifdef HAVE_PSI_INTERFACE
171                               key_LOCK_flush_queue
172 #endif
173                               );
174     m_queue[SYNC_STAGE].init(
175 #ifdef HAVE_PSI_INTERFACE
176                              key_LOCK_sync_queue
177 #endif
178                              );
179     m_queue[COMMIT_STAGE].init(
180 #ifdef HAVE_PSI_INTERFACE
181                                key_LOCK_commit_queue
182 #endif
183                                );
184   }
185 
deinit()186   void deinit()
187   {
188     for (size_t i = 0 ; i < STAGE_COUNTER ; ++i)
189       m_queue[i].deinit();
190     mysql_cond_destroy(&m_cond_done);
191     mysql_mutex_destroy(&m_lock_done);
192   }
193 
194   /**
195     Enroll a set of sessions for a stage.
196 
197     This will queue the session thread for writing and flushing.
198 
199     If the thread being queued is assigned as stage leader, it will
200     return immediately.
201 
202     If wait_if_follower is true the thread is not the stage leader,
203     the thread will be wait for the queue to be processed by the
204     leader before it returns.
205     In DBUG-ON version the follower marks is preempt status as ready.
206 
207     @param stage Stage identifier for the queue to append to.
208     @param first Queue to append.
209     @param stage_mutex
210                  Pointer to the currently held stage mutex, or NULL if
211                  we're not in a stage.
212 
213     @retval true  Thread is stage leader.
214     @retval false Thread was not stage leader and processing has been done.
215    */
216   bool enroll_for(StageID stage, THD *first, mysql_mutex_t *stage_mutex);
217 
pop_front(StageID stage)218   std::pair<bool,THD*> pop_front(StageID stage)
219   {
220     return m_queue[stage].pop_front();
221   }
222 
223 #ifndef NDEBUG
224   /**
225      The method ensures the follower's execution path can be preempted
226      by the leader's thread.
227      Preempt status of @c head follower is checked to engange the leader
228      into waiting when set.
229 
230      @param head  THD* of a follower thread
231   */
232   void clear_preempt_status(THD *head);
233 #endif
234 
235   /**
236     Fetch the entire queue and empty it.
237 
238     @return Pointer to the first session of the queue.
239    */
fetch_queue_for(StageID stage)240   THD *fetch_queue_for(StageID stage) {
241     DBUG_PRINT("debug", ("Fetching queue for stage %d", stage));
242     return m_queue[stage].fetch_and_empty();
243   }
244 
245   /**
246     Introduces a wait operation on the executing thread.  The
247     waiting is done until the timeout elapses or count is
248     reached (whichever comes first).
249 
250     If count == 0, then the session will wait until the timeout
251     elapses. If timeout == 0, then there is no waiting.
252 
253     @param usec     the number of microseconds to wait.
254     @param count    wait for as many as count to join the queue the
255                     session is waiting on
256     @param stage    which stage queue size to compare count against.
257    */
258   void wait_count_or_timeout(ulong count, long usec, StageID stage);
259 
260   void signal_done(THD *queue);
261 
262 private:
263   /**
264      Queues for sessions.
265 
266      We need two queues:
267      - Waiting. Threads waiting to be processed
268      - Committing. Threads waiting to be committed.
269    */
270   Mutex_queue m_queue[STAGE_COUNTER];
271 
272   /** Condition variable to indicate that the commit was processed */
273   mysql_cond_t m_cond_done;
274 
275   /** Mutex used for the condition variable above */
276   mysql_mutex_t m_lock_done;
277 #ifndef NDEBUG
278   /** Flag is set by Leader when it starts waiting for follower's all-clear */
279   bool leader_await_preempt_status;
280 
281   /** Condition variable to indicate a follower started waiting for commit */
282   mysql_cond_t m_cond_preempt;
283 #endif
284 };
285 
286 /* log info errors */
287 #define LOG_INFO_EOF -1
288 #define LOG_INFO_IO  -2
289 #define LOG_INFO_INVALID -3
290 #define LOG_INFO_SEEK -4
291 #define LOG_INFO_MEM -6
292 #define LOG_INFO_FATAL -7
293 #define LOG_INFO_IN_USE -8
294 #define LOG_INFO_EMFILE -9
295 
296 /* bitmap to MYSQL_BIN_LOG::close() */
297 #define LOG_CLOSE_INDEX		1
298 #define LOG_CLOSE_TO_BE_OPENED	2
299 #define LOG_CLOSE_STOP_EVENT	4
300 
301 
302 /*
303   Note that we destroy the lock mutex in the destructor here.
304   This means that object instances cannot be destroyed/go out of scope
305   until we have reset thd->current_linfo to NULL;
306  */
307 typedef struct st_log_info
308 {
309   char log_file_name[FN_REFLEN];
310   my_off_t index_file_offset, index_file_start_offset;
311   my_off_t pos;
312   bool fatal; // if the purge happens to give us a negative offset
313   int entry_index; //used in purge_logs(), calculatd in find_log_pos().
st_log_infost_log_info314   st_log_info()
315     : index_file_offset(0), index_file_start_offset(0),
316       pos(0), fatal(0), entry_index(0)
317     {
318       memset(log_file_name, 0, FN_REFLEN);
319     }
320 } LOG_INFO;
321 
322 /*
323   TODO use mmap instead of IO_CACHE for binlog
324   (mmap+fsync is two times faster than write+fsync)
325 */
326 
327 class MYSQL_BIN_LOG: public TC_LOG
328 {
329   enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
330 
331   /* LOCK_log is inited by init_pthread_objects() */
332   mysql_mutex_t LOCK_log;
333   char *name;
334   char log_file_name[FN_REFLEN];
335   char db[NAME_LEN + 1];
336   bool write_error, inited;
337   IO_CACHE log_file;
338   const enum cache_type io_cache_type;
339 #ifdef HAVE_PSI_INTERFACE
340   /** Instrumentation key to use for file io in @c log_file */
341   PSI_file_key m_log_file_key;
342   /** The instrumentation key to use for @ LOCK_log. */
343   PSI_mutex_key m_key_LOCK_log;
344   /** The instrumentation key to use for @ LOCK_index. */
345   PSI_mutex_key m_key_LOCK_index;
346   /** The instrumentation key to use for @ LOCK_binlog_end_pos. */
347   PSI_mutex_key m_key_LOCK_binlog_end_pos;
348 
349   PSI_mutex_key m_key_COND_done;
350 
351   PSI_mutex_key m_key_LOCK_commit_queue;
352   PSI_mutex_key m_key_LOCK_done;
353   PSI_mutex_key m_key_LOCK_flush_queue;
354   PSI_mutex_key m_key_LOCK_sync_queue;
355   /** The instrumentation key to use for @ LOCK_commit. */
356   PSI_mutex_key m_key_LOCK_commit;
357   /** The instrumentation key to use for @ LOCK_sync. */
358   PSI_mutex_key m_key_LOCK_sync;
359   /** The instrumentation key to use for @ LOCK_xids. */
360   PSI_mutex_key m_key_LOCK_xids;
361   /** The instrumentation key to use for @ update_cond. */
362   PSI_cond_key m_key_update_cond;
363   /** The instrumentation key to use for @ prep_xids_cond. */
364   PSI_cond_key m_key_prep_xids_cond;
365   /** The instrumentation key to use for opening the log file. */
366   PSI_file_key m_key_file_log;
367   /** The instrumentation key to use for opening the log index file. */
368   PSI_file_key m_key_file_log_index;
369   /** The instrumentation key to use for opening a log cache file. */
370   PSI_file_key m_key_file_log_cache;
371   /** The instrumentation key to use for opening a log index cache file. */
372   PSI_file_key m_key_file_log_index_cache;
373 #endif
374   /* POSIX thread objects are inited by init_pthread_objects() */
375   mysql_mutex_t LOCK_index;
376   mysql_mutex_t LOCK_commit;
377   mysql_mutex_t LOCK_sync;
378   mysql_mutex_t LOCK_binlog_end_pos;
379   mysql_mutex_t LOCK_xids;
380   mysql_cond_t update_cond;
381 
382   my_off_t binlog_end_pos;
383   ulonglong bytes_written;
384   ulonglong binlog_space_total;
385   IO_CACHE index_file;
386   char index_file_name[FN_REFLEN];
387   /*
388     crash_safe_index_file is temp file used for guaranteeing
389     index file crash safe when master server restarts.
390   */
391   IO_CACHE crash_safe_index_file;
392   char crash_safe_index_file_name[FN_REFLEN];
393   /*
394     purge_file is a temp file used in purge_logs so that the index file
395     can be updated before deleting files from disk, yielding better crash
396     recovery. It is created on demand the first time purge_logs is called
397     and then reused for subsequent calls. It is cleaned up in cleanup().
398   */
399   IO_CACHE purge_index_file;
400   char purge_index_file_name[FN_REFLEN];
401   /*
402      The max size before rotation (usable only if log_type == LOG_BIN: binary
403      logs and relay logs).
404      For a binlog, max_size should be max_binlog_size.
405      For a relay log, it should be max_relay_log_size if this is non-zero,
406      max_binlog_size otherwise.
407      max_size is set in init(), and dynamically changed (when one does SET
408      GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
409      fix_max_relay_log_size).
410   */
411   ulong max_size;
412 
413   // current file sequence number for load data infile binary logging
414   uint file_id;
415   uint open_count;				// For replication
416   int readers_count;
417 
418   /* binlog encryption data */
419   Binlog_crypt_data crypto;
420 
421   /* pointer to the sync period variable, for binlog this will be
422      sync_binlog_period, for relay log this will be
423      sync_relay_log_period
424   */
425   uint *sync_period_ptr;
426   uint sync_counter;
427 
428   mysql_cond_t m_prep_xids_cond;
429   Atomic_int32 m_prep_xids;
430 
431   /**
432     Increment the prepared XID counter.
433    */
434   void inc_prep_xids(THD *thd);
435 
436   /**
437     Decrement the prepared XID counter.
438 
439     Signal m_prep_xids_cond if the counter reaches zero.
440    */
441   void dec_prep_xids(THD *thd);
442 
get_prep_xids()443   int32 get_prep_xids() {
444     int32 result= m_prep_xids.atomic_get();
445     return result;
446   }
447 
get_sync_period()448   inline uint get_sync_period()
449   {
450     return *sync_period_ptr;
451   }
452 
453   int write_to_file(Log_event* event);
454 
455   int write_to_file(IO_CACHE *cache);
456   /*
457     This is used to start writing to a new log file. The difference from
458     new_file() is locking. new_file_without_locking() does not acquire
459     LOCK_log.
460   */
461   int new_file_without_locking(Format_description_log_event *extra_description_event);
462   int new_file_impl(bool need_lock, Format_description_log_event *extra_description_event);
463 
464   /** Manage the stages in ordered_commit. */
465   Stage_manager stage_manager;
466   void do_flush(THD *thd);
467 
468   bool open(
469 #ifdef HAVE_PSI_INTERFACE
470             PSI_file_key log_file_key,
471 #endif
472             const char *log_name,
473             const char *new_name);
474   bool init_and_set_log_file_name(const char *log_name,
475                                   const char *new_name);
476   int generate_new_name(char *new_name, const char *log_name);
477 
478 public:
479   const char *generate_name(const char *log_name, const char *suffix,
480                             char *buff);
is_open()481   bool is_open() { return log_state.atomic_get() != LOG_CLOSED; }
482 
483   /* This is relay log */
484   bool is_relay_log;
485   ulong signal_cnt;  // update of the counter is checked by heartbeat
486   uint8 checksum_alg_reset; // to contain a new value when binlog is rotated
487   /*
488     Holds the last seen in Relay-Log FD's checksum alg value.
489     The initial value comes from the slave's local FD that heads
490     the very first Relay-Log file. In the following the value may change
491     with each received master's FD_m.
492     Besides to be used in verification events that IO thread receives
493     (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd),
494     the value specifies if/how to compute checksum for slave's local events
495     and the first fake Rotate (R_f^1) coming from the master.
496     R_f^1 needs logging checksum-compatibly with the RL's heading FD_s.
497 
498     Legends for the checksum related comments:
499 
500     FD     - Format-Description event,
501     R      - Rotate event
502     R_f    - the fake Rotate event
503     E      - an arbirary event
504 
505     The underscore indexes for any event
506     `_s'   indicates the event is generated by Slave
507     `_m'   - by Master
508 
509     Two special underscore indexes of FD:
510     FD_q   - Format Description event for queuing   (relay-logging)
511     FD_e   - Format Description event for executing (relay-logging)
512 
513     Upper indexes:
514     E^n    - n:th event is a sequence
515 
516     RL     - Relay Log
517     (A)    - checksum algorithm descriptor value
518     FD.(A) - the value of (A) in FD
519   */
520   binary_log::enum_binlog_checksum_alg relay_log_checksum_alg;
521 
522   MYSQL_BIN_LOG(uint *sync_period,
523                 enum cache_type io_cache_type_arg);
524   /*
525     note that there's no destructor ~MYSQL_BIN_LOG() !
526     The reason is that we don't want it to be automatically called
527     on exit() - but only during the correct shutdown process
528   */
529 
530 #ifdef HAVE_PSI_INTERFACE
set_psi_keys(PSI_mutex_key key_LOCK_index,PSI_mutex_key key_LOCK_commit,PSI_mutex_key key_LOCK_commit_queue,PSI_mutex_key key_LOCK_done,PSI_mutex_key key_LOCK_flush_queue,PSI_mutex_key key_LOCK_log,PSI_mutex_key key_LOCK_binlog_end_pos,PSI_mutex_key key_LOCK_sync,PSI_mutex_key key_LOCK_sync_queue,PSI_mutex_key key_LOCK_xids,PSI_cond_key key_COND_done,PSI_cond_key key_update_cond,PSI_cond_key key_prep_xids_cond,PSI_file_key key_file_log,PSI_file_key key_file_log_index,PSI_file_key key_file_log_cache,PSI_file_key key_file_log_index_cache)531   void set_psi_keys(PSI_mutex_key key_LOCK_index,
532                     PSI_mutex_key key_LOCK_commit,
533                     PSI_mutex_key key_LOCK_commit_queue,
534                     PSI_mutex_key key_LOCK_done,
535                     PSI_mutex_key key_LOCK_flush_queue,
536                     PSI_mutex_key key_LOCK_log,
537                     PSI_mutex_key key_LOCK_binlog_end_pos,
538                     PSI_mutex_key key_LOCK_sync,
539                     PSI_mutex_key key_LOCK_sync_queue,
540                     PSI_mutex_key key_LOCK_xids,
541                     PSI_cond_key key_COND_done,
542                     PSI_cond_key key_update_cond,
543                     PSI_cond_key key_prep_xids_cond,
544                     PSI_file_key key_file_log,
545                     PSI_file_key key_file_log_index,
546                     PSI_file_key key_file_log_cache,
547                     PSI_file_key key_file_log_index_cache)
548   {
549     m_key_COND_done= key_COND_done;
550 
551     m_key_LOCK_commit_queue= key_LOCK_commit_queue;
552     m_key_LOCK_done= key_LOCK_done;
553     m_key_LOCK_flush_queue= key_LOCK_flush_queue;
554     m_key_LOCK_sync_queue= key_LOCK_sync_queue;
555 
556     m_key_LOCK_index= key_LOCK_index;
557     m_key_LOCK_log= key_LOCK_log;
558     m_key_LOCK_binlog_end_pos= key_LOCK_binlog_end_pos;
559     m_key_LOCK_commit= key_LOCK_commit;
560     m_key_LOCK_sync= key_LOCK_sync;
561     m_key_LOCK_xids= key_LOCK_xids;
562     m_key_update_cond= key_update_cond;
563     m_key_prep_xids_cond= key_prep_xids_cond;
564     m_key_file_log= key_file_log;
565     m_key_file_log_index= key_file_log_index;
566     m_key_file_log_cache= key_file_log_cache;
567     m_key_file_log_index_cache= key_file_log_index_cache;
568   }
569 #endif
570 
571 public:
572   /** Manage the MTS dependency tracking */
573   Transaction_dependency_tracker m_dependency_tracker;
574 
575   /**
576     Find the oldest binary log that contains any GTID that
577     is not in the given gtid set.
578 
579     @param[out] binlog_file_name, the file name of oldest binary log found
580     @param[in]  gtid_set, the given gtid set
581     @param[out] first_gtid, the first GTID information from the binary log
582                 file returned at binlog_file_name
583     @param[out] errmsg, the error message outputted, which is left untouched
584                 if the function returns false
585     @return false on success, true on error.
586   */
587   bool find_first_log_not_in_gtid_set(char *binlog_file_name,
588                                       const Gtid_set *gtid_set,
589                                       Gtid *first_gtid, std::string &errmsg);
590 
591   /**
592     Reads the set of all GTIDs in the binary/relay log, and the set
593     of all lost GTIDs in the binary log, and stores each set in
594     respective argument.
595 
596     @param gtid_set Will be filled with all GTIDs in this binary/relay
597     log.
598     @param lost_groups Will be filled with all GTIDs in the
599     Previous_gtids_log_event of the first binary log that has a
600     Previous_gtids_log_event. This is requested to binary logs but not
601     to relay logs.
602     @param verify_checksum If true, checksums will be checked.
603     @param need_lock If true, LOCK_log, LOCK_index, and
604     global_sid_lock->wrlock are acquired; otherwise they are asserted
605     to be taken already.
606     @param trx_parser [out] This will be used to return the actual
607     relaylog transaction parser state because of the possibility
608     of partial transactions.
609     @param [out] gtid_partial_trx If a transaction was left incomplete
610     on the relaylog, it's GTID should be returned to be used in the
611     case of the rest of the transaction be added to the relaylog.
612     @param is_server_starting True if the server is starting.
613     @return false on success, true on error.
614   */
615   bool init_gtid_sets(Gtid_set *gtid_set, Gtid_set *lost_groups,
616                       bool verify_checksum,
617                       bool need_lock,
618                       Transaction_boundary_parser *trx_parser,
619                       Gtid *gtid_partial_trx,
620                       bool is_server_starting= false);
621 
set_previous_gtid_set_relaylog(Gtid_set * previous_gtid_set_param)622   void set_previous_gtid_set_relaylog(Gtid_set *previous_gtid_set_param)
623   {
624     assert(is_relay_log);
625     previous_gtid_set_relaylog= previous_gtid_set_param;
626   }
627   /**
628     If the thread owns a GTID, this function generates an empty
629     transaction and releases ownership of the GTID.
630 
631     - If the binary log is disabled for this thread, the GTID is
632       inserted directly into the mysql.gtid_executed table and the
633       GTID is included in @@global.gtid_executed.  (This only happens
634       for DDL, since DML will save the GTID into table and release
635       ownership inside ha_commit_trans.)
636 
637     - If the binary log is enabled for this thread, an empty
638       transaction consisting of GTID, BEGIN, COMMIT is written to the
639       binary log, the GTID is included in @@global.gtid_executed, and
640       the GTID is added to the mysql.gtid_executed table on the next
641       binlog rotation.
642 
643     This function must be called by any committing statement (COMMIT,
644     implicitly committing statements, or Xid_log_event), after the
645     statement has completed execution, regardless of whether the
646     statement updated the database.
647 
648     This logic ensures that an empty transaction is generated for the
649     following cases:
650 
651     - Explicit empty transaction:
652       SET GTID_NEXT = 'UUID:NUMBER'; BEGIN; COMMIT;
653 
654     - Transaction or DDL that gets completely filtered out in the
655       slave thread.
656 
657     @param thd The committing thread
658 
659     @retval 0 Success
660     @retval nonzero Error
661   */
662   int gtid_end_transaction(THD *thd);
663 private:
664   Atomic_int32 log_state; /* atomic enum_log_state */
665 
666   /* The previous gtid set in relay log. */
667   Gtid_set* previous_gtid_set_relaylog;
668 
669   bool snapshot_lock_acquired;
670 
open(const char * opt_name)671   int open(const char *opt_name) { return open_binlog(opt_name); }
672   bool change_stage(THD *thd, Stage_manager::StageID stage,
673                     THD* queue, mysql_mutex_t *leave,
674                     mysql_mutex_t *enter);
675   std::pair<int,my_off_t> flush_thread_caches(THD *thd);
676   int flush_cache_to_file(my_off_t *flush_end_pos);
677   int finish_commit(THD *thd);
678   std::pair<bool, bool> sync_binlog_file(bool force);
679   void process_commit_stage_queue(THD *thd, THD *queue);
680   void process_after_commit_stage_queue(THD *thd, THD *first);
681   int process_flush_stage_queue(my_off_t *total_bytes_var, bool *rotate_var,
682                                 THD **out_queue_var);
683   int prepare_ordered_commit(THD *thd, bool all, bool skip_commit= false);
684   int ordered_commit(THD *thd);
685   void handle_binlog_flush_or_sync_error(THD *thd, bool need_lock_log,
686                                          const char *message);
687 public:
688   int open_binlog(const char *opt_name);
689   void close();
690   enum_result commit(THD *thd, bool all);
691   int rollback(THD *thd, bool all);
692   int prepare(THD *thd, bool all);
693   int recover(IO_CACHE *log, Format_description_log_event *fdle,
694               my_off_t *valid_pos);
695   int recover(IO_CACHE *log, Format_description_log_event *fdle);
696 #if !defined(MYSQL_CLIENT)
697 
698   void update_thd_next_event_pos(THD *thd);
699   int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
700                                        bool is_transactional);
701   void xlock(void);
702   void xunlock(void);
slock(void)703   void slock(void) { mysql_rwlock_rdlock(&LOCK_consistent_snapshot); }
sunlock(void)704   void sunlock(void) { mysql_rwlock_unlock(&LOCK_consistent_snapshot); }
705 #else
xlock(void)706   void xlock(void) { }
xunlock(void)707   void xunlock(void) { }
slock(void)708   void slock(void) { }
sunlock(void)709   void sunlock(void) { }
710 #endif /* !defined(MYSQL_CLIENT) */
add_bytes_written(ulonglong inc)711   void add_bytes_written(ulonglong inc)
712   {
713     bytes_written += inc;
714   }
reset_bytes_written()715   void reset_bytes_written()
716   {
717     bytes_written = 0;
718   }
719   void harvest_bytes_written(Relay_log_info *rli, bool need_log_space_lock);
720   void set_max_size(ulong max_size_arg);
signal_update()721   void signal_update()
722   {
723     DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
724     signal_cnt++;
725     mysql_cond_broadcast(&update_cond);
726     DBUG_VOID_RETURN;
727   }
728 
update_binlog_end_pos()729   void update_binlog_end_pos()
730   {
731     /*
732       binlog_end_pos is used only on master's binlog right now. It is possible
733       to use it on relay log.
734     */
735     if (is_relay_log)
736       signal_update();
737     else
738     {
739       lock_binlog_end_pos();
740       binlog_end_pos= my_b_tell(&log_file);
741       signal_update();
742       unlock_binlog_end_pos();
743     }
744   }
745 
update_binlog_end_pos(const char * file,my_off_t pos)746   void update_binlog_end_pos(const char *file, my_off_t pos)
747   {
748     lock_binlog_end_pos();
749     if (is_active(file) && pos > binlog_end_pos)
750       binlog_end_pos= pos;
751     signal_update();
752     unlock_binlog_end_pos();
753   }
754 
755   int wait_for_update_relay_log(THD* thd, const struct timespec * timeout);
756   int wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
757   bool do_write_cache(IO_CACHE *cache, class Binlog_event_writer *writer);
758 public:
759   void init_pthread_objects();
760   void cleanup();
761   /**
762     Create a new binary log.
763     @param log_name Name of binlog
764     @param new_name Name of binlog, too. todo: what's the difference
765     between new_name and log_name?
766     @param max_size The size at which this binlog will be rotated.
767     @param null_created If false, and a Format_description_log_event
768     is written, then the Format_description_log_event will have the
769     timestamp 0. Otherwise, it the timestamp will be the time when the
770     event was written to the log.
771     @param need_lock_index If true, LOCK_index is acquired; otherwise
772     LOCK_index must be taken by the caller.
773     @param need_sid_lock If true, the read lock on global_sid_lock
774     will be acquired.  Otherwise, the caller must hold the read lock
775     on global_sid_lock.
776   */
777   bool open_binlog(const char *log_name,
778                    const char *new_name,
779                    ulong max_size,
780                    bool null_created,
781                    bool need_lock_index, bool need_sid_lock,
782                    Format_description_log_event *extra_description_event);
783   bool open_index_file(const char *index_file_name_arg,
784                        const char *log_name, bool need_lock_index);
785   /* Use this to start writing a new log file */
786   int new_file(Format_description_log_event *extra_description_event);
787 
788   bool write_event(Log_event* event_info);
789   bool write_cache(THD *thd, class binlog_cache_data *binlog_cache_data,
790                    class Binlog_event_writer *writer);
791   /**
792     Assign automatic generated GTIDs for all commit group threads in the flush
793     stage having gtid_next.type == AUTOMATIC_GROUP.
794 
795     @param first_seen The first thread seen entering the flush stage.
796     @return Returns false if succeeds, otherwise true is returned.
797   */
798   bool assign_automatic_gtids_to_flush_group(THD *first_seen);
799   bool write_gtid(THD *thd, binlog_cache_data *cache_data,
800                   class Binlog_event_writer *writer);
801 
802   /**
803      Write a dml into statement cache and then flush it into binlog. It writes
804      Gtid_log_event and BEGIN, COMMIT automatically.
805 
806      It is aimed to handle cases of "background" logging where a statement is
807      logged indirectly, like "TRUNCATE TABLE a_memory_table". So don't use it on any
808      normal statement.
809 
810      @param[IN] thd  the THD object of current thread.
811      @param[IN] stmt the DML statement.
812      @param[IN] stmt_len the length of the DML statement.
813      @param[IN] sql_command the type of SQL command.
814 
815      @return Returns false if succeeds, otherwise true is returned.
816   */
817   bool write_stmt_directly(THD* thd, const char *stmt, size_t stmt_len,
818                           enum enum_sql_command sql_command);
819 
820   void set_write_error(THD *thd, bool is_transactional);
821   bool check_write_error(THD *thd);
822   bool write_incident(THD *thd, bool need_lock_log,
823                       const char* err_msg,
824                       bool do_flush_and_sync= true);
825   bool write_incident(Incident_log_event *ev, THD *thd,
826                       bool need_lock_log,
827                       const char* err_msg,
828                       bool do_flush_and_sync= true);
829 
830   void start_union_events(THD *thd, query_id_t query_id_param);
831   void stop_union_events(THD *thd);
832   bool is_query_in_union(THD *thd, query_id_t query_id_param);
833 
834 #ifdef HAVE_REPLICATION
835   bool append_buffer(uchar* buf, size_t len, Master_info *mi);
836   bool append_event(Log_event* ev, Master_info *mi);
837 private:
838   bool after_append_to_relay_log(Master_info *mi);
839 #endif // ifdef HAVE_REPLICATION
840 public:
841 
842   void make_log_name(char* buf, const char* log_ident);
843   bool is_active(const char* log_file_name);
844   int remove_logs_from_index(LOG_INFO* linfo, bool need_update_threads);
845   int rotate(bool force_rotate, bool* check_purge);
846   void purge();
847   int rotate_and_purge(THD* thd, bool force_rotate);
848   /**
849      Flush binlog cache and synchronize to disk.
850 
851      This function flushes events in binlog cache to binary log file,
852      it will do synchronizing according to the setting of system
853      variable 'sync_binlog'. If file is synchronized, @c synced will
854      be set to 1, otherwise 0.
855 
856      @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
857      @param[in] force if TRUE, ignores the 'sync_binlog' and synchronizes the file.
858 
859      @retval 0 Success
860      @retval other Failure
861   */
862   bool flush_and_sync(const bool force= false);
863   int purge_logs(const char *to_log, bool included,
864                  bool need_lock_index, bool need_update_threads,
865                  ulonglong *decrease_log_space, bool auto_purge);
866   int count_binlog_space(bool need_lock_index);
867   int purge_logs_by_size(bool need_lock_index);
868   int purge_logs_maximum_number(ulong max_nr_files);
869   int purge_logs_before_date(time_t purge_time, bool auto_purge);
870   int purge_first_log(Relay_log_info* rli, bool included);
871   int set_crash_safe_index_file_name(const char *base_file_name);
872   int open_crash_safe_index_file();
873   int close_crash_safe_index_file();
874   int add_log_to_index(uchar* log_file_name, size_t name_len,
875                        bool need_lock_index);
876   int move_crash_safe_index_file_to_index_file(bool need_lock_index);
877   int set_purge_index_file_name(const char *base_file_name);
878   int open_purge_index_file(bool destroy);
879   bool is_inited_purge_index_file();
880   int close_purge_index_file();
881   int clean_purge_index_file();
882   int sync_purge_index_file();
883   int register_purge_index_entry(const char* entry);
884   int register_create_index_entry(const char* entry);
885   int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
886                         bool need_lock_index);
887   bool reset_logs(THD* thd, bool delete_only= false);
888   void close(uint exiting, bool need_lock_log, bool need_lock_index);
889 
890   // iterating through the log index file
891   int find_log_pos(LOG_INFO* linfo, const char* log_name,
892                    bool need_lock_index);
893   int find_next_log(LOG_INFO* linfo, bool need_lock_index);
894   int find_next_relay_log(char log_name[FN_REFLEN+1]);
895   int get_current_log(LOG_INFO* linfo, bool need_lock_log= true);
896   int raw_get_current_log(LOG_INFO* linfo);
897   uint next_file_id();
get_index_fname()898   inline char* get_index_fname() { return index_file_name;}
get_log_fname()899   inline char* get_log_fname() { return log_file_name; }
get_name()900   inline char* get_name() { return name; }
get_log_lock()901   inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
get_log_cond()902   inline mysql_cond_t* get_log_cond() { return &update_cond; }
get_log_file()903   inline IO_CACHE* get_log_file() { return &log_file; }
904 
lock_index()905   inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
unlock_index()906   inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
get_index_file()907   inline IO_CACHE *get_index_file() { return &index_file;}
get_open_count()908   inline uint32 get_open_count() { return open_count; }
909 
910   /**
911     Function to report the missing GTIDs.
912 
913     This function logs the missing transactions on master to its error log
914     as a warning. If the missing GTIDs are too long to print in a message,
915     it suggests the steps to extract the missing transactions.
916 
917     This function also informs slave about the GTID set sent by the slave,
918     transactions missing on the master and few suggestions to recover from
919     the error. This message shall be wrapped by
920     ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
921     error.
922 
923     This function will be called from mysql_binlog_send() function.
924 
925     @param slave_executed_gtid_set     GTID set executed by slave
926     @param errmsg                      Pointer to the error message
927 
928     @return void
929   */
930   void report_missing_purged_gtids(const Gtid_set *slave_executed_gtid_set,
931                                    std::string &errmsg);
932 
933   /**
934     Function to report the missing GTIDs.
935 
936     This function logs the missing transactions on master to its error log
937     as a warning. If the missing GTIDs are too long to print in a message,
938     it suggests the steps to extract the missing transactions.
939 
940     This function also informs slave about the GTID set sent by the slave,
941     transactions missing on the master and few suggestions to recover from
942     the error. This message shall be wrapped by
943     ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
944     error.
945 
946     This function will be called from find_first_log_not_in_gtid_set()
947     function.
948 
949     @param previous_gtid_set           Previous GTID set found
950     @param slave_executed_gtid_set     GTID set executed by slave
951     @param errmsg                      Pointer to the error message
952 
953     @return void
954   */
955   void report_missing_gtids(const Gtid_set *previous_gtid_set,
956                             const Gtid_set *slave_executed_gtid_set,
957                             std::string &errmsg);
958   static const int MAX_RETRIES_FOR_DELETE_RENAME_FAILURE= 5;
959   /*
960     It is called by the threads(e.g. dump thread) which want to read
961     hot log without LOCK_log protection.
962   */
get_binlog_end_pos()963   my_off_t get_binlog_end_pos() const
964   {
965     mysql_mutex_assert_not_owner(&LOCK_log);
966     mysql_mutex_assert_owner(&LOCK_binlog_end_pos);
967     return binlog_end_pos;
968   }
get_binlog_end_pos_lock()969   mysql_mutex_t* get_binlog_end_pos_lock() { return &LOCK_binlog_end_pos; }
lock_binlog_end_pos()970   void lock_binlog_end_pos() { mysql_mutex_lock(&LOCK_binlog_end_pos); }
unlock_binlog_end_pos()971   void unlock_binlog_end_pos() { mysql_mutex_unlock(&LOCK_binlog_end_pos); }
972 
973   /**
974     Deep copy global_sid_map to @param sid_map and
975     gtid_state->get_executed_gtids() to @param gtid_set
976     Both operations are done under LOCK_commit and global_sid_lock
977     protection.
978 
979     @param[out] sid_map  The Sid_map to which global_sid_map will
980                          be copied.
981     @param[out] gtid_set The Gtid_set to which gtid_executed will
982                          be copied.
983 
984     @return the operation status
985       @retval 0      OK
986       @retval !=0    Error
987   */
988   int get_gtid_executed(Sid_map *sid_map, Gtid_set *gtid_set);
989 
990   /*
991     True while rotating binlog, which is caused by logging Incident_log_event.
992   */
993   bool is_rotating_caused_by_incident;
994 
get_crypto_data()995   Binlog_crypt_data* get_crypto_data()
996   {
997     return &crypto;
998   }
999 private:
1000   void publish_coordinates_for_global_status(void) const;
1001 };
1002 
1003 typedef struct st_load_file_info
1004 {
1005   THD* thd;
1006   my_off_t last_pos_in_file;
1007   bool wrote_create_file, log_delayed;
1008 } LOAD_FILE_INFO;
1009 
1010 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
1011 
1012 /**
1013   Check if the the transaction is empty.
1014 
1015   @param thd The client thread that executed the current statement.
1016 
1017   @retval true No changes found in any storage engine
1018   @retval false Otherwise.
1019 
1020 **/
1021 bool is_transaction_empty(THD* thd);
1022 /**
1023   Check if the transaction has no rw flag set for any of the storage engines.
1024 
1025   @param thd The client thread that executed the current statement.
1026   @param trx_scope The transaction scope to look into.
1027 
1028   @retval the number of engines which have actual changes.
1029  */
1030 int check_trx_rw_engines(THD *thd, Transaction_ctx::enum_trx_scope trx_scope);
1031 
1032 /**
1033   Check if at least one of transacaction and statement binlog caches contains
1034   an empty transaction, other one is empty or contains an empty transaction,
1035   which has two binlog events "BEGIN" and "COMMIT".
1036 
1037   @param thd The client thread that executed the current statement.
1038 
1039   @retval true  At least one of transacaction and statement binlog caches
1040                 contains an empty transaction, other one is empty or
1041                 contains an empty transaction.
1042   @retval false Otherwise.
1043 */
1044 bool is_empty_transaction_in_binlog_cache(const THD* thd);
1045 bool trans_has_updated_trans_table(const THD* thd);
1046 bool stmt_has_updated_trans_table(Ha_trx_info* ha_list);
1047 /**
1048   This function checks if the transaction has no operation dml.
1049 
1050   @param ha_list Registered storage engine handler list.
1051   @return true  if the transaction has no operation dml.
1052           false otherwise.
1053 */
1054 bool trans_has_noop_dml(Ha_trx_info* ha_list);
1055 bool ending_trans(THD* thd, const bool all);
1056 bool ending_single_stmt_trans(THD* thd, const bool all);
1057 bool trans_cannot_safely_rollback(const THD* thd);
1058 bool stmt_cannot_safely_rollback(const THD* thd);
1059 
1060 int log_loaded_block(IO_CACHE* file);
1061 
1062 /**
1063   Open a single binary log file for reading.
1064 */
1065 File open_binlog_file(IO_CACHE *log, const char *log_file_name,
1066                       const char **errmsg);
1067 int check_binlog_magic(IO_CACHE* log, const char** errmsg);
1068 bool purge_master_logs(THD* thd, const char* to_log);
1069 bool purge_master_logs_before_date(THD* thd, time_t purge_time);
1070 bool show_binlog_events(THD *thd, MYSQL_BIN_LOG *binary_log);
1071 bool mysql_show_binlog_events(THD* thd);
1072 void check_binlog_cache_size(THD *thd);
1073 void check_binlog_stmt_cache_size(THD *thd);
1074 bool binlog_enabled();
1075 void register_binlog_handler(THD *thd, bool trx);
1076 int query_error_code(THD *thd, bool not_killed);
1077 
1078 bool handle_gtid_consistency_violation(THD *thd, int error_code);
1079 
1080 extern const char *log_bin_index;
1081 extern const char *log_bin_basename;
1082 extern bool opt_binlog_order_commits;
1083 
1084 /*
1085   Maximum unique log filename extension.
1086   Note: setting to 0x7FFFFFFF due to atol windows
1087   overflow/truncate.
1088 */
1089 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF
1090 
1091 /**
1092   Turns a relative log binary log path into a full path, based on the
1093   opt_bin_logname or opt_relay_logname. Also trims the cr-lf at the
1094   end of the full_path before return to avoid any server startup
1095   problem on windows.
1096 
1097   @param from         The log name we want to make into an absolute path.
1098   @param to           The buffer where to put the results of the
1099                       normalization.
1100   @param is_relay_log Switch that makes is used inside to choose which
1101                       option (opt_bin_logname or opt_relay_logname) to
1102                       use when calculating the base path.
1103 
1104   @returns true if a problem occurs, false otherwise.
1105  */
1106 
normalize_binlog_name(char * to,const char * from,bool is_relay_log)1107 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
1108 {
1109   DBUG_ENTER("normalize_binlog_name");
1110   bool error= false;
1111   char buff[FN_REFLEN];
1112   char *ptr= (char*) from;
1113   char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
1114 
1115   assert(from);
1116 
1117   /* opt_name is not null and not empty and from is a relative path */
1118   if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
1119   {
1120     // take the path from opt_name
1121     // take the filename from from
1122     char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
1123     size_t log_dirpart_len, log_dirname_len;
1124     dirname_part(log_dirpart, opt_name, &log_dirpart_len);
1125     dirname_part(log_dirname, from, &log_dirname_len);
1126 
1127     /* log may be empty => relay-log or log-bin did not
1128         hold paths, just filename pattern */
1129     if (log_dirpart_len > 0)
1130     {
1131       /* create the new path name */
1132       if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
1133                    MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
1134       {
1135         error= true;
1136         goto end;
1137       }
1138 
1139       ptr= buff;
1140     }
1141   }
1142 
1143   assert(ptr);
1144   if (ptr)
1145   {
1146     size_t length= strlen(ptr);
1147 
1148     // Strips the CR+LF at the end of log name and \0-terminates it.
1149     if (length && ptr[length-1] == '\n')
1150     {
1151       ptr[length-1]= 0;
1152       length--;
1153       if (length && ptr[length-1] == '\r')
1154       {
1155         ptr[length-1]= 0;
1156         length--;
1157       }
1158     }
1159     if (!length)
1160     {
1161       error= true;
1162       goto end;
1163     }
1164     strmake(to, ptr, length);
1165   }
1166 end:
1167   DBUG_RETURN(error);
1168 }
1169 #endif /* BINLOG_H_INCLUDED */
1170