Commit b36b2567 authored by guilhem@mysql.com's avatar guilhem@mysql.com

Merge gbichot@bk-internal.mysql.com:/home/bk/mysql-4.0

into mysql.com:/home/mysql_src/mysql-4.0
parents 4c89512f cf287341
...@@ -1543,13 +1543,11 @@ longlong Item_master_pos_wait::val_int() ...@@ -1543,13 +1543,11 @@ longlong Item_master_pos_wait::val_int()
} }
longlong pos = args[1]->val_int(); longlong pos = args[1]->val_int();
longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ; longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
LOCK_ACTIVE_MI;
if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2) if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
{ {
null_value = 1; null_value = 1;
event_count=0; event_count=0;
} }
UNLOCK_ACTIVE_MI;
return event_count; return event_count;
} }
......
...@@ -750,7 +750,7 @@ int load_master_data(THD* thd) ...@@ -750,7 +750,7 @@ int load_master_data(THD* thd)
We do not want anyone messing with the slave at all for the entire We do not want anyone messing with the slave at all for the entire
duration of the data load. duration of the data load.
*/ */
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
lock_slave_threads(active_mi); lock_slave_threads(active_mi);
init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/); init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/);
if (restart_thread_mask && if (restart_thread_mask &&
...@@ -759,7 +759,7 @@ int load_master_data(THD* thd) ...@@ -759,7 +759,7 @@ int load_master_data(THD* thd)
{ {
send_error(&thd->net,error); send_error(&thd->net,error);
unlock_slave_threads(active_mi); unlock_slave_threads(active_mi);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
return 1; return 1;
} }
...@@ -913,7 +913,7 @@ int load_master_data(THD* thd) ...@@ -913,7 +913,7 @@ int load_master_data(THD* thd)
{ {
send_error(&thd->net, 0, "Failed purging old relay logs"); send_error(&thd->net, 0, "Failed purging old relay logs");
unlock_slave_threads(active_mi); unlock_slave_threads(active_mi);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
return 1; return 1;
} }
pthread_mutex_lock(&active_mi->rli.data_lock); pthread_mutex_lock(&active_mi->rli.data_lock);
...@@ -934,7 +934,7 @@ int load_master_data(THD* thd) ...@@ -934,7 +934,7 @@ int load_master_data(THD* thd)
err: err:
unlock_slave_threads(active_mi); unlock_slave_threads(active_mi);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
thd->proc_info = 0; thd->proc_info = 0;
mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init() mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init()
......
...@@ -1273,7 +1273,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type) ...@@ -1273,7 +1273,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type)
bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
{ {
int result= 0; int result= 0;
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
pthread_mutex_lock(&active_mi->rli.run_lock); pthread_mutex_lock(&active_mi->rli.run_lock);
if (active_mi->rli.slave_running) if (active_mi->rli.slave_running)
{ {
...@@ -1281,14 +1281,14 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) ...@@ -1281,14 +1281,14 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
result=1; result=1;
} }
pthread_mutex_unlock(&active_mi->rli.run_lock); pthread_mutex_unlock(&active_mi->rli.run_lock);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
return result; return result;
} }
bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
{ {
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
pthread_mutex_lock(&active_mi->rli.run_lock); pthread_mutex_lock(&active_mi->rli.run_lock);
/* /*
The following test should normally never be true as we test this The following test should normally never be true as we test this
...@@ -1302,7 +1302,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) ...@@ -1302,7 +1302,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
pthread_mutex_unlock(&active_mi->rli.data_lock); pthread_mutex_unlock(&active_mi->rli.data_lock);
} }
pthread_mutex_unlock(&active_mi->rli.run_lock); pthread_mutex_unlock(&active_mi->rli.run_lock);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
return 0; return 0;
} }
......
...@@ -34,7 +34,6 @@ typedef bool (*CHECK_KILLED_FUNC)(THD*,void*); ...@@ -34,7 +34,6 @@ typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
volatile bool slave_sql_running = 0, slave_io_running = 0; volatile bool slave_sql_running = 0, slave_io_running = 0;
char* slave_load_tmpdir = 0; char* slave_load_tmpdir = 0;
MASTER_INFO *active_mi; MASTER_INFO *active_mi;
volatile int active_mi_in_use = 0;
HASH replicate_do_table, replicate_ignore_table; HASH replicate_do_table, replicate_ignore_table;
DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
bool do_table_inited = 0, ignore_table_inited = 0; bool do_table_inited = 0, ignore_table_inited = 0;
...@@ -114,8 +113,12 @@ int init_slave() ...@@ -114,8 +113,12 @@ int init_slave()
{ {
DBUG_ENTER("init_slave"); DBUG_ENTER("init_slave");
/* This is called when mysqld starts */ /*
This is called when mysqld starts. Before client connections are
accepted. However bootstrap may conflict with us if it does START SLAVE.
So it's safer to take the lock.
*/
pthread_mutex_lock(&LOCK_active_mi);
/* /*
TODO: re-write this to interate through the list of files TODO: re-write this to interate through the list of files
for multi-master for multi-master
...@@ -160,9 +163,11 @@ int init_slave() ...@@ -160,9 +163,11 @@ int init_slave()
goto err; goto err;
} }
} }
pthread_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
pthread_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -806,7 +811,14 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) ...@@ -806,7 +811,14 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
void end_slave() void end_slave()
{ {
/* This is called when the server terminates, in close_connections(). */ /*
This is called when the server terminates, in close_connections().
It terminates slave threads. However, some CHANGE MASTER etc may still be
running presently. If a START SLAVE was in progress, the mutex lock below
will make us wait until slave threads have started, and START SLAVE
returns, then we terminate them here.
*/
pthread_mutex_lock(&LOCK_active_mi);
if (active_mi) if (active_mi)
{ {
/* /*
...@@ -827,6 +839,7 @@ void end_slave() ...@@ -827,6 +839,7 @@ void end_slave()
delete active_mi; delete active_mi;
active_mi= 0; active_mi= 0;
} }
pthread_mutex_unlock(&LOCK_active_mi);
} }
......
...@@ -27,12 +27,19 @@ ...@@ -27,12 +27,19 @@
/* /*
MUTEXES in replication: MUTEXES in replication:
LOCK_active_mi: this is meant for multimaster, when we can switch from a LOCK_active_mi: [note: this was originally meant for multimaster, to switch
master to another. It protects active_mi. We don't care of it for the moment, from a master to another, to protect active_mi] It is used to SERIALIZE ALL
as active_mi never moves (it's created at startup and deleted at shutdown, and administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE
not changed: it always points to the same MASTER_INFO struct), because we MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not
don't have multimaster. So for the moment, mi does not move, and mi->rli does need it it's called early]. Any of these commands holds the mutex from the
not either. start till the end. This thus protects us against a handful of deadlocks
(consider start_slave_thread() which, when starting the I/O thread, releases
mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock).
Currently active_mi never moves (it's created at startup and deleted at
shutdown, and not changed: it always points to the same MASTER_INFO struct),
because we don't have multimaster. So for the moment, mi does not move, and
mi->rli does not either.
In MASTER_INFO: run_lock, data_lock In MASTER_INFO: run_lock, data_lock
run_lock protects all information about the run state: slave_running, and the run_lock protects all information about the run state: slave_running, and the
...@@ -43,6 +50,9 @@ ...@@ -43,6 +50,9 @@
In RELAY_LOG_INFO: run_lock, data_lock In RELAY_LOG_INFO: run_lock, data_lock
see MASTER_INFO see MASTER_INFO
Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
must acquire LOCK_active_mi first.
In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log
LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
(so that you have to update the .index file). (so that you have to update the .index file).
...@@ -64,19 +74,6 @@ enum enum_binlog_formats { ...@@ -64,19 +74,6 @@ enum enum_binlog_formats {
BINLOG_FORMAT_323_LESS_57, BINLOG_FORMAT_323_LESS_57,
BINLOG_FORMAT_323_GEQ_57 }; BINLOG_FORMAT_323_GEQ_57 };
/*
TODO: this needs to be redone, but for now it does not matter since
we do not have multi-master yet.
*/
#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
++active_mi_in_use; \
pthread_mutex_unlock(&LOCK_active_mi);}
#define UNLOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
--active_mi_in_use; \
pthread_mutex_unlock(&LOCK_active_mi); }
/* /*
st_relay_log_info contains information on the current relay log and st_relay_log_info contains information on the current relay log and
relay log offset, and master log name and log sequence corresponding to the relay log offset, and master log name and log sequence corresponding to the
...@@ -441,7 +438,6 @@ extern "C" pthread_handler_decl(handle_slave_io,arg); ...@@ -441,7 +438,6 @@ extern "C" pthread_handler_decl(handle_slave_io,arg);
extern "C" pthread_handler_decl(handle_slave_sql,arg); extern "C" pthread_handler_decl(handle_slave_sql,arg);
extern bool volatile abort_loop; extern bool volatile abort_loop;
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */ extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
extern volatile int active_mi_in_use;
extern LIST master_list; extern LIST master_list;
extern HASH replicate_do_table, replicate_ignore_table; extern HASH replicate_do_table, replicate_ignore_table;
extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
......
...@@ -1519,9 +1519,9 @@ mysql_execute_command(void) ...@@ -1519,9 +1519,9 @@ mysql_execute_command(void)
{ {
if (check_global_access(thd, SUPER_ACL)) if (check_global_access(thd, SUPER_ACL))
goto error; goto error;
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
res = change_master(thd,active_mi); res = change_master(thd,active_mi);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
break; break;
} }
case SQLCOM_SHOW_SLAVE_STAT: case SQLCOM_SHOW_SLAVE_STAT:
...@@ -1529,9 +1529,9 @@ mysql_execute_command(void) ...@@ -1529,9 +1529,9 @@ mysql_execute_command(void)
/* Accept one of two privileges */ /* Accept one of two privileges */
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error; goto error;
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
res = show_master_info(thd,active_mi); res = show_master_info(thd,active_mi);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
break; break;
} }
case SQLCOM_SHOW_MASTER_STAT: case SQLCOM_SHOW_MASTER_STAT:
...@@ -1581,7 +1581,7 @@ mysql_execute_command(void) ...@@ -1581,7 +1581,7 @@ mysql_execute_command(void)
if (error) if (error)
goto error; goto error;
} }
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
/* /*
fetch_master_table will send the error to the client on failure. fetch_master_table will send the error to the client on failure.
Give error if the table already exists. Give error if the table already exists.
...@@ -1591,7 +1591,7 @@ mysql_execute_command(void) ...@@ -1591,7 +1591,7 @@ mysql_execute_command(void)
{ {
send_ok(&thd->net); send_ok(&thd->net);
} }
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
break; break;
} }
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */
...@@ -1702,9 +1702,9 @@ mysql_execute_command(void) ...@@ -1702,9 +1702,9 @@ mysql_execute_command(void)
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
case SQLCOM_SLAVE_START: case SQLCOM_SLAVE_START:
{ {
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
start_slave(thd,active_mi,1 /* net report*/); start_slave(thd,active_mi,1 /* net report*/);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
break; break;
} }
case SQLCOM_SLAVE_STOP: case SQLCOM_SLAVE_STOP:
...@@ -1727,9 +1727,9 @@ mysql_execute_command(void) ...@@ -1727,9 +1727,9 @@ mysql_execute_command(void)
break; break;
} }
{ {
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
stop_slave(thd,active_mi,1/* net report*/); stop_slave(thd,active_mi,1/* net report*/);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
break; break;
} }
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */
...@@ -3638,9 +3638,9 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) ...@@ -3638,9 +3638,9 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
mysql_update_log.new_file(1); mysql_update_log.new_file(1);
mysql_bin_log.new_file(1); mysql_bin_log.new_file(1);
mysql_slow_log.new_file(1); mysql_slow_log.new_file(1);
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi); rotate_relay_log(active_mi);
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
if (ha_flush_logs()) if (ha_flush_logs())
result=1; result=1;
...@@ -3685,7 +3685,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) ...@@ -3685,7 +3685,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
#endif #endif
if (options & REFRESH_SLAVE) if (options & REFRESH_SLAVE)
{ {
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
if (reset_slave(thd, active_mi)) if (reset_slave(thd, active_mi))
{ {
result=1; result=1;
...@@ -3697,7 +3697,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) ...@@ -3697,7 +3697,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
*/ */
error_already_sent=1; error_already_sent=1;
} }
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
} }
if (options & REFRESH_USER_RESOURCES) if (options & REFRESH_USER_RESOURCES)
reset_mqh(thd,(LEX_USER *) NULL); reset_mqh(thd,(LEX_USER *) NULL);
......
...@@ -1270,11 +1270,11 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, ...@@ -1270,11 +1270,11 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
case SHOW_SLAVE_RUNNING: case SHOW_SLAVE_RUNNING:
{ {
LOCK_ACTIVE_MI; pthread_mutex_lock(&LOCK_active_mi);
net_store_data(&packet2, (active_mi->slave_running && net_store_data(&packet2, (active_mi->slave_running &&
active_mi->rli.slave_running) active_mi->rli.slave_running)
? "ON" : "OFF"); ? "ON" : "OFF");
UNLOCK_ACTIVE_MI; pthread_mutex_unlock(&LOCK_active_mi);
break; break;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment