List:Commits« Previous MessageNext Message »
From:Andrei Elkin Date:April 20 2009 12:16pm
Subject:bzr commit into mysql-6.0-rpl branch (aelkin:2840) Bug#41902
View as plain text  
#At file:///home/andrei/MySQL/BZR/FIXES/6.0-rpl-bug41902-reset_logs_no_my_error_2_assert/ based on revid:alfranio.correia@stripped

 2840 Andrei Elkin	2009-04-20
      Bug#41902  MYSQL_BIN_LOG::reset_logs() doesn't call my_error() in face of an error
      
      The assert happened because thd->stmt_da->status() reacted on the
      fact of a gained error in reset_logs() which was not prepared and therefore
      sent but still the fact of the error was propagated upwards to callers.
      
      Fixed with deploying a part the former purge_error_message() in the reported error
      branch of reset_logs(). A user level error gets prepared for reporting via my_message().
            
      Side effects: Bug#44179 appears be fixed with the current patch, at least in 6.0.
added:
  mysql-test/suite/rpl/r/rpl_bug41902.result
  mysql-test/suite/rpl/t/rpl_bug41902-slave.opt
  mysql-test/suite/rpl/t/rpl_bug41902.test
modified:
  sql/log.cc
  sql/log.h
  sql/sql_repl.cc

per-file messages:
  mysql-test/suite/rpl/r/rpl_bug41902.result
     a new results file for Bug#41902.
  mysql-test/suite/rpl/t/rpl_bug41902-slave.opt
    The opt is added to avoid using the server after performing error simulation
    as a precaution from  Bug #44181 and possible others.
  mysql-test/suite/rpl/t/rpl_bug41902.test
    Regression tests for bug#41902. 
    Bug #44181 forces to add the first of +change master to master_host='dummy' lines.
  sql/log.cc
    a new purge_log_get_error_code() is factored out of purge_error_message()
    to be called without necessary my_error or my_ok to follow;
    MYSQL_BIN_LOG::find_log_pos() simulates LOG_INFO_EOF purge error;
    MYSQL_BIN_LOG::reset_logs() calls  my_message(err_code,...) - the central matter of
    the bug fix;
    MYSQL_BIN_LOG::reset_logs() restores  name= save_name in the error branches. That
    happens to be a separate issue not letting to re-issue RESET SLAVE once again after the
    failing invocation of the sql command.
  sql/log.h
    Exporting the new purge_log_get_error_code() interface
    for purge_error_message() the "parent" code.
  sql/sql_repl.cc
    separating purge_log_get_error_code() out of purge_error_message();
    renfining reset_slave() to set sql_errno= ER_RELAY_LOG_FAIL
    when purge_relay_logs() fails - that's Bug#44179 fixing.
=== added file 'mysql-test/suite/rpl/r/rpl_bug41902.result'
--- a/mysql-test/suite/rpl/r/rpl_bug41902.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_bug41902.result	2009-04-20 12:16:34 +0000
@@ -0,0 +1,34 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+stop slave;
+SET @@debug="d,simulate_find_log_pos_error";
+reset slave;
+ERROR HY000: Target log not found in binlog index
+show warnings;
+Level	Code	Message
+Error	1373	Target log not found in binlog index
+Error	1371	Failed purging old relay logs: Failed during log reset
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+SET @@debug="d,simulate_find_log_pos_error";
+change master to master_host='dummy';
+ERROR HY000: Target log not found in binlog index
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+SET @@debug="d,simulate_find_log_pos_error";
+reset master;
+ERROR HY000: Target log not found in binlog index
+SET @@debug="";
+reset master;
+SET @@debug="d,simulate_find_log_pos_error";
+purge binary logs to 'master-bin.000001';
+ERROR HY000: Target log not found in binlog index
+SET @@debug="";
+purge binary logs to 'master-bin.000001';
+End of the tests

