mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / sql / repl_failsafe.cc
blob71bb2d9c9ac68492a176b45eeddf5d9b045a97c9
1 /*
2 Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 /**
19 @file
21 All of the functions defined in this file which are not used (the ones to
22 handle failsafe) are not used; their code has not been updated for more
23 than one year now so should be considered as BADLY BROKEN. Do not enable
24 it. The used functions (to handle LOAD DATA FROM MASTER, plus some small
25 functions like register_slave()) are working.
28 #include "mysql_priv.h"
29 #ifdef HAVE_REPLICATION
31 #include "repl_failsafe.h"
32 #include "sql_repl.h"
33 #include "slave.h"
34 #include "rpl_mi.h"
35 #include "rpl_filter.h"
36 #include "log_event.h"
37 #include <mysql.h>
39 #define SLAVE_LIST_CHUNK 128
40 #define SLAVE_ERRMSG_SIZE (FN_REFLEN+64)
43 RPL_STATUS rpl_status=RPL_NULL;
44 pthread_mutex_t LOCK_rpl_status;
45 pthread_cond_t COND_rpl_status;
46 HASH slave_list;
48 const char *rpl_role_type[] = {"MASTER","SLAVE",NullS};
49 TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"",
50 rpl_role_type, NULL};
52 const char* rpl_status_type[]=
54 "AUTH_MASTER","ACTIVE_SLAVE","IDLE_SLAVE", "LOST_SOLDIER","TROOP_SOLDIER",
55 "RECOVERY_CAPTAIN","NULL",NullS
57 TYPELIB rpl_status_typelib= {array_elements(rpl_status_type)-1,"",
58 rpl_status_type, NULL};
61 static Slave_log_event* find_slave_event(IO_CACHE* log,
62 const char* log_file_name,
63 char* errmsg);
66 All of the functions defined in this file which are not used (the ones to
67 handle failsafe) are not used; their code has not been updated for more than
68 one year now so should be considered as BADLY BROKEN. Do not enable it.
69 The used functions (to handle LOAD DATA FROM MASTER, plus some small
70 functions like register_slave()) are working.
73 #if NOT_USED
74 static int init_failsafe_rpl_thread(THD* thd)
76 DBUG_ENTER("init_failsafe_rpl_thread");
77 thd->system_thread = SYSTEM_THREAD_DELAYED_INSERT;
79 thd->bootstrap is to report errors barely to stderr; if this code is
80 enable again one day, one should check if bootstrap is still needed (maybe
81 this thread has no other error reporting method).
83 thd->bootstrap = 1;
84 thd->security_ctx->skip_grants();
85 my_net_init(&thd->net, 0);
86 thd->net.read_timeout = slave_net_timeout;
87 thd->max_client_packet_length=thd->net.max_packet;
88 pthread_mutex_lock(&LOCK_thread_count);
89 thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
90 pthread_mutex_unlock(&LOCK_thread_count);
92 if (init_thr_lock() || thd->store_globals())
94 /* purecov: begin inspected */
95 close_connection(thd, ER_OUT_OF_RESOURCES, 1); // is this needed?
96 statistic_increment(aborted_connects,&LOCK_status);
97 one_thread_per_connection_end(thd,0);
98 DBUG_RETURN(-1);
99 /* purecov: end */
102 thd->mem_root->free= thd->mem_root->used= 0;
103 if (thd->variables.max_join_size == HA_POS_ERROR)
104 thd->options|= OPTION_BIG_SELECTS;
106 thd_proc_info(thd, "Thread initialized");
107 thd->version=refresh_version;
108 thd->set_time();
109 DBUG_RETURN(0);
111 #endif
113 void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status)
115 pthread_mutex_lock(&LOCK_rpl_status);
116 if (rpl_status == from_status || rpl_status == RPL_ANY)
117 rpl_status = to_status;
118 pthread_cond_signal(&COND_rpl_status);
119 pthread_mutex_unlock(&LOCK_rpl_status);
123 #define get_object(p, obj, msg) \
125 uint len = (uint)*p++; \
126 if (p + len > p_end || len >= sizeof(obj)) \
128 errmsg= msg;\
129 goto err; \
131 strmake(obj,(char*) p,len); \
132 p+= len; \
136 static inline int cmp_master_pos(Slave_log_event* sev, LEX_MASTER_INFO* mi)
138 return cmp_master_pos(sev->master_log, sev->master_pos, mi->log_file_name,
139 mi->pos);
143 void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
145 if (thd->server_id)
147 if (need_mutex)
148 pthread_mutex_lock(&LOCK_slave_list);
150 SLAVE_INFO* old_si;
151 if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
152 (uchar*)&thd->server_id, 4)) &&
153 (!only_mine || old_si->thd == thd))
154 hash_delete(&slave_list, (uchar*)old_si);
156 if (need_mutex)
157 pthread_mutex_unlock(&LOCK_slave_list);
163 Register slave in 'slave_list' hash table.
165 @return
166 0 ok
167 @return
168 1 Error. Error message sent to client
171 int register_slave(THD* thd, uchar* packet, uint packet_length)
173 int res;
174 SLAVE_INFO *si;
175 uchar *p= packet, *p_end= packet + packet_length;
176 const char *errmsg= "Wrong parameters to function register_slave";
178 if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0,0))
179 return 1;
180 if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
181 goto err2;
183 thd->server_id= si->server_id= uint4korr(p);
184 p+= 4;
185 get_object(p,si->host, "Failed to register slave: too long 'report-host'");
186 get_object(p,si->user, "Failed to register slave: too long 'report-user'");
187 get_object(p,si->password, "Failed to register slave; too long 'report-password'");
188 if (p+10 > p_end)
189 goto err;
190 si->port= uint2korr(p);
191 p += 2;
192 si->rpl_recovery_rank= uint4korr(p);
193 p += 4;
194 if (!(si->master_id= uint4korr(p)))
195 si->master_id= server_id;
196 si->thd= thd;
198 pthread_mutex_lock(&LOCK_slave_list);
199 unregister_slave(thd,0,0);
200 res= my_hash_insert(&slave_list, (uchar*) si);
201 pthread_mutex_unlock(&LOCK_slave_list);
202 return res;
204 err:
205 my_free(si, MYF(MY_WME));
206 my_message(ER_UNKNOWN_ERROR, errmsg, MYF(0)); /* purecov: inspected */
207 err2:
208 return 1;
211 extern "C" uint32
212 *slave_list_key(SLAVE_INFO* si, size_t *len,
213 my_bool not_used __attribute__((unused)))
215 *len = 4;
216 return &si->server_id;
219 extern "C" void slave_info_free(void *s)
221 my_free(s, MYF(MY_WME));
224 void init_slave_list()
226 hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
227 (hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0);
228 pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
231 void end_slave_list()
233 /* No protection by a mutex needed as we are only called at shutdown */
234 if (hash_inited(&slave_list))
236 hash_free(&slave_list);
237 pthread_mutex_destroy(&LOCK_slave_list);
241 static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg)
243 my_off_t log_pos = (my_off_t) mi->pos;
244 uint32 target_server_id = mi->server_id;
246 for (;;)
248 Log_event* ev;
249 if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*) 0, 0)))
251 if (log->error > 0)
252 strmov(errmsg, "Binary log truncated in the middle of event");
253 else if (log->error < 0)
254 strmov(errmsg, "I/O error reading binary log");
255 else
256 strmov(errmsg, "Could not find target event in the binary log");
257 return 1;
260 if (ev->log_pos >= log_pos && ev->server_id == target_server_id)
262 delete ev;
263 mi->pos = my_b_tell(log);
264 return 0;
266 delete ev;
268 /* Impossible */
272 @details
273 Before 4.0.15 we had a member of THD called log_pos, it was meant for
274 failsafe replication code in repl_failsafe.cc which is disabled until
275 it is reworked. Event's log_pos used to be preserved through
276 log-slave-updates to make code in repl_failsafe.cc work (this
277 function, SHOW NEW MASTER); but on the other side it caused unexpected
278 values in Exec_Master_Log_Pos in A->B->C replication setup,
279 synchronization problems in master_pos_wait(), ... So we
280 (Dmitri & Guilhem) removed it.
282 So for now this function is broken.
285 int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
287 LOG_INFO linfo;
288 char last_log_name[FN_REFLEN];
289 IO_CACHE log;
290 File file = -1, last_file = -1;
291 pthread_mutex_t *log_lock;
292 const char* errmsg_p;
293 Slave_log_event* sev = 0;
294 my_off_t last_pos = 0;
295 int error = 1;
296 int cmp_res;
297 LINT_INIT(cmp_res);
298 DBUG_ENTER("translate_master");
300 if (!mysql_bin_log.is_open())
302 strmov(errmsg,"Binary log is not open");
303 DBUG_RETURN(1);
306 if (!server_id_supplied)
308 strmov(errmsg, "Misconfigured master - server id was not set");
309 DBUG_RETURN(1);
312 if (mysql_bin_log.find_log_pos(&linfo, NullS, 1))
314 strmov(errmsg,"Could not find first log");
315 DBUG_RETURN(1);
317 thd->current_linfo = &linfo;
319 bzero((char*) &log,sizeof(log));
320 log_lock = mysql_bin_log.get_log_lock();
321 pthread_mutex_lock(log_lock);
323 for (;;)
325 if ((file=open_binlog(&log, linfo.log_file_name, &errmsg_p)) < 0)
327 strmov(errmsg, errmsg_p);
328 goto err;
331 if (!(sev = find_slave_event(&log, linfo.log_file_name, errmsg)))
332 goto err;
334 cmp_res = cmp_master_pos(sev, mi);
335 delete sev;
337 if (!cmp_res)
339 /* Copy basename */
340 fn_format(mi->log_file_name, linfo.log_file_name, "","",1);
341 mi->pos = my_b_tell(&log);
342 goto mi_inited;
344 else if (cmp_res > 0)
346 if (!last_pos)
348 strmov(errmsg,
349 "Slave event in first log points past the target position");
350 goto err;
352 end_io_cache(&log);
353 (void) my_close(file, MYF(MY_WME));
354 if (init_io_cache(&log, (file = last_file), IO_SIZE, READ_CACHE, 0, 0,
355 MYF(MY_WME)))
357 errmsg[0] = 0;
358 goto err;
360 break;
363 strmov(last_log_name, linfo.log_file_name);
364 last_pos = my_b_tell(&log);
366 switch (mysql_bin_log.find_next_log(&linfo, 1)) {
367 case LOG_INFO_EOF:
368 if (last_file >= 0)
369 (void)my_close(last_file, MYF(MY_WME));
370 last_file = -1;
371 goto found_log;
372 case 0:
373 break;
374 default:
375 strmov(errmsg, "Error reading log index");
376 goto err;
379 end_io_cache(&log);
380 if (last_file >= 0)
381 (void) my_close(last_file, MYF(MY_WME));
382 last_file = file;
385 found_log:
386 my_b_seek(&log, last_pos);
387 if (find_target_pos(mi,&log,errmsg))
388 goto err;
389 fn_format(mi->log_file_name, last_log_name, "","",1); /* Copy basename */
391 mi_inited:
392 error = 0;
393 err:
394 pthread_mutex_unlock(log_lock);
395 end_io_cache(&log);
396 pthread_mutex_lock(&LOCK_thread_count);
397 thd->current_linfo = 0;
398 pthread_mutex_unlock(&LOCK_thread_count);
399 if (file >= 0)
400 (void) my_close(file, MYF(MY_WME));
401 if (last_file >= 0 && last_file != file)
402 (void) my_close(last_file, MYF(MY_WME));
404 DBUG_RETURN(error);
409 Caller must delete result when done.
412 static Slave_log_event* find_slave_event(IO_CACHE* log,
413 const char* log_file_name,
414 char* errmsg)
416 Log_event* ev;
417 int i;
418 bool slave_event_found = 0;
419 LINT_INIT(ev);
421 for (i = 0; i < 2; i++)
423 if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0, 0)))
425 my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
426 "Error reading event in log '%s'",
427 (char*)log_file_name);
428 return 0;
430 if (ev->get_type_code() == SLAVE_EVENT)
432 slave_event_found = 1;
433 break;
435 delete ev;
437 if (!slave_event_found)
439 my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
440 "Could not find slave event in log '%s'",
441 (char*)log_file_name);
442 return 0;
445 return (Slave_log_event*)ev;
449 This function is broken now.
451 @seealso translate_master()
454 bool show_new_master(THD* thd)
456 Protocol *protocol= thd->protocol;
457 DBUG_ENTER("show_new_master");
458 List<Item> field_list;
459 char errmsg[SLAVE_ERRMSG_SIZE];
460 LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
462 errmsg[0]=0; // Safety
463 if (translate_master(thd, lex_mi, errmsg))
465 if (errmsg[0])
466 my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
467 "SHOW NEW MASTER", errmsg);
468 DBUG_RETURN(TRUE);
470 else
472 field_list.push_back(new Item_empty_string("Log_name", 20));
473 field_list.push_back(new Item_return_int("Log_pos", 10,
474 MYSQL_TYPE_LONGLONG));
475 if (protocol->send_fields(&field_list,
476 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
477 DBUG_RETURN(TRUE);
478 protocol->prepare_for_resend();
479 protocol->store(lex_mi->log_file_name, &my_charset_bin);
480 protocol->store((ulonglong) lex_mi->pos);
481 if (protocol->write())
482 DBUG_RETURN(TRUE);
483 my_eof(thd);
484 DBUG_RETURN(FALSE);
489 Asks the master for the list of its other connected slaves.
491 This is for failsafe replication:
492 in order for failsafe replication to work, the servers involved in
493 replication must know of each other. We accomplish this by having each
494 slave report to the master how to reach it, and on connection, each
495 slave receives information about where the other slaves are.
497 @param mysql pre-existing connection to the master
498 @param mi master info
500 @note
501 mi is used only to give detailed error messages which include the
502 hostname/port of the master, the username used by the slave to connect to
503 the master.
504 If the user used by the slave to connect to the master does not have the
505 REPLICATION SLAVE privilege, it will pop in this function because
506 SHOW SLAVE HOSTS will fail on the master.
508 @retval
509 1 error
510 @retval
511 0 success
514 int update_slave_list(MYSQL* mysql, Master_info* mi)
516 MYSQL_RES* res=0;
517 MYSQL_ROW row;
518 const char* error=0;
519 bool have_auth_info;
520 int port_ind;
521 DBUG_ENTER("update_slave_list");
523 if (mysql_real_query(mysql, STRING_WITH_LEN("SHOW SLAVE HOSTS")) ||
524 !(res = mysql_store_result(mysql)))
526 error= mysql_error(mysql);
527 goto err;
530 switch (mysql_num_fields(res)) {
531 case 5:
532 have_auth_info = 0;
533 port_ind=2;
534 break;
535 case 7:
536 have_auth_info = 1;
537 port_ind=4;
538 break;
539 default:
540 error= "the master returned an invalid number of fields for SHOW SLAVE \
541 HOSTS";
542 goto err;
545 pthread_mutex_lock(&LOCK_slave_list);
547 while ((row= mysql_fetch_row(res)))
549 uint32 log_server_id;
550 SLAVE_INFO* si, *old_si;
551 log_server_id = atoi(row[0]);
552 if ((old_si= (SLAVE_INFO*)hash_search(&slave_list,
553 (uchar*)&log_server_id,4)))
554 si = old_si;
555 else
557 if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
559 error= "the slave is out of memory";
560 pthread_mutex_unlock(&LOCK_slave_list);
561 goto err;
563 si->server_id = log_server_id;
564 if (my_hash_insert(&slave_list, (uchar*)si))
566 error= "the slave is out of memory";
567 pthread_mutex_unlock(&LOCK_slave_list);
568 goto err;
571 strmake(si->host, row[1], sizeof(si->host)-1);
572 si->port = atoi(row[port_ind]);
573 si->rpl_recovery_rank = atoi(row[port_ind+1]);
574 si->master_id = atoi(row[port_ind+2]);
575 if (have_auth_info)
577 strmake(si->user, row[2], sizeof(si->user)-1);
578 strmake(si->password, row[3], sizeof(si->password)-1);
581 pthread_mutex_unlock(&LOCK_slave_list);
583 err:
584 if (res)
585 mysql_free_result(res);
586 if (error)
588 sql_print_error("While trying to obtain the list of slaves from the master "
589 "'%s:%d', user '%s' got the following error: '%s'",
590 mi->host, mi->port, mi->user, error);
591 DBUG_RETURN(1);
593 DBUG_RETURN(0);
597 #if NOT_USED
598 int find_recovery_captain(THD* thd, MYSQL* mysql)
600 return 0;
602 #endif
604 #if NOT_USED
605 pthread_handler_t handle_failsafe_rpl(void *arg)
607 DBUG_ENTER("handle_failsafe_rpl");
608 THD *thd = new THD;
609 thd->thread_stack = (char*)&thd;
610 MYSQL* recovery_captain = 0;
611 const char* msg;
613 pthread_detach_this_thread();
614 if (init_failsafe_rpl_thread(thd) || !(recovery_captain=mysql_init(0)))
616 sql_print_error("Could not initialize failsafe replication thread");
617 goto err;
619 pthread_mutex_lock(&LOCK_rpl_status);
620 msg= thd->enter_cond(&COND_rpl_status,
621 &LOCK_rpl_status, "Waiting for request");
622 while (!thd->killed && !abort_loop)
624 bool break_req_chain = 0;
625 pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status);
626 thd_proc_info(thd, "Processing request");
627 while (!break_req_chain)
629 switch (rpl_status) {
630 case RPL_LOST_SOLDIER:
631 if (find_recovery_captain(thd, recovery_captain))
632 rpl_status=RPL_TROOP_SOLDIER;
633 else
634 rpl_status=RPL_RECOVERY_CAPTAIN;
635 break_req_chain=1; /* for now until other states are implemented */
636 break;
637 default:
638 break_req_chain=1;
639 break;
643 thd->exit_cond(msg);
644 err:
645 if (recovery_captain)
646 mysql_close(recovery_captain);
647 delete thd;
649 DBUG_LEAVE; // Must match DBUG_ENTER()
650 my_thread_end();
651 pthread_exit(0);
652 return 0; // Avoid compiler warnings
654 #endif
658 Execute a SHOW SLAVE HOSTS statement.
660 @param thd Pointer to THD object for the client thread executing the
661 statement.
663 @retval FALSE success
664 @retval TRUE failure
666 bool show_slave_hosts(THD* thd)
668 List<Item> field_list;
669 Protocol *protocol= thd->protocol;
670 DBUG_ENTER("show_slave_hosts");
672 field_list.push_back(new Item_return_int("Server_id", 10,
673 MYSQL_TYPE_LONG));
674 field_list.push_back(new Item_empty_string("Host", 20));
675 if (opt_show_slave_auth_info)
677 field_list.push_back(new Item_empty_string("User",20));
678 field_list.push_back(new Item_empty_string("Password",20));
680 field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
681 field_list.push_back(new Item_return_int("Rpl_recovery_rank", 7,
682 MYSQL_TYPE_LONG));
683 field_list.push_back(new Item_return_int("Master_id", 10,
684 MYSQL_TYPE_LONG));
686 if (protocol->send_fields(&field_list,
687 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
688 DBUG_RETURN(TRUE);
690 pthread_mutex_lock(&LOCK_slave_list);
692 for (uint i = 0; i < slave_list.records; ++i)
694 SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
695 protocol->prepare_for_resend();
696 protocol->store((uint32) si->server_id);
697 protocol->store(si->host, &my_charset_bin);
698 if (opt_show_slave_auth_info)
700 protocol->store(si->user, &my_charset_bin);
701 protocol->store(si->password, &my_charset_bin);
703 protocol->store((uint32) si->port);
704 protocol->store((uint32) si->rpl_recovery_rank);
705 protocol->store((uint32) si->master_id);
706 if (protocol->write())
708 pthread_mutex_unlock(&LOCK_slave_list);
709 DBUG_RETURN(TRUE);
712 pthread_mutex_unlock(&LOCK_slave_list);
713 my_eof(thd);
714 DBUG_RETURN(FALSE);
718 int connect_to_master(THD *thd, MYSQL* mysql, Master_info* mi)
720 DBUG_ENTER("connect_to_master");
722 if (!mi->host || !*mi->host) /* empty host */
724 strmov(mysql->net.last_error, "Master is not configured");
725 DBUG_RETURN(1);
727 mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
728 mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
730 #ifdef HAVE_OPENSSL
731 if (mi->ssl)
733 mysql_ssl_set(mysql,
734 mi->ssl_key[0]?mi->ssl_key:0,
735 mi->ssl_cert[0]?mi->ssl_cert:0,
736 mi->ssl_ca[0]?mi->ssl_ca:0,
737 mi->ssl_capath[0]?mi->ssl_capath:0,
738 mi->ssl_cipher[0]?mi->ssl_cipher:0);
739 mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
740 &mi->ssl_verify_server_cert);
742 #endif
744 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname);
745 mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
746 if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
747 mi->port, 0, 0))
748 DBUG_RETURN(1);
749 mysql->reconnect= 1;
750 DBUG_RETURN(0);
754 static inline void cleanup_mysql_results(MYSQL_RES* db_res,
755 MYSQL_RES** cur, MYSQL_RES** start)
757 for (; cur >= start; --cur)
759 if (*cur)
760 mysql_free_result(*cur);
762 mysql_free_result(db_res);
766 static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
767 MYSQL_RES *table_res, Master_info *mi)
769 MYSQL_ROW row;
770 for (row = mysql_fetch_row(table_res); row;
771 row = mysql_fetch_row(table_res))
773 TABLE_LIST table;
774 const char* table_name= row[0];
775 int error;
776 if (rpl_filter->is_on())
778 bzero((char*) &table, sizeof(table)); //just for safe
779 table.db= (char*) db;
780 table.table_name= (char*) table_name;
781 table.updating= 1;
783 if (!rpl_filter->tables_ok(thd->db, &table))
784 continue;
786 /* download master's table and overwrite slave's table */
787 if ((error= fetch_master_table(thd, db, table_name, mi, mysql, 1)))
788 return error;
790 return 0;
794 Load all MyISAM tables from master to this slave.
796 REQUIREMENTS
797 - No active transaction (flush_relay_log_info would not work in this case).
799 @todo
800 - add special option, not enabled
801 by default, to allow inclusion of mysql database into load
802 data from master
805 bool load_master_data(THD* thd)
807 MYSQL mysql;
808 MYSQL_RES* master_status_res = 0;
809 int error = 0;
810 const char* errmsg=0;
811 int restart_thread_mask;
812 HA_CREATE_INFO create_info;
814 mysql_init(&mysql);
817 We do not want anyone messing with the slave at all for the entire
818 duration of the data load.
820 pthread_mutex_lock(&LOCK_active_mi);
821 lock_slave_threads(active_mi);
822 init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/);
823 if (restart_thread_mask &&
824 (error=terminate_slave_threads(active_mi,restart_thread_mask,
825 1 /*skip lock*/)))
827 my_message(error, ER(error), MYF(0));
828 unlock_slave_threads(active_mi);
829 pthread_mutex_unlock(&LOCK_active_mi);
830 return TRUE;
833 if (connect_to_master(thd, &mysql, active_mi))
835 my_error(error= ER_CONNECT_TO_MASTER, MYF(0), mysql_error(&mysql));
836 goto err;
839 // now that we are connected, get all database and tables in each
841 MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res;
842 uint num_dbs;
844 if (mysql_real_query(&mysql, STRING_WITH_LEN("SHOW DATABASES")) ||
845 !(db_res = mysql_store_result(&mysql)))
847 my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
848 goto err;
851 if (!(num_dbs = (uint) mysql_num_rows(db_res)))
852 goto err;
854 In theory, the master could have no databases at all
855 and run with skip-grant
858 if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
860 my_message(error = ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
861 goto err;
865 This is a temporary solution until we have online backup
866 capabilities - to be replaced once online backup is working
867 we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
868 can to minimize the lock time.
870 if (mysql_real_query(&mysql,
871 STRING_WITH_LEN("FLUSH TABLES WITH READ LOCK")) ||
872 mysql_real_query(&mysql, STRING_WITH_LEN("SHOW MASTER STATUS")) ||
873 !(master_status_res = mysql_store_result(&mysql)))
875 my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
876 goto err;
880 Go through every table in every database, and if the replication
881 rules allow replicating it, get it
884 table_res_end = table_res + num_dbs;
886 for (cur_table_res = table_res; cur_table_res < table_res_end;
887 cur_table_res++)
889 // since we know how many rows we have, this can never be NULL
890 MYSQL_ROW row = mysql_fetch_row(db_res);
891 char* db = row[0];
894 Do not replicate databases excluded by rules. We also test
895 replicate_wild_*_table rules (replicate_wild_ignore_table='db1.%' will
896 be considered as "ignore the 'db1' database as a whole, as it already
897 works for CREATE DATABASE and DROP DATABASE).
898 Also skip 'mysql' database - in most cases the user will
899 mess up and not exclude mysql database with the rules when
900 he actually means to - in this case, he is up for a surprise if
901 his priv tables get dropped and downloaded from master
902 TODO - add special option, not enabled
903 by default, to allow inclusion of mysql database into load
904 data from master
907 if (!rpl_filter->db_ok(db) ||
908 !rpl_filter->db_ok_with_wild_table(db) ||
909 !strcmp(db,"mysql") ||
910 is_schema_db(db))
912 *cur_table_res = 0;
913 continue;
916 bzero((char*) &create_info, sizeof(create_info));
917 create_info.options= HA_LEX_CREATE_IF_NOT_EXISTS;
919 if (mysql_create_db(thd, db, &create_info, 1))
921 cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
922 goto err;
924 /* Clear the result of mysql_create_db(). */
925 thd->main_da.reset_diagnostics_area();
927 if (mysql_select_db(&mysql, db) ||
928 mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) ||
929 !(*cur_table_res = mysql_store_result(&mysql)))
931 my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
932 cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
933 goto err;
936 if ((error = fetch_db_tables(thd,&mysql,db,*cur_table_res,active_mi)))
938 // we do not report the error - fetch_db_tables handles it
939 cleanup_mysql_results(db_res, cur_table_res, table_res);
940 goto err;
944 cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
946 // adjust replication coordinates from the master
947 if (master_status_res)
949 MYSQL_ROW row = mysql_fetch_row(master_status_res);
952 We need this check because the master may not be running with
953 log-bin, but it will still allow us to do all the steps
954 of LOAD DATA FROM MASTER - no reason to forbid it, really,
955 although it does not make much sense for the user to do it
957 if (row && row[0] && row[1])
960 If the slave's master info is not inited, we init it, then we write
961 the new coordinates to it. Must call init_master_info() *before*
962 setting active_mi, because init_master_info() sets active_mi with
963 defaults.
965 int error_2;
967 if (init_master_info(active_mi, master_info_file, relay_log_info_file,
968 0, (SLAVE_IO | SLAVE_SQL)))
969 my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
970 strmake(active_mi->master_log_name, row[0],
971 sizeof(active_mi->master_log_name) -1);
972 active_mi->master_log_pos= my_strtoll10(row[1], (char**) 0, &error_2);
973 /* at least in recent versions, the condition below should be false */
974 if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE)
975 active_mi->master_log_pos = BIN_LOG_HEADER_SIZE;
977 Relay log's IO_CACHE may not be inited (even if we are sure that some
978 host was specified; there could have been a problem when replication
979 started, which led to relay log's IO_CACHE to not be inited.
981 if (flush_master_info(active_mi, FALSE, FALSE))
982 sql_print_error("Failed to flush master info file");
984 mysql_free_result(master_status_res);
987 if (mysql_real_query(&mysql, STRING_WITH_LEN("UNLOCK TABLES")))
989 my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
990 goto err;
993 thd_proc_info(thd, "purging old relay logs");
994 if (purge_relay_logs(&active_mi->rli,thd,
995 0 /* not only reset, but also reinit */,
996 &errmsg))
998 my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
999 unlock_slave_threads(active_mi);
1000 pthread_mutex_unlock(&LOCK_active_mi);
1001 return TRUE;
1003 pthread_mutex_lock(&active_mi->rli.data_lock);
1004 active_mi->rli.group_master_log_pos = active_mi->master_log_pos;
1005 strmake(active_mi->rli.group_master_log_name,active_mi->master_log_name,
1006 sizeof(active_mi->rli.group_master_log_name)-1);
1008 Cancel the previous START SLAVE UNTIL, as the fact to download
1009 a new copy logically makes UNTIL irrelevant.
1011 active_mi->rli.clear_until_condition();
1014 No need to update rli.event* coordinates, they will be when the slave
1015 threads start ; only rli.group* coordinates are necessary here.
1017 flush_relay_log_info(&active_mi->rli);
1018 pthread_cond_broadcast(&active_mi->rli.data_cond);
1019 pthread_mutex_unlock(&active_mi->rli.data_lock);
1020 thd_proc_info(thd, "starting slave");
1021 if (restart_thread_mask)
1023 error=start_slave_threads(0 /* mutex not needed */,
1024 1 /* wait for start */,
1025 active_mi,master_info_file,relay_log_info_file,
1026 restart_thread_mask);
1029 err:
1030 unlock_slave_threads(active_mi);
1031 pthread_mutex_unlock(&LOCK_active_mi);
1032 thd_proc_info(thd, 0);
1034 mysql_close(&mysql); // safe to call since we always do mysql_init()
1035 if (!error)
1036 my_ok(thd);
1038 return error;
1041 #endif /* HAVE_REPLICATION */