List:Commits« Previous MessageNext Message »
From:Marc Alff Date:April 17 2009 3:46pm
Subject:bzr commit into mysql-6.0-perf branch (marc.alff:2872)
View as plain text  
#At file:///home/malff/BZR-TREE/mysql-6.0-perf/ based on revid:marc.alff@stripped

 2872 Marc Alff	2009-04-17 [merge]
      Merge mysql-6.0 --> mysql-6.0-perf
added:
  sql/rpl_info.cc
  sql/rpl_info.h
  sql/rpl_mi_file.cc
  sql/rpl_mi_file.h
  sql/rpl_rli_file.cc
  sql/rpl_rli_file.h
modified:
  mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test
  mysql-test/extra/rpl_tests/rpl_row_tabledefs.test
  mysql-test/r/mysqldump.result
  mysql-test/suite/rpl/r/rpl_extraCol_innodb.result
  mysql-test/suite/rpl/r/rpl_extraCol_myisam.result
  mysql-test/suite/rpl/r/rpl_heartbeat_2slaves.result
  mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result
  mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result
  mysql-test/suite/rpl/t/disabled.def
  mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf
  mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test
  sql/CMakeLists.txt
  sql/Makefile.am
  sql/ha_ndbcluster.cc
  sql/item_func.cc
  sql/log.cc
  sql/log_event.cc
  sql/log_event_old.cc
  sql/mysql_priv.h
  sql/mysqld.cc
  sql/rpl_mi.cc
  sql/rpl_mi.h
  sql/rpl_record.cc
  sql/rpl_record.h
  sql/rpl_reporting.cc
  sql/rpl_reporting.h
  sql/rpl_rli.cc
  sql/rpl_rli.h
  sql/set_var.cc
  sql/slave.cc
  sql/slave.h
  sql/sp_head.cc
  sql/sql_acl.cc
  sql/sql_acl.h
  sql/sql_binlog.cc
  sql/sql_insert.cc
  sql/sql_load.cc
  sql/sql_parse.cc
  sql/sql_repl.cc

=== modified file 'mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test'
--- a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test	2008-07-10 16:09:39 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test	2009-04-08 13:09:37 +0000
@@ -405,13 +405,18 @@ sync_slave_with_master;
 ###########################################
 # Bug#22234, Bug#23907 Extra Slave Col is not 
 # erroring on extra col with no default values.
-########################################################
+###############################################################
+# Error reaction is up to sql_mode of the slave sql (bug#38173)
 #--echo *** Create t9 on slave  ***
 STOP SLAVE;
 RESET SLAVE;
 eval CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5),
                       d TIMESTAMP,
-                      e INT NOT NULL) ENGINE=$engine_type;
+                      e INT NOT NULL,
+		      f text not null,
+		      g text,
+		      h blob not null,
+		      i blob) ENGINE=$engine_type;
 
 --echo *** Create t9 on Master ***
 connection master;
@@ -429,13 +434,25 @@ set @b1 = 'b1b1b1b1';
 set @b1 = concat(@b1,@b1);
 INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
 
-connection slave;
---source include/wait_for_slave_sql_to_stop.inc
---replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 #
---query_vertical SHOW SLAVE STATUS
-SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
-START SLAVE;
+# the test would stop slave if @@sql_mode for the sql thread
+# was set to strict. Otherwise, as with this tests setup, 
+# the implicit defaults will be inserted into fields even though
+# they are declared without DEFAULT clause.
+
+sync_slave_with_master;
+select * from t9;
+
+# todo: fix Bug #43992 slave sql thread can't tune own sql_mode ...
+# and add/restore waiting for stop test
+
+#--source include/wait_for_slave_sql_to_stop.inc
+#--replace_result $MASTER_MYPORT MASTER_PORT
+#--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 #
+#--query_vertical SHOW SLAVE STATUS
+#SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
+#START SLAVE;
+
+
 
 #--echo *** Drop t9  ***
 #connection master;

=== modified file 'mysql-test/extra/rpl_tests/rpl_row_tabledefs.test'
--- a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test	2009-02-02 15:58:48 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test	2009-04-08 13:09:37 +0000
@@ -111,21 +111,18 @@ SELECT a,b,x FROM t1_int ORDER BY a;
 SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
 SELECT a,b,x FROM t1_char ORDER BY a;
 
-# Each of these inserts should generate an error and stop the slave
-
 connection master;
 INSERT INTO t9 VALUES (2);
 sync_slave_with_master;
 # Now slave is guaranteed to be running
 connection master;
 INSERT INTO t1_nodef VALUES (1,2);
-connection slave;
---source include/wait_for_slave_sql_to_stop.inc
---replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 4 # 7 # 8 # 9 # 20 <Last_Error> 22 # 23 # 33 # 35 <Last_IO_Errno> 36 <Last_IO_Error> 38 <Last_SQL_Error>
---query_vertical SHOW SLAVE STATUS
-SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
-START SLAVE;
+
+# Last insert on wider slave table succeeds while slave sql sql_mode permits.
+# The previous version of the above test expected slave sql to stop.
+# bug#38173 relaxed conditions to stop only with the strict mode.
+sync_slave_with_master;
+select count(*) from t1_nodef;
 
 #
 # Replicating to tables with fewer columns at the end works as of WL#3228

=== modified file 'mysql-test/r/mysqldump.result'
--- a/mysql-test/r/mysqldump.result	2009-04-01 21:36:07 +0000
+++ b/mysql-test/r/mysqldump.result	2009-04-05 16:11:17 +0000
@@ -3558,8 +3558,8 @@ reset master;
 mysqldump: Couldn't execute 'FLUSH /*!40101 LOCAL */ TABLES': Access denied; you need the RELOAD privilege for this operation (1227)
 mysqldump: Couldn't execute 'FLUSH /*!40101 LOCAL */ TABLES': Access denied; you need the RELOAD privilege for this operation (1227)
 grant RELOAD on *.* to mysqltest_1@localhost;
-mysqldump: Couldn't execute 'SHOW MASTER STATUS': Access denied; you need the SUPER,REPLICATION CLIENT privilege for this operation (1227)
-mysqldump: Couldn't execute 'SHOW MASTER STATUS': Access denied; you need the SUPER,REPLICATION CLIENT privilege for this operation (1227)
+mysqldump: Couldn't execute 'SHOW MASTER STATUS': Access denied; you need the SUPER|REPLICATION CLIENT privilege for this operation (1227)
+mysqldump: Couldn't execute 'SHOW MASTER STATUS': Access denied; you need the SUPER|REPLICATION CLIENT privilege for this operation (1227)
 grant REPLICATION CLIENT on *.* to mysqltest_1@localhost;
 drop table t1;
 drop user mysqltest_1@localhost;

=== modified file 'mysql-test/suite/rpl/r/rpl_extraCol_innodb.result'
--- a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result	2008-11-12 15:23:22 +0000
+++ b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result	2009-04-08 13:09:37 +0000
@@ -413,7 +413,11 @@ STOP SLAVE;
 RESET SLAVE;
 CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5),
 d TIMESTAMP,
-e INT NOT NULL) ENGINE='InnoDB';
+e INT NOT NULL,
+f text not null,
+g text,
+h blob not null,
+i blob) ENGINE='InnoDB';
 *** Create t9 on Master ***
 CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5)
 ) ENGINE='InnoDB';
@@ -424,49 +428,11 @@ START SLAVE;
 set @b1 = 'b1b1b1b1';
 set @b1 = concat(@b1,@b1);
 INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
-SHOW SLAVE STATUS;
-Slave_IO_State	#
-Master_Host	127.0.0.1
-Master_User	root
-Master_Port	#
-Connect_Retry	1
-Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	#
-Relay_Log_File	#
-Relay_Log_Pos	#
-Relay_Master_Log_File	master-bin.000001
-Slave_IO_Running	Yes
-Slave_SQL_Running	No
-Replicate_Do_DB	
-Replicate_Ignore_DB	
-Replicate_Do_Table	
-Replicate_Ignore_Table	#
-Replicate_Wild_Do_Table	
-Replicate_Wild_Ignore_Table	
-Last_Errno	1364
-Last_Error	Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 331
-Skip_Counter	0
-Exec_Master_Log_Pos	#
-Relay_Log_Space	#
-Until_Condition	None
-Until_Log_File	
-Until_Log_Pos	0
-Master_SSL_Allowed	No
-Master_SSL_CA_File	
-Master_SSL_CA_Path	
-Master_SSL_Cert	
-Master_SSL_Cipher	
-Master_SSL_Key	
-Seconds_Behind_Master	#
-Master_SSL_Verify_Server_Cert	No
-Last_IO_Errno	#
-Last_IO_Error	#
-Last_SQL_Errno	1364
-Last_SQL_Error	Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 331
-Replicate_Ignore_Server_Ids	
-Master_Server_Id	1
-SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
-START SLAVE;
+select * from t9;
+a	b	c	d	e	f	g	h	i
+1	b1b1b1b1b1b1b1b1	Kyle	0000-00-00 00:00:00	0		NULL		NULL
+2	b1b1b1b1b1b1b1b1	JOE	0000-00-00 00:00:00	0		NULL		NULL
+3	b1b1b1b1b1b1b1b1	QA	0000-00-00 00:00:00	0		NULL		NULL
 *** Create t10 on slave  ***
 STOP SLAVE;
 RESET SLAVE;

=== modified file 'mysql-test/suite/rpl/r/rpl_extraCol_myisam.result'
--- a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result	2008-11-12 15:23:22 +0000
+++ b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result	2009-04-08 13:09:37 +0000
@@ -413,7 +413,11 @@ STOP SLAVE;
 RESET SLAVE;
 CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5),
 d TIMESTAMP,
-e INT NOT NULL) ENGINE='MyISAM';
+e INT NOT NULL,
+f text not null,
+g text,
+h blob not null,
+i blob) ENGINE='MyISAM';
 *** Create t9 on Master ***
 CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5)
 ) ENGINE='MyISAM';
@@ -424,49 +428,11 @@ START SLAVE;
 set @b1 = 'b1b1b1b1';
 set @b1 = concat(@b1,@b1);
 INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
-SHOW SLAVE STATUS;
-Slave_IO_State	#
-Master_Host	127.0.0.1
-Master_User	root
-Master_Port	#
-Connect_Retry	1
-Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	#
-Relay_Log_File	#
-Relay_Log_Pos	#
-Relay_Master_Log_File	master-bin.000001
-Slave_IO_Running	Yes
-Slave_SQL_Running	No
-Replicate_Do_DB	
-Replicate_Ignore_DB	
-Replicate_Do_Table	
-Replicate_Ignore_Table	#
-Replicate_Wild_Do_Table	
-Replicate_Wild_Ignore_Table	
-Last_Errno	1364
-Last_Error	Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 331
-Skip_Counter	0
-Exec_Master_Log_Pos	#
-Relay_Log_Space	#
-Until_Condition	None
-Until_Log_File	
-Until_Log_Pos	0
-Master_SSL_Allowed	No
-Master_SSL_CA_File	
-Master_SSL_CA_Path	
-Master_SSL_Cert	
-Master_SSL_Cipher	
-Master_SSL_Key	
-Seconds_Behind_Master	#
-Master_SSL_Verify_Server_Cert	No
-Last_IO_Errno	#
-Last_IO_Error	#
-Last_SQL_Errno	1364
-Last_SQL_Error	Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 331
-Replicate_Ignore_Server_Ids	
-Master_Server_Id	1
-SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
-START SLAVE;
+select * from t9;
+a	b	c	d	e	f	g	h	i
+1	b1b1b1b1b1b1b1b1	Kyle	0000-00-00 00:00:00	0		NULL		NULL
+2	b1b1b1b1b1b1b1b1	JOE	0000-00-00 00:00:00	0		NULL		NULL
+3	b1b1b1b1b1b1b1b1	QA	0000-00-00 00:00:00	0		NULL		NULL
 *** Create t10 on slave  ***
 STOP SLAVE;
 RESET SLAVE;

=== modified file 'mysql-test/suite/rpl/r/rpl_heartbeat_2slaves.result'
--- a/mysql-test/suite/rpl/r/rpl_heartbeat_2slaves.result	2009-03-16 13:26:41 +0000
+++ b/mysql-test/suite/rpl/r/rpl_heartbeat_2slaves.result	2009-03-24 18:54:58 +0000
@@ -12,6 +12,7 @@ RESET SLAVE;
 CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1, MASTER_LOG_FILE='MASTER_BINLOG';
 include/start_slave.inc
 [on slave1]
+STOP SLAVE;
 RESET SLAVE;
 CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=1, MASTER_LOG_FILE='MASTER_BINLOG';
 include/start_slave.inc
@@ -21,33 +22,34 @@ Slave has received heartbeat event
 Slave1 has received heartbeat event
 Slave has received more heartbeats than Slave1 (1 means 'yes'): 1
 
-*** Master->heartbeat->Slave   Master->data->Slave1: ***
+*** Master->data->Slave1->heartbeat->Slave: ***
+[on slave1]
+RESET MASTER;
+[on slave]
+include/stop_slave.inc
+RESET SLAVE;
+CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=SLAVE1_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.2, MASTER_LOG_FILE='SLAVE1_BINLOG';
+include/start_slave.inc
+Slave has received heartbeat event
 [on master]
-CREATE DATABASE test_slave1;
-USE test_slave1;
 CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10), c LONGTEXT);
 INSERT INTO t1 VALUES (1, 'on master', '');
-[on slave]
-SHOW DATABASES LIKE 'test_slave1';
-Database (test_slave1)
+SHOW TABLES;
+Tables_in_test
+t1
 [on slave1]
-SHOW DATABASES LIKE 'test_slave1';
-Database (test_slave1)
-test_slave1
-include/stop_slave.inc
+SHOW TABLES;
+Tables_in_test
+t1
+[on slave]
+SHOW TABLES;
+Tables_in_test
 [on master]
-creating 1000 updates in binlog
-[on slave1]
-START SLAVE;
-[on slave1]
-USE test_slave1;
-SELECT a FROM t1;
-a
-1000
+creating updates on master and send to slave1 during 5 second
 [on slave]
 Slave has received heartbeats (1 means 'yes'): 1
 
 *** Clean up ***
-DROP DATABASE test_slave1;
+DROP TABLE t1;
 
 End of 6.0 test

=== modified file 'mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result'
--- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result	2009-02-02 15:58:48 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result	2009-04-08 13:09:37 +0000
@@ -105,49 +105,9 @@ a	b	x
 2	10	Foo is a bar
 INSERT INTO t9 VALUES (2);
 INSERT INTO t1_nodef VALUES (1,2);
-SHOW SLAVE STATUS;
-Slave_IO_State	#
-Master_Host	127.0.0.1
-Master_User	root
-Master_Port	#
-Connect_Retry	1
-Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	#
-Relay_Log_File	#
-Relay_Log_Pos	#
-Relay_Master_Log_File	master-bin.000001
-Slave_IO_Running	Yes
-Slave_SQL_Running	No
-Replicate_Do_DB	
-Replicate_Ignore_DB	
-Replicate_Do_Table	
-Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
-Replicate_Wild_Ignore_Table	
-Last_Errno	1364
-Last_Error	<Last_Error>
-Skip_Counter	0
-Exec_Master_Log_Pos	#
-Relay_Log_Space	#
-Until_Condition	None
-Until_Log_File	
-Until_Log_Pos	0
-Master_SSL_Allowed	No
-Master_SSL_CA_File	
-Master_SSL_CA_Path	
-Master_SSL_Cert	
-Master_SSL_Cipher	
-Master_SSL_Key	
-Seconds_Behind_Master	#
-Master_SSL_Verify_Server_Cert	No
-Last_IO_Errno	<Last_IO_Errno>
-Last_IO_Error	<Last_IO_Error>
-Last_SQL_Errno	1364
-Last_SQL_Error	<Last_SQL_Error>
-Replicate_Ignore_Server_Ids	
-Master_Server_Id	1
-SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
-START SLAVE;
+select count(*) from t1_nodef;
+count(*)
+1
 INSERT INTO t9 VALUES (2);
 **** On Master ****
 INSERT INTO t2 VALUES (2,4);

=== modified file 'mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result'
--- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result	2009-02-02 15:58:48 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result	2009-04-08 13:09:37 +0000
@@ -105,49 +105,9 @@ a	b	x
 2	10	Foo is a bar
 INSERT INTO t9 VALUES (2);
 INSERT INTO t1_nodef VALUES (1,2);
-SHOW SLAVE STATUS;
-Slave_IO_State	#
-Master_Host	127.0.0.1
-Master_User	root
-Master_Port	#
-Connect_Retry	1
-Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	#
-Relay_Log_File	#
-Relay_Log_Pos	#
-Relay_Master_Log_File	master-bin.000001
-Slave_IO_Running	Yes
-Slave_SQL_Running	No
-Replicate_Do_DB	
-Replicate_Ignore_DB	
-Replicate_Do_Table	
-Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
-Replicate_Wild_Ignore_Table	
-Last_Errno	1364
-Last_Error	<Last_Error>
-Skip_Counter	0
-Exec_Master_Log_Pos	#
-Relay_Log_Space	#
-Until_Condition	None
-Until_Log_File	
-Until_Log_Pos	0
-Master_SSL_Allowed	No
-Master_SSL_CA_File	
-Master_SSL_CA_Path	
-Master_SSL_Cert	
-Master_SSL_Cipher	
-Master_SSL_Key	
-Seconds_Behind_Master	#
-Master_SSL_Verify_Server_Cert	No
-Last_IO_Errno	<Last_IO_Errno>
-Last_IO_Error	<Last_IO_Error>
-Last_SQL_Errno	1364
-Last_SQL_Error	<Last_SQL_Error>
-Replicate_Ignore_Server_Ids	
-Master_Server_Id	1
-SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
-START SLAVE;
+select count(*) from t1_nodef;
+count(*)
+1
 INSERT INTO t9 VALUES (2);
 **** On Master ****
 INSERT INTO t2 VALUES (2,4);

=== modified file 'mysql-test/suite/rpl/t/disabled.def'
--- a/mysql-test/suite/rpl/t/disabled.def	2009-04-01 09:34:34 +0000
+++ b/mysql-test/suite/rpl/t/disabled.def	2009-04-13 13:24:28 +0000
@@ -18,7 +18,6 @@ rpl_cross_version          : BUG#42311 2
 rpl_extraCol_falcon        : Bug#40930 2008-11-21 johnemb rpl.rpl_extraCol_falcon fails doing STOP SLAVE (on Windows PB2)
 rpl_cross_version          : Bug#42311 2009-01-23 aelkin
 rpl_heartbeat_basic        : Bug#43828 Sporadic failures (Serge.Kozlov@stripped)
-rpl_heartbeat_2slaves      : Bug#43828 Sporadic failrues (Serge.Kozlov@stripped)
 rpl_temp_table_mix_row     : Bug#43440 2009-03-26 alik rpl.rpl_temp_table_mix_row fails sporadicly
 rpl_log_pos                : Bug#42858 2009-02-14 alik rpl.rpl_log_pos fails, thus was disabled
 rpl_failed_optimize        : WL#4284: Can't optimize table used by a pending transaction (there is metadata lock on the table).

=== modified file 'mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf'
--- a/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf	2009-03-16 11:33:16 +0000
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf	2009-03-24 18:54:58 +0000
@@ -5,10 +5,8 @@ server_id=1
 
 [mysqld.2]
 server_id=2
-replicate-ignore-db=test_slave1
 
 [mysqld.3]
-log-slave-updates
 server_id=3
 
 [ENV]

=== modified file 'mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test'
--- a/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test	2009-03-16 13:26:41 +0000
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test	2009-03-24 18:54:58 +0000
@@ -21,6 +21,9 @@ eval CHANGE MASTER TO MASTER_HOST='127.0
 --connect(slave1,127.0.0.1,root,,test,$SLAVE_MYPORT1,)
 --connection slave1
 --echo [on slave1]
+--disable_warnings
+STOP SLAVE;
+--enable_warnings
 RESET SLAVE;
 --replace_result $MASTER_MYPORT MASTER_PORT $binlog_file MASTER_BINLOG
 eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=1, MASTER_LOG_FILE='$binlog_file';
@@ -52,60 +55,72 @@ let $result= query_get_value(SELECT ($sl
 --echo Slave has received more heartbeats than Slave1 (1 means 'yes'): $result
 --echo
 
-# First slave doesn't receive data from master because it masked by --replicate-ignore-db.
-# Second slave receives data. Check that the 1st can receive heartbeat.
---echo *** Master->heartbeat->Slave   Master->data->Slave1: ***
+
+# Create topology A->B->C and check that C receives heartbeat while B gets data
+# Slave1 (B) started w/o --log-slave-updates because B should not send data from A to C
+--echo *** Master->data->Slave1->heartbeat->Slave: ***
+--connection slave1
+--echo [on slave1]
+RESET MASTER;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+--connection slave
+--echo [on slave]
+--source include/stop_slave.inc
+RESET SLAVE;
+--replace_result $SLAVE_MYPORT1 SLAVE1_PORT $binlog_file SLAVE1_BINLOG
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT1, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.2, MASTER_LOG_FILE='$binlog_file';
+--source include/start_slave.inc
+# Check heartbeat for new replication channel slave1->slave
+let $status_var= slave_received_heartbeats;
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Slave has received heartbeat event
 --connection master
 --echo [on master]
-CREATE DATABASE test_slave1;
-USE test_slave1;
 CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10), c LONGTEXT);
 INSERT INTO t1 VALUES (1, 'on master', '');
---sync_slave_with_master
---echo [on slave]
-SHOW DATABASES LIKE 'test_slave1';
+--save_master_pos
+SHOW TABLES;
 --connection slave1
---sync_with_master
+--sync_with_master 0
 --echo [on slave1]
-SHOW DATABASES LIKE 'test_slave1';
---source include/stop_slave.inc
+SHOW TABLES;
+let $slave_pos_before= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+--save_master_pos
+--connection slave
+--sync_with_master 0
+--echo [on slave]
+SHOW TABLES;
 --connection master
 --echo [on master]
---echo creating 1000 updates in binlog
-# Generate events for binlog on master
-let $i= 1000;
+--echo creating updates on master and send to slave1 during 5 second
+# Generate events on master and send to slave1 during 5 second
+let $i= 1;
 let $j= 1;
+let $k= 1;
 --disable_query_log
 while ($i) {
-  eval SET @c_text=REPEAT('1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890', 1000+$j);
+  eval SET @c_text=REPEAT('1234567890', $j);
   eval UPDATE t1 SET a=$j, c=@c_text;
-  dec $i;
+  --connection slave1
+  let $slave_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);  
+  if (`SELECT ($k*($slave_pos - $slave_pos_before)) > 0`) {
+    --connection slave
+    let $slave_rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);    
+    let $k= 0;
+    let $time_before = `SELECT NOW()`;
+  }
+  if (`SELECT ((1-$k)*TIMESTAMPDIFF(SECOND,'$time_before',NOW())) > 5`) {
+    --connection slave
+    let $slave_rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);    
+    let $i= 0;
+  }
+  --connection master
   inc $j;
+  sleep 0.1;
 }
 --enable_query_log
-save_master_pos;
-let $binlog_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
---connection slave1
---echo [on slave1]
-START SLAVE;
-let $slave_param= Read_Master_Log_Pos;
-let $slave_param_value= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
-let $slave_param_comparison= >;
---source include/wait_for_slave_param.inc
---connection slave
-let $slave_rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
---connection slave1
-let $slave_param= Read_Master_Log_Pos;
-let $slave_param_value= $binlog_pos;
-let $slave_param_comparison= =;
---source include/wait_for_slave_param.inc
---connection slave
-let $slave_rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
---connection slave1
---sync_with_master
---echo [on slave1]
-USE test_slave1;
-SELECT a FROM t1;
 --connection slave
 --echo [on slave]
 let $result= query_get_value(SELECT ($slave_rcvd_heartbeats_after - $slave_rcvd_heartbeats_before) > 0 AS Result, Result, 1);
