Commit d974959b authored by unknown's avatar unknown

Fix for BUG#791:

a safer way of initing the mutexes in MYSQL_LOG.
is_open() is now always thread-safe.
See each file for details.


sql/handler.cc:
  is_open() with locks
sql/item_func.cc:
  is_open() with locks
sql/log.cc:
  No more 'inited'.
  We now always use is_open() in a thread-safe manner.
  This simplifies some functions (no more need to test is_open() twice).
sql/log_event.cc:
  is_open() with locks
sql/mysqld.cc:
  Init mutexes for the global MYSQL_LOG objects.
  We care about no_rotate, because we can't do it in open() anymore (because
  we don't have 'inited' anymore).
sql/repl_failsafe.cc:
  is_open() with locks
sql/slave.cc:
  init pthread objects (mutexes, conds) in the constructor of st_relay_log_info.
  Some better locking in rotate_relay_log().
sql/sql_base.cc:
  is_open() with locks
sql/sql_class.h:
  Before, we inited LOCK_log in MYSQL_LOG::open(), so in other places of the code
  when we were never 100% sure that it had been inited. For example, if the server
  was running without --log-bin, ::open() was not called so the mutex was not
  inited. We could detect it with !inited, but not safely as 'inited' was not
  protected by any mutex.
  So now:
  we *always* init the LOCK_log mutex, even if the log is not used. We can't init
  the mutex in MYSQL_LOG's constructor, because for global objects like
  mysql_bin_log, mysql_log etc, the constructor is called before MY_INIT(), but
  safe_mutex depends on MY_INIT(). So we have a new function MYSQL_LOG::init_pthread_objects
  which we call in main(), after MY_INIT().
  For the relay log, we call this function in the constructor of
  st_relay_log_info, which is called before any function tries to
  use the relay log (the relay log is always invoked as rli.relay_log).
  So now we should be safe in all cases and we don't need 'inited'.
sql/sql_db.cc:
  is_open() with locks
sql/sql_delete.cc:
  is_open() with locks
sql/sql_insert.cc:
  is_open() with locks
sql/sql_load.cc:
  is_open() with locks
sql/sql_parse.cc:
  is_open() with locks
sql/sql_rename.cc:
  is_open() with locks
sql/sql_repl.cc:
  is_open() with locks
sql/sql_table.cc:
  is_open() with locks
sql/sql_update.cc:
  is_open() with locks
