diff options
author | unknown <SergeyV@selena.> | 2005-10-03 20:34:42 +0400 |
---|---|---|
committer | unknown <SergeyV@selena.> | 2005-10-03 20:34:42 +0400 |
commit | 76d4d4d45fec835ab3e896a0ef93f62aa8ff7c35 (patch) | |
tree | b17d1a566a5575ed3924ecb63801228be96d4018 | |
parent | ee437eb74602c72c22bb93404c1b6f1e0a8e493d (diff) | |
download | mariadb-git-76d4d4d45fec835ab3e896a0ef93f62aa8ff7c35.tar.gz |
Fixes bug #13377. Added code to close active log files in case
of log reset condition.
sql/log.cc:
Added references counter of binlog readers to wait for closing opened log
files by al readers for binary log reset.
sql/slave.cc:
Added a code to close opened relay log files, when they are not used anymore.
sql/sql_class.h:
Added declarations to maintain references count of binlog readers.
Added reset log wait condition.
sql/sql_repl.cc:
Added code to close active log files in case of log reset condition.
-rw-r--r-- | sql/log.cc | 67 | ||||
-rw-r--r-- | sql/slave.cc | 17 | ||||
-rw-r--r-- | sql/sql_class.h | 8 | ||||
-rw-r--r-- | sql/sql_repl.cc | 37 |
4 files changed, 122 insertions, 7 deletions
diff --git a/sql/log.cc b/sql/log.cc index 6e372938752..d5a5eecf36b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -353,7 +353,7 @@ MYSQL_LOG::MYSQL_LOG() :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), need_start_event(1), prepared_xids(0), description_event_for_exec(0), - description_event_for_queue(0) + description_event_for_queue(0), readers_count(0), reset_pending(false) { /* We don't want to initialize LOCK_Log here as such initialization depends on @@ -379,7 +379,9 @@ void MYSQL_LOG::cleanup() delete description_event_for_exec; (void) pthread_mutex_destroy(&LOCK_log); (void) pthread_mutex_destroy(&LOCK_index); + (void) pthread_mutex_destroy(&LOCK_readers); (void) pthread_cond_destroy(&update_cond); + (void) pthread_cond_destroy(&reset_cond); } DBUG_VOID_RETURN; } @@ -424,7 +426,9 @@ void MYSQL_LOG::init_pthread_objects() inited= 1; (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_readers, MY_MUTEX_INIT_SLOW); (void) pthread_cond_init(&update_cond, 0); + (void) pthread_cond_init(&reset_cond, 0); } const char *MYSQL_LOG::generate_name(const char *log_name, @@ -927,6 +931,13 @@ bool MYSQL_LOG::reset_logs(THD* thd) */ pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_index); + + /* + we need one more lock to block attempts to open a log while + we are waiting untill all log files will be closed + */ + pthread_mutex_lock(&LOCK_readers); + /* The following mutex is needed to ensure that no threads call 'delete thd' as we would then risk missing a 'rollback' from this @@ -949,6 +960,19 @@ bool MYSQL_LOG::reset_logs(THD* thd) goto err; } + reset_pending = true; + /* + send update signal just in case so that all reader threads waiting + for log update will leave wait condition + */ + signal_update(); + /* + if there are active readers wait until all of them will + release opened files + */ + if (readers_count) + pthread_cond_wait(&reset_cond, &LOCK_log); + for (;;) { my_delete(linfo.log_file_name, MYF(MY_WME)); @@ -967,7 +991,10 @@ bool MYSQL_LOG::reset_logs(THD* thd) my_free((gptr) save_name, MYF(0)); err: + reset_pending = false; + (void) pthread_mutex_unlock(&LOCK_thread_count); + pthread_mutex_unlock(&LOCK_readers); pthread_mutex_unlock(&LOCK_index); pthread_mutex_unlock(&LOCK_log); DBUG_RETURN(error); @@ -2038,6 +2065,10 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave) { const char *old_msg; DBUG_ENTER("wait_for_update"); + + if (reset_pending) + DBUG_VOID_RETURN; + old_msg= thd->enter_cond(&update_cond, &LOCK_log, is_slave ? "Has read all relay log; waiting for the slave I/O " @@ -2288,6 +2319,40 @@ void MYSQL_LOG::signal_update() DBUG_VOID_RETURN; } +void MYSQL_LOG::readers_addref() +{ + /* + currently readers_addref and readers_release are necessary + only for __WIN__ build to wait untill readers will close + opened log files before reset. + There is no necessity for this on *nix, since it allows to + delete opened files, however it is more clean way to wait + untill all files will be closed on *nix as well. + If decided, the following #ifdef section is to be removed. + */ +#ifdef __WIN__ + DBUG_ENTER("MYSQL_LOG::reader_addref"); + pthread_mutex_lock(&LOCK_log); + pthread_mutex_lock(&LOCK_readers); + readers_count++; + pthread_mutex_unlock(&LOCK_readers); + pthread_mutex_unlock(&LOCK_log); + DBUG_VOID_RETURN; +#endif +} + +void MYSQL_LOG::readers_release() +{ +#ifdef __WIN__ + DBUG_ENTER("MYSQL_LOG::reader_release"); + pthread_mutex_lock(&LOCK_log); + readers_count--; + if (!readers_count) + pthread_cond_broadcast(&reset_cond); + pthread_mutex_unlock(&LOCK_log); + DBUG_VOID_RETURN; +#endif +} #ifdef __NT__ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, diff --git a/sql/slave.cc b/sql/slave.cc index 092fb40d9d9..0fd9393ed3a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3615,6 +3615,15 @@ err: pthread_mutex_lock(&mi->run_lock); mi->slave_running = 0; mi->io_thd = 0; + + /* Close log file and free buffers */ + if (mi->rli.cur_log_fd >= 0) + { + end_io_cache(&mi->rli.cache_buf); + my_close(mi->rli.cur_log_fd, MYF(MY_WME)); + mi->rli.cur_log_fd= -1; + } + /* Forget the relay log's format */ delete mi->rli.relay_log.description_event_for_queue; mi->rli.relay_log.description_event_for_queue= 0; @@ -3831,6 +3840,14 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ rli->cached_charset_invalidate(); rli->save_temporary_tables = thd->temporary_tables; + /* Close log file and free buffers if it's already open */ + if (rli->cur_log_fd >= 0) + { + end_io_cache(&rli->cache_buf); + my_close(rli->cur_log_fd, MYF(MY_WME)); + rli->cur_log_fd = -1; + } + /* TODO: see if we can do this conditionally in next_event() instead to avoid unneeded position re-init diff --git a/sql/sql_class.h b/sql/sql_class.h index 7cbfc19123f..903b786d21d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -189,8 +189,11 @@ class MYSQL_LOG: public TC_LOG { private: /* LOCK_log and LOCK_index are inited by init_pthread_objects() */ - pthread_mutex_t LOCK_log, LOCK_index; + pthread_mutex_t LOCK_log, LOCK_index, LOCK_readers; pthread_cond_t update_cond; + pthread_cond_t reset_cond; + bool reset_pending; + int readers_count; ulonglong bytes_written; time_t last_time,query_start; IO_CACHE log_file; @@ -334,6 +337,9 @@ public: int purge_logs_before_date(time_t purge_time); int purge_first_log(struct st_relay_log_info* rli, bool included); bool reset_logs(THD* thd); + inline bool is_reset_pending() { return reset_pending; } + void readers_addref(); + void readers_release(); void close(uint exiting); // iterating through the log index file diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 98f47d13eee..b5865fa8816 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -372,6 +372,11 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, goto err; } + /* + Call readers_addref before opening log to track count + of binlog readers + */ + mysql_bin_log.readers_addref(); if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0) { my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; @@ -569,7 +574,8 @@ impossible position"; goto err; if (!(flags & BINLOG_DUMP_NON_BLOCK) && - mysql_bin_log.is_active(log_file_name)) + mysql_bin_log.is_active(log_file_name) && + !mysql_bin_log.is_reset_pending()) { /* Block until there is more data in the log @@ -683,6 +689,13 @@ impossible position"; { bool loop_breaker = 0; // need this to break out of the for loop from switch + + // if we are going to switch log file anyway, close current log first + end_io_cache(&log); + (void) my_close(file, MYF(MY_WME)); + // decrease reference count of binlog readers + mysql_bin_log.readers_release(); + thd->proc_info = "Finished reading one binlog; switching to next binlog"; switch (mysql_bin_log.find_next_log(&linfo, 1)) { case LOG_INFO_EOF: @@ -691,16 +704,25 @@ impossible position"; case 0: break; default: + // need following call to do release on err label + mysql_bin_log.readers_addref(); errmsg = "could not find next log"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; } - if (loop_breaker) - break; + if (loop_breaker) + { + // need following call to do release on end label + mysql_bin_log.readers_addref(); + break; + } - end_io_cache(&log); - (void) my_close(file, MYF(MY_WME)); + /* + Call readers_addref before opening log to track count + of binlog readers + */ + mysql_bin_log.readers_addref(); /* Call fake_rotate_event() in case the previous log (the one which @@ -733,6 +755,8 @@ end: end_io_cache(&log); (void)my_close(file, MYF(MY_WME)); + // decrease reference count of binlog readers + mysql_bin_log.readers_release(); send_eof(thd); thd->proc_info = "Waiting to finalize termination"; @@ -759,6 +783,9 @@ err: pthread_mutex_unlock(&LOCK_thread_count); if (file >= 0) (void) my_close(file, MYF(MY_WME)); + // decrease reference count of binlog readers + mysql_bin_log.readers_release(); + my_message(my_errno, errmsg, MYF(0)); DBUG_VOID_RETURN; } |