@@ -117,10 +132,10 @@ let $result= query_get_value(SELECT ($sl
 #
 --echo *** Clean up ***
 --connection master
-DROP DATABASE test_slave1;
---sync_slave_with_master
+DROP TABLE t1;
+--save_master_pos
 --connection slave1
---sync_with_master
+--sync_with_master 0
 --echo
 
 # End of 6.0 test

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2009-03-30 02:25:31 +0000
+++ b/sql/CMakeLists.txt	2009-04-17 15:45:46 +0000
@@ -74,11 +74,11 @@ ADD_EXECUTABLE(mysqld
                event_queue.cc event_db_repository.cc 
                sql_tablespace.cc events.cc ../sql-common/my_user.c 
                partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
-               rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
+               rpl_info.cc rpl_rli.cc rpl_rli_file.cc rpl_mi.cc rpl_mi_file.cc
+               sql_servers.cc sql_audit.cc
                sql_connect.cc scheduler.cc transaction.cc
                bml.cc si_objects.cc si_logs.cc
-               sql_profile.cc event_parse_data.cc mdl.cc rpl_handler.cc
-               sql_signal.cc
+               sql_profile.cc event_parse_data.cc mdl.cc rpl_handler.cc sql_signal.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
                ${PROJECT_SOURCE_DIR}/include/mysqld_error.h

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2009-03-26 15:35:49 +0000
+++ b/sql/Makefile.am	2009-04-17 15:45:46 +0000
@@ -84,7 +84,8 @@ noinst_HEADERS =	item.h item_func.h item
 			debug_sync.h \
 			opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \
 			rpl_reporting.h \
-			log.h sql_show.h rpl_rli.h rpl_mi.h \
+			log.h sql_show.h rpl_info.h \
+			rpl_rli.h rpl_rli_file.h rpl_mi.h rpl_mi_file.h \
 			sql_select.h structs.h table.h sql_udf.h hash_filo.h \
 			lex.h lex_symbol.h sql_acl.h sql_crypt.h  \
 			sql_repl.h slave.h rpl_filter.h rpl_injector.h \
@@ -137,6 +138,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
 			slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \
 			rpl_utility.cc rpl_injector.cc rpl_rli.cc rpl_mi.cc \
+			rpl_info.cc rpl_rli_file.cc rpl_mi_file.cc \
 			rpl_reporting.cc \
                         sql_union.cc sql_derived.cc \
 			sql_client.cc \

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2009-04-14 21:37:16 +0000
+++ b/sql/ha_ndbcluster.cc	2009-04-17 15:45:46 +0000
@@ -4502,17 +4502,17 @@ static int ndbcluster_update_apply_statu
   // log_name
   char tmp_buf[FN_REFLEN];
   ndb_pack_varchar(ndbtab->getColumn(2u), tmp_buf,
-                   active_mi->rli.group_master_log_name,
-                   strlen(active_mi->rli.group_master_log_name));
+                   active_mi->rli->group_master_log_name,
+                   strlen(active_mi->rli->group_master_log_name));
   r|= op->setValue(2u, tmp_buf);
   DBUG_ASSERT(r == 0);
   // start_pos
-  r|= op->setValue(3u, (Uint64)active_mi->rli.group_master_log_pos);
+  r|= op->setValue(3u, (Uint64)active_mi->rli->group_master_log_pos);
   DBUG_ASSERT(r == 0);
   // end_pos
-  r|= op->setValue(4u, (Uint64)active_mi->rli.group_master_log_pos + 
-                   ((Uint64)active_mi->rli.future_event_relay_log_pos -
-                    (Uint64)active_mi->rli.group_relay_log_pos));
+  r|= op->setValue(4u, (Uint64)active_mi->rli->group_master_log_pos + 
+                   ((Uint64)active_mi->rli->future_event_relay_log_pos -
+                    (Uint64)active_mi->rli->group_relay_log_pos));
   DBUG_ASSERT(r == 0);
   return 0;
 }

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2009-04-14 21:37:16 +0000
+++ b/sql/item_func.cc	2009-04-17 15:45:46 +0000
@@ -3399,7 +3399,7 @@ longlong Item_master_pos_wait::val_int()
 #ifdef HAVE_REPLICATION
   longlong pos = (ulong)args[1]->val_int();
   longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
-  if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
+  if ((event_count = active_mi->rli->wait_for_pos(thd, log_name, pos, timeout)) == -2)
   {
     null_value = 1;
     event_count=0;

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2009-04-14 21:37:16 +0000
+++ b/sql/log.cc	2009-04-17 15:45:46 +0000
@@ -4795,7 +4795,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay
   }
 
   /* Store where we are in the new file for the execution thread */
-  flush_relay_log_info(rli);
+  rli->flush_info();
 
   DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_ABORT(););
 

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2009-04-13 16:15:22 +0000
+++ b/sql/log_event.cc	2009-04-17 15:45:46 +0000
@@ -4816,7 +4816,7 @@ int Rotate_log_event::do_update_pos(Rela
                         rli->group_master_log_name,
                         (ulong) rli->group_master_log_pos));
     MYSQL_MUTEX_UNLOCK(&rli->data_lock);
-    flush_relay_log_info(rli);
+    rli->flush_info();
     
     /*
       Reset thd->options and sql_mode etc, because this could be the signal of
@@ -5805,7 +5805,7 @@ int Stop_log_event::do_update_pos(Relay_
   else
   {
     rli->inc_group_relay_log_pos(0);
-    flush_relay_log_info(rli);
+    rli->flush_info();
   }
   return 0;
 }
@@ -7139,7 +7139,7 @@ int Rows_log_event::do_apply_event(Relay
     do_apply_event(). We still check here to prevent future coding
     errors.
   */
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /*
     If there is no locks taken, this is the first binrow event seen
@@ -8008,7 +8008,7 @@ int Table_map_log_event::do_apply_event(
   size_t dummy_len;
   void *memory;
   DBUG_ENTER("Table_map_log_event::do_apply_event(Relay_log_info*)");
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /* Step the query id to mark what columns that are actually used. */
   MYSQL_MUTEX_LOCK(&LOCK_thread_count);
@@ -8037,7 +8037,7 @@ int Table_map_log_event::do_apply_event(
 
   int error= 0;
 
-  if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
+  if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
       (!rpl_filter->db_ok(table_list->db) ||
        (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
   {
@@ -8401,7 +8401,10 @@ Rows_log_event::write_row(const Relay_lo
      values should be checked. Maybe these two flags can be combined.
   */
   if ((error= prepare_record(table, &m_cols, m_width,
-                             table->file->ht->db_type != DB_TYPE_NDBCLUSTER)))
+                             table->file->ht->db_type != DB_TYPE_NDBCLUSTER,
+                             (rli->info_thd->variables.sql_mode &
+                              (MODE_STRICT_TRANS_TABLES |
+                               MODE_STRICT_ALL_TABLES)))))
     DBUG_RETURN(error);
   
   /* unpack row into table->record[0] */

=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc	2009-03-17 20:07:27 +0000
+++ b/sql/log_event_old.cc	2009-04-13 13:24:28 +0000
@@ -43,7 +43,7 @@ Old_rows_log_event::do_apply_event(Old_r
     do_apply_event(). We still check here to prevent future coding
     errors.
   */
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /*
     If there is no locks taken, this is the first binrow event seen
@@ -1465,7 +1465,7 @@ int Old_rows_log_event::do_apply_event(R
     do_apply_event(). We still check here to prevent future coding
     errors.
   */
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /*
     If there is no locks taken, this is the first binrow event seen

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2009-04-13 16:15:22 +0000
+++ b/sql/mysql_priv.h	2009-04-17 15:45:46 +0000
@@ -2117,11 +2117,11 @@ extern PSI_mutex_key key_LOCK_scheduler_
 extern PSI_cond_key key_Event_scheduler_COND_state;
 extern PSI_mutex_key key_LOCK_event_metadata;
 extern PSI_mutex_key key_hash_filo_lock;
-extern PSI_mutex_key key_MI_run_lock;
-extern PSI_mutex_key key_MI_data_lock;
-extern PSI_cond_key key_MI_data_cond;
-extern PSI_cond_key key_MI_start_cond;
-extern PSI_cond_key key_MI_stop_cond;
+extern PSI_mutex_key key_mutex_rpl_info_run_lock;
+extern PSI_mutex_key key_mutex_rpl_info_data_lock;
+extern PSI_cond_key key_cond_rpl_info_data_cond;
+extern PSI_cond_key key_cond_rpl_info_start_cond;
+extern PSI_cond_key key_cond_rpl_info_stop_cond;
 extern PSI_mutex_key key_RLI_run_lock;
 extern PSI_mutex_key key_RLI_data_lock;
 extern PSI_mutex_key key_RLI_log_space_lock;
@@ -2160,6 +2160,9 @@ extern PSI_mutex_key key_mutex_THR_LOCK_
 extern PSI_cond_key key_cond_COND_BML;
 extern PSI_cond_key key_cond_COND_BML_registered;
 extern PSI_cond_key key_cond_COND_BML_release;
+extern PSI_mutex_key key_mutex_slave_reporting_capability_err_lock;
+extern PSI_mutex_key key_mutex_relay_log_info_log_space_lock;
+extern PSI_cond_key key_cond_relay_log_info_log_space_cond;
 
 #ifdef HAVE_OPENSSL
 extern PSI_mutex_key key_LOCK_des_key_file;

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2009-04-15 04:34:51 +0000
+++ b/sql/mysqld.cc	2009-04-17 15:45:46 +0000
@@ -7462,7 +7462,7 @@ static int show_slave_running(THD *thd,
   var->value= buff;
   *((my_bool *)buff)= (my_bool) (active_mi && 
                                  active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
-                                 active_mi->rli.slave_running);
+                                 active_mi->rli->slave_running);
   MYSQL_MUTEX_UNLOCK(&LOCK_active_mi);
   return 0;
 }
@@ -7478,9 +7478,9 @@ static int show_slave_retried_trans(THD
   {
     var->type= SHOW_LONG;
     var->value= buff;
-    MYSQL_MUTEX_LOCK(&active_mi->rli.data_lock);
-    *((long *)buff)= (long)active_mi->rli.retried_trans;
-    MYSQL_MUTEX_UNLOCK(&active_mi->rli.data_lock);
+    MYSQL_MUTEX_LOCK(&active_mi->rli->data_lock);
+    *((long *)buff)= (long)active_mi->rli->retried_trans;
+    MYSQL_MUTEX_UNLOCK(&active_mi->rli->data_lock);
   }
   else
     var->type= SHOW_UNDEF;
@@ -7495,9 +7495,9 @@ static int show_slave_received_heartbeat
   {
     var->type= SHOW_LONGLONG;
     var->value= buff;
-    MYSQL_MUTEX_LOCK(&active_mi->rli.data_lock);
+    MYSQL_MUTEX_LOCK(&active_mi->rli->data_lock);
     *((longlong *)buff)= active_mi->received_heartbeats;
-    MYSQL_MUTEX_UNLOCK(&active_mi->rli.data_lock);
+    MYSQL_MUTEX_UNLOCK(&active_mi->rli->data_lock);
   }
   else
     var->type= SHOW_UNDEF;
@@ -9434,8 +9434,8 @@ PSI_mutex_key key_structure_guard_mutex;
 PSI_mutex_key key_RLI_run_lock;
 PSI_mutex_key key_RLI_data_lock;
 PSI_mutex_key key_RLI_log_space_lock;
-PSI_mutex_key key_MI_run_lock;
-PSI_mutex_key key_MI_data_lock;
+PSI_mutex_key key_mutex_rpl_info_run_lock;
+PSI_mutex_key key_mutex_rpl_info_data_lock;
 PSI_mutex_key key_LOCK_scheduler_state;
 PSI_mutex_key key_LOCK_event_metadata;
 PSI_mutex_key key_LOCK_event_queue;
@@ -9459,6 +9459,8 @@ PSI_mutex_key key_mutex_hadata;
 PSI_mutex_key key_mutex_THR_LOCK_BML;
 PSI_mutex_key key_mutex_THR_LOCK_BML_active;
 PSI_mutex_key key_mutex_THR_LOCK_BML_get;
+PSI_mutex_key key_mutex_slave_reporting_capability_err_lock;
+PSI_mutex_key key_mutex_relay_log_info_log_space_lock;
 
 static PSI_mutex_info all_server_mutexes[]=
 {
@@ -9550,10 +9552,10 @@ static PSI_mutex_info all_server_mutexes
    "RLI_data_lock", PSI_FLAG_GLOBAL},
  { & key_RLI_log_space_lock,
    "RLI_log_space_lock", PSI_FLAG_GLOBAL},
- { & key_MI_run_lock,
-   "MI_run_lock", PSI_FLAG_GLOBAL},
- { & key_MI_data_lock,
-   "MI_data_lock", PSI_FLAG_GLOBAL},
+ { & key_mutex_rpl_info_run_lock,
+   "Rpl_info::run_lock", PSI_FLAG_GLOBAL},
+ { & key_mutex_rpl_info_data_lock,
+   "Rpl_info::data_lock", PSI_FLAG_GLOBAL},
  { & key_LOCK_scheduler_state,
    "LOCK_scheduler_state", PSI_FLAG_GLOBAL},
  { & key_LOCK_event_metadata,
@@ -9599,7 +9601,11 @@ static PSI_mutex_info all_server_mutexes
  { & key_mutex_THR_LOCK_BML_active,
    "BML_class::THR_LOCK_BML_active", PSI_FLAG_GLOBAL},
  { & key_mutex_THR_LOCK_BML_get,
-   "BML_class::THR_LOCK_BML_get", PSI_FLAG_GLOBAL}
+   "BML_class::THR_LOCK_BML_get", PSI_FLAG_GLOBAL},
+ { & key_mutex_slave_reporting_capability_err_lock,
+   "Slave_reporting_capability::err_lock", 0},
+ { & key_mutex_relay_log_info_log_space_lock,
+   "Relay_log_info::log_space_lock", 0}
 };
 
 PSI_rwlock_key key_LOCK_grant;
@@ -9650,9 +9656,9 @@ PSI_cond_key key_RLI_data_cond;
 PSI_cond_key key_RLI_start_cond;
 PSI_cond_key key_RLI_stop_cond;
 PSI_cond_key key_RLI_log_space_cond;
-PSI_cond_key key_MI_data_cond;
-PSI_cond_key key_MI_start_cond;
-PSI_cond_key key_MI_stop_cond;
+PSI_cond_key key_cond_rpl_info_data_cond;
+PSI_cond_key key_cond_rpl_info_start_cond;
+PSI_cond_key key_cond_rpl_info_stop_cond;
 PSI_cond_key key_Event_scheduler_COND_state;
 PSI_cond_key key_COND_queue_state;
 PSI_cond_key key_COND_thread_wait;
@@ -9666,6 +9672,7 @@ PSI_cond_key key_Delayed_insert_cond_cli
 PSI_cond_key key_cond_COND_BML;
 PSI_cond_key key_cond_COND_BML_registered;
 PSI_cond_key key_cond_COND_BML_release;
+PSI_cond_key key_cond_relay_log_info_log_space_cond;
 
 static PSI_cond_info all_server_conds[]=
 {
@@ -9713,12 +9720,12 @@ static PSI_cond_info all_server_conds[]=
    "RLI_stop_cond", PSI_FLAG_GLOBAL},
   { & key_RLI_log_space_cond,
    "RLI_log_space_cond", PSI_FLAG_GLOBAL},
-  { & key_MI_data_cond,
-   "MI_data_cond", PSI_FLAG_GLOBAL},
-  { & key_MI_start_cond,
-   "MI_start_cond", PSI_FLAG_GLOBAL},
-  { & key_MI_stop_cond,
-   "MI_stop_cond", PSI_FLAG_GLOBAL},
+  { & key_cond_rpl_info_data_cond,
+   "Rpl_info::data_cond", PSI_FLAG_GLOBAL},
+  { & key_cond_rpl_info_start_cond,
+   "Rpl_info::start_cond", PSI_FLAG_GLOBAL},
+  { & key_cond_rpl_info_stop_cond,
+   "Rpl_info::stop_cond", PSI_FLAG_GLOBAL},
   { & key_Event_scheduler_COND_state,
    "Event_scheduler::COND_state", PSI_FLAG_GLOBAL},
   { & key_COND_queue_state,
@@ -9744,7 +9751,9 @@ static PSI_cond_info all_server_conds[]=
   { & key_cond_COND_BML_registered,
    "BML_class::COND_BML_registered", PSI_FLAG_GLOBAL},
   { & key_cond_COND_BML_release,
-   "BML_class::COND_BML_release", PSI_FLAG_GLOBAL}
+   "BML_class::COND_BML_release", PSI_FLAG_GLOBAL},
+  { & key_cond_relay_log_info_log_space_cond,
+   "Relay_log_info::log_space_cond", 0}
 };
 
 PSI_thread_key key_thread_main;

=== added file 'sql/rpl_info.cc'
--- a/sql/rpl_info.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info.cc	2009-04-17 15:45:46 +0000
@@ -0,0 +1,63 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <my_global.h>
+#include "mysql_priv.h"
+#include "rpl_info.h"
+
+#ifdef HAVE_REPLICATION
+
+Rpl_info::Rpl_info(const char* type)
+    :Slave_reporting_capability(type),
+    info_thd(0), inited(0), abort_slave(0),
+    slave_running(0), slave_run_id(0)
+{
+  /*
+    We have to use MYF_NO_DEADLOCK_DETECTION because mysqld doesn't
+    lock run_lock and data_lock consistently.
+    Should be fixed as this can easily lead to deadlocks
+  */
+  MYSQL_MUTEX_INIT_EXTRA(key_mutex_rpl_info_run_lock,
+                         &run_lock, MY_MUTEX_INIT_FAST,
+                        "Rpl_info::run_lock", MYF_NO_DEADLOCK_DETECTION);
+  MYSQL_MUTEX_INIT_EXTRA(key_mutex_rpl_info_data_lock,
+                         &data_lock, MY_MUTEX_INIT_FAST,
+                        "Rpl_info::data_lock", MYF_NO_DEADLOCK_DETECTION);
+  MYSQL_COND_INIT(key_cond_rpl_info_data_cond, &data_cond, NULL);
+  MYSQL_COND_INIT(key_cond_rpl_info_start_cond, &start_cond, NULL);
+  MYSQL_COND_INIT(key_cond_rpl_info_stop_cond, &stop_cond, NULL);
+
+#ifdef SAFE_MUTEX
+  /* Define mutex order for locks to find wrong lock usage */
+  MYSQL_MUTEX_LOCK(&data_lock);
+  MYSQL_MUTEX_LOCK(&run_lock);
+  MYSQL_MUTEX_UNLOCK(&run_lock);
+  MYSQL_MUTEX_UNLOCK(&data_lock);
+#endif
+}
+
+Rpl_info::~Rpl_info()
+{
+  DBUG_ENTER("Rpl_info::~Rpl_info");
+
+  MYSQL_MUTEX_DESTROY(&run_lock);
+  MYSQL_MUTEX_DESTROY(&data_lock);
+  MYSQL_COND_DESTROY(&data_cond);
+  MYSQL_COND_DESTROY(&start_cond);
+  MYSQL_COND_DESTROY(&stop_cond);
+
+  DBUG_VOID_RETURN;
+}
+#endif /* HAVE_REPLICATION */

=== added file 'sql/rpl_info.h'
--- a/sql/rpl_info.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info.h	2009-04-17 15:45:46 +0000
@@ -0,0 +1,81 @@
+/* Copyright (C) 2005 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_INFO_H
+#define RPL_INFO_H
+
+#include "rpl_reporting.h"
+
+class Rpl_info : public Slave_reporting_capability
+{
+public:
+  /*
+    standard lock acquisition order to avoid deadlocks:
+    run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
+  */
+  mysql_mutex_t data_lock,run_lock;
+  /*
+    start_cond is broadcast when SQL thread is started
+    stop_cond - when stopped
+    data_cond - when data protected by data_lock changes
+  */
+  mysql_cond_t data_cond,start_cond,stop_cond;
+
+  THD *info_thd; 
+
+  bool inited;
+  volatile bool abort_slave;
+  volatile uint slave_running;
+  volatile ulong slave_run_id;
+
+#ifndef DBUG_OFF
+  int events_until_exit;
+#endif
+
+  inline int check()
+  {
+    return do_check();
+  }
+  
+  inline int flush_info()
+  {
+    return do_flush_info();
+  }
+  
+  inline int reset_info()
+  {
+    return do_reset_info();
+  }
+  
+  inline void end_info()
+  {
+    do_end_info();
+  }
+
+  Rpl_info(const char* type);
+  virtual ~Rpl_info();
+
+private:
+  virtual int do_check()= 0;
+  virtual int do_init_info()= 0;
+  virtual int do_flush_info()= 0;
+  virtual void do_end_info()= 0;
+  virtual int do_reset_info()= 0;
+
+  Rpl_info& operator=(const Rpl_info& info);
+  Rpl_info(const Rpl_info& info);
+};
+
+#endif /* RPL_INFO_H */

=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc	2009-04-14 21:37:16 +0000
+++ b/sql/rpl_mi.cc	2009-04-17 15:45:46 +0000
@@ -21,60 +21,22 @@
 
 #ifdef HAVE_REPLICATION
 
-#define DEFAULT_CONNECT_RETRY 60
-
-// Defined in slave.cc
-int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
-int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-			  const char *default_val);
-int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
-int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f);
-
-Master_info::Master_info(bool is_slave_recovery)
-  :Slave_reporting_capability("I/O"),
-   ssl(0), ssl_verify_server_cert(0), fd(-1),  io_thd(0), 
-   rli(is_slave_recovery), port(MYSQL_PORT),
-   connect_retry(DEFAULT_CONNECT_RETRY), heartbeat_period(0),
-   received_heartbeats(0), inited(0), master_id(0),
-   abort_slave(0), slave_running(0), slave_run_id(0),
-   sync_counter(0)
+Master_info::Master_info()
+   :Rpl_info("I/O"),
+   ssl(0), ssl_verify_server_cert(0),
+   port(MYSQL_PORT), connect_retry(DEFAULT_CONNECT_RETRY), 
+   heartbeat_period(0), received_heartbeats(0),
+   master_id(0)
 {
   host[0] = 0; user[0] = 0; password[0] = 0;
   ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
   ssl_cipher[0]= 0; ssl_key[0]= 0;
   my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16);
