1
/* Copyright (C) 2000-2003 MySQL AB
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 <my_global.h> // For HAVE_REPLICATION
17
#include "mysql_priv.h"
20
#include <rpl_mi_file.h>
22
#ifdef HAVE_REPLICATION
24
// Defined in slave.cc
25
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
26
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
27
const char *default_val);
28
int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
29
int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f);
32
LINES_IN_MASTER_INFO_WITH_SSL= 14,
34
/* 5.1.16 added value of master_ssl_verify_server_cert */
35
LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT= 15,
37
/* 6.0 added value of master_heartbeat_period */
38
LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16,
40
/* 6.0 added value of master_ignore_server_id */
41
LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 17,
43
/* Number of lines currently used when saving master info file */
44
LINES_IN_MASTER_INFO= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS
47
Master_info_file::Master_info_file(const char* param_info_fname)
48
:info_fname(param_info_fname), info_fd(-1),
51
DBUG_ENTER("Master_info_file::Master_info_file");
53
bzero((char*) &info_file, sizeof(info_file));
58
int Master_info_file::do_check()
60
char fname[FN_REFLEN+128];
61
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
63
return (access(fname,F_OK));
66
int Master_info_file::do_init_info()
69
char fname[FN_REFLEN+128];
70
DBUG_ENTER("Master_info_file::do_init_info");
74
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
76
/* does master.info exist ? */
77
if (access(fname,F_OK))
80
if someone removed the file from underneath our feet, just close
81
the old descriptor and re-create the old file
84
my_close(info_fd, MYF(MY_WME));
85
if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
87
sql_print_error("Failed to create a new master info file (\
88
file '%s', errno %d)", fname, my_errno);
91
if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
94
sql_print_error("Failed to create a cache on master info file (\
99
init_master_log_pos(this);
104
reinit_io_cache(&info_file, READ_CACHE, 0L,0,0);
107
if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
109
sql_print_error("Failed to open the existing master info file (\
110
file '%s', errno %d)", fname, my_errno);
113
if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,
116
sql_print_error("Failed to create a cache on master info file (\
122
int var_port, var_connect_retry, var_master_log_pos, lines;
123
int var_ssl= 0, var_ssl_verify_server_cert= 0;
124
float var_master_heartbeat_period= 0.0;
125
char *first_non_digit;
128
Starting from 4.1.x master.info has new format. Now its
129
first line contains number of lines in file. By reading this
130
number we will be always distinguish to which version our
131
master.info corresponds to. We can't simply count lines in
132
file since versions before 4.1.x could generate files with more
134
If first line doesn't contain a number or contain number less than
135
LINES_IN_MASTER_INFO_WITH_SSL then such file is treated like file
136
from pre 4.1.1 version.
137
There is no ambiguity when reading an old master.info, as before
138
4.1.1, the first line contained the binlog's name, which is either
139
empty or has an extension (contains a '.'), so can't be confused
142
So we're just reading first line and trying to figure which version
147
The first row is temporarily stored in master_log_name,
148
if it is line count and not binlog name (new format) it will be
149
overwritten by the second row later.
151
if (init_strvar_from_file(master_log_name,
152
sizeof(master_log_name), &info_file,
156
lines= strtoul(master_log_name, &first_non_digit, 10);
158
if (master_log_name[0]!='\0' &&
159
*first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
161
/* Seems to be new format => read master log name from next line */
162
if (init_strvar_from_file(master_log_name,
163
sizeof(master_log_name), &info_file, ""))
169
if (init_intvar_from_file(&var_master_log_pos, &info_file, 4) ||
170
init_strvar_from_file(host, sizeof(host), &info_file, 0) ||
171
init_strvar_from_file(user, sizeof(user), &info_file, "test") ||
172
init_strvar_from_file(password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
174
init_intvar_from_file(&var_port, &info_file, MYSQL_PORT) ||
175
init_intvar_from_file(&var_connect_retry, &info_file, DEFAULT_CONNECT_RETRY))
179
If file has ssl part use it even if we have server without
180
SSL support. But these option will be ignored later when
181
slave will try connect to master, so in this case warning
184
if (lines >= LINES_IN_MASTER_INFO_WITH_SSL)
186
if (init_intvar_from_file(&var_ssl, &info_file, 0) ||
187
init_strvar_from_file(ssl_ca, sizeof(ssl_ca),
189
init_strvar_from_file(ssl_capath, sizeof(ssl_capath),
191
init_strvar_from_file(ssl_cert, sizeof(ssl_cert),
193
init_strvar_from_file(ssl_cipher, sizeof(ssl_cipher),
195
init_strvar_from_file(ssl_key, sizeof(ssl_key),
200
Starting from 5.1.16 ssl_verify_server_cert might be
203
if (lines >= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT &&
204
init_intvar_from_file(&var_ssl_verify_server_cert, &info_file, 0))
207
Starting from 6.0 master_heartbeat_period might be
210
if (lines >= LINE_FOR_MASTER_HEARTBEAT_PERIOD &&
211
init_floatvar_from_file(&var_master_heartbeat_period, &info_file, 0.0))
214
Starting from 6.0 list of server_id of ignorable servers might be
217
if (lines >= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS &&
218
init_dynarray_intvar_from_file(&ignore_server_ids, &info_file))
220
sql_print_error("Failed to initialize master info ignore_server_ids");
227
sql_print_warning("SSL information in the master info file "
228
"('%s') are ignored because this MySQL slave was "
229
"compiled without SSL support.", fname);
230
#endif /* HAVE_OPENSSL */
233
This has to be handled here as init_intvar_from_file can't handle
236
master_log_pos= (my_off_t) var_master_log_pos;
237
port= (uint) var_port;
238
connect_retry= (uint) var_connect_retry;
239
ssl= (my_bool) var_ssl;
240
ssl_verify_server_cert= var_ssl_verify_server_cert;
241
heartbeat_period= var_master_heartbeat_period;
243
DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
245
(ulong) master_log_pos));
247
// now change cache READ -> WRITE - must do this before flush_info
248
reinit_io_cache(&info_file, WRITE_CACHE, 0L, 0, 1);
249
if ((error=test(do_flush_info())))
250
sql_print_error("Failed to flush master info file");
254
sql_print_error("Error reading master configuration");
259
my_close(info_fd, MYF(0));
260
end_io_cache(&info_file);
267
Flushes the master info to a file.
269
@retval 1 if it failed,
272
int Master_info_file::do_flush_info()
274
IO_CACHE* file = &info_file;
278
DBUG_ENTER("Master_info_file::do_flush_info");
279
DBUG_PRINT("enter",("master_pos: %ld", (long) master_log_pos));
282
In certain cases this code may create master.info files that seems
283
corrupted, because of extra lines filled with garbage in the end
284
file (this happens if new contents take less space than previous
285
contents of file). But because of number of lines in the first line
286
of file we don't care about this garbage.
288
char heartbeat_buf[sizeof(heartbeat_period) * 4]; // buffer to suffice always
289
my_sprintf(heartbeat_buf, (heartbeat_buf, "%.3f", heartbeat_period));
291
produce a line listing the total number and all the ignored server_id:s
293
char* ignore_server_ids_buf;
295
ignore_server_ids_buf=
296
(char *) my_malloc((sizeof(::server_id) * 3 + 1) *
297
(1 + ignore_server_ids.elements), MYF(MY_WME));
298
if (!ignore_server_ids_buf)
300
for (ulong i= 0, cur_len= my_sprintf(ignore_server_ids_buf,
301
(ignore_server_ids_buf, "%u",
302
ignore_server_ids.elements));
303
i < ignore_server_ids.elements; i++)
306
get_dynamic(&ignore_server_ids, (uchar*) &s_id, i);
307
cur_len +=my_sprintf(ignore_server_ids_buf + cur_len,
308
(ignore_server_ids_buf + cur_len,
314
"%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n",
315
LINES_IN_MASTER_INFO,
316
master_log_name, llstr(master_log_pos, lbuf),
318
password, port, connect_retry,
319
(int)(ssl), ssl_ca, ssl_capath, ssl_cert,
320
ssl_cipher, ssl_key, ssl_verify_server_cert,
322
ignore_server_ids_buf);
323
my_free(ignore_server_ids_buf, MYF(0));
324
err= flush_io_cache(file);
325
if (sync_masterinfo_period && !err &&
326
++(sync_counter) >= sync_masterinfo_period)
328
err= my_sync(info_fd, MYF(MY_WME));
334
void Master_info_file::do_end_info()
336
DBUG_ENTER("Master_info_file::do_end_info");
343
end_io_cache(&info_file);
344
(void)my_close(info_fd, MYF(MY_WME));
352
int Master_info_file::do_reset_info()
355
char fname[FN_REFLEN];
358
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
359
if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
364
#endif /* HAVE_REPLICATION */