1
/* Copyright (C) 2000-2006 MySQL AB & Sasha
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <drizzled/server_includes.h>
18
#include <drizzled/replication/mi.h>
19
#include <drizzled/replication/replication.h>
20
#include <drizzled/log_event.h>
21
#include <drizzled/replication/filter.h>
22
#include <drizzled/error.h>
23
#include <drizzled/gettext.h>
24
#include <drizzled/data_home.h>
26
int max_binlog_dump_events = 0; // unlimited
29
fake_rotate_event() builds a fake (=which does not exist physically in any
30
binlog) Rotate event, which contains the name of the binlog we are going to
31
send to the slave (because the slave may not know it if it just asked for
32
MASTER_LOG_FILE='', MASTER_LOG_POS=4).
33
< 4.0.14, fake_rotate_event() was called only if the requested pos was 4.
34
After this version we always call it, so that a 3.23.58 slave can rely on
35
it to detect if the master is 4.0 (and stop) (the _fake_ Rotate event has
36
zeros in the good positions which, by chance, make it possible for the 3.23
37
slave to detect that this event is unexpected) (this is luck which happens
38
because the master and slave disagree on the size of the header of
41
Relying on the event length of the Rotate event instead of these
42
well-placed zeros was not possible as Rotate events have a variable-length
45
static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
46
uint64_t position, const char** errmsg)
48
char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN+100];
50
'when' (the timestamp) is set to 0 so that slave could distinguish between
51
real and fake Rotate events (if necessary)
54
header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
56
char* p = log_file_name+dirname_length(log_file_name);
57
uint32_t ident_len = (uint32_t) strlen(p);
58
uint32_t event_len = ident_len + LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN;
59
int4store(header + SERVER_ID_OFFSET, server_id);
60
int4store(header + EVENT_LEN_OFFSET, event_len);
61
int2store(header + FLAGS_OFFSET, 0);
63
// TODO: check what problems this may cause and fix them
64
int4store(header + LOG_POS_OFFSET, 0);
66
packet->append(header, sizeof(header));
67
int8store(buf+R_POS_OFFSET,position);
68
packet->append(buf, ROTATE_HEADER_LEN);
69
packet->append(p,ident_len);
70
if (my_net_write(net, (unsigned char*) packet->ptr(), packet->length()))
72
*errmsg = "failed on my_net_write()";
78
static int send_file(Session *session)
80
NET* net = &session->net;
81
int fd = -1, error = 1;
83
char fname[FN_REFLEN+1];
84
const char *errmsg = 0;
86
unsigned long packet_len;
87
unsigned char buf[IO_SIZE]; // It's safe to alloc this
90
The client might be slow loading the data, give him wait_timeout to do
93
old_timeout= net->read_timeout;
94
my_net_set_read_timeout(net, session->variables.net_wait_timeout);
97
We need net_flush here because the client will not know it needs to send
98
us the file name until it has processed the load event entry
100
if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error)
102
errmsg = _("Failed in send_file() while reading file name");
106
// terminate with \0 for fn_format
107
*((char*)net->read_pos + packet_len) = 0;
108
fn_format(fname, (char*) net->read_pos + 1, "", "", 4);
109
// this is needed to make replicate-ignore-db
110
if (!strcmp(fname,"/dev/null"))
113
if ((fd = my_open(fname, O_RDONLY, MYF(0))) < 0)
115
errmsg = _("Failed in send_file() on open of file");
119
while ((long) (bytes= my_read(fd, buf, IO_SIZE, MYF(0))) > 0)
121
if (my_net_write(net, buf, bytes))
123
errmsg = _("Failed in send_file() while writing data to client");
129
if (my_net_write(net, (unsigned char*) "", 0) || net_flush(net) ||
130
(my_net_read(net) == packet_error))
132
errmsg = _("Failed in send_file() while negotiating file transfer close");
138
my_net_set_read_timeout(net, old_timeout);
140
(void) my_close(fd, MYF(0));
143
sql_print_error("%s",errmsg);
150
Adjust the position pointer in the binary log file for all running slaves
153
adjust_linfo_offsets()
154
purge_offset Number of bytes removed from start of log index file
157
- This is called when doing a PURGE when we delete lines from the
161
- Before calling this function, we have to ensure that no threads are
162
using any binary log file before purge_offset.a
165
- Inform the slave threads that they should sync the position
166
in the binary log file with flush_relay_log_info.
167
Now they sync is done for next read.
170
void adjust_linfo_offsets(my_off_t purge_offset)
174
pthread_mutex_lock(&LOCK_thread_count);
175
I_List_iterator<Session> it(threads);
180
if ((linfo = tmp->current_linfo))
182
pthread_mutex_lock(&linfo->lock);
184
Index file offset can be less that purge offset only if
185
we just started reading the index file. In that case
186
we have nothing to adjust
188
if (linfo->index_file_offset < purge_offset)
189
linfo->fatal = (linfo->index_file_offset != 0);
191
linfo->index_file_offset -= purge_offset;
192
pthread_mutex_unlock(&linfo->lock);
195
pthread_mutex_unlock(&LOCK_thread_count);
199
bool log_in_use(const char* log_name)
201
int log_name_len = strlen(log_name) + 1;
205
pthread_mutex_lock(&LOCK_thread_count);
206
I_List_iterator<Session> it(threads);
211
if ((linfo = tmp->current_linfo))
213
pthread_mutex_lock(&linfo->lock);
214
result = !memcmp(log_name, linfo->log_file_name, log_name_len);
215
pthread_mutex_unlock(&linfo->lock);
221
pthread_mutex_unlock(&LOCK_thread_count);
225
bool purge_error_message(Session* session, int res)
231
case LOG_INFO_EOF: errmsg= ER_UNKNOWN_TARGET_BINLOG; break;
232
case LOG_INFO_IO: errmsg= ER_IO_ERR_LOG_INDEX_READ; break;
233
case LOG_INFO_INVALID:errmsg= ER_BINLOG_PURGE_PROHIBITED; break;
234
case LOG_INFO_SEEK: errmsg= ER_FSEEK_FAIL; break;
235
case LOG_INFO_MEM: errmsg= ER_OUT_OF_RESOURCES; break;
236
case LOG_INFO_FATAL: errmsg= ER_BINLOG_PURGE_FATAL_ERR; break;
237
case LOG_INFO_IN_USE: errmsg= ER_LOG_IN_USE; break;
238
case LOG_INFO_EMFILE: errmsg= ER_BINLOG_PURGE_EMFILE; break;
239
default: errmsg= ER_LOG_PURGE_UNKNOWN_ERR; break;
244
my_message(errmsg, ER(errmsg), MYF(0));
252
bool purge_master_logs(Session* session, const char* to_log)
254
char search_file_name[FN_REFLEN];
255
if (!mysql_bin_log.is_open())
261
mysql_bin_log.make_log_name(search_file_name, to_log);
262
return purge_error_message(session,
263
mysql_bin_log.purge_logs(search_file_name, 0, 1,
268
bool purge_master_logs_before_date(Session* session, time_t purge_time)
270
if (!mysql_bin_log.is_open())
275
return purge_error_message(session,
276
mysql_bin_log.purge_logs_before_date(purge_time));
279
int test_for_non_eof_log_read_errors(int error, const char **errmsg)
281
if (error == LOG_READ_EOF)
283
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
286
*errmsg = "bogus data in log event";
288
case LOG_READ_TOO_LARGE:
289
*errmsg = "log event entry exceeded max_allowed_packet; \
290
Increase max_allowed_packet on master";
293
*errmsg = "I/O error reading log event";
296
*errmsg = "memory allocation failed reading log event";
299
*errmsg = "binlog truncated in the middle of event";
302
*errmsg = "unknown error reading log event on the master";
310
An auxiliary function for calling in mysql_binlog_send
311
to initialize the heartbeat timeout in waiting for a binlogged event.
313
@param[in] session Session to access a user variable
315
@return heartbeat period an uint64_t of nanoseconds
316
or zero if heartbeat was not demanded by slave
318
static uint64_t get_heartbeat_period(Session * session)
321
LEX_STRING name= { C_STRING_WITH_LEN("master_heartbeat_period")};
322
user_var_entry *entry=
323
(user_var_entry*) hash_search(&session->user_vars, (unsigned char*) name.str,
325
return entry? entry->val_int(&null_value) : 0;
329
Function prepares and sends repliation heartbeat event.
331
@param net net object of Session
332
@param packet buffer to store the heartbeat instance
333
@param event_coordinates binlog file name and position of the last
334
real event master sent from binlog
337
Among three essential pieces of heartbeat data Log_event::when
339
The error to send is serious and should force terminating
342
static int send_heartbeat_event(NET* net, String* packet,
343
const struct event_coordinates *coord)
345
char header[LOG_EVENT_HEADER_LEN];
347
'when' (the timestamp) is set to 0 so that slave could distinguish between
348
real and fake Rotate events (if necessary)
350
memset(header, 0, 4); // when
352
header[EVENT_TYPE_OFFSET] = HEARTBEAT_LOG_EVENT;
354
char* p= coord->file_name + dirname_length(coord->file_name);
356
uint32_t ident_len = strlen(p);
357
uint32_t event_len = ident_len + LOG_EVENT_HEADER_LEN;
358
int4store(header + SERVER_ID_OFFSET, server_id);
359
int4store(header + EVENT_LEN_OFFSET, event_len);
360
int2store(header + FLAGS_OFFSET, 0);
362
int4store(header + LOG_POS_OFFSET, coord->pos); // log_pos
364
packet->append(header, sizeof(header));
365
packet->append(p, ident_len); // log_file_name
367
if (my_net_write(net, (unsigned char*) packet->ptr(), packet->length()) ||
372
packet->set("\0", 1, &my_charset_bin);
377
TODO: Clean up loop to only have one call to send_file()
380
void mysql_binlog_send(Session* session, char* log_ident, my_off_t pos,
384
char *log_file_name = linfo.log_file_name;
385
char search_file_name[FN_REFLEN], *name;
388
String* packet = &session->packet;
390
const char *errmsg = "Unknown error";
391
NET* net = &session->net;
392
pthread_mutex_t *log_lock;
393
bool binlog_can_be_corrupted= false;
395
memset(&log, 0, sizeof(log));
397
heartbeat_period from @master_heartbeat_period user variable
399
uint64_t heartbeat_period= get_heartbeat_period(session);
400
struct timespec heartbeat_buf;
401
struct event_coordinates coord_buf;
402
struct timespec *heartbeat_ts= NULL;
403
struct event_coordinates *coord= NULL;
404
if (heartbeat_period != 0L)
406
heartbeat_ts= &heartbeat_buf;
407
set_timespec_nsec(*heartbeat_ts, 0);
409
coord->file_name= log_file_name; // initialization basing on what slave remembers
413
if (!mysql_bin_log.is_open())
415
errmsg = "Binary log is not open";
416
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
419
if (!server_id_supplied)
421
errmsg = "Misconfigured master - server id was not set";
422
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
426
name=search_file_name;
428
mysql_bin_log.make_log_name(search_file_name, log_ident);
430
name=0; // Find first log
432
linfo.index_file_offset = 0;
434
if (mysql_bin_log.find_log_pos(&linfo, name, 1))
436
errmsg = "Could not find first log file name in binary log index file";
437
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
441
pthread_mutex_lock(&LOCK_thread_count);
442
session->current_linfo = &linfo;
443
pthread_mutex_unlock(&LOCK_thread_count);
445
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
447
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
450
if (pos < BIN_LOG_HEADER_SIZE || pos > my_b_filelength(&log))
452
errmsg= "Client requested master to start replication from \
453
impossible position";
454
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
459
We need to start a packet with something other than 255
460
to distinguish it from error
462
packet->set("\0", 1, &my_charset_bin); /* This is the start of a new packet */
465
Tell the client about the log name with a fake Rotate event;
466
this is needed even if we also send a Format_description_log_event
467
just after, because that event does not contain the binlog's name.
468
Note that as this Rotate event is sent before
469
Format_description_log_event, the slave cannot have any info to
470
understand this event's format, so the header len of
471
Rotate_log_event is FROZEN (so in 5.0 it will have a header shorter
472
than other events except FORMAT_DESCRIPTION_EVENT).
473
Before 4.0.14 we called fake_rotate_event below only if (pos ==
474
BIN_LOG_HEADER_SIZE), because if this is false then the slave
475
already knows the binlog's name.
476
Since, we always call fake_rotate_event; if the slave already knew
477
the log's name (ex: CHANGE MASTER TO MASTER_LOG_FILE=...) this is
478
useless but does not harm much. It is nice for 3.23 (>=.58) slaves
479
which test Rotate events to see if the master is 4.0 (then they
480
choose to stop because they can't replicate 4.0); by always calling
481
fake_rotate_event we are sure that 3.23.58 and newer will detect the
482
problem as soon as replication starts (BUG#198).
483
Always calling fake_rotate_event makes sending of normal
484
(=from-binlog) Rotate events a priori unneeded, but it is not so
485
simple: the 2 Rotate events are not equivalent, the normal one is
486
before the Stop event, the fake one is after. If we don't send the
487
normal one, then the Stop event will be interpreted (by existing 4.0
488
slaves) as "the master stopped", which is wrong. So for safety,
489
given that we want minimum modification of 4.0, we send the normal
492
if (fake_rotate_event(net, packet, log_file_name, pos, &errmsg))
495
This error code is not perfect, as fake_rotate_event() does not
496
read anything from the binlog; if it fails it's because of an
497
error in my_net_write(), fortunately it will say so in errmsg.
499
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
502
packet->set("\0", 1, &my_charset_bin);
504
Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
505
this larger than the corresponding packet (query) sent
506
from client to master.
508
session->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
511
We can set log_lock now, it does not move (it's a member of
512
mysql_bin_log, and it's already inited, and it will be destroyed
515
log_lock = mysql_bin_log.get_log_lock();
516
if (pos > BIN_LOG_HEADER_SIZE)
519
Try to find a Format_description_log_event at the beginning of
522
if (!(error = Log_event::read_log_event(&log, packet, log_lock)))
525
The packet has offsets equal to the normal offsets in a binlog
526
event +1 (the first character is \0).
528
if ((*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
530
binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] &
531
LOG_EVENT_BINLOG_IN_USE_F);
532
(*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F;
534
mark that this event with "log_pos=0", so the slave
535
should not increment master's binlog position
536
(rli->group_master_log_pos)
538
int4store((char*) packet->ptr()+LOG_POS_OFFSET+1, 0);
540
if reconnect master sends FD event with `created' as 0
541
to avoid destroying temp tables.
543
int4store((char*) packet->ptr()+LOG_EVENT_MINIMAL_HEADER_LEN+
544
ST_CREATED_OFFSET+1, (uint32_t) 0);
546
if (my_net_write(net, (unsigned char*) packet->ptr(), packet->length()))
548
errmsg = "Failed on my_net_write()";
549
my_errno= ER_UNKNOWN_ERROR;
554
No need to save this event. We are only doing simple reads
555
(no real parsing of the events) so we don't need it. And so
556
we don't need the artificial Format_description_log_event of
563
if (test_for_non_eof_log_read_errors(error, &errmsg))
566
It's EOF, nothing to do, go on reading next events, the
567
Format_description_log_event will be found naturally if it is written.
570
/* reset the packet as we wrote to it in any case */
571
packet->set("\0", 1, &my_charset_bin);
572
} /* end of if (pos > BIN_LOG_HEADER_SIZE); */
575
/* The Format_description_log_event event will be found naturally. */
578
/* seek to the requested position, to start the requested dump */
579
my_b_seek(&log, pos); // Seek will done on next read
581
while (!net->error && net->vio != 0 && !session->killed)
583
while (!(error = Log_event::read_log_event(&log, packet, log_lock)))
586
log's filename does not change while it's active
589
coord->pos= uint4korr(packet->ptr() + 1 + LOG_POS_OFFSET);
591
if ((*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
593
binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] &
594
LOG_EVENT_BINLOG_IN_USE_F);
595
(*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F;
597
else if ((*packet)[EVENT_TYPE_OFFSET+1] == STOP_EVENT)
598
binlog_can_be_corrupted= false;
600
if (my_net_write(net, (unsigned char*) packet->ptr(), packet->length()))
602
errmsg = "Failed on my_net_write()";
603
my_errno= ER_UNKNOWN_ERROR;
607
if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
609
if (send_file(session))
611
errmsg = "failed in send_file()";
612
my_errno= ER_UNKNOWN_ERROR;
616
packet->set("\0", 1, &my_charset_bin);
620
here we were reading binlog that was not closed properly (as a result
621
of a crash ?). treat any corruption as EOF
623
if (binlog_can_be_corrupted && error != LOG_READ_MEM)
626
TODO: now that we are logging the offset, check to make sure
627
the recorded offset and the actual match.
628
Guilhem 2003-06: this is not true if this master is a slave
629
<4.0.15 running with --log-slave-updates, because then log_pos may
630
be the offset in the-master-of-this-master's binlog.
632
if (test_for_non_eof_log_read_errors(error, &errmsg))
635
if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
636
mysql_bin_log.is_active(log_file_name))
639
Block until there is more data in the log
643
errmsg = "failed on net_flush()";
644
my_errno= ER_UNKNOWN_ERROR;
649
We may have missed the update broadcast from the log
650
that has just happened, let's try to catch it if it did.
651
If we did not miss anything, we just wait for other threads
656
bool read_packet = 0, fatal_error = 0;
659
No one will update the log while we are reading
660
now, but we'll be quick and just read one record
663
Add an counter that is incremented for each time we update the
664
binary log. We can avoid the following read if the counter
665
has not been updated since last read.
668
pthread_mutex_lock(log_lock);
669
switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*)0)) {
671
/* we read successfully, so we'll need to send it to the slave */
672
pthread_mutex_unlock(log_lock);
675
coord->pos= uint4korr(packet->ptr() + 1 + LOG_POS_OFFSET);
681
if (session->server_id==0) // for mysqlbinlog (mysqlbinlog.server_id==0)
683
pthread_mutex_unlock(log_lock);
691
assert(heartbeat_ts && heartbeat_period != 0L);
692
set_timespec_nsec(*heartbeat_ts, heartbeat_period);
694
ret= mysql_bin_log.wait_for_update_bin_log(session, heartbeat_ts);
695
assert(ret == 0 || (heartbeat_period != 0L && coord != NULL));
696
if (ret == ETIMEDOUT || ret == ETIME)
698
if (send_heartbeat_event(net, packet, coord))
700
errmsg = "Failed on my_net_write()";
701
my_errno= ER_UNKNOWN_ERROR;
702
pthread_mutex_unlock(log_lock);
710
} while (ret != 0 && coord != NULL && !session->killed);
711
pthread_mutex_unlock(log_lock);
716
pthread_mutex_unlock(log_lock);
723
session->set_proc_info("Sending binlog event to slave");
724
if (my_net_write(net, (unsigned char*) packet->ptr(), packet->length()) )
726
errmsg = "Failed on my_net_write()";
727
my_errno= ER_UNKNOWN_ERROR;
731
if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
733
if (send_file(session))
735
errmsg = "failed in send_file()";
736
my_errno= ER_UNKNOWN_ERROR;
740
packet->set("\0", 1, &my_charset_bin);
742
No need to net_flush because we will get to flush later when
743
we hit EOF pretty quick
749
errmsg = "error reading log entry";
750
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
758
bool loop_breaker = 0;
759
/* need this to break out of the for loop from switch */
761
session->set_proc_info("Finished reading one binlog; switching to next binlog");
762
switch (mysql_bin_log.find_next_log(&linfo, 1)) {
764
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
769
errmsg = "could not find next log";
770
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
778
(void) my_close(file, MYF(MY_WME));
781
Call fake_rotate_event() in case the previous log (the one which
782
we have just finished reading) did not contain a Rotate event
783
(for example (I don't know any other example) the previous log
784
was the last one before the master was shutdown & restarted).
785
This way we tell the slave about the new log's name and
786
position. If the binlog is 5.0, the next event we are going to
787
read and send is Format_description_log_event.
789
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
790
fake_rotate_event(net, packet, log_file_name, BIN_LOG_HEADER_SIZE,
793
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
798
packet->append('\0');
800
coord->file_name= log_file_name; // reset to the next
806
(void)my_close(file, MYF(MY_WME));
809
session->set_proc_info("Waiting to finalize termination");
810
pthread_mutex_lock(&LOCK_thread_count);
811
session->current_linfo = 0;
812
pthread_mutex_unlock(&LOCK_thread_count);
816
session->set_proc_info("Waiting to finalize termination");
819
Exclude iteration through thread list
820
this is needed for purge_logs() - it will iterate through
821
thread list and update session->current_linfo->index_file_offset
822
this mutex will make sure that it never tried to update our linfo
823
after we return from this stack frame
825
pthread_mutex_lock(&LOCK_thread_count);
826
session->current_linfo = 0;
827
pthread_mutex_unlock(&LOCK_thread_count);
829
(void) my_close(file, MYF(MY_WME));
831
my_message(my_errno, errmsg, MYF(0));
835
int start_slave(Session* session , Master_info* mi, bool net_report)
840
lock_slave_threads(mi); // this allows us to cleanly read slave_running
841
// Get a mask of _stopped_ threads
842
init_thread_mask(&thread_mask,mi,1 /* inverse */);
844
Below we will start all stopped threads. But if the user wants to
845
start only one thread, do as if the other thread was running (as we
846
don't wan't to touch the other thread), so set the bit to 0 for the
849
if (session->lex->slave_session_opt)
850
thread_mask&= session->lex->slave_session_opt;
851
if (thread_mask) //some threads are stopped, start them
853
if (mi->init_master_info(master_info_file, relay_log_info_file, thread_mask))
854
slave_errno=ER_MASTER_INFO;
855
else if (server_id_supplied && *mi->getHostname())
858
If we will start SQL thread we will care about UNTIL options If
859
not and they are specified we will ignore them and warn user
862
if (thread_mask & SLAVE_SQL)
864
pthread_mutex_lock(&mi->rli.data_lock);
866
if (session->lex->mi.pos)
868
mi->rli.until_condition= Relay_log_info::UNTIL_MASTER_POS;
869
mi->rli.until_log_pos= session->lex->mi.pos;
871
We don't check session->lex->mi.log_file_name for NULL here
872
since it is checked in sql_yacc.yy
874
strmake(mi->rli.until_log_name, session->lex->mi.log_file_name,
875
sizeof(mi->rli.until_log_name)-1);
877
else if (session->lex->mi.relay_log_pos)
879
mi->rli.until_condition= Relay_log_info::UNTIL_RELAY_POS;
880
mi->rli.until_log_pos= session->lex->mi.relay_log_pos;
881
strmake(mi->rli.until_log_name, session->lex->mi.relay_log_name,
882
sizeof(mi->rli.until_log_name)-1);
885
mi->rli.clear_until_condition();
887
if (mi->rli.until_condition != Relay_log_info::UNTIL_NONE)
889
/* Preparing members for effective until condition checking */
890
const char *p= fn_ext(mi->rli.until_log_name);
895
mi->rli.until_log_name_extension= strtoul(++p,&p_end, 10);
897
p_end points to the first invalid character. If it equals
898
to p, no digits were found, error. If it contains '\0' it
899
means conversion went ok.
901
if (p_end==p || *p_end)
902
slave_errno=ER_BAD_SLAVE_UNTIL_COND;
905
slave_errno=ER_BAD_SLAVE_UNTIL_COND;
907
/* mark the cached result of the UNTIL comparison as "undefined" */
908
mi->rli.until_log_names_cmp_result=
909
Relay_log_info::UNTIL_LOG_NAMES_CMP_UNKNOWN;
911
/* Issuing warning then started without --skip-slave-start */
912
if (!opt_skip_slave_start)
913
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
914
ER_MISSING_SKIP_SLAVE,
915
ER(ER_MISSING_SKIP_SLAVE));
918
pthread_mutex_unlock(&mi->rli.data_lock);
920
else if (session->lex->mi.pos || session->lex->mi.relay_log_pos)
921
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_UNTIL_COND_IGNORED,
922
ER(ER_UNTIL_COND_IGNORED));
925
slave_errno = start_slave_threads(0 /*no mutex */,
926
1 /* wait for start */,
928
master_info_file,relay_log_info_file,
932
slave_errno = ER_BAD_SLAVE;
936
/* no error if all threads are already started, only a warning */
937
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_SLAVE_WAS_RUNNING,
938
ER(ER_SLAVE_WAS_RUNNING));
941
unlock_slave_threads(mi);
946
my_message(slave_errno, ER(slave_errno), MYF(0));
956
int stop_slave(Session* session, Master_info* mi, bool net_report )
960
session = current_session;
962
session->set_proc_info("Killing slave");
964
lock_slave_threads(mi);
965
// Get a mask of _running_ threads
966
init_thread_mask(&thread_mask,mi,0 /* not inverse*/);
968
Below we will stop all running threads.
969
But if the user wants to stop only one thread, do as if the other thread
970
was stopped (as we don't wan't to touch the other thread), so set the
971
bit to 0 for the other thread
973
if (session->lex->slave_session_opt)
974
thread_mask &= session->lex->slave_session_opt;
978
slave_errno= terminate_slave_threads(mi,thread_mask,
983
//no error if both threads are already stopped, only a warning
985
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_SLAVE_WAS_NOT_RUNNING,
986
ER(ER_SLAVE_WAS_NOT_RUNNING));
988
unlock_slave_threads(mi);
989
session->set_proc_info(0);
994
my_message(slave_errno, ER(slave_errno), MYF(0));
1005
Remove all relay logs and start replication from the start
1009
session Thread handler
1010
mi Master info for the slave
1018
int reset_slave(Session *session, Master_info* mi)
1020
struct stat stat_area;
1021
char fname[FN_REFLEN];
1022
int thread_mask= 0, error= 0;
1023
uint32_t sql_errno=0;
1024
const char* errmsg=0;
1026
lock_slave_threads(mi);
1027
init_thread_mask(&thread_mask,mi,0 /* not inverse */);
1028
if (thread_mask) // We refuse if any slave thread is running
1030
sql_errno= ER_SLAVE_MUST_STOP;
1035
// delete relay logs, clear relay log coordinates
1036
if ((error= purge_relay_logs(&mi->rli, session,
1041
/* Clear master's log coordinates */
1044
Reset errors (the idea is that we forget about the
1047
mi->rli.clear_error();
1048
mi->rli.clear_until_condition();
1050
// close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
1051
mi->end_master_info();
1052
// and delete these two files
1053
fn_format(fname, master_info_file, drizzle_data_home, "", 4+32);
1054
if (!stat(fname, &stat_area) && my_delete(fname, MYF(MY_WME)))
1059
// delete relay_log_info_file
1060
fn_format(fname, relay_log_info_file, drizzle_data_home, "", 4+32);
1061
if (!stat(fname, &stat_area) && my_delete(fname, MYF(MY_WME)))
1068
unlock_slave_threads(mi);
1070
my_error(sql_errno, MYF(0), errmsg);
1076
Kill all Binlog_dump threads which previously talked to the same slave
1077
("same" means with the same server id). Indeed, if the slave stops, if the
1078
Binlog_dump thread is waiting (pthread_cond_wait) for binlog update, then it
1079
will keep existing until a query is written to the binlog. If the master is
1080
idle, then this could last long, and if the slave reconnects, we could have 2
1081
Binlog_dump threads in SHOW PROCESSLIST, until a query is written to the
1082
binlog. To avoid this, when the slave reconnects and sends COM_BINLOG_DUMP,
1083
the master kills any existing thread with the slave's server id (if this id is
1084
not zero; it will be true for real slaves, but false for mysqlbinlog when it
1085
sends COM_BINLOG_DUMP to get a remote binlog dump).
1088
kill_zombie_dump_threads()
1089
slave_server_id the slave's server id
1094
void kill_zombie_dump_threads(uint32_t slave_server_id)
1096
pthread_mutex_lock(&LOCK_thread_count);
1097
I_List_iterator<Session> it(threads);
1102
if (tmp->command == COM_BINLOG_DUMP &&
1103
tmp->server_id == slave_server_id)
1105
pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete
1109
pthread_mutex_unlock(&LOCK_thread_count);
1113
Here we do not call kill_one_thread() as
1114
it will be slow because it will iterate through the list
1115
again. We just to do kill the thread ourselves.
1117
tmp->awake(Session::KILL_QUERY);
1118
pthread_mutex_unlock(&tmp->LOCK_delete);
1123
bool change_master(Session* session, Master_info* mi)
1126
const char* errmsg= 0;
1127
bool need_relay_log_purge= 1;
1129
lock_slave_threads(mi);
1130
init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
1131
if (thread_mask) // We refuse if any slave thread is running
1133
my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
1134
unlock_slave_threads(mi);
1138
session->set_proc_info("Changing master");
1139
LEX_MASTER_INFO* lex_mi= &session->lex->mi;
1140
// TODO: see if needs re-write
1141
if (mi->init_master_info(master_info_file, relay_log_info_file, thread_mask))
1143
my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
1144
unlock_slave_threads(mi);
1149
Data lock not needed since we have already stopped the running threads,
1150
and we have the hold on the run locks which will keep all threads that
1151
could possibly modify the data structures from running
1155
If the user specified host or port without binlog or position,
1156
reset binlog's name to FIRST and position to 4.
1159
if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
1162
if (lex_mi->log_file_name)
1163
mi->setLogName(lex_mi->log_file_name);
1166
mi->setLogPosition(lex_mi->pos);
1170
mi->setHost(lex_mi->host, lex_mi->port);
1172
mi->setUsername(lex_mi->user);
1173
if (lex_mi->password)
1174
mi->setPassword(lex_mi->password);
1175
if (lex_mi->connect_retry)
1176
mi->connect_retry = lex_mi->connect_retry;
1177
if (lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
1178
mi->heartbeat_period = lex_mi->heartbeat_period;
1180
mi->heartbeat_period= (float) cmin((double)SLAVE_MAX_HEARTBEAT_PERIOD,
1181
(slave_net_timeout/2.0));
1182
mi->received_heartbeats= 0L; // counter lives until master is CHANGEd
1184
if (lex_mi->relay_log_name)
1186
need_relay_log_purge= 0;
1187
mi->rli.event_relay_log_name.assign(lex_mi->relay_log_name);
1190
if (lex_mi->relay_log_pos)
1192
need_relay_log_purge= 0;
1193
mi->rli.group_relay_log_pos= mi->rli.event_relay_log_pos= lex_mi->relay_log_pos;
1197
If user did specify neither host nor port nor any log name nor any log
1198
pos, i.e. he specified only user/password/master_connect_retry, he probably
1199
wants replication to resume from where it had left, i.e. from the
1200
coordinates of the **SQL** thread (imagine the case where the I/O is ahead
1201
of the SQL; restarting from the coordinates of the I/O would lose some
1202
events which is probably unwanted when you are just doing minor changes
1203
like changing master_connect_retry).
1204
A side-effect is that if only the I/O thread was started, this thread may
1205
restart from ''/4 after the CHANGE MASTER. That's a minor problem (it is a
1206
much more unlikely situation than the one we are fixing here).
1207
Note: coordinates of the SQL thread must be read here, before the
1208
'if (need_relay_log_purge)' block which resets them.
1210
if (!lex_mi->host && !lex_mi->port &&
1211
!lex_mi->log_file_name && !lex_mi->pos &&
1212
need_relay_log_purge)
1215
Sometimes mi->rli.master_log_pos == 0 (it happens when the SQL thread is
1216
not initialized), so we use a cmax().
1217
What happens to mi->rli.master_log_pos during the initialization stages
1218
of replication is not 100% clear, so we guard against problems using
1221
mi->setLogPosition(((BIN_LOG_HEADER_SIZE > mi->rli.group_master_log_pos)
1222
? BIN_LOG_HEADER_SIZE
1223
: mi->rli.group_master_log_pos));
1224
mi->setLogName(mi->rli.group_master_log_name.c_str());
1227
Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never
1232
my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file");
1233
unlock_slave_threads(mi);
1236
if (need_relay_log_purge)
1239
session->set_proc_info("Purging old relay logs");
1240
if (purge_relay_logs(&mi->rli, session,
1241
0 /* not only reset, but also reinit */,
1244
my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
1245
unlock_slave_threads(mi);
1253
/* Relay log is already initialized */
1254
if (init_relay_log_pos(&mi->rli,
1255
mi->rli.group_relay_log_name.c_str(),
1256
mi->rli.group_relay_log_pos,
1260
my_error(ER_RELAY_LOG_INIT, MYF(0), msg);
1261
unlock_slave_threads(mi);
1266
Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block,
1267
so restore them to good values. If we left them to ''/0, that would work;
1268
but that would fail in the case of 2 successive CHANGE MASTER (without a
1269
START SLAVE in between): because first one would set the coords in mi to
1270
the good values of those in rli, the set those in rli to ''/0, then
1271
second CHANGE MASTER would set the coords in mi to those of rli, i.e. to
1272
''/0: we have lost all copies of the original good coordinates.
1273
That's why we always save good coords in rli.
1275
mi->rli.group_master_log_pos= mi->getLogPosition();
1276
mi->rli.group_master_log_name.assign(mi->getLogName());
1278
if (mi->rli.group_master_log_name.size() == 0) // uninitialized case
1279
mi->rli.group_master_log_pos= 0;
1281
pthread_mutex_lock(&mi->rli.data_lock);
1282
mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */
1283
/* Clear the errors, for a clean start */
1284
mi->rli.clear_error();
1285
mi->rli.clear_until_condition();
1287
If we don't write new coordinates to disk now, then old will remain in
1288
relay-log.info until START SLAVE is issued; but if mysqld is shutdown
1289
before START SLAVE, then old will remain in relay-log.info, and will be the
1290
in-memory value at restart (thus causing errors, as the old relay log does
1293
flush_relay_log_info(&mi->rli);
1294
pthread_cond_broadcast(&mi->data_cond);
1295
pthread_mutex_unlock(&mi->rli.data_lock);
1297
unlock_slave_threads(mi);
1298
session->set_proc_info(0);
1303
int reset_master(Session* session)
1305
if (!mysql_bin_log.is_open())
1307
my_message(ER_FLUSH_MASTER_BINLOG_CLOSED,
1308
ER(ER_FLUSH_MASTER_BINLOG_CLOSED), MYF(ME_BELL+ME_WAITTANG));
1311
return mysql_bin_log.reset_logs(session);
1314
int cmp_master_pos(const char* log_file_name1, uint64_t log_pos1,
1315
const char* log_file_name2, uint64_t log_pos2)
1318
uint32_t log_file_name1_len= strlen(log_file_name1);
1319
uint32_t log_file_name2_len= strlen(log_file_name2);
1321
// We assume that both log names match up to '.'
1322
if (log_file_name1_len == log_file_name2_len)
1324
if ((res= strcmp(log_file_name1, log_file_name2)))
1326
return (log_pos1 < log_pos2) ? -1 : (log_pos1 == log_pos2) ? 0 : 1;
1328
return ((log_file_name1_len < log_file_name2_len) ? -1 : 1);
1332
bool show_binlog_info(Session* session)
1334
Protocol *protocol= session->protocol;
1335
List<Item> field_list;
1336
field_list.push_back(new Item_empty_string("File", FN_REFLEN));
1337
field_list.push_back(new Item_return_int("Position",20,
1338
DRIZZLE_TYPE_LONGLONG));
1339
field_list.push_back(new Item_empty_string("Binlog_Do_DB",255));
1340
field_list.push_back(new Item_empty_string("Binlog_Ignore_DB",255));
1342
if (protocol->send_fields(&field_list,
1343
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1345
protocol->prepare_for_resend();
1347
if (mysql_bin_log.is_open())
1350
mysql_bin_log.get_current_log(&li);
1351
int dir_len = dirname_length(li.log_file_name);
1352
protocol->store(li.log_file_name + dir_len, &my_charset_bin);
1353
protocol->store((uint64_t) li.pos);
1354
protocol->store(binlog_filter->get_do_db());
1355
protocol->store(binlog_filter->get_ignore_db());
1356
if (protocol->write())
1365
Send a list of all binary logs to client
1369
session Thread specific variable
1376
bool show_binlogs(Session* session)
1378
IO_CACHE *index_file;
1381
char fname[FN_REFLEN];
1382
List<Item> field_list;
1385
Protocol *protocol= session->protocol;
1387
if (!mysql_bin_log.is_open())
1389
my_message(ER_NO_BINARY_LOGGING, ER(ER_NO_BINARY_LOGGING), MYF(0));
1393
field_list.push_back(new Item_empty_string("Log_name", 255));
1394
field_list.push_back(new Item_return_int("File_size", 20,
1395
DRIZZLE_TYPE_LONGLONG));
1396
if (protocol->send_fields(&field_list,
1397
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1400
pthread_mutex_lock(mysql_bin_log.get_log_lock());
1401
mysql_bin_log.lock_index();
1402
index_file=mysql_bin_log.get_index_file();
1404
mysql_bin_log.raw_get_current_log(&cur); // dont take mutex
1405
pthread_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK
1407
cur_dir_len= dirname_length(cur.log_file_name);
1409
reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0);
1411
/* The file ends with EOF or empty line */
1412
while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
1415
uint64_t file_length= 0; // Length if open fails
1416
fname[--length] = '\0'; // remove the newline
1418
protocol->prepare_for_resend();
1419
dir_len= dirname_length(fname);
1421
protocol->store(fname + dir_len, length, &my_charset_bin);
1423
if (!(strncmp(fname+dir_len, cur.log_file_name+cur_dir_len, length)))
1424
file_length= cur.pos; /* The active log, use the active position */
1427
/* this is an old log, open it and find the size */
1428
if ((file= my_open(fname, O_RDONLY,
1431
file_length= (uint64_t) my_seek(file, 0L, MY_SEEK_END, MYF(0));
1432
my_close(file, MYF(0));
1435
protocol->store(file_length);
1436
if (protocol->write())
1439
mysql_bin_log.unlock_index();
1444
mysql_bin_log.unlock_index();
1449
Load data's io cache specific hook to be executed
1450
before a chunk of data is being read into the cache's buffer
1451
The fuction instantianates and writes into the binlog
1452
replication events along LOAD DATA processing.
1454
@param file pointer to io-cache
1457
int log_loaded_block(IO_CACHE* file)
1459
LOAD_FILE_INFO *lf_info;
1461
/* buffer contains position where we started last read */
1462
unsigned char* buffer= (unsigned char*) my_b_get_buffer_start(file);
1463
uint32_t max_event_size= current_session->variables.max_allowed_packet;
1464
lf_info= (LOAD_FILE_INFO*) file->arg;
1465
if (lf_info->session->current_stmt_binlog_row_based)
1467
if (lf_info->last_pos_in_file != HA_POS_ERROR &&
1468
lf_info->last_pos_in_file >= my_b_get_pos_in_file(file))
1471
for (block_len= my_b_get_bytes_in_buffer(file); block_len > 0;
1472
buffer += cmin(block_len, max_event_size),
1473
block_len -= cmin(block_len, max_event_size))
1475
lf_info->last_pos_in_file= my_b_get_pos_in_file(file);
1476
if (lf_info->wrote_create_file)
1478
Append_block_log_event a(lf_info->session, lf_info->session->db, buffer,
1479
cmin(block_len, max_event_size),
1480
lf_info->log_delayed);
1481
mysql_bin_log.write(&a);
1485
Begin_load_query_log_event b(lf_info->session, lf_info->session->db,
1487
cmin(block_len, max_event_size),
1488
lf_info->log_delayed);
1489
mysql_bin_log.write(&b);
1490
lf_info->wrote_create_file= 1;
1497
Replication System Variables
1500
class sys_var_slave_skip_counter :public sys_var
1503
sys_var_slave_skip_counter(sys_var_chain *chain, const char *name_arg)
1505
{ chain_sys_var(chain); }
1506
bool check(Session *session, set_var *var);
1507
bool update(Session *session, set_var *var);
1508
bool check_type(enum_var_type type) { return type != OPT_GLOBAL; }
1510
We can't retrieve the value of this, so we don't have to define
1511
type() or value_ptr()
1515
class sys_var_sync_binlog_period :public sys_var_long_ptr
1518
sys_var_sync_binlog_period(sys_var_chain *chain, const char *name_arg,
1520
:sys_var_long_ptr(chain, name_arg,value_ptr) {}
1521
bool update(Session *session, set_var *var);
1524
static void fix_slave_net_timeout(Session *session,
1525
enum_var_type type __attribute__((unused)))
1527
pthread_mutex_lock(&LOCK_active_mi);
1528
if (active_mi && slave_net_timeout < active_mi->heartbeat_period)
1529
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1530
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE,
1531
"The currect value for master_heartbeat_period"
1532
" exceeds the new value of `slave_net_timeout' sec."
1533
" A sensible value for the period should be"
1534
" less than the timeout.");
1535
pthread_mutex_unlock(&LOCK_active_mi);
1539
static sys_var_chain vars = { NULL, NULL };
1541
static sys_var_bool_ptr sys_relay_log_purge(&vars, "relay_log_purge",
1543
static sys_var_long_ptr sys_slave_net_timeout(&vars, "slave_net_timeout",
1545
fix_slave_net_timeout);
1546
static sys_var_long_ptr sys_slave_trans_retries(&vars, "slave_transaction_retries",
1547
&slave_trans_retries);
1548
static sys_var_sync_binlog_period sys_sync_binlog_period(&vars, "sync_binlog", &sync_binlog_period);
1549
static sys_var_slave_skip_counter sys_slave_skip_counter(&vars, "sql_slave_skip_counter");
1551
static int show_slave_skip_errors(Session *session, SHOW_VAR *var, char *buff);
1554
static int show_slave_skip_errors(Session *session __attribute__((unused)),
1555
SHOW_VAR *var, char *buff)
1557
var->type=SHOW_CHAR;
1559
if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask))
1561
var->value= const_cast<char *>("OFF");
1563
else if (bitmap_is_set_all(&slave_error_mask))
1565
var->value= const_cast<char *>("ALL");
1569
/* 10 is enough assuming errors are max 4 digits */
1573
i < MAX_SLAVE_ERROR &&
1574
(buff - var->value) < SHOW_VAR_FUNC_BUFF_SIZE;
1577
if (bitmap_is_set(&slave_error_mask, i))
1579
buff= int10_to_str(i, buff, 10);
1583
if (var->value != buff)
1584
buff--; // Remove last ','
1585
if (i < MAX_SLAVE_ERROR)
1586
buff= my_stpcpy(buff, "..."); // Couldn't show all errors
1592
static st_show_var_func_container
1593
show_slave_skip_errors_cont = { &show_slave_skip_errors };
1596
static SHOW_VAR fixed_vars[]= {
1597
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL},
1598
{"relay_log" , (char*) &opt_relay_logname, SHOW_CHAR_PTR},
1599
{"relay_log_index", (char*) &opt_relaylog_index_name, SHOW_CHAR_PTR},
1600
{"relay_log_info_file", (char*) &relay_log_info_file, SHOW_CHAR_PTR},
1601
{"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG},
1602
{"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR},
1603
{"slave_skip_errors", (char*) &show_slave_skip_errors_cont, SHOW_FUNC},
1606
bool sys_var_slave_skip_counter::check(Session *session __attribute__((unused)),
1610
pthread_mutex_lock(&LOCK_active_mi);
1611
pthread_mutex_lock(&active_mi->rli.run_lock);
1612
if (active_mi->rli.slave_running)
1614
my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
1617
pthread_mutex_unlock(&active_mi->rli.run_lock);
1618
pthread_mutex_unlock(&LOCK_active_mi);
1619
var->save_result.uint32_t_value= (ulong) var->value->val_int();
1624
bool sys_var_slave_skip_counter::update(Session *session __attribute__((unused)),
1627
pthread_mutex_lock(&LOCK_active_mi);
1628
pthread_mutex_lock(&active_mi->rli.run_lock);
1630
The following test should normally never be true as we test this
1631
in the check function; To be safe against multiple
1632
SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
1634
if (!active_mi->rli.slave_running)
1636
pthread_mutex_lock(&active_mi->rli.data_lock);
1637
active_mi->rli.slave_skip_counter= var->save_result.uint32_t_value;
1638
pthread_mutex_unlock(&active_mi->rli.data_lock);
1640
pthread_mutex_unlock(&active_mi->rli.run_lock);
1641
pthread_mutex_unlock(&LOCK_active_mi);
1646
bool sys_var_sync_binlog_period::update(Session *session __attribute__((unused)),
1649
sync_binlog_period= (uint32_t) var->save_result.uint64_t_value;
1653
int init_replication_sys_vars()
1655
mysql_append_static_vars(fixed_vars, sizeof(fixed_vars) / sizeof(SHOW_VAR));
1657
if (mysql_add_sys_var_chain(vars.first, my_long_options))
1659
/* should not happen */
1660
fprintf(stderr, "failed to initialize replication system variables");