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