-
-  bzero((char*) &file, sizeof(file));
-  /*
-    We have to use MYF_NO_DEADLOCK_DETECTION because mysqld doesn't
-    lock run_lock and data_lock consistently.
-    Should be fixed as this can easily lead to deadlocks
-  */
-  MYSQL_MUTEX_INIT_EXTRA(key_MI_run_lock, &run_lock, MY_MUTEX_INIT_FAST,
-                         "Master_info::run_lock", MYF_NO_DEADLOCK_DETECTION);
-  MYSQL_MUTEX_INIT_EXTRA(key_MI_data_lock, &data_lock, MY_MUTEX_INIT_FAST,
-                         "Master_info::data_lock", MYF_NO_DEADLOCK_DETECTION);
-  MYSQL_COND_INIT(key_MI_data_cond, &data_cond, NULL);
-  MYSQL_COND_INIT(key_MI_start_cond, &start_cond, NULL);
-  MYSQL_COND_INIT(key_MI_stop_cond, &stop_cond, NULL);
-
-#ifdef SAFE_MUTEX
-  /* Define mutex order for locks to find wrong lock usage */
-  MYSQL_MUTEX_LOCK(&data_lock);
-  MYSQL_MUTEX_LOCK(&run_lock);
-  MYSQL_MUTEX_UNLOCK(&run_lock);
-  MYSQL_MUTEX_UNLOCK(&data_lock);
-#endif
 }
 
 Master_info::~Master_info()
 {
   delete_dynamic(&ignore_server_ids);
-  MYSQL_MUTEX_DESTROY(&run_lock);
-  MYSQL_MUTEX_DESTROY(&data_lock);
-  MYSQL_COND_DESTROY(&data_cond);
-  MYSQL_COND_DESTROY(&start_cond);
-  MYSQL_COND_DESTROY(&stop_cond);
 }
 
 /**
@@ -134,389 +96,25 @@ void init_master_log_pos(Master_info* mi
   DBUG_VOID_RETURN;
 }
 
-
-enum {
-  LINES_IN_MASTER_INFO_WITH_SSL= 14,
-
-  /* 5.1.16 added value of master_ssl_verify_server_cert */
-  LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT= 15,
-
-  /* 6.0 added value of master_heartbeat_period */
-  LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16,
-
-  /* 6.0 added value of master_ignore_server_id */
-  LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 17,
-
-  /* Number of lines currently used when saving master info file */
-  LINES_IN_MASTER_INFO= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS
-};
-
-
-int init_master_info(Master_info* mi, const char* master_info_fname,
-                     const char* slave_info_fname,
-                     bool abort_if_no_master_info_file,
-                     int thread_mask)
+int Master_info::init_info(bool abort_if_no_info)
 {
-  int fd,error;
-  char fname[FN_REFLEN+128];
-  DBUG_ENTER("init_master_info");
-
-  if (mi->inited)
-  {
-    /*
-      We have to reset read position of relay-log-bin as we may have
-      already been reading from 'hotlog' when the slave was stopped
-      last time. If this case pos_in_file would be set and we would
-      get a crash when trying to read the signature for the binary
-      relay log.
-
-      We only rewind the read position if we are starting the SQL
-      thread. The handle_slave_sql thread assumes that the read
-      position is at the beginning of the file, and will read the
-      "signature" and then fast-forward to the last position read.
-    */
-    if (thread_mask & SLAVE_SQL)
-    {
-      my_b_seek(mi->rli.cur_log, (my_off_t) 0);
-    }
-    DBUG_RETURN(0);
-  }
-
-  mi->mysql=0;
-  mi->file_id=1;
-  fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
-
-  /*
-    We need a mutex while we are changing master info parameters to
-    keep other threads from reading bogus info
-  */
-
-  MYSQL_MUTEX_LOCK(&mi->data_lock);
-  fd = mi->fd;
-
-  /* does master.info exist ? */
+  int error= 0;
 
-  if (access(fname,F_OK))
-  {
-    if (abort_if_no_master_info_file)
-    {
-      MYSQL_MUTEX_UNLOCK(&mi->data_lock);
-      DBUG_RETURN(0);
-    }
-    /*
-      if someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (fd >= 0)
-      MYSQL_CLOSE(fd, MYF(MY_WME));
-    if ((fd= MYSQL_OPEN(key_file_master_info, fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-    {
-      sql_print_error("Failed to create a new master info file (\
-file '%s', errno %d)", fname, my_errno);
-      goto err;
-    }
-    if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
-                      MYF(MY_WME)))
-    {
-      sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
-      goto err;
-    }
-
-    mi->fd = fd;
-    init_master_log_pos(mi);
-
-  }
-  else // file exists
-  {
-    if (fd >= 0)
-      reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
-    else
-    {
-      if ((fd= MYSQL_OPEN(key_file_master_info, fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-      {
-        sql_print_error("Failed to open the existing master info file (\
-file '%s', errno %d)", fname, my_errno);
-        goto err;
-      }
-      if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
-                        0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
-        goto err;
-      }
-    }
-
-    mi->fd = fd;
-    int port, connect_retry, master_log_pos, lines;
-    int ssl= 0, ssl_verify_server_cert= 0;
-    float master_heartbeat_period= 0.0;
-    char *first_non_digit;
-
-    /*
-       Starting from 4.1.x master.info has new format. Now its
-       first line contains number of lines in file. By reading this
-       number we will be always distinguish to which version our
-       master.info corresponds to. We can't simply count lines in
-       file since versions before 4.1.x could generate files with more
-       lines than needed.
-       If first line doesn't contain a number or contain number less than
-       LINES_IN_MASTER_INFO_WITH_SSL then such file is treated like file
-       from pre 4.1.1 version.
-       There is no ambiguity when reading an old master.info, as before
-       4.1.1, the first line contained the binlog's name, which is either
-       empty or has an extension (contains a '.'), so can't be confused
-       with an integer.
-
-       So we're just reading first line and trying to figure which version
-       is this.
-    */
-
-    /*
-       The first row is temporarily stored in mi->master_log_name,
-       if it is line count and not binlog name (new format) it will be
-       overwritten by the second row later.
-    */
-    if (init_strvar_from_file(mi->master_log_name,
-                              sizeof(mi->master_log_name), &mi->file,
-                              ""))
-      goto errwithmsg;
-
-    lines= strtoul(mi->master_log_name, &first_non_digit, 10);
-
-    if (mi->master_log_name[0]!='\0' &&
-        *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
-    {
-      /* Seems to be new format => read master log name from next line */
-      if (init_strvar_from_file(mi->master_log_name,
-            sizeof(mi->master_log_name), &mi->file, ""))
-        goto errwithmsg;
-    }
-    else
-      lines= 7;
-
-    if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
-        init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, 0) ||
-        init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, "test") ||
-        init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
-                              &mi->file, 0 ) ||
-        init_intvar_from_file(&port, &mi->file, MYSQL_PORT) ||
-        init_intvar_from_file(&connect_retry, &mi->file, DEFAULT_CONNECT_RETRY))
-      goto errwithmsg;
-
-    /*
-      If file has ssl part use it even if we have server without
-      SSL support. But these option will be ignored later when
-      slave will try connect to master, so in this case warning
-      is printed.
-    */
-    if (lines >= LINES_IN_MASTER_INFO_WITH_SSL)
-    {
-      if (init_intvar_from_file(&ssl, &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
-                               &mi->file, 0))
-      goto errwithmsg;
-
-      /*
-        Starting from 5.1.16 ssl_verify_server_cert might be
-        in the file
-      */
-      if (lines >= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT &&
-          init_intvar_from_file(&ssl_verify_server_cert, &mi->file, 0))
-        goto errwithmsg;
-      /*
-        Starting from 6.0 master_heartbeat_period might be
-        in the file
-      */
-      if (lines >= LINE_FOR_MASTER_HEARTBEAT_PERIOD &&
-          init_floatvar_from_file(&master_heartbeat_period, &mi->file, 0.0))
-        goto errwithmsg;
-      /*
-        Starting from 6.0 list of server_id of ignorable servers might be
-        in the file
-      */
-      if (lines >= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS &&
-          init_dynarray_intvar_from_file(&mi->ignore_server_ids, &mi->file))
-      {
-        sql_print_error("Failed to initialize master info ignore_server_ids");
-        goto errwithmsg;
-      }
-
-    }
-
-#ifndef HAVE_OPENSSL
-    if (ssl)
-      sql_print_warning("SSL information in the master info file "
-                      "('%s') are ignored because this MySQL slave was "
-                      "compiled without SSL support.", fname);
-#endif /* HAVE_OPENSSL */
-
-    /*
-      This has to be handled here as init_intvar_from_file can't handle
-      my_off_t types
-    */
-    mi->master_log_pos= (my_off_t) master_log_pos;
-    mi->port= (uint) port;
-    mi->connect_retry= (uint) connect_retry;
-    mi->ssl= (my_bool) ssl;
-    mi->ssl_verify_server_cert= ssl_verify_server_cert;
-    mi->heartbeat_period= master_heartbeat_period;
-  }
-  DBUG_PRINT("master_info",("log_file_name: %s  position: %ld",
-                            mi->master_log_name,
-                            (ulong) mi->master_log_pos));
-
-  mi->rli.mi = mi;
-  if (init_relay_log_info(&mi->rli, slave_info_fname))
-    goto err;
-
-  mi->inited = 1;
-  mi->rli.is_relay_log_recovery= FALSE;
-  // now change cache READ -> WRITE - must do this before flush_master_info
-  reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
-  if ((error=test(flush_master_info(mi, 1))))
-    sql_print_error("Failed to flush master info file");
-  MYSQL_MUTEX_UNLOCK(&mi->data_lock);
-  DBUG_RETURN(error);
-
-errwithmsg:
-  sql_print_error("Error reading master configuration");
-
-err:
-  if (fd >= 0)
-  {
-    MYSQL_CLOSE(fd, MYF(0));
-    end_io_cache(&mi->file);
-  }
-  mi->fd= -1;
-  MYSQL_MUTEX_UNLOCK(&mi->data_lock);
-  DBUG_RETURN(1);
-}
+  DBUG_ENTER("Master_info::init_info");
 
+  if (inited)
+    DBUG_RETURN(error);
 
-/*
-  RETURN
-     2 - flush relay log failed
-     1 - flush master info failed
-     0 - all ok
-*/
-int flush_master_info(Master_info* mi, bool flush_relay_log_cache)
-{
-  IO_CACHE* file = &mi->file;
-  char lbuf[22];
-  int err= 0;
-
-  DBUG_ENTER("flush_master_info");
-  DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
-
-  /*
-    Flush the relay log to disk. If we don't do it, then the relay log while
-    have some part (its last kilobytes) in memory only, so if the slave server
-    dies now, with, say, from master's position 100 to 150 in memory only (not
-    on disk), and with position 150 in master.info, then when the slave
-    restarts, the I/O thread will fetch binlogs from 150, so in the relay log
-    we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
-    SQL thread will jump from 100 to 150, and replication will silently break.
+  if (!(abort_if_no_info && do_check()) &&
+      !(error= do_init_info()))
+    inited= 1;
 
-    When we come to this place in code, relay log may or not be initialized;
-    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
-  */
-  if (flush_relay_log_cache)
-  {
-    IO_CACHE *log_file= mi->rli.relay_log.get_log_file();
-    if (flush_io_cache(log_file))
-      DBUG_RETURN(2);
-  }
-
-  /*
-    We flushed the relay log BEFORE the master.info file, because if we crash
-    now, we will get a duplicate event in the relay log at restart. If we
-    flushed in the other order, we would get a hole in the relay log.
-    And duplicate is better than hole (with a duplicate, in later versions we
-    can add detection and scrap one event; with a hole there's nothing we can
-    do).
-  */
-
-  /*
-     In certain cases this code may create master.info files that seems
-     corrupted, because of extra lines filled with garbage in the end
-     file (this happens if new contents take less space than previous
-     contents of file). But because of number of lines in the first line
-     of file we don't care about this garbage.
-  */
-  char heartbeat_buf[sizeof(mi->heartbeat_period) * 4]; // buffer to suffice always
-  my_sprintf(heartbeat_buf, (heartbeat_buf, "%.3f", mi->heartbeat_period));
-  /*
-    produce a line listing the total number and all the ignored server_id:s
-  */
-  char* ignore_server_ids_buf;
-  {
-    ignore_server_ids_buf=
-      (char *) my_malloc((sizeof(::server_id) * 3 + 1) *
-                         (1 + mi->ignore_server_ids.elements), MYF(MY_WME));
-    if (!ignore_server_ids_buf)
-      DBUG_RETURN(1);
-    for (ulong i= 0, cur_len= my_sprintf(ignore_server_ids_buf,
-                                         (ignore_server_ids_buf, "%u",
-                                          mi->ignore_server_ids.elements));
-         i < mi->ignore_server_ids.elements; i++)
-    {
-      ulong s_id;
-      get_dynamic(&mi->ignore_server_ids, (uchar*) &s_id, i);
-      cur_len +=my_sprintf(ignore_server_ids_buf + cur_len,
-                           (ignore_server_ids_buf + cur_len,
-                            " %lu", s_id));
-    }
-  }
-  my_b_seek(file, 0L);
-  my_b_printf(file,
-              "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n",
-              LINES_IN_MASTER_INFO,
-              mi->master_log_name, llstr(mi->master_log_pos, lbuf),
-              mi->host, mi->user,
-              mi->password, mi->port, mi->connect_retry,
-              (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
-              mi->ssl_cipher, mi->ssl_key, mi->ssl_verify_server_cert,
-              heartbeat_buf,
-              ignore_server_ids_buf);
-  my_free(ignore_server_ids_buf, MYF(0));
-  err= flush_io_cache(file);
-  if (sync_masterinfo_period && !err && 
-      ++(mi->sync_counter) >= sync_masterinfo_period)
-  {
-    err= MYSQL_SYNC(mi->fd, MYF(MY_WME));
-    mi->sync_counter= 0;
-  }
-  DBUG_RETURN(-err);
+  DBUG_RETURN (error);
 }
 
-
-void end_master_info(Master_info* mi)
+void Master_info::inject_relay_log_info(Relay_log_info* info)
 {
-  DBUG_ENTER("end_master_info");
-
-  if (!mi->inited)
-    DBUG_VOID_RETURN;
-  end_relay_log_info(&mi->rli);
-  if (mi->fd >= 0)
-  {
-    end_io_cache(&mi->file);
-    (void) MYSQL_CLOSE(mi->fd, MYF(MY_WME));
-    mi->fd = -1;
-  }
-  mi->inited = 0;
-
-  DBUG_VOID_RETURN;
+  rli= info;
 }
 
-
 #endif /* HAVE_REPLICATION */

=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h	2009-03-26 15:35:49 +0000
+++ b/sql/rpl_mi.h	2009-04-17 15:45:46 +0000
@@ -19,9 +19,9 @@
 #ifdef HAVE_REPLICATION
 
 #include "rpl_rli.h"
-#include "rpl_reporting.h"
 #include "my_sys.h"
 
+#define DEFAULT_CONNECT_RETRY 60
 
 /*****************************************************************************
 
@@ -33,12 +33,12 @@
     - current master log offset
     - misc control variables
 
-  Master_info is initialized once from the master.info file if such
+  Master_info is initialized once from the master.info repository if such
   exists. Otherwise, data members corresponding to master.info fields
   are initialized with defaults specified by master-* options. The
-  initialization is done through init_master_info() call.
+  initialization is done through init_info() call.
 
-  The format of master.info file:
+  Logically, the format of master.info repository is presented as follows:
 
   log_name
   log_pos
@@ -48,19 +48,19 @@
   master_port
   master_connect_retry
 
-  To write out the contents of master.info file to disk ( needed every
-  time we read and queue data from the master ), a call to
-  flush_master_info() is required.
+  To write out the contents of master.info to disk a call to flush_info() 
+  is required. Currently, it is needed every time we read and queue data 
+  from the master.
 
-  To clean up, call end_master_info()
+  To clean up, call end_info()
 
 *****************************************************************************/
 
-class Master_info : public Slave_reporting_capability
+class Master_info : public Rpl_info
 {
  public:
-  Master_info(bool is_slave_recovery);
-  ~Master_info();
+  Master_info();
+  virtual ~Master_info();
   bool shall_ignore_server_id(ulong s_id);
 
   /* the variables below are needed because we can change masters on the fly */
@@ -74,28 +74,16 @@ class Master_info : public Slave_reporti
   my_bool ssl_verify_server_cert;
 
   my_off_t master_log_pos;
-  File fd; // we keep the file open, so we need to remember the file pointer
-  IO_CACHE file;
 
-  mysql_mutex_t data_lock,run_lock;
-  mysql_cond_t data_cond,start_cond,stop_cond;
-  THD *io_thd;
   MYSQL* mysql;
   uint32 file_id;				/* for 3.23 load data infile */
-  Relay_log_info rli;
+  Relay_log_info *rli;
   uint port;
   uint connect_retry;
   float heartbeat_period;         // interface with CHANGE MASTER or master.info
   ulonglong received_heartbeats;  // counter of received heartbeat events
   DYNAMIC_ARRAY ignore_server_ids;
-#ifndef DBUG_OFF
-  int events_till_disconnect;
-#endif
-  bool inited;
   ulong master_id;
-  volatile bool abort_slave;
-  volatile uint slave_running;
-  volatile ulong slave_run_id;
   /*
      The difference in seconds between the clock of the master and the clock of
      the slave (second - first). It must be signed as it may be <0 or >0.
@@ -107,21 +95,22 @@ class Master_info : public Slave_reporti
   */
   long clock_diff_with_master;
 
-  /*
-   * Keeps track of the number of events before fsyncing.
-   * The option --sync-master-info determines how many
-   * events should happen before fsyncing.
-   */
-  uint sync_counter;
+  int init_info(bool abort_if_no_info);
+  void inject_relay_log_info(Relay_log_info *info);
+
+private:
+  virtual int do_check()= 0;
+  virtual int do_init_info()= 0;
+  virtual void do_end_info()= 0;
+  virtual int do_flush_info()= 0;
+  virtual int do_reset_info()= 0;
+
+  Master_info& operator=(const Master_info& info);
+  Master_info(const Master_info& info);
 };
 
 void init_master_log_pos(Master_info* mi);
-int init_master_info(Master_info* mi, const char* master_info_fname,
-		     const char* slave_info_fname,
-		     bool abort_if_no_master_info_file,
-		     int thread_mask);
-void end_master_info(Master_info* mi);
-int flush_master_info(Master_info* mi, bool flush_relay_log_cache);
+
 int server_id_cmp(ulong *id1, ulong *id2);
 
 #endif /* HAVE_REPLICATION */

=== added file 'sql/rpl_mi_file.cc'
--- a/sql/rpl_mi_file.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_mi_file.cc	2009-04-02 16:14:14 +0000
@@ -0,0 +1,364 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <my_global.h> // For HAVE_REPLICATION
+#include "mysql_priv.h"
+#include <my_dir.h>
+
+#include <rpl_mi_file.h>
+
+#ifdef HAVE_REPLICATION
+
+// Defined in slave.cc
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+			  const char *default_val);
+int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
+int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f);
+
+enum {
+  LINES_IN_MASTER_INFO_WITH_SSL= 14,
+
+  /* 5.1.16 added value of master_ssl_verify_server_cert */
+  LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT= 15,
+
+  /* 6.0 added value of master_heartbeat_period */
+  LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16,
+
+  /* 6.0 added value of master_ignore_server_id */
+  LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 17,
+
+  /* Number of lines currently used when saving master info file */
+  LINES_IN_MASTER_INFO= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS
+};
+
+Master_info_file::Master_info_file(const char* param_info_fname)
+  :info_fname(param_info_fname), info_fd(-1),
+  sync_counter(0)
+{
+  DBUG_ENTER("Master_info_file::Master_info_file");
+
+  bzero((char*) &info_file, sizeof(info_file));
+
+  DBUG_VOID_RETURN;
+}
+
+int Master_info_file::do_check()
+{
+  char fname[FN_REFLEN+128];
+  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+
+  return (access(fname,F_OK));
+}
+
+int Master_info_file::do_init_info()
+{
+  int error;
+  char fname[FN_REFLEN+128];
+  DBUG_ENTER("Master_info_file::do_init_info");
+
+  mysql= 0;
+  file_id= 1;
+  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+
+  /* does master.info exist ? */
+  if (access(fname,F_OK))
+  {
+    /*
+      if someone removed the file from underneath our feet, just close
+      the old descriptor and re-create the old file
+    */
+    if (info_fd >= 0)
+      my_close(info_fd, MYF(MY_WME));
+    if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
+    {
+      sql_print_error("Failed to create a new master info file (\
+file '%s', errno %d)", fname, my_errno);
+      goto err;
+    }
+    if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
+                      MYF(MY_WME)))
+    {
+      sql_print_error("Failed to create a cache on master info file (\
+file '%s')", fname);
+      goto err;
+    }
+
+    init_master_log_pos(this);
+  }
+  else // file exists
+  {
+    if (info_fd >= 0)
+      reinit_io_cache(&info_file, READ_CACHE, 0L,0,0);
+    else
+    {
+      if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
+      {
+        sql_print_error("Failed to open the existing master info file (\
+file '%s', errno %d)", fname, my_errno);
+        goto err;
+      }
+      if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,
+                        0, MYF(MY_WME)))
+      {
+        sql_print_error("Failed to create a cache on master info file (\
+file '%s')", fname);
+        goto err;
+      }
+    }
+
+    int var_port, var_connect_retry, var_master_log_pos, lines;
+    int var_ssl= 0, var_ssl_verify_server_cert= 0;
+    float var_master_heartbeat_period= 0.0;
+    char *first_non_digit;
+
+    /*
+       Starting from 4.1.x master.info has new format. Now its
+       first line contains number of lines in file. By reading this
+       number we will be always distinguish to which version our
+       master.info corresponds to. We can't simply count lines in
+       file since versions before 4.1.x could generate files with more
+       lines than needed.
+       If first line doesn't contain a number or contain number less than
+       LINES_IN_MASTER_INFO_WITH_SSL then such file is treated like file
+       from pre 4.1.1 version.
+       There is no ambiguity when reading an old master.info, as before
+       4.1.1, the first line contained the binlog's name, which is either
+       empty or has an extension (contains a '.'), so can't be confused
+       with an integer.
+
+       So we're just reading first line and trying to figure which version
+       is this.
+    */
+
+    /*
+       The first row is temporarily stored in master_log_name,
+       if it is line count and not binlog name (new format) it will be
+       overwritten by the second row later.
+    */
+    if (init_strvar_from_file(master_log_name,
+                              sizeof(master_log_name), &info_file,
+                              ""))
+      goto errwithmsg;
+
+    lines= strtoul(master_log_name, &first_non_digit, 10);
+
+    if (master_log_name[0]!='\0' &&
+        *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
+    {
+      /* Seems to be new format => read master log name from next line */
+      if (init_strvar_from_file(master_log_name,
+            sizeof(master_log_name), &info_file, ""))
+        goto errwithmsg;
+    }
+    else
+      lines= 7;
+
+    if (init_intvar_from_file(&var_master_log_pos, &info_file, 4) ||
+        init_strvar_from_file(host, sizeof(host), &info_file, 0) ||
+        init_strvar_from_file(user, sizeof(user), &info_file, "test") ||
+        init_strvar_from_file(password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
+                              &info_file, 0 ) ||
+        init_intvar_from_file(&var_port, &info_file, MYSQL_PORT) ||
+        init_intvar_from_file(&var_connect_retry, &info_file, DEFAULT_CONNECT_RETRY))
+      goto errwithmsg;
+
+    /*
+      If file has ssl part use it even if we have server without
+      SSL support. But these option will be ignored later when
+      slave will try connect to master, so in this case warning
+      is printed.
+    */
+    if (lines >= LINES_IN_MASTER_INFO_WITH_SSL)
+    {
+      if (init_intvar_from_file(&var_ssl, &info_file, 0) ||
+          init_strvar_from_file(ssl_ca, sizeof(ssl_ca),
+                                &info_file, 0) ||
+          init_strvar_from_file(ssl_capath, sizeof(ssl_capath),
+                                &info_file, 0) ||
+          init_strvar_from_file(ssl_cert, sizeof(ssl_cert),
+                                &info_file, 0) ||
+          init_strvar_from_file(ssl_cipher, sizeof(ssl_cipher),
+                                &info_file, 0) ||
+          init_strvar_from_file(ssl_key, sizeof(ssl_key),
+                               &info_file, 0))
+      goto errwithmsg;
+
+      /*
+        Starting from 5.1.16 ssl_verify_server_cert might be
+        in the file
+      */
+      if (lines >= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT &&
+          init_intvar_from_file(&var_ssl_verify_server_cert, &info_file, 0))
+        goto errwithmsg;
+      /*
+        Starting from 6.0 master_heartbeat_period might be
+        in the file
+      */
+      if (lines >= LINE_FOR_MASTER_HEARTBEAT_PERIOD &&
+          init_floatvar_from_file(&var_master_heartbeat_period, &info_file, 0.0))
+        goto errwithmsg;
+      /*
+        Starting from 6.0 list of server_id of ignorable servers might be
+        in the file
+      */
+      if (lines >= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS &&
+          init_dynarray_intvar_from_file(&ignore_server_ids, &info_file))
+      {
+        sql_print_error("Failed to initialize master info ignore_server_ids");
+        goto errwithmsg;
+      }
+    }
+
+#ifndef HAVE_OPENSSL
+    if (var_ssl)
+      sql_print_warning("SSL information in the master info file "
+                      "('%s') are ignored because this MySQL slave was "
+                      "compiled without SSL support.", fname);
+#endif /* HAVE_OPENSSL */
+
+    /*
+      This has to be handled here as init_intvar_from_file can't handle
+      my_off_t types
+    */
+    master_log_pos= (my_off_t) var_master_log_pos;
+    port= (uint) var_port;
+    connect_retry= (uint) var_connect_retry;
+    ssl= (my_bool) var_ssl;
+    ssl_verify_server_cert= var_ssl_verify_server_cert;
+    heartbeat_period= var_master_heartbeat_period;
+  }
+  DBUG_PRINT("master_info",("log_file_name: %s  position: %ld",
+                            master_log_name,
+                            (ulong) master_log_pos));
+
+  // now change cache READ -> WRITE - must do this before flush_info
+  reinit_io_cache(&info_file, WRITE_CACHE, 0L, 0, 1);
+  if ((error=test(do_flush_info())))
+    sql_print_error("Failed to flush master info file");
+  DBUG_RETURN(error);
+
+errwithmsg:
+  sql_print_error("Error reading master configuration");
+
+err:
+  if (info_fd >= 0)
+  {
+    my_close(info_fd, MYF(0));
+    end_io_cache(&info_file);
+  }
+  info_fd= -1;
+  DBUG_RETURN(1);
+}
+
+/**
+  Flushes the master info to a file.
+  
+  @retval 1 if it failed,
+  @retval 0 otherwise.
+*/
+int Master_info_file::do_flush_info()
+{
+  IO_CACHE* file = &info_file;
+  char lbuf[22];
+  int err= 0;
+
+  DBUG_ENTER("Master_info_file::do_flush_info");
+  DBUG_PRINT("enter",("master_pos: %ld", (long) master_log_pos));
+
+  /*
+     In certain cases this code may create master.info files that seems
+     corrupted, because of extra lines filled with garbage in the end
+     file (this happens if new contents take less space than previous
+     contents of file). But because of number of lines in the first line
+     of file we don't care about this garbage.
+  */
+  char heartbeat_buf[sizeof(heartbeat_period) * 4]; // buffer to suffice always
+  my_sprintf(heartbeat_buf, (heartbeat_buf, "%.3f", heartbeat_period));
+  /*
+    produce a line listing the total number and all the ignored server_id:s
+  */
+  char* ignore_server_ids_buf;
+  {
+    ignore_server_ids_buf=
+      (char *) my_malloc((sizeof(::server_id) * 3 + 1) *
+                         (1 + ignore_server_ids.elements), MYF(MY_WME));
+    if (!ignore_server_ids_buf)
+      DBUG_RETURN(1);
+    for (ulong i= 0, cur_len= my_sprintf(ignore_server_ids_buf,
+                                         (ignore_server_ids_buf, "%u",
+                                          ignore_server_ids.elements));
+         i < ignore_server_ids.elements; i++)
+    {
+      ulong s_id;
+      get_dynamic(&ignore_server_ids, (uchar*) &s_id, i);
+      cur_len +=my_sprintf(ignore_server_ids_buf + cur_len,
+                           (ignore_server_ids_buf + cur_len,
+                            " %lu", s_id));
+    }
+  }
+  my_b_seek(file, 0L);
+  my_b_printf(file,
+              "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n",
+              LINES_IN_MASTER_INFO,
+              master_log_name, llstr(master_log_pos, lbuf),
+              host, user,
+              password, port, connect_retry,
+              (int)(ssl), ssl_ca, ssl_capath, ssl_cert,
+              ssl_cipher, ssl_key, ssl_verify_server_cert,
+              heartbeat_buf,
+              ignore_server_ids_buf);
+  my_free(ignore_server_ids_buf, MYF(0));
+  err= flush_io_cache(file);
+  if (sync_masterinfo_period && !err && 
+      ++(sync_counter) >= sync_masterinfo_period)
+  {
+    err= my_sync(info_fd, MYF(MY_WME));
+    sync_counter= 0;
+  }
+  DBUG_RETURN(-err);
+}
+
+void Master_info_file::do_end_info()
+{
+  DBUG_ENTER("Master_info_file::do_end_info");
+
+  if (!inited)
+    DBUG_VOID_RETURN;
+
+  if (info_fd >= 0)
+  {
+    end_io_cache(&info_file);
+    (void)my_close(info_fd, MYF(MY_WME));
+    info_fd = -1;
+  }
+  inited = 0;
+
+  DBUG_VOID_RETURN;
+}
+
+int Master_info_file::do_reset_info() 
+{
+  MY_STAT stat_area;
+  char fname[FN_REFLEN];
+  int error= 0;
+
+  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+  if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
+    error= 1;
+
+  return (error);
+}
+#endif /* HAVE_REPLICATION */

