1 #ifndef BINLOG_H_INCLUDED
2 /* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23
24 #define BINLOG_H_INCLUDED
25
26 #include "mysqld.h" /* opt_relay_logname */
27 #include "log_event.h"
28 #include "log.h"
29
30 class Relay_log_info;
31 class Master_info;
32
33 class Format_description_log_event;
34
35 /**
36 Class for maintaining the commit stages for binary log group commit.
37 */
38 class Stage_manager {
39 public:
40 class Mutex_queue {
41 friend class Stage_manager;
42 public:
Mutex_queue()43 Mutex_queue()
44 : m_first(NULL), m_last(&m_first)
45 {
46 }
47
init(PSI_mutex_key key_LOCK_queue)48 void init(
49 #ifdef HAVE_PSI_INTERFACE
50 PSI_mutex_key key_LOCK_queue
51 #endif
52 ) {
53 mysql_mutex_init(key_LOCK_queue, &m_lock, MY_MUTEX_INIT_FAST);
54 }
55
deinit()56 void deinit() {
57 mysql_mutex_destroy(&m_lock);
58 }
59
is_empty()60 bool is_empty() const {
61 return m_first == NULL;
62 }
63
64 /** Append a linked list of threads to the queue */
65 bool append(THD *first);
66
67 /**
68 Fetch the entire queue for a stage.
69
70 This will fetch the entire queue in one go.
71 */
72 THD *fetch_and_empty();
73
74 std::pair<bool,THD*> pop_front();
75
76 private:
lock()77 void lock() { mysql_mutex_lock(&m_lock); }
unlock()78 void unlock() { mysql_mutex_unlock(&m_lock); }
79
80 /**
81 Pointer to the first thread in the queue, or NULL if the queue is
82 empty.
83 */
84 THD *m_first;
85
86 /**
87 Pointer to the location holding the end of the queue.
88
89 This is either @c &first, or a pointer to the @c next_to_commit of
90 the last thread that is enqueued.
91 */
92 THD **m_last;
93
94 /** Lock for protecting the queue. */
95 mysql_mutex_t m_lock;
96 } MY_ATTRIBUTE((aligned(CPU_LEVEL1_DCACHE_LINESIZE)));
97
98 public:
Stage_manager()99 Stage_manager()
100 {
101 }
102
~Stage_manager()103 ~Stage_manager()
104 {
105 }
106
107 /**
108 Constants for queues for different stages.
109 */
110 enum StageID {
111 FLUSH_STAGE,
112 SYNC_STAGE,
113 COMMIT_STAGE,
114 STAGE_COUNTER
115 };
116
init(PSI_mutex_key key_LOCK_flush_queue,PSI_mutex_key key_LOCK_sync_queue,PSI_mutex_key key_LOCK_commit_queue,PSI_mutex_key key_LOCK_done,PSI_cond_key key_COND_done)117 void init(
118 #ifdef HAVE_PSI_INTERFACE
119 PSI_mutex_key key_LOCK_flush_queue,
120 PSI_mutex_key key_LOCK_sync_queue,
121 PSI_mutex_key key_LOCK_commit_queue,
122 PSI_mutex_key key_LOCK_done,
123 PSI_cond_key key_COND_done
124 #endif
125 )
126 {
127 mysql_mutex_init(key_LOCK_done, &m_lock_done, MY_MUTEX_INIT_FAST);
128 mysql_cond_init(key_COND_done, &m_cond_done, NULL);
129 #ifndef DBUG_OFF
130 /* reuse key_COND_done 'cos a new PSI object would be wasteful in DBUG_ON */
131 mysql_cond_init(key_COND_done, &m_cond_preempt, NULL);
132 #endif
133 m_queue[FLUSH_STAGE].init(
134 #ifdef HAVE_PSI_INTERFACE
135 key_LOCK_flush_queue
136 #endif
137 );
138 m_queue[SYNC_STAGE].init(
139 #ifdef HAVE_PSI_INTERFACE
140 key_LOCK_sync_queue
141 #endif
142 );
143 m_queue[COMMIT_STAGE].init(
144 #ifdef HAVE_PSI_INTERFACE
145 key_LOCK_commit_queue
146 #endif
147 );
148 }
149
deinit()150 void deinit()
151 {
152 for (size_t i = 0 ; i < STAGE_COUNTER ; ++i)
153 m_queue[i].deinit();
154 mysql_cond_destroy(&m_cond_done);
155 mysql_mutex_destroy(&m_lock_done);
156 }
157
158 /**
159 Enroll a set of sessions for a stage.
160
161 This will queue the session thread for writing and flushing.
162
163 If the thread being queued is assigned as stage leader, it will
164 return immediately.
165
166 If wait_if_follower is true the thread is not the stage leader,
167 the thread will be wait for the queue to be processed by the
168 leader before it returns.
169 In DBUG-ON version the follower marks is preempt status as ready.
170
171 @param stage Stage identifier for the queue to append to.
172 @param first Queue to append.
173 @param stage_mutex
174 Pointer to the currently held stage mutex, or NULL if
175 we're not in a stage.
176
177 @retval true Thread is stage leader.
178 @retval false Thread was not stage leader and processing has been done.
179 */
180 bool enroll_for(StageID stage, THD *first, mysql_mutex_t *stage_mutex);
181
pop_front(StageID stage)182 std::pair<bool,THD*> pop_front(StageID stage)
183 {
184 return m_queue[stage].pop_front();
185 }
186
187 #ifndef DBUG_OFF
188 /**
189 The method ensures the follower's execution path can be preempted
190 by the leader's thread.
191 Preempt status of @c head follower is checked to engange the leader
192 into waiting when set.
193
194 @param head THD* of a follower thread
195 */
196 void clear_preempt_status(THD *head);
197 #endif
198
199 /**
200 Fetch the entire queue and empty it.
201
202 @return Pointer to the first session of the queue.
203 */
fetch_queue_for(StageID stage)204 THD *fetch_queue_for(StageID stage) {
205 DBUG_PRINT("debug", ("Fetching queue for stage %d", stage));
206 return m_queue[stage].fetch_and_empty();
207 }
208
signal_done(THD * queue)209 void signal_done(THD *queue) {
210 mysql_mutex_lock(&m_lock_done);
211 for (THD *thd= queue ; thd ; thd = thd->next_to_commit)
212 thd->transaction.flags.pending= false;
213 mysql_mutex_unlock(&m_lock_done);
214 mysql_cond_broadcast(&m_cond_done);
215 }
216
217 private:
218 /**
219 Queues for sessions.
220
221 We need two queues:
222 - Waiting. Threads waiting to be processed
223 - Committing. Threads waiting to be committed.
224 */
225 Mutex_queue m_queue[STAGE_COUNTER];
226
227 /** Condition variable to indicate that the commit was processed */
228 mysql_cond_t m_cond_done;
229
230 /** Mutex used for the condition variable above */
231 mysql_mutex_t m_lock_done;
232 #ifndef DBUG_OFF
233 /** Flag is set by Leader when it starts waiting for follower's all-clear */
234 bool leader_await_preempt_status;
235
236 /** Condition variable to indicate a follower started waiting for commit */
237 mysql_cond_t m_cond_preempt;
238 #endif
239 };
240
241
242 class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
243 {
244 private:
245 #ifdef HAVE_PSI_INTERFACE
246 /** The instrumentation key to use for @ LOCK_index. */
247 PSI_mutex_key m_key_LOCK_index;
248
249 PSI_mutex_key m_key_COND_done;
250
251 PSI_mutex_key m_key_LOCK_commit_queue;
252 PSI_mutex_key m_key_LOCK_done;
253 PSI_mutex_key m_key_LOCK_flush_queue;
254 PSI_mutex_key m_key_LOCK_sync_queue;
255 /** The instrumentation key to use for @ LOCK_commit. */
256 PSI_mutex_key m_key_LOCK_commit;
257 /** The instrumentation key to use for @ LOCK_sync. */
258 PSI_mutex_key m_key_LOCK_sync;
259 /** The instrumentation key to use for @ LOCK_xids. */
260 PSI_mutex_key m_key_LOCK_xids;
261 /** The instrumentation key to use for @ update_cond. */
262 PSI_cond_key m_key_update_cond;
263 /** The instrumentation key to use for @ prep_xids_cond. */
264 PSI_cond_key m_key_prep_xids_cond;
265 /** The instrumentation key to use for opening the log file. */
266 PSI_file_key m_key_file_log;
267 /** The instrumentation key to use for opening the log index file. */
268 PSI_file_key m_key_file_log_index;
269 #endif
270 /* POSIX thread objects are inited by init_pthread_objects() */
271 mysql_mutex_t LOCK_index;
272 mysql_mutex_t LOCK_commit;
273 mysql_mutex_t LOCK_sync;
274 mysql_mutex_t LOCK_xids;
275 mysql_cond_t update_cond;
276 ulonglong bytes_written;
277 IO_CACHE index_file;
278 char index_file_name[FN_REFLEN];
279 /*
280 crash_safe_index_file is temp file used for guaranteeing
281 index file crash safe when master server restarts.
282 */
283 IO_CACHE crash_safe_index_file;
284 char crash_safe_index_file_name[FN_REFLEN];
285 /*
286 purge_file is a temp file used in purge_logs so that the index file
287 can be updated before deleting files from disk, yielding better crash
288 recovery. It is created on demand the first time purge_logs is called
289 and then reused for subsequent calls. It is cleaned up in cleanup().
290 */
291 IO_CACHE purge_index_file;
292 char purge_index_file_name[FN_REFLEN];
293 /*
294 The max size before rotation (usable only if log_type == LOG_BIN: binary
295 logs and relay logs).
296 For a binlog, max_size should be max_binlog_size.
297 For a relay log, it should be max_relay_log_size if this is non-zero,
298 max_binlog_size otherwise.
299 max_size is set in init(), and dynamically changed (when one does SET
300 GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
301 fix_max_relay_log_size).
302 */
303 ulong max_size;
304
305 // current file sequence number for load data infile binary logging
306 uint file_id;
307 uint open_count; // For replication
308 int readers_count;
309
310 /* pointer to the sync period variable, for binlog this will be
311 sync_binlog_period, for relay log this will be
312 sync_relay_log_period
313 */
314 uint *sync_period_ptr;
315 uint sync_counter;
316
317 my_atomic_rwlock_t m_prep_xids_lock;
318 mysql_cond_t m_prep_xids_cond;
319 volatile int32 m_prep_xids;
320
321 /**
322 Increment the prepared XID counter.
323 */
inc_prep_xids(THD * thd)324 void inc_prep_xids(THD *thd) {
325 DBUG_ENTER("MYSQL_BIN_LOG::inc_prep_xids");
326 my_atomic_rwlock_wrlock(&m_prep_xids_lock);
327 #ifndef DBUG_OFF
328 int result= my_atomic_add32(&m_prep_xids, 1);
329 #else
330 (void) my_atomic_add32(&m_prep_xids, 1);
331 #endif
332 DBUG_PRINT("debug", ("m_prep_xids: %d", result + 1));
333 my_atomic_rwlock_wrunlock(&m_prep_xids_lock);
334 thd->transaction.flags.xid_written= true;
335 DBUG_VOID_RETURN;
336 }
337
338 /**
339 Decrement the prepared XID counter.
340
341 Signal m_prep_xids_cond if the counter reaches zero.
342 */
dec_prep_xids(THD * thd)343 void dec_prep_xids(THD *thd) {
344 DBUG_ENTER("MYSQL_BIN_LOG::dec_prep_xids");
345 my_atomic_rwlock_wrlock(&m_prep_xids_lock);
346 int32 result= my_atomic_add32(&m_prep_xids, -1);
347 DBUG_PRINT("debug", ("m_prep_xids: %d", result - 1));
348 my_atomic_rwlock_wrunlock(&m_prep_xids_lock);
349 thd->transaction.flags.xid_written= false;
350 /* If the old value was 1, it is zero now. */
351 if (result == 1)
352 {
353 mysql_mutex_lock(&LOCK_xids);
354 mysql_cond_signal(&m_prep_xids_cond);
355 mysql_mutex_unlock(&LOCK_xids);
356 }
357 DBUG_VOID_RETURN;
358 }
359
get_prep_xids()360 int32 get_prep_xids() {
361 my_atomic_rwlock_rdlock(&m_prep_xids_lock);
362 int32 result= my_atomic_load32(&m_prep_xids);
363 my_atomic_rwlock_rdunlock(&m_prep_xids_lock);
364 return result;
365 }
366
get_sync_period()367 inline uint get_sync_period()
368 {
369 return *sync_period_ptr;
370 }
371
372 int write_to_file(IO_CACHE *cache);
373 /*
374 This is used to start writing to a new log file. The difference from
375 new_file() is locking. new_file_without_locking() does not acquire
376 LOCK_log.
377 */
378 int new_file_without_locking(Format_description_log_event *extra_description_event);
379 int new_file_impl(bool need_lock, Format_description_log_event *extra_description_event);
380
381 /** Manage the stages in ordered_commit. */
382 Stage_manager stage_manager;
383 void do_flush(THD *thd);
384
385 public:
386 using MYSQL_LOG::generate_name;
387 using MYSQL_LOG::is_open;
388
389 /* This is relay log */
390 bool is_relay_log;
391 ulong signal_cnt; // update of the counter is checked by heartbeat
392 uint8 checksum_alg_reset; // to contain a new value when binlog is rotated
393 /*
394 Holds the last seen in Relay-Log FD's checksum alg value.
395 The initial value comes from the slave's local FD that heads
396 the very first Relay-Log file. In the following the value may change
397 with each received master's FD_m.
398 Besides to be used in verification events that IO thread receives
399 (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd),
400 the value specifies if/how to compute checksum for slave's local events
401 and the first fake Rotate (R_f^1) coming from the master.
402 R_f^1 needs logging checksum-compatibly with the RL's heading FD_s.
403
404 Legends for the checksum related comments:
405
406 FD - Format-Description event,
407 R - Rotate event
408 R_f - the fake Rotate event
409 E - an arbirary event
410
411 The underscore indexes for any event
412 `_s' indicates the event is generated by Slave
413 `_m' - by Master
414
415 Two special underscore indexes of FD:
416 FD_q - Format Description event for queuing (relay-logging)
417 FD_e - Format Description event for executing (relay-logging)
418
419 Upper indexes:
420 E^n - n:th event is a sequence
421
422 RL - Relay Log
423 (A) - checksum algorithm descriptor value
424 FD.(A) - the value of (A) in FD
425 */
426 uint8 relay_log_checksum_alg;
427
428 MYSQL_BIN_LOG(uint *sync_period);
429 /*
430 note that there's no destructor ~MYSQL_BIN_LOG() !
431 The reason is that we don't want it to be automatically called
432 on exit() - but only during the correct shutdown process
433 */
434
435 #ifdef HAVE_PSI_INTERFACE
set_psi_keys(PSI_mutex_key key_LOCK_index,PSI_mutex_key key_LOCK_commit,PSI_mutex_key key_LOCK_commit_queue,PSI_mutex_key key_LOCK_done,PSI_mutex_key key_LOCK_flush_queue,PSI_mutex_key key_LOCK_log,PSI_mutex_key key_LOCK_sync,PSI_mutex_key key_LOCK_sync_queue,PSI_mutex_key key_LOCK_xids,PSI_cond_key key_COND_done,PSI_cond_key key_update_cond,PSI_cond_key key_prep_xids_cond,PSI_file_key key_file_log,PSI_file_key key_file_log_index)436 void set_psi_keys(PSI_mutex_key key_LOCK_index,
437 PSI_mutex_key key_LOCK_commit,
438 PSI_mutex_key key_LOCK_commit_queue,
439 PSI_mutex_key key_LOCK_done,
440 PSI_mutex_key key_LOCK_flush_queue,
441 PSI_mutex_key key_LOCK_log,
442 PSI_mutex_key key_LOCK_sync,
443 PSI_mutex_key key_LOCK_sync_queue,
444 PSI_mutex_key key_LOCK_xids,
445 PSI_cond_key key_COND_done,
446 PSI_cond_key key_update_cond,
447 PSI_cond_key key_prep_xids_cond,
448 PSI_file_key key_file_log,
449 PSI_file_key key_file_log_index)
450 {
451 m_key_COND_done= key_COND_done;
452
453 m_key_LOCK_commit_queue= key_LOCK_commit_queue;
454 m_key_LOCK_done= key_LOCK_done;
455 m_key_LOCK_flush_queue= key_LOCK_flush_queue;
456 m_key_LOCK_sync_queue= key_LOCK_sync_queue;
457
458 m_key_LOCK_index= key_LOCK_index;
459 m_key_LOCK_log= key_LOCK_log;
460 m_key_LOCK_commit= key_LOCK_commit;
461 m_key_LOCK_sync= key_LOCK_sync;
462 m_key_LOCK_xids= key_LOCK_xids;
463 m_key_update_cond= key_update_cond;
464 m_key_prep_xids_cond= key_prep_xids_cond;
465 m_key_file_log= key_file_log;
466 m_key_file_log_index= key_file_log_index;
467 }
468 #endif
469 /**
470 Find the oldest binary log that contains any GTID that
471 is not in the given gtid set.
472
473 @param[out] binlog_file_name, the file name of oldest binary log found
474 @param[in] gtid_set, the given gtid set
475 @param[out] first_gtid, the first GTID information from the binary log
476 file returned at binlog_file_name
477 @param[out] errmsg, the error message outputted, which is left untouched
478 if the function returns false
479 @return false on success, true on error.
480 */
481 bool find_first_log_not_in_gtid_set(char *binlog_file_name,
482 const Gtid_set *gtid_set,
483 Gtid *first_gtid,
484 const char **errmsg);
485
486 /**
487 Reads the set of all GTIDs in the binary log, and the set of all
488 lost GTIDs in the binary log, and stores each set in respective
489 argument.
490
491 @param gtid_set Will be filled with all GTIDs in this binary log.
492 @param lost_groups Will be filled with all GTIDs in the
493 Previous_gtids_log_event of the first binary log that has a
494 Previous_gtids_log_event.
495 @param last_gtid Will be filled with the last availble GTID information
496 in the binary/relay log files.
497 @param verify_checksum If true, checksums will be checked.
498 @param need_lock If true, LOCK_log, LOCK_index, and
499 global_sid_lock->wrlock are acquired; otherwise they are asserted
500 to be taken already.
501 @param is_server_starting True if the server is starting.
502 @return false on success, true on error.
503 */
504 bool init_gtid_sets(Gtid_set *gtid_set, Gtid_set *lost_groups,
505 Gtid *last_gtid, bool verify_checksum,
506 bool need_lock, bool is_server_starting= false);
507
set_previous_gtid_set(Gtid_set * previous_gtid_set_param)508 void set_previous_gtid_set(Gtid_set *previous_gtid_set_param)
509 {
510 previous_gtid_set= previous_gtid_set_param;
511 }
512 private:
513 Gtid_set* previous_gtid_set;
514
open(const char * opt_name)515 int open(const char *opt_name) { return open_binlog(opt_name); }
516 bool change_stage(THD *thd, Stage_manager::StageID stage,
517 THD* queue, mysql_mutex_t *leave,
518 mysql_mutex_t *enter);
519 std::pair<int,my_off_t> flush_thread_caches(THD *thd);
520 int flush_cache_to_file(my_off_t *flush_end_pos);
521 int finish_commit(THD *thd);
522 std::pair<bool, bool> sync_binlog_file(bool force);
523 void process_commit_stage_queue(THD *thd, THD *queue);
524 void process_after_commit_stage_queue(THD *thd, THD *first);
525 int process_flush_stage_queue(my_off_t *total_bytes_var, bool *rotate_var,
526 THD **out_queue_var);
527 int ordered_commit(THD *thd, bool all, bool skip_commit = false);
528 void handle_binlog_flush_or_sync_error(THD *thd, bool need_lock_log);
529 public:
530 int open_binlog(const char *opt_name);
531 void close();
532 enum_result commit(THD *thd, bool all);
533 int rollback(THD *thd, bool all);
534 int prepare(THD *thd, bool all);
535 int recover(IO_CACHE *log, Format_description_log_event *fdle,
536 my_off_t *valid_pos);
537 int recover(IO_CACHE *log, Format_description_log_event *fdle);
538 #if !defined(MYSQL_CLIENT)
539
540 void update_thd_next_event_pos(THD *thd);
541 int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
542 bool is_transactional);
543
544 #endif /* !defined(MYSQL_CLIENT) */
add_bytes_written(ulonglong inc)545 void add_bytes_written(ulonglong inc)
546 {
547 bytes_written += inc;
548 }
reset_bytes_written()549 void reset_bytes_written()
550 {
551 bytes_written = 0;
552 }
553 void harvest_bytes_written(Relay_log_info *rli, bool need_log_space_lock);
554 void set_max_size(ulong max_size_arg);
555 void signal_update();
556 int wait_for_update_relay_log(THD* thd, const struct timespec * timeout);
557 int wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
558 public:
559 void init_pthread_objects();
560 void cleanup();
561 /**
562 Create a new binary log.
563 @param log_name Name of binlog
564 @param new_name Name of binlog, too. todo: what's the difference
565 between new_name and log_name?
566 @param io_cache_type_arg Specifies how the IO cache is opened:
567 read-only or read-write.
568 @param max_size The size at which this binlog will be rotated.
569 @param null_created If false, and a Format_description_log_event
570 is written, then the Format_description_log_event will have the
571 timestamp 0. Otherwise, it the timestamp will be the time when the
572 event was written to the log.
573 @param need_lock_index If true, LOCK_index is acquired; otherwise
574 LOCK_index must be taken by the caller.
575 @param need_sid_lock If true, the read lock on global_sid_lock
576 will be acquired. Otherwise, the caller must hold the read lock
577 on global_sid_lock.
578 */
579 bool open_binlog(const char *log_name,
580 const char *new_name,
581 enum cache_type io_cache_type_arg,
582 ulong max_size,
583 bool null_created,
584 bool need_lock_log,
585 bool need_lock_index, bool need_sid_lock,
586 Format_description_log_event *extra_description_event);
587 bool open_index_file(const char *index_file_name_arg,
588 const char *log_name, bool need_lock_index);
589 /* Use this to start writing a new log file */
590 int new_file(Format_description_log_event *extra_description_event);
591
592 bool write_event(Log_event* event_info);
593 bool write_cache(THD *thd, class binlog_cache_data *binlog_cache_data);
594 int do_write_cache(IO_CACHE *cache);
595
596 /**
597 Write a DML into statement cache and then flush it into binlog. It writes
598 Gtid_log_event and BEGIN, COMMIT automatically.
599
600 It is aimed to handle cases of "background" logging where a statement is
601 logged indirectly, like "DELETE FROM a_memory_table". So don't use it on any
602 normal statement.
603
604 @param[IN] thd the THD object of current thread.
605 @param[IN] stmt the DML statement.
606 @param[IN] stmt_len the length of the DML statement.
607 @param[IN] sql_command type of the DML statement.
608
609 @return Returns false if succeeds, otherwise true is returned.
610 */
611 bool write_dml_directly(THD* thd, const char *stmt, size_t stmt_len,
612 enum enum_sql_command sql_command);
613
614 void set_write_error(THD *thd, bool is_transactional);
615 bool check_write_error(THD *thd);
616 bool write_incident(THD *thd, bool need_lock_log,
617 bool do_flush_and_sync= true);
618 bool write_incident(Incident_log_event *ev, bool need_lock_log,
619 bool do_flush_and_sync= true);
620
621 void start_union_events(THD *thd, query_id_t query_id_param);
622 void stop_union_events(THD *thd);
623 bool is_query_in_union(THD *thd, query_id_t query_id_param);
624
625 #ifdef HAVE_REPLICATION
626 bool append_buffer(const char* buf, uint len, Master_info *mi);
627 bool append_event(Log_event* ev, Master_info *mi);
628 private:
629 bool after_append_to_relay_log(Master_info *mi);
630 #endif // ifdef HAVE_REPLICATION
631 public:
632
633 void make_log_name(char* buf, const char* log_ident);
634 bool is_active(const char* log_file_name);
635 int remove_logs_from_index(LOG_INFO* linfo, bool need_update_threads);
636 int rotate(bool force_rotate, bool* check_purge);
637 void purge();
638 int rotate_and_purge(THD* thd, bool force_rotate);
639 /**
640 Flush binlog cache and synchronize to disk.
641
642 This function flushes events in binlog cache to binary log file,
643 it will do synchronizing according to the setting of system
644 variable 'sync_binlog'. If file is synchronized, @c synced will
645 be set to 1, otherwise 0.
646
647 @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
648 @param[in] force if TRUE, ignores the 'sync_binlog' and synchronizes the file.
649
650 @retval 0 Success
651 @retval other Failure
652 */
653 bool flush_and_sync(const bool force= false);
654 int purge_logs(const char *to_log, bool included,
655 bool need_lock_index, bool need_update_threads,
656 ulonglong *decrease_log_space, bool auto_purge);
657 int purge_logs_before_date(time_t purge_time, bool auto_purge);
658 int purge_first_log(Relay_log_info* rli, bool included);
659 int set_crash_safe_index_file_name(const char *base_file_name);
660 int open_crash_safe_index_file();
661 int close_crash_safe_index_file();
662 int add_log_to_index(uchar* log_file_name, int name_len,
663 bool need_lock_index);
664 int move_crash_safe_index_file_to_index_file(bool need_lock_index);
665 int set_purge_index_file_name(const char *base_file_name);
666 int open_purge_index_file(bool destroy);
667 bool is_inited_purge_index_file();
668 int close_purge_index_file();
669 int clean_purge_index_file();
670 int sync_purge_index_file();
671 int register_purge_index_entry(const char* entry);
672 int register_create_index_entry(const char* entry);
673 int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
674 bool need_lock_index);
675 bool reset_logs(THD* thd);
676 void close(uint exiting, bool need_lock_log, bool need_lock_index);
677
678 // iterating through the log index file
679 int find_log_pos(LOG_INFO* linfo, const char* log_name,
680 bool need_lock_index);
681 int find_next_log(LOG_INFO* linfo, bool need_lock_index);
682 int get_current_log(LOG_INFO* linfo, bool need_lock_log= true);
683 int raw_get_current_log(LOG_INFO* linfo);
684 uint next_file_id();
get_index_fname()685 inline char* get_index_fname() { return index_file_name;}
get_log_fname()686 inline char* get_log_fname() { return log_file_name; }
get_name()687 inline char* get_name() { return name; }
get_log_lock()688 inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
get_log_cond()689 inline mysql_cond_t* get_log_cond() { return &update_cond; }
get_log_file()690 inline IO_CACHE* get_log_file() { return &log_file; }
691
lock_index()692 inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
unlock_index()693 inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
get_index_file()694 inline IO_CACHE *get_index_file() { return &index_file;}
get_open_count()695 inline uint32 get_open_count() { return open_count; }
696
697 /**
698 Function to report the missing GTIDs.
699
700 This function logs the missing transactions on master to its error log
701 as a warning. If the missing GTIDs are too long to print in a message,
702 it suggests the steps to extract the missing transactions.
703
704 This function also informs slave about the GTID set sent by the slave,
705 transactions missing on the master and few suggestions to recover from
706 the error. This message shall be wrapped by
707 ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
708 error.
709
710 This function will be called from mysql_binlog_send() function.
711
712 @param slave_executed_gtid_set GTID set executed by slave
713 @param errmsg Pointer to the error message
714
715 @return void
716 */
717 void report_missing_purged_gtids(const Gtid_set* slave_executed_gtid_set,
718 const char** errmsg);
719
720 /**
721 Function to report the missing GTIDs.
722
723 This function logs the missing transactions on master to its error log
724 as a warning. If the missing GTIDs are too long to print in a message,
725 it suggests the steps to extract the missing transactions.
726
727 This function also informs slave about the GTID set sent by the slave,
728 transactions missing on the master and few suggestions to recover from
729 the error. This message shall be wrapped by
730 ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
731 error.
732
733 This function will be called from find_first_log_not_in_gtid_set()
734 function.
735
736 @param previous_gtid_set Previous GTID set found
737 @param slave_executed_gtid_set GTID set executed by slave
738 @param errmsg Pointer to the error message
739
740 @return void
741 */
742 void report_missing_gtids(const Gtid_set* previous_gtid_set,
743 const Gtid_set* slave_executed_gtid_set,
744 const char** errmsg);
745 static const int MAX_RETRIES_FOR_DELETE_RENAME_FAILURE = 5;
746 };
747
748 typedef struct st_load_file_info
749 {
750 THD* thd;
751 my_off_t last_pos_in_file;
752 bool wrote_create_file, log_delayed;
753 } LOAD_FILE_INFO;
754
755 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
756
757 bool trans_has_updated_trans_table(const THD* thd);
758 bool stmt_has_updated_trans_table(Ha_trx_info* ha_list);
759 bool ending_trans(THD* thd, const bool all);
760 bool ending_single_stmt_trans(THD* thd, const bool all);
761 bool trans_cannot_safely_rollback(const THD* thd);
762 bool stmt_cannot_safely_rollback(const THD* thd);
763
764 int log_loaded_block(IO_CACHE* file);
765
766 /**
767 Open a single binary log file for reading.
768 */
769 File open_binlog_file(IO_CACHE *log, const char *log_file_name,
770 const char **errmsg);
771 int check_binlog_magic(IO_CACHE* log, const char** errmsg);
772 bool purge_master_logs(THD* thd, const char* to_log);
773 bool purge_master_logs_before_date(THD* thd, time_t purge_time);
774 bool show_binlog_events(THD *thd, MYSQL_BIN_LOG *binary_log);
775 bool mysql_show_binlog_events(THD* thd);
776 void check_binlog_cache_size(THD *thd);
777 void check_binlog_stmt_cache_size(THD *thd);
778 bool binlog_enabled();
779 void register_binlog_handler(THD *thd, bool trx);
780 int gtid_empty_group_log_and_cleanup(THD *thd);
781
782 extern const char *log_bin_index;
783 extern const char *log_bin_basename;
784 extern bool opt_binlog_order_commits;
785
786 /**
787 Turns a relative log binary log path into a full path, based on the
788 opt_bin_logname or opt_relay_logname.
789
790 @param from The log name we want to make into an absolute path.
791 @param to The buffer where to put the results of the
792 normalization.
793 @param is_relay_log Switch that makes is used inside to choose which
794 option (opt_bin_logname or opt_relay_logname) to
795 use when calculating the base path.
796
797 @returns true if a problem occurs, false otherwise.
798 */
799
normalize_binlog_name(char * to,const char * from,bool is_relay_log)800 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
801 {
802 DBUG_ENTER("normalize_binlog_name");
803 bool error= false;
804 char buff[FN_REFLEN];
805 char *ptr= (char*) from;
806 char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
807
808 DBUG_ASSERT(from);
809
810 /* opt_name is not null and not empty and from is a relative path */
811 if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
812 {
813 // take the path from opt_name
814 // take the filename from from
815 char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
816 size_t log_dirpart_len, log_dirname_len;
817 dirname_part(log_dirpart, opt_name, &log_dirpart_len);
818 dirname_part(log_dirname, from, &log_dirname_len);
819
820 /* log may be empty => relay-log or log-bin did not
821 hold paths, just filename pattern */
822 if (log_dirpart_len > 0)
823 {
824 /* create the new path name */
825 if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
826 MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
827 {
828 error= true;
829 goto end;
830 }
831
832 ptr= buff;
833 }
834 }
835
836 DBUG_ASSERT(ptr);
837
838 if (ptr)
839 strmake(to, ptr, strlen(ptr));
840
841 end:
842 DBUG_RETURN(error);
843 }
844 #endif /* BINLOG_H_INCLUDED */
845