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
515 bool snapshot_lock_acquired;
516
open(const char * opt_name)517 int open(const char *opt_name) { return open_binlog(opt_name); }
518 bool change_stage(THD *thd, Stage_manager::StageID stage,
519 THD* queue, mysql_mutex_t *leave,
520 mysql_mutex_t *enter);
521 std::pair<int,my_off_t> flush_thread_caches(THD *thd);
522 int flush_cache_to_file(my_off_t *flush_end_pos);
523 int finish_commit(THD *thd);
524 std::pair<bool, bool> sync_binlog_file(bool force);
525 void process_commit_stage_queue(THD *thd, THD *queue);
526 void process_after_commit_stage_queue(THD *thd, THD *first);
527 int process_flush_stage_queue(my_off_t *total_bytes_var, bool *rotate_var,
528 THD **out_queue_var);
529 int ordered_commit(THD *thd, bool all, bool skip_commit = false);
530 void handle_binlog_flush_or_sync_error(THD *thd, bool need_lock_log);
531 public:
532 int open_binlog(const char *opt_name);
533 void close();
534 enum_result commit(THD *thd, bool all);
535 int rollback(THD *thd, bool all);
536 int prepare(THD *thd, bool all);
537 int recover(IO_CACHE *log, Format_description_log_event *fdle,
538 my_off_t *valid_pos);
539 int recover(IO_CACHE *log, Format_description_log_event *fdle);
540 #if !defined(MYSQL_CLIENT)
541
542 void update_thd_next_event_pos(THD *thd);
543 int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
544 bool is_transactional);
545 void xlock(void);
546 void xunlock(void);
slock(void)547 void slock(void) { mysql_rwlock_rdlock(&LOCK_consistent_snapshot); }
sunlock(void)548 void sunlock(void) { mysql_rwlock_unlock(&LOCK_consistent_snapshot); }
549 #else
xlock(void)550 void xlock(void) { }
xunlock(void)551 void xunlock(void) { }
slock(void)552 void slock(void) { }
sunlock(void)553 void sunlock(void) { }
554 #endif /* !defined(MYSQL_CLIENT) */
add_bytes_written(ulonglong inc)555 void add_bytes_written(ulonglong inc)
556 {
557 bytes_written += inc;
558 }
reset_bytes_written()559 void reset_bytes_written()
560 {
561 bytes_written = 0;
562 }
563 void harvest_bytes_written(Relay_log_info *rli, bool need_log_space_lock);
564 void set_max_size(ulong max_size_arg);
565 void signal_update();
566 int wait_for_update_relay_log(THD* thd, const struct timespec * timeout);
567 int wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
568 public:
569 void init_pthread_objects();
570 void cleanup();
571 /**
572 Create a new binary log.
573 @param log_name Name of binlog
574 @param new_name Name of binlog, too. todo: what's the difference
575 between new_name and log_name?
576 @param io_cache_type_arg Specifies how the IO cache is opened:
577 read-only or read-write.
578 @param max_size The size at which this binlog will be rotated.
579 @param null_created If false, and a Format_description_log_event
580 is written, then the Format_description_log_event will have the
581 timestamp 0. Otherwise, it the timestamp will be the time when the
582 event was written to the log.
583 @param need_lock_index If true, LOCK_index is acquired; otherwise
584 LOCK_index must be taken by the caller.
585 @param need_sid_lock If true, the read lock on global_sid_lock
586 will be acquired. Otherwise, the caller must hold the read lock
587 on global_sid_lock.
588 */
589 bool open_binlog(const char *log_name,
590 const char *new_name,
591 enum cache_type io_cache_type_arg,
592 ulong max_size,
593 bool null_created,
594 bool need_lock_log,
595 bool need_lock_index, bool need_sid_lock,
596 Format_description_log_event *extra_description_event);
597 bool open_index_file(const char *index_file_name_arg,
598 const char *log_name, bool need_lock_index);
599 /* Use this to start writing a new log file */
600 int new_file(Format_description_log_event *extra_description_event);
601
602 bool write_event(Log_event* event_info);
603 bool write_cache(THD *thd, class binlog_cache_data *binlog_cache_data);
604 int do_write_cache(THD *thd, IO_CACHE *cache);
605
606 /**
607 Write a DML into statement cache and then flush it into binlog. It writes
608 Gtid_log_event and BEGIN, COMMIT automatically.
609
610 It is aimed to handle cases of "background" logging where a statement is
611 logged indirectly, like "DELETE FROM a_memory_table". So don't use it on any
612 normal statement.
613
614 @param[IN] thd the THD object of current thread.
615 @param[IN] stmt the DML statement.
616 @param[IN] stmt_len the length of the DML statement.
617 @param[IN] sql_command type of the DML statement.
618
619 @return Returns false if succeeds, otherwise true is returned.
620 */
621 bool write_dml_directly(THD* thd, const char *stmt, size_t stmt_len,
622 enum enum_sql_command sql_command);
623
624 void set_write_error(THD *thd, bool is_transactional);
625 bool check_write_error(THD *thd);
626 bool write_incident(THD *thd, bool need_lock_log,
627 bool do_flush_and_sync= true);
628 bool write_incident(Incident_log_event *ev, bool need_lock_log,
629 bool do_flush_and_sync= true);
630
631 void start_union_events(THD *thd, query_id_t query_id_param);
632 void stop_union_events(THD *thd);
633 bool is_query_in_union(THD *thd, query_id_t query_id_param);
634
635 #ifdef HAVE_REPLICATION
636 bool append_buffer(const char* buf, uint len, Master_info *mi);
637 bool append_event(Log_event* ev, Master_info *mi);
638 private:
639 bool after_append_to_relay_log(Master_info *mi);
640 #endif // ifdef HAVE_REPLICATION
641 public:
642
643 void make_log_name(char* buf, const char* log_ident);
644 bool is_active(const char* log_file_name);
645 int remove_logs_from_index(LOG_INFO* linfo, bool need_update_threads);
646 int rotate(bool force_rotate, bool* check_purge);
647 void purge();
648 int rotate_and_purge(THD* thd, bool force_rotate);
649 /**
650 Flush binlog cache and synchronize to disk.
651
652 This function flushes events in binlog cache to binary log file,
653 it will do synchronizing according to the setting of system
654 variable 'sync_binlog'. If file is synchronized, @c synced will
655 be set to 1, otherwise 0.
656
657 @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
658 @param[in] force if TRUE, ignores the 'sync_binlog' and synchronizes the file.
659
660 @retval 0 Success
661 @retval other Failure
662 */
663 bool flush_and_sync(const bool force= false);
664 int purge_logs(const char *to_log, bool included,
665 bool need_lock_index, bool need_update_threads,
666 ulonglong *decrease_log_space, bool auto_purge);
667 int purge_logs_maximum_number(ulong max_nr_files);
668 int purge_logs_before_date(time_t purge_time, bool auto_purge);
669 int purge_first_log(Relay_log_info* rli, bool included);
670 int set_crash_safe_index_file_name(const char *base_file_name);
671 int open_crash_safe_index_file();
672 int close_crash_safe_index_file();
673 int add_log_to_index(uchar* log_file_name, int name_len,
674 bool need_lock_index);
675 int move_crash_safe_index_file_to_index_file(bool need_lock_index);
676 int set_purge_index_file_name(const char *base_file_name);
677 int open_purge_index_file(bool destroy);
678 bool is_inited_purge_index_file();
679 int close_purge_index_file();
680 int clean_purge_index_file();
681 int sync_purge_index_file();
682 int register_purge_index_entry(const char* entry);
683 int register_create_index_entry(const char* entry);
684 int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
685 bool need_lock_index);
686 bool reset_logs(THD* thd);
687 void close(uint exiting, bool need_lock_log, bool need_lock_index);
688
689 // iterating through the log index file
690 int find_log_pos(LOG_INFO* linfo, const char* log_name,
691 bool need_lock_index);
692 int find_next_log(LOG_INFO* linfo, bool need_lock_index);
693 int get_current_log(LOG_INFO* linfo, bool need_lock_log= true);
694 int raw_get_current_log(LOG_INFO* linfo);
695 uint next_file_id();
get_index_fname()696 inline char* get_index_fname() { return index_file_name;}
get_log_fname()697 inline char* get_log_fname() { return log_file_name; }
get_name()698 inline char* get_name() { return name; }
get_log_lock()699 inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
get_log_cond()700 inline mysql_cond_t* get_log_cond() { return &update_cond; }
get_log_file()701 inline IO_CACHE* get_log_file() { return &log_file; }
702
lock_index()703 inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
unlock_index()704 inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
get_index_file()705 inline IO_CACHE *get_index_file() { return &index_file;}
get_open_count()706 inline uint32 get_open_count() { return open_count; }
707
708 /**
709 Function to report the missing GTIDs.
710
711 This function logs the missing transactions on master to its error log
712 as a warning. If the missing GTIDs are too long to print in a message,
713 it suggests the steps to extract the missing transactions.
714
715 This function also informs slave about the GTID set sent by the slave,
716 transactions missing on the master and few suggestions to recover from
717 the error. This message shall be wrapped by
718 ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
719 error.
720
721 This function will be called from mysql_binlog_send() function.
722
723 @param slave_executed_gtid_set GTID set executed by slave
724 @param errmsg Pointer to the error message
725
726 @return void
727 */
728 void report_missing_purged_gtids(const Gtid_set* slave_executed_gtid_set,
729 const char** errmsg);
730
731 /**
732 Function to report the missing GTIDs.
733
734 This function logs the missing transactions on master to its error log
735 as a warning. If the missing GTIDs are too long to print in a message,
736 it suggests the steps to extract the missing transactions.
737
738 This function also informs slave about the GTID set sent by the slave,
739 transactions missing on the master and few suggestions to recover from
740 the error. This message shall be wrapped by
741 ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
742 error.
743
744 This function will be called from find_first_log_not_in_gtid_set()
745 function.
746
747 @param previous_gtid_set Previous GTID set found
748 @param slave_executed_gtid_set GTID set executed by slave
749 @param errmsg Pointer to the error message
750
751 @return void
752 */
753 void report_missing_gtids(const Gtid_set* previous_gtid_set,
754 const Gtid_set* slave_executed_gtid_set,
755 const char** errmsg);
756 static const int MAX_RETRIES_FOR_DELETE_RENAME_FAILURE = 5;
757 private:
758 void publish_coordinates_for_global_status(void) const;
759 };
760
761 typedef struct st_load_file_info
762 {
763 THD* thd;
764 my_off_t last_pos_in_file;
765 bool wrote_create_file, log_delayed;
766 } LOAD_FILE_INFO;
767
768 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
769
770 bool trans_has_updated_trans_table(const THD* thd);
771 bool stmt_has_updated_trans_table(Ha_trx_info* ha_list);
772 bool ending_trans(THD* thd, const bool all);
773 bool ending_single_stmt_trans(THD* thd, const bool all);
774 bool trans_cannot_safely_rollback(const THD* thd);
775 bool stmt_cannot_safely_rollback(const THD* thd);
776
777 int log_loaded_block(IO_CACHE* file);
778
779 /**
780 Open a single binary log file for reading.
781 */
782 File open_binlog_file(IO_CACHE *log, const char *log_file_name,
783 const char **errmsg);
784 int check_binlog_magic(IO_CACHE* log, const char** errmsg);
785 bool purge_master_logs(THD* thd, const char* to_log);
786 bool purge_master_logs_before_date(THD* thd, time_t purge_time);
787 bool show_binlog_events(THD *thd, MYSQL_BIN_LOG *binary_log);
788 bool mysql_show_binlog_events(THD* thd);
789 void check_binlog_cache_size(THD *thd);
790 void check_binlog_stmt_cache_size(THD *thd);
791 bool binlog_enabled();
792 void register_binlog_handler(THD *thd, bool trx);
793 int gtid_empty_group_log_and_cleanup(THD *thd);
794
795 extern const char *log_bin_index;
796 extern const char *log_bin_basename;
797 extern bool opt_binlog_order_commits;
798
799 /**
800 Turns a relative log binary log path into a full path, based on the
801 opt_bin_logname or opt_relay_logname.
802
803 @param from The log name we want to make into an absolute path.
804 @param to The buffer where to put the results of the
805 normalization.
806 @param is_relay_log Switch that makes is used inside to choose which
807 option (opt_bin_logname or opt_relay_logname) to
808 use when calculating the base path.
809
810 @returns true if a problem occurs, false otherwise.
811 */
812
normalize_binlog_name(char * to,const char * from,bool is_relay_log)813 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
814 {
815 DBUG_ENTER("normalize_binlog_name");
816 bool error= false;
817 char buff[FN_REFLEN];
818 char *ptr= (char*) from;
819 char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
820
821 DBUG_ASSERT(from);
822
823 /* opt_name is not null and not empty and from is a relative path */
824 if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
825 {
826 // take the path from opt_name
827 // take the filename from from
828 char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
829 size_t log_dirpart_len, log_dirname_len;
830 dirname_part(log_dirpart, opt_name, &log_dirpart_len);
831 dirname_part(log_dirname, from, &log_dirname_len);
832
833 /* log may be empty => relay-log or log-bin did not
834 hold paths, just filename pattern */
835 if (log_dirpart_len > 0)
836 {
837 /* create the new path name */
838 if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
839 MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
840 {
841 error= true;
842 goto end;
843 }
844
845 ptr= buff;
846 }
847 }
848
849 DBUG_ASSERT(ptr);
850
851 if (ptr)
852 strmake(to, ptr, strlen(ptr));
853
854 end:
855 DBUG_RETURN(error);
856 }
857 #endif /* BINLOG_H_INCLUDED */
858