=== added file 'sql/rpl_mi_file.h'
--- a/sql/rpl_mi_file.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_mi_file.h	2009-04-02 16:14:14 +0000
@@ -0,0 +1,56 @@
+/* Copyright (C) 2005 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_MI_FILE_H
+#define RPL_MI_FILE_H
+
+#ifdef HAVE_REPLICATION
+
+#include "rpl_mi.h"
+
+class Master_info_file : public Master_info
+{
+  public:
+  
+  const char* info_fname;
+  /*
+    info_fd - file descriptor of the info file. set only during
+    initialization or clean up - safe to read anytime
+  */
+  File info_fd;
+  /* IO_CACHE of the info file - set only during init or end */
+  IO_CACHE info_file;
+  /*
+   Keeps track of the number of events before fsyncing. The option 
+   --sync-master-info determines how many events should be processed
+   before fsyncing.
+  */
+  uint sync_counter;
+
+  Master_info_file(const char* param_info_fname);
+
+private:
+  int do_check();
+  int do_init_info();
+  void do_end_info();
+  int do_flush_info();
+  int do_reset_info();
+
+  Master_info_file& operator=(const Master_info_file& info);
+  Master_info_file(const Master_info_file& info);
+};
+
+#endif /* HAVE_REPLICATION */
+#endif /* RPL_MI_FILE_H */

=== modified file 'sql/rpl_record.cc'
--- a/sql/rpl_record.cc	2009-03-05 21:13:37 +0000
+++ b/sql/rpl_record.cc	2009-04-08 13:09:37 +0000
@@ -373,14 +373,16 @@ unpack_row(Relay_log_info const *rli,
 
   @param table[in,out] Table whose record[0] buffer is prepared. 
   @param cols[in]      Vector of bits denoting columns that will not be checked.
-  @param check[in]     Indicates if errors should be raised when checking default 
-                       values.
-
+  @param check[in]     Specifies if lack of default error needs checking.
+  @param abort_on_warning[in] 
+                       Controls how to react on lack of a field's default.
+                       The parameter mimics the master side one for
+                       @c check_that_all_fields_are_given_values.
   @retval 0                       Success
   @retval ER_NO_DEFAULT_FOR_FIELD Default value could not be checked for a field
  */ 
-int prepare_record(TABLE *const table, 
-                   const MY_BITMAP *cols, uint width, const bool check)
+int prepare_record(TABLE *const table, const MY_BITMAP *cols, uint width,
+                   const bool check, const bool abort_on_warning)
 {
   DBUG_ENTER("prepare_record");
 
@@ -390,28 +392,34 @@ int prepare_record(TABLE *const table,
   if (!check)
     DBUG_RETURN(error);
 
-  /*
-    For fields that are not in the cols for the row, we check them if they
-    have default or can be null.
+  /**
+    For fields that are not in @c cols for the row, we check them if they
+    have a default. The check follows the same rules as the INSERT
+    query without specifying an explicit value for a field not having
+    the explicit default (@c check_that_all_fields_are_given_values()).
   */
 
   DBUG_PRINT_BITSET("debug", "cols: %s", cols);
-  for (Field **field_ptr= table->field ; *field_ptr ; ++field_ptr)
+  for (Field **field_ptr= table->field; *field_ptr; ++field_ptr)
   {
     if ((uint) (field_ptr - table->field) >= cols->n_bits ||
         !bitmap_is_set(cols, field_ptr - table->field))
     {
-      uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG;
       Field *const f= *field_ptr;
-
-      if (((f->flags & mask) == mask))
+      if ((f->flags &  NO_DEFAULT_VALUE_FLAG) &&
+          (f->real_type() != MYSQL_TYPE_ENUM))
       {
-        my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), f->field_name);
-        error = HA_ERR_ROWS_EVENT_APPLY;
+        push_warning_printf(current_thd, abort_on_warning?
+                            MYSQL_ERROR::WARN_LEVEL_ERROR :
+                            MYSQL_ERROR::WARN_LEVEL_WARN,
+                            ER_NO_DEFAULT_FOR_FIELD,
+                            ER(ER_NO_DEFAULT_FOR_FIELD),
+                            f->field_name);
+        if (abort_on_warning)
+          error = HA_ERR_ROWS_EVENT_APPLY;
       }
     }
   }
-
   DBUG_RETURN(error);
 }
 

=== modified file 'sql/rpl_record.h'
--- a/sql/rpl_record.h	2008-09-09 08:19:21 +0000
+++ b/sql/rpl_record.h	2009-04-08 13:09:37 +0000
@@ -32,7 +32,8 @@ int unpack_row(Relay_log_info const *rli
                bool unpack_blobs);
 
 // Fill table's record[0] with default values.
-int prepare_record(TABLE *const, const MY_BITMAP *cols, uint width, const bool);
+int prepare_record(TABLE *const, const MY_BITMAP *cols, uint width,
+                   const bool, const bool= FALSE);
 #endif
 
 #endif

=== modified file 'sql/rpl_reporting.cc'
--- a/sql/rpl_reporting.cc	2007-06-11 20:15:39 +0000
+++ b/sql/rpl_reporting.cc	2009-04-17 15:45:46 +0000
@@ -2,6 +2,13 @@
 #include "mysql_priv.h"
 #include "rpl_reporting.h"
 
+Slave_reporting_capability::Slave_reporting_capability(char const *thread_name)
+  : m_thread_name(thread_name)
+{
+  MYSQL_MUTEX_INIT(key_mutex_slave_reporting_capability_err_lock,
+                   &err_lock, MY_MUTEX_INIT_FAST);
+}
+
 void
 Slave_reporting_capability::report(loglevel level, int err_code,
                                    const char *msg, ...) const
@@ -13,6 +20,7 @@ Slave_reporting_capability::report(logle
   va_list args;
   va_start(args, msg);
 
+  MYSQL_MUTEX_LOCK(&err_lock);
   switch (level)
   {
   case ERROR_LEVEL:
@@ -38,6 +46,7 @@ Slave_reporting_capability::report(logle
 
   my_vsnprintf(pbuff, pbuffsize, msg, args);
 
+  MYSQL_MUTEX_UNLOCK(&err_lock);
   va_end(args);
 
   /* If the msg string ends with '.', do not add a ',' it would be ugly */
@@ -46,3 +55,8 @@ Slave_reporting_capability::report(logle
                   (pbuff[0] && *(strend(pbuff)-1) == '.') ? "" : ",",
                   err_code);
 }
+
+Slave_reporting_capability::~Slave_reporting_capability()
+{
+  MYSQL_MUTEX_DESTROY(&err_lock);
+}

=== modified file 'sql/rpl_reporting.h'
--- a/sql/rpl_reporting.h	2007-06-11 20:15:39 +0000
+++ b/sql/rpl_reporting.h	2009-04-17 15:45:46 +0000
@@ -16,15 +16,14 @@
 class Slave_reporting_capability
 {
 public:
+  /** lock used to synchronize m_last_error on 'SHOW SLAVE STATUS' **/
+  mutable mysql_mutex_t err_lock;
   /**
      Constructor.
 
      @param thread_name Printable name of the slave thread that is reporting.
    */
-  Slave_reporting_capability(char const *thread_name)
-    : m_thread_name(thread_name)
-  {
-  }
+  Slave_reporting_capability(char const *thread_name);
 
   /**
      Writes a message and, if it's an error message, to Last_Error
@@ -44,7 +43,9 @@ public:
      STATUS</code>.
    */
   void clear_error() {
+    MYSQL_MUTEX_LOCK(&err_lock);
     m_last_error.clear();
+    MYSQL_MUTEX_UNLOCK(&err_lock);
   }
 
   /**
@@ -72,6 +73,7 @@ public:
 
   Error const& last_error() const { return m_last_error; }
 
+  virtual ~Slave_reporting_capability()= 0;
 private:
   /**
      Last error produced by the I/O or SQL thread respectively.
@@ -79,6 +81,10 @@ private:
   mutable Error m_last_error;
 
   char const *const m_thread_name;
+
+  // not implemented
+  Slave_reporting_capability(const Slave_reporting_capability& rhs);
+  Slave_reporting_capability& operator=(const Slave_reporting_capability& rhs);
 };
 
 #endif // RPL_REPORTING_H

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2009-04-14 21:37:16 +0000
+++ b/sql/rpl_rli.cc	2009-04-17 15:45:46 +0000
@@ -22,19 +22,11 @@
 #include "rpl_utility.h"
 #include "transaction.h"
 
-static int count_relay_log_space(Relay_log_info* rli);
-
-// Defined in slave.cc
-int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
-int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-			  const char *default_val);
-
-
 Relay_log_info::Relay_log_info(bool is_slave_recovery)
-  :Slave_reporting_capability("SQL"),
+   :Rpl_info("SQL"),
    no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
-   info_fd(-1), cur_log_fd(-1), 
-   relay_log(&sync_relaylog_period), sync_counter(0),
+   cur_log_fd(-1), 
+   relay_log(&sync_relaylog_period),
    is_relay_log_recovery(is_slave_recovery),
    save_temporary_tables(0),
    cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),
@@ -43,8 +35,7 @@ Relay_log_info::Relay_log_info(bool is_s
 #endif
    group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
    last_master_timestamp(0), slave_skip_counter(0),
-   abort_pos_wait(0), slave_run_id(0), sql_thd(0),
-   inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
+   abort_pos_wait(0), until_condition(UNTIL_NONE),
    until_log_pos(0), retried_trans(0),
    tables_to_lock(0), tables_to_lock_count(0),
    last_event_start_time(0), m_flags(0)
@@ -54,266 +45,28 @@ Relay_log_info::Relay_log_info(bool is_s
   group_relay_log_name[0]= event_relay_log_name[0]=
     group_master_log_name[0]= 0;
   until_log_name[0]= ign_master_log_name_end[0]= 0;
-  bzero((char*) &info_file, sizeof(info_file));
   bzero((char*) &cache_buf, sizeof(cache_buf));
   cached_charset_invalidate();
-  MYSQL_MUTEX_INIT(key_RLI_run_lock, &run_lock, MY_MUTEX_INIT_FAST);
-  MYSQL_MUTEX_INIT(key_RLI_data_lock, &data_lock, MY_MUTEX_INIT_FAST);
-  MYSQL_MUTEX_INIT(key_RLI_log_space_lock, &log_space_lock, MY_MUTEX_INIT_FAST);
-  MYSQL_COND_INIT(key_RLI_data_cond, &data_cond, NULL);
-  MYSQL_COND_INIT(key_RLI_start_cond, &start_cond, NULL);
-  MYSQL_COND_INIT(key_RLI_stop_cond, &stop_cond, NULL);
-  MYSQL_COND_INIT(key_RLI_log_space_cond, &log_space_cond, NULL);
+  MYSQL_MUTEX_INIT(key_mutex_relay_log_info_log_space_lock,
+                   &log_space_lock, MY_MUTEX_INIT_FAST);
+  MYSQL_COND_INIT(key_cond_relay_log_info_log_space_cond,
+                  &log_space_cond, NULL);
   relay_log.init_pthread_objects();
+
   DBUG_VOID_RETURN;
 }
 
-
 Relay_log_info::~Relay_log_info()
 {
   DBUG_ENTER("Relay_log_info::~Relay_log_info");
 
-  MYSQL_MUTEX_DESTROY(&run_lock);
-  MYSQL_MUTEX_DESTROY(&data_lock);
   MYSQL_MUTEX_DESTROY(&log_space_lock);
-  MYSQL_COND_DESTROY(&data_cond);
-  MYSQL_COND_DESTROY(&start_cond);
-  MYSQL_COND_DESTROY(&stop_cond);
   MYSQL_COND_DESTROY(&log_space_cond);
   relay_log.cleanup();
-  DBUG_VOID_RETURN;
-}
-
-
-int init_relay_log_info(Relay_log_info* rli,
-			const char* info_fname)
-{
-  char fname[FN_REFLEN+128];
-  int info_fd;
-  const char* msg = 0;
-  int error = 0;
-  DBUG_ENTER("init_relay_log_info");
-  DBUG_ASSERT(!rli->no_storage);         // Don't init if there is no storage
-
-  if (rli->inited)                       // Set if this function called
-    DBUG_RETURN(0);
-  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
-  MYSQL_MUTEX_LOCK(&rli->data_lock);
-  info_fd = rli->info_fd;
-  rli->cur_log_fd = -1;
-  rli->slave_skip_counter=0;
-  rli->abort_pos_wait=0;
-  rli->log_space_limit= relay_log_space_limit;
-  rli->log_space_total= 0;
-  rli->tables_to_lock= 0;
-  rli->tables_to_lock_count= 0;
-
-  fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "",
-            MY_PACK_FILENAME | MY_UNPACK_FILENAME |
-            MY_RETURN_REAL_PATH);
-  rli->slave_patternload_file_size= strlen(rli->slave_patternload_file);
-
-  /*
-    The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
-    Note that the I/O thread flushes it to disk after writing every
-    event, in flush_master_info(mi, 1).
-  */
-
-  /*
-    For the maximum log size, we choose max_relay_log_size if it is
-    non-zero, max_binlog_size otherwise. If later the user does SET
-    GLOBAL on one of these variables, fix_max_binlog_size and
-    fix_max_relay_log_size will reconsider the choice (for example
-    if the user changes max_relay_log_size to zero, we have to
-    switch to using max_binlog_size for the relay log) and update
-    rli->relay_log.max_size (and mysql_bin_log.max_size).
-  */
-  {
-    char buf[FN_REFLEN];
-    const char *ln;
-    static bool name_warning_sent= 0;
-    ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
-                                     1, buf);
-    /* We send the warning only at startup, not after every RESET SLAVE */
-    if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent)
-    {
-      /*
-        User didn't give us info to name the relay log index file.
-        Picking `hostname`-relay-bin.index like we do, causes replication to
-        fail if this slave's hostname is changed later. So, we would like to
-        instead require a name. But as we don't want to break many existing
-        setups, we only give warning, not error.
-      */
-      sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
-                        " so replication "
-                        "may break when this MySQL server acts as a "
-                        "slave and has his hostname changed!! Please "
-                        "use '--relay-log=%s' to avoid this problem.", ln);
-      name_warning_sent= 1;
-    }
-    /*
-      note, that if open() fails, we'll still have index file open
-      but a destructor will take care of that
-    */
-    if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) ||
-        rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
-                            (max_relay_log_size ? max_relay_log_size :
-                            max_binlog_size), 1))
-    {
-      MYSQL_MUTEX_UNLOCK(&rli->data_lock);
-      sql_print_error("Failed in open_log() called from init_relay_log_info()");
-      DBUG_RETURN(1);
-    }
-    rli->relay_log.is_relay_log= TRUE;
-  }
-
-  /* if file does not exist */
-  if (access(fname,F_OK))
-  {
-    /*
-      If someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (info_fd >= 0)
-      MYSQL_CLOSE(info_fd, MYF(MY_WME));
-    if ((info_fd= MYSQL_OPEN(key_file_rli, fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-    {
-      sql_print_error("Failed to create a new relay log info file (\
-file '%s', errno %d)", fname, my_errno);
-      msg= current_thd->stmt_da->message();
-      goto err;
-    }
-    if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
-                      MYF(MY_WME)))
-    {
-      sql_print_error("Failed to create a cache on relay log info file '%s'",
-                      fname);
-      msg= current_thd->stmt_da->message();
-      goto err;
-    }
-
-    /* Init relay log with first entry in the relay index file */
-    if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
-                           &msg, 0))
-    {
-      sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
-      goto err;
-    }
-    rli->group_master_log_name[0]= 0;
-    rli->group_master_log_pos= 0;
-    rli->info_fd= info_fd;
-  }
-  else // file exists
-  {
-    if (info_fd >= 0)
-      reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
-    else
-    {
-      int error=0;
-      if ((info_fd= MYSQL_OPEN(key_file_rli, fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-      {
-        sql_print_error("\
-Failed to open the existing relay log info file '%s' (errno %d)",
-                        fname, my_errno);
-        error= 1;
-      }
-      else if (init_io_cache(&rli->info_file, info_fd,
-                             IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on relay log info file '%s'",
-                        fname);
-        error= 1;
-      }
-      if (error)
-      {
-        if (info_fd >= 0)
-          MYSQL_CLOSE(info_fd, MYF(0));
-        rli->info_fd= -1;
-        rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-        MYSQL_MUTEX_UNLOCK(&rli->data_lock);
-        DBUG_RETURN(1);
-      }
-    }
-
-    rli->info_fd = info_fd;
-    int relay_log_pos, master_log_pos;
-    if (init_strvar_from_file(rli->group_relay_log_name,
-                              sizeof(rli->group_relay_log_name),
-                              &rli->info_file, "") ||
-       init_intvar_from_file(&relay_log_pos,
-                             &rli->info_file, BIN_LOG_HEADER_SIZE) ||
-       init_strvar_from_file(rli->group_master_log_name,
-                             sizeof(rli->group_master_log_name),
-                             &rli->info_file, "") ||
-       init_intvar_from_file(&master_log_pos, &rli->info_file, 0))
-    {
-      msg="Error reading slave log configuration";
-      goto err;
-    }
-    strmake(rli->event_relay_log_name,rli->group_relay_log_name,
-            sizeof(rli->event_relay_log_name)-1);
-    rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos;
-    rli->group_master_log_pos= master_log_pos;
-
-    if (rli->is_relay_log_recovery && init_recovery(rli->mi, &msg)) 
-      goto err;
-
-    if (init_relay_log_pos(rli,
-                           rli->group_relay_log_name,
-                           rli->group_relay_log_pos,
-                           0 /* no data lock*/,
-                           &msg, 0))
-    {
-      char llbuf[22];
-      sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
-                      rli->group_relay_log_name,
-                      llstr(rli->group_relay_log_pos, llbuf));
-      goto err;
-    }
-  }
-
-#ifndef DBUG_OFF
-  {
-    char llbuf1[22], llbuf2[22];
-    DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
-                        llstr(my_b_tell(rli->cur_log),llbuf1),
-                        llstr(rli->event_relay_log_pos,llbuf2)));
-    DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
-    DBUG_ASSERT((my_b_tell(rli->cur_log) == rli->event_relay_log_pos));
-  }
-#endif
-
-  /*
-    Now change the cache from READ to WRITE - must do this
-    before flush_relay_log_info
-  */
-  reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
-  if ((error= flush_relay_log_info(rli)))
-  {
-    msg="Failed to flush relay log info file";
-    goto err;
-  }
-  if (count_relay_log_space(rli))
-  {
-    msg="Error counting relay log space";
-    goto err;
-  }
-  rli->inited= 1;
-  MYSQL_MUTEX_UNLOCK(&rli->data_lock);
-  DBUG_RETURN(error);
 
-err:
-  sql_print_error(msg);
-  end_io_cache(&rli->info_file);
-  if (info_fd >= 0)
-    MYSQL_CLOSE(info_fd, MYF(0));
-  rli->info_fd= -1;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  MYSQL_MUTEX_UNLOCK(&rli->data_lock);
-  DBUG_RETURN(1);
+  DBUG_VOID_RETURN;
 }
 
-
 static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo)
 {
   MY_STAT s;
@@ -332,38 +85,32 @@ static inline int add_relay_log(Relay_lo
   DBUG_RETURN(0);
 }
 
-
-static int count_relay_log_space(Relay_log_info* rli)
+int Relay_log_info::count_relay_log_space()
 {
   LOG_INFO linfo;
-  DBUG_ENTER("count_relay_log_space");
-  rli->log_space_total= 0;
-  if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
+  DBUG_ENTER("Relay_log_info::count_relay_log_space");
+  log_space_total= 0;
+  if (relay_log.find_log_pos(&linfo, NullS, 1))
   {
     sql_print_error("Could not find first log while counting relay log space");
     DBUG_RETURN(1);
   }
   do
   {
-    if (add_relay_log(rli,&linfo))
+    if (add_relay_log(this, &linfo))
       DBUG_RETURN(1);
-  } while (!rli->relay_log.find_next_log(&linfo, 1));
+  } while (!relay_log.find_next_log(&linfo, 1));
   /*
      As we have counted everything, including what may have written in a
      preceding write, we must reset bytes_written, or we may count some space
      twice.
   */
-  rli->relay_log.reset_bytes_written();
+  relay_log.reset_bytes_written();
   DBUG_RETURN(0);
 }
 
-
-/*
-   Reset UNTIL condition for Relay_log_info
-
-   SYNOPSYS
-    clear_until_condition()
-      rli - Relay_log_info structure where UNTIL condition should be reset
+/**
+   Resets UNTIL condition for Relay_log_info
  */
 
 void Relay_log_info::clear_until_condition()
@@ -376,37 +123,31 @@ void Relay_log_info::clear_until_conditi
   DBUG_VOID_RETURN;
 }
 
