Hi Alfranio,
On Tue, 2009-07-14 at 03:22 +0100, Alfranio Correia wrote:
> Hi Luis,
>
> Thank you.
>
> As we already discussed on skype I will split this bug in two.
>
> The current bug will be addressing item #1 and #2 and a
> new bug will be addressing #3. Let me know if you agree
> with that.
Just make sure that the escalated bug, fixes the right thing.
Regards,
Luís
> See other comments in-line.
>
> Cheers.
>
>
> Luís Soares wrote:
> > Hi Alfranio,
> >
> > Check some comments inline. Please, feel free to discuss them.
> >
> > Regards,
> > Luís
> >
> >
> > STATUS
> > ------
> >
> > Not Approved.
> >
> > REQUIRED CHANGES
> > ----------------
> >
> > 1. Before heading into more technical issues, I think that we
> > need a patch that fixes the case that a binlog file is
> > created without even being recorded in the index file. This
> > is somewhat the situation that is pointed out in issue #2 in
> > your description in the bug report. Without a fix for this,
> > one can still get an orphan/dangling binlog file in the
> > filesystem, eventually causing some oddness in some perverse
> > way.
> >
> > This should be addressed, because there are people that
> > write tools that rely on filesystem information/data (like
> > binlog files, binlog file sizes, etc...) to decide whether
> > to start/stop, issue purge operations and so forth... So if
> > we have some dangling binlog file that the server is not
> > aware of, or is inconsistent with server state, some
> > reasonable assumptions will break.
> >
> As you already discussed on the skype this will be addressed. I just
> wasted more time than I was expecting to build part of the solution (#1)
> and
> forgot to implement the part #2. The patch is quite simple I just need
> to know if you
> agree with my idea. Let's chat on the skype today.
> > 2. With respect to fix for issue #1, I am a bit skeptical to
> > have yet another file for tracking logging issues. Also,
> > that behavior is just the way things are, since updating
> > index files and purging logs is not an atomic operation.
> >
> > Since you are addressing it, maybe we could persist purge
> > information as part of a system table (as we are thinking on
> > doing for *.info files in WL#2775), but I have not really
> > thought of this. At the lack of a better proposal, I think
> > that we can get along with a file, although I don't like
> > this.
> >
> > Furthermore, given that we are considering this behavior as
> > a bug, I think we should consider issue #2 also (the case
> > where a binlog file is created on unsuccessful server
> > startup and is not recorded in the index files before
> > crash). This seems to be what is causing some pains (see
> > support issue).
> >
> > Basically, it seems that binlog orphan files may happen due
> > to:
> >
> > i) (from your description in issue #1) - server crash after
> > updating binlog index files and before deleting the
> > binlog files from the filesystem.
> >
> > ii) (from the description in support case - related to issue
> > #2 you posted in the bug report) - server crash on startup,
> > which can cause creation of binlog file but no update to
> > index before crash...
> >
> > The proposed fix, only addresses the case in 'i)', which
> > most likely won't solve problems reported in support
> > case. Take the following example: if the server starts up
> > successfully before the script that calculates purging cuts
> > then no left over binlog files will exist. However, if their
> > script runs before the server starts up successfully and
> > later executes a purge, then they can be in trouble).
> >
> >
> > 3. log_in_use removal
> >
> > I think you cannot replace log_in_use with is_active. If you
> > do so, you may run into some cases that you will be purging
> > logs that are actually in use. For example, take the case
> > that a user is issuing "SHOW BINLOG EVENTS IN
> > 'log-bin.000001'" and during this operation a PURGE is
> > issued concurrently. Please, revert that and check why the
> > log_in_use was actually not reporting correctly if a log
> > file was in use or not.
> >
> >
> I agree with you. This log_in_use simply does not work in the sense
> that it always return false no matter when and which files are open.
>
>
> > REQUESTS
> > --------
> >
> > 1. What is that change in the result file for the
> > rpl_ndb_row_001?
> >
> >
> > SUGGESTIONS
> > -----------
> >
> > 1. In the test files, please, avoid using --exec . You use it
> > while you are starting and stopping the server explicitly. I
> > suggest that you use the commands provided by mtr to make
> > test more robust and not hitting platform heterogeneity
> > issues. Something like:
> >
> >
> > --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
> > wait
> > EOF
> >
> >
> > ...
> >
> >
> > --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
> > restart
> > EOF
> >
> > Check mysql-test/suite/rpl/t/rpl_trigger.test for details.
> >
> > DETAILS
> > -------
> >
> > I'll wait for a newer patch addressing issue #2 as we discussed
> > over skype.
> >
> > On Sun, 2009-07-12 at 23:24 +0000, Alfranio Correia wrote:
> >
> >> #At
> file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-45292/mysql-5.1-bugteam/
> based on revid:joro@stripped
> >>
> >> 3013 Alfranio Correia 2009-07-13
> >> BUG#45292 orphan binary log created when starting server twice
> >>
> >> This patch fixes two bugs as follows. First, aborting the server while
> purging
> >> binary logs might generate orphan files due to how the purge operation
> was
> >> implemented:
> >>
> >> (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs)
> >>
> >> 1 - register the files to be removed in a temporary buffer.
> >> 2 - update the log-bin.index.
> >> 3 - flush the log-bin.index.
> >> 4 - erase the files whose names where register in the temporary
> buffer
> >> in step 1.
> >>
> >> Thus aborting a server while executing step 4 would generate an
> orphan file.
> >> To fix this issue, we record the files to be purged before removing
> them from
> >> the index file and from the file system. So if a failure happens such
> registers
> >> can be used to automatically remove dangling files. The new steps
> might be
> >> outlined as follows:
> >>
> >> (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs)
> >>
> >> 1 - register the files to be removed in a the log-bin.purge
> >> place in the data directory.
> >> 2 - update the log-bin.index.
> >> 3 - flush the log-bin.index.
> >> 4 - erase the files whose names where register in the log-bin.purge
> >> in step 1.
> >>
> >> (purge routine - sql/log.cc - MYSQL_BIN_LOG::open_index_file)
> >>
> >> 1 - open the log-bin.index.
> >> 2 - open the log-bin.purge.
> >> 3 - for each file in log-bin.purge
> >> 3.1 Check if file is in log-bin.index and if so ignored it.
> >> 3.2 Otherwise, delete it.
> >>
> >> Regarding the second issue. The purge operation was allowing to remove
> a file
> >> in use thus leading to the loss of data and possible inconsistencies
> between
> >> the master and slave. Roughly, there was a problem with the
> sql_repl.cc::bool
> >> log_in_use(), which was not correctly checking if a file was in use.
> To avoid
> >> this issue, we replaced the call to such function by a call to the
> method
> >> MYSQL_BIN_LOG::is_active() and remove the previous function as it was
> obsolete.
> >>
> >> modified:
> >> mysql-test/suite/binlog/r/binlog_index.result
> >> mysql-test/suite/binlog/t/binlog_index.test
> >> mysql-test/suite/rpl_ndb/r/rpl_ndb_row_001.result
> >> sql/log.cc
> >> sql/log.h
> >> sql/sql_repl.cc
> >> sql/sql_repl.h
> >> === modified file 'mysql-test/suite/binlog/r/binlog_index.result'
> >> --- a/mysql-test/suite/binlog/r/binlog_index.result 2009-01-23 12:22:05
> +0000
> >> +++ b/mysql-test/suite/binlog/r/binlog_index.result 2009-07-12 23:24:45
> +0000
> >> @@ -1,3 +1,4 @@
> >> +call mtr.add_suppression('Attempting backtrace');
> >> flush logs;
> >> flush logs;
> >> flush logs;
> >> @@ -37,4 +38,16 @@ Level Code Message
> >> Error 1377 a problem with deleting master-bin.000001; consider examining
> correspondence of your binlog index file to the actual binlog files
> >> Error 1377 Fatal error during log purge
> >> reset master;
> >> +flush logs;
> >> +SET SESSION debug="+d,crash_before_update_index";
> >> +purge binary logs TO 'master-bin.000002';
> >> +ERROR HY000: Lost connection to MySQL server during query
> >> +flush logs;
> >> +SET SESSION debug="+d,crash_non_critical_after_update_index";
> >> +purge binary logs TO 'master-bin.000004';
> >> +ERROR HY000: Lost connection to MySQL server during query
> >> +flush logs;
> >> +SET SESSION debug="+d,crash_critical_after_update_index";
> >> +purge binary logs TO 'master-bin.000006';
> >> +ERROR HY000: Lost connection to MySQL server during query
> >> End of tests
> >>
> >> === modified file 'mysql-test/suite/binlog/t/binlog_index.test'
> >> --- a/mysql-test/suite/binlog/t/binlog_index.test 2008-04-05 11:09:53 +0000
> >> +++ b/mysql-test/suite/binlog/t/binlog_index.test 2009-07-12 23:24:45 +0000
> >> @@ -3,6 +3,7 @@
> >> #
> >> source include/have_log_bin.inc;
> >> source include/not_embedded.inc;
> >> +call mtr.add_suppression('Attempting backtrace');
> >>
> >> #
> >> # testing purge binary logs TO
> >> @@ -66,4 +67,35 @@ rmdir $MYSQLD_DATADIR/master-bin.000001;
> >> --disable_warnings
> >> reset master;
> >> --enable_warnings
> >> +
> >> +flush logs;
> >> +
> >> +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
> >> +SET SESSION debug="+d,crash_before_update_index";
> >> +--error 2013
> >> +purge binary logs TO 'master-bin.000002';
> >> +
> >> +--enable_reconnect
> >> +--source include/wait_until_connected_again.inc
> >> +
> >> +flush logs;
> >> +
> >> +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
> >> +SET SESSION debug="+d,crash_non_critical_after_update_index";
> >> +--error 2013
> >> +purge binary logs TO 'master-bin.000004';
> >> +
> >> +--enable_reconnect
> >> +--source include/wait_until_connected_again.inc
> >> +
> >> +flush logs;
> >> +
> >> +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
> >> +SET SESSION debug="+d,crash_critical_after_update_index";
> >> +--error 2013
> >> +purge binary logs TO 'master-bin.000006';
> >> +
> >> +--enable_reconnect
> >> +--source include/wait_until_connected_again.inc
> >> +
> >> --echo End of tests
> >>
> >> === modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_row_001.result'
> >> --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_row_001.result 2007-12-19 08:42:31
> +0000
> >> +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_row_001.result 2009-07-12 23:24:45
> +0000
> >> @@ -42,6 +42,8 @@ COUNT(*)
> >> 5000
> >> LOCK TABLES t1 READ;
> >> START SLAVE;
> >> +Warnings:
> >> +Error 1100 Table 'ndb_binlog_index' was not locked with LOCK TABLES
> >> UNLOCK TABLES;
> >> SELECT COUNT(*) FROM t1;
> >> COUNT(*)
> >>
> >> === modified file 'sql/log.cc'
> >> --- a/sql/log.cc 2009-06-19 08:24:43 +0000
> >> +++ b/sql/log.cc 2009-07-12 23:24:45 +0000
> >> @@ -2388,8 +2388,9 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG()
> >> before main().
> >> */
> >> index_file_name[0] = 0;
> >> + purge_file_name[0] = 0;
> >> bzero((char*) &index_file, sizeof(index_file));
> >> - bzero((char*) &purge_temp, sizeof(purge_temp));
> >> + bzero((char*) &purge_file, sizeof(purge_file));
> >> }
> >>
> >> /* this is called only once */
> >> @@ -2469,10 +2470,20 @@ bool MYSQL_BIN_LOG::open_index_file(cons
> >> my_close(index_file_nr,MYF(0));
> >> return TRUE;
> >> }
> >> +
> >> + #ifdef HAVE_REPLICATION
> >> + /* Read each entry from purge_file and delete the file. */
> >> + if (open_purge_file(index_file_name_arg) || process_purge_file(NULL,
> NULL, TRUE))
> >> + {
> >> + sql_print_error("MYSQL_BIN_LOG::open_index_file to process cache to "
> >> + "purge logs.");
> >> + return TRUE;
> >> + }
> >> + #endif
> >> +
> >> return FALSE;
> >> }
> >>
> >> -
> >> /**
> >> Open a (new) binlog file.
> >>
> >> @@ -3134,28 +3145,12 @@ int MYSQL_BIN_LOG::purge_logs(const char
> >> goto err;
> >> }
> >>
> >> - /*
> >> - For crash recovery reasons the index needs to be updated before
> >> - any files are deleted. Move files to be deleted into a temp file
> >> - to be processed after the index is updated.
> >> - */
> >> - if (!my_b_inited(&purge_temp))
> >> + if ((error= open_purge_file(NULL)) ||
> >> + DBUG_EVALUATE_IF("fault_injection_open_info_purge", 1, 0))
> >> {
> >> - if ((error=open_cached_file(&purge_temp, mysql_tmpdir,
> TEMP_PREFIX,
> >> - DISK_BUFFER_SIZE, MYF(MY_WME))))
> >> - {
> >> - sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp");
> >> - goto err;
> >> - }
> >> - }
> >> - else
> >> - {
> >> - if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1)))
> >> - {
> >> - sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp "
> >> - "for write");
> >> - goto err;
> >> - }
> >> + sql_print_error("MSYQL_LOG::purge_logs failed to prepare cache to "
> >> + "purge logs.");
> >> + goto err;
> >> }
> >>
> >> /*
> >> @@ -3165,20 +3160,32 @@ int MYSQL_BIN_LOG::purge_logs(const char
> >> if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
> >> goto err;
> >> while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included))
> &&
> >> - !log_in_use(log_info.log_file_name))
> >> + !is_active(log_info.log_file_name))
> >> {
> >> - if ((error=my_b_write(&purge_temp, (const
> uchar*)log_info.log_file_name,
> >> + if ((error=my_b_write(&purge_file, (const
> uchar*)log_info.log_file_name,
> >> strlen(log_info.log_file_name))) ||
> >> - (error=my_b_write(&purge_temp, (const uchar*)"\n", 1)))
> >> + (error=my_b_write(&purge_file, (const uchar*)"\n", 1)))
> >> {
> >> - sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to
> purge_temp",
> >> + sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to
> purge_file",
> >> log_info.log_file_name);
> >> goto err;
> >> }
> >>
> >> if (find_next_log(&log_info, 0) || exit_loop)
> >> break;
> >> - }
> >> + }
> >> +
> >> + DBUG_EXECUTE_IF("crash_before_update_index", abort(););
> >> +
> >> + if ((error= flush_io_cache(&purge_file)) ||
> >> + (error= my_sync(purge_file.file, MYF(MY_WME))))
> >> + {
> >> + sql_print_error("MSYQL_LOG::purge_logs failed to flush cache to purge
> "
> >> + "logs.");
> >> + goto err;
> >> + }
> >> +
> >> + DBUG_EXECUTE_IF("crash_critical_after_update_index", abort(););
> >>
> >> /* We know how many files to delete. Update index file. */
> >> if ((error=update_log_index(&log_info, need_update_threads)))
> >> @@ -3187,29 +3194,93 @@ int MYSQL_BIN_LOG::purge_logs(const char
> >> goto err;
> >> }
> >>
> >> - DBUG_EXECUTE_IF("crash_after_update_index", abort(););
> >> + DBUG_EXECUTE_IF("crash_non_critical_after_update_index", abort(););
> >> +
> >> + /* Read each entry from purge_file and delete the file. */
> >> + if ((error= process_purge_file(thd, decrease_log_space, FALSE)))
> >> + {
> >> + sql_print_error("MSYQL_LOG::purge_logs failed to process cache to "
> >> + "purge logs.");
> >> + }
> >> +
> >> +err:
> >> + if (need_mutex)
> >> + pthread_mutex_unlock(&LOCK_index);
> >> + DBUG_RETURN(error);
> >> +}
> >> +
> >> + /*
> >> + For crash recovery reasons the index needs to be updated before
> >> + any files are deleted. Move files to be deleted into a temp file
> >> + to be processed after the index is updated.
> >> + */
> >> +int MYSQL_BIN_LOG::open_purge_file(const char *base_file_name)
> >> +{
> >> + int error= 0;
> >> + File file;
> >> +
> >> + DBUG_ENTER("MYSQL_BIN_LOG::open_info_purge");
> >> + if (!my_b_inited(&purge_file))
> >> + {
> >> + if (fn_format(purge_file_name, base_file_name, mysql_data_home,
> >> + ".purge", MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH |
> >> + MY_REPLACE_EXT)) == NULL ||
> >> + (file= my_open(purge_file_name, O_RDWR | O_CREAT | O_BINARY,
> >> + MYF(MY_WME | ME_WAITTANG))) < 0 ||
> >> + init_io_cache(&purge_file, file, IO_SIZE, READ_CACHE,
> >> + 0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)))
> >> + {
> >> + error= 1;
> >> + sql_print_error("MYSQL_LOG::open_info_purge failed to open
> purge_file.");
> >> + }
> >> + }
> >> + else
> >> + {
> >> + if ((error=reinit_io_cache(&purge_file, WRITE_CACHE, 0, 0, 1)))
> >> + {
> >> + error= 1;
> >> + sql_print_error("MYSQL_LOG::open_info_purge failed to reinit
> purge_file "
> >> + "for write.");
> >> + }
> >> + file= purge_file.file;
> >> + if (!error && (my_chsize(file, 0, '\n', MYF(MY_WME)) ||
> >> + my_sync(file, MYF(MY_WME))))
> >> + {
> >> + error= 1;
> >> + sql_print_error("MYSQL_LOG::open_info_purge failed to clean
> purge_file.");
> >> + }
> >> + }
> >> + DBUG_RETURN(error);
> >> +}
> >> +
> >> +int MYSQL_BIN_LOG::process_purge_file(THD *thd, ulonglong
> *decrease_log_space,
> >> + bool need_mutex)
> >> +{
> >> + int error= 0;
> >> + LOG_INFO log_info;
> >> + LOG_INFO check_log_info;
> >> +
> >> + DBUG_ENTER("MYSQL_BIN_LOG::process_purge_file");
> >>
> >> - /* Switch purge_temp for read. */
> >> - if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0)))
> >> + if ((error=reinit_io_cache(&purge_file, READ_CACHE, 0, 0, 0)))
> >> {
> >> - sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp "
> >> + sql_print_error("MSYQL_LOG::process_purge_file failed to reinit
> purge_file "
> >> "for read");
> >> goto err;
> >> }
> >>
> >> - /* Read each entry from purge_temp and delete the file. */
> >> for (;;)
> >> {
> >> uint length;
> >>
> >> - if ((length=my_b_gets(&purge_temp, log_info.log_file_name,
> >> + if ((length=my_b_gets(&purge_file, log_info.log_file_name,
> >> FN_REFLEN)) <= 1)
> >> {
> >> - if (purge_temp.error)
> >> + if (purge_file.error)
> >> {
> >> - error= purge_temp.error;
> >> - sql_print_error("MSYQL_LOG::purge_logs error %d reading from "
> >> - "purge_temp", error);
> >> + error= purge_file.error;
> >> + sql_print_error("MSYQL_LOG::process_purge_file error %d reading
> from "
> >> + "purge_file", error);
> >> goto err;
> >> }
> >>
> >> @@ -3270,64 +3341,63 @@ int MYSQL_BIN_LOG::purge_logs(const char
> >> }
> >> else
> >> {
> >> - DBUG_PRINT("info",("purging %s",log_info.log_file_name));
> >> - if (!my_delete(log_info.log_file_name, MYF(0)))
> >> - {
> >> - if (decrease_log_space)
> >> - *decrease_log_space-= s.st_size;
> >> - }
> >> - else
> >> + if (find_log_pos(&check_log_info, log_info.log_file_name,
> need_mutex))
> >> {
> >> - if (my_errno == ENOENT)
> >> + DBUG_PRINT("info",("purging %s",log_info.log_file_name));
> >> + if (!my_delete(log_info.log_file_name, MYF(0)))
> >> {
> >> - if (thd)
> >> - {
> >> - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> >> - ER_LOG_PURGE_NO_FILE,
> ER(ER_LOG_PURGE_NO_FILE),
> >> - log_info.log_file_name);
> >> - }
> >> - sql_print_information("Failed to delete file '%s'",
> >> - log_info.log_file_name);
> >> - my_errno= 0;
> >> + if (decrease_log_space)
> >> + *decrease_log_space-= s.st_size;
> >> }
> >> else
> >> {
> >> - if (thd)
> >> + if (my_errno == ENOENT)
> >> {
> >> - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
> >> - ER_BINLOG_PURGE_FATAL_ERR,
> >> - "a problem with deleting %s; "
> >> - "consider examining correspondence "
> >> - "of your binlog index file "
> >> - "to the actual binlog files",
> >> + if (thd)
> >> + {
> >> + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> >> + ER_LOG_PURGE_NO_FILE,
> ER(ER_LOG_PURGE_NO_FILE),
> >> + log_info.log_file_name);
> >> + }
> >> + sql_print_information("Failed to delete file '%s'",
> >> log_info.log_file_name);
> >> + my_errno= 0;
> >> }
> >> else
> >> {
> >> - sql_print_information("Failed to delete file '%s'; "
> >> + if (thd)
> >> + {
> >> + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
> >> + ER_BINLOG_PURGE_FATAL_ERR,
> >> + "a problem with deleting %s; "
> >> "consider examining correspondence "
> >> "of your binlog index file "
> >> "to the actual binlog files",
> >> log_info.log_file_name);
> >> - }
> >> - if (my_errno == EMFILE)
> >> - {
> >> - DBUG_PRINT("info",
> >> - ("my_errno: %d, set ret = LOG_INFO_EMFILE",
> my_errno));
> >> - error= LOG_INFO_EMFILE;
> >> + }
> >> + else
> >> + {
> >> + sql_print_information("Failed to delete file '%s'; "
> >> + "consider examining correspondence "
> >> + "of your binlog index file "
> >> + "to the actual binlog files",
> >> + log_info.log_file_name);
> >> + }
> >> + if (my_errno == EMFILE)
> >> + {
> >> + DBUG_PRINT("info",
> >> + ("my_errno: %d, set ret = LOG_INFO_EMFILE",
> my_errno));
> >> + error= LOG_INFO_EMFILE;
> >> + goto err;
> >> + }
> >> + error= LOG_INFO_FATAL;
> >> goto err;
> >> }
> >> - error= LOG_INFO_FATAL;
> >> - goto err;
> >> }
> >> }
> >> }
> >> }
> >> -
> >> err:
> >> - close_cached_file(&purge_temp);
> >> - if (need_mutex)
> >> - pthread_mutex_unlock(&LOCK_index);
> >> DBUG_RETURN(error);
> >> }
> >>
> >> @@ -3367,7 +3437,7 @@ int MYSQL_BIN_LOG::purge_logs_before_dat
> >> goto err;
> >>
> >> while (strcmp(log_file_name, log_info.log_file_name) &&
> >> - !log_in_use(log_info.log_file_name))
> >> + !is_active(log_info.log_file_name))
> >> {
> >> if (!my_stat(log_info.log_file_name, &stat_area, MYF(0)))
> >> {
> >> @@ -4663,6 +4733,13 @@ void MYSQL_BIN_LOG::close(uint exiting)
> >> write_error= 1;
> >> sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno);
> >> }
> >> +
> >> + end_io_cache(&purge_file);
> >> + if (my_close(purge_file.file, MYF(0)) < 0 && ! write_error)
> >> + {
> >> + write_error= 1;
> >> + sql_print_error(ER(ER_ERROR_ON_WRITE), purge_file_name, errno);
> >> + }
> >> }
> >> log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED :
> LOG_CLOSED;
> >> safeFree(name);
> >>
> >> === modified file 'sql/log.h'
> >> --- a/sql/log.h 2009-06-18 13:52:46 +0000
> >> +++ b/sql/log.h 2009-07-12 23:24:45 +0000
> >> @@ -234,13 +234,14 @@ class MYSQL_BIN_LOG: public TC_LOG, priv
> >> ulonglong bytes_written;
> >> IO_CACHE index_file;
> >> /*
> >> - purge_temp is a temp file used in purge_logs so that the index file
> >> + purge_file is a temp file used in purge_logs so that the index file
> >> can be updated before deleting files from disk, yielding better crash
> >> recovery. It is created on demand the first time purge_logs is called
> >> and then reused for subsequent calls. It is cleaned up in cleanup().
> >> */
> >> - IO_CACHE purge_temp;
> >> + IO_CACHE purge_file;
> >> char index_file_name[FN_REFLEN];
> >> + char purge_file_name[FN_REFLEN];
> >> /*
> >> The max size before rotation (usable only if log_type == LOG_BIN:
> binary
> >> logs and relay logs).
> >> @@ -384,6 +385,9 @@ public:
> >> ulonglong *decrease_log_space);
> >> int purge_logs_before_date(time_t purge_time);
> >> int purge_first_log(Relay_log_info* rli, bool included);
> >> + int open_purge_file(const char *base_file_name);
> >> + int process_purge_file(THD *thd, ulonglong *decrease_log_space,
> >> + bool mutex);
> >> bool reset_logs(THD* thd);
> >> void close(uint exiting);
> >>
> >>
> >> === modified file 'sql/sql_repl.cc'
> >> --- a/sql/sql_repl.cc 2009-06-29 14:00:47 +0000
> >> +++ b/sql/sql_repl.cc 2009-07-12 23:24:45 +0000
> >> @@ -202,34 +202,6 @@ void adjust_linfo_offsets(my_off_t purge
> >> pthread_mutex_unlock(&LOCK_thread_count);
> >> }
> >>
> >> -
> >> -bool log_in_use(const char* log_name)
> >> -{
> >> - size_t log_name_len = strlen(log_name) + 1;
> >> - THD *tmp;
> >> - bool result = 0;
> >> -
> >> - pthread_mutex_lock(&LOCK_thread_count);
> >> - I_List_iterator<THD> it(threads);
> >> -
> >> - while ((tmp=it++))
> >> - {
> >> - LOG_INFO* linfo;
> >> - if ((linfo = tmp->current_linfo))
> >> - {
> >> - pthread_mutex_lock(&linfo->lock);
> >> - result = !bcmp((uchar*) log_name, (uchar*) linfo->log_file_name,
> >> - log_name_len);
> >> - pthread_mutex_unlock(&linfo->lock);
> >> - if (result)
> >> - break;
> >> - }
> >> - }
> >> -
> >> - pthread_mutex_unlock(&LOCK_thread_count);
> >> - return result;
> >> -}
> >> -
> >> bool purge_error_message(THD* thd, int res)
> >> {
> >> uint errmsg= 0;
> >>
> >> === modified file 'sql/sql_repl.h'
> >> --- a/sql/sql_repl.h 2008-03-14 17:38:54 +0000
> >> +++ b/sql/sql_repl.h 2009-07-12 23:24:45 +0000
> >> @@ -46,7 +46,6 @@ int reset_slave(THD *thd, Master_info* m
> >> int reset_master(THD* thd);
> >> bool purge_master_logs(THD* thd, const char* to_log);
> >> bool purge_master_logs_before_date(THD* thd, time_t purge_time);
> >> -bool log_in_use(const char* log_name);
> >> void adjust_linfo_offsets(my_off_t purge_offset);
> >> bool show_binlogs(THD* thd);
> >> extern int init_master_info(Master_info* mi);
> >>
> >>
>
>
--
Luís