List:Commits« Previous MessageNext Message »
From:Luis Soares Date:December 16 2010 9:01pm
Subject:bzr push into mysql-5.5-bugteam branch (luis.soares:3204 to 3206)
View as plain text  
 3206 Luis Soares	2010-12-16 [merge]
      empty merge from mysql-5.1-bugteam.

 3205 Luis Soares	2010-12-16 [merge]
      BUG#46166
      
      Merging to latest mysql-5.5-bugteam.

    added:
      mysql-test/include/io_thd_fault_injection.inc
      mysql-test/suite/rpl/r/rpl_binlog_errors.result
      mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt
      mysql-test/suite/rpl/t/rpl_binlog_errors.test
    modified:
      mysql-test/include/restart_mysqld.inc
      mysql-test/suite/binlog/r/binlog_index.result
      mysql-test/suite/binlog/r/binlog_max_extension.result
      mysql-test/suite/binlog/t/binlog_index.test
      mysql-test/suite/binlog/t/binlog_max_extension.test
      sql/handler.cc
      sql/log.cc
      sql/log.h
      sql/mysqld.cc
      sql/rpl_injector.cc
      sql/slave.cc
      sql/slave.h
      sql/sql_load.cc
      sql/sql_parse.cc
      sql/sql_reload.cc
      sql/sql_reload.h
      sql/sql_repl.cc
 3204 Alexander Nozdrin	2010-12-16 [merge]
      Manual merge from mysql-5.5.

    added:
      mysql-test/suite/innodb/r/innodb_bug56947.result
      mysql-test/suite/innodb/t/innodb_bug56947.test
    modified:
      .bzrignore
      README
      VERSION
      cmake/install_layout.cmake
      mysql-test/collections/default.experimental
      mysql-test/mysql-test-run.pl
      mysql-test/r/ctype_latin1.result
      mysql-test/r/ctype_ujis.result
      mysql-test/r/ctype_utf16.result
      mysql-test/r/ctype_utf8.result
      mysql-test/r/date_formats.result
      mysql-test/r/func_misc.result
      mysql-test/r/lock_sync.result
      mysql-test/r/mysqltest.result
      mysql-test/r/partition_innodb_plugin.result
      mysql-test/r/sp-destruct.result
      mysql-test/r/truncate_coverage.result
      mysql-test/r/type_date.result
      mysql-test/r/xml.result
      mysql-test/suite/binlog/t/disabled.def
      mysql-test/t/ctype_latin1.test
      mysql-test/t/ctype_ujis.test
      mysql-test/t/ctype_utf8.test
      mysql-test/t/date_formats.test
      mysql-test/t/fulltext.test
      mysql-test/t/func_misc.test
      mysql-test/t/lock_sync.test
      mysql-test/t/mysqltest.test
      mysql-test/t/partition_innodb_plugin.test
      mysql-test/t/sp-destruct.test
      mysql-test/t/truncate_coverage.test
      mysql-test/t/type_date.test
      mysql-test/t/xml.test
      packaging/WiX/CMakeLists.txt
      sql-common/my_time.c
      sql/item.cc
      sql/item.h
      sql/item_cmpfunc.cc
      sql/item_strfunc.cc
      sql/item_timefunc.cc
      sql/item_xmlfunc.cc
      sql/key.cc
      sql/sp.cc
      sql/sp_head.cc
      sql/sql_parse.cc
      sql/sql_show.cc
      sql/sql_truncate.cc
      strings/ctype-ucs2.c
      strings/ctype-utf8.c
      support-files/mysql.spec.sh
=== added file 'mysql-test/include/io_thd_fault_injection.inc'
--- a/mysql-test/include/io_thd_fault_injection.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/io_thd_fault_injection.inc	2010-11-30 23:32:51 +0000
@@ -0,0 +1,21 @@
+#
+#  Takes the flag as an argument:
+#  -- let $io_thd_injection_fault_flag=+d,fault_injection_new_file_rotate_event
+#  -- source include/io_thd_fault_injection.inc
+#
+
+SET @old_debug=@@global.debug;
+-- disable_warnings
+-- source include/stop_slave.inc 
+-- enable_warnings
+-- eval SET GLOBAL debug="+d,$io_thd_injection_fault_flag"
+
+START SLAVE io_thread;
+-- source include/wait_for_slave_io_to_stop.inc
+-- source include/wait_for_slave_io_error.inc
+
+-- eval SET GLOBAL debug="-d,$io_thd_injection_fault_flag"
+SET GLOBAL debug=@old_debug;
+
+# restart because slave is in bad shape
+-- source include/restart_mysqld.inc

=== modified file 'mysql-test/include/restart_mysqld.inc'
--- a/mysql-test/include/restart_mysqld.inc	2010-11-26 12:59:39 +0000
+++ b/mysql-test/include/restart_mysqld.inc	2010-11-30 23:32:51 +0000
@@ -1,14 +1,16 @@
 
 # Write file to make mysql-test-run.pl expect the "crash", but don't start
 # it until it's told to
---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--let $_server_id= `SELECT @@server_id`
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
+--exec echo "wait" > $_expect_file_name
 
 # Send shutdown to the connected server and give
 # it 10 seconds to die before zapping it
 shutdown_server 10;
 
 # Write file to make mysql-test-run.pl start up the server again
---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--exec echo "restart" > $_expect_file_name
 
 # Turn on reconnect
 --enable_reconnect

=== modified file 'mysql-test/suite/binlog/r/binlog_index.result'
--- a/mysql-test/suite/binlog/r/binlog_index.result	2009-12-17 17:10:18 +0000
+++ b/mysql-test/suite/binlog/r/binlog_index.result	2010-12-07 16:11:13 +0000
@@ -2,7 +2,9 @@ call mtr.add_suppression('Attempting bac
 call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.');
 call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
 call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
+call mtr.add_suppression('Could not open .*');
 call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+RESET MASTER;
 flush logs;
 flush logs;
 flush logs;
@@ -116,11 +118,31 @@ master-bin.000011
 # This should put the server in unsafe state and stop
 # accepting any command. If we inject a fault at this
 # point and continue the execution the server crashes.
-# Besides the flush command does not report an error.
 #
+SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
+SELECT @index;
+@index
+master-bin.000006
+master-bin.000007
+master-bin.000008
+master-bin.000009
+master-bin.000010
+master-bin.000011
+
 # fault_injection_registering_index
 SET SESSION debug="+d,fault_injection_registering_index";
 flush logs;
+ERROR HY000: Can't open file: './master-bin.000012' (errno: 1)
+SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
+SELECT @index;
+@index
+master-bin.000006
+master-bin.000007
+master-bin.000008
+master-bin.000009
+master-bin.000010
+master-bin.000011
+
 SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
 SELECT @index;
 @index
@@ -135,6 +157,18 @@ master-bin.000012
 # fault_injection_updating_index
 SET SESSION debug="+d,fault_injection_updating_index";
 flush logs;
+ERROR HY000: Can't open file: './master-bin.000013' (errno: 1)
+SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
+SELECT @index;
+@index
+master-bin.000006
+master-bin.000007
+master-bin.000008
+master-bin.000009
+master-bin.000010
+master-bin.000011
+master-bin.000012
+
 SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
 SELECT @index;
 @index

=== modified file 'mysql-test/suite/binlog/r/binlog_max_extension.result'
--- a/mysql-test/suite/binlog/r/binlog_max_extension.result	2009-11-22 03:59:48 +0000
+++ b/mysql-test/suite/binlog/r/binlog_max_extension.result	2010-12-07 16:55:25 +0000
@@ -3,6 +3,5 @@ call mtr.add_suppression("Log filename e
 call mtr.add_suppression("Can't generate a unique log-filename");
 RESET MASTER;
 FLUSH LOGS;
-Warnings:
-Warning	1098	Can't generate a unique log-filename master-bin.(1-999)
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
 

=== modified file 'mysql-test/suite/binlog/t/binlog_index.test'
--- a/mysql-test/suite/binlog/t/binlog_index.test	2009-12-08 16:03:19 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index.test	2010-11-30 23:32:51 +0000
@@ -10,9 +10,12 @@ call mtr.add_suppression('Attempting bac
 call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.');
 call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
 call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
+call mtr.add_suppression('Could not open .*');
 call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
 let $old=`select @@debug`;
 
+RESET MASTER;
+
 let $MYSQLD_DATADIR= `select @@datadir`;
 let $INDEX=$MYSQLD_DATADIR/master-bin.index;
 
@@ -205,12 +208,25 @@ SELECT @index;
 --echo # This should put the server in unsafe state and stop
 --echo # accepting any command. If we inject a fault at this
 --echo # point and continue the execution the server crashes.
---echo # Besides the flush command does not report an error.
 --echo #
 
+--chmod 0644 $INDEX
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
 --echo # fault_injection_registering_index
 SET SESSION debug="+d,fault_injection_registering_index";
+-- error ER_CANT_OPEN_FILE
 flush logs;
+
+--chmod 0644 $INDEX
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
 --source include/restart_mysqld.inc
 
 --chmod 0644 $INDEX
@@ -221,7 +237,15 @@ SELECT @index;
 
 --echo # fault_injection_updating_index
 SET SESSION debug="+d,fault_injection_updating_index";
+-- error ER_CANT_OPEN_FILE
 flush logs;
+
+--chmod 0644 $INDEX
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
 --source include/restart_mysqld.inc
 
 --chmod 0644 $INDEX

=== modified file 'mysql-test/suite/binlog/t/binlog_max_extension.test'
--- a/mysql-test/suite/binlog/t/binlog_max_extension.test	2010-11-26 13:30:22 +0000
+++ b/mysql-test/suite/binlog/t/binlog_max_extension.test	2010-12-07 16:55:25 +0000
@@ -58,7 +58,8 @@ EOF
 # Assertion
 ###########
 
-# assertion: should throw warning
+# assertion: should raise error
+-- error ER_NO_UNIQUE_LOGFILE
 FLUSH LOGS;
 
 ##############

=== added file 'mysql-test/suite/rpl/r/rpl_binlog_errors.result'
--- a/mysql-test/suite/rpl/r/rpl_binlog_errors.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_binlog_errors.result	2010-11-30 23:32:51 +0000
@@ -0,0 +1,274 @@
+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;
+#######################################################################
+####################### PART 1: MASTER TESTS ##########################
+#######################################################################
+include/stop_slave.inc
+call mtr.add_suppression("Can't generate a unique log-filename");
+call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
+call mtr.add_suppression("Error writing file .*");
+SET @old_debug= @@global.debug;
+SELECT repeat('x',8192) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data';
+SELECT repeat('x',10) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data';
+RESET MASTER;
+###################### TEST #1
+FLUSH LOGS;
+# assert: must show two binlogs
+show binary logs;
+Log_name	File_size
+master-bin.000001	#
+master-bin.000002	#
+###################### TEST #2
+RESET MASTER;
+SET GLOBAL debug="+d,error_unique_log_filename";
+FLUSH LOGS;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+# assert: must show one binlog
+show binary logs;
+Log_name	File_size
+master-bin.000001	#
+SET GLOBAL debug="";
+RESET MASTER;
+###################### TEST #3
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a TEXT) Engine=InnoDB;
+CREATE TABLE t4 (a TEXT);
+INSERT INTO t1 VALUES (1);
+RESET MASTER;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
+# assert: must show two binlog
+show binary logs;
+Log_name	File_size
+master-bin.000001	#
+master-bin.000002	#
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+###################### TEST #4
+SET GLOBAL debug="+d,error_unique_log_filename";
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+# assert: must show one entry
+SELECT count(*) FROM t2;
+count(*)
+1
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+###################### TEST #5
+SET GLOBAL debug="+d,error_unique_log_filename";
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data' INTO TABLE t2;
+# assert: must show one entry
+SELECT count(*) FROM t2;
+count(*)
+1
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+###################### TEST #6
+SET GLOBAL debug="+d,error_unique_log_filename";
+SET AUTOCOMMIT=0;
+INSERT INTO t2 VALUES ('muse');
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
+INSERT INTO t2 VALUES ('muse');
+COMMIT;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+# assert: must show three entries
+SELECT count(*) FROM t2;
+count(*)
+3
+SET AUTOCOMMIT= 1;
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+###################### TEST #7
+SET GLOBAL debug="+d,error_unique_log_filename";
+SELECT count(*) FROM t4;
+count(*)
+0
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t4;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+# assert: must show 1 entry
+SELECT count(*) FROM t4;
+count(*)
+1
+### check that the incident event is written to the current log
+SET GLOBAL debug="-d,error_unique_log_filename";
+FLUSH LOGS;
+SHOW BINLOG EVENTS IN 'BINLOG_FILE' FROM <binlog_start> LIMIT 1;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+BINLOG_FILE	#	Incident	#	#	#1 (LOST_EVENTS)
+DELETE FROM t4;
+RESET MASTER;
+###################### TEST #8
+SET GLOBAL debug="+d,error_unique_log_filename";
+# must show 0 entries
+SELECT count(*) FROM t4;
+count(*)
+0
+SELECT count(*) FROM t2;
+count(*)
+0
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t4;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc');
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+# INFO: Count(*) Before Offending DELETEs
+# assert: must show 1 entry
+SELECT count(*) FROM t4;
+count(*)
+1
+# assert: must show 4 entries
+SELECT count(*) FROM t2;
+count(*)
+4
+DELETE FROM t4;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+DELETE FROM t2;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+# INFO: Count(*) After Offending DELETEs
+# assert: must show zero entries
+SELECT count(*) FROM t4;
+count(*)
+0
+SELECT count(*) FROM t2;
+count(*)
+0
+SET GLOBAL debug="-d,error_unique_log_filename";
+###################### TEST #9
+SET GLOBAL debug="+d,error_unique_log_filename";
+SET SQL_LOG_BIN=0;
+INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc'), ('ddd');
+INSERT INTO t4 VALUES ('eee'), ('fff'), ('ggg'), ('hhh');
+# assert: must show four entries
+SELECT count(*) FROM t2;
+count(*)
+4
+SELECT count(*) FROM t4;
+count(*)
+4
+DELETE FROM t2;
+DELETE FROM t4;
+# assert: must show zero entries
+SELECT count(*) FROM t2;
+count(*)
+0
+SELECT count(*) FROM t4;
+count(*)
+0
+SET SQL_LOG_BIN=1;
+SET GLOBAL debug="-d,error_unique_log_filename";
+###################### TEST #10
+call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file.");
+call mtr.add_suppression("Could not open .*");
+RESET MASTER;
+SHOW WARNINGS;
+Level	Code	Message
+SET GLOBAL debug="+d,fault_injection_registering_index";
+FLUSH LOGS;
+ERROR HY000: Can't open file: './master-bin.000002' (errno: 1)
+SET GLOBAL debug="-d,fault_injection_registering_index";
+SHOW BINARY LOGS;
+ERROR HY000: You are not using binary logging
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+###################### TEST #11
+SET GLOBAL debug="+d,fault_injection_openning_index";
+FLUSH LOGS;
+ERROR HY000: Can't open file: './master-bin.index' (errno: 1)
+SET GLOBAL debug="-d,fault_injection_openning_index";
+RESET MASTER;
+ERROR HY000: Binlog closed, cannot RESET MASTER
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+###################### TEST #12
+SET GLOBAL debug="+d,fault_injection_new_file_rotate_event";
+FLUSH LOGS;
+ERROR HY000: Can't open file: 'master-bin' (errno: 0)
+SET GLOBAL debug="-d,fault_injection_new_file_rotate_event";
+RESET MASTER;
+ERROR HY000: Binlog closed, cannot RESET MASTER
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+SET GLOBAL debug= @old_debug;
+DROP TABLE t1, t2, t4;
+RESET MASTER;
+include/start_slave.inc
+#######################################################################
+####################### PART 2: SLAVE TESTS ###########################
+#######################################################################
+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;
+call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*");
+call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not open .*");
+call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file.");
+call mtr.add_suppression("Can't generate a unique log-filename .*");
+###################### TEST #13
+SET @old_debug=@@global.debug;
+include/stop_slave.inc
+SET GLOBAL debug="+d,error_unique_log_filename";
+START SLAVE io_thread;
+Last_IO_Error = Relay log write failure: could not queue event from master
+SET GLOBAL debug="-d,error_unique_log_filename";
+SET GLOBAL debug=@old_debug;
+###################### TEST #14
+SET @old_debug=@@global.debug;
+include/stop_slave.inc
+SET GLOBAL debug="+d,fault_injection_new_file_rotate_event";
+START SLAVE io_thread;
+Last_IO_Error = Relay log write failure: could not queue event from master
+SET GLOBAL debug="-d,fault_injection_new_file_rotate_event";
+SET GLOBAL debug=@old_debug;
+###################### TEST #15
+SET @old_debug=@@global.debug;
+include/stop_slave.inc
+SET GLOBAL debug="+d,fault_injection_registering_index";
+START SLAVE io_thread;
+Last_IO_Error = Relay log write failure: could not queue event from master
+SET GLOBAL debug="-d,fault_injection_registering_index";
+SET GLOBAL debug=@old_debug;
+###################### TEST #16
+SET @old_debug=@@global.debug;
+include/stop_slave.inc
+SET GLOBAL debug="+d,fault_injection_openning_index";
+START SLAVE io_thread;
+Last_IO_Error = Relay log write failure: could not queue event from master
+SET GLOBAL debug="-d,fault_injection_openning_index";
+SET GLOBAL debug=@old_debug;
+include/stop_slave.inc
+SET GLOBAL debug=@old_debug;
+RESET SLAVE;
+RESET MASTER;
+include/start_slave.inc

=== added file 'mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt'
--- a/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt	2010-11-30 23:32:51 +0000
@@ -0,0 +1 @@
+--max_binlog_size=4096

=== added file 'mysql-test/suite/rpl/t/rpl_binlog_errors.test'
--- a/mysql-test/suite/rpl/t/rpl_binlog_errors.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_binlog_errors.test	2010-11-30 23:32:51 +0000
@@ -0,0 +1,413 @@
+# BUG#46166: MYSQL_BIN_LOG::new_file_impl is not propagating error
+#            when generating new name.
+#  
+# WHY
+# ===
+#
+# We want to check whether error is reported or not when
+# new_file_impl fails (this may happen when rotation is not
+# possible because there is some problem finding an 
+# unique filename).
+#
+# HOW
+# ===
+# 
+# Test cases are documented inline.
+
+-- source include/master-slave.inc
+-- source include/have_innodb.inc
+-- source include/have_debug.inc
+
+-- echo #######################################################################
+-- echo ####################### PART 1: MASTER TESTS ##########################
+-- echo #######################################################################
+
+
+### ACTION: stopping slave as it is not needed for the first part of
+###         the test
+
+-- connection slave
+-- source include/stop_slave.inc
+-- connection master
+
+call mtr.add_suppression("Can't generate a unique log-filename");
+call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
+call mtr.add_suppression("Error writing file .*");
+
+SET @old_debug= @@global.debug;
+
+### ACTION: create a large file (> 4096 bytes) that will be later used
+###         in LOAD DATA INFILE to check binlog errors in its vacinity
+-- let $load_file= $MYSQLTEST_VARDIR/tmp/bug_46166.data
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SELECT repeat('x',8192) INTO OUTFILE '$load_file'
+
+### ACTION: create a small file (< 4096 bytes) that will be later used
+###         in LOAD DATA INFILE to check for absence of binlog errors
+###         when file loading this file does not force flushing and
+###         rotating the binary log
+-- let $load_file2= $MYSQLTEST_VARDIR/tmp/bug_46166-2.data
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SELECT repeat('x',10) INTO OUTFILE '$load_file2'
+
+RESET MASTER;
+
+-- echo ###################### TEST #1
+
+### ASSERTION: no problem flushing logs (should show two binlogs)
+FLUSH LOGS;
+-- echo # assert: must show two binlogs
+-- source include/show_binary_logs.inc
+
+-- echo ###################### TEST #2
+
+### ASSERTION: check that FLUSH LOGS actually fails and reports
+###            failure back to the user if find_uniq_filename fails
+###            (should show just one binlog)
+
+RESET MASTER;
+SET GLOBAL debug="+d,error_unique_log_filename";
+-- error ER_NO_UNIQUE_LOGFILE
+FLUSH LOGS;
+-- echo # assert: must show one binlog
+-- source include/show_binary_logs.inc
+
+### ACTION: clean up and move to next test
+SET GLOBAL debug="";
+RESET MASTER;
+
+-- echo ###################### TEST #3
+
+### ACTION: create some tables (t1, t2, t4) and insert some values in
+###         table t1
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a TEXT) Engine=InnoDB;
+CREATE TABLE t4 (a TEXT);
+INSERT INTO t1 VALUES (1);
+RESET MASTER;
+
+### ASSERTION: we force rotation of the binary log because it exceeds
+###            the max_binlog_size option (should show two binary
+###            logs)
+
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+
+# shows two binary logs
+-- echo # assert: must show two binlog
+-- source include/show_binary_logs.inc
+
+# clean up the table and the binlog to be used in next part of test
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #4
+
+### ASSERTION: load the big file into a transactional table and check
+###            that it reports error. The table will contain the
+###            changes performed despite the fact that it reported an
+###            error.
+
+SET GLOBAL debug="+d,error_unique_log_filename";
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+
+# show table 
+-- echo # assert: must show one entry
+SELECT count(*) FROM t2;
+
+# clean up the table and the binlog to be used in next part of test
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #5
+
+### ASSERTION: load the small file into a transactional table and
+###            check that it succeeds
+
+SET GLOBAL debug="+d,error_unique_log_filename";
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$load_file2' INTO TABLE t2
+
+# show table 
+-- echo # assert: must show one entry
+SELECT count(*) FROM t2;
+
+# clean up the table and the binlog to be used in next part of test
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #6
+
+### ASSERTION: check that even if one is using a transactional table
+###            and explicit transactions (no autocommit) if rotation
+###            fails we get the error. Transaction is not rolledback
+###            because rotation happens after the commit.
+
+SET GLOBAL debug="+d,error_unique_log_filename";
+SET AUTOCOMMIT=0;
+INSERT INTO t2 VALUES ('muse');
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+INSERT INTO t2 VALUES ('muse');
+-- error ER_NO_UNIQUE_LOGFILE
+COMMIT;
+
+### ACTION: Show the contents of the table after the test 
+-- echo # assert: must show three entries
+SELECT count(*) FROM t2;
+
+### ACTION: clean up and move to the next test 
+SET AUTOCOMMIT= 1;
+SET GLOBAL debug="-d,error_unique_log_filename";
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #7
+
+### ASSERTION: check that on a non-transactional table, if rotation
+###            fails then an error is reported and an incident event
+###            is written to the current binary log.
+
+SET GLOBAL debug="+d,error_unique_log_filename";
+SELECT count(*) FROM t4;
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t4
+
+-- echo # assert: must show 1 entry
+SELECT count(*) FROM t4;
+
+-- echo ### check that the incident event is written to the current log
+SET GLOBAL debug="-d,error_unique_log_filename";
+-- let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
+-- let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+
+# 53 is the size of the incident event, so we start from 22 bytes before the
+# current position
+-- let $binlog_start = `SELECT $binlog_start - 53`
+FLUSH LOGS;
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR $binlog_start <binlog_start> $binlog_file BINLOG_FILE
+-- replace_column 2 # 4 # 5 #
+-- eval SHOW BINLOG EVENTS IN '$binlog_file' FROM $binlog_start LIMIT 1
+
+# clean up and move to next test
+DELETE FROM t4;
+RESET MASTER;
+
+-- echo ###################### TEST #8
+
+### ASSERTION: check that statements end up in error but they succeed
+###            on changing the data. 
+
+SET GLOBAL debug="+d,error_unique_log_filename";
+-- echo # must show 0 entries
+SELECT count(*) FROM t4;
+SELECT count(*) FROM t2;
+
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t4
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+-- error ER_NO_UNIQUE_LOGFILE
+INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc');
+
+-- echo # INFO: Count(*) Before Offending DELETEs
+-- echo # assert: must show 1 entry
+SELECT count(*) FROM t4;
+-- echo # assert: must show 4 entries
+SELECT count(*) FROM t2;
+
+-- error ER_NO_UNIQUE_LOGFILE
+DELETE FROM t4;
+-- error ER_NO_UNIQUE_LOGFILE
+DELETE FROM t2;
+
+-- echo # INFO: Count(*) After Offending DELETEs
+-- echo # assert: must show zero entries
+SELECT count(*) FROM t4;
+SELECT count(*) FROM t2;
+
+# remove fault injection
+SET GLOBAL debug="-d,error_unique_log_filename";
+
+-- echo ###################### TEST #9
+
+### ASSERTION: check that if we disable binlogging, then statements
+###            succeed.
+SET GLOBAL debug="+d,error_unique_log_filename";
+SET SQL_LOG_BIN=0;
+INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc'), ('ddd');
+INSERT INTO t4 VALUES ('eee'), ('fff'), ('ggg'), ('hhh');
+-- echo # assert: must show four entries
+SELECT count(*) FROM t2;
+SELECT count(*) FROM t4;
+DELETE FROM t2;
+DELETE FROM t4;
+-- echo # assert: must show zero entries
+SELECT count(*) FROM t2;
+SELECT count(*) FROM t4;
+SET SQL_LOG_BIN=1;
+SET GLOBAL debug="-d,error_unique_log_filename";
+
+-- echo ###################### TEST #10
+
+### ASSERTION: check that error is reported if there is a failure
+###            while registering the index file and the binary log
+###            file or failure to write the rotate event.
+
+call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file.");
+call mtr.add_suppression("Could not open .*");
+
+RESET MASTER;
+SHOW WARNINGS;
+
+# +d,fault_injection_registering_index => injects fault on MYSQL_BIN_LOG::open
+SET GLOBAL debug="+d,fault_injection_registering_index";
+-- error ER_CANT_OPEN_FILE
+FLUSH LOGS;
+SET GLOBAL debug="-d,fault_injection_registering_index";
+
+-- error ER_NO_BINARY_LOGGING
+SHOW BINARY LOGS;
+
+# issue some statements and check that they don't fail
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+
+-- echo ###################### TEST #11
+
+### ASSERTION: check that error is reported if there is a failure
+###            while opening the index file and the binary log file or
+###            failure to write the rotate event.
+
+# restart the server so that we have binlog again
+--source include/restart_mysqld.inc
+
+# +d,fault_injection_openning_index => injects fault on MYSQL_BIN_LOG::open_index_file
+SET GLOBAL debug="+d,fault_injection_openning_index";
+-- error ER_CANT_OPEN_FILE
+FLUSH LOGS;
+SET GLOBAL debug="-d,fault_injection_openning_index";
+
+-- error ER_FLUSH_MASTER_BINLOG_CLOSED
+RESET MASTER;
+
+# issue some statements and check that they don't fail
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+
+# restart the server so that we have binlog again
+-- source include/restart_mysqld.inc
+
+-- echo ###################### TEST #12
+
+### ASSERTION: check that error is reported if there is a failure
+###            while writing the rotate event when creating a new log
+###            file.
+
+# +d,fault_injection_new_file_rotate_event => injects fault on MYSQL_BIN_LOG::MYSQL_BIN_LOG::new_file_impl
+SET GLOBAL debug="+d,fault_injection_new_file_rotate_event";
+-- error ER_ERROR_ON_WRITE
+FLUSH LOGS;
+SET GLOBAL debug="-d,fault_injection_new_file_rotate_event";
+
+-- error ER_FLUSH_MASTER_BINLOG_CLOSED
+RESET MASTER;
+
+# issue some statements and check that they don't fail
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+
+# restart the server so that we have binlog again
+-- source include/restart_mysqld.inc
+
+## clean up
+SET GLOBAL debug= @old_debug;
+DROP TABLE t1, t2, t4;
+RESET MASTER;
+
+# restart slave again
+-- connection slave
+-- source include/start_slave.inc
+-- connection master
+
+-- echo #######################################################################
+-- echo ####################### PART 2: SLAVE TESTS ###########################
+-- echo #######################################################################
+
+### setup
+-- connection master
+# master-slave-reset starts the slave automatically
+-- source include/master-slave-reset.inc
+-- connection slave
+
+# slave suppressions
+
+call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*");
+call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not open .*");
+call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file.");
+call mtr.add_suppression("Can't generate a unique log-filename .*");
+-- echo ###################### TEST #13
+
+#### ASSERTION: check against unique log filename error
+-- let $io_thd_injection_fault_flag= error_unique_log_filename
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+-- echo ###################### TEST #14
+
+#### ASSERTION: check against rotate failing
+-- let $io_thd_injection_fault_flag= fault_injection_new_file_rotate_event
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+-- echo ###################### TEST #15
+
+#### ASSERTION: check against relay log open failure
+-- let $io_thd_injection_fault_flag= fault_injection_registering_index
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+-- echo ###################### TEST #16
+
+#### ASSERTION: check against relay log index open failure
+-- let $io_thd_injection_fault_flag= fault_injection_openning_index
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+### clean up
+-- disable_warnings
+-- source include/stop_slave.inc
+-- enable_warnings
+SET GLOBAL debug=@old_debug;
+RESET SLAVE;
+RESET MASTER;
+-- source include/start_slave.inc
+-- connection master
+-- source include/master-slave-end.inc

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2010-12-13 12:11:16 +0000
+++ b/sql/handler.cc	2010-12-16 19:15:55 +0000
@@ -1237,7 +1237,11 @@ int ha_commit_trans(THD *thd, bool all)
     error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
     DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
     if (cookie)
-      tc_log->unlog(cookie, xid);
+      if(tc_log->unlog(cookie, xid))
+      {
+        error= 2;
+        goto end;
+      }
     DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
     RUN_HOOK(transaction, after_commit, (thd, FALSE));
 end:

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-12-15 22:38:43 +0000
+++ b/sql/log.cc	2010-12-16 19:12:31 +0000
@@ -2185,7 +2185,8 @@ static int find_uniq_filename(char *name
   *end='.';
   length= (size_t) (end - start + 1);
 
-  if (!(dir_info= my_dir(buff,MYF(MY_DONT_SORT))))
+  if ((DBUG_EVALUATE_IF("error_unique_log_filename", 1, 
+      !(dir_info= my_dir(buff,MYF(MY_DONT_SORT))))))
   {						// This shouldn't happen
     strmov(end,".1");				// use name+1
     DBUG_RETURN(1);
@@ -2212,7 +2213,11 @@ updating the index files.", max_found);
   }
 
   next= max_found + 1;
-  sprintf(ext_buf, "%06lu", next);
+  if (sprintf(ext_buf, "%06lu", next)<0)
+  {
+    error= 1;
+    goto end;
+  }
   *end++='.';
 
   /* 
@@ -2229,7 +2234,11 @@ index files.", name, ext_buf, (strlen(ex
     goto end;
   }
 
-  sprintf(end, "%06lu", next);
+  if (sprintf(end, "%06lu", next)<0)
+  {
+    error= 1;
+    goto end;
+  }
 
   /* print warning if reaching the end of available extensions. */
   if ((next > (MAX_LOG_UNIQUE_FN_EXT - LOG_WARN_UNIQUE_FN_EXT_LEFT)))
@@ -2462,13 +2471,8 @@ int MYSQL_LOG::generate_new_name(char *n
     {
       if (find_uniq_filename(new_name))
       {
-        /* 
-          This should be treated as error once propagation of error further
-          up in the stack gets proper handling.
-        */
-        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
-                            ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE),
-                            log_name);
+        my_printf_error(ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE),
+                        MYF(ME_FATALERROR), log_name);
 	sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name);
 	return 1;
       }
@@ -3453,7 +3457,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
   if (!thd->slave_thread)
     need_start_event=1;
   if (!open_index_file(index_file_name, 0, FALSE))
-    open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE);
+    if ((error= open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE)))
+      goto err;
   my_free((void *) save_name);
 
 err:
@@ -4118,17 +4123,23 @@ bool MYSQL_BIN_LOG::is_active(const char
   incapsulation 3) allows external access to the class without
   a lock (which is not possible with private new_file_without_locking
   method).
+
+  @retval
+    nonzero - error
 */
 
-void MYSQL_BIN_LOG::new_file()
+int MYSQL_BIN_LOG::new_file()
 {
-  new_file_impl(1);
+  return new_file_impl(1);
 }
 
-
-void MYSQL_BIN_LOG::new_file_without_locking()
+/*
+  @retval
+    nonzero - error
+ */
+int MYSQL_BIN_LOG::new_file_without_locking()
 {
-  new_file_impl(0);
+  return new_file_impl(0);
 }
 
 
@@ -4137,19 +4148,23 @@ void MYSQL_BIN_LOG::new_file_without_loc
 
   @param need_lock		Set to 1 if caller has not locked LOCK_log
 
+  @retval
+    nonzero - error
+
   @note
     The new file name is stored last in the index file
 */
 
-void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
+int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
 {
-  char new_name[FN_REFLEN], *new_name_ptr, *old_name;
+  int error= 0, close_on_error= FALSE;
+  char new_name[FN_REFLEN], *new_name_ptr, *old_name, *file_to_open;
 
   DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
   if (!is_open())
   {
     DBUG_PRINT("info",("log is closed"));
-    DBUG_VOID_RETURN;
+    DBUG_RETURN(error);
   }
 
   if (need_lock)
@@ -4187,7 +4202,7 @@ void MYSQL_BIN_LOG::new_file_impl(bool n
     We have to do this here and not in open as we want to store the
     new file name in the current binary log file.
   */
-  if (generate_new_name(new_name, name))
+  if ((error= generate_new_name(new_name, name)))
     goto end;
   new_name_ptr=new_name;
 
@@ -4201,7 +4216,13 @@ void MYSQL_BIN_LOG::new_file_impl(bool n
       */
       Rotate_log_event r(new_name+dirname_length(new_name),
                          0, LOG_EVENT_OFFSET, is_relay_log ? Rotate_log_event::RELAY_LOG : 0);
-      r.write(&log_file);
+      if(DBUG_EVALUATE_IF("fault_injection_new_file_rotate_event", (error=close_on_error=TRUE), FALSE) ||
+         (error= r.write(&log_file)))
+      {
+        close_on_error= TRUE;
+        my_printf_error(ER_ERROR_ON_WRITE, ER(ER_CANT_OPEN_FILE), MYF(ME_FATALERROR), name, errno);
+        goto end;
+      }
       bytes_written += r.data_written;
     }
     /*
@@ -4229,17 +4250,56 @@ void MYSQL_BIN_LOG::new_file_impl(bool n
   */
 
   /* reopen index binlog file, BUG#34582 */
-  if (!open_index_file(index_file_name, 0, FALSE))
-    open(old_name, log_type, new_name_ptr,
-         io_cache_type, no_auto_events, max_size, 1, FALSE);
+  file_to_open= index_file_name;
+  error= open_index_file(index_file_name, 0, FALSE);
+  if (!error)
+  {
+    /* reopen the binary log file. */
+    file_to_open= new_name_ptr;
+    error= open(old_name, log_type, new_name_ptr, io_cache_type,
+                no_auto_events, max_size, 1, FALSE);
+  }
+
+  /* handle reopening errors */
+  if (error)
+  {
+    my_printf_error(ER_CANT_OPEN_FILE, ER(ER_CANT_OPEN_FILE), 
+                    MYF(ME_FATALERROR), file_to_open, error);
+    close_on_error= TRUE;
+  }
+
   my_free(old_name);
 
 end:
+
+  if (error && close_on_error /* rotate or reopen failed */)
+  {
+    /* 
+      Close whatever was left opened.
+
+      We are keeping the behavior as it exists today, ie,
+      we disable logging and move on (see: BUG#51014).
+
+      TODO: as part of WL#1790 consider other approaches:
+       - kill mysql (safety);
+       - try multiple locations for opening a log file;
+       - switch server to protected/readonly mode
+       - ...
+    */
+    close(LOG_CLOSE_INDEX);
+    sql_print_error("Could not open %s for logging (error %d). "
+                     "Turning logging off for the whole duration "
+                     "of the MySQL server process. To turn it on "
+                     "again: fix the cause, shutdown the MySQL "
+                     "server and restart it.", 
+                     new_name_ptr, errno);
+  }
+
   if (need_lock)
     mysql_mutex_unlock(&LOCK_log);
   mysql_mutex_unlock(&LOCK_index);
 
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(error);
 }
 
 
@@ -4264,8 +4324,7 @@ bool MYSQL_BIN_LOG::append(Log_event* ev
   if (flush_and_sync(0))
     goto err;
   if ((uint) my_b_append_tell(&log_file) > max_size)
-    new_file_without_locking();
-
+    error= new_file_without_locking();
 err:
   mysql_mutex_unlock(&LOCK_log);
   signal_update();				// Safe as we don't call close
@@ -4296,8 +4355,7 @@ bool MYSQL_BIN_LOG::appendv(const char*
   if (flush_and_sync(0))
     goto err;
   if ((uint) my_b_append_tell(&log_file) > max_size)
-    new_file_without_locking();
-
+    error= new_file_without_locking();
 err:
   if (!error)
     signal_update();
@@ -4920,7 +4978,6 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
       goto err;
 
     error= 0;
-
 err:
     if (event_info->use_direct_logging())
     {
@@ -5025,8 +5082,19 @@ bool general_log_write(THD *thd, enum en
   return FALSE;
 }
 
-void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
+/**
+  @note
+    If rotation fails, for instance the server was unable 
+    to create a new log file, we still try to write an 
+    incident event to the current log.
+
+  @retval
+    nonzero - error 
+*/
+int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
 {
+  int error= 0;
+  DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
 #ifdef HAVE_REPLICATION
   bool check_purge= false;
 #endif
@@ -5035,26 +5103,38 @@ void MYSQL_BIN_LOG::rotate_and_purge(uin
   if ((flags & RP_FORCE_ROTATE) ||
       (my_b_tell(&log_file) >= (my_off_t) max_size))
   {
-    new_file_without_locking();
+    if ((error= new_file_without_locking()))
+      /** 
+         Be conservative... There are possible lost events (eg, 
+         failing to log the Execute_load_query_log_event
+         on a LOAD DATA while using a non-transactional
+         table)!
+
+         We give it a shot and try to write an incident event anyway
+         to the current log. 
+      */
+      if (!write_incident(current_thd, FALSE))
+        flush_and_sync(0);
+
 #ifdef HAVE_REPLICATION
     check_purge= true;
 #endif
   }
   if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
     mysql_mutex_unlock(&LOCK_log);
-
 #ifdef HAVE_REPLICATION
   /*
     NOTE: Run purge_logs wo/ holding LOCK_log
           as it otherwise will deadlock in ndbcluster_binlog_index_purge_file
   */
-  if (check_purge && expire_logs_days)
+  if (!error && check_purge && expire_logs_days)
   {
     time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
     if (purge_time >= 0)
       purge_logs_before_date(purge_time);
   }
 #endif
+  DBUG_RETURN(error);
 }
 
 uint MYSQL_BIN_LOG::next_file_id()
@@ -5240,6 +5320,10 @@ bool MYSQL_BIN_LOG::write_incident(THD *
 {
   uint error= 0;
   DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
+
+  if (!is_open())
+    DBUG_RETURN(error);
+
   LEX_STRING const write_error_msg=
     { C_STRING_WITH_LEN("error writing to the binary log") };
   Incident incident= INCIDENT_LOST_EVENTS;
@@ -5252,7 +5336,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *
     if (!error && !(error= flush_and_sync(0)))
     {
       signal_update();
-      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+      error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
     }
     mysql_mutex_unlock(&LOCK_log);
   }
@@ -5361,7 +5445,8 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
       mysql_mutex_unlock(&LOCK_prep_xids);
     }
     else
-      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+      if (rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED))
+        goto err;
   }
   mysql_mutex_unlock(&LOCK_log);
 
@@ -6194,7 +6279,7 @@ int TC_LOG_MMAP::sync()
   cookie points directly to the memory where xid was logged.
 */
 
-void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
+int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
 {
   PAGE *p=pages+(cookie/tc_log_page_size);
   my_xid *x=(my_xid *)(data+cookie);
@@ -6212,6 +6297,7 @@ void TC_LOG_MMAP::unlog(ulong cookie, my
   if (p->waiters == 0)                 // the page is in pool and ready to rock
     mysql_cond_signal(&COND_pool);     // ping ... for overflow()
   mysql_mutex_unlock(&p->lock);
+  return 0;
 }
 
 void TC_LOG_MMAP::close()
@@ -6454,8 +6540,9 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_
               !binlog_commit_flush_trx_cache(thd, cache_mngr, xid));
 }
 
-void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
+int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
 {
+  DBUG_ENTER("TC_LOG_BINLOG::unlog");
   mysql_mutex_lock(&LOCK_prep_xids);
   DBUG_ASSERT(prepared_xids > 0);
   if (--prepared_xids == 0) {
@@ -6463,7 +6550,7 @@ void TC_LOG_BINLOG::unlog(ulong cookie,
     mysql_cond_signal(&COND_prep_xids);
   }
   mysql_mutex_unlock(&LOCK_prep_xids);
-  rotate_and_purge(0);     // as ::write() did not rotate
+  DBUG_RETURN(rotate_and_purge(0));     // as ::write() did not rotate
 }
 
 int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)

=== modified file 'sql/log.h'
--- a/sql/log.h	2010-12-03 01:06:56 +0000
+++ b/sql/log.h	2010-12-07 16:11:13 +0000
@@ -45,7 +45,7 @@ class TC_LOG
   virtual int open(const char *opt_name)=0;
   virtual void close()=0;
   virtual int log_xid(THD *thd, my_xid xid)=0;
-  virtual void unlog(ulong cookie, my_xid xid)=0;
+  virtual int unlog(ulong cookie, my_xid xid)=0;
 };
 
 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
@@ -55,7 +55,7 @@ public:
   int open(const char *opt_name)        { return 0; }
   void close()                          { }
   int log_xid(THD *thd, my_xid xid)         { return 1; }
-  void unlog(ulong cookie, my_xid xid)  { }
+  int unlog(ulong cookie, my_xid xid)  { return 0; }
 };
 
 #ifdef HAVE_MMAP
@@ -100,7 +100,7 @@ class TC_LOG_MMAP: public TC_LOG
   int open(const char *opt_name);
   void close();
   int log_xid(THD *thd, my_xid xid);
-  void unlog(ulong cookie, my_xid xid);
+  int unlog(ulong cookie, my_xid xid);
   int recover();
 
   private:
@@ -334,8 +334,8 @@ class MYSQL_BIN_LOG: public TC_LOG, priv
     new_file() is locking. new_file_without_locking() does not acquire
     LOCK_log.
   */
-  void new_file_without_locking();
-  void new_file_impl(bool need_lock);
+  int new_file_without_locking();
+  int new_file_impl(bool need_lock);
 
 public:
   MYSQL_LOG::generate_name;
@@ -365,7 +365,7 @@ public:
   int open(const char *opt_name);
   void close();
   int log_xid(THD *thd, my_xid xid);
-  void unlog(ulong cookie, my_xid xid);
+  int unlog(ulong cookie, my_xid xid);
   int recover(IO_CACHE *log, Format_description_log_event *fdle);
 #if !defined(MYSQL_CLIENT)
 
@@ -408,7 +408,7 @@ public:
   bool open_index_file(const char *index_file_name_arg,
                        const char *log_name, bool need_mutex);
   /* Use this to start writing a new log file */
-  void new_file();
+  int new_file();
 
   bool write(Log_event* event_info); // binary log write
   bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
@@ -432,7 +432,7 @@ public:
   void make_log_name(char* buf, const char* log_ident);
   bool is_active(const char* log_file_name);
   int update_log_index(LOG_INFO* linfo, bool need_update_threads);
-  void rotate_and_purge(uint flags);
+  int rotate_and_purge(uint flags);
   /**
      Flush binlog cache and synchronize to disk.
 

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-12-16 18:43:21 +0000
+++ b/sql/mysqld.cc	2010-12-16 19:12:31 +0000
@@ -2736,7 +2736,7 @@ pthread_handler_t signal_hand(void *arg
     case SIGHUP:
       if (!abort_loop)
       {
-        bool not_used;
+        int not_used;
 	mysql_print_status();		// Print some debug info
 	reload_acl_and_cache((THD*) 0,
 			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |

=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc	2010-07-08 21:20:08 +0000
+++ b/sql/rpl_injector.cc	2010-12-07 16:11:13 +0000
@@ -237,8 +237,7 @@ int injector::record_incident(THD *thd,
   Incident_log_event ev(thd, incident);
   if (int error= mysql_bin_log.write(&ev))
     return error;
-  mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
-  return 0;
+  return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
 }
 
 int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message)
@@ -246,6 +245,5 @@ int injector::record_incident(THD *thd,
   Incident_log_event ev(thd, incident, message);
   if (int error= mysql_bin_log.write(&ev))
     return error;
-  mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
-  return 0;
+  return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
 }

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2010-11-18 15:01:58 +0000
+++ b/sql/slave.cc	2010-12-07 16:55:25 +0000
@@ -523,7 +523,8 @@ int terminate_slave_threads(Master_info*
     if (flush_master_info(mi, TRUE, FALSE))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
-    if (my_sync(mi->rli.relay_log.get_log_file()->file, MYF(MY_WME)))
+    if (mi->rli.relay_log.is_open() &&
+        my_sync(mi->rli.relay_log.get_log_file()->file, MYF(MY_WME)))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
     if (my_sync(mi->fd, MYF(MY_WME)))
@@ -3632,8 +3633,7 @@ static int process_io_rotate(Master_info
     Rotate the relay log makes binlog format detection easier (at next slave
     start or mysqlbinlog)
   */
-  rotate_relay_log(mi); /* will take the right mutexes */
-  DBUG_RETURN(0);
+  DBUG_RETURN(rotate_relay_log(mi) /* will take the right mutexes */);
 }
 
 /*
@@ -4870,12 +4870,13 @@ err:
   is void).
 */
 
-void rotate_relay_log(Master_info* mi)
+int rotate_relay_log(Master_info* mi)
 {
   DBUG_ENTER("rotate_relay_log");
   Relay_log_info* rli= &mi->rli;
+  int error= 0;
 
-  DBUG_EXECUTE_IF("crash_before_rotate_relaylog", abort(););
+  DBUG_EXECUTE_IF("crash_before_rotate_relaylog", DBUG_SUICIDE(););
 
   /*
      We need to test inited because otherwise, new_file() will attempt to lock
@@ -4888,7 +4889,8 @@ void rotate_relay_log(Master_info* mi)
   }
 
   /* If the relay log is closed, new_file() will do nothing. */
-  rli->relay_log.new_file();
+  if ((error= rli->relay_log.new_file()))
+    goto end;
 
   /*
     We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
@@ -4905,7 +4907,7 @@ void rotate_relay_log(Master_info* mi)
   */
   rli->relay_log.harvest_bytes_written(&rli->log_space_total);
 end:
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(error);
 }
 
 

=== modified file 'sql/slave.h'
--- a/sql/slave.h	2010-03-31 14:05:33 +0000
+++ b/sql/slave.h	2010-12-07 16:11:13 +0000
@@ -205,7 +205,7 @@ int purge_relay_logs(Relay_log_info* rli
 		     const char** errmsg);
 void set_slave_thread_options(THD* thd);
 void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli);
-void rotate_relay_log(Master_info* mi);
+int rotate_relay_log(Master_info* mi);
 int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli);
 
 pthread_handler_t handle_slave_io(void *arg);

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2010-10-01 20:12:27 +0000
+++ b/sql/sql_load.cc	2010-12-07 16:11:13 +0000
@@ -625,6 +625,13 @@ int mysql_load(THD *thd,sql_exchange *ex
                                                   transactional_table,
                                                   errcode);
       }
+
+      /*
+        Flushing the IO CACHE while writing the execute load query log event
+        may result in error (for instance, because the max_binlog_size has been 
+        reached, and rotation of the binary log failed).
+      */
+      error= error || mysql_bin_log.get_log_file()->error;
     }
     if (error)
       goto err;

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-12-16 18:43:21 +0000
+++ b/sql/sql_parse.cc	2010-12-16 19:15:55 +0000
@@ -1218,7 +1218,7 @@ bool dispatch_command(enum enum_server_c
 #endif
   case COM_REFRESH:
   {
-    bool not_used;
+    int not_used;
     status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
     ulong options= (ulong) (uchar) packet[0];
     if (trans_commit_implicit(thd))
@@ -2780,7 +2780,11 @@ end_with_restore_list:
       {
         Incident_log_event ev(thd, incident);
         (void) mysql_bin_log.write(&ev);        /* error is ignored */
-        mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+        if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
+        {
+          res= 1;
+          break;
+        }
       }
       DBUG_PRINT("debug", ("Just after generate_incident()"));
     }
@@ -3516,8 +3520,7 @@ end_with_restore_list:
     lex->no_write_to_binlog= 1;
   case SQLCOM_FLUSH:
   {
-    bool write_to_binlog;
-
+    int write_to_binlog;
     if (check_global_access(thd,RELOAD_ACL))
       goto error;
 
@@ -3546,12 +3549,22 @@ end_with_restore_list:
       /*
         Presumably, RESET and binlog writing doesn't require synchronization
       */
-      if (!lex->no_write_to_binlog && write_to_binlog)
-      {
-        if ((res= write_bin_log(thd, FALSE, thd->query(), thd->query_length())))
-          break;
-      }
-      my_ok(thd);
+
+      if (write_to_binlog > 0)  // we should write
+      { 
+        if (!lex->no_write_to_binlog)
+          res= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+      } else if (write_to_binlog < 0) 
+      {
+        /* 
+           We should not write, but rather report error because 
+           reload_acl_and_cache binlog interactions failed 
+         */
+        res= 1;
+      } 
+
+      if (!res)
+        my_ok(thd);
     } 
     
     break;

=== modified file 'sql/sql_reload.cc'
--- a/sql/sql_reload.cc	2010-09-09 14:29:14 +0000
+++ b/sql/sql_reload.cc	2010-12-07 16:11:13 +0000
@@ -33,7 +33,11 @@
   @param thd Thread handler (can be NULL!)
   @param options What should be reset/reloaded (tables, privileges, slave...)
   @param tables Tables to flush (if any)
-  @param write_to_binlog True if we can write to the binlog.
+  @param write_to_binlog < 0 if there was an error while interacting with the binary log inside
+                         reload_acl_and_cache,
+                         0 if we should not write to the binary log,
+                         > 0 if we can write to the binlog.
+
                
   @note Depending on 'options', it may be very bad to write the
     query to the binlog (e.g. FLUSH SLAVE); this is a
@@ -47,11 +51,11 @@
 */
 
 bool reload_acl_and_cache(THD *thd, unsigned long options,
-                          TABLE_LIST *tables, bool *write_to_binlog)
+                          TABLE_LIST *tables, int *write_to_binlog)
 {
   bool result=0;
   select_errors=0;				/* Write if more errors */
-  bool tmp_write_to_binlog= 1;
+  int tmp_write_to_binlog= *write_to_binlog= 1;
 
   DBUG_ASSERT(!thd || !thd->in_sub_stmt);
 
@@ -136,13 +140,17 @@ bool reload_acl_and_cache(THD *thd, unsi
     */
     tmp_write_to_binlog= 0;
     if (mysql_bin_log.is_open())
-      mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+    {
+      if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
+        *write_to_binlog= -1;
+    }
   }
   if (options & REFRESH_RELAY_LOG)
   {
 #ifdef HAVE_REPLICATION
     mysql_mutex_lock(&LOCK_active_mi);
-    rotate_relay_log(active_mi);
+    if (rotate_relay_log(active_mi))
+      *write_to_binlog= -1;
     mysql_mutex_unlock(&LOCK_active_mi);
 #endif
   }
@@ -274,7 +282,8 @@ bool reload_acl_and_cache(THD *thd, unsi
 #endif
  if (options & REFRESH_USER_RESOURCES)
    reset_mqh((LEX_USER *) NULL, 0);             /* purecov: inspected */
- *write_to_binlog= tmp_write_to_binlog;
+ if (*write_to_binlog != -1)
+   *write_to_binlog= tmp_write_to_binlog;
  /*
    If the query was killed then this function must fail.
  */

=== modified file 'sql/sql_reload.h'
--- a/sql/sql_reload.h	2010-08-13 09:51:48 +0000
+++ b/sql/sql_reload.h	2010-12-07 16:11:13 +0000
@@ -19,7 +19,7 @@ class THD;
 struct TABLE_LIST;
 
 bool reload_acl_and_cache(THD *thd, unsigned long options,
-                          TABLE_LIST *tables, bool *write_to_binlog);
+                          TABLE_LIST *tables, int *write_to_binlog);
 
 bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables);
 

=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc	2010-09-06 17:18:44 +0000
+++ b/sql/sql_repl.cc	2010-12-07 16:55:25 +0000
@@ -1925,7 +1925,7 @@ bool show_binlogs(THD* thd)
 
   if (!mysql_bin_log.is_open())
   {
-    my_message(ER_NO_BINARY_LOGGING, ER(ER_NO_BINARY_LOGGING), MYF(0));
+    my_error(ER_NO_BINARY_LOGGING, MYF(0));
     DBUG_RETURN(TRUE);
   }
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-bugteam branch (luis.soares:3204 to 3206) Luis Soares16 Dec