+/**
+  Opens and intialize the given relay log. Specifically, it does what follows:
 
-/*
-  Open the given relay log
-
-  SYNOPSIS
-    init_relay_log_pos()
-    rli                 Relay information (will be initialized)
-    log                 Name of relay log file to read from. NULL = First log
-    pos                 Position in relay log file
-    need_data_lock      Set to 1 if this functions should do mutex locks
-    errmsg              Store pointer to error message here
-    look_for_description_event
-                        1 if we should look for such an event. We only need
-                        this when the SQL thread starts and opens an existing
-                        relay log and has to execute it (possibly from an
-                        offset >4); then we need to read the first event of
-                        the relay log to be able to parse the events we have
-                        to execute.
-
-  DESCRIPTION
-  - Close old open relay log files.
-  - If we are using the same relay log as the running IO-thread, then set
+  - Closes old open relay log files.
+  - If we are using the same relay log as the running IO-thread, then sets.
     rli->cur_log to point to the same IO_CACHE entry.
-  - If not, open the 'log' binary file.
+  - If not, opens the 'log' binary file.
+
+  @todo check proper initialization of group_master_log_name/group_master_log_pos.
 
-  TODO
-    - check proper initialization of group_master_log_name/group_master_log_pos
 
-  RETURN VALUES
-    0   ok
-    1   error.  errmsg is set to point to the error message
+  @param  rli[in]                 Relay information (will be initialized)
+  @param  log[in]                 Name of relay log file to read from. NULL = First log
+  @param  pos[in]                 Position in relay log file
+  @param  need_data_lock[in]      Set to 1 if this functions should do mutex locks
+  @param  errmsg[out]             Store pointer to error message here
+  @param  look_for_description_event[in]
+                                  1 if we should look for such an event. We only need
+                                  this when the SQL thread starts and opens an existing
+                                  relay log and has to execute it (possibly from an
+                                  offset >4); then we need to read the first event of
+                                  the relay log to be able to parse the events we have
+                                  to execute.
+  @retval 0 ok,
+  @retval 1 otherwise error, where errmsg is set to point to the error message.
 */
 
 int init_relay_log_pos(Relay_log_info* rli,const char* log,
@@ -593,29 +334,24 @@ err:
   DBUG_RETURN ((*errmsg) ? 1 : 0);
 }
 
-
-/*
+/**
   Waits until the SQL thread reaches (has executed up to) the
   log/position or timed out.
 
   SYNOPSIS
-    wait_for_pos()
-    thd             client thread that sent SELECT MASTER_POS_WAIT
-    log_name        log name to wait for
-    log_pos         position to wait for
-    timeout         timeout in seconds before giving up waiting
-
-  NOTES
-    timeout is longlong whereas it should be ulong ; but this is
-    to catch if the user submitted a negative timeout.
+  @param[in]  thd             client thread that sent @c SELECT @c MASTER_POS_WAIT,
+  @param[in]  log_name        log name to wait for,
+  @param[in]  log_pos         position to wait for,
+  @param[in]  timeout         @c timeout in seconds before giving up waiting.
+                              @c timeout is longlong whereas it should be ulong; but this is
+                              to catch if the user submitted a negative timeout.
 
-  RETURN VALUES
-    -2          improper arguments (log_pos<0)
+  @retval  -2   improper arguments (log_pos<0)
                 or slave not running, or master info changed
                 during the function's execution,
-                or client thread killed. -2 is translated to NULL by caller
-    -1          timed out
-    >=0         number of log events the function had to wait
+                or client thread killed. -2 is translated to NULL by caller,
+  @retval  -1   timed out
+  @retval  >=0  number of log events the function had to wait
                 before reaching the desired log/position
  */
 
@@ -876,11 +612,18 @@ void Relay_log_info::close_temporary_tab
   DBUG_VOID_RETURN;
 }
 
-/*
-  purge_relay_logs()
+/**
+  Purges relay logs. It assumes to have a run lock on rli and that no 
+  slave thread are running.
+ 
+  @param[in]   rli         @c Relay_log_info,
+  @param[in]   THD         connection,
+  @param[in]   just_reset  if false, it tells that logs should be purged
+                           and @c init_relay_log_pos() should be called,
+  @errmsg[out] errmsg      store pointer to an error message.
 
-  NOTES
-    Assumes to have a run lock on rli and that no slave thread are running.
+  @retval 0 successfuly executed,
+  @retval 1 otherwise error, where errmsg is set to point to the error message.
 */
 
 int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
@@ -894,10 +637,10 @@ int purge_relay_logs(Relay_log_info* rli
     Indeed, rli->inited==0 does not imply that they already are empty.
     It could be that slave's info initialization partly succeeded :
     for example if relay-log.info existed but *relay-bin*.*
-    have been manually removed, init_relay_log_info reads the old
-    relay-log.info and fills rli->master_log_*, then init_relay_log_info
+    have been manually removed, init_info reads the old
+    relay-log.info and fills rli->master_log_*, then init_info
     checks for the existence of the relay log, this fails and
-    init_relay_log_info leaves rli->inited to 0.
+    init_info leaves rli->inited to 0.
     In that pathological case, rli->master_log_pos* will be properly reinited
     at the next START SLAVE (as RESET SLAVE or CHANGE
     MASTER, the callers of purge_relay_logs, will delete bogus *.info files
@@ -947,9 +690,10 @@ int purge_relay_logs(Relay_log_info* rli
   strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
           sizeof(rli->event_relay_log_name)-1);
   rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
-  if (count_relay_log_space(rli))
+  if (rli->count_relay_log_space())
   {
     *errmsg= "Error counting relay log space";
+    error= 1;
     goto err;
   }
   if (!just_reset)
@@ -967,37 +711,34 @@ err:
 }
 
 
-/*
-     Check if condition stated in UNTIL clause of START SLAVE is reached.
-   SYNOPSYS
-     Relay_log_info::is_until_satisfied()
-     master_beg_pos    position of the beginning of to be executed event
-                       (not log_pos member of the event that points to the
-                        beginning of the following event)
-
+/**
+     Checks if condition stated in UNTIL clause of START SLAVE is reached.
 
-   DESCRIPTION
-     Checks if UNTIL condition is reached. Uses caching result of last
-     comparison of current log file name and target log file name. So cached
-     value should be invalidated if current log file name changes
-     (see Relay_log_info::notify_... functions).
+     Specifically, it checks if UNTIL condition is reached. Uses caching result
+     of last comparison of current log file name and target log file name. So
+     cached value should be invalidated if current log file name changes (see
+     @c Relay_log_info::notify_... functions).
 
      This caching is needed to avoid of expensive string comparisons and
-     strtol() conversions needed for log names comparison. We don't need to
+     @c strtol() conversions needed for log names comparison. We don't need to
      compare them each time this function is called, we only need to do this
-     when current log name changes. If we have UNTIL_MASTER_POS condition we
-     need to do this only after Rotate_log_event::do_apply_event() (which is
-     rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS
+     when current log name changes. If we have @c UNTIL_MASTER_POS condition we
+     need to do this only after @c Rotate_log_event::do_apply_event() (which is
+     rare, so caching gives real benifit), and if we have @c UNTIL_RELAY_POS
      condition then we should invalidate cached comarison value after
-     inc_group_relay_log_pos() which called for each group of events (so we
+     @c inc_group_relay_log_pos() which called for each group of events (so we
      have some benefit if we have something like queries that use
      autoincrement or if we have transactions).
 
-     Should be called ONLY if until_condition != UNTIL_NONE !
-   RETURN VALUE
-     true - condition met or error happened (condition seems to have
-            bad log file name)
-     false - condition not met
+     Should be called ONLY if @c until_condition @c != @c UNTIL_NONE !
+
+     @param master_beg_pos    position of the beginning of to be executed event
+                              (not @c log_pos member of the event that points to 
+                              the beginning of the following event)
+
+     @retval true   condition met or error happened (condition seems to have
+                    bad log file name),
+     @retval false  condition not met.
 */
 
 bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos)
@@ -1135,12 +876,12 @@ void Relay_log_info::stmt_done(my_off_t
     middle of the "transaction". START SLAVE will resume at BEGIN
     while the MyISAM table has already been updated.
   */
-  if ((sql_thd->options & OPTION_BEGIN) && opt_using_transactions)
+  if ((info_thd->options & OPTION_BEGIN) && opt_using_transactions)
     inc_event_relay_log_pos();
   else
   {
     inc_group_relay_log_pos(event_master_log_pos);
-    flush_relay_log_info(this);
+    do_flush_info();
     /*
       Note that Rotate_log_event::do_apply_event() does not call this
       function, so there is no chance that a fake rotate event resets
@@ -1163,7 +904,7 @@ void Relay_log_info::cleanup_context(THD
 {
   DBUG_ENTER("Relay_log_info::cleanup_context");
 
-  DBUG_ASSERT(sql_thd == thd);
+  DBUG_ASSERT(info_thd == thd);
   /*
     1) Instances of Table_map_log_event, if ::do_apply_event() was called on them,
     may have opened tables, which we cannot be sure have been closed (because
@@ -1219,3 +960,182 @@ void Relay_log_info::slave_close_thread_
   clear_tables_to_lock();
 }
 #endif
+
+int Relay_log_info::init_info(bool abort_if_no_info)
+{
+  int error= 0;
+
+  DBUG_ENTER("Relay_log_info::init_info");
+
+  if (abort_if_no_info && do_check())
+    DBUG_RETURN(error);
+
+  if (inited)
+  {
+    /*
+      We have to reset read position of relay-log-bin as we may have
+      already been reading from 'hotlog' when the slave was stopped
+      last time. If this case pos_in_file would be set and we would
+      get a crash when trying to read the signature for the binary
+      relay log.
+
+      We only rewind the read position if we are starting the SQL
+      thread. The handle_slave_sql thread assumes that the read
+      position is at the beginning of the file, and will read the
+      "signature" and then fast-forward to the last position read.
+    */
+    my_b_seek(cur_log, (my_off_t) 0);
+    DBUG_RETURN(error);
+  }
+  
+  cur_log_fd = -1;
+  slave_skip_counter= 0;
+  abort_pos_wait= 0;
+  log_space_limit= relay_log_space_limit;
+  log_space_total= 0;
+  tables_to_lock= 0;
+  tables_to_lock_count= 0;
+
+  fn_format(slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "",
+            MY_PACK_FILENAME | MY_UNPACK_FILENAME |
+            MY_RETURN_REAL_PATH);
+  slave_patternload_file_size= strlen(slave_patternload_file);
+
+  /*
+    The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
+  */
+  /*
+    For the maximum log size, we choose max_relay_log_size if it is
+    non-zero, max_binlog_size otherwise. If later the user does SET
+    GLOBAL on one of these variables, fix_max_binlog_size and
+    fix_max_relay_log_size will reconsider the choice (for example
+    if the user changes max_relay_log_size to zero, we have to
+    switch to using max_binlog_size for the relay log) and update
+    relay_log.max_size (and mysql_bin_log.max_size).
+  */
+  {
+    char buf[FN_REFLEN];
+    const char *ln;
+    static bool name_warning_sent= 0;
+    ln= relay_log.generate_name(opt_relay_logname, "-relay-bin",
+                                     1, buf);
+    /* We send the warning only at startup, not after every RESET SLAVE */
+    if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent)
+    {
+      /*
+        User didn't give us info to name the relay log index file.
+        Picking `hostname`-relay-bin.index like we do, causes replication to
+        fail if this slave's hostname is changed later. So, we would like to
+        instead require a name. But as we don't want to break many existing
+        setups, we only give warning, not error.
+      */
+      sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
+                        " so replication "
+                        "may break when this MySQL server acts as a "
+                        "slave and has his hostname changed!! Please "
+                        "use '--relay-log=%s' to avoid this problem.", ln);
+      name_warning_sent= 1;
+    }
+    /*
+      note, that if open() fails, we'll still have index file open
+      but a destructor will take care of that
+    */
+    if (relay_log.open_index_file(opt_relaylog_index_name, ln) ||
+        relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
+                            (max_relay_log_size ? max_relay_log_size :
+                            max_binlog_size), 1))
+    {
+      sql_print_error("Failed in open_log() called from Relay_log_info::init_info()");
+      DBUG_RETURN(1);
+    }
+    relay_log.is_relay_log= TRUE;
+  }
+
+  if ((error= do_init_info()))
+  {
+    /*
+      There is no need to report an error as it was already reported. 
+     */ 
+    error= 1;
+    goto err; 
+  }
+
+  if (count_relay_log_space())
+  {
+    sql_print_error("Error counting relay log space");
+    error= 1;
+    goto err;
+  }
+
+  inited= 1;
+  is_relay_log_recovery= FALSE;
+  DBUG_RETURN(error);
+
+err:
+  relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+  DBUG_RETURN(error);
+}
+
+void Relay_log_info::end_info()
+{
+  DBUG_ENTER("Relay_log_info::end_info");
+
+  if (!inited)
+    DBUG_VOID_RETURN;
+
+  do_end_info();
+
+  if (cur_log_fd >= 0)
+  {
+    end_io_cache(&cache_buf);
+    (void)my_close(cur_log_fd, MYF(MY_WME));
+    cur_log_fd= -1;
+  }
+  inited = 0;
+  relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+  relay_log.harvest_bytes_written(&log_space_total);
+  /*
+    Delete the slave's temporary tables from memory.
+    In the future there will be other actions than this, to ensure persistance
+    of slave's temp tables after shutdown.
+  */
+  close_temporary_tables();
+
+  DBUG_VOID_RETURN;
+}
+
+int Relay_log_info::flush_current_log()
+{
+  DBUG_ENTER("Relay_log_info::flush_current_log");
+  /*
+    Flush the relay log to disk. If we don't do it, then the relay log while
+    have some part (its last kilobytes) in memory only, so if the slave server
+    dies now, with, say, from master's position 100 to 150 in memory only (not
+    on disk), and with position 150 in master.info, then when the slave
+    restarts, the I/O thread will fetch binlogs from 150, so in the relay log
+    we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
+    SQL thread will jump from 100 to 150, and replication will silently break.
+    
+    When we come to this place in code, relay log may or not be initialized;
+    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
+  */
+  IO_CACHE *log_file= relay_log.get_log_file();
+  if (flush_io_cache(log_file))
+    DBUG_RETURN(2);
+  
+  /*
+    We flushed the relay log BEFORE the master.info file, because if we crash
+    now, we will get a duplicate event in the relay log at restart. If we
+    flushed in the other order, we would get a hole in the relay log.
+    And duplicate is better than hole (with a duplicate, in later versions we
+    can add detection and scrap one event; with a hole there's nothing we can
+    do).
+  */
+
+  DBUG_RETURN(0);
+}
+
+void Relay_log_info::inject_master_info(Master_info* info)
+{
+  mi= info;
+}

=== modified file 'sql/rpl_rli.h'
--- a/sql/rpl_rli.h	2009-03-26 15:35:49 +0000
+++ b/sql/rpl_rli.h	2009-04-17 15:45:46 +0000
@@ -17,7 +17,7 @@
 #define RPL_RLI_H
 
 #include "rpl_tblmap.h"
-#include "rpl_reporting.h"
+#include "rpl_info.h"
 #include "rpl_utility.h"
 
 struct RPL_TABLE_LIST;
@@ -49,7 +49,7 @@ class Master_info;
 
 *****************************************************************************/
 
-class Relay_log_info : public Slave_reporting_capability
+class Relay_log_info : public Rpl_info
 {
 public:
   /**
@@ -80,14 +80,10 @@ public:
   bool replicate_same_server_id;
 
   /*** The following variables can only be read when protect by data lock ****/
-
   /*
-    info_fd - file descriptor of the info file. set only during
-    initialization or clean up - safe to read anytime
     cur_log_fd - file descriptor of the current read  relay log
   */
-  File info_fd,cur_log_fd;
-
+  File cur_log_fd;
   /*
     Protected with internal locks.
     Must get data_lock when resetting the logs.
@@ -97,13 +93,6 @@ public:
   IO_CACHE cache_buf,*cur_log;
 
   /*
-   * Keeps track of the number of transactions that commits
-   * before fsyncing. The option --sync-relay-log-info determines 
-   * how many transactions should commit before fsyncing.
-   */ 
-  uint sync_counter;
-
-  /*
    * Identifies when the recovery process is going on.
    * See sql/slave.cc:init_recovery for further details.
    */ 
@@ -111,9 +100,6 @@ public:
 
   /* The following variables are safe to read any time */
 
-  /* IO_CACHE of the info file - set only during init or end */
-  IO_CACHE info_file;
-
   /*
     When we restart slave thread we need to have access to the previously
     created temporary tables. Modified only on init/end and by the SQL
@@ -121,19 +107,6 @@ public:
   */
   TABLE *save_temporary_tables;
 
-  /*
-    standard lock acquistion order to avoid deadlocks:
-    run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
-  */
-  mysql_mutex_t data_lock,run_lock;
-
-  /*
-    start_cond is broadcast when SQL thread is started
-    stop_cond - when stopped
-    data_cond - when data protected by data_lock changes
-  */
-  mysql_cond_t start_cond, stop_cond, data_cond;
-
   /* parent Master_info structure */
   Master_info *mi;
 
@@ -213,18 +186,8 @@ public:
   */
   volatile uint32 slave_skip_counter;
   volatile ulong abort_pos_wait;	/* Incremented on change master */
-  volatile ulong slave_run_id;		/* Incremented on slave start */
   mysql_mutex_t log_space_lock;
   mysql_cond_t log_space_cond;
-  THD * sql_thd;
-#ifndef DBUG_OFF
-  int events_till_abort;
-#endif  
-
-  /* if not set, the value of other members of the structure are undefined */
-  bool inited;
-  volatile bool abort_slave;
-  volatile uint slave_running;
 
   /* 
      Condition and its parameters from START SLAVE UNTIL clause.
@@ -281,10 +244,10 @@ public:
   char slave_patternload_file[FN_REFLEN]; 
   size_t slave_patternload_file_size;  
 
-  ~Relay_log_info();
+  virtual ~Relay_log_info();
 
-  /*
-    Invalidate cached until_log_name and group_relay_log_name comparison 
+  /**
+    Invalidates cached until_log_name and group_relay_log_name comparison 
     result. Should be called after any update of group_realy_log_name if
     there chances that sql_thread is running.
   */
@@ -294,8 +257,9 @@ public:
       until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
   }
 
-  /*
-    The same as previous but for group_master_log_name. 
+  /**
+    The same as @c notify_group_relay_log_name_update but for
+    @c group_master_log_name.
   */
   inline void notify_group_master_log_name_update()
   {
@@ -315,7 +279,9 @@ public:
 		   longlong timeout);
   void close_temporary_tables();
 
-  /* Check if UNTIL condition is satisfied. See slave.cc for more. */
+  /** 
+   Checks if UNTIL condition is satisfied. See slave.cc for more. 
+  */
   bool is_until_satisfied(my_off_t master_beg_pos);
   inline ulonglong until_pos()
   {
@@ -336,9 +302,9 @@ public:
     return (td);
   }
 
-  /*
+  /**
     Last charset (6 bytes) seen by slave SQL thread is cached here; it helps
-    the thread save 3 get_charset() per Query_log_event if the charset is not
+    the thread save 3 @c get_charset() per @c Query_log_event if the charset is not
     changing from event to event (common situation).
     When the 6 bytes are equal to 0 is used to mean "cache is invalidated".
   */
@@ -423,17 +389,29 @@ public:
      @retval false Replication thread is currently not inside a group
    */
   bool is_in_group() const {
-    return (sql_thd->options & OPTION_BEGIN) ||
+    return (info_thd->options & OPTION_BEGIN) ||
       (m_flags & (1UL << IN_STMT));
   }
 
-private:
-  uint32 m_flags;
-};
+  int count_relay_log_space();
+
+  int init_info(bool abort_if_no_info);
+  void end_info();
+  int flush_current_log();
+  void inject_master_info(Master_info *info);
 
+private:
+  virtual int do_check()= 0;
+  virtual int do_init_info()= 0;
+  virtual void do_end_info()= 0;
+  virtual int do_flush_info()= 0;
+  virtual int do_reset_info()= 0;
 
-// Defined in rpl_rli.cc
-int init_relay_log_info(Relay_log_info* rli, const char* info_fname);
+  Relay_log_info& operator=(const Relay_log_info& info);
+  Relay_log_info(const Relay_log_info& info);
 
+private:
+  uint32 m_flags;
+};
 
 #endif /* RPL_RLI_H */

=== added file 'sql/rpl_rli_file.cc'
--- a/sql/rpl_rli_file.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_rli_file.cc	2009-04-02 16:14:14 +0000
@@ -0,0 +1,278 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include "mysql_priv.h"
+
+#include "rpl_mi.h"
+#include "rpl_rli.h"
+#include "rpl_rli_file.h"
+#include <my_dir.h>    // For MY_STAT
+#include "sql_repl.h"  // For check_binlog_magic
+#include "rpl_utility.h"
+#include "transaction.h"
+
+// Defined in slave.cc
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+                          const char *default_val);
+
+Relay_log_info_file::Relay_log_info_file(bool is_slave_recovery, const char* param_info_fname)
+  :Relay_log_info(is_slave_recovery),
+  info_fname(param_info_fname), info_fd(-1), sync_counter(0)
+{
+  DBUG_ENTER("Relay_log_info_file::Relay_log_info");
+
+  bzero((char*) &info_file, sizeof(info_file));
+
+  DBUG_VOID_RETURN;
+}
+
+int Relay_log_info_file::do_check()
+{
+  char fname[FN_REFLEN+128];
+  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+
+  return (access(fname,F_OK));
+}
+
+int Relay_log_info_file::do_init_info()
+{
+  char fname[FN_REFLEN+128];
+  const char* msg = 0;
+  int error = 0;
+  DBUG_ENTER("Relay_log_info_file::do_init_info");
+  DBUG_ASSERT(!no_storage);         // Don't init if there is no storage
+
+  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+
+  /* if file does not exist */
+  if (access(fname,F_OK))
+  {
+    /*
+      If someone removed the file from underneath our feet, just close
+      the old descriptor and re-create the old file
+    */
+    if (info_fd >= 0)
+      my_close(info_fd, MYF(MY_WME));
+    if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
+    {
+      sql_print_error("Failed to create a new relay log info file (\
+file '%s', errno %d)", fname, my_errno);
+      msg= current_thd->stmt_da->message();
+      goto err;
+    }
+    if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
+                      MYF(MY_WME)))
+    {
+      sql_print_error("Failed to create a cache on relay log info file '%s'",
+                      fname);
+      msg= current_thd->stmt_da->message();
+      goto err;
+    }
+
+    /* Init relay log with first entry in the relay index file */
+    if (init_relay_log_pos(this,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
+                           &msg, 0))
+    {
+      sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
+      goto err;
+    }
+    group_master_log_name[0]= 0;
+    group_master_log_pos= 0;
+  }
+  else // file exists
+  {
+    if (info_fd >= 0)
+      reinit_io_cache(&info_file, READ_CACHE, 0L,0,0);
+    else
+    {
+      int error= 0;
+      if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
+      {
+        sql_print_error("\
+Failed to open the existing relay log info file '%s' (errno %d)",
+                        fname, my_errno);
+        error= 1;
+      }
+      else if (init_io_cache(&info_file, info_fd,
+                             IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
+      {
+        sql_print_error("Failed to create a cache on relay log info file '%s'",
+                        fname);
+        error= 1;
+      }
+      if (error)
+      {
+        msg= "Error openning slave log configuration";
+        goto err;
+      }
+    }
+
+    int relay_log_pos, master_log_pos;
+    if (init_strvar_from_file(group_relay_log_name,
+                              sizeof(group_relay_log_name),
+                              &info_file, "") ||
+       init_intvar_from_file(&relay_log_pos,
+                             &info_file, BIN_LOG_HEADER_SIZE) ||
+       init_strvar_from_file(group_master_log_name,
+                             sizeof(group_master_log_name),
+                             &info_file, "") ||
+       init_intvar_from_file(&master_log_pos, &info_file, 0))
+    {
+      msg="Error reading slave log configuration";
+      goto err;
+    }
+    strmake(event_relay_log_name,group_relay_log_name,
+            sizeof(event_relay_log_name)-1);
+    group_relay_log_pos= event_relay_log_pos= relay_log_pos;
+    group_master_log_pos= master_log_pos;
+
+    if (is_relay_log_recovery && init_recovery(mi, &msg))
+      goto err;
+
+    if (init_relay_log_pos(this,
+                           group_relay_log_name,
+                           group_relay_log_pos,
+                           0 /* no data lock*/,
+                           &msg, 0))
+    {
+      char llbuf[22];
+      sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
+                      group_relay_log_name,
+                      llstr(group_relay_log_pos, llbuf));
+      goto err;
+    }
+  }
+
+#ifndef DBUG_OFF
+  {
+    char llbuf1[22], llbuf2[22];
+    DBUG_PRINT("info", ("my_b_tell(cur_log)=%s event_relay_log_pos=%s",
+                        llstr(my_b_tell(cur_log),llbuf1),
+                        llstr(event_relay_log_pos,llbuf2)));
+    DBUG_ASSERT(event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
+    DBUG_ASSERT((my_b_tell(cur_log) == event_relay_log_pos));
+  }
+#endif
+
+  /*
+    Now change the cache from READ to WRITE - must do this
+    before flush_info
+  */
+  reinit_io_cache(&info_file, WRITE_CACHE,0L,0,1);
+  if ((error= do_flush_info()))
+  {
+    msg= "Failed to flush relay log info file";
+    goto err;
+  }
+
+  DBUG_RETURN(error);
+
+err:
+  sql_print_error(msg);
+  end_io_cache(&info_file);
+  if (info_fd >= 0)
+    my_close(info_fd, MYF(0));
+  info_fd= -1;
+  DBUG_RETURN(1);
+}
+
+
+void Relay_log_info_file::do_end_info()
+{
+  DBUG_ENTER("Relay_log_info_file::do_end_info");
+
+  if (info_fd >= 0)
+  {
+    end_io_cache(&info_file);
+    (void) my_close(info_fd, MYF(MY_WME));
+    info_fd = -1;
+  }
+
+  DBUG_VOID_RETURN;
+}
+
+/**
+  Stores the file and position where the execute-slave thread are in the
+  relay log:
+
+    - As this is only called by the slave thread, we don't need to
+      have a lock on this.
+    - If there is an active transaction, then we don't update the position
+      in the relay log.  This is to ensure that we re-execute statements
+      if we die in the middle of an transaction that was rolled back.
+    - As a transaction never spans binary logs, we don't have to handle the
+      case where we do a relay-log-rotation in the middle of the transaction.
+      If this would not be the case, we would have to ensure that we
+      don't delete the relay log file where the transaction started when
+      we switch to a new relay log file.
+
+  @todo Change the log file information to a binary format to avoid calling
+  longlong2str.
+
+  @retval  0   ok,
+  @retval  1   write error, otherwise.
+*/
+
+int Relay_log_info_file::do_flush_info()
+{
+  bool error=0;
+  DBUG_ENTER("Relay_log_info_file::do_flush_info");
+
+  if (unlikely(no_storage))
+    DBUG_RETURN(0);
+
+  IO_CACHE *file = &info_file;
+  char buff[FN_REFLEN*2+22*2+4], *pos;
+
+  my_b_seek(file, 0L);
+  pos=strmov(buff, group_relay_log_name);
+  *pos++='\n';
+  pos=longlong2str(group_relay_log_pos, pos, 10);
+  *pos++='\n';
+  pos=strmov(pos, group_master_log_name);
+  *pos++='\n';
+  pos=longlong2str(group_master_log_pos, pos, 10);
+  *pos='\n';
+  if (my_b_write(file, (uchar*) buff, (size_t) (pos-buff)+1))
+    error=1;
+  if (flush_io_cache(file))
+    error=1;
+  if (sync_relayloginfo_period &&
+      !error &&
+      ++(sync_counter) >= sync_relayloginfo_period)
+  {
+    if (my_sync(info_fd, MYF(MY_WME)))
+      error=0;
+    sync_counter= 0;
+  }
+  /* Flushing the relay log is done by the slave I/O thread */
+  DBUG_RETURN(error);
+}
+
+int Relay_log_info_file::do_reset_info()
+{
+  MY_STAT stat_area;
+  char fname[FN_REFLEN];
+  int error= 0;
+
+  DBUG_ENTER("Relay_log_info_file::do_reset_info");
+
+  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+  if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
+    error= 1;
+
+  DBUG_RETURN (error);
+}

=== added file 'sql/rpl_rli_file.h'
--- a/sql/rpl_rli_file.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_rli_file.h	2009-04-02 16:14:14 +0000
@@ -0,0 +1,53 @@
+/* Copyright (C) 2005 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_RLI_FILE_H
+#define RPL_RLI_FILE_H
+
+#include "rpl_rli.h"
+
+class Relay_log_info_file : public Relay_log_info
+{
+  public:
+  
+  const char* info_fname;
+  /*
+    info_fd - file descriptor of the info file. set only during
+    initialization or clean up - safe to read anytime
+  */
+  File info_fd;
+  /* IO_CACHE of the info file - set only during init or end */
+  IO_CACHE info_file;
+  /*
+   Keeps track of the number of transactions that commits
+   before fsyncing. The option --sync-relay-log-info determines
+   how many transactions should commit before fsyncing.
+  */
+  uint sync_counter;
+
+  Relay_log_info_file(bool is_slave_recovery, const char* info_name);
+
+private:
+  int do_check();
+  int do_init_info();
+  int do_flush_info();
+  void do_end_info();
+  int do_reset_info();
+
+  Relay_log_info_file& operator=(const Relay_log_info_file& info);
+  Relay_log_info_file(const Relay_log_info_file& info);
+};
+
+#endif /* RPL_RLI_FILE_H */

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2009-04-13 16:15:22 +0000
+++ b/sql/set_var.cc	2009-04-17 15:45:46 +0000
@@ -1411,7 +1411,7 @@ static void fix_max_binlog_size(THD *thd
   mysql_bin_log.set_max_size(max_binlog_size);
 #ifdef HAVE_REPLICATION
   if (!max_relay_log_size)
-    active_mi->rli.relay_log.set_max_size(max_binlog_size);
+    active_mi->rli->relay_log.set_max_size(max_binlog_size);
 #endif
   DBUG_VOID_RETURN;
 }
