1 /* Copyright (c) 2005, 2016, Oracle and/or its affiliates.
2    Copyright (c) 2009, 2020, MariaDB Corporation.
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 as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA */
16 
17 #ifndef LOG_H
18 #define LOG_H
19 
20 #include "handler.h"                            /* my_xid */
21 #include "wsrep_mysqld.h"
22 #include "rpl_constants.h"
23 
24 class Relay_log_info;
25 
26 class Format_description_log_event;
27 
28 bool reopen_fstreams(const char *filename, FILE *outstream, FILE *errstream);
29 void setup_log_handling();
30 bool trans_has_updated_trans_table(const THD* thd);
31 bool stmt_has_updated_trans_table(const THD *thd);
32 bool use_trans_cache(const THD* thd, bool is_transactional);
33 bool ending_trans(THD* thd, const bool all);
34 bool ending_single_stmt_trans(THD* thd, const bool all);
35 bool trans_has_updated_non_trans_table(const THD* thd);
36 bool stmt_has_updated_non_trans_table(const THD* thd);
37 
38 /*
39   Transaction Coordinator log - a base abstract class
40   for two different implementations
41 */
42 class TC_LOG
43 {
44   public:
45   int using_heuristic_recover();
TC_LOG()46   TC_LOG() {}
~TC_LOG()47   virtual ~TC_LOG() {}
48 
49   virtual int open(const char *opt_name)=0;
50   virtual void close()=0;
51   /*
52     Transaction coordinator 2-phase commit.
53 
54     Must invoke the run_prepare_ordered and run_commit_ordered methods, as
55     described below for these methods.
56 
57     In addition, must invoke THD::wait_for_prior_commit(), or equivalent
58     wait, to ensure that one commit waits for another if registered to do so.
59   */
60   virtual int log_and_order(THD *thd, my_xid xid, bool all,
61                             bool need_prepare_ordered,
62                             bool need_commit_ordered) = 0;
63   virtual int unlog(ulong cookie, my_xid xid)=0;
64   virtual int unlog_xa_prepare(THD *thd, bool all)= 0;
65   virtual void commit_checkpoint_notify(void *cookie)= 0;
66 
67 protected:
68   /*
69     These methods are meant to be invoked from log_and_order() implementations
70     to run any prepare_ordered() respectively commit_ordered() methods in
71     participating handlers.
72 
73     They must be called using suitable thread syncronisation to ensure that
74     they are each called in the correct commit order among all
75     transactions. However, it is only necessary to call them if the
76     corresponding flag passed to log_and_order is set (it is safe, but not
77     required, to call them when the flag is false).
78 
79     The caller must be holding LOCK_prepare_ordered respectively
80     LOCK_commit_ordered when calling these methods.
81   */
82   void run_prepare_ordered(THD *thd, bool all);
83   void run_commit_ordered(THD *thd, bool all);
84 };
85 
86 /*
87   Locks used to ensure serialised execution of TC_LOG::run_prepare_ordered()
88   and TC_LOG::run_commit_ordered(), or any other code that calls handler
89   prepare_ordered() or commit_ordered() methods.
90 */
91 extern mysql_mutex_t LOCK_prepare_ordered;
92 extern mysql_cond_t COND_prepare_ordered;
93 extern mysql_mutex_t LOCK_after_binlog_sync;
94 extern mysql_mutex_t LOCK_commit_ordered;
95 #ifdef HAVE_PSI_INTERFACE
96 extern PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
97 extern PSI_mutex_key key_LOCK_after_binlog_sync;
98 extern PSI_cond_key key_COND_prepare_ordered;
99 #endif
100 
101 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
102 {
103 public:
TC_LOG_DUMMY()104   TC_LOG_DUMMY() {}
open(const char * opt_name)105   int open(const char *opt_name)        { return 0; }
close()106   void close()                          { }
107   /*
108     TC_LOG_DUMMY is only used when there are <= 1 XA-capable engines, and we
109     only use internal XA during commit when >= 2 XA-capable engines
110     participate.
111   */
log_and_order(THD * thd,my_xid xid,bool all,bool need_prepare_ordered,bool need_commit_ordered)112   int log_and_order(THD *thd, my_xid xid, bool all,
113                     bool need_prepare_ordered, bool need_commit_ordered)
114   {
115     DBUG_ASSERT(0);
116     return 1;
117   }
unlog(ulong cookie,my_xid xid)118   int unlog(ulong cookie, my_xid xid)  { return 0; }
unlog_xa_prepare(THD * thd,bool all)119   int unlog_xa_prepare(THD *thd, bool all)
120   {
121     return 0;
122   }
commit_checkpoint_notify(void * cookie)123   void commit_checkpoint_notify(void *cookie) { DBUG_ASSERT(0); };
124 };
125 
126 #define TC_LOG_PAGE_SIZE   8192
127 
128 #ifdef HAVE_MMAP
129 class TC_LOG_MMAP: public TC_LOG
130 {
131   public:                // only to keep Sun Forte on sol9x86 happy
132   typedef enum {
133     PS_POOL,                 // page is in pool
134     PS_ERROR,                // last sync failed
135     PS_DIRTY                 // new xids added since last sync
136   } PAGE_STATE;
137 
138   struct pending_cookies {
139     uint count;
140     uint pending_count;
141     ulong cookies[1];
142   };
143 
144   private:
145   typedef struct st_page {
146     struct st_page *next; // page a linked in a fifo queue
147     my_xid *start, *end;  // usable area of a page
148     my_xid *ptr;          // next xid will be written here
149     int size, free;       // max and current number of free xid slots on the page
150     int waiters;          // number of waiters on condition
151     PAGE_STATE state;     // see above
152     mysql_mutex_t lock; // to access page data or control structure
153     mysql_cond_t  cond; // to wait for a sync
154   } PAGE;
155 
156   /* List of THDs for which to invoke commit_ordered(), in order. */
157   struct commit_entry
158   {
159     struct commit_entry *next;
160     THD *thd;
161   };
162 
163   char logname[FN_REFLEN];
164   File fd;
165   my_off_t file_length;
166   uint npages, inited;
167   uchar *data;
168   struct st_page *pages, *syncing, *active, *pool, **pool_last_ptr;
169   /*
170     note that, e.g. LOCK_active is only used to protect
171     'active' pointer, to protect the content of the active page
172     one has to use active->lock.
173     Same for LOCK_pool and LOCK_sync
174   */
175   mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync, LOCK_pending_checkpoint;
176   mysql_cond_t COND_pool, COND_active;
177   /*
178     Queue of threads that need to call commit_ordered().
179     Access to this queue must be protected by LOCK_prepare_ordered.
180   */
181   commit_entry *commit_ordered_queue;
182   /*
183     This flag and condition is used to reserve the queue while threads in it
184     each run the commit_ordered() methods one after the other. Only once the
185     last commit_ordered() in the queue is done can we start on a new queue
186     run.
187 
188     Since we start this process in the first thread in the queue and finish in
189     the last (and possibly different) thread, we need a condition variable for
190     this (we cannot unlock a mutex in a different thread than the one who
191     locked it).
192 
193     The condition is used together with the LOCK_prepare_ordered mutex.
194   */
195   mysql_cond_t COND_queue_busy;
196   my_bool commit_ordered_queue_busy;
197   pending_cookies* pending_checkpoint;
198 
199   public:
TC_LOG_MMAP()200   TC_LOG_MMAP(): inited(0), pending_checkpoint(0) {}
201   int open(const char *opt_name);
202   void close();
203   int log_and_order(THD *thd, my_xid xid, bool all,
204                     bool need_prepare_ordered, bool need_commit_ordered);
205   int unlog(ulong cookie, my_xid xid);
unlog_xa_prepare(THD * thd,bool all)206   int unlog_xa_prepare(THD *thd, bool all)
207   {
208     return 0;
209   }
210   void commit_checkpoint_notify(void *cookie);
211   int recover();
212 
213   private:
214   int log_one_transaction(my_xid xid);
215   void get_active_from_pool();
216   int sync();
217   int overflow();
218   int delete_entry(ulong cookie);
219 };
220 #else
221 #define TC_LOG_MMAP TC_LOG_DUMMY
222 #endif
223 
224 extern TC_LOG *tc_log;
225 extern TC_LOG_MMAP tc_log_mmap;
226 extern TC_LOG_DUMMY tc_log_dummy;
227 
228 /* log info errors */
229 #define LOG_INFO_EOF -1
230 #define LOG_INFO_IO  -2
231 #define LOG_INFO_INVALID -3
232 #define LOG_INFO_SEEK -4
233 #define LOG_INFO_MEM -6
234 #define LOG_INFO_FATAL -7
235 #define LOG_INFO_IN_USE -8
236 #define LOG_INFO_EMFILE -9
237 
238 
239 /* bitmap to SQL_LOG::close() */
240 #define LOG_CLOSE_INDEX		1
241 #define LOG_CLOSE_TO_BE_OPENED	2
242 #define LOG_CLOSE_STOP_EVENT	4
243 #define LOG_CLOSE_DELAYED_CLOSE 8
244 
245 /*
246   Maximum unique log filename extension.
247   Note: setting to 0x7FFFFFFF due to atol windows
248         overflow/truncate.
249  */
250 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF
251 
252 /*
253    Number of warnings that will be printed to error log
254    before extension number is exhausted.
255 */
256 #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000
257 
258 class Relay_log_info;
259 
260 /*
261   Note that we destroy the lock mutex in the desctructor here.
262   This means that object instances cannot be destroyed/go out of scope,
263   until we have reset thd->current_linfo to NULL;
264  */
265 typedef struct st_log_info
266 {
267   char log_file_name[FN_REFLEN];
268   my_off_t index_file_offset, index_file_start_offset;
269   my_off_t pos;
270   bool fatal; // if the purge happens to give us a negative offset
st_log_infost_log_info271   st_log_info() : index_file_offset(0), index_file_start_offset(0),
272       pos(0), fatal(0)
273   {
274     DBUG_ENTER("LOG_INFO");
275     log_file_name[0] = '\0';
276     DBUG_VOID_RETURN;
277   }
278 } LOG_INFO;
279 
280 /*
281   Currently we have only 3 kinds of logging functions: old-fashioned
282   logs, stdout and csv logging routines.
283 */
284 #define MAX_LOG_HANDLERS_NUM 3
285 
286 /* log event handler flags */
287 #define LOG_NONE       1U
288 #define LOG_FILE       2U
289 #define LOG_TABLE      4U
290 
291 class Log_event;
292 class Rows_log_event;
293 
294 enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN };
295 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
296 
297 /*
298   Use larger buffers when reading from and to binary log
299   We make it one step smaller than 64K to account for malloc overhead.
300 */
301 #define LOG_BIN_IO_SIZE MY_ALIGN_DOWN(65536-1, IO_SIZE)
302 
303 /*
304   TODO use mmap instead of IO_CACHE for binlog
305   (mmap+fsync is two times faster than write+fsync)
306 */
307 
308 class MYSQL_LOG
309 {
310 public:
311   MYSQL_LOG();
~MYSQL_LOG()312   virtual ~MYSQL_LOG() {}
313   void init_pthread_objects();
314   void cleanup();
315   bool open(
316 #ifdef HAVE_PSI_INTERFACE
317             PSI_file_key log_file_key,
318 #endif
319             const char *log_name,
320             enum_log_type log_type,
321             const char *new_name, ulong next_file_number,
322             enum cache_type io_cache_type_arg);
323   void close(uint exiting);
is_open()324   inline bool is_open() { return log_state != LOG_CLOSED; }
325   const char *generate_name(const char *log_name,
326                             const char *suffix,
327                             bool strip_ext, char *buff);
328   virtual int generate_new_name(char *new_name, const char *log_name,
329                                 ulong next_log_number);
330  protected:
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 time_buff[20], db[NAME_LEN + 1];
336   bool write_error, inited;
337   IO_CACHE log_file;
338   enum_log_type log_type;
339   volatile enum_log_state log_state;
340   enum cache_type io_cache_type;
341   friend class Log_event;
342 #ifdef HAVE_PSI_INTERFACE
343   /** Instrumentation key to use for file io in @c log_file */
344   PSI_file_key m_log_file_key;
345 #endif
346 
347   bool init_and_set_log_file_name(const char *log_name,
348                                   const char *new_name,
349                                   ulong next_log_number,
350                                   enum_log_type log_type_arg,
351                                   enum cache_type io_cache_type_arg);
352 };
353 
354 /* Tell the io thread if we can delay the master info sync. */
355 #define SEMI_SYNC_SLAVE_DELAY_SYNC 1
356 /* Tell the io thread if the current event needs a ack. */
357 #define SEMI_SYNC_NEED_ACK  2
358 
359 class MYSQL_QUERY_LOG: public MYSQL_LOG
360 {
361 public:
MYSQL_QUERY_LOG()362   MYSQL_QUERY_LOG() : last_time(0) {}
363   void reopen_file();
364   bool write(time_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id,
365              const char *command_type, size_t command_type_len,
366              const char *sql_text, size_t sql_text_len);
367   bool write(THD *thd, time_t current_time,
368              const char *user_host, size_t user_host_len,
369              ulonglong query_utime, ulonglong lock_utime, bool is_command,
370              const char *sql_text, size_t sql_text_len);
open_slow_log(const char * log_name)371   bool open_slow_log(const char *log_name)
372   {
373     char buf[FN_REFLEN];
374     return open(
375 #ifdef HAVE_PSI_INTERFACE
376                 key_file_slow_log,
377 #endif
378                 generate_name(log_name, "-slow.log", 0, buf),
379                 LOG_NORMAL, 0, 0, WRITE_CACHE);
380   }
open_query_log(const char * log_name)381   bool open_query_log(const char *log_name)
382   {
383     char buf[FN_REFLEN];
384     return open(
385 #ifdef HAVE_PSI_INTERFACE
386                 key_file_query_log,
387 #endif
388                 generate_name(log_name, ".log", 0, buf),
389                 LOG_NORMAL, 0, 0, WRITE_CACHE);
390   }
391 
392 private:
393   time_t last_time;
394 };
395 
396 /*
397   We assign each binlog file an internal ID, used to identify them for unlog().
398   The IDs start from 0 and increment for each new binlog created.
399 
400   In unlog() we need to know the ID of the binlog file that the corresponding
401   transaction was written into. We also need a special value for a corner
402   case where there is no corresponding binlog id (since nothing was logged).
403   And we need an error flag to mark that unlog() must return failure.
404 
405   We use the following macros to pack all of this information into the single
406   ulong available with log_and_order() / unlog().
407 
408   Note that we cannot use the value 0 for cookie, as that is reserved as error
409   return value from log_and_order().
410   */
411 #define BINLOG_COOKIE_ERROR_RETURN 0
412 #define BINLOG_COOKIE_DUMMY_ID 1
413 #define BINLOG_COOKIE_BASE 2
414 #define BINLOG_COOKIE_DUMMY(error_flag) \
415   ( (BINLOG_COOKIE_DUMMY_ID<<1) | ((error_flag)&1) )
416 #define BINLOG_COOKIE_MAKE(id, error_flag) \
417   ( (((id)+BINLOG_COOKIE_BASE)<<1) | ((error_flag)&1) )
418 #define BINLOG_COOKIE_GET_ERROR_FLAG(c) ((c) & 1)
419 #define BINLOG_COOKIE_GET_ID(c) ( ((ulong)(c)>>1) - BINLOG_COOKIE_BASE )
420 #define BINLOG_COOKIE_IS_DUMMY(c) \
421   ( ((ulong)(c)>>1) == BINLOG_COOKIE_DUMMY_ID )
422 
423 class binlog_cache_mngr;
424 class binlog_cache_data;
425 struct rpl_gtid;
426 struct wait_for_commit;
427 
428 class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
429 {
430   /** The instrumentation key to use for @ LOCK_index. */
431   PSI_mutex_key m_key_LOCK_index;
432   /** The instrumentation key to use for @ COND_relay_log_updated */
433   PSI_cond_key m_key_relay_log_update;
434   /** The instrumentation key to use for @ COND_bin_log_updated */
435   PSI_cond_key m_key_bin_log_update;
436   /** The instrumentation key to use for opening the log file. */
437   PSI_file_key m_key_file_log, m_key_file_log_cache;
438   /** The instrumentation key to use for opening the log index file. */
439   PSI_file_key m_key_file_log_index, m_key_file_log_index_cache;
440 
441   PSI_cond_key m_key_COND_queue_busy;
442   /** The instrumentation key to use for LOCK_binlog_end_pos. */
443   PSI_mutex_key m_key_LOCK_binlog_end_pos;
444 
445   struct group_commit_entry
446   {
447     struct group_commit_entry *next;
448     THD *thd;
449     binlog_cache_mngr *cache_mngr;
450     bool using_stmt_cache;
451     bool using_trx_cache;
452     /*
453       Extra events (COMMIT/ROLLBACK/XID, and possibly INCIDENT) to be
454       written during group commit. The incident_event is only valid if
455       trx_data->has_incident() is true.
456     */
457     Log_event *end_event;
458     Log_event *incident_event;
459     /* Set during group commit to record any per-thread error. */
460     int error;
461     int commit_errno;
462     IO_CACHE *error_cache;
463     /* This is the `all' parameter for ha_commit_ordered(). */
464     bool all;
465     /*
466       True if we need to increment xid_count in trx_group_commit_leader() and
467       decrement in unlog() (this is needed if there is a participating engine
468       that does not implement the commit_checkpoint_request() handlerton
469       method).
470     */
471     bool need_unlog;
472     /*
473       Fields used to pass the necessary information to the last thread in a
474       group commit, only used when opt_optimize_thread_scheduling is not set.
475     */
476     bool check_purge;
477     /* Flag used to optimise around wait_for_prior_commit. */
478     bool queued_by_other;
479     ulong binlog_id;
480   };
481 
482   /*
483     When this is set, a RESET MASTER is in progress.
484 
485     Then we should not write any binlog checkpoints into the binlog (that
486     could result in deadlock on LOCK_log, and we will delete all binlog files
487     anyway). Instead we should signal COND_xid_list whenever a new binlog
488     checkpoint arrives - when all have arrived, RESET MASTER will complete.
489   */
490   uint reset_master_pending;
491   ulong mark_xid_done_waiting;
492 
493   /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
494   mysql_mutex_t LOCK_index;
495   mysql_mutex_t LOCK_binlog_end_pos;
496   mysql_mutex_t LOCK_xid_list;
497   mysql_cond_t  COND_xid_list;
498   mysql_cond_t  COND_relay_log_updated, COND_bin_log_updated;
499   ulonglong bytes_written;
500   IO_CACHE index_file;
501   char index_file_name[FN_REFLEN];
502   /*
503     purge_file is a temp file used in purge_logs so that the index file
504     can be updated before deleting files from disk, yielding better crash
505     recovery. It is created on demand the first time purge_logs is called
506     and then reused for subsequent calls. It is cleaned up in cleanup().
507   */
508   IO_CACHE purge_index_file;
509   char purge_index_file_name[FN_REFLEN];
510   /*
511      The max size before rotation (usable only if log_type == LOG_BIN: binary
512      logs and relay logs).
513      For a binlog, max_size should be max_binlog_size.
514      max_size is set in init(), and dynamically changed (when one does SET
515      GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) from sys_vars.cc
516   */
517   ulong max_size;
518   /*
519     Number generated by last call of find_uniq_filename(). Corresponds
520     closely with current_binlog_id
521   */
522   ulong last_used_log_number;
523   // current file sequence number for load data infile binary logging
524   uint file_id;
525   uint open_count;				// For replication
526   int readers_count;
527   /* Queue of transactions queued up to participate in group commit. */
528   group_commit_entry *group_commit_queue;
529   /*
530     Condition variable to mark that the group commit queue is busy.
531     Used when each thread does it's own commit_ordered() (when
532     binlog_optimize_thread_scheduling=1).
533     Used with the LOCK_commit_ordered mutex.
534   */
535   my_bool group_commit_queue_busy;
536   mysql_cond_t COND_queue_busy;
537   /* Total number of committed transactions. */
538   ulonglong num_commits;
539   /* Number of group commits done. */
540   ulonglong num_group_commits;
541   /* The reason why the group commit was grouped */
542   ulonglong group_commit_trigger_count, group_commit_trigger_timeout;
543   ulonglong group_commit_trigger_lock_wait;
544 
545   /* binlog encryption data */
546   struct Binlog_crypt_data crypto;
547 
548   /* pointer to the sync period variable, for binlog this will be
549      sync_binlog_period, for relay log this will be
550      sync_relay_log_period
551   */
552   uint *sync_period_ptr;
553   uint sync_counter;
554   bool state_file_deleted;
555   bool binlog_state_recover_done;
556 
get_sync_period()557   inline uint get_sync_period()
558   {
559     return *sync_period_ptr;
560   }
561 
562   int write_to_file(IO_CACHE *cache);
563   /*
564     This is used to start writing to a new log file. The difference from
565     new_file() is locking. new_file_without_locking() does not acquire
566     LOCK_log.
567   */
568   int new_file_without_locking();
569   int new_file_impl();
570   void do_checkpoint_request(ulong binlog_id);
571   void purge();
572   int write_transaction_or_stmt(group_commit_entry *entry, uint64 commit_id);
573   int queue_for_group_commit(group_commit_entry *entry);
574   bool write_transaction_to_binlog_events(group_commit_entry *entry);
575   void trx_group_commit_leader(group_commit_entry *leader);
576   bool is_xidlist_idle_nolock();
577 public:
578   /*
579     A list of struct xid_count_per_binlog is used to keep track of how many
580     XIDs are in prepared, but not committed, state in each binlog. And how
581     many commit_checkpoint_request()'s are pending.
582 
583     When count drops to zero in a binlog after rotation, it means that there
584     are no more XIDs in prepared state, so that binlog is no longer needed
585     for XA crash recovery, and we can log a new binlog checkpoint event.
586 
587     The list is protected against simultaneous access from multiple
588     threads by LOCK_xid_list.
589   */
590   struct xid_count_per_binlog : public ilink {
591     char *binlog_name;
592     uint binlog_name_len;
593     ulong binlog_id;
594     /* Total prepared XIDs and pending checkpoint requests in this binlog. */
595     long xid_count;
596     long notify_count;
597     /* For linking in requests to the binlog background thread. */
598     xid_count_per_binlog *next_in_queue;
xid_count_per_binlogxid_count_per_binlog599     xid_count_per_binlog(char *log_file_name, uint log_file_name_len)
600       :binlog_id(0), xid_count(0), notify_count(0)
601     {
602       binlog_name_len= log_file_name_len;
603       binlog_name= (char *) my_malloc(PSI_INSTRUMENT_ME, binlog_name_len, MYF(MY_ZEROFILL));
604       if (binlog_name)
605         memcpy(binlog_name, log_file_name, binlog_name_len);
606     }
~xid_count_per_binlogxid_count_per_binlog607     ~xid_count_per_binlog()
608     {
609       my_free(binlog_name);
610     }
611   };
612   I_List<xid_count_per_binlog> binlog_xid_count_list;
613   mysql_mutex_t LOCK_binlog_background_thread;
614   mysql_cond_t COND_binlog_background_thread;
615   mysql_cond_t COND_binlog_background_thread_end;
616 
617   void stop_background_thread();
618 
619   using MYSQL_LOG::generate_name;
620   using MYSQL_LOG::is_open;
621 
622   /* This is relay log */
623   bool is_relay_log;
624   ulong relay_signal_cnt;  // update of the counter is checked by heartbeat
625   enum enum_binlog_checksum_alg checksum_alg_reset; // to contain a new value when binlog is rotated
626   /*
627     Holds the last seen in Relay-Log FD's checksum alg value.
628     The initial value comes from the slave's local FD that heads
629     the very first Relay-Log file. In the following the value may change
630     with each received master's FD_m.
631     Besides to be used in verification events that IO thread receives
632     (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd),
633     the value specifies if/how to compute checksum for slave's local events
634     and the first fake Rotate (R_f^1) coming from the master.
635     R_f^1 needs logging checksum-compatibly with the RL's heading FD_s.
636 
637     Legends for the checksum related comments:
638 
639     FD     - Format-Description event,
640     R      - Rotate event
641     R_f    - the fake Rotate event
642     E      - an arbirary event
643 
644     The underscore indexes for any event
645     `_s'   indicates the event is generated by Slave
646     `_m'   - by Master
647 
648     Two special underscore indexes of FD:
649     FD_q   - Format Description event for queuing   (relay-logging)
650     FD_e   - Format Description event for executing (relay-logging)
651 
652     Upper indexes:
653     E^n    - n:th event is a sequence
654 
655     RL     - Relay Log
656     (A)    - checksum algorithm descriptor value
657     FD.(A) - the value of (A) in FD
658   */
659   enum enum_binlog_checksum_alg relay_log_checksum_alg;
660   /*
661     These describe the log's format. This is used only for relay logs.
662     _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
663     necessary to have 2 distinct objects, because the I/O thread may be reading
664     events in a different format from what the SQL thread is reading (consider
665     the case of a master which has been upgraded from 5.0 to 5.1 without doing
666     RESET MASTER, or from 4.x to 5.0).
667   */
668   Format_description_log_event *description_event_for_exec,
669     *description_event_for_queue;
670   /*
671     Binlog position of last commit (or non-transactional write) to the binlog.
672     Access to this is protected by LOCK_commit_ordered.
673   */
674   char last_commit_pos_file[FN_REFLEN];
675   my_off_t last_commit_pos_offset;
676   ulong current_binlog_id;
677 
678   /*
679     Tracks the number of times that the master has been reset
680   */
681   Atomic_counter<uint64> reset_master_count;
682 
683   MYSQL_BIN_LOG(uint *sync_period);
684   /*
685     note that there's no destructor ~MYSQL_BIN_LOG() !
686     The reason is that we don't want it to be automatically called
687     on exit() - but only during the correct shutdown process
688   */
689 
690 #ifdef HAVE_PSI_INTERFACE
set_psi_keys(PSI_mutex_key key_LOCK_index,PSI_cond_key key_relay_log_update,PSI_cond_key key_bin_log_update,PSI_file_key key_file_log,PSI_file_key key_file_log_cache,PSI_file_key key_file_log_index,PSI_file_key key_file_log_index_cache,PSI_cond_key key_COND_queue_busy,PSI_mutex_key key_LOCK_binlog_end_pos)691   void set_psi_keys(PSI_mutex_key key_LOCK_index,
692                     PSI_cond_key key_relay_log_update,
693                     PSI_cond_key key_bin_log_update,
694                     PSI_file_key key_file_log,
695                     PSI_file_key key_file_log_cache,
696                     PSI_file_key key_file_log_index,
697                     PSI_file_key key_file_log_index_cache,
698                     PSI_cond_key key_COND_queue_busy,
699                     PSI_mutex_key key_LOCK_binlog_end_pos)
700   {
701     m_key_LOCK_index= key_LOCK_index;
702     m_key_relay_log_update=  key_relay_log_update;
703     m_key_bin_log_update=    key_bin_log_update;
704     m_key_file_log= key_file_log;
705     m_key_file_log_cache= key_file_log_cache;
706     m_key_file_log_index= key_file_log_index;
707     m_key_file_log_index_cache= key_file_log_index_cache;
708     m_key_COND_queue_busy= key_COND_queue_busy;
709     m_key_LOCK_binlog_end_pos= key_LOCK_binlog_end_pos;
710   }
711 #endif
712 
713   int open(const char *opt_name);
714   void close();
715   virtual int generate_new_name(char *new_name, const char *log_name,
716                                 ulong next_log_number);
717   int log_and_order(THD *thd, my_xid xid, bool all,
718                     bool need_prepare_ordered, bool need_commit_ordered);
719   int unlog(ulong cookie, my_xid xid);
720   int unlog_xa_prepare(THD *thd, bool all);
721   void commit_checkpoint_notify(void *cookie);
722   int recover(LOG_INFO *linfo, const char *last_log_name, IO_CACHE *first_log,
723               Format_description_log_event *fdle, bool do_xa);
724   int do_binlog_recovery(const char *opt_name, bool do_xa_recovery);
725 #if !defined(MYSQL_CLIENT)
726 
727   int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
728                                        bool is_transactional);
729   int remove_pending_rows_event(THD *thd, bool is_transactional);
730 
731 #endif /* !defined(MYSQL_CLIENT) */
reset_bytes_written()732   void reset_bytes_written()
733   {
734     bytes_written = 0;
735   }
harvest_bytes_written(Atomic_counter<uint64> * counter)736   void harvest_bytes_written(Atomic_counter<uint64> *counter)
737   {
738 #ifndef DBUG_OFF
739     char buf1[22],buf2[22];
740 #endif
741     DBUG_ENTER("harvest_bytes_written");
742     (*counter)+=bytes_written;
743     DBUG_PRINT("info",("counter: %s  bytes_written: %s", llstr(*counter,buf1),
744 		       llstr(bytes_written,buf2)));
745     bytes_written=0;
746     DBUG_VOID_RETURN;
747   }
748   void set_max_size(ulong max_size_arg);
749 
750   /* Handle signaling that relay has been updated */
signal_relay_log_update()751   void signal_relay_log_update()
752   {
753     mysql_mutex_assert_owner(&LOCK_log);
754     DBUG_ASSERT(is_relay_log);
755     DBUG_ENTER("MYSQL_BIN_LOG::signal_relay_log_update");
756     relay_signal_cnt++;
757     mysql_cond_broadcast(&COND_relay_log_updated);
758     DBUG_VOID_RETURN;
759   }
signal_bin_log_update()760   void signal_bin_log_update()
761   {
762     mysql_mutex_assert_owner(&LOCK_binlog_end_pos);
763     DBUG_ASSERT(!is_relay_log);
764     DBUG_ENTER("MYSQL_BIN_LOG::signal_bin_log_update");
765     mysql_cond_broadcast(&COND_bin_log_updated);
766     DBUG_VOID_RETURN;
767   }
update_binlog_end_pos()768   void update_binlog_end_pos()
769   {
770     if (is_relay_log)
771       signal_relay_log_update();
772     else
773     {
774       lock_binlog_end_pos();
775       binlog_end_pos= my_b_safe_tell(&log_file);
776       signal_bin_log_update();
777       unlock_binlog_end_pos();
778     }
779   }
update_binlog_end_pos(my_off_t pos)780   void update_binlog_end_pos(my_off_t pos)
781   {
782     mysql_mutex_assert_owner(&LOCK_log);
783     mysql_mutex_assert_not_owner(&LOCK_binlog_end_pos);
784     lock_binlog_end_pos();
785     /*
786       Note: it would make more sense to assert(pos > binlog_end_pos)
787       but there are two places triggered by mtr that has pos == binlog_end_pos
788       i didn't investigate but accepted as it should do no harm
789     */
790     DBUG_ASSERT(pos >= binlog_end_pos);
791     binlog_end_pos= pos;
792     signal_bin_log_update();
793     unlock_binlog_end_pos();
794   }
795 
796   void wait_for_sufficient_commits();
797   void binlog_trigger_immediate_group_commit();
798   void wait_for_update_relay_log(THD* thd);
799   void init(ulong max_size);
800   void init_pthread_objects();
801   void cleanup();
802   bool open(const char *log_name,
803             const char *new_name,
804             ulong next_log_number,
805 	    enum cache_type io_cache_type_arg,
806 	    ulong max_size,
807             bool null_created,
808             bool need_mutex);
809   bool open_index_file(const char *index_file_name_arg,
810                        const char *log_name, bool need_mutex);
811   /* Use this to start writing a new log file */
812   int new_file();
813 
814   bool write(Log_event* event_info,
815              my_bool *with_annotate= 0); // binary log write
816   bool write_transaction_to_binlog(THD *thd, binlog_cache_mngr *cache_mngr,
817                                    Log_event *end_ev, bool all,
818                                    bool using_stmt_cache, bool using_trx_cache);
819 
820   bool write_incident_already_locked(THD *thd);
821   bool write_incident(THD *thd);
822   void write_binlog_checkpoint_event_already_locked(const char *name, uint len);
823   int  write_cache(THD *thd, IO_CACHE *cache);
824   void set_write_error(THD *thd, bool is_transactional);
825   bool check_write_error(THD *thd);
826 
827   void start_union_events(THD *thd, query_id_t query_id_param);
828   void stop_union_events(THD *thd);
829   bool is_query_in_union(THD *thd, query_id_t query_id_param);
830 
831   bool write_event(Log_event *ev, binlog_cache_data *data, IO_CACHE *file);
write_event(Log_event * ev)832   bool write_event(Log_event *ev) { return write_event(ev, 0, &log_file); }
833 
834   bool write_event_buffer(uchar* buf,uint len);
835   bool append(Log_event* ev);
836   bool append_no_lock(Log_event* ev);
837 
838   void mark_xids_active(ulong cookie, uint xid_count);
839   void mark_xid_done(ulong cookie, bool write_checkpoint);
840   void make_log_name(char* buf, const char* log_ident);
841   bool is_active(const char* log_file_name);
842   bool can_purge_log(const char *log_file_name);
843   int update_log_index(LOG_INFO* linfo, bool need_update_threads);
844   int rotate(bool force_rotate, bool* check_purge);
845   void checkpoint_and_purge(ulong binlog_id);
846   int rotate_and_purge(bool force_rotate, DYNAMIC_ARRAY* drop_gtid_domain= NULL);
847   /**
848      Flush binlog cache and synchronize to disk.
849 
850      This function flushes events in binlog cache to binary log file,
851      it will do synchronizing according to the setting of system
852      variable 'sync_binlog'. If file is synchronized, @c synced will
853      be set to 1, otherwise 0.
854 
855      @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
856 
857      @retval 0 Success
858      @retval other Failure
859   */
860   bool flush_and_sync(bool *synced);
861   int purge_logs(const char *to_log, bool included,
862                  bool need_mutex, bool need_update_threads,
863                  ulonglong *decrease_log_space);
864   int purge_logs_before_date(time_t purge_time);
865   int purge_first_log(Relay_log_info* rli, bool included);
866   int set_purge_index_file_name(const char *base_file_name);
867   int open_purge_index_file(bool destroy);
868   bool is_inited_purge_index_file();
869   int close_purge_index_file();
870   int clean_purge_index_file();
871   int sync_purge_index_file();
872   int register_purge_index_entry(const char* entry);
873   int register_create_index_entry(const char* entry);
874   int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
875                         bool need_mutex);
876   bool reset_logs(THD* thd, bool create_new_log,
877                   rpl_gtid *init_state, uint32 init_state_len,
878                   ulong next_log_number);
879   void wait_for_last_checkpoint_event();
880   void close(uint exiting);
881   void clear_inuse_flag_when_closing(File file);
882 
883   // iterating through the log index file
884   int find_log_pos(LOG_INFO* linfo, const char* log_name,
885 		   bool need_mutex);
886   int find_next_log(LOG_INFO* linfo, bool need_mutex);
887   int get_current_log(LOG_INFO* linfo);
888   int raw_get_current_log(LOG_INFO* linfo);
889   uint next_file_id();
get_index_fname()890   inline char* get_index_fname() { return index_file_name;}
get_log_fname()891   inline char* get_log_fname() { return log_file_name; }
get_name()892   inline char* get_name() { return name; }
get_log_lock()893   inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
get_bin_log_cond()894   inline mysql_cond_t* get_bin_log_cond() { return &COND_bin_log_updated; }
get_log_file()895   inline IO_CACHE* get_log_file() { return &log_file; }
get_reset_master_count()896   inline uint64 get_reset_master_count() { return reset_master_count; }
897 
lock_index()898   inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
unlock_index()899   inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
get_index_file()900   inline IO_CACHE *get_index_file() { return &index_file;}
get_open_count()901   inline uint32 get_open_count() { return open_count; }
902   void set_status_variables(THD *thd);
903   bool is_xidlist_idle();
904   bool write_gtid_event(THD *thd, bool standalone, bool is_transactional,
905                         uint64 commit_id);
906   int read_state_from_file();
907   int write_state_to_file();
908   int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
909   bool append_state_pos(String *str);
910   bool append_state(String *str);
911   bool is_empty_state();
912   bool find_in_binlog_state(uint32 domain_id, uint32 server_id,
913                             rpl_gtid *out_gtid);
914   bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid);
915   int bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no);
916   bool check_strict_gtid_sequence(uint32 domain_id, uint32 server_id,
917                                   uint64 seq_no);
918 
919   /**
920    * used when opening new file, and binlog_end_pos moves backwards
921    */
reset_binlog_end_pos(const char file_name[FN_REFLEN],my_off_t pos)922   void reset_binlog_end_pos(const char file_name[FN_REFLEN], my_off_t pos)
923   {
924     mysql_mutex_assert_owner(&LOCK_log);
925     mysql_mutex_assert_not_owner(&LOCK_binlog_end_pos);
926     lock_binlog_end_pos();
927     binlog_end_pos= pos;
928     strcpy(binlog_end_pos_file, file_name);
929     signal_bin_log_update();
930     unlock_binlog_end_pos();
931   }
932 
933   /*
934     It is called by the threads(e.g. dump thread) which want to read
935     log without LOCK_log protection.
936   */
get_binlog_end_pos(char file_name_buf[FN_REFLEN])937   my_off_t get_binlog_end_pos(char file_name_buf[FN_REFLEN]) const
938   {
939     mysql_mutex_assert_not_owner(&LOCK_log);
940     mysql_mutex_assert_owner(&LOCK_binlog_end_pos);
941     strcpy(file_name_buf, binlog_end_pos_file);
942     return binlog_end_pos;
943   }
lock_binlog_end_pos()944   void lock_binlog_end_pos() { mysql_mutex_lock(&LOCK_binlog_end_pos); }
unlock_binlog_end_pos()945   void unlock_binlog_end_pos() { mysql_mutex_unlock(&LOCK_binlog_end_pos); }
get_binlog_end_pos_lock()946   mysql_mutex_t* get_binlog_end_pos_lock() { return &LOCK_binlog_end_pos; }
947 
948   /*
949     Ensures the log's state is either LOG_OPEN or LOG_CLOSED. If something
950     failed along the desired path and left the log in invalid state, i.e.
951     LOG_TO_BE_OPENED, forces the state to be LOG_CLOSED.
952   */
try_fix_log_state()953   void try_fix_log_state()
954   {
955     mysql_mutex_lock(get_log_lock());
956     /* Only change the log state if it is LOG_TO_BE_OPENED */
957     if (log_state == LOG_TO_BE_OPENED)
958       log_state= LOG_CLOSED;
959     mysql_mutex_unlock(get_log_lock());
960   }
961 
962   int wait_for_update_binlog_end_pos(THD* thd, struct timespec * timeout);
963 
964   /*
965     Binlog position of end of the binlog.
966     Access to this is protected by LOCK_binlog_end_pos
967 
968     The difference between this and last_commit_pos_{file,offset} is that
969     the commit position is updated later. If semi-sync wait point is set
970     to WAIT_AFTER_SYNC, the commit pos is update after semi-sync-ack has
971     been received and the end point is updated after the write as it's needed
972     for the dump threads to be able to semi-sync the event.
973   */
974   my_off_t binlog_end_pos;
975   char binlog_end_pos_file[FN_REFLEN];
976 };
977 
978 class Log_event_handler
979 {
980 public:
Log_event_handler()981   Log_event_handler() {}
982   virtual bool init()= 0;
983   virtual void cleanup()= 0;
984 
985   virtual bool log_slow(THD *thd, my_hrtime_t current_time,
986                         const char *user_host, size_t user_host_len, ulonglong query_utime,
987                         ulonglong lock_utime, bool is_command,
988                         const char *sql_text, size_t sql_text_len)= 0;
989   virtual bool log_error(enum loglevel level, const char *format,
990                          va_list args)= 0;
991   virtual bool log_general(THD *thd, my_hrtime_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id,
992                            const char *command_type, size_t command_type_len,
993                            const char *sql_text, size_t sql_text_len,
994                            CHARSET_INFO *client_cs)= 0;
~Log_event_handler()995   virtual ~Log_event_handler() {}
996 };
997 
998 
999 int check_if_log_table(const TABLE_LIST *table, bool check_if_opened,
1000                        const char *errmsg);
1001 
1002 class Log_to_csv_event_handler: public Log_event_handler
1003 {
1004   friend class LOGGER;
1005 
1006 public:
1007   Log_to_csv_event_handler();
1008   ~Log_to_csv_event_handler();
1009   virtual bool init();
1010   virtual void cleanup();
1011 
1012   virtual bool log_slow(THD *thd, my_hrtime_t current_time,
1013                         const char *user_host, size_t user_host_len, ulonglong query_utime,
1014                         ulonglong lock_utime, bool is_command,
1015                         const char *sql_text, size_t sql_text_len);
1016   virtual bool log_error(enum loglevel level, const char *format,
1017                          va_list args);
1018   virtual bool log_general(THD *thd, my_hrtime_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id,
1019                            const char *command_type, size_t command_type_len,
1020                            const char *sql_text, size_t sql_text_len,
1021                            CHARSET_INFO *client_cs);
1022 
1023   int activate_log(THD *thd, uint log_type);
1024 };
1025 
1026 
1027 /* type of the log table */
1028 #define QUERY_LOG_SLOW 1
1029 #define QUERY_LOG_GENERAL 2
1030 
1031 class Log_to_file_event_handler: public Log_event_handler
1032 {
1033   MYSQL_QUERY_LOG mysql_log;
1034   MYSQL_QUERY_LOG mysql_slow_log;
1035   bool is_initialized;
1036 public:
Log_to_file_event_handler()1037   Log_to_file_event_handler(): is_initialized(FALSE)
1038   {}
1039   virtual bool init();
1040   virtual void cleanup();
1041 
1042   virtual bool log_slow(THD *thd, my_hrtime_t current_time,
1043                         const char *user_host, size_t user_host_len, ulonglong query_utime,
1044                         ulonglong lock_utime, bool is_command,
1045                         const char *sql_text, size_t sql_text_len);
1046   virtual bool log_error(enum loglevel level, const char *format,
1047                          va_list args);
1048   virtual bool log_general(THD *thd, my_hrtime_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id,
1049                            const char *command_type, size_t command_type_len,
1050                            const char *sql_text, size_t sql_text_len,
1051                            CHARSET_INFO *client_cs);
1052   void flush();
1053   void init_pthread_objects();
get_mysql_slow_log()1054   MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
get_mysql_log()1055   MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
1056 };
1057 
1058 
1059 /* Class which manages slow, general and error log event handlers */
1060 class LOGGER
1061 {
1062   mysql_rwlock_t LOCK_logger;
1063   /* flag to check whether logger mutex is initialized */
1064   uint inited;
1065 
1066   /* available log handlers */
1067   Log_to_csv_event_handler *table_log_handler;
1068   Log_to_file_event_handler *file_log_handler;
1069 
1070   /* NULL-terminated arrays of log handlers */
1071   Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
1072   Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
1073   Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
1074 
1075 public:
1076 
1077   bool is_log_tables_initialized;
1078 
LOGGER()1079   LOGGER() : inited(0), table_log_handler(NULL),
1080              file_log_handler(NULL), is_log_tables_initialized(FALSE)
1081   {}
lock_shared()1082   void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); }
lock_exclusive()1083   void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); }
unlock()1084   void unlock() { mysql_rwlock_unlock(&LOCK_logger); }
1085   bool is_log_table_enabled(uint log_table_type);
1086   bool log_command(THD *thd, enum enum_server_command command);
1087 
1088   /*
1089     We want to initialize all log mutexes as soon as possible,
1090     but we cannot do it in constructor, as safe_mutex relies on
1091     initialization, performed by MY_INIT(). This why this is done in
1092     this function.
1093   */
1094   void init_base();
1095   void init_log_tables();
1096   bool flush_slow_log();
1097   bool flush_general_log();
1098   /* Perform basic logger cleanup. this will leave e.g. error log open. */
1099   void cleanup_base();
1100   /* Free memory. Nothing could be logged after this function is called */
1101   void cleanup_end();
1102   bool error_log_print(enum loglevel level, const char *format,
1103                       va_list args);
1104   bool slow_log_print(THD *thd, const char *query, size_t query_length,
1105                       ulonglong current_utime);
1106   bool general_log_print(THD *thd,enum enum_server_command command,
1107                          const char *format, va_list args);
1108   bool general_log_write(THD *thd, enum enum_server_command command,
1109                          const char *query, size_t query_length);
1110 
1111   /* we use this function to setup all enabled log event handlers */
1112   int set_handlers(ulonglong error_log_printer,
1113                    ulonglong slow_log_printer,
1114                    ulonglong general_log_printer);
1115   void init_error_log(ulonglong error_log_printer);
1116   void init_slow_log(ulonglong slow_log_printer);
1117   void init_general_log(ulonglong general_log_printer);
1118   void deactivate_log_handler(THD* thd, uint log_type);
1119   bool activate_log_handler(THD* thd, uint log_type);
get_slow_log_file_handler()1120   MYSQL_QUERY_LOG *get_slow_log_file_handler() const
1121   {
1122     if (file_log_handler)
1123       return file_log_handler->get_mysql_slow_log();
1124     return NULL;
1125   }
get_log_file_handler()1126   MYSQL_QUERY_LOG *get_log_file_handler() const
1127   {
1128     if (file_log_handler)
1129       return file_log_handler->get_mysql_log();
1130     return NULL;
1131   }
1132 };
1133 
1134 enum enum_binlog_format {
1135   BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected
1136   BINLOG_FORMAT_STMT=  1, ///< statement-based
1137   BINLOG_FORMAT_ROW=   2, ///< row-based
1138   BINLOG_FORMAT_UNSPEC=3  ///< thd_binlog_format() returns it when binlog is closed
1139 };
1140 
1141 int query_error_code(THD *thd, bool not_killed);
1142 uint purge_log_get_error_code(int res);
1143 
1144 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
1145 void sql_print_error(const char *format, ...);
1146 void sql_print_warning(const char *format, ...);
1147 void sql_print_information(const char *format, ...);
1148 void sql_print_information_v(const char *format, va_list ap);
1149 typedef void (*sql_print_message_func)(const char *format, ...);
1150 extern sql_print_message_func sql_print_message_handlers[];
1151 
1152 int error_log_print(enum loglevel level, const char *format,
1153                     va_list args);
1154 
1155 bool slow_log_print(THD *thd, const char *query, uint query_length,
1156                     ulonglong current_utime);
1157 
1158 bool general_log_print(THD *thd, enum enum_server_command command,
1159                        const char *format,...);
1160 
1161 bool general_log_write(THD *thd, enum enum_server_command command,
1162                        const char *query, size_t query_length);
1163 
1164 void binlog_report_wait_for(THD *thd, THD *other_thd);
1165 void sql_perror(const char *message);
1166 bool flush_error_log();
1167 
1168 File open_binlog(IO_CACHE *log, const char *log_file_name,
1169                  const char **errmsg);
1170 
1171 void make_default_log_name(char **out, const char* log_ext, bool once);
1172 void binlog_reset_cache(THD *thd);
1173 bool write_annotated_row(THD *thd);
1174 
1175 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
1176 extern handlerton *binlog_hton;
1177 extern LOGGER logger;
1178 
1179 extern const char *log_bin_index;
1180 extern const char *log_bin_basename;
1181 
1182 /**
1183   Turns a relative log binary log path into a full path, based on the
1184   opt_bin_logname or opt_relay_logname.
1185 
1186   @param from         The log name we want to make into an absolute path.
1187   @param to           The buffer where to put the results of the
1188                       normalization.
1189   @param is_relay_log Switch that makes is used inside to choose which
1190                       option (opt_bin_logname or opt_relay_logname) to
1191                       use when calculating the base path.
1192 
1193   @returns true if a problem occurs, false otherwise.
1194  */
1195 
normalize_binlog_name(char * to,const char * from,bool is_relay_log)1196 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
1197 {
1198   DBUG_ENTER("normalize_binlog_name");
1199   bool error= false;
1200   char buff[FN_REFLEN];
1201   char *ptr= (char*) from;
1202   char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
1203 
1204   DBUG_ASSERT(from);
1205 
1206   /* opt_name is not null and not empty and from is a relative path */
1207   if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
1208   {
1209     // take the path from opt_name
1210     // take the filename from from
1211     char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
1212     size_t log_dirpart_len, log_dirname_len;
1213     dirname_part(log_dirpart, opt_name, &log_dirpart_len);
1214     dirname_part(log_dirname, from, &log_dirname_len);
1215 
1216     /* log may be empty => relay-log or log-bin did not
1217         hold paths, just filename pattern */
1218     if (log_dirpart_len > 0)
1219     {
1220       /* create the new path name */
1221       if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
1222                    MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
1223       {
1224         error= true;
1225         goto end;
1226       }
1227 
1228       ptr= buff;
1229     }
1230   }
1231 
1232   DBUG_ASSERT(ptr);
1233 
1234   if (ptr)
1235     strmake(to, ptr, strlen(ptr));
1236 
1237 end:
1238   DBUG_RETURN(error);
1239 }
1240 
get_tc_log_implementation()1241 static inline TC_LOG *get_tc_log_implementation()
1242 {
1243   if (total_ha_2pc <= 1)
1244     return &tc_log_dummy;
1245   if (opt_bin_log)
1246     return &mysql_bin_log;
1247   return &tc_log_mmap;
1248 }
1249 
1250 #ifdef WITH_WSREP
1251 IO_CACHE* wsrep_get_trans_cache(THD *);
1252 void wsrep_thd_binlog_trx_reset(THD * thd);
1253 void wsrep_thd_binlog_stmt_rollback(THD * thd);
1254 #endif /* WITH_WSREP */
1255 
1256 class Gtid_list_log_event;
1257 const char *
1258 get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list);
1259 
1260 #endif /* LOG_H */
1261