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