@@ -1422,7 +1422,7 @@ static void fix_max_relay_log_size(THD *
   DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
                      max_binlog_size, max_relay_log_size));
 #ifdef HAVE_REPLICATION
-  active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
+  active_mi->rli->relay_log.set_max_size(max_relay_log_size ?
                                         max_relay_log_size: max_binlog_size);
 #endif
   DBUG_VOID_RETURN;

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2009-04-13 16:15:22 +0000
+++ b/sql/slave.cc	2009-04-17 15:45:46 +0000
@@ -30,7 +30,9 @@
 #include <myisam.h>
 #include "slave.h"
 #include "rpl_mi.h"
+#include "rpl_mi_file.h"
 #include "rpl_rli.h"
+#include "rpl_rli_file.h"
 #include "sql_repl.h"
 #include "rpl_filter.h"
 #include "repl_failsafe.h"
@@ -68,7 +70,6 @@ ulonglong relay_log_space_limit = 0;
 */
 
 int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
-int events_till_abort = -1;
 
 static pthread_key(Master_info*, RPL_MASTER_INFO);
 
@@ -169,7 +170,7 @@ static bool check_io_slave_killed(THD *t
 
 void init_thread_mask(int* mask,Master_info* mi,bool inverse)
 {
-  bool set_io = mi->slave_running, set_sql = mi->rli.slave_running;
+  bool set_io = mi->slave_running, set_sql = mi->rli->slave_running;
   register int tmp_mask=0;
   DBUG_ENTER("init_thread_mask");
 
@@ -194,7 +195,7 @@ void lock_slave_threads(Master_info* mi)
 
   //TODO: see if we can do this without dual mutex
   MYSQL_MUTEX_LOCK(&mi->run_lock);
-  MYSQL_MUTEX_LOCK(&mi->rli.run_lock);
+  MYSQL_MUTEX_LOCK(&mi->rli->run_lock);
   DBUG_VOID_RETURN;
 }
 
@@ -208,7 +209,7 @@ void unlock_slave_threads(Master_info* m
   DBUG_ENTER("unlock_slave_threads");
 
   //TODO: see if we can do this without dual mutex
-  MYSQL_MUTEX_UNLOCK(&mi->rli.run_lock);
+  MYSQL_MUTEX_UNLOCK(&mi->rli->run_lock);
   MYSQL_MUTEX_UNLOCK(&mi->run_lock);
   DBUG_VOID_RETURN;
 }
@@ -220,6 +221,7 @@ int init_slave()
 {
   DBUG_ENTER("init_slave");
   int error= 0;
+  int thread_mask= SLAVE_SQL | SLAVE_IO;
 
   /*
     This is called when mysqld starts. Before client connections are
@@ -235,16 +237,21 @@ int init_slave()
   if (pthread_key_create(&RPL_MASTER_INFO, NULL))
   {
     error= 1;
+    DBUG_RETURN(error);
+  }
+
+  Relay_log_info* rli= new Relay_log_info_file(relay_log_recovery,
+                                               relay_log_info_file);
+
+  if (!rli)
+  {
+    sql_print_error("Failed to allocate memory for the master info structure");
+    error= 1;
     goto err;
   }
 
-  active_mi= new Master_info(relay_log_recovery);
+  active_mi= new Master_info_file(master_info_file);
 
-  /*
-    If master_host is not specified, try to read it from the master_info file.
-    If master_host is specified, create the master_info file if it doesn't
-    exists.
-  */
   if (!active_mi)
   {
     sql_print_error("Failed to allocate memory for the master info structure");
@@ -252,24 +259,30 @@ int init_slave()
     goto err;
   }
 
-  if (init_master_info(active_mi,master_info_file,relay_log_info_file,
-                       1, (SLAVE_IO | SLAVE_SQL)))
+  /*
+    Setting the cross dependency used all over the code.
+  */ 
+  active_mi->inject_relay_log_info(rli);
+  rli->inject_master_info(active_mi);
+
+  /*
+    We do not need to check which one should be configured.
+    This is the startup routine and as such we try to 
+    configure both.
+  */
+  if (init_info(active_mi, TRUE, thread_mask))
   {
     sql_print_error("Failed to initialize the master info structure");
     error= 1;
     goto err;
   }
 
-  /* If server id is not set, start_slave_thread() will say it */
-
   if (active_mi->host[0] && !opt_skip_slave_start)
   {
     if (start_slave_threads(1 /* need mutex */,
                             0 /* no wait for start*/,
                             active_mi,
-                            master_info_file,
-                            relay_log_info_file,
-                            SLAVE_IO | SLAVE_SQL))
+                            thread_mask))
     {
       sql_print_error("Failed to create slave threads");
       error= 1;
@@ -286,7 +299,7 @@ err:
   Updates the master info based on the information stored in the
   relay info and ignores relay logs previously retrieved by the IO 
   thread, which thus starts fetching again based on to the  
-  group_master_log_pos and group_master_log_name. Eventually, the old
+  master_log_pos and master_log_name. Eventually, the old
   relay logs will be purged by the normal purge mechanism.
 
   In the feature, we should improve this routine in order to avoid throwing
@@ -313,7 +326,7 @@ int init_recovery(Master_info* mi, const
 {
   DBUG_ENTER("init_recovery");
  
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   if (rli->group_master_log_name[0])
   {
     mi->master_log_pos= max(BIN_LOG_HEADER_SIZE,
@@ -327,14 +340,105 @@ int init_recovery(Master_info* mi, const
     strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(),
             sizeof(rli->group_relay_log_name)-1);
     strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
-            sizeof(mi->rli.event_relay_log_name)-1);
+            sizeof(mi->rli->event_relay_log_name)-1);
  
     rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
   }
 
   DBUG_RETURN(0);
 }
- 
+
+int init_info(Master_info* mi, bool abort_if_no_info, int thread_mask)
+{
+  int error= 0;
+
+  DBUG_ENTER("init_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+  
+  /*
+    We need a mutex while we are changing master info parameters to
+    keep other threads from reading bogus info
+  */
+  MYSQL_MUTEX_LOCK(&mi->data_lock);
+  MYSQL_MUTEX_LOCK(&mi->rli->data_lock);
+
+  /*
+    This takes care of the startup dependency between the master_info
+    and relay_info. If a user wants to start just the SLAVE_IO Thread 
+    but the SLAVE_SQL is not properly configure it.
+
+    In the future, we should try to improve this by making the
+    init_info idempotent.
+  */
+  if (((thread_mask & SLAVE_IO) && mi->init_info(abort_if_no_info)) ||
+     (((thread_mask & SLAVE_SQL) || !(mi->rli->inited)) && 
+     mi->rli->init_info(abort_if_no_info)))
+    error= 1;
+
+  MYSQL_MUTEX_UNLOCK(&mi->rli->data_lock);
+  MYSQL_MUTEX_UNLOCK(&mi->data_lock);
+
+  DBUG_RETURN(error);
+}
+
+void end_info(Master_info* mi)
+{
+  DBUG_ENTER("end_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+  
+  /*
+    The previous implementation was not acquiring locks.
+    We do the same here. However, this is quite strange.
+  */
+  mi->end_info();
+  mi->rli->end_info();
+
+  DBUG_VOID_RETURN;
+}
+
+int reset_info(Master_info* mi)
+{
+  int error= 0;
+  DBUG_ENTER("reset_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+
+  /*
+    The previous implementation was not acquiring locks.
+    We do the same here. However, this is quite strange.
+  */
+  /*
+    Reset errors (the idea is that we forget about the
+    old master).
+  */
+  mi->clear_error();
+  mi->rli->clear_error();
+  mi->rli->clear_until_condition();
+
+  mi->end_info();
+  mi->rli->end_info();
+
+  if (mi->reset_info() || mi->rli->reset_info())
+    error= 1;
+
+  DBUG_RETURN(error);
+}
+
+int flush_master_info(Master_info* mi)
+{
+  DBUG_ENTER("flush_master_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+  /*
+    The previous implementation was not acquiring locks.
+    We do the same here. However, this is quite strange.
+  */
+  /*
+    With the appropriate recovery process, we will not need to flush 
+    the content of the current log. This indirection is here just to 
+    remember that in the future, we need to remove it.
+   */
+  DBUG_RETURN(mi->rli->flush_current_log() ||  mi->flush_info());
+}
+
 /**
   Convert slave skip errors bitmap into a printable string.
 */
@@ -445,13 +549,13 @@ int terminate_slave_threads(Master_info*
   if (!mi->inited)
     DBUG_RETURN(0); /* successfully do nothing */
   int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
-  mysql_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
+  mysql_mutex_t *sql_lock = &mi->rli->run_lock, *io_lock = &mi->run_lock;
 
   if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)))
   {
     DBUG_PRINT("info",("Terminating IO thread"));
     mi->abort_slave=1;
-    if ((error=terminate_slave_thread(mi->io_thd,io_lock,
+    if ((error=terminate_slave_thread(mi->info_thd,io_lock,
                                       &mi->stop_cond,
                                       &mi->slave_running,
                                       skip_lock)) &&
@@ -461,10 +565,10 @@ int terminate_slave_threads(Master_info*
   if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)))
   {
     DBUG_PRINT("info",("Terminating SQL thread"));
-    mi->rli.abort_slave=1;
-    if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
-                                      &mi->rli.stop_cond,
-                                      &mi->rli.slave_running,
+    mi->rli->abort_slave=1;
+    if ((error=terminate_slave_thread(mi->rli->info_thd,sql_lock,
+                                      &mi->rli->stop_cond,
+                                      &mi->rli->slave_running,
                                       skip_lock)) &&
         !force_all)
       DBUG_RETURN(error);
@@ -639,8 +743,7 @@ int start_slave_thread(pthread_handler h
 */
 
 int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
-                        Master_info* mi, const char* master_info_fname,
-                        const char* slave_info_fname, int thread_mask)
+                        Master_info* mi, int thread_mask)
 {
   mysql_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0;
   mysql_cond_t* cond_io=0,*cond_sql=0;
@@ -650,14 +753,14 @@ int start_slave_threads(bool need_slave_
   if (need_slave_mutex)
   {
     lock_io = &mi->run_lock;
-    lock_sql = &mi->rli.run_lock;
+    lock_sql = &mi->rli->run_lock;
   }
   if (wait_for_start)
   {
     cond_io = &mi->start_cond;
-    cond_sql = &mi->rli.start_cond;
+    cond_sql = &mi->rli->start_cond;
     lock_cond_io = &mi->run_lock;
-    lock_cond_sql = &mi->rli.run_lock;
+    lock_cond_sql = &mi->rli->run_lock;
   }
 
   if (thread_mask & SLAVE_IO)
@@ -669,7 +772,7 @@ int start_slave_threads(bool need_slave_
   {
     error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql,
                              cond_sql,
-                             &mi->rli.slave_running, &mi->rli.slave_run_id,
+                             &mi->rli->slave_running, &mi->rli->slave_run_id,
                              mi);
     if (error)
       terminate_slave_threads(mi, thread_mask & SLAVE_IO, 0);
@@ -683,7 +786,8 @@ static int end_slave_on_walk(Master_info
 {
   DBUG_ENTER("end_slave_on_walk");
 
-  end_master_info(mi);
+  end_info(mi);
+
   DBUG_RETURN(0);
 }
 #endif
@@ -716,7 +820,8 @@ void end_slave()
       once multi-master code is ready.
     */
     terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
-    end_master_info(active_mi);
+    end_info(active_mi);
+    delete active_mi->rli;
     delete active_mi;
     active_mi= 0;
   }
@@ -729,7 +834,7 @@ static bool io_slave_killed(THD* thd, Ma
 {
   DBUG_ENTER("io_slave_killed");
 
-  DBUG_ASSERT(mi->io_thd == thd);
+  DBUG_ASSERT(mi->info_thd == thd);
   DBUG_ASSERT(mi->slave_running); // tracking buffer overrun
   DBUG_RETURN(mi->abort_slave || abort_loop || thd->killed);
 }
@@ -739,7 +844,7 @@ static bool sql_slave_killed(THD* thd, R
 {
   DBUG_ENTER("sql_slave_killed");
 
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
   DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun
   if (abort_loop || thd->killed || rli->abort_slave)
   {
@@ -885,7 +990,7 @@ int init_floatvar_from_file(float* var,
 /**
    A master info read method
 
-   This function is called from @c init_master_info() along with
+   This function is called from @c init_info() along with
    init_{type}_from_file relatives to restore some of @c active_mi members.
    Particularly, this function is responsible for restoring
    IGNORE_SERVER_IDS list of servers whose events the slave is
@@ -1012,8 +1117,8 @@ static int get_master_version_and_clock(
     Free old description_event_for_queue (that is needed if we are in
     a reconnection).
   */
-  delete mi->rli.relay_log.description_event_for_queue;
-  mi->rli.relay_log.description_event_for_queue= 0;
+  delete mi->rli->relay_log.description_event_for_queue;
+  mi->rli->relay_log.description_event_for_queue= 0;
 
   if (!my_isdigit(&my_charset_bin,*mysql->server_version))
   {
@@ -1038,11 +1143,11 @@ static int get_master_version_and_clock(
       err_msg.append(err_buff);
       break;
     case '3':
-      mi->rli.relay_log.description_event_for_queue= new
+      mi->rli->relay_log.description_event_for_queue= new
         Format_description_log_event(1, mysql->server_version);
       break;
     case '4':
-      mi->rli.relay_log.description_event_for_queue= new
+      mi->rli->relay_log.description_event_for_queue= new
         Format_description_log_event(3, mysql->server_version);
       break;
     default:
@@ -1054,7 +1159,7 @@ static int get_master_version_and_clock(
         (it has the format of the *slave*); it's only good to help know if the
         master is 3.23, 4.0, etc.
       */
-      mi->rli.relay_log.description_event_for_queue= new
+      mi->rli->relay_log.description_event_for_queue= new
         Format_description_log_event(4, mysql->server_version);
       break;
     }
@@ -1071,7 +1176,7 @@ static int get_master_version_and_clock(
     goto err;
 
   /* as we are here, we tried to allocate the event */
-  if (!mi->rli.relay_log.description_event_for_queue)
+  if (!mi->rli->relay_log.description_event_for_queue)
   {
     errmsg= "default Format_description_log_event";
     err_code= ER_SLAVE_CREATE_EVENT_FAILURE;
@@ -1092,7 +1197,7 @@ static int get_master_version_and_clock(
     mi->clock_diff_with_master=
       (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
   }
-  else if (!check_io_slave_killed(mi->io_thd, mi, NULL))
+  else if (!check_io_slave_killed(mi->info_thd, mi, NULL))
   {
     mi->clock_diff_with_master= 0; /* The "most sensible" value */
     sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, "
@@ -1119,7 +1224,7 @@ static int get_master_version_and_clock(
   {
     if ((master_row= mysql_fetch_row(master_res)) &&
         (::server_id == (mi->master_id= strtoul(master_row[1], 0, 10))) &&
-        !mi->rli.replicate_same_server_id)
+        !mi->rli->replicate_same_server_id)
     {
       errmsg=
         "The slave I/O thread stops because master and slave have equal"
@@ -1233,7 +1338,7 @@ static int get_master_version_and_clock(
     my_sprintf(query, (query, query_format, llbuf));
 
     if (mysql_real_query(mysql, query, strlen(query))
-        && !check_io_slave_killed(mi->io_thd, mi, NULL))
+        && !check_io_slave_killed(mi->info_thd, mi, NULL))
     {
       err_msg.append("The slave I/O thread stops because querying master with '");
       err_msg.append(query);
@@ -1268,7 +1373,7 @@ static bool wait_for_relay_log_space(Rel
   bool slave_killed=0;
   Master_info* mi = rli->mi;
   const char *save_proc_info;
-  THD* thd = mi->io_thd;
+  THD* thd = mi->info_thd;
   DBUG_ENTER("wait_for_relay_log_space");
 
   MYSQL_MUTEX_LOCK(&rli->log_space_lock);
@@ -1300,11 +1405,11 @@ Waiting for the slave SQL thread to free
  */
 static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi)
 {
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   mysql_mutex_t *log_lock= rli->relay_log.get_log_lock();
   DBUG_ENTER("write_ignored_events_info_to_relay_log");
 
-  DBUG_ASSERT(thd == mi->io_thd);
+  DBUG_ASSERT(thd == mi->info_thd);
   MYSQL_MUTEX_LOCK(log_lock);
   if (rli->ign_master_log_name_end[0])
   {
@@ -1325,7 +1430,7 @@ static void write_ignored_events_info_to
                    " to the relay log, SHOW SLAVE STATUS may be"
                    " inaccurate");
       rli->relay_log.harvest_bytes_written(&rli->log_space_total);
-      if (flush_master_info(mi, 1))
+      if (flush_master_info(mi))
         sql_print_error("Failed to flush master info file");
       delete ev;
     }
@@ -1376,7 +1481,7 @@ int register_slave_on_master(MYSQL* mysq
     {
       *suppress_warnings= TRUE;                 // Suppress reconnect warning
     }
-    else if (!check_io_slave_killed(mi->io_thd, mi, NULL))
+    else if (!check_io_slave_killed(mi->info_thd, mi, NULL))
     {
       char buf[256];
       my_snprintf(buf, sizeof(buf), "%s (Errno: %d)", mysql_error(mysql), 
@@ -1485,29 +1590,32 @@ bool show_master_info(THD* thd, Master_i
 
     /*
       slave_running can be accessed without run_lock but not other
-      non-volotile members like mi->io_thd, which is guarded by the mutex.
+      non-volotile members like mi->info_thd, which is guarded by the mutex.
     */
     MYSQL_MUTEX_LOCK(&mi->run_lock);
-    protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin);
+    protocol->store(mi->info_thd ? mi->info_thd->proc_info : "", &my_charset_bin);
     MYSQL_MUTEX_UNLOCK(&mi->run_lock);
 
     MYSQL_MUTEX_LOCK(&mi->data_lock);
-    MYSQL_MUTEX_LOCK(&mi->rli.data_lock);
+    MYSQL_MUTEX_LOCK(&mi->rli->data_lock);
+    MYSQL_MUTEX_LOCK(&mi->err_lock);
+    MYSQL_MUTEX_LOCK(&mi->rli->err_lock);
+
     protocol->store(mi->host, &my_charset_bin);
     protocol->store(mi->user, &my_charset_bin);
     protocol->store((uint32) mi->port);
     protocol->store((uint32) mi->connect_retry);
     protocol->store(mi->master_log_name, &my_charset_bin);
     protocol->store((ulonglong) mi->master_log_pos);
-    protocol->store(mi->rli.group_relay_log_name +
-                    dirname_length(mi->rli.group_relay_log_name),
+    protocol->store(mi->rli->group_relay_log_name +
+                    dirname_length(mi->rli->group_relay_log_name),
                     &my_charset_bin);
-    protocol->store((ulonglong) mi->rli.group_relay_log_pos);
-    protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
+    protocol->store((ulonglong) mi->rli->group_relay_log_pos);
+    protocol->store(mi->rli->group_master_log_name, &my_charset_bin);
     protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT ?
                     "Yes" : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ?
                              "Connecting" : "No"), &my_charset_bin);
-    protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin);
+    protocol->store(mi->rli->slave_running ? "Yes":"No", &my_charset_bin);
     protocol->store(rpl_filter->get_do_db());
     protocol->store(rpl_filter->get_ignore_db());
 
@@ -1522,18 +1630,18 @@ bool show_master_info(THD* thd, Master_i
     rpl_filter->get_wild_ignore_table(&tmp);
     protocol->store(&tmp);
 
-    protocol->store(mi->rli.last_error().number);
-    protocol->store(mi->rli.last_error().message, &my_charset_bin);
-    protocol->store((uint32) mi->rli.slave_skip_counter);
-    protocol->store((ulonglong) mi->rli.group_master_log_pos);
-    protocol->store((ulonglong) mi->rli.log_space_total);
+    protocol->store(mi->rli->last_error().number);
+    protocol->store(mi->rli->last_error().message, &my_charset_bin);
+    protocol->store((uint32) mi->rli->slave_skip_counter);
+    protocol->store((ulonglong) mi->rli->group_master_log_pos);
+    protocol->store((ulonglong) mi->rli->log_space_total);
 
     protocol->store(
-      mi->rli.until_condition==Relay_log_info::UNTIL_NONE ? "None":
-        ( mi->rli.until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master":
+      mi->rli->until_condition==Relay_log_info::UNTIL_NONE ? "None":
+        ( mi->rli->until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master":
           "Relay"), &my_charset_bin);
-    protocol->store(mi->rli.until_log_name, &my_charset_bin);
-    protocol->store((ulonglong) mi->rli.until_log_pos);
+    protocol->store(mi->rli->until_log_name, &my_charset_bin);
+    protocol->store((ulonglong) mi->rli->until_log_pos);
 
 #ifdef HAVE_OPENSSL
     protocol->store(mi->ssl? "Yes":"No", &my_charset_bin);
@@ -1551,9 +1659,9 @@ bool show_master_info(THD* thd, Master_i
       connected, we can compute it otherwise show NULL (i.e. unknown).
     */
     if ((mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) &&
-        mi->rli.slave_running)
+        mi->rli->slave_running)
     {
-      long time_diff= ((long)(time(0) - mi->rli.last_master_timestamp)
+      long time_diff= ((long)(time(0) - mi->rli->last_master_timestamp)
                        - mi->clock_diff_with_master);
       /*
         Apparently on some systems time_diff can be <0. Here are possible
@@ -1575,7 +1683,7 @@ bool show_master_info(THD* thd, Master_i
         last_master_timestamp == 0 (an "impossible" timestamp 1970) is a
         special marker to say "consider we have caught up".
       */
-      protocol->store((longlong)(mi->rli.last_master_timestamp ?
+      protocol->store((longlong)(mi->rli->last_master_timestamp ?
                                  max(0, time_diff) : 0));
     }
     else
@@ -1589,9 +1697,9 @@ bool show_master_info(THD* thd, Master_i
     // Last_IO_Error
     protocol->store(mi->last_error().message, &my_charset_bin);
     // Last_SQL_Errno
-    protocol->store(mi->rli.last_error().number);
+    protocol->store(mi->rli->last_error().number);
     // Last_SQL_Error
-    protocol->store(mi->rli.last_error().message, &my_charset_bin);
+    protocol->store(mi->rli->last_error().message, &my_charset_bin);
     // Replicate_Ignore_Server_Ids
     {
       char buff[FN_REFLEN];
@@ -1619,7 +1727,9 @@ bool show_master_info(THD* thd, Master_i
     // Master_Server_id
     protocol->store((uint32) mi->master_id);
 
-    MYSQL_MUTEX_UNLOCK(&mi->rli.data_lock);
+    MYSQL_MUTEX_UNLOCK(&mi->rli->err_lock);
+    MYSQL_MUTEX_UNLOCK(&mi->err_lock);
+    MYSQL_MUTEX_UNLOCK(&mi->rli->data_lock);
     MYSQL_MUTEX_UNLOCK(&mi->data_lock);
 
     if (my_net_write(&thd->net, (uchar*) thd->packet.ptr(), packet->length()))
@@ -1828,7 +1938,7 @@ static ulong read_event(MYSQL* mysql, Ma
     We check if we were told to die, and if not, try reading again
   */
 #ifndef DBUG_OFF
-  if (disconnect_slave_event_count && !(mi->events_till_disconnect--))
+  if (disconnect_slave_event_count && !(mi->events_until_exit--))
     DBUG_RETURN(packet_error);
 #endif
 
@@ -2111,7 +2221,7 @@ int apply_event_and_update_pos(Log_event
      tried slave_trans_retries times.  If the event has been retried
      fewer times, 0 is returned.
 
-   - init_master_info or init_relay_log_pos failed. (These are called
+   - init_info or init_relay_log_pos failed. (These are called
      if a failure occurs when applying the event.)
 
    - An error occurred when updating the binlog position.
@@ -2133,7 +2243,7 @@ static int exec_relay_log_event(THD* thd
 
   Log_event * ev = next_event(rli);
 
-  DBUG_ASSERT(rli->sql_thd==thd);
+  DBUG_ASSERT(rli->info_thd==thd);
 
   if (sql_slave_killed(thd,rli))
   {
@@ -2199,16 +2309,20 @@ static int exec_relay_log_event(THD* thd
 	  Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
 	  there is no rollback since 5.0.13 (ref: manual).
           We have to not only seek but also
-          a) init_master_info(), to seek back to hot relay log's start for later
+          a) init_info(), to seek back to hot relay log's start for later
           (for when we will come back to this hot log after re-processing the
           possibly existing old logs where BEGIN is: check_binlog_magic() will
           then need the cache to be at position 0 (see comments at beginning of
-          init_master_info()).
+          init_info()).
           b) init_relay_log_pos(), because the BEGIN may be an older relay log.
         */
         if (rli->trans_retries < slave_trans_retries)
         {
-          if (init_master_info(rli->mi, 0, 0, 0, SLAVE_SQL))
+          /*
+             We need to figure out if there is a test case that covers
+             this part. \Alfranio.
+          */
+          if (init_info(rli->mi, FALSE, SLAVE_SQL))
             sql_print_error("Failed to initialize the master info structure");
           else if (init_relay_log_pos(rli,
                                       rli->group_relay_log_name,
@@ -2361,7 +2475,7 @@ pthread_handler_t handle_slave_io(void *
   THD *thd; // needs to be first for thread_stack
   MYSQL *mysql;
   Master_info *mi = (Master_info*)arg;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   char llbuff[22];
   uint retry_count;
   bool suppress_warnings;
@@ -2388,10 +2502,12 @@ pthread_handler_t handle_slave_io(void *
   mi->slave_run_id++;
 
 #ifndef DBUG_OFF
-  mi->events_till_disconnect = disconnect_slave_event_count;
+  mi->events_until_exit = disconnect_slave_event_count;
 #endif
 
-  mi->io_thd = thd;
+  thd= new THD; // note that contructor of THD uses DBUG_ !
+  THD_CHECK_SENTRY(thd);
+  mi->info_thd = thd;
 
   pthread_detach_this_thread();
   thd->thread_stack= (char*) &thd; // remember where our stack is
@@ -2459,7 +2575,7 @@ connected:
   if (get_master_version_and_clock(mysql, mi))
     goto err;
 
-  if (mi->rli.relay_log.description_event_for_queue->binlog_version > 1)
+  if (mi->rli->relay_log.description_event_for_queue->binlog_version > 1)
   {
     /*
       Register ourselves with the master.
@@ -2592,19 +2708,19 @@ Stopping slave I/O thread due to out-of-
                  (thd, mi, event_buf, event_len, synced)))
       goto err;
 
-    if (flush_master_info(mi, 1))
+    if (flush_master_info(mi))
     {
-      sql_print_error("Failed to flush master info file");
+      sql_print_error("Failed to flush master info");
       goto err;
     }
     /*
       See if the relay logs take too much space.
-      We don't lock mi->rli.log_space_lock here; this dirty read saves time
+      We don't lock mi->rli->log_space_lock here; this dirty read saves time
       and does not introduce any problem:
-      - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so
+      - if mi->rli->ignore_log_space_limit is 1 but becomes 0 just after (so
       the clean value is 0), then we are reading only one more event as we
       should, and we'll block only at the next event. No big deal.
-      - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so
+      - if mi->rli->ignore_log_space_limit is 0 but becomes 1 just after (so
       the clean value is 1), then we are going into wait_for_relay_log_space()
       for no reason, but this function will do a clean read, notice the clean
       value and exit immediately.
@@ -2662,8 +2778,8 @@ err:
   MYSQL_MUTEX_LOCK(&mi->run_lock);
 
   /* Forget the relay log's format */
-  delete mi->rli.relay_log.description_event_for_queue;
-  mi->rli.relay_log.description_event_for_queue= 0;
+  delete mi->rli->relay_log.description_event_for_queue;
+  mi->rli->relay_log.description_event_for_queue= 0;
   // TODO: make rpl_status part of Master_info
   change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
   DBUG_ASSERT(thd->net.buff != 0);
@@ -2675,7 +2791,7 @@ err:
   MYSQL_MUTEX_UNLOCK(&LOCK_thread_count);
   mi->abort_slave= 0;
   mi->slave_running= 0;
-  mi->io_thd= 0;
+  mi->info_thd= 0;
   /*
     Note: the order of the two following calls (first broadcast, then unlock)
     is important. Otherwise a killer_thread can execute between the calls and
@@ -2737,7 +2853,7 @@ pthread_handler_t handle_slave_sql(void
   THD *thd;                     /* needs to be first for thread_stack */
   char llbuff[22],llbuff1[22];
 
-  Relay_log_info* rli = &((Master_info*)arg)->rli;
+  Relay_log_info* rli = ((Master_info*)arg)->rli;
   const char *errmsg;
 
   // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
@@ -2756,10 +2872,12 @@ pthread_handler_t handle_slave_sql(void
   DBUG_ASSERT(!rli->slave_running);
   errmsg= 0;
 #ifndef DBUG_OFF
-  rli->events_till_abort = abort_slave_event_count;
+  rli->events_until_exit = abort_slave_event_count;
 #endif
 
-  rli->sql_thd= thd;
+  thd = new THD; // note that contructor of THD uses DBUG_ !
+  thd->thread_stack = (char*)&thd; // remember where our stack is
+  rli->info_thd= thd;
   
   /* Inform waiting threads that slave has started */
   rli->slave_run_id++;
@@ -2848,7 +2966,7 @@ pthread_handler_t handle_slave_sql(void
 #endif
   }
 #endif
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   DBUG_PRINT("master_info",("log_file_name: %s  position: %s",
                             rli->group_master_log_name,
@@ -2903,7 +3021,7 @@ Slave SQL thread aborted. Can't execute
   while (!sql_slave_killed(thd,rli))
   {
     thd_proc_info(thd, "Reading event from the relay log");
-    DBUG_ASSERT(rli->sql_thd == thd);
+    DBUG_ASSERT(rli->info_thd == thd);
     THD_CHECK_SENTRY(thd);
 
     sql_print_information("new_mode %u", thd->variables.new_mode);
@@ -3019,9 +3137,9 @@ the slave SQL thread with \"SLAVE START\
   thd->temporary_tables = 0; // remove tempation from destructor to close them
   DBUG_ASSERT(thd->net.buff != 0);
   net_end(&thd->net); // destructor will not free it, because we are weird
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
   THD_CHECK_SENTRY(thd);
-  rli->sql_thd= 0;
+  rli->info_thd= 0;
   MYSQL_MUTEX_LOCK(&LOCK_thread_count);
   THD_CHECK_SENTRY(thd);
   delete thd;
@@ -3049,7 +3167,7 @@ static int process_io_create_file(Master
   int error = 1;
   ulong num_bytes;
   bool cev_not_written;
-  THD *thd = mi->io_thd;
+  THD *thd = mi->info_thd;
   NET *net = &mi->mysql->net;
   DBUG_ENTER("process_io_create_file");
 
@@ -3103,21 +3221,21 @@ static int process_io_create_file(Master
           break;
         Execute_load_log_event xev(thd,0,0);
         xev.log_pos = cev->log_pos;
-        if (unlikely(mi->rli.relay_log.append(&xev)))
+        if (unlikely(mi->rli->relay_log.append(&xev)))
         {
           mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
                      ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
                      "error writing Exec_load event to relay log");
           goto err;
         }
-        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        mi->rli->relay_log.harvest_bytes_written(&mi->rli->log_space_total);
         break;
       }
       if (unlikely(cev_not_written))
       {
         cev->block = net->read_pos;
         cev->block_len = num_bytes;
-        if (unlikely(mi->rli.relay_log.append(cev)))
+        if (unlikely(mi->rli->relay_log.append(cev)))
         {
           mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
                      ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
@@ -3125,21 +3243,21 @@ static int process_io_create_file(Master
           goto err;
         }
         cev_not_written=0;
-        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        mi->rli->relay_log.harvest_bytes_written(&mi->rli->log_space_total);
       }
       else
       {
         aev.block = net->read_pos;
         aev.block_len = num_bytes;
         aev.log_pos = cev->log_pos;
-        if (unlikely(mi->rli.relay_log.append(&aev)))
+        if (unlikely(mi->rli->relay_log.append(&aev)))
         {
           mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
                      ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
                      "error writing Append_block event to relay log");
           goto err;
         }
-        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ;
+        mi->rli->relay_log.harvest_bytes_written(&mi->rli->log_space_total) ;
       }
     }
   }
@@ -3190,7 +3308,7 @@ static int process_io_rotate(Master_info
     rotate event forever, so we need to not disconnect after one.
   */
   if (disconnect_slave_event_count)
-    mi->events_till_disconnect++;
+    mi->events_until_exit++;
 #endif
 
   /*
@@ -3200,11 +3318,11 @@ static int process_io_rotate(Master_info
     no need to reset description_event_for_queue now. And if it's nothing (same
     master version as before), no need (still using the slave's format).
   */
-  if (mi->rli.relay_log.description_event_for_queue->binlog_version >= 4)
+  if (mi->rli->relay_log.description_event_for_queue->binlog_version >= 4)
   {
-    delete mi->rli.relay_log.description_event_for_queue;
+    delete mi->rli->relay_log.description_event_for_queue;
     /* start from format 3 (MySQL 4.0) again */
-    mi->rli.relay_log.description_event_for_queue= new
+    mi->rli->relay_log.description_event_for_queue= new
       Format_description_log_event(3);
   }
   /*
@@ -3226,7 +3344,7 @@ static int queue_binlog_ver_1_event(Mast
   ulong inc_pos;
   bool ignore_event= 0;
   char *tmp_buf = 0;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   DBUG_ENTER("queue_binlog_ver_1_event");
 
   /*
@@ -3260,7 +3378,7 @@ static int queue_binlog_ver_1_event(Mast
     connected to the master).
   */
   Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
-                                            mi->rli.relay_log.description_event_for_queue);
+                                            mi->rli->relay_log.description_event_for_queue);
   if (unlikely(!ev))
   {
     sql_print_error("Read invalid event from master: '%s',\
@@ -3343,12 +3461,12 @@ static int queue_binlog_ver_3_event(Mast
   const char *errmsg = 0;
   ulong inc_pos;
   char *tmp_buf = 0;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   DBUG_ENTER("queue_binlog_ver_3_event");
 
   /* read_log_event() will adjust log_pos to be end_log_pos */
   Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
-                                            mi->rli.relay_log.description_event_for_queue);
+                                            mi->rli->relay_log.description_event_for_queue);
   if (unlikely(!ev))
   {
     sql_print_error("Read invalid event from master: '%s',\
@@ -3406,7 +3524,7 @@ static int queue_old_event(Master_info *
 {
   DBUG_ENTER("queue_old_event");
 
-  switch (mi->rli.relay_log.description_event_for_queue->binlog_version)
+  switch (mi->rli->relay_log.description_event_for_queue->binlog_version)
   {
   case 1:
       DBUG_RETURN(queue_binlog_ver_1_event(mi,buf,event_len));
@@ -3414,7 +3532,7 @@ static int queue_old_event(Master_info *
       DBUG_RETURN(queue_binlog_ver_3_event(mi,buf,event_len));
   default: /* unsupported format; eg version 2 */
     DBUG_PRINT("info",("unsupported binlog format %d in queue_old_event()",
-                       mi->rli.relay_log.description_event_for_queue->binlog_version));
+                       mi->rli->relay_log.description_event_for_queue->binlog_version));
     DBUG_RETURN(1);
   }
 }
@@ -3434,14 +3552,14 @@ static int queue_event(Master_info* mi,c
   int error= 0;
   String error_msg;
   ulong inc_pos;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   mysql_mutex_t *log_lock= rli->relay_log.get_log_lock();
   ulong s_id;
   DBUG_ENTER("queue_event");
 
   LINT_INIT(inc_pos);
 
-  if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
+  if (mi->rli->relay_log.description_event_for_queue->binlog_version<4 &&
       buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */)
     DBUG_RETURN(queue_old_event(mi,buf,event_len));
 
@@ -3465,7 +3583,7 @@ static int queue_event(Master_info* mi,c
     goto err;
   case ROTATE_EVENT:
   {
-    Rotate_log_event rev(buf,event_len,mi->rli.relay_log.description_event_for_queue);
+    Rotate_log_event rev(buf,event_len,mi->rli->relay_log.description_event_for_queue);
     if (unlikely(process_io_rotate(mi,&rev)))
     {
       error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
@@ -3493,13 +3611,13 @@ static int queue_event(Master_info* mi,c
     const char* errmsg;
     if (!(tmp= (Format_description_log_event*)
           Log_event::read_log_event(buf, event_len, &errmsg,
-                                    mi->rli.relay_log.description_event_for_queue)))
+                                    mi->rli->relay_log.description_event_for_queue)))
     {
       error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
       goto err;
     }
-    delete mi->rli.relay_log.description_event_for_queue;
-    mi->rli.relay_log.description_event_for_queue= tmp;
+    delete mi->rli->relay_log.description_event_for_queue;
+    mi->rli->relay_log.description_event_for_queue= tmp;
     /*
        Though this does some conversion to the slave's format, this will
        preserve the master's binlog format version, and number of event types.
@@ -3510,7 +3628,7 @@ static int queue_event(Master_info* mi,c
     */
     inc_pos= uint4korr(buf+LOG_POS_OFFSET) ? event_len : 0;
     DBUG_PRINT("info",("binlog format is now %d",
-                       mi->rli.relay_log.description_event_for_queue->binlog_version));
+                       mi->rli->relay_log.description_event_for_queue->binlog_version));
 
   }
   break;
@@ -3521,7 +3639,7 @@ static int queue_event(Master_info* mi,c
       HB (heartbeat) cannot come before RL (Relay)
     */
     char  llbuf[22];
-    Heartbeat_log_event hb(buf, event_len, mi->rli.relay_log.description_event_for_queue);
+    Heartbeat_log_event hb(buf, event_len, mi->rli->relay_log.description_event_for_queue);
     if (!hb.is_valid())
     {
       error= ER_SLAVE_HEARTBEAT_FAILURE;
@@ -3584,7 +3702,7 @@ static int queue_event(Master_info* mi,c
 
   MYSQL_MUTEX_LOCK(log_lock);
   s_id= uint4korr(buf + SERVER_ID_OFFSET);
-  if ((s_id == ::server_id && !mi->rli.replicate_same_server_id) ||
+  if ((s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
       /*
         the following conjunction deals with IGNORE_SERVER_IDS, if set
         If the master is on the ignore list, execution of
@@ -3615,7 +3733,7 @@ static int queue_event(Master_info* mi,c
       IGNORE_SERVER_IDS it increments mi->master_log_pos
       as well as rli->group_relay_log_pos.
     */
-    if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) ||
+    if (!(s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
         buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT &&
         buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT &&
         buf[EVENT_TYPE_OFFSET] != STOP_EVENT)
@@ -3660,36 +3778,6 @@ err:
 }
 
 
-void end_relay_log_info(Relay_log_info* rli)
-{
-  DBUG_ENTER("end_relay_log_info");
-
-  if (!rli->inited)
-    DBUG_VOID_RETURN;
-  if (rli->info_fd >= 0)
-  {
-    end_io_cache(&rli->info_file);
-    (void) MYSQL_CLOSE(rli->info_fd, MYF(MY_WME));
-    rli->info_fd = -1;
-  }
-  if (rli->cur_log_fd >= 0)
-  {
-    end_io_cache(&rli->cache_buf);
-    (void) MYSQL_CLOSE(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
-  }
-  rli->inited = 0;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  rli->relay_log.harvest_bytes_written(&rli->log_space_total);
-  /*
-    Delete the slave's temporary tables from memory.
-    In the future there will be other actions than this, to ensure persistance
-    of slave's temp tables after shutdown.
-  */
-  rli->close_temporary_tables();
-  DBUG_VOID_RETURN;
-}
-
 /*
   Try to connect until successful or slave killed
 
@@ -3731,7 +3819,7 @@ static int connect_to_master(THD* thd, M
   DBUG_ENTER("connect_to_master");
 
 #ifndef DBUG_OFF
-  mi->events_till_disconnect = disconnect_slave_event_count;
+  mi->events_until_exit = disconnect_slave_event_count;
 #endif
   ulong client_flag= CLIENT_REMEMBER_OPTIONS;
   if (opt_slave_compressed_protocol)
@@ -3895,72 +3983,6 @@ MYSQL *rpl_connect_master(MYSQL *mysql)
 }
 
 /*
-  Store the file and position where the execute-slave thread are in the
-  relay log.
-
-  SYNOPSIS
-    flush_relay_log_info()
-    rli                 Relay log information
-
-  NOTES
-    - As this is only called by the slave thread, we don't need to
-      have a lock on this.
-    - If there is an active transaction, then we don't update the position
-      in the relay log.  This is to ensure that we re-execute statements
-      if we die in the middle of an transaction that was rolled back.
-    - As a transaction never spans binary logs, we don't have to handle the
-      case where we do a relay-log-rotation in the middle of the transaction.
-      If this would not be the case, we would have to ensure that we
-      don't delete the relay log file where the transaction started when
-      we switch to a new relay log file.
-
-  TODO
-    - Change the log file information to a binary format to avoid calling
-      longlong2str.
-
-  RETURN VALUES
-    0   ok
-    1   write error
-*/
-
-bool flush_relay_log_info(Relay_log_info* rli)
-{
-  bool error=0;
-  DBUG_ENTER("flush_relay_log_info");
-
-  if (unlikely(rli->no_storage))
-    DBUG_RETURN(0);
-
-  IO_CACHE *file = &rli->info_file;
-  char buff[FN_REFLEN*2+22*2+4], *pos;
-
-  my_b_seek(file, 0L);
-  pos=strmov(buff, rli->group_relay_log_name);
-  *pos++='\n';
-  pos=longlong2str(rli->group_relay_log_pos, pos, 10);
-  *pos++='\n';
-  pos=strmov(pos, rli->group_master_log_name);
-  *pos++='\n';
-  pos=longlong2str(rli->group_master_log_pos, pos, 10);
-  *pos='\n';
-  if (my_b_write(file, (uchar*) buff, (size_t) (pos-buff)+1))
-    error=1;
-  if (flush_io_cache(file))
-    error=1;
-  if (sync_relayloginfo_period &&
-      !error &&
-      ++(rli->sync_counter) >= sync_relayloginfo_period)
-  {
-    if (my_sync(rli->info_fd, MYF(MY_WME)))
-      error=1;
-    rli->sync_counter= 0;
-  }
-  /* Flushing the relay log is done by the slave I/O thread */
-  DBUG_RETURN(error);
-}
-
-
-/*
   Called when we notice that the current "hot" log got rotated under our feet.
 */
 
@@ -4001,13 +4023,13 @@ static Log_event* next_event(Relay_log_i
   IO_CACHE* cur_log = rli->cur_log;
   mysql_mutex_t *log_lock = rli->relay_log.get_log_lock();
   const char* errmsg=0;
-  THD* thd = rli->sql_thd;
+  THD* thd = rli->info_thd;
   DBUG_ENTER("next_event");
 
   DBUG_ASSERT(thd != 0);
 
 #ifndef DBUG_OFF
-  if (abort_slave_event_count && !rli->events_till_abort--)
+  if (abort_slave_event_count && !rli->events_until_exit--)
     DBUG_RETURN(0);
 #endif
 
@@ -4087,7 +4109,7 @@ static Log_event* next_event(Relay_log_i
                                       rli->relay_log.description_event_for_exec)))
 
     {
-      DBUG_ASSERT(thd==rli->sql_thd);
+      DBUG_ASSERT(thd==rli->info_thd);
       /*
         read it while we have a lock, to avoid a mutex lock in
         inc_event_relay_log_pos()
@@ -4097,7 +4119,7 @@ static Log_event* next_event(Relay_log_i
         MYSQL_MUTEX_UNLOCK(log_lock);
       DBUG_RETURN(ev);
     }
-    DBUG_ASSERT(thd==rli->sql_thd);
+    DBUG_ASSERT(thd==rli->info_thd);
     if (opt_reckless_slave)                     // For mysql-test
       cur_log->error = 0;
     if (cur_log->error < 0)
@@ -4204,7 +4226,7 @@ static Log_event* next_event(Relay_log_i
         MYSQL_MUTEX_UNLOCK(&rli->log_space_lock);
         MYSQL_COND_BROADCAST(&rli->log_space_cond);
         // Note that wait_for_update_relay_log unlocks lock_log !
-        rli->relay_log.wait_for_update_relay_log(rli->sql_thd);
+        rli->relay_log.wait_for_update_relay_log(rli->info_thd);
         // re-acquire data lock since we released it earlier
         MYSQL_MUTEX_LOCK(&rli->data_lock);
         rli->last_master_timestamp= save_timestamp;
@@ -4259,7 +4281,7 @@ static Log_event* next_event(Relay_log_i
         rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE;
         strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
                 sizeof(rli->event_relay_log_name)-1);
-        flush_relay_log_info(rli);
+        rli->flush_info();
       }
 
       /*
@@ -4359,7 +4381,7 @@ err:
 void rotate_relay_log(Master_info* mi)
 {
   DBUG_ENTER("rotate_relay_log");
-  Relay_log_info* rli= &mi->rli;
+  Relay_log_info* rli= mi->rli;
 
   DBUG_EXECUTE_IF("crash_before_rotate_relaylog", DBUG_ABORT(););
 
@@ -4490,9 +4512,9 @@ bool rpl_master_has_bug(const Relay_log_
  */
 bool rpl_master_erroneous_autoinc(THD *thd)
 {
-  if (active_mi && active_mi->rli.sql_thd == thd)
+  if (active_mi && active_mi->rli->info_thd == thd)
   {
-    Relay_log_info *rli= &active_mi->rli;
+    Relay_log_info *rli= active_mi->rli;
     DBUG_EXECUTE_IF("simulate_bug33029", return TRUE;);
     return rpl_master_has_bug(rli, 33029, FALSE, NULL, NULL);
   }

=== modified file 'sql/slave.h'
--- a/sql/slave.h	2009-03-26 15:35:49 +0000
+++ b/sql/slave.h	2009-04-17 15:45:46 +0000
@@ -145,14 +145,16 @@ extern ulonglong relay_log_space_limit;
 
 int init_slave();
 int init_recovery(Master_info* mi, const char** errmsg);
+int init_info(Master_info* mi, bool abort_if_no_info, int thread_mask);
+void end_info(Master_info* mi);
+int reset_info(Master_info* mi);
+int flush_master_info(Master_info* mi);
 void init_slave_skip_errors(const char* arg);
-bool flush_relay_log_info(Relay_log_info* rli);
 int register_slave_on_master(MYSQL* mysql);
 int terminate_slave_threads(Master_info* mi, int thread_mask,
 			     bool skip_lock = 0);
 int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
-			Master_info* mi, const char* master_info_fname,
-			const char* slave_info_fname, int thread_mask);
+			Master_info* mi, int thread_mask);
 /*
   cond_lock is usually same as start_lock. It is needed for the case when
   start_lock is 0 which happens if start_slave_thread() is called already
@@ -187,7 +189,6 @@ void skip_load_data_infile(NET* net);
 void end_slave(); /* clean up */
 void clear_until_condition(Relay_log_info* rli);
 void clear_slave_error(Relay_log_info* rli);
-void end_relay_log_info(Relay_log_info* rli);
 void lock_slave_threads(Master_info* mi);
 void unlock_slave_threads(Master_info* mi);
 void init_thread_mask(int* mask,Master_info* mi,bool inverse);
@@ -206,7 +207,7 @@ int apply_event_and_update_pos(Log_event
 pthread_handler_t handle_slave_io(void *arg);
 pthread_handler_t handle_slave_sql(void *arg);
 extern bool volatile abort_loop;
-extern Master_info main_mi, *active_mi; /* active_mi for multi-master */
+extern Master_info *active_mi;      /* active_mi  for multi-master */
 extern LIST master_list;
 extern my_bool replicate_same_server_id;
 

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2009-04-13 16:15:22 +0000
+++ b/sql/sp_head.cc	2009-04-17 15:45:46 +0000
@@ -1517,7 +1517,7 @@ sp_head::execute_trigger(THD *thd,
   if (!(grant_info->privilege & TRIGGER_ACL))
   {
     char priv_desc[128];
-    get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL);
+    get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL, FALSE);
 
     my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc,
              thd->security_ctx->priv_user, thd->security_ctx->host_or_ip,

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2009-04-13 16:15:22 +0000
+++ b/sql/sql_acl.cc	2009-04-17 15:45:46 +0000
@@ -3014,7 +3014,7 @@ int mysql_table_grant(THD *thd, TABLE_LI
       {
         char command[128];
         get_privilege_desc(command, sizeof(command),
-                           table_list->grant.want_privilege);
+                           table_list->grant.want_privilege, FALSE);
         my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
                  command, thd->security_ctx->priv_user,
                  thd->security_ctx->host_or_ip, table_list->alias);
@@ -3992,7 +3992,7 @@ err:
   if (!no_errors)				// Not a silent skip of table
   {
     char command[128];
-    get_privilege_desc(command, sizeof(command), want_access);
+    get_privilege_desc(command, sizeof(command), want_access, FALSE);
     my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
              command,
              sctx->priv_user,
@@ -4148,7 +4148,7 @@ bool check_grant_column(THD *thd, GRANT_
 err:
   MYSQL_RWLOCK_UNLOCK(&LOCK_grant);
   char command[128];
-  get_privilege_desc(command, sizeof(command), want_access);
+  get_privilege_desc(command, sizeof(command), want_access, FALSE);
   my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
            command,
            sctx->priv_user,
@@ -4310,7 +4310,7 @@ err:
   MYSQL_RWLOCK_UNLOCK(&LOCK_grant);
 
   char command[128];
-  get_privilege_desc(command, sizeof(command), want_access);
+  get_privilege_desc(command, sizeof(command), want_access, FALSE);
   /*
     Do not give an error message listing a column name unless the user has
     privilege to see all columns.
@@ -5062,16 +5062,25 @@ static int show_routine_grants(THD* thd,
   return error;
 }
 
-/*
+/**
   Make a clear-text version of the requested privilege.
+
+  @param to         pointer to the buffer
+  @param max_length max length of the description message allowed
+  @param access     privileges to check for access
+  @param any        if TRUE, any of the privileges is sufficient,
+                    if FALSE, all privileges are required
 */
 
-void get_privilege_desc(char *to, uint max_length, ulong access)
+void get_privilege_desc(char *to, uint max_length, ulong access, bool any)
 {
   uint pos;
   char *start=to;
+  char sep=',';
   DBUG_ASSERT(max_length >= 30);		// For end ',' removal
 
+  if (any)
+    sep= '|';
   if (access)
   {
     max_length--;				// Reserve place for end-zero
@@ -5081,7 +5090,7 @@ void get_privilege_desc(char *to, uint m
 	  command_lengths[pos] + (uint) (to-start) < max_length)
       {
 	to= strmov(to, command_array[pos]);
-	*to++=',';
+	*to++= sep;
       }
     }
     to--;					// Remove end ','

=== modified file 'sql/sql_acl.h'
--- a/sql/sql_acl.h	2009-03-26 06:08:24 +0000
+++ b/sql/sql_acl.h	2009-04-02 08:50:24 +0000
@@ -261,7 +261,7 @@ ulong get_column_grant(THD *thd, GRANT_I
                        const char *db_name, const char *table_name,
                        const char *field_name);
 bool mysql_show_grants(THD *thd, LEX_USER *user);
-void get_privilege_desc(char *to, uint max_length, ulong access);
+void get_privilege_desc(char *to, uint max_length, ulong access, bool any);
 void get_mqh(const char *user, const char *host, USER_CONN *uc);
 bool mysql_create_user(THD *thd, List <LEX_USER> &list);
 bool mysql_drop_user(THD *thd, List <LEX_USER> &list);

=== modified file 'sql/sql_binlog.cc'
--- a/sql/sql_binlog.cc	2009-03-25 00:04:41 +0000
+++ b/sql/sql_binlog.cc	2009-04-10 03:21:51 +0000
@@ -14,7 +14,7 @@
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
 #include "mysql_priv.h"
-#include "rpl_rli.h"
+#include "rpl_rli_file.h"
 #include "base64.h"
 
 /**
@@ -58,7 +58,7 @@ void mysql_client_binlog_statement(THD*
   my_bool have_fd_event= TRUE;
   if (!thd->rli_fake)
   {
-    thd->rli_fake= new Relay_log_info(FALSE);
+    thd->rli_fake= new Relay_log_info_file(FALSE, "fake");
 #ifdef HAVE_purify
     thd->rli_fake->is_fake= TRUE;
 #endif
@@ -86,7 +86,7 @@ void mysql_client_binlog_statement(THD*
     goto end;
   }
 
-  thd->rli_fake->sql_thd= thd;
+  thd->rli_fake->info_thd= thd;
   thd->rli_fake->no_storage= TRUE;
 
   for (char const *strptr= thd->lex->comment.str ;

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2009-04-14 21:37:16 +0000
+++ b/sql/sql_insert.cc	2009-04-17 15:45:46 +0000
@@ -708,7 +708,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   if (thd->slave_thread &&
       (info.handle_duplicates == DUP_UPDATE) &&
       (table->next_number_field != NULL) &&
-      rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL))
+      rpl_master_has_bug(active_mi->rli, 24432, TRUE, NULL, NULL))
     goto abort;
 #endif
 
@@ -3084,7 +3084,7 @@ select_insert::prepare(List<Item> &value
   if (thd->slave_thread &&
       (info.handle_duplicates == DUP_UPDATE) &&
       (table->next_number_field != NULL) &&
-      rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL))
+      rpl_master_has_bug(active_mi->rli, 24432, TRUE, NULL, NULL))
     DBUG_RETURN(1);
 #endif
 

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2009-04-13 16:15:22 +0000
+++ b/sql/sql_load.cc	2009-04-17 15:45:46 +0000
@@ -328,8 +328,8 @@ int mysql_load(THD *thd,sql_exchange *ex
       if (thd->slave_thread)
       {
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-        if (strncmp(active_mi->rli.slave_patternload_file, name,
-            active_mi->rli.slave_patternload_file_size))
+        if (strncmp(active_mi->rli->slave_patternload_file, name,
+            active_mi->rli->slave_patternload_file_size))
         {
           /*
             LOAD DATA INFILE in the slave SQL Thread can only read from

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2009-04-13 16:15:22 +0000
+++ b/sql/sql_parse.cc	2009-04-17 15:45:46 +0000
@@ -5538,7 +5538,7 @@ bool check_global_access(THD *thd, ulong
   char command[128];
   if ((thd->security_ctx->master_access & want_access))
     return 0;
-  get_privilege_desc(command, sizeof(command), want_access);
+  get_privilege_desc(command, sizeof(command), want_access, TRUE);
   my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
   return 1;
 #else

=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc	2009-04-14 21:37:16 +0000
+++ b/sql/sql_repl.cc	2009-04-17 15:45:46 +0000
@@ -173,7 +173,7 @@ static int send_file(THD *thd)
 
   TODO
     - Inform the slave threads that they should sync the position
-      in the binary log file with flush_relay_log_info.
+      in the binary log file with flush_info.
       Now they sync is done for next read.
 */
 
@@ -1094,8 +1094,7 @@ int start_slave(THD* thd , Master_info*
     thread_mask&= thd->lex->slave_thd_opt;
   if (thread_mask) //some threads are stopped, start them
   {
-    if (init_master_info(mi,master_info_file,relay_log_info_file, 0,
-			 thread_mask))
+    if (init_info(mi, FALSE, thread_mask))
       slave_errno=ER_MASTER_INFO;
     else if (server_id_supplied && *mi->host)
     {
@@ -1106,38 +1105,38 @@ int start_slave(THD* thd , Master_info*
       */
       if (thread_mask & SLAVE_SQL)
       {
-        MYSQL_MUTEX_LOCK(&mi->rli.data_lock);
+        MYSQL_MUTEX_LOCK(&mi->rli->data_lock);
 
         if (thd->lex->mi.pos)
         {
-          mi->rli.until_condition= Relay_log_info::UNTIL_MASTER_POS;
-          mi->rli.until_log_pos= thd->lex->mi.pos;
+          mi->rli->until_condition= Relay_log_info::UNTIL_MASTER_POS;
+          mi->rli->until_log_pos= thd->lex->mi.pos;
           /*
              We don't check thd->lex->mi.log_file_name for NULL here
              since it is checked in sql_yacc.yy
           */
-          strmake(mi->rli.until_log_name, thd->lex->mi.log_file_name,
-                  sizeof(mi->rli.until_log_name)-1);
+          strmake(mi->rli->until_log_name, thd->lex->mi.log_file_name,
+                  sizeof(mi->rli->until_log_name)-1);
         }
         else if (thd->lex->mi.relay_log_pos)
         {
-          mi->rli.until_condition= Relay_log_info::UNTIL_RELAY_POS;
-          mi->rli.until_log_pos= thd->lex->mi.relay_log_pos;
-          strmake(mi->rli.until_log_name, thd->lex->mi.relay_log_name,
-                  sizeof(mi->rli.until_log_name)-1);
+          mi->rli->until_condition= Relay_log_info::UNTIL_RELAY_POS;
+          mi->rli->until_log_pos= thd->lex->mi.relay_log_pos;
+          strmake(mi->rli->until_log_name, thd->lex->mi.relay_log_name,
+                  sizeof(mi->rli->until_log_name)-1);
         }
         else
-          mi->rli.clear_until_condition();
+          mi->rli->clear_until_condition();
 
-        if (mi->rli.until_condition != Relay_log_info::UNTIL_NONE)
+        if (mi->rli->until_condition != Relay_log_info::UNTIL_NONE)
         {
           /* Preparing members for effective until condition checking */
-          const char *p= fn_ext(mi->rli.until_log_name);
+          const char *p= fn_ext(mi->rli->until_log_name);
           char *p_end;
           if (*p)
           {
             //p points to '.'
-            mi->rli.until_log_name_extension= strtoul(++p,&p_end, 10);
+            mi->rli->until_log_name_extension= strtoul(++p,&p_end, 10);
             /*
               p_end points to the first invalid character. If it equals
               to p, no digits were found, error. If it contains '\0' it
@@ -1150,7 +1149,7 @@ int start_slave(THD* thd , Master_info*
             slave_errno=ER_BAD_SLAVE_UNTIL_COND;
 
           /* mark the cached result of the UNTIL comparison as "undefined" */
-          mi->rli.until_log_names_cmp_result=
+          mi->rli->until_log_names_cmp_result=
             Relay_log_info::UNTIL_LOG_NAMES_CMP_UNKNOWN;
 
           /* Issuing warning then started without --skip-slave-start */
@@ -1160,7 +1159,7 @@ int start_slave(THD* thd , Master_info*
                          ER(ER_MISSING_SKIP_SLAVE));
         }
 
-        MYSQL_MUTEX_UNLOCK(&mi->rli.data_lock);
+        MYSQL_MUTEX_UNLOCK(&mi->rli->data_lock);
       }
       else if (thd->lex->mi.pos || thd->lex->mi.relay_log_pos)
         push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_UNTIL_COND_IGNORED,
@@ -1170,7 +1169,6 @@ int start_slave(THD* thd , Master_info*
         slave_errno = start_slave_threads(0 /*no mutex */,
 					1 /* wait for start */,
 					mi,
-					master_info_file,relay_log_info_file,
 					thread_mask);
     }
     else
@@ -1276,8 +1274,6 @@ int stop_slave(THD* thd, Master_info* mi
 */
 int reset_slave(THD *thd, Master_info* mi)
 {
-  MY_STAT stat_area;
-  char fname[FN_REFLEN];
   int thread_mask= 0, error= 0;
   uint sql_errno=0;
   const char* errmsg=0;
@@ -1296,35 +1292,17 @@ int reset_slave(THD *thd, Master_info* m
     goto err;
 
   // delete relay logs, clear relay log coordinates
-  if ((error= purge_relay_logs(&mi->rli, thd,
+  if ((error= purge_relay_logs(mi->rli, thd,
 			       1 /* just reset */,
 			       &errmsg)))
     goto err;
 
   /* Clear master's log coordinates */
   init_master_log_pos(mi);
-  /*
-     Reset errors (the idea is that we forget about the
-     old master).
-  */
-  mi->clear_error();
-  mi->rli.clear_error();
-  mi->rli.clear_until_condition();
-
-  // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
-  end_master_info(mi);
-  // and delete these two files
-  fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
-  if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
-  {
-    error=1;
-    goto err;
-  }
-  // delete relay_log_info_file
-  fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-  if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
+
+  if (reset_info(mi))
   {
-    error=1;
+    error= 1;
     goto err;
   }
 
@@ -1413,6 +1391,7 @@ bool change_master(THD* thd, Master_info
     ret= TRUE;
     goto err;
   }
+  thread_mask= SLAVE_IO | SLAVE_SQL;
 
   thd_proc_info(thd, "Changing master");
   /* 
@@ -1429,9 +1408,7 @@ bool change_master(THD* thd, Master_info
     DBUG_RETURN(TRUE);
   }
 
-  // TODO: see if needs re-write
-  if (init_master_info(mi, master_info_file, relay_log_info_file, 0,
-		       thread_mask))
+  if (init_info(mi, FALSE, thread_mask))
   {
     my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
     ret= TRUE;
@@ -1536,16 +1513,16 @@ bool change_master(THD* thd, Master_info
   if (lex_mi->relay_log_name)
   {
     need_relay_log_purge= 0;
-    strmake(mi->rli.group_relay_log_name,lex_mi->relay_log_name,
-	    sizeof(mi->rli.group_relay_log_name)-1);
-    strmake(mi->rli.event_relay_log_name,lex_mi->relay_log_name,
-	    sizeof(mi->rli.event_relay_log_name)-1);
+    strmake(mi->rli->group_relay_log_name,lex_mi->relay_log_name,
+	    sizeof(mi->rli->group_relay_log_name)-1);
+    strmake(mi->rli->event_relay_log_name,lex_mi->relay_log_name,
+	    sizeof(mi->rli->event_relay_log_name)-1);
   }
 
   if (lex_mi->relay_log_pos)
   {
     need_relay_log_purge= 0;
-    mi->rli.group_relay_log_pos= mi->rli.event_relay_log_pos= lex_mi->relay_log_pos;
+    mi->rli->group_relay_log_pos= mi->rli->event_relay_log_pos= lex_mi->relay_log_pos;
   }
 
   /*
@@ -1567,22 +1544,22 @@ bool change_master(THD* thd, Master_info
       need_relay_log_purge)
    {
      /*
-       Sometimes mi->rli.master_log_pos == 0 (it happens when the SQL thread is
+       Sometimes mi->rli->master_log_pos == 0 (it happens when the SQL thread is
        not initialized), so we use a max().
-       What happens to mi->rli.master_log_pos during the initialization stages
+       What happens to mi->rli->master_log_pos during the initialization stages
        of replication is not 100% clear, so we guard against problems using
        max().
       */
      mi->master_log_pos = max(BIN_LOG_HEADER_SIZE,
-			      mi->rli.group_master_log_pos);
-     strmake(mi->master_log_name, mi->rli.group_master_log_name,
+			      mi->rli->group_master_log_pos);
+     strmake(mi->master_log_name, mi->rli->group_master_log_name,
              sizeof(mi->master_log_name)-1);
   }
   /*
     Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never
     a slave before).
   */
-  if (flush_master_info(mi, 0))
+  if (mi->flush_info())
   {
     my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file");
     ret= TRUE;
@@ -1592,7 +1569,7 @@ bool change_master(THD* thd, Master_info
   {
     relay_log_purge= 1;
     thd_proc_info(thd, "Purging old relay logs");
-    if (purge_relay_logs(&mi->rli, thd,
+    if (purge_relay_logs(mi->rli, thd,
 			 0 /* not only reset, but also reinit */,
 			 &errmsg))
     {
@@ -1606,9 +1583,9 @@ bool change_master(THD* thd, Master_info
     const char* msg;
     relay_log_purge= 0;
     /* Relay log is already initialized */
-    if (init_relay_log_pos(&mi->rli,
-			   mi->rli.group_relay_log_name,
-			   mi->rli.group_relay_log_pos,
+    if (init_relay_log_pos(mi->rli,
+			   mi->rli->group_relay_log_name,
+			   mi->rli->group_relay_log_pos,
 			   0 /*no data lock*/,
 			   &msg, 0))
     {
@@ -1627,19 +1604,19 @@ bool change_master(THD* thd, Master_info
     ''/0: we have lost all copies of the original good coordinates.
     That's why we always save good coords in rli.
   */
-  mi->rli.group_master_log_pos= mi->master_log_pos;
+  mi->rli->group_master_log_pos= mi->master_log_pos;
   DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
-  strmake(mi->rli.group_master_log_name,mi->master_log_name,
-	  sizeof(mi->rli.group_master_log_name)-1);
+  strmake(mi->rli->group_master_log_name,mi->master_log_name,
+	  sizeof(mi->rli->group_master_log_name)-1);
 
-  if (!mi->rli.group_master_log_name[0]) // uninitialized case
-    mi->rli.group_master_log_pos=0;
+  if (!mi->rli->group_master_log_name[0]) // uninitialized case
+    mi->rli->group_master_log_pos=0;
 
-  MYSQL_MUTEX_LOCK(&mi->rli.data_lock);
-  mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */
+  MYSQL_MUTEX_LOCK(&mi->rli->data_lock);
+  mi->rli->abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */
   /* Clear the errors, for a clean start */
-  mi->rli.clear_error();
-  mi->rli.clear_until_condition();
+  mi->rli->clear_error();
+  mi->rli->clear_until_condition();
   /*
     If we don't write new coordinates to disk now, then old will remain in
     relay-log.info until START SLAVE is issued; but if mysqld is shutdown
@@ -1647,9 +1624,9 @@ bool change_master(THD* thd, Master_info
     in-memory value at restart (thus causing errors, as the old relay log does
     not exist anymore).
   */
-  flush_relay_log_info(&mi->rli);
+  mi->rli->flush_info();
   MYSQL_COND_BROADCAST(&mi->data_cond);
-  MYSQL_MUTEX_UNLOCK(&mi->rli.data_lock);
+  MYSQL_MUTEX_UNLOCK(&mi->rli->data_lock);
 
 err:
   unlock_slave_threads(mi);
@@ -2126,13 +2103,13 @@ bool sys_var_slave_skip_counter::check(T
 {
   int result= 0;
   MYSQL_MUTEX_LOCK(&LOCK_active_mi);
-  MYSQL_MUTEX_LOCK(&active_mi->rli.run_lock);
-  if (active_mi->rli.slave_running)
+  MYSQL_MUTEX_LOCK(&active_mi->rli->run_lock);
+  if (active_mi->rli->slave_running)
   {
     my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
     result=1;
   }
-  MYSQL_MUTEX_UNLOCK(&active_mi->rli.run_lock);
+  MYSQL_MUTEX_UNLOCK(&active_mi->rli->run_lock);
   MYSQL_MUTEX_UNLOCK(&LOCK_active_mi);
   var->save_result.ulong_value= (ulong) var->value->val_int();
   return result;
@@ -2142,19 +2119,19 @@ bool sys_var_slave_skip_counter::check(T
 bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
 {
   MYSQL_MUTEX_LOCK(&LOCK_active_mi);
-  MYSQL_MUTEX_LOCK(&active_mi->rli.run_lock);
+  MYSQL_MUTEX_LOCK(&active_mi->rli->run_lock);
   /*
     The following test should normally never be true as we test this
     in the check function;  To be safe against multiple
     SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
   */
-  if (!active_mi->rli.slave_running)
+  if (!active_mi->rli->slave_running)
   {
-    MYSQL_MUTEX_LOCK(&active_mi->rli.data_lock);
-    active_mi->rli.slave_skip_counter= var->save_result.ulong_value;
-    MYSQL_MUTEX_UNLOCK(&active_mi->rli.data_lock);
+    MYSQL_MUTEX_LOCK(&active_mi->rli->data_lock);
+    active_mi->rli->slave_skip_counter= var->save_result.ulong_value;
+    MYSQL_MUTEX_UNLOCK(&active_mi->rli->data_lock);
   }
-  MYSQL_MUTEX_UNLOCK(&active_mi->rli.run_lock);
+  MYSQL_MUTEX_UNLOCK(&active_mi->rli->run_lock);
   MYSQL_MUTEX_UNLOCK(&LOCK_active_mi);
   return 0;
 }

Thread
bzr commit into mysql-6.0-perf branch (marc.alff:2872) Marc Alff17 Apr