=== added file 'mysql-test/suite/rpl/t/rpl_bug41902-slave.opt'
--- a/mysql-test/suite/rpl/t/rpl_bug41902-slave.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_bug41902-slave.opt	2009-04-20 12:16:34 +0000
@@ -0,0 +1 @@
+--loose-debug=-d,simulate_find_log_pos_error

=== added file 'mysql-test/suite/rpl/t/rpl_bug41902.test'
--- a/mysql-test/suite/rpl/t/rpl_bug41902.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_bug41902.test	2009-04-20 12:16:34 +0000
@@ -0,0 +1,53 @@
+# Test for Bug #41902 MYSQL_BIN_LOG::reset_logs() doesn't call my_error()
+#                     in face of an error
+#
+
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+#
+# test checks that 
+# a. there is no crash when find_log_pos() returns with an error
+#    that tests expect to receive;
+# b. in the case of multiple error messages the first error message is 
+#    reported to the user and others are available as warnings.
+#
+
+connection slave;
+stop slave;
+
+SET @@debug="d,simulate_find_log_pos_error";
+
+--error ER_UNKNOWN_TARGET_BINLOG
+reset slave;
+show warnings;
+
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+
+SET @@debug="d,simulate_find_log_pos_error";
+
+--error ER_UNKNOWN_TARGET_BINLOG
+change master to master_host='dummy';
+
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+
+connection master;
+SET @@debug="d,simulate_find_log_pos_error";
+--error ER_UNKNOWN_TARGET_BINLOG
+reset master;
+
+SET @@debug="";
+reset master;
+
+SET @@debug="d,simulate_find_log_pos_error";
+--error ER_UNKNOWN_TARGET_BINLOG
+purge binary logs to 'master-bin.000001';
+
+SET @@debug="";
+purge binary logs to 'master-bin.000001';
+
+--echo End of the tests

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2009-04-02 16:14:14 +0000
+++ b/sql/log.cc	2009-04-20 12:16:34 +0000
@@ -66,6 +66,35 @@ static int binlog_rollback(handlerton *h
 static int binlog_prepare(handlerton *hton, THD *thd, bool all);
 
 /**
+   purge logs, master and slave sides both, related error code
+   convertor.
+   Called from @c purge_error_message(), @c MYSQL_BIN_LOG::reset_logs()
+
+   @param  res  an internal to purging routines error code 
+
+   @return the user level error code ER_*
+*/
+uint purge_log_get_error_code(int res)
+{
+  uint errcode= 0;
+
+  switch (res)  {
+  case 0: break;
+  case LOG_INFO_EOF:	errcode= ER_UNKNOWN_TARGET_BINLOG; break;
+  case LOG_INFO_IO:	errcode= ER_IO_ERR_LOG_INDEX_READ; break;
+  case LOG_INFO_INVALID:errcode= ER_BINLOG_PURGE_PROHIBITED; break;
+  case LOG_INFO_SEEK:	errcode= ER_FSEEK_FAIL; break;
+  case LOG_INFO_MEM:	errcode= ER_OUT_OF_RESOURCES; break;
+  case LOG_INFO_FATAL:	errcode= ER_BINLOG_PURGE_FATAL_ERR; break;
+  case LOG_INFO_IN_USE: errcode= ER_LOG_IN_USE; break;
+  case LOG_INFO_EMFILE: errcode= ER_BINLOG_PURGE_EMFILE; break;
+  default:		errcode= ER_LOG_PURGE_UNKNOWN_ERR; break;
+  }
+
+  return errcode;
+}
+
+/**
   Silence all errors and warnings reported when performing a write
   to a log table.
   Errors and warnings are not reported to the client or SQL exception
@@ -4501,8 +4530,10 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO
   {
     uint length;
     my_off_t offset= my_b_tell(&index_file);
-    /* If we get 0 or 1 characters, this is the end of the file */
 
+    DBUG_EXECUTE_IF("simulate_find_log_pos_error",
+                    error=  LOG_INFO_EOF; break;);
+    /* If we get 0 or 1 characters, this is the end of the file */
     if ((length= my_b_gets(&index_file, fname, FN_REFLEN)) <= 1)
     {
       /* Did not find the given entry; Return not found or error */
@@ -4604,6 +4635,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
 {
   LOG_INFO linfo;
   bool error=0;
+  int err;
   const char* save_name;
   DBUG_ENTER("reset_logs");
 
@@ -4634,9 +4666,12 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
 
   /* First delete all old log files */
 
-  if (find_log_pos(&linfo, NullS, 0))
+  if ((err= find_log_pos(&linfo, NullS, 0)) != 0)
   {
-    error=1;
+    uint errcode= purge_log_get_error_code(err);
+    sql_print_error("Failed to locate old binlog or relay log files");
+    my_message(errcode, ER(errcode), MYF(0));
+    error= 1;
     goto err;
   }
 
@@ -4705,6 +4740,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
   my_free((uchar*) save_name, MYF(0));
 
 err:
+  if (error == 1)
+    name= const_cast<char*>(save_name);
   pthread_mutex_unlock(&LOCK_thread_count);
   pthread_mutex_unlock(&LOCK_index);
   pthread_mutex_unlock(&LOCK_log);

=== modified file 'sql/log.h'
--- a/sql/log.h	2009-01-26 16:32:29 +0000
+++ b/sql/log.h	2009-04-20 12:16:34 +0000
@@ -813,4 +813,6 @@ enum enum_binlog_format {
 };
 extern TYPELIB binlog_format_typelib;
 
+uint purge_log_get_error_code(int res);
+
 #endif /* LOG_H */

=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc	2009-04-02 16:14:14 +0000
+++ b/sql/sql_repl.cc	2009-04-20 12:16:34 +0000
@@ -235,24 +235,11 @@ bool log_in_use(const char* log_name)
 
 bool purge_error_message(THD* thd, int res)
 {
-  uint errmsg= 0;
+  uint errcode;
 
-  switch (res)  {
-  case 0: break;
-  case LOG_INFO_EOF:	errmsg= ER_UNKNOWN_TARGET_BINLOG; break;
-  case LOG_INFO_IO:	errmsg= ER_IO_ERR_LOG_INDEX_READ; break;
-  case LOG_INFO_INVALID:errmsg= ER_BINLOG_PURGE_PROHIBITED; break;
-  case LOG_INFO_SEEK:	errmsg= ER_FSEEK_FAIL; break;
-  case LOG_INFO_MEM:	errmsg= ER_OUT_OF_RESOURCES; break;
-  case LOG_INFO_FATAL:	errmsg= ER_BINLOG_PURGE_FATAL_ERR; break;
-  case LOG_INFO_IN_USE: errmsg= ER_LOG_IN_USE; break;
-  case LOG_INFO_EMFILE: errmsg= ER_BINLOG_PURGE_EMFILE; break;
-  default:		errmsg= ER_LOG_PURGE_UNKNOWN_ERR; break;
-  }
-
-  if (errmsg)
+  if ((errcode= purge_log_get_error_code(res)) != 0)
   {
-    my_message(errmsg, ER(errmsg), MYF(0));
+    my_message(errcode, ER(errcode), MYF(0));
     return TRUE;
   }
   my_ok(thd);
@@ -1295,7 +1282,10 @@ int reset_slave(THD *thd, Master_info* m
   if ((error= purge_relay_logs(mi->rli, thd,
 			       1 /* just reset */,
 			       &errmsg)))
+  {
+    sql_errno= ER_RELAY_LOG_FAIL;
     goto err;
+  }
 
   /* Clear master's log coordinates */
   init_master_log_pos(mi);

Thread
bzr commit into mysql-6.0-rpl branch (aelkin:2840) Bug#41902Andrei Elkin20 Apr
  • Re: bzr commit into mysql-6.0-rpl branch (aelkin:2840) Bug#41902Alfranio Correia21 Apr