parent f200fa15
...@@ -346,7 +346,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) ...@@ -346,7 +346,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
bool transaction_commited= 0; bool transaction_commited= 0;
/* Update the binary log if we have cached some queries */ /* Update the binary log if we have cached some queries */
if (trans == &thd->transaction.all && mysql_bin_log.is_open() && if (trans == &thd->transaction.all && mysql_bin_log.is_open(1) &&
my_b_tell(&thd->transaction.trans_log)) my_b_tell(&thd->transaction.trans_log))
{ {
mysql_bin_log.write(thd, &thd->transaction.trans_log); mysql_bin_log.write(thd, &thd->transaction.trans_log);
...@@ -385,7 +385,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) ...@@ -385,7 +385,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
if (transaction_commited && thd->transaction.changed_tables) if (transaction_commited && thd->transaction.changed_tables)
query_cache.invalidate(thd->transaction.changed_tables); query_cache.invalidate(thd->transaction.changed_tables);
#endif /*HAVE_QUERY_CACHE*/ #endif /*HAVE_QUERY_CACHE*/
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open()) if (error && trans == &thd->transaction.all && mysql_bin_log.is_open(1))
sql_print_error("Error: Got error during commit; Binlog is not up to date!"); sql_print_error("Error: Got error during commit; Binlog is not up to date!");
thd->variables.tx_isolation=thd->session_tx_isolation; thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done) if (operation_done)
......
...@@ -1504,7 +1504,7 @@ void item_user_lock_free(void) ...@@ -1504,7 +1504,7 @@ void item_user_lock_free(void)
void item_user_lock_release(ULL *ull) void item_user_lock_release(ULL *ull)
{ {
ull->locked=0; ull->locked=0;
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
char buf[256]; char buf[256];
String tmp(buf,sizeof(buf)); String tmp(buf,sizeof(buf));
......
...@@ -82,12 +82,14 @@ static int find_uniq_filename(char *name) ...@@ -82,12 +82,14 @@ static int find_uniq_filename(char *name)
MYSQL_LOG::MYSQL_LOG() MYSQL_LOG::MYSQL_LOG()
:bytes_written(0), last_time(0), query_start(0), name(0), :bytes_written(0), last_time(0), query_start(0), name(0),
file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0), file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0),
no_rotate(0), need_start_event(1) no_rotate(0), need_start_event(1)
{ {
/* /*
We don't want to intialize LOCK_Log here as the thread system may We don't want to initialize LOCK_Log here as such initialization depends on
not have been initailized yet. We do it instead at 'open'. safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
called only in main(). Doing initialization here would make it happen before
main().
*/ */
index_file_name[0] = 0; index_file_name[0] = 0;
bzero((char*) &log_file,sizeof(log_file)); bzero((char*) &log_file,sizeof(log_file));
...@@ -100,18 +102,35 @@ MYSQL_LOG::~MYSQL_LOG() ...@@ -100,18 +102,35 @@ MYSQL_LOG::~MYSQL_LOG()
cleanup(); cleanup();
} }
void MYSQL_LOG::cleanup() void MYSQL_LOG::cleanup() /* this is called only once */
{ {
if (inited)
{
close(1); close(1);
inited= 0;
(void) pthread_mutex_destroy(&LOCK_log); (void) pthread_mutex_destroy(&LOCK_log);
(void) pthread_mutex_destroy(&LOCK_index); (void) pthread_mutex_destroy(&LOCK_index);
(void) pthread_cond_destroy(&update_cond); (void) pthread_cond_destroy(&update_cond);
}
} }
bool MYSQL_LOG::is_open(bool need_mutex)
{
/*
Since MySQL 4.0.14, LOCK_log is always inited:
* for log/update_log/slow_log/bin_log which are global objects, this is done in
main(), even if the server does not use these logs.
* for relay_log which belongs to rli which belongs to active_mi, this is
done in the constructor of rli.
In older versions, we were never 100% sure that LOCK_log was inited, which
was a problem.
*/
if (need_mutex)
{
pthread_mutex_lock(&LOCK_log);
bool res= (log_type != LOG_CLOSED);
pthread_mutex_unlock(&LOCK_log);
return res;
}
else
return (log_type != LOG_CLOSED);
}
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
{ {
...@@ -142,17 +161,16 @@ void MYSQL_LOG::init(enum_log_type log_type_arg, ...@@ -142,17 +161,16 @@ void MYSQL_LOG::init(enum_log_type log_type_arg,
no_auto_events = no_auto_events_arg; no_auto_events = no_auto_events_arg;
max_size=max_size_arg; max_size=max_size_arg;
DBUG_PRINT("info",("log_type: %d max_size: %lu", log_type, max_size)); DBUG_PRINT("info",("log_type: %d max_size: %lu", log_type, max_size));
if (!inited) DBUG_VOID_RETURN;
{ }
inited= 1;
void MYSQL_LOG::init_pthread_objects()
{
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
(void) pthread_cond_init(&update_cond, 0); (void) pthread_cond_init(&update_cond, 0);
}
DBUG_VOID_RETURN;
} }
/* /*
Open a (new) log file. Open a (new) log file.
...@@ -182,8 +200,6 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, ...@@ -182,8 +200,6 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
last_time=query_start=0; last_time=query_start=0;
write_error=0; write_error=0;
if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name))
no_rotate = 1;
init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size); init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size);
if (!(name=my_strdup(log_name,MYF(MY_WME)))) if (!(name=my_strdup(log_name,MYF(MY_WME))))
...@@ -631,7 +647,7 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli) ...@@ -631,7 +647,7 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
Assume that we have previously read the first log and Assume that we have previously read the first log and
stored it in rli->relay_log_name stored it in rli->relay_log_name
*/ */
DBUG_ASSERT(is_open()); DBUG_ASSERT(is_open(1));
DBUG_ASSERT(rli->slave_running == 1); DBUG_ASSERT(rli->slave_running == 1);
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name)); DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
DBUG_ASSERT(rli->linfo.index_file_offset == DBUG_ASSERT(rli->linfo.index_file_offset ==
...@@ -770,14 +786,11 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log) ...@@ -770,14 +786,11 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
{ {
if (inited) // QQ When is this not true ?
{
uint dir_len = dirname_length(log_file_name); uint dir_len = dirname_length(log_file_name);
if (dir_len > FN_REFLEN) if (dir_len > FN_REFLEN)
dir_len=FN_REFLEN-1; dir_len=FN_REFLEN-1;
strnmov(buf, log_file_name, dir_len); strnmov(buf, log_file_name, dir_len);
strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len); strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len);
}
} }
...@@ -787,7 +800,7 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) ...@@ -787,7 +800,7 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
bool MYSQL_LOG::is_active(const char *log_file_name_arg) bool MYSQL_LOG::is_active(const char *log_file_name_arg)
{ {
return inited && !strcmp(log_file_name, log_file_name_arg); return !strcmp(log_file_name, log_file_name_arg);
} }
...@@ -809,7 +822,7 @@ void MYSQL_LOG::new_file(bool need_lock) ...@@ -809,7 +822,7 @@ void MYSQL_LOG::new_file(bool need_lock)
enum_log_type save_log_type; enum_log_type save_log_type;
DBUG_ENTER("MYSQL_LOG::new_file"); DBUG_ENTER("MYSQL_LOG::new_file");
if (!is_open()) if (!is_open(need_lock))
{ {
DBUG_PRINT("info",("log is closed")); DBUG_PRINT("info",("log is closed"));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -876,7 +889,9 @@ void MYSQL_LOG::new_file(bool need_lock) ...@@ -876,7 +889,9 @@ void MYSQL_LOG::new_file(bool need_lock)
name=0; // Don't free name name=0; // Don't free name
close(); close();
// TODO: at this place is_open() will see the log closed, which is BUG#791. /*
Note that at this point, log_type == LOG_CLOSED (important for is_open()).
*/
open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type, open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type,
no_auto_events, max_size); no_auto_events, max_size);
...@@ -967,12 +982,11 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...) ...@@ -967,12 +982,11 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
const char *format,...) const char *format,...)
{ {
if (is_open() && (what_to_log & (1L << (uint) command))) if (what_to_log & (1L << (uint) command))
{ {
int error=0; int error=0;
VOID(pthread_mutex_lock(&LOCK_log)); VOID(pthread_mutex_lock(&LOCK_log));
/* Test if someone closed between the is_open test and lock */
if (is_open()) if (is_open())
{ {
time_t skr; time_t skr;
...@@ -1055,14 +1069,13 @@ bool MYSQL_LOG::write(Log_event* event_info) ...@@ -1055,14 +1069,13 @@ bool MYSQL_LOG::write(Log_event* event_info)
bool error=0; bool error=0;
DBUG_ENTER("MYSQL_LOG::write(event)"); DBUG_ENTER("MYSQL_LOG::write(event)");
if (!inited) // Can't use mutex if not init
{
DBUG_PRINT("error",("not initied"));
DBUG_RETURN(0);
}
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
/* In most cases this is only called if 'is_open()' is true */ /*
In most cases this is only called if 'is_open()' is true; in fact this is
mostly called if is_open() *was* true a few instructions before, but it
could have changed since.
*/
if (is_open()) if (is_open())
{ {
bool should_rotate = 0; bool should_rotate = 0;
...@@ -1380,8 +1393,6 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, ...@@ -1380,8 +1393,6 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
time_t query_start_arg) time_t query_start_arg)
{ {
bool error=0; bool error=0;
if (is_open())
{
time_t current_time; time_t current_time;
VOID(pthread_mutex_lock(&LOCK_log)); VOID(pthread_mutex_lock(&LOCK_log));
if (is_open()) if (is_open())
...@@ -1493,7 +1504,6 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, ...@@ -1493,7 +1504,6 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
} }
} }
VOID(pthread_mutex_unlock(&LOCK_log)); VOID(pthread_mutex_unlock(&LOCK_log));
}
return error; return error;
} }
...@@ -1591,14 +1601,12 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg) ...@@ -1591,14 +1601,12 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg)
uses the old_max_size argument, so max_size_arg has been overwritten and uses the old_max_size argument, so max_size_arg has been overwritten and
it's like if the SET command was never run. it's like if the SET command was never run.
*/ */
if (is_open()) DBUG_ENTER("MYSQL_LOG::set_max_size");
{
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
pthread_mutex_lock(&LOCK_index); if (is_open())
max_size= max_size_arg; max_size= max_size_arg;
pthread_mutex_unlock(&LOCK_index);
pthread_mutex_unlock(&LOCK_log); pthread_mutex_unlock(&LOCK_log);
} DBUG_VOID_RETURN;
} }
/* /*
......
...@@ -2167,7 +2167,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2167,7 +2167,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
int Slave_log_event::exec_event(struct st_relay_log_info* rli) int Slave_log_event::exec_event(struct st_relay_log_info* rli)
{ {
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
mysql_bin_log.write(this); mysql_bin_log.write(this);
return Log_event::exec_event(rli); return Log_event::exec_event(rli);
} }
...@@ -2217,7 +2217,7 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2217,7 +2217,7 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
slave_print_error(rli,my_errno, "Write to '%s' failed", fname_buf); slave_print_error(rli,my_errno, "Write to '%s' failed", fname_buf);
goto err; goto err;
} }
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
mysql_bin_log.write(this); mysql_bin_log.write(this);
error=0; // Everything is ok error=0; // Everything is ok
...@@ -2237,7 +2237,7 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2237,7 +2237,7 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
(void) my_delete(fname, MYF(MY_WME)); (void) my_delete(fname, MYF(MY_WME));
memcpy(p, ".info", 6); memcpy(p, ".info", 6);
(void) my_delete(fname, MYF(MY_WME)); (void) my_delete(fname, MYF(MY_WME));
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
mysql_bin_log.write(this); mysql_bin_log.write(this);
return Log_event::exec_event(rli); return Log_event::exec_event(rli);
} }
...@@ -2260,7 +2260,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2260,7 +2260,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
slave_print_error(rli,my_errno, "Write to '%s' failed", fname); slave_print_error(rli,my_errno, "Write to '%s' failed", fname);
goto err; goto err;
} }
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
mysql_bin_log.write(this); mysql_bin_log.write(this);
error=0; error=0;
...@@ -2319,7 +2319,7 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2319,7 +2319,7 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
(void) my_delete(fname, MYF(MY_WME)); (void) my_delete(fname, MYF(MY_WME));
memcpy(p, ".data", 6); memcpy(p, ".data", 6);
(void) my_delete(fname, MYF(MY_WME)); (void) my_delete(fname, MYF(MY_WME));
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
mysql_bin_log.write(this); mysql_bin_log.write(this);
error = 0; error = 0;
......
...@@ -1972,6 +1972,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname, ...@@ -1972,6 +1972,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
strmake(tmp,opt_name,min(length,FN_REFLEN)); strmake(tmp,opt_name,min(length,FN_REFLEN));
opt_name=tmp; opt_name=tmp;
} }
if (*fn_ext(opt_name))
log->set_no_rotate(1);
} }
return log->open(opt_name, type, 0, index_file_name, return log->open(opt_name, type, 0, index_file_name,
(read_append) ? SEQ_READ_APPEND : WRITE_CACHE, (read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
...@@ -2019,6 +2021,17 @@ int main(int argc, char **argv) ...@@ -2019,6 +2021,17 @@ int main(int argc, char **argv)
} }
#endif #endif
/*
Init mutexes for the global MYSQL_LOG objects.
As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
global MYSQL_LOGs in their constructors, because then they would be inited
before MY_INIT(). So we do it here.
*/
mysql_log.init_pthread_objects();
mysql_update_log.init_pthread_objects();
mysql_slow_log.init_pthread_objects();
mysql_bin_log.init_pthread_objects();
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
strmov(glob_hostname,"mysql"); strmov(glob_hostname,"mysql");
strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5); strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
......
...@@ -265,7 +265,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) ...@@ -265,7 +265,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
LINT_INIT(cmp_res); LINT_INIT(cmp_res);
DBUG_ENTER("translate_master"); DBUG_ENTER("translate_master");
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open(1))
{ {
strmov(errmsg,"Binary log is not open"); strmov(errmsg,"Binary log is not open");
DBUG_RETURN(1); DBUG_RETURN(1);
......
...@@ -1736,6 +1736,7 @@ st_relay_log_info::st_relay_log_info() ...@@ -1736,6 +1736,7 @@ st_relay_log_info::st_relay_log_info()
pthread_cond_init(&start_cond, NULL); pthread_cond_init(&start_cond, NULL);
pthread_cond_init(&stop_cond, NULL); pthread_cond_init(&stop_cond, NULL);
pthread_cond_init(&log_space_cond, NULL); pthread_cond_init(&log_space_cond, NULL);
relay_log.init_pthread_objects();
} }
...@@ -3443,14 +3444,18 @@ void rotate_relay_log(MASTER_INFO* mi) ...@@ -3443,14 +3444,18 @@ void rotate_relay_log(MASTER_INFO* mi)
{ {
DBUG_ENTER("rotate_relay_log"); DBUG_ENTER("rotate_relay_log");
RELAY_LOG_INFO* rli= &mi->rli; RELAY_LOG_INFO* rli= &mi->rli;
/* If this server is not a slave (or RESET SLAVE has just been run) */
lock_slave_threads(mi);
pthread_mutex_lock(&rli->data_lock);
/*
We need to test inited because otherwise, new_file() will attempt to lock
LOCK_log, which may not be inited (if we're not a slave).
*/
if (!rli->inited) if (!rli->inited)
{ {
DBUG_PRINT("info", ("rli->inited == 0")); DBUG_PRINT("info", ("rli->inited == 0"));
DBUG_VOID_RETURN; goto end;
} }
lock_slave_threads(mi);
pthread_mutex_lock(&rli->data_lock);
/* If the relay log is closed, new_file() will do nothing. */ /* If the relay log is closed, new_file() will do nothing. */
rli->relay_log.new_file(1); rli->relay_log.new_file(1);
...@@ -3469,6 +3474,7 @@ void rotate_relay_log(MASTER_INFO* mi) ...@@ -3469,6 +3474,7 @@ void rotate_relay_log(MASTER_INFO* mi)
0 as they probably have been harvested. 0 as they probably have been harvested.
*/ */
rli->relay_log.harvest_bytes_written(&rli->log_space_total); rli->relay_log.harvest_bytes_written(&rli->log_space_total);
end:
pthread_mutex_unlock(&rli->data_lock); pthread_mutex_unlock(&rli->data_lock);
unlock_slave_threads(mi); unlock_slave_threads(mi);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
......
...@@ -574,7 +574,7 @@ void close_temporary_tables(THD *thd) ...@@ -574,7 +574,7 @@ void close_temporary_tables(THD *thd)
next=table->next; next=table->next;
close_temporary(table); close_temporary(table);
} }
if (query && found_user_tables && mysql_bin_log.is_open()) if (query && found_user_tables && mysql_bin_log.is_open(1))
{ {
/* The -1 is to remove last ',' */ /* The -1 is to remove last ',' */
Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
......
...@@ -61,6 +61,11 @@ class Log_event; ...@@ -61,6 +61,11 @@ class Log_event;
class MYSQL_LOG { class MYSQL_LOG {
private: private:
/*
LOCK_log is inited by MYSQL_LOG::init(), so one should try to lock it only
if he is sure MYSQL_LOG::init() has been called (i.e. if 'inited' is true).
Same for LOCK_index.
*/
pthread_mutex_t LOCK_log, LOCK_index; pthread_mutex_t LOCK_log, LOCK_index;
pthread_cond_t update_cond; pthread_cond_t update_cond;
ulonglong bytes_written; ulonglong bytes_written;
...@@ -80,7 +85,7 @@ class MYSQL_LOG { ...@@ -80,7 +85,7 @@ class MYSQL_LOG {
*/ */
volatile enum_log_type log_type; volatile enum_log_type log_type;
enum cache_type io_cache_type; enum cache_type io_cache_type;
bool write_error,inited; bool write_error;
bool no_rotate; bool no_rotate;
bool need_start_event; bool need_start_event;
bool no_auto_events; // for relay binlog bool no_auto_events; // for relay binlog
...@@ -123,6 +128,7 @@ class MYSQL_LOG { ...@@ -123,6 +128,7 @@ class MYSQL_LOG {
void init(enum_log_type log_type_arg, void init(enum_log_type log_type_arg,
enum cache_type io_cache_type_arg, enum cache_type io_cache_type_arg,
bool no_auto_events_arg, ulong max_size); bool no_auto_events_arg, ulong max_size);
void init_pthread_objects();
void cleanup(); void cleanup();
bool open(const char *log_name,enum_log_type log_type, bool open(const char *log_name,enum_log_type log_type,
const char *new_name, const char *index_file_name_arg, const char *new_name, const char *index_file_name_arg,
...@@ -158,8 +164,8 @@ class MYSQL_LOG { ...@@ -158,8 +164,8 @@ class MYSQL_LOG {
int find_next_log(LOG_INFO* linfo, bool need_mutex); int find_next_log(LOG_INFO* linfo, bool need_mutex);
int get_current_log(LOG_INFO* linfo); int get_current_log(LOG_INFO* linfo);
uint next_file_id(); uint next_file_id();
bool is_open(bool need_mutex=0);
inline bool is_open() { return log_type != LOG_CLOSED; }
inline char* get_index_fname() { return index_file_name;} inline char* get_index_fname() { return index_file_name;}
inline char* get_log_fname() { return log_file_name; } inline char* get_log_fname() { return log_file_name; }
inline pthread_mutex_t* get_log_lock() { return &LOCK_log; } inline pthread_mutex_t* get_log_lock() { return &LOCK_log; }
...@@ -169,6 +175,7 @@ class MYSQL_LOG { ...@@ -169,6 +175,7 @@ class MYSQL_LOG {
inline void unlock_index() { pthread_mutex_unlock(&LOCK_index);} inline void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
inline IO_CACHE *get_index_file() { return &index_file;} inline IO_CACHE *get_index_file() { return &index_file;}
inline uint32 get_open_count() { return open_count; } inline uint32 get_open_count() { return open_count; }
inline void set_no_rotate(bool no_rotate_arg) {no_rotate= no_rotate_arg;}
}; };
/* character conversion tables */ /* character conversion tables */
......
...@@ -84,7 +84,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) ...@@ -84,7 +84,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
} }
{ {
mysql_update_log.write(thd,thd->query, thd->query_length); mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
...@@ -174,7 +174,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) ...@@ -174,7 +174,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
thd->query= path; thd->query= path;
} }
mysql_update_log.write(thd, thd->query, thd->query_length); mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
......
...@@ -172,7 +172,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -172,7 +172,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (deleted && (error <= 0 || !transactional_table)) if (deleted && (error <= 0 || !transactional_table))
{ {
mysql_update_log.write(thd,thd->query, thd->query_length); mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed); log_delayed);
...@@ -476,7 +476,7 @@ bool multi_delete::send_eof() ...@@ -476,7 +476,7 @@ bool multi_delete::send_eof()
if (deleted && (error <= 0 || normal_tables)) if (deleted && (error <= 0 || normal_tables))
{ {
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed); log_delayed);
...@@ -588,7 +588,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) ...@@ -588,7 +588,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!error) if (!error)
{ {
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
thd->tmp_table); thd->tmp_table);
......
...@@ -308,7 +308,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -308,7 +308,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if ((info.copied || info.deleted) && (error <= 0 || !transactional_table)) if ((info.copied || info.deleted) && (error <= 0 || !transactional_table))
{ {
mysql_update_log.write(thd, thd->query, thd->query_length); mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed); log_delayed);
...@@ -1143,7 +1143,7 @@ bool delayed_insert::handle_inserts(void) ...@@ -1143,7 +1143,7 @@ bool delayed_insert::handle_inserts(void)
{ {
int error; int error;
uint max_rows; uint max_rows;
bool using_ignore=0, using_bin_log=mysql_bin_log.is_open(); bool using_ignore=0, using_bin_log=mysql_bin_log.is_open(1);
delayed_row *row; delayed_row *row;
DBUG_ENTER("handle_inserts"); DBUG_ENTER("handle_inserts");
...@@ -1361,7 +1361,7 @@ void select_insert::send_error(uint errcode,const char *err) ...@@ -1361,7 +1361,7 @@ void select_insert::send_error(uint errcode,const char *err)
if (last_insert_id) if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log thd->insert_id(last_insert_id); // For binary log
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions()); table->file->has_transactions());
...@@ -1387,7 +1387,7 @@ bool select_insert::send_eof() ...@@ -1387,7 +1387,7 @@ bool select_insert::send_eof()
thd->insert_id(last_insert_id); // For binary log thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */ /* Write to binlog before commiting transaction */
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions()); table->file->has_transactions());
......
...@@ -219,7 +219,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -219,7 +219,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_RETURN(-1); // Can't allocate buffers DBUG_RETURN(-1); // Can't allocate buffers
} }
if (!opt_old_rpl_compat && mysql_bin_log.is_open()) if (!opt_old_rpl_compat && mysql_bin_log.is_open(1))
{ {
lf_info.thd = thd; lf_info.thd = thd;
lf_info.ex = ex; lf_info.ex = ex;
...@@ -281,7 +281,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -281,7 +281,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{ {
if (transactional_table) if (transactional_table)
ha_autocommit_or_rollback(thd,error); ha_autocommit_or_rollback(thd,error);
if (!opt_old_rpl_compat && mysql_bin_log.is_open()) if (!opt_old_rpl_compat && mysql_bin_log.is_open(1))
{ {
if (lf_info.wrote_create_file) if (lf_info.wrote_create_file)
{ {
...@@ -315,7 +315,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -315,7 +315,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!log_delayed) if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
if (opt_old_rpl_compat) if (opt_old_rpl_compat)
{ {
...@@ -607,7 +607,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term, ...@@ -607,7 +607,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
cache.read_function = _my_b_net_read; cache.read_function = _my_b_net_read;
need_end_io_cache = 1; need_end_io_cache = 1;
if (!opt_old_rpl_compat && mysql_bin_log.is_open()) if (!opt_old_rpl_compat && mysql_bin_log.is_open(1))
cache.pre_read = cache.pre_close = cache.pre_read = cache.pre_close =
(IO_CACHE_CALLBACK) log_loaded_block; (IO_CACHE_CALLBACK) log_loaded_block;
} }
......
...@@ -2432,7 +2432,7 @@ mysql_execute_command(void) ...@@ -2432,7 +2432,7 @@ mysql_execute_command(void)
lex->sql_command == SQLCOM_REVOKE))) lex->sql_command == SQLCOM_REVOKE)))
{ {
mysql_update_log.write(thd, thd->query, thd->query_length); mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
...@@ -2452,7 +2452,7 @@ mysql_execute_command(void) ...@@ -2452,7 +2452,7 @@ mysql_execute_command(void)
if (!res) if (!res)
{ {
mysql_update_log.write(thd, thd->query, thd->query_length); mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
......
...@@ -80,7 +80,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) ...@@ -80,7 +80,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if (!error) if (!error)
{ {
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
......
...@@ -269,7 +269,7 @@ int purge_master_logs(THD* thd, const char* to_log) ...@@ -269,7 +269,7 @@ int purge_master_logs(THD* thd, const char* to_log)
const char* errmsg = 0; const char* errmsg = 0;
int res; int res;
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open(1))
goto end; goto end;
mysql_bin_log.make_log_name(search_file_name, to_log); mysql_bin_log.make_log_name(search_file_name, to_log);
...@@ -335,7 +335,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ...@@ -335,7 +335,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
} }
#endif #endif
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open(1))
{ {
errmsg = "Binary log is not open"; errmsg = "Binary log is not open";
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
...@@ -972,7 +972,7 @@ int change_master(THD* thd, MASTER_INFO* mi) ...@@ -972,7 +972,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
int reset_master(THD* thd) int reset_master(THD* thd)
{ {
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open(1))
{ {
my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG)); my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG));
return 1; return 1;
...@@ -1010,7 +1010,7 @@ int show_binlog_events(THD* thd) ...@@ -1010,7 +1010,7 @@ int show_binlog_events(THD* thd)
if (send_fields(thd, field_list, 1)) if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
LEX_MASTER_INFO *lex_mi = &thd->lex.mi; LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
ha_rows event_count, limit_start, limit_end; ha_rows event_count, limit_start, limit_end;
...@@ -1110,7 +1110,7 @@ int show_binlog_info(THD* thd) ...@@ -1110,7 +1110,7 @@ int show_binlog_info(THD* thd)
String* packet = &thd->packet; String* packet = &thd->packet;
packet->length(0); packet->length(0);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
LOG_INFO li; LOG_INFO li;
mysql_bin_log.get_current_log(&li); mysql_bin_log.get_current_log(&li);
...@@ -1128,7 +1128,7 @@ int show_binlog_info(THD* thd) ...@@ -1128,7 +1128,7 @@ int show_binlog_info(THD* thd)
/* /*
Send a lost of all binary logs to client Send a list of all binary logs to client
SYNOPSIS SYNOPSIS
show_binlogs() show_binlogs()
...@@ -1148,7 +1148,7 @@ int show_binlogs(THD* thd) ...@@ -1148,7 +1148,7 @@ int show_binlogs(THD* thd)
String *packet = &thd->packet; String *packet = &thd->packet;
uint length; uint length;
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open(1))
{ {
//TODO: Replace with ER() error message //TODO: Replace with ER() error message
send_error(net, 0, "You are not using binary logging"); send_error(net, 0, "You are not using binary logging");
......
...@@ -235,7 +235,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -235,7 +235,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (!dont_log_query) if (!dont_log_query)
{ {
mysql_update_log.write(thd, thd->query,thd->query_length); mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
tmp_table_deleted && !some_tables_deleted); tmp_table_deleted && !some_tables_deleted);
...@@ -766,7 +766,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -766,7 +766,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{ {
// Must be written before unlock // Must be written before unlock
mysql_update_log.write(thd,thd->query, thd->query_length); mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
test(create_info->options & test(create_info->options &
...@@ -1548,7 +1548,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1548,7 +1548,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!error) if (!error)
{ {
mysql_update_log.write(thd, thd->query, thd->query_length); mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
...@@ -1918,7 +1918,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1918,7 +1918,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err; goto err;
} }
mysql_update_log.write(thd, thd->query,thd->query_length); mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
...@@ -2050,7 +2050,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2050,7 +2050,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
thd->proc_info="end"; thd->proc_info="end";
mysql_update_log.write(thd, thd->query,thd->query_length); mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
......
...@@ -317,7 +317,7 @@ int mysql_update(THD *thd, ...@@ -317,7 +317,7 @@ int mysql_update(THD *thd,
if (updated && (error <= 0 || !transactional_table)) if (updated && (error <= 0 || !transactional_table))
{ {
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed); log_delayed);
...@@ -933,7 +933,7 @@ bool multi_update::send_eof() ...@@ -933,7 +933,7 @@ bool multi_update::send_eof()
if (updated && (local_error <= 0 || !trans_safe)) if (updated && (local_error <= 0 || !trans_safe))
{ {
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open(1))
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed); log_delayed);
......
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