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