|
|
@ -102,35 +102,37 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
|
|
|
|
|
|
|
|
|
|
|
|
int tables_ok(THD* thd, TABLE_LIST* tables)
|
|
|
|
int tables_ok(THD* thd, TABLE_LIST* tables)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for(; tables; tables = tables->next)
|
|
|
|
for (; tables; tables = tables->next)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!tables->updating)
|
|
|
|
if (!tables->updating)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
char hash_key[2*NAME_LEN+2];
|
|
|
|
char hash_key[2*NAME_LEN+2];
|
|
|
|
char* p;
|
|
|
|
char* p;
|
|
|
|
p = strmov(hash_key, tables->db ? tables->db : thd->db);
|
|
|
|
p = strmov(hash_key, tables->db ? tables->db : thd->db);
|
|
|
|
*p++ = '.';
|
|
|
|
*p++ = '.';
|
|
|
|
uint len = strmov(p, tables->real_name) - hash_key ;
|
|
|
|
uint len = strmov(p, tables->real_name) - hash_key ;
|
|
|
|
if(do_table_inited) // if there are any do's
|
|
|
|
if (do_table_inited) // if there are any do's
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(hash_search(&replicate_do_table, (byte*) hash_key, len))
|
|
|
|
if (hash_search(&replicate_do_table, (byte*) hash_key, len))
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ignore_table_inited) // if there are any do's
|
|
|
|
if (ignore_table_inited) // if there are any do's
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(hash_search(&replicate_ignore_table, (byte*) hash_key, len))
|
|
|
|
if (hash_search(&replicate_ignore_table, (byte*) hash_key, len))
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(wild_do_table_inited && find_wild(&replicate_wild_do_table,
|
|
|
|
if (wild_do_table_inited && find_wild(&replicate_wild_do_table,
|
|
|
|
hash_key, len)) return 1;
|
|
|
|
hash_key, len))
|
|
|
|
if(wild_ignore_table_inited && find_wild(&replicate_wild_ignore_table,
|
|
|
|
return 1;
|
|
|
|
hash_key, len)) return 0;
|
|
|
|
if (wild_ignore_table_inited && find_wild(&replicate_wild_ignore_table,
|
|
|
|
|
|
|
|
hash_key, len))
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return !do_table_inited && !wild_do_table_inited;
|
|
|
|
|
|
|
|
// if no explicit rule found
|
|
|
|
// if no explicit rule found
|
|
|
|
// and there was a do list, do not replicate. If there was
|
|
|
|
// and there was a do list, do not replicate. If there was
|
|
|
|
// no do list, go ahead
|
|
|
|
// no do list, go ahead
|
|
|
|
|
|
|
|
return !do_table_inited && !wild_do_table_inited;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -138,8 +140,8 @@ int add_table_rule(HASH* h, const char* table_spec)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const char* dot = strchr(table_spec, '.');
|
|
|
|
const char* dot = strchr(table_spec, '.');
|
|
|
|
if(!dot) return 1;
|
|
|
|
if(!dot) return 1;
|
|
|
|
|
|
|
|
// len is always > 0 because we know the there exists a '.'
|
|
|
|
uint len = (uint)strlen(table_spec);
|
|
|
|
uint len = (uint)strlen(table_spec);
|
|
|
|
if(!len) return 1;
|
|
|
|
|
|
|
|
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
|
|
|
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
|
|
|
+ len, MYF(MY_WME));
|
|
|
|
+ len, MYF(MY_WME));
|
|
|
|
if(!e) return 1;
|
|
|
|
if(!e) return 1;
|
|
|
@ -156,7 +158,6 @@ int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
|
|
|
|
const char* dot = strchr(table_spec, '.');
|
|
|
|
const char* dot = strchr(table_spec, '.');
|
|
|
|
if(!dot) return 1;
|
|
|
|
if(!dot) return 1;
|
|
|
|
uint len = (uint)strlen(table_spec);
|
|
|
|
uint len = (uint)strlen(table_spec);
|
|
|
|
if(!len) return 1;
|
|
|
|
|
|
|
|
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
|
|
|
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
|
|
|
+ len, MYF(MY_WME));
|
|
|
|
+ len, MYF(MY_WME));
|
|
|
|
if(!e) return 1;
|
|
|
|
if(!e) return 1;
|
|
|
@ -174,7 +175,7 @@ static void free_string_array(DYNAMIC_ARRAY *a)
|
|
|
|
for(i = 0; i < a->elements; i++)
|
|
|
|
for(i = 0; i < a->elements; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char* p;
|
|
|
|
char* p;
|
|
|
|
get_dynamic(a, (gptr)&p, i);
|
|
|
|
get_dynamic(a, (gptr) &p, i);
|
|
|
|
my_free(p, MYF(MY_WME));
|
|
|
|
my_free(p, MYF(MY_WME));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete_dynamic(a);
|
|
|
|
delete_dynamic(a);
|
|
|
@ -227,9 +228,10 @@ int db_ok(const char* db, I_List<i_string> &do_list,
|
|
|
|
if(do_list.is_empty() && ignore_list.is_empty())
|
|
|
|
if(do_list.is_empty() && ignore_list.is_empty())
|
|
|
|
return 1; // ok to replicate if the user puts no constraints
|
|
|
|
return 1; // ok to replicate if the user puts no constraints
|
|
|
|
|
|
|
|
|
|
|
|
if(!db)
|
|
|
|
// if the user has specified restrictions on which databases to replicate
|
|
|
|
return 0; // if the user has specified restrictions on which databases to replicate
|
|
|
|
|
|
|
|
// and db was not selected, do not replicate
|
|
|
|
// and db was not selected, do not replicate
|
|
|
|
|
|
|
|
if(!db)
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(!do_list.is_empty()) // if the do's are not empty
|
|
|
|
if(!do_list.is_empty()) // if the do's are not empty
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -255,40 +257,40 @@ int db_ok(const char* db, I_List<i_string> &do_list,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f,
|
|
|
|
static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f,
|
|
|
|
char* default_val)
|
|
|
|
char* default_val)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
uint length;
|
|
|
|
if(my_b_gets(f,var, max_size))
|
|
|
|
if ((length=my_b_gets(f,var, max_size)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char* last_p = strend(var) - 1;
|
|
|
|
char* last_p = var + length -1;
|
|
|
|
int c;
|
|
|
|
if (*last_p == '\n')
|
|
|
|
if(*last_p == '\n') *last_p = 0; // if we stopped on newline, kill it
|
|
|
|
*last_p = 0; // if we stopped on newline, kill it
|
|
|
|
else
|
|
|
|
else
|
|
|
|
while( ((c=my_b_get(f)) != '\n' && c != my_b_EOF));
|
|
|
|
{
|
|
|
|
// if we truncated a line or stopped on last char, remove all chars
|
|
|
|
// if we truncated a line or stopped on last char, remove all chars
|
|
|
|
// up to and including newline
|
|
|
|
// up to and including newline
|
|
|
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
while( ((c=my_b_get(f)) != '\n' && c != my_b_EOF));
|
|
|
|
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(default_val)
|
|
|
|
else if (default_val)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
strmake(var, default_val, max_size);
|
|
|
|
strmake(var, default_val, max_size);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int init_intvar_from_file(int* var, IO_CACHE* f,
|
|
|
|
static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
|
|
|
|
int default_val)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char buf[32];
|
|
|
|
char buf[32];
|
|
|
|
|
|
|
|
|
|
|
|
if(my_b_gets(f, buf, sizeof(buf)))
|
|
|
|
if (my_b_gets(f, buf, sizeof(buf)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
*var = atoi(buf);
|
|
|
|
*var = atoi(buf);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -334,9 +336,9 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
|
|
|
|
thd->query_error = 0;
|
|
|
|
thd->query_error = 0;
|
|
|
|
thd->net.no_send_ok = 1;
|
|
|
|
thd->net.no_send_ok = 1;
|
|
|
|
thd->proc_info = "Creating table from master dump";
|
|
|
|
thd->proc_info = "Creating table from master dump";
|
|
|
|
|
|
|
|
// save old db in case we are creating in a different database
|
|
|
|
char* save_db = thd->db;
|
|
|
|
char* save_db = thd->db;
|
|
|
|
thd->db = thd->last_nx_db; // in case we are creating in a different
|
|
|
|
thd->db = thd->last_nx_db;
|
|
|
|
// database
|
|
|
|
|
|
|
|
mysql_parse(thd, thd->query, packet_len); // run create table
|
|
|
|
mysql_parse(thd, thd->query, packet_len); // run create table
|
|
|
|
thd->db = save_db; // leave things the way the were before
|
|
|
|
thd->db = save_db; // leave things the way the were before
|
|
|
|
|
|
|
|
|
|
|
@ -351,7 +353,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
|
|
|
|
tables.name = tables.real_name = (char*)table_name;
|
|
|
|
tables.name = tables.real_name = (char*)table_name;
|
|
|
|
tables.lock_type = TL_WRITE;
|
|
|
|
tables.lock_type = TL_WRITE;
|
|
|
|
thd->proc_info = "Opening master dump table";
|
|
|
|
thd->proc_info = "Opening master dump table";
|
|
|
|
if(!open_ltable(thd, &tables, TL_WRITE))
|
|
|
|
if (!open_ltable(thd, &tables, TL_WRITE))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// open tables will send the error
|
|
|
|
// open tables will send the error
|
|
|
|
sql_print_error("create_table_from_dump: could not open created table");
|
|
|
|
sql_print_error("create_table_from_dump: could not open created table");
|
|
|
@ -361,7 +363,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
|
|
|
|
|
|
|
|
|
|
|
|
handler *file = tables.table->file;
|
|
|
|
handler *file = tables.table->file;
|
|
|
|
thd->proc_info = "Reading master dump table data";
|
|
|
|
thd->proc_info = "Reading master dump table data";
|
|
|
|
if(file->net_read_dump(net))
|
|
|
|
if (file->net_read_dump(net))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
net_printf(&thd->net, ER_MASTER_NET_READ);
|
|
|
|
net_printf(&thd->net, ER_MASTER_NET_READ);
|
|
|
|
sql_print_error("create_table_from_dump::failed in\
|
|
|
|
sql_print_error("create_table_from_dump::failed in\
|
|
|
@ -376,10 +378,11 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
|
|
|
|
check_opt.quick = 1;
|
|
|
|
check_opt.quick = 1;
|
|
|
|
thd->proc_info = "rebuilding the index on master dump table";
|
|
|
|
thd->proc_info = "rebuilding the index on master dump table";
|
|
|
|
Vio* save_vio = thd->net.vio;
|
|
|
|
Vio* save_vio = thd->net.vio;
|
|
|
|
thd->net.vio = 0; // we do not want repair() to spam us with messages
|
|
|
|
// we do not want repair() to spam us with messages
|
|
|
|
// just send them to the error log, and report the failure in case of
|
|
|
|
// just send them to the error log, and report the failure in case of
|
|
|
|
// problems
|
|
|
|
// problems
|
|
|
|
if(file->repair(thd,&check_opt ))
|
|
|
|
thd->net.vio = 0;
|
|
|
|
|
|
|
|
if (file->repair(thd,&check_opt ))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
net_printf(&thd->net, ER_INDEX_REBUILD,tables.table->real_name );
|
|
|
|
net_printf(&thd->net, ER_INDEX_REBUILD,tables.table->real_name );
|
|
|
|
error = 1;
|
|
|
|
error = 1;
|
|
|
@ -423,15 +426,12 @@ int fetch_nx_table(THD* thd, MASTER_INFO* mi)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
error = 0;
|
|
|
|
err:
|
|
|
|
|
|
|
|
if(mysql)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
mc_mysql_close(mysql);
|
|
|
|
|
|
|
|
mysql = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(nx_errno && thd->net.vio)
|
|
|
|
|
|
|
|
send_error(&thd->net, nx_errno, "Error in fetch_nx_table");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
|
|
|
if (mysql)
|
|
|
|
|
|
|
|
mc_mysql_close(mysql);
|
|
|
|
|
|
|
|
if (nx_errno && thd->net.vio)
|
|
|
|
|
|
|
|
send_error(&thd->net, nx_errno, "Error in fetch_nx_table");
|
|
|
|
return error;
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -448,14 +448,14 @@ void end_master_info(MASTER_INFO* mi)
|
|
|
|
|
|
|
|
|
|
|
|
int init_master_info(MASTER_INFO* mi)
|
|
|
|
int init_master_info(MASTER_INFO* mi)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(mi->inited)
|
|
|
|
if (mi->inited)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
int fd;
|
|
|
|
int fd,length,error;
|
|
|
|
MY_STAT stat_area;
|
|
|
|
MY_STAT stat_area;
|
|
|
|
char fname[FN_REFLEN+128];
|
|
|
|
char fname[FN_REFLEN+128];
|
|
|
|
|
|
|
|
const char *msg;
|
|
|
|
fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
|
|
|
|
fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// we need a mutex while we are changing master info parameters to
|
|
|
|
// we need a mutex while we are changing master info parameters to
|
|
|
|
// keep other threads from reading bogus info
|
|
|
|
// keep other threads from reading bogus info
|
|
|
|
|
|
|
|
|
|
|
@ -463,13 +463,14 @@ int init_master_info(MASTER_INFO* mi)
|
|
|
|
mi->pending = 0;
|
|
|
|
mi->pending = 0;
|
|
|
|
fd = mi->fd;
|
|
|
|
fd = mi->fd;
|
|
|
|
|
|
|
|
|
|
|
|
if(!my_stat(fname, &stat_area, MYF(0))) // we do not want any messages
|
|
|
|
// we do not want any messages if the file does not exist
|
|
|
|
// if the file does not exist
|
|
|
|
if (!my_stat(fname, &stat_area, MYF(0)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// if someone removed the file from underneath our feet, just close
|
|
|
|
// if someone removed the file from underneath our feet, just close
|
|
|
|
// the old descriptor and re-create the old file
|
|
|
|
// the old descriptor and re-create the old file
|
|
|
|
if(fd >= 0) my_close(fd, MYF(MY_WME));
|
|
|
|
if (fd >= 0)
|
|
|
|
if((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0
|
|
|
|
my_close(fd, MYF(MY_WME));
|
|
|
|
|
|
|
|
if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0
|
|
|
|
|| init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
|
|
|
|
|| init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
|
|
|
|
MYF(MY_WME)))
|
|
|
|
MYF(MY_WME)))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -482,15 +483,14 @@ int init_master_info(MASTER_INFO* mi)
|
|
|
|
mi->pos = 4; // skip magic number
|
|
|
|
mi->pos = 4; // skip magic number
|
|
|
|
mi->fd = fd;
|
|
|
|
mi->fd = fd;
|
|
|
|
|
|
|
|
|
|
|
|
if(master_host)
|
|
|
|
if (master_host)
|
|
|
|
strmake(mi->host, master_host, sizeof(mi->host) - 1);
|
|
|
|
strmake(mi->host, master_host, sizeof(mi->host) - 1);
|
|
|
|
if(master_user)
|
|
|
|
if (master_user)
|
|
|
|
strmake(mi->user, master_user, sizeof(mi->user) - 1);
|
|
|
|
strmake(mi->user, master_user, sizeof(mi->user) - 1);
|
|
|
|
if(master_password)
|
|
|
|
if (master_password)
|
|
|
|
strmake(mi->password, master_password, sizeof(mi->password) - 1);
|
|
|
|
strmake(mi->password, master_password, sizeof(mi->password) - 1);
|
|
|
|
mi->port = master_port;
|
|
|
|
mi->port = master_port;
|
|
|
|
mi->connect_retry = master_connect_retry;
|
|
|
|
mi->connect_retry = master_connect_retry;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // file exists
|
|
|
|
else // file exists
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -506,24 +506,19 @@ int init_master_info(MASTER_INFO* mi)
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(!my_b_gets(&mi->file, mi->log_file_name, sizeof(mi->log_file_name)))
|
|
|
|
if (!(length=my_b_gets(&mi->file, mi->log_file_name,
|
|
|
|
|
|
|
|
sizeof(mi->log_file_name))))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("Error reading log file name from master info file ");
|
|
|
|
msg="Error reading log file name from master info file ";
|
|
|
|
end_io_cache(&mi->file);
|
|
|
|
goto error;
|
|
|
|
my_close(fd, MYF(0));
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*(strend(mi->log_file_name) - 1) = 0; // kill \n
|
|
|
|
mi->log_file_name[length]= 0; // kill \n
|
|
|
|
char buf[FN_REFLEN];
|
|
|
|
char buf[FN_REFLEN];
|
|
|
|
if(!my_b_gets(&mi->file, buf, sizeof(buf)))
|
|
|
|
if(!my_b_gets(&mi->file, buf, sizeof(buf)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("Error reading log file position from master info file");
|
|
|
|
msg="Error reading log file position from master info file";
|
|
|
|
end_io_cache(&mi->file);
|
|
|
|
goto error;
|
|
|
|
my_close(fd, MYF(0));
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mi->pos = strtoull(buf,(char**) 0, 10);
|
|
|
|
mi->pos = strtoull(buf,(char**) 0, 10);
|
|
|
@ -538,11 +533,8 @@ int init_master_info(MASTER_INFO* mi)
|
|
|
|
init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
|
|
|
|
init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
|
|
|
|
master_connect_retry))
|
|
|
|
master_connect_retry))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("Error reading master configuration");
|
|
|
|
msg="Error reading master configuration";
|
|
|
|
end_io_cache(&mi->file);
|
|
|
|
goto error;
|
|
|
|
my_close(fd, MYF(0));
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -550,14 +542,16 @@ int init_master_info(MASTER_INFO* mi)
|
|
|
|
// now change the cache from READ to WRITE - must do this
|
|
|
|
// now change the cache from READ to WRITE - must do this
|
|
|
|
// before flush_master_info
|
|
|
|
// before flush_master_info
|
|
|
|
reinit_io_cache(&mi->file, WRITE_CACHE, 0L,0,1);
|
|
|
|
reinit_io_cache(&mi->file, WRITE_CACHE, 0L,0,1);
|
|
|
|
if(flush_master_info(mi))
|
|
|
|
error=test(flush_master_info(mi));
|
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
|
|
|
sql_print_error(msg);
|
|
|
|
|
|
|
|
end_io_cache(&mi->file);
|
|
|
|
|
|
|
|
my_close(fd, MYF(0));
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&mi->lock);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int show_master_info(THD* thd)
|
|
|
|
int show_master_info(THD* thd)
|
|
|
@ -588,7 +582,7 @@ int show_master_info(THD* thd)
|
|
|
|
net_store_data(packet, (uint32) glob_mi.port);
|
|
|
|
net_store_data(packet, (uint32) glob_mi.port);
|
|
|
|
net_store_data(packet, (uint32) glob_mi.connect_retry);
|
|
|
|
net_store_data(packet, (uint32) glob_mi.connect_retry);
|
|
|
|
net_store_data(packet, glob_mi.log_file_name);
|
|
|
|
net_store_data(packet, glob_mi.log_file_name);
|
|
|
|
net_store_data(packet, (longlong)glob_mi.pos);
|
|
|
|
net_store_data(packet, (longlong) glob_mi.pos);
|
|
|
|
pthread_mutex_unlock(&glob_mi.lock);
|
|
|
|
pthread_mutex_unlock(&glob_mi.lock);
|
|
|
|
pthread_mutex_lock(&LOCK_slave);
|
|
|
|
pthread_mutex_lock(&LOCK_slave);
|
|
|
|
net_store_data(packet, slave_running ? "Yes":"No");
|
|
|
|
net_store_data(packet, slave_running ? "Yes":"No");
|
|
|
@ -596,7 +590,7 @@ int show_master_info(THD* thd)
|
|
|
|
net_store_data(packet, &replicate_do_db);
|
|
|
|
net_store_data(packet, &replicate_do_db);
|
|
|
|
net_store_data(packet, &replicate_ignore_db);
|
|
|
|
net_store_data(packet, &replicate_ignore_db);
|
|
|
|
|
|
|
|
|
|
|
|
if(my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
|
|
|
|
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
|
|
|
|
DBUG_RETURN(-1);
|
|
|
|
DBUG_RETURN(-1);
|
|
|
|
|
|
|
|
|
|
|
|
send_eof(&thd->net);
|
|
|
|
send_eof(&thd->net);
|
|
|
@ -610,26 +604,28 @@ int flush_master_info(MASTER_INFO* mi)
|
|
|
|
|
|
|
|
|
|
|
|
my_b_seek(file, 0L);
|
|
|
|
my_b_seek(file, 0L);
|
|
|
|
my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
|
|
|
|
my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
|
|
|
|
mi->log_file_name, llstr(mi->pos, lbuf), mi->host, mi->user, mi->password,
|
|
|
|
mi->log_file_name, llstr(mi->pos, lbuf), mi->host, mi->user,
|
|
|
|
mi->port, mi->connect_retry);
|
|
|
|
mi->password, mi->port, mi->connect_retry);
|
|
|
|
flush_io_cache(file);
|
|
|
|
flush_io_cache(file);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int st_master_info::wait_for_pos(THD* thd, String* log_name, ulong log_pos)
|
|
|
|
int st_master_info::wait_for_pos(THD* thd, String* log_name, ulong log_pos)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!inited) return -1;
|
|
|
|
if (!inited) return -1;
|
|
|
|
bool pos_reached = 0;
|
|
|
|
bool pos_reached;
|
|
|
|
int event_count = 0;
|
|
|
|
int event_count = 0;
|
|
|
|
for(;!pos_reached && !thd->killed;)
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int cmp_result;
|
|
|
|
int cmp_result;
|
|
|
|
char* basename;
|
|
|
|
if (*log_file_name)
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
|
|
|
|
if(*log_file_name)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
basename = strrchr(log_file_name, FN_LIBCHAR);
|
|
|
|
/*
|
|
|
|
if(basename)
|
|
|
|
We should use dirname_length() here when we have a version of
|
|
|
|
|
|
|
|
this that doesn't modify the argument */
|
|
|
|
|
|
|
|
char *basename = strrchr(log_file_name, FN_LIBCHAR);
|
|
|
|
|
|
|
|
if (basename)
|
|
|
|
++basename;
|
|
|
|
++basename;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
basename = log_file_name;
|
|
|
|
basename = log_file_name;
|
|
|
@ -640,20 +636,19 @@ int st_master_info::wait_for_pos(THD* thd, String* log_name, ulong log_pos)
|
|
|
|
cmp_result = 0;
|
|
|
|
cmp_result = 0;
|
|
|
|
|
|
|
|
|
|
|
|
pos_reached = ((!cmp_result && pos >= log_pos) || cmp_result > 0);
|
|
|
|
pos_reached = ((!cmp_result && pos >= log_pos) || cmp_result > 0);
|
|
|
|
if(!pos_reached && !thd->killed)
|
|
|
|
if (pos_reached || thd->killed)
|
|
|
|
|
|
|
|
break;
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const char* msg = thd->enter_cond(&cond, &lock,
|
|
|
|
const char* msg = thd->enter_cond(&cond, &lock,
|
|
|
|
"Waiting for master update");
|
|
|
|
"Waiting for master update");
|
|
|
|
pthread_cond_wait(&cond, &lock);
|
|
|
|
pthread_cond_wait(&cond, &lock);
|
|
|
|
thd->exit_cond(msg);
|
|
|
|
thd->exit_cond(msg);
|
|
|
|
event_count++;
|
|
|
|
event_count++;
|
|
|
|
|
|
|
|
pos_reached = (pos >= log_pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (!pos_reached && !thd->killed);
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
if(thd->killed)
|
|
|
|
return thd->killed ? -1 : event_count;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return event_count;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -715,12 +710,17 @@ static int safe_sleep(THD* thd, int sec)
|
|
|
|
while (start_time < end_time)
|
|
|
|
while (start_time < end_time)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int nap_time = (int) (end_time - start_time);
|
|
|
|
int nap_time = (int) (end_time - start_time);
|
|
|
|
thr_alarm(&alarmed, 2 * nap_time,&alarm_buff); // the only reason we are asking for alarm is so that
|
|
|
|
/*
|
|
|
|
// we will be woken up in case of murder, so if we do not get killed, set the alarm
|
|
|
|
the only reason we are asking for alarm is so that
|
|
|
|
// so it goes off after we wake up naturally
|
|
|
|
we will be woken up in case of murder, so if we do not get killed,
|
|
|
|
|
|
|
|
set the alarm so it goes off after we wake up naturally
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
thr_alarm(&alarmed, 2 * nap_time,&alarm_buff);
|
|
|
|
sleep(nap_time);
|
|
|
|
sleep(nap_time);
|
|
|
|
if (thr_alarm_in_use(&alarmed)) // if we wake up before the alarm goes off, hit the button
|
|
|
|
// if we wake up before the alarm goes off, hit the button
|
|
|
|
thr_end_alarm(&alarmed); // so it will not wake up the wife and kids :-)
|
|
|
|
// so it will not wake up the wife and kids :-)
|
|
|
|
|
|
|
|
if (thr_alarm_in_use(&alarmed))
|
|
|
|
|
|
|
|
thr_end_alarm(&alarmed);
|
|
|
|
|
|
|
|
|
|
|
|
if (slave_killed(thd))
|
|
|
|
if (slave_killed(thd))
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
@ -741,11 +741,11 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
|
|
|
|
int4store(buf + 6, server_id);
|
|
|
|
int4store(buf + 6, server_id);
|
|
|
|
len = (uint) strlen(logname);
|
|
|
|
len = (uint) strlen(logname);
|
|
|
|
memcpy(buf + 10, logname,len);
|
|
|
|
memcpy(buf + 10, logname,len);
|
|
|
|
if(mc_simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1))
|
|
|
|
if (mc_simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1))
|
|
|
|
|
|
|
|
{
|
|
|
|
// something went wrong, so we will just reconnect and retry later
|
|
|
|
// something went wrong, so we will just reconnect and retry later
|
|
|
|
// in the future, we should do a better error analysis, but for
|
|
|
|
// in the future, we should do a better error analysis, but for
|
|
|
|
// now we just fill up the error log :-)
|
|
|
|
// now we just fill up the error log :-)
|
|
|
|
{
|
|
|
|
|
|
|
|
sql_print_error("Error on COM_BINLOG_DUMP: %s, will retry in %d secs",
|
|
|
|
sql_print_error("Error on COM_BINLOG_DUMP: %s, will retry in %d secs",
|
|
|
|
mc_mysql_error(mysql), master_connect_retry);
|
|
|
|
mc_mysql_error(mysql), master_connect_retry);
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
@ -772,7 +772,7 @@ static int request_table_dump(MYSQL* mysql, char* db, char* table)
|
|
|
|
*p++ = table_len;
|
|
|
|
*p++ = table_len;
|
|
|
|
memcpy(p, table, table_len);
|
|
|
|
memcpy(p, table, table_len);
|
|
|
|
|
|
|
|
|
|
|
|
if(mc_simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1))
|
|
|
|
if (mc_simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("request_table_dump: Error sending the table dump \
|
|
|
|
sql_print_error("request_table_dump: Error sending the table dump \
|
|
|
|
command");
|
|
|
|
command");
|
|
|
@ -786,21 +786,24 @@ command");
|
|
|
|
static uint read_event(MYSQL* mysql, MASTER_INFO *mi)
|
|
|
|
static uint read_event(MYSQL* mysql, MASTER_INFO *mi)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint len = packet_error;
|
|
|
|
uint len = packet_error;
|
|
|
|
int read_errno = EINTR; // for convinience lets think we start by
|
|
|
|
// for convinience lets think we start by
|
|
|
|
// being in the interrupted state :-)
|
|
|
|
// being in the interrupted state :-)
|
|
|
|
|
|
|
|
int read_errno = EINTR;
|
|
|
|
|
|
|
|
|
|
|
|
// my_real_read() will time us out
|
|
|
|
// my_real_read() will time us out
|
|
|
|
// we check if we were told to die, and if not, try reading again
|
|
|
|
// we check if we were told to die, and if not, try reading again
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
if(disconnect_slave_event_count && !(events_till_disconnect--))
|
|
|
|
if (disconnect_slave_event_count && !(events_till_disconnect--))
|
|
|
|
return packet_error;
|
|
|
|
return packet_error;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
while (!abort_loop && !abort_slave && len == packet_error && read_errno == EINTR )
|
|
|
|
while (!abort_loop && !abort_slave && len == packet_error &&
|
|
|
|
|
|
|
|
read_errno == EINTR )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
len = mc_net_safe_read(mysql);
|
|
|
|
len = mc_net_safe_read(mysql);
|
|
|
|
read_errno = errno;
|
|
|
|
read_errno = errno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(abort_loop || abort_slave)
|
|
|
|
if (abort_loop || abort_slave)
|
|
|
|
return packet_error;
|
|
|
|
return packet_error;
|
|
|
|
if (len == packet_error || (int) len < 1)
|
|
|
|
if (len == packet_error || (int) len < 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -810,7 +813,7 @@ server_errno=%d)",
|
|
|
|
return packet_error;
|
|
|
|
return packet_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(len == 1)
|
|
|
|
if (len == 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("Slave: received 0 length packet from server, apparent\
|
|
|
|
sql_print_error("Slave: received 0 length packet from server, apparent\
|
|
|
|
master shutdown: %s (%d)",
|
|
|
|
master shutdown: %s (%d)",
|
|
|
@ -820,7 +823,6 @@ server_errno=%d)",
|
|
|
|
|
|
|
|
|
|
|
|
DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n",
|
|
|
|
DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n",
|
|
|
|
len, mysql->net.read_pos[4]));
|
|
|
|
len, mysql->net.read_pos[4]));
|
|
|
|
|
|
|
|
|
|
|
|
return len - 1;
|
|
|
|
return len - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -833,7 +835,7 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|
|
|
if (ev)
|
|
|
|
if (ev)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int type_code = ev->get_type_code();
|
|
|
|
int type_code = ev->get_type_code();
|
|
|
|
if(ev->server_id == ::server_id)
|
|
|
|
if (ev->server_id == ::server_id)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(type_code == LOAD_EVENT)
|
|
|
|
if(type_code == LOAD_EVENT)
|
|
|
|
skip_load_data_infile(net);
|
|
|
|
skip_load_data_infile(net);
|
|
|
@ -848,15 +850,14 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|
|
|
thd->set_time(); // time the query
|
|
|
|
thd->set_time(); // time the query
|
|
|
|
ev->when = time(NULL);
|
|
|
|
ev->when = time(NULL);
|
|
|
|
|
|
|
|
|
|
|
|
switch(type_code)
|
|
|
|
switch(type_code) {
|
|
|
|
{
|
|
|
|
|
|
|
|
case QUERY_EVENT:
|
|
|
|
case QUERY_EVENT:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Query_log_event* qev = (Query_log_event*)ev;
|
|
|
|
Query_log_event* qev = (Query_log_event*)ev;
|
|
|
|
int q_len = qev->q_len;
|
|
|
|
int q_len = qev->q_len;
|
|
|
|
init_sql_alloc(&thd->mem_root, 8192,0);
|
|
|
|
init_sql_alloc(&thd->mem_root, 8192,0);
|
|
|
|
thd->db = rewrite_db((char*)qev->db);
|
|
|
|
thd->db = rewrite_db((char*)qev->db);
|
|
|
|
if(db_ok(thd->db, replicate_do_db, replicate_ignore_db))
|
|
|
|
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
thd->query = (char*)qev->query;
|
|
|
|
thd->query = (char*)qev->query;
|
|
|
|
thd->set_time((time_t)qev->when);
|
|
|
|
thd->set_time((time_t)qev->when);
|
|
|
@ -871,7 +872,7 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|
|
|
thd->slave_proxy_id = qev->thread_id; // for temp tables
|
|
|
|
thd->slave_proxy_id = qev->thread_id; // for temp tables
|
|
|
|
mysql_parse(thd, thd->query, q_len);
|
|
|
|
mysql_parse(thd, thd->query, q_len);
|
|
|
|
int expected_error,actual_error;
|
|
|
|
int expected_error,actual_error;
|
|
|
|
if((expected_error = qev->error_code) !=
|
|
|
|
if ((expected_error = qev->error_code) !=
|
|
|
|
(actual_error = thd->net.last_errno) && expected_error)
|
|
|
|
(actual_error = thd->net.last_errno) && expected_error)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("Slave: did not get the expected error\
|
|
|
|
sql_print_error("Slave: did not get the expected error\
|
|
|
@ -881,13 +882,13 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
thd->query_error = 1;
|
|
|
|
thd->query_error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(expected_error == actual_error)
|
|
|
|
else if (expected_error == actual_error)
|
|
|
|
thd->query_error = 0;
|
|
|
|
thd->query_error = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
thd->db = 0;// prevent db from being freed
|
|
|
|
thd->db = 0; // prevent db from being freed
|
|
|
|
thd->query = 0; // just to be sure
|
|
|
|
thd->query = 0; // just to be sure
|
|
|
|
thd->convert_set = 0; // assume no convert for next query
|
|
|
|
// assume no convert for next query unless set explictly
|
|
|
|
// unless set explictly
|
|
|
|
thd->convert_set = 0;
|
|
|
|
close_thread_tables(thd);
|
|
|
|
close_thread_tables(thd);
|
|
|
|
|
|
|
|
|
|
|
|
if (thd->query_error || thd->fatal_error)
|
|
|
|
if (thd->query_error || thd->fatal_error)
|
|
|
@ -989,9 +990,10 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|
|
|
net->pkt_nr = thd->net.pkt_nr;
|
|
|
|
net->pkt_nr = thd->net.pkt_nr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // we will just ask the master to send us /dev/null if we do not want to
|
|
|
|
else
|
|
|
|
// load the data :-)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// we will just ask the master to send us /dev/null if we do not
|
|
|
|
|
|
|
|
// want to load the data :-)
|
|
|
|
skip_load_data_infile(net);
|
|
|
|
skip_load_data_infile(net);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1077,7 +1079,6 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1099,7 +1100,7 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
|
|
|
MYSQL *mysql = NULL ;
|
|
|
|
MYSQL *mysql = NULL ;
|
|
|
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&LOCK_slave);
|
|
|
|
pthread_mutex_lock(&LOCK_slave);
|
|
|
|
if(!server_id)
|
|
|
|
if (!server_id)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pthread_cond_broadcast(&COND_slave_start);
|
|
|
|
pthread_cond_broadcast(&COND_slave_start);
|
|
|
|
pthread_mutex_unlock(&LOCK_slave);
|
|
|
|
pthread_mutex_unlock(&LOCK_slave);
|
|
|
@ -1125,14 +1126,14 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
|
|
|
bool retried_once = 0;
|
|
|
|
bool retried_once = 0;
|
|
|
|
ulonglong last_failed_pos = 0;
|
|
|
|
ulonglong last_failed_pos = 0;
|
|
|
|
|
|
|
|
|
|
|
|
my_thread_init(); // needs to be up here, otherwise we get a coredump
|
|
|
|
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
|
|
|
|
// trying to use DBUG_ stuff
|
|
|
|
my_thread_init();
|
|
|
|
thd = new THD; // note that contructor of THD uses DBUG_ !
|
|
|
|
thd = new THD; // note that contructor of THD uses DBUG_ !
|
|
|
|
thd->set_time();
|
|
|
|
thd->set_time();
|
|
|
|
DBUG_ENTER("handle_slave");
|
|
|
|
DBUG_ENTER("handle_slave");
|
|
|
|
|
|
|
|
|
|
|
|
pthread_detach_this_thread();
|
|
|
|
pthread_detach_this_thread();
|
|
|
|
if(init_slave_thread(thd) || init_master_info(&glob_mi))
|
|
|
|
if (init_slave_thread(thd) || init_master_info(&glob_mi))
|
|
|
|
goto err;
|
|
|
|
goto err;
|
|
|
|
thd->thread_stack = (char*)&thd; // remember where our stack is
|
|
|
|
thd->thread_stack = (char*)&thd; // remember where our stack is
|
|
|
|
thd->temporary_tables = save_temporary_tables; // restore temp tables
|
|
|
|
thd->temporary_tables = save_temporary_tables; // restore temp tables
|
|
|
@ -1141,8 +1142,8 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
|
|
|
DBUG_PRINT("info",("master info: log_file_name=%s, position=%d",
|
|
|
|
DBUG_PRINT("info",("master info: log_file_name=%s, position=%d",
|
|
|
|
glob_mi.log_file_name, glob_mi.pos));
|
|
|
|
glob_mi.log_file_name, glob_mi.pos));
|
|
|
|
|
|
|
|
|
|
|
|
mysql = mc_mysql_init(NULL);
|
|
|
|
|
|
|
|
if(!mysql)
|
|
|
|
if (!(mysql = mc_mysql_init(NULL)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sql_print_error("Slave thread: error in mc_mysql_init()");
|
|
|
|
sql_print_error("Slave thread: error in mc_mysql_init()");
|
|
|
|
goto err;
|
|
|
|
goto err;
|
|
|
@ -1162,7 +1163,7 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
|
|
|
else
|
|
|
|
else
|
|
|
|
goto err;
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
|
|
while(!slave_killed(thd))
|
|
|
|
while (!slave_killed(thd))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
thd->proc_info = "requesting binlog dump";
|
|
|
|
thd->proc_info = "requesting binlog dump";
|
|
|
|
if(request_dump(mysql, &glob_mi))
|
|
|
|
if(request_dump(mysql, &glob_mi))
|
|
|
@ -1255,12 +1256,11 @@ reconnecting to retry, log '%s' position %ld", RPL_LOG_NAME,
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
stuck_count++;
|
|
|
|
|
|
|
|
// show a little mercy, allow slave to read one more event
|
|
|
|
// show a little mercy, allow slave to read one more event
|
|
|
|
// before cutting him off - otherwise he gets stuck
|
|
|
|
// before cutting him off - otherwise he gets stuck
|
|
|
|
// on Invar events, since they do not advance the offset
|
|
|
|
// on Invar events, since they do not advance the offset
|
|
|
|
// immediately
|
|
|
|
// immediately
|
|
|
|
if(stuck_count > 2)
|
|
|
|
if (++stuck_count > 2)
|
|
|
|
events_till_disconnect++;
|
|
|
|
events_till_disconnect++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -1276,10 +1276,7 @@ position %ld",
|
|
|
|
RPL_LOG_NAME, glob_mi.pos);
|
|
|
|
RPL_LOG_NAME, glob_mi.pos);
|
|
|
|
thd->query = thd->db = 0; // extra safety
|
|
|
|
thd->query = thd->db = 0; // extra safety
|
|
|
|
if(mysql)
|
|
|
|
if(mysql)
|
|
|
|
{
|
|
|
|
|
|
|
|
mc_mysql_close(mysql);
|
|
|
|
mc_mysql_close(mysql);
|
|
|
|
mysql = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
thd->proc_info = "waiting for slave mutex on exit";
|
|
|
|
thd->proc_info = "waiting for slave mutex on exit";
|
|
|
|
pthread_mutex_lock(&LOCK_slave);
|
|
|
|
pthread_mutex_lock(&LOCK_slave);
|
|
|
|
slave_running = 0;
|
|
|
|
slave_running = 0;
|
|
|
@ -1299,8 +1296,10 @@ position %ld",
|
|
|
|
DBUG_RETURN(0); // Can't return anything here
|
|
|
|
DBUG_RETURN(0); // Can't return anything here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* try to connect until successful or slave killed */
|
|
|
|
|
|
|
|
|
|
|
|
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
|
|
|
|
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
|
|
|
|
// will try to connect until successful or slave killed
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int slave_was_killed;
|
|
|
|
int slave_was_killed;
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
#ifndef DBUG_OFF
|
|
|
@ -1322,13 +1321,14 @@ static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
|
|
|
|
return slave_was_killed;
|
|
|
|
return slave_was_killed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// will try to connect until successful or slave killed
|
|
|
|
/* try to connect until successful or slave killed */
|
|
|
|
|
|
|
|
|
|
|
|
static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
|
|
|
|
static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int slave_was_killed;
|
|
|
|
int slave_was_killed;
|
|
|
|
mi->pending = 0; // if we lost connection after reading a state set event
|
|
|
|
// if we lost connection after reading a state set event
|
|
|
|
// we will be re-reading it, so pending needs to be cleared
|
|
|
|
// we will be re-reading it, so pending needs to be cleared
|
|
|
|
|
|
|
|
mi->pending = 0;
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
events_till_disconnect = disconnect_slave_event_count;
|
|
|
|
events_till_disconnect = disconnect_slave_event_count;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -1354,4 +1354,3 @@ replication resumed in log '%s' at position %ld", glob_mi.user,
|
|
|
|
template class I_List_iterator<i_string>;
|
|
|
|
template class I_List_iterator<i_string>;
|
|
|
|
template class I_List_iterator<i_string_pair>;
|
|
|
|
template class I_List_iterator<i_string_pair>;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|