List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:January 17 2011 10:17am
Subject:bzr commit into mysql-trunk-bugfixing branch (alfranio.correia:3475)
Bug#58897
View as plain text  
#At file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/bug-58897/mysql-trunk-bugfixing/ based on revid:dao-gang.qu@stripped

 3475 Alfranio Correia	2011-01-17 [merge]
      BUG#58897 Rpl_info_table::do_is_transactional causes too much overhead
      
      After WL#2775, Slave's information,i.e. IO Thread and SQL Thread's information, can be
      stored into different types of repositories. The current implementation provides two
      repositories, i.e. FILE or TABLE, and any type of engine can be used.
      
      However, only transactional engines, such as Innodb, can provide a crash-safe behaviour
      in the sense that a slave can continue operating after a crash without requiring any
      manual-intervention.
      
      If a transactional table is in use, a different execution path is called to provide a
      crash-safe behaviour. Testing if a transactional engine is in use, unfortunately,
      requires to open and close the table, slave_relay_log_info, and this has a negative
      impact on performance.
      
      To fix this, we only allow to change the type of the repository when replication is
      stopped. We also have implemented the following changes:
      
      . Refactored Rpl_info_factory and removed unnecessary code.
      . Do not allow to change replication repository tables when replication is runnning,
        i.e., alter, drop, rename, etc.
      . Alerted when a configuration is not crash-safe.
     @ mysql-test/extra/rpl_tests/rpl_crash_safe.inc
        Updated test case.
     @ mysql-test/suite/rpl/r/rpl_migration_crash_safe.result
        Updated result file.
     @ mysql-test/suite/rpl/r/rpl_row_crash_safe.result
        Updated result file.
     @ mysql-test/suite/rpl/r/rpl_stm_mixed_crash_safe.result
        Updated result file.
     @ mysql-test/suite/rpl/t/rpl_migration_crash_safe.test
        Updated test case.
     @ mysql-test/suite/sys_vars/r/master_info_repository_basic.result
        Updated result file.
     @ mysql-test/suite/sys_vars/r/relay_log_info_repository_basic.result
        Updated result file.
     @ mysql-test/suite/sys_vars/t/master_info_repository_basic.test
        Updated test case.
     @ mysql-test/suite/sys_vars/t/relay_log_info_repository_basic.test
        Updated test case.
     @ scripts/mysql_install_db.pl.in
        Removed the option --rpl-engine.
     @ scripts/mysql_install_db.sh
        Removed the option --rpl-engine.
     @ sql/lock.cc
        Checked if a SYSTEM_THREAD_INFO_REPOSITORY is trying to acquire a lock.
     @ sql/rpl_info.cc
        Removed unnecessasry code as delete and my_free may be called when pointers
        are null.
     @ sql/rpl_info.h
        Improved design making constructor protected.
        
        Added set_rpl_info_type(), get_rpl_info_type(), get_rpl_info_handler()
        and update_transactional().
     @ sql/rpl_info_factory.cc
        Refactored it.
     @ sql/rpl_info_factory.h
        Refactored it.
     @ sql/rpl_info_file.cc
        Implemented do_update_transactional().
     @ sql/rpl_info_file.h
        Improved design making constructor private and Rpl_info_factory a friend.
     @ sql/rpl_info_handler.cc
        Removed unnecessasry code as delete and my_free may be called when pointers
        are null.
     @ sql/rpl_info_handler.h
        Defined do_update_transactional() and improved design making constructor protected.
     @ sql/rpl_info_table.cc
        Changed do do_is_transactional() and implemented do_update_transactional().
        
        Removed unnecessasry code as delete and my_free may be called when pointers
        are null.
     @ sql/rpl_info_table.h
        Introduced the member variable is_transactional that identifies if the
        table used as repository is transactional or not. This value is updated
        by calling do_update_transactional.
        
        Improved design making constructor private and Rpl_info_factory a friend.
     @ sql/rpl_info_table_access.cc
        Skipped security validation if doing updates through the Rpl_info_table_access and
        set thread information.
     @ sql/rpl_info_values.cc
        Removed unnecessary code as delete [] already calls the destructor.
     @ sql/rpl_mi.h
        Improved design making constructor private and Rpl_info_factory a friend.
     @ sql/rpl_rli.h
        Improved design making constructor private and Rpl_info_factory a friend.
     @ sql/rpl_slave.cc
        Added code to check if the current replication configuration is transactional
        and to alert when it is not.
     @ sql/share/errmsg-utf8.txt
        Added error message to be fired if a failure happens while changing the type of the repository.
     @ sql/sql_class.h
        Added system information to indentify threads created to update replication
        repository tables.
     @ sql/sql_db.cc
        Database that contains replication repository tables may be dropped if
        replication is stopped.
     @ sql/sql_partition_admin.cc
        Replication repository tables may have its partitions changed if replication is stopped.
     @ sql/sql_rename.cc
        Replication repository tables may have their name changed if replication is stopped.
     @ sql/sql_table.cc
        Replication repository tables may be dropped or altered if replication is stopped.
     @ sql/sql_table.h
        Added a function to check if it is a replication repository table.
     @ sql/sys_vars.cc
        Changed sys_vars.cc to allow master_info_repository and relay_log_info_repository
        to be changed on-line if replication is stopped.
     @ sql/table.h
        Defined global variables to identify the replication repository tables.

    modified:
      mysql-test/extra/rpl_tests/rpl_crash_safe.inc
      mysql-test/suite/rpl/r/rpl_migration_crash_safe.result
      mysql-test/suite/rpl/r/rpl_row_crash_safe.result
      mysql-test/suite/rpl/r/rpl_stm_mixed_crash_safe.result
      mysql-test/suite/rpl/t/rpl_migration_crash_safe.test
      mysql-test/suite/sys_vars/r/master_info_repository_basic.result
      mysql-test/suite/sys_vars/r/relay_log_info_repository_basic.result
      mysql-test/suite/sys_vars/t/master_info_repository_basic.test
      mysql-test/suite/sys_vars/t/relay_log_info_repository_basic.test
      scripts/mysql_install_db.pl.in
      scripts/mysql_install_db.sh
      sql/lock.cc
      sql/rpl_info.cc
      sql/rpl_info.h
      sql/rpl_info_factory.cc
      sql/rpl_info_factory.h
      sql/rpl_info_file.cc
      sql/rpl_info_file.h
      sql/rpl_info_handler.cc
      sql/rpl_info_handler.h
      sql/rpl_info_table.cc
      sql/rpl_info_table.h
      sql/rpl_info_table_access.cc
      sql/rpl_info_values.cc
      sql/rpl_mi.h
      sql/rpl_rli.h
      sql/rpl_slave.cc
      sql/share/errmsg-utf8.txt
      sql/sql_class.h
      sql/sql_db.cc
      sql/sql_partition_admin.cc
      sql/sql_rename.cc
      sql/sql_table.cc
      sql/sql_table.h
      sql/sys_vars.cc
      sql/table.h
=== modified file 'mysql-test/extra/rpl_tests/rpl_crash_safe.inc'
--- a/mysql-test/extra/rpl_tests/rpl_crash_safe.inc	2010-12-20 14:27:17 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_crash_safe.inc	2011-01-17 10:16:47 +0000
@@ -10,9 +10,11 @@
 if (`SELECT HEX(@commands) = HEX('configure')`)
 {
   --sync_slave_with_master
+  --source include/stop_slave.inc
   SHOW CREATE TABLE mysql.slave_relay_log_info;
   ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
   SHOW CREATE TABLE mysql.slave_relay_log_info;
+  --source include/start_slave.inc
 
   connection master;
   --source extra/rpl_tests/rpl_mixing_engines.inc

=== modified file 'mysql-test/suite/rpl/r/rpl_migration_crash_safe.result'
--- a/mysql-test/suite/rpl/r/rpl_migration_crash_safe.result	2010-12-19 17:22:30 +0000
+++ b/mysql-test/suite/rpl/r/rpl_migration_crash_safe.result	2011-01-17 10:16:47 +0000
@@ -5,5 +5,39 @@ CREATE TABLE test(id INTEGER NOT NULL PR
 INSERT INTO test VALUES (1), (2), (3);
 include/rpl_restart_server.inc [server_number=2 parameters: --relay-log-info-repository=TABLE --skip-slave-start]
 include/rpl_restart_server.inc [server_number=2 parameters: --relay-log-info-repository=FILE --skip-slave-start]
+SET @@GLOBAL.relay_log_info_repository= "TABLE";
+SET @@GLOBAL.relay_log_info_repository= "FILE";
+SET @@GLOBAL.relay_log_info_repository= "FILE";
+include/start_slave.inc
+SET @@GLOBAL.relay_log_info_repository= "TABLE";
+ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first
+ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
+ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first
+DROP TABLE mysql.slave_relay_log_info;
+ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first
+RENAME TABLE mysql.slave_relay_log_info TO mysql.slave_relay_log_info_backup;
+ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first
+INSERT INTO mysql.slave_relay_log_info(Master_id) VALUES(1);
+ERROR HY000: You can't use locks with rpl info tables.
+UPDATE mysql.slave_relay_log_info set Master_id= 1;
+ERROR HY000: You can't use locks with rpl info tables.
+DELETE FROM mysql.slave_relay_log_info;
+ERROR HY000: You can't use locks with rpl info tables.
+REPAIR TABLE mysql.slave_relay_log_info;
+Table	Op	Msg_type	Msg_text
+mysql.slave_relay_log_info	repair	status	OK
+include/stop_slave.inc
+INSERT INTO mysql.slave_relay_log_info(Master_id) VALUES(1);
+ERROR HY000: You can't use locks with rpl info tables.
+UPDATE mysql.slave_relay_log_info set Master_id= 1;
+ERROR HY000: You can't use locks with rpl info tables.
+DELETE FROM mysql.slave_relay_log_info;
+ERROR HY000: You can't use locks with rpl info tables.
+REPAIR TABLE mysql.slave_relay_log_info;
+Table	Op	Msg_type	Msg_text
+mysql.slave_relay_log_info	repair	status	OK
+ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
+RENAME TABLE mysql.slave_relay_log_info TO mysql.slave_relay_log_info_backup;
+DROP TABLE mysql.slave_relay_log_info_backup;
 include/start_slave.inc
 DROP TABLE test;

=== modified file 'mysql-test/suite/rpl/r/rpl_row_crash_safe.result'
--- a/mysql-test/suite/rpl/r/rpl_row_crash_safe.result	2010-12-19 17:22:30 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_crash_safe.result	2011-01-17 10:16:47 +0000
@@ -10,6 +10,7 @@ call mtr.add_suppression(".*int __cxa_pu
 ###################################################################################
 SET @verbose= 'Y';
 SET @commands= 'configure';
+include/stop_slave.inc
 SHOW CREATE TABLE mysql.slave_relay_log_info;
 Table	Create Table
 slave_relay_log_info	CREATE TABLE `slave_relay_log_info` (
@@ -35,6 +36,7 @@ slave_relay_log_info	CREATE TABLE `slave
   `Sql_delay` int(11) NOT NULL,
   PRIMARY KEY (`Master_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Relay Log Information'
+include/start_slave.inc
 SET SQL_LOG_BIN=0;
 CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
 CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;

=== modified file 'mysql-test/suite/rpl/r/rpl_stm_mixed_crash_safe.result'
--- a/mysql-test/suite/rpl/r/rpl_stm_mixed_crash_safe.result	2010-12-19 17:22:30 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stm_mixed_crash_safe.result	2011-01-17 10:16:47 +0000
@@ -10,6 +10,7 @@ call mtr.add_suppression(".*int __cxa_pu
 ###################################################################################
 SET @verbose= 'Y';
 SET @commands= 'configure';
+include/stop_slave.inc
 SHOW CREATE TABLE mysql.slave_relay_log_info;
 Table	Create Table
 slave_relay_log_info	CREATE TABLE `slave_relay_log_info` (
@@ -35,6 +36,7 @@ slave_relay_log_info	CREATE TABLE `slave
   `Sql_delay` int(11) NOT NULL,
   PRIMARY KEY (`Master_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Relay Log Information'
+include/start_slave.inc
 SET SQL_LOG_BIN=0;
 CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
 CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;

=== modified file 'mysql-test/suite/rpl/t/rpl_migration_crash_safe.test'
--- a/mysql-test/suite/rpl/t/rpl_migration_crash_safe.test	2010-12-20 14:27:17 +0000
+++ b/mysql-test/suite/rpl/t/rpl_migration_crash_safe.test	2011-01-17 10:16:47 +0000
@@ -22,16 +22,33 @@
 #   if data is replicated correctly.
 #   1.3. Assertions AF1 and AF2 are verified.
 #
-# 2. Migration from FILE to TABLE
+# 2. Migration from FILE to TABLE by restarting the SERVER
 #   2.1. The slave is stopped and restarted with --relay-log-info-repository=TABLE
 #   2.2. Assertions AT1 and AT2 are verified.
 #
-# 3. Migration from TABLE to FILE with success
+# 3. Migration from TABLE to FILE by restarting the SERVER
 #   4.1. The slave is stopped and restarted with --relay-log-info-repository=FILE
 #   4.2. Assertions AF1 and AF2 are verified.
 #
-# 4. Check consistency
-#   4.1. The replication is started and the master is compared to the slave.
+# 4. Migration from FILE to TALBE by using SET
+#   4.1. SET @GLOBAL.relay_log_info_repository=TABLE is exectued.
+#   4.2. Assertions AT1 and AT2 are verified.
+#
+# 5. Migration from TABLE to FILE by using SET
+#   5.1. SET @GLOBAL.relay_log_info_repository=FILE is executed.
+#   5.2. Assertions AF1 and AF2 are verified.
+#
+# 6. Migration from FILE to FILE by using SET
+#   6.1. SET @GLOBAL.relay_log_info_repository=FILE is executed.
+#   6.2. Assertions AF1 and AF2 are verified.
+#
+# 7. Migration while slave is running by using SET
+#   7.1  Slave is started.
+#   7.2. SET @GLOBAL.relay_log_info_repository=FILE is executed and fails.
+#   7.3. Assertions AF1 and AF2 are verified.
+#
+# 8. Check consistency
+#   8.1. The replication is started and the master is compared to the slave.
 ########################################################################################
 ########################################################################################
 # 1. Preparation
@@ -62,7 +79,7 @@ CREATE TABLE test(id INTEGER NOT NULL PR
 INSERT INTO test VALUES (1), (2), (3);
 
 ########################################################################################
-# 2. Migration from FILE to TABLE
+# 2. Migration from FILE to TABLE by restarting the SERVER
 ########################################################################################
 --connection slave
 
@@ -74,15 +91,16 @@ let $exp_slave= 1;
 let $got_slave= `SELECT COUNT(*) FROM mysql.slave_relay_log_info`;
 if ($got_slave != $exp_slave)
 {
-  --echo "The mysql.slave_relay_log_info has information and this is not expected."
+  --echo "The mysql.slave_relay_log_info has no information and this is not expected."
   --die
 }
 --error 1
 file_exists $MYSQLD_DATADIR/relay-log.info;
 
 ########################################################################################
-# 3. Migration from TABLE to FILE
+# 3. Migration from TABLE to FILE by restarting the SERVER
 ########################################################################################
+--connection slave
 
 --let $rpl_server_number= 2
 --let $rpl_server_parameters= --relay-log-info-repository=FILE --skip-slave-start
@@ -98,12 +116,67 @@ if ($got_slave != $exp_slave)
 file_exists $MYSQLD_DATADIR/relay-log.info;
 
 ########################################################################################
-# 4. Check consistency
+# 4. Migration FROM FILE TO TABLE by using SET
+########################################################################################
+--connection slave
+
+SET @@GLOBAL.relay_log_info_repository= "TABLE";
+
+let $exp_slave= 1;
+let $got_slave= `SELECT COUNT(*) FROM mysql.slave_relay_log_info`;
+if ($got_slave != $exp_slave)
+{
+  --echo "The mysql.slave_relay_log_info has no information and this is not expected."
+  --die
+}
+--error 1
+file_exists $MYSQLD_DATADIR/relay-log.info;
+
+########################################################################################
+# 5. Migration FROM TABLE TO FILE by using SET
+########################################################################################
+--connection slave
+
+SET @@GLOBAL.relay_log_info_repository= "FILE";
+
+let $exp_slave= 0;
+let $got_slave= `SELECT COUNT(*) FROM mysql.slave_relay_log_info`;
+if ($got_slave != $exp_slave)
+{
+  --echo "The mysql.slave_relay_log_info has information and this is not expected."
+  --die
+}
+file_exists $MYSQLD_DATADIR/relay-log.info;
+
+########################################################################################
+# 6. Migration FROM FILE TO FILE by using SET
+########################################################################################
+--connection slave
+
+SET @@GLOBAL.relay_log_info_repository= "FILE";
+
+let $exp_slave= 0;
+let $got_slave= `SELECT COUNT(*) FROM mysql.slave_relay_log_info`;
+if ($got_slave != $exp_slave)
+{
+  --echo "The mysql.slave_relay_log_info has information and this is not expected."
+  --die
+}
+file_exists $MYSQLD_DATADIR/relay-log.info;
+
+########################################################################################
+# 7. Migration while slave is running by using SET
 ########################################################################################
 --connection slave
 
 --source include/start_slave.inc
 
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.relay_log_info_repository= "TABLE";
+
+########################################################################################
+# 8. Check consistency
+########################################################################################
 --connection master
 
 sync_slave_with_master;
@@ -111,6 +184,58 @@ sync_slave_with_master;
 --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLD_DATADIR/test-migration-slave.sql
 --diff_files $MYSQLD_DATADIR/test-migration-master.sql $MYSQLD_DATADIR/test-migration-slave.sql
 
+########################################################################################
+# 8. Check consistency
+########################################################################################
+--connection slave
+
+--error ER_SLAVE_MUST_STOP
+ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
+
+--error ER_SLAVE_MUST_STOP
+DROP TABLE mysql.slave_relay_log_info;
+
+--error ER_SLAVE_MUST_STOP
+RENAME TABLE mysql.slave_relay_log_info TO mysql.slave_relay_log_info_backup;
+
+--error ER_CANT_LOCK_RPL_INFO_TABLE
+INSERT INTO mysql.slave_relay_log_info(Master_id) VALUES(1);
+
+--error ER_CANT_LOCK_RPL_INFO_TABLE
+UPDATE mysql.slave_relay_log_info set Master_id= 1;
+
+--error ER_CANT_LOCK_RPL_INFO_TABLE
+DELETE FROM mysql.slave_relay_log_info;
+
+#--error ER_CANT_LOCK_RPL_INFO_TABLE
+#TRUNCATE mysql.slave_relay_log_info;
+
+REPAIR TABLE mysql.slave_relay_log_info;
+
+--source include/stop_slave.inc
+
+--error ER_CANT_LOCK_RPL_INFO_TABLE
+INSERT INTO mysql.slave_relay_log_info(Master_id) VALUES(1);
+
+--error ER_CANT_LOCK_RPL_INFO_TABLE
+UPDATE mysql.slave_relay_log_info set Master_id= 1;
+
+--error ER_CANT_LOCK_RPL_INFO_TABLE
+DELETE FROM mysql.slave_relay_log_info;
+
+#--error ER_CANT_LOCK_RPL_INFO_TABLE
+#TRUNCATE mysql.slave_relay_log_info;
+
+REPAIR TABLE mysql.slave_relay_log_info;
+
+ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
+
+RENAME TABLE mysql.slave_relay_log_info TO mysql.slave_relay_log_info_backup;
+
+DROP TABLE mysql.slave_relay_log_info_backup;
+
+--source include/start_slave.inc
+
 --connection master
 
 DROP TABLE test;

=== modified file 'mysql-test/suite/sys_vars/r/master_info_repository_basic.result'
--- a/mysql-test/suite/sys_vars/r/master_info_repository_basic.result	2010-07-06 22:01:07 +0000
+++ b/mysql-test/suite/sys_vars/r/master_info_repository_basic.result	2011-01-17 10:16:47 +0000
@@ -10,10 +10,9 @@ SELECT COUNT(@@SESSION.master_info_repos
 ERROR HY000: Variable 'master_info_repository' is a GLOBAL variable
 '#---------------------BS_STVARS_002_02----------------------#'
 SET @@GLOBAL.master_info_repository= "TABLE";
-ERROR HY000: Variable 'master_info_repository' is a read only variable
 SELECT @@GLOBAL.master_info_repository;
 @@GLOBAL.master_info_repository
-FILE
+TABLE
 '#---------------------BS_STVARS_002_03----------------------#'
 SELECT @@GLOBAL.master_info_repository = VARIABLE_VALUE
 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -42,3 +41,5 @@ SELECT COUNT(@@GLOBAL.master_info_reposi
 COUNT(@@GLOBAL.master_info_repository)
 1
 1 Expected
+'#---------------------BS_STVARS_002_06----------------------#'
+SET @@GLOBAL.master_info_repository= "FILE";

=== modified file 'mysql-test/suite/sys_vars/r/relay_log_info_repository_basic.result'
--- a/mysql-test/suite/sys_vars/r/relay_log_info_repository_basic.result	2010-07-06 22:01:07 +0000
+++ b/mysql-test/suite/sys_vars/r/relay_log_info_repository_basic.result	2011-01-17 10:16:47 +0000
@@ -10,10 +10,9 @@ SELECT COUNT(@@SESSION.relay_log_info_re
 ERROR HY000: Variable 'relay_log_info_repository' is a GLOBAL variable
 '#---------------------BS_STVARS_002_02----------------------#'
 SET @@GLOBAL.relay_log_info_repository= "TABLE";
-ERROR HY000: Variable 'relay_log_info_repository' is a read only variable
 SELECT @@GLOBAL.relay_log_info_repository;
 @@GLOBAL.relay_log_info_repository
-FILE
+TABLE
 '#---------------------BS_STVARS_002_03----------------------#'
 SELECT @@GLOBAL.relay_log_info_repository = VARIABLE_VALUE
 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -42,3 +41,5 @@ SELECT COUNT(@@GLOBAL.relay_log_info_rep
 COUNT(@@GLOBAL.relay_log_info_repository)
 1
 1 Expected
+'#---------------------BS_STVARS_002_06----------------------#'
+SET @@GLOBAL.relay_log_info_repository= "FILE";

=== modified file 'mysql-test/suite/sys_vars/t/master_info_repository_basic.test'
--- a/mysql-test/suite/sys_vars/t/master_info_repository_basic.test	2010-10-25 10:39:01 +0000
+++ b/mysql-test/suite/sys_vars/t/master_info_repository_basic.test	2011-01-17 10:16:47 +0000
@@ -37,7 +37,6 @@ SELECT COUNT(@@SESSION.master_info_repos
 ####################################################################
 #   Check if Value can set                                         #
 ####################################################################
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
 SET @@GLOBAL.master_info_repository= "TABLE";
 
 SELECT @@GLOBAL.master_info_repository;
@@ -74,3 +73,10 @@ SELECT COUNT(@@local.master_info_reposit
 
 SELECT COUNT(@@GLOBAL.master_info_repository);
 --echo 1 Expected
+
+
+--echo '#---------------------BS_STVARS_002_06----------------------#'
+################################################################################
+#                                     Clean up                                 #
+################################################################################
+SET @@GLOBAL.master_info_repository= "FILE";

=== modified file 'mysql-test/suite/sys_vars/t/relay_log_info_repository_basic.test'
--- a/mysql-test/suite/sys_vars/t/relay_log_info_repository_basic.test	2010-10-25 10:39:01 +0000
+++ b/mysql-test/suite/sys_vars/t/relay_log_info_repository_basic.test	2011-01-17 10:16:47 +0000
@@ -37,7 +37,6 @@ SELECT COUNT(@@SESSION.relay_log_info_re
 ####################################################################
 #   Check if Value can set                                         #
 ####################################################################
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
 SET @@GLOBAL.relay_log_info_repository= "TABLE";
 
 SELECT @@GLOBAL.relay_log_info_repository;
@@ -74,3 +73,10 @@ SELECT COUNT(@@local.relay_log_info_repo
 
 SELECT COUNT(@@GLOBAL.relay_log_info_repository);
 --echo 1 Expected
+
+
+--echo '#---------------------BS_STVARS_002_06----------------------#'
+################################################################################
+#                                     Clean up                                 #
+################################################################################
+SET @@GLOBAL.relay_log_info_repository= "FILE";

=== modified file 'scripts/mysql_install_db.pl.in'
--- a/scripts/mysql_install_db.pl.in	2010-10-25 10:39:01 +0000
+++ b/scripts/mysql_install_db.pl.in	2010-12-13 18:18:56 +0000
@@ -79,11 +79,6 @@ Usage: $0 [OPTIONS]
                        user.  You must be root to use this option.  By default
                        mysqld runs using your current login name and files and
                        directories that it creates will be owned by you.
-  --rpl-engine=engine  The storage engine used for the mysql.slave_master_info and
-                       mysql.slave_relay_log_info tables. By default, both tables are
-                       created using the MyISAM storage engine. However, any storage
-                       engine available to the server may be used. If a crash-safe
-                       slave is required, the storage engine must be transactional.
 
 All other options are passed to the mysqld program
 
@@ -122,7 +117,6 @@ sub parse_arguments
              "builddir=s",      # FIXME not documented
              "srcdir=s",
              "ldata|datadir=s",
-             "rpl-engine=s",
 
              # Note that the user will be passed to mysqld so that it runs
              # as 'user' (crucial e.g. if log-bin=/some_other_path/
@@ -459,29 +453,6 @@ if ( open(PIPE, "| $mysqld_install_cmd_l
   report_verbose($opt,"OK");
 
   # ----------------------------------------------------------------------
-  # Pipe ALTER TABLE mysql.slave_master_info|slave_relay_log_info to "mysqld --bootstrap"
-  # ----------------------------------------------------------------------
-
-  if ($opt->{'rpl-engine'})
-  {
-    report_verbose_wait($opt,"Setting engine for mysql.slave_master_info mysql.slave_relay_log_info tables...");
-    if ( open(PIPE, "| $mysqld_install_cmd_line") )
-    {
-      print PIPE "use mysql;\n";
-      print PIPE "ALTER TABLE mysql.slave_master_info ENGINE= " . $opt->{'rpl-engine'} . ";\n";
-      print PIPE "ALTER TABLE mysql.slave_relay_log_info ENGINE= " . $opt->{'$rpl-engine'} . ";\n";
-      close PIPE;
-
-      report_verbose($opt,"OK");
-    }
-    else
-    {
-      warning($opt,"CRASH-SAFE SLAVE IS NOT COMPLETELY CONFIGURED!",
-                   "The \"CRASH-SAFE SLAVE\" might not work properly.");
-    }
-  }
-
-  # ----------------------------------------------------------------------
   # Pipe fill_help_tables.sql to "mysqld --bootstrap"
   # ----------------------------------------------------------------------
 

=== modified file 'scripts/mysql_install_db.sh'
--- a/scripts/mysql_install_db.sh	2010-10-25 10:39:01 +0000
+++ b/scripts/mysql_install_db.sh	2010-12-13 18:18:56 +0000
@@ -63,11 +63,6 @@ Usage: $0 [OPTIONS]
                        user.  You must be root to use this option.  By default
                        mysqld runs using your current login name and files and
                        directories that it creates will be owned by you.
-  --rpl-engine=engine  The storage engine used for the mysql.slave_master_info and
-                       mysql.slave_relay_log_info tables. By default, both tables are
-                       created using the MyISAM storage engine. However, any storage
-                       engine available to the server may be used. If a crash-safe
-                       slave is required, the storage engine must be transactional.
 
 All other options are passed to the mysqld program
 
@@ -120,8 +115,6 @@ parse_arguments()
       --no-defaults|--defaults-file=*|--defaults-extra-file=*)
         defaults="$arg" ;;
 
-      --rpl-engine=*) rpl_engine=`parse_arg "$arg"` ;;
-
       --cross-bootstrap|--windows)
         # Used when building the MySQL system tables on a different host than
         # the target. The platform-independent files that are created in
@@ -434,19 +427,6 @@ else
   exit 1
 fi
 
-if test -n "$rpl_engine"
-then
-  s_echo "Setting engine for mysql.slave_master_info mysql.slave_relay_log_info tables..."
-  if { echo "use mysql;"; echo "ALTER TABLE mysql.slave_master_info ENGINE= $rpl_engine;"; echo "ALTER TABLE mysql.slave_relay_log_info ENGINE= $rpl_engine;"; } | $mysqld_install_cmd_line > /dev/null
-  then
-    s_echo "OK"
-  else
-    echo
-    echo "WARNING: CRASH-SAFE SLAVE IS NOT COMPLETELY CONFIGURED!"
-    echo "The \"CRASH-SAFE SLAVE\" might not work properly."
-  fi
-fi
-
 s_echo "Filling help tables..."
 if { echo "use mysql;"; cat $fill_help_tables; } | $mysqld_install_cmd_line > /dev/null
 then

=== modified file 'sql/lock.cc'
--- a/sql/lock.cc	2010-11-23 22:37:59 +0000
+++ b/sql/lock.cc	2011-01-17 10:16:47 +0000
@@ -130,7 +130,8 @@ lock_tables_check(THD *thd, TABLE **tabl
   log_table_write_query=
      is_log_table_write_query(thd->lex->sql_command);
   rpl_info_table_write_query=
-     is_rpl_info_table_write_query(thd->lex->sql_command);
+     (is_rpl_info_table_write_query(thd->lex->sql_command)) ||
+     (thd->system_thread == SYSTEM_THREAD_INFO_REPOSITORY);
 
   for (i=0 ; i<count; i++)
   {

=== modified file 'sql/rpl_info.cc'
--- a/sql/rpl_info.cc	2010-12-21 09:33:41 +0000
+++ b/sql/rpl_info.cc	2011-01-17 10:16:47 +0000
@@ -36,7 +36,7 @@ Rpl_info::Rpl_info(const char* type
 #endif
   info_thd(0), inited(0), abort_slave(0),
   slave_running(0), slave_run_id(0),
-  handler(0)
+  handler(0), rpl_info_type(INVALID_INFO_REPOSITORY)
 {
 #ifdef HAVE_PSI_INTERFACE
   mysql_mutex_init(*key_info_run_lock,
@@ -65,13 +65,7 @@ Rpl_info::~Rpl_info()
   mysql_cond_destroy(&start_cond);
   mysql_cond_destroy(&stop_cond);
 
-  if (handler)
-    delete handler;
+  delete handler;
 
   DBUG_VOID_RETURN;
 }
-
-void Rpl_info::set_rpl_info_handler(Rpl_info_handler * param_handler)
-{
-  handler= param_handler;
-}

=== modified file 'sql/rpl_info.h'
--- a/sql/rpl_info.h	2010-12-21 09:33:41 +0000
+++ b/sql/rpl_info.h	2011-01-17 10:16:47 +0000
@@ -16,6 +16,8 @@
 #ifndef RPL_INFO_H
 #define RPL_INFO_H
 
+#define INVALID_INFO_REPOSITORY -1
+
 #include "sql_priv.h"
 #include "sql_class.h"
 #include "rpl_info_handler.h"
@@ -24,6 +26,8 @@
 class Rpl_info : public Slave_reporting_capability
 {
 public:
+  virtual ~Rpl_info();
+
   /*
     standard lock acquisition order to avoid deadlocks:
     run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
@@ -53,16 +57,45 @@ public:
   int events_until_exit;
 #endif
 
-  Rpl_info(const char* type
-#ifdef HAVE_PSI_INTERFACE
-           ,PSI_mutex_key *param_key_info_run_lock,
-           PSI_mutex_key *param_key_info_data_lock,
-           PSI_mutex_key *param_key_info_data_cond,
-           PSI_mutex_key *param_key_info_start_cond,
-           PSI_mutex_key *param_key_info_stop_cond
-#endif
-          );
-  virtual ~Rpl_info();
+  /**
+    Defines the type of the repository that is used.
+
+    @param param_rpl_info_type Type of repository.
+  */
+  void set_rpl_info_type(uint param_rpl_info_type)
+  {
+    rpl_info_type= param_rpl_info_type;
+  }
+
+  /**
+    Gets the type of the repository that is used.
+
+    @return Type of repository.
+  */
+  uint get_rpl_info_type()
+  {
+    return(rpl_info_type);
+  }
+
+  /**
+    Sets the persistency component/handler.
+
+    @param[in] hanlder Pointer to the handler.
+  */ 
+  void set_rpl_info_handler(Rpl_info_handler * param_handler)
+  {
+    handler= param_handler;
+  }
+
+  /**
+    Gets the persistency component/handler.
+
+    @return the handler if there is one.
+  */ 
+  Rpl_info_handler *get_rpl_info_handler()
+  {
+    return (handler);
+  }
 
   int check_info()
   {
@@ -79,6 +112,11 @@ public:
     return (handler->is_transactional());
   }
 
+  bool update_transactional()
+  {
+    return (handler->update_transactional());
+  }
+
   char *get_description_info()
   {
     return (handler->get_description_info());
@@ -92,21 +130,26 @@ public:
     return(FALSE);
   }
 
-  /**
-    Sets the persistency component/handler.
-
-    @param[in] hanlder Pointer to the handler.
-  */ 
-  void set_rpl_info_handler(Rpl_info_handler * handler);
-
 protected:
   Rpl_info_handler *handler;
 
+  uint rpl_info_type;
+
+  Rpl_info(const char* type
+#ifdef HAVE_PSI_INTERFACE
+           ,PSI_mutex_key *param_key_info_run_lock,
+           PSI_mutex_key *param_key_info_data_lock,
+           PSI_mutex_key *param_key_info_data_cond,
+           PSI_mutex_key *param_key_info_start_cond,
+           PSI_mutex_key *param_key_info_stop_cond
+#endif
+          );
+
 private:
   virtual bool read_info(Rpl_info_handler *from)= 0;
   virtual bool write_info(Rpl_info_handler *to, bool force)= 0;
 
-  Rpl_info& operator=(const Rpl_info& info);
   Rpl_info(const Rpl_info& info);
+  Rpl_info& operator=(const Rpl_info& info);
 };
 #endif /* RPL_INFO_H */

=== modified file 'sql/rpl_info_factory.cc'
--- a/sql/rpl_info_factory.cc	2010-12-21 09:33:41 +0000
+++ b/sql/rpl_info_factory.cc	2011-01-17 10:16:47 +0000
@@ -18,13 +18,6 @@
 #include "rpl_slave.h"
 #include "rpl_info_factory.h"
 
-/*
-  We need to replace these definitions by an option that states the
-  engine one wants to use in the master info repository.
-*/
-#define master_info_engine NULL
-#define relay_log_info_engine NULL
-
 /**
   Creates both a Master info and a Relay log info repository whose types are
   defined as parameters.
@@ -42,7 +35,7 @@
 bool Rpl_info_factory::create(uint mi_option, Master_info **mi,
                               uint rli_option, Relay_log_info **rli)
 {
-  DBUG_ENTER("Rpl_info_factory::Rpl_info_factory");
+  DBUG_ENTER("Rpl_info_factory::create");
 
   if (!((*mi)= Rpl_info_factory::create_mi(mi_option)))
     DBUG_RETURN(TRUE);
@@ -80,12 +73,12 @@ bool Rpl_info_factory::create(uint mi_op
 Master_info *Rpl_info_factory::create_mi(uint mi_option)
 {
   Master_info* mi= NULL;
-  Rpl_info_file*  mi_file= NULL;
-  Rpl_info_table*  mi_table= NULL;
+  Rpl_info_handler*  handler_src= NULL;
+  Rpl_info_handler*  handler_dest= NULL;
   const char *msg= "Failed to allocate memory for the master info "
                    "structure";
 
-  DBUG_ENTER("Rpl_info_factory::Rpl_info_factory");
+  DBUG_ENTER("Rpl_info_factory::create_mi");
 
   if (!(mi= new Master_info(
 #ifdef HAVE_PSI_INTERFACE
@@ -98,36 +91,17 @@ Master_info *Rpl_info_factory::create_mi
                            )))
     goto err;
 
-  /*
-    Now we instantiate all info repos and later decide which one to take,
-    but not without first checking if there is already existing data for
-    a repo different from the one that is being requested.
-  */
-  if (!(mi_file= new Rpl_info_file(mi->get_number_info_mi_fields(),
-                                   master_info_file)))
-    goto err;
-
-  if (!(mi_table= new Rpl_info_table(mi->get_number_info_mi_fields() + 1,
-                                     MI_FIELD_ID, MI_SCHEMA, MI_TABLE)))
-    goto err;
-
-  DBUG_ASSERT(mi_option == MI_REPOSITORY_FILE ||
-              mi_option == MI_REPOSITORY_TABLE);
-
-  if (decide_repository(mi, &mi_table, &mi_file,
-                        mi_option == MI_REPOSITORY_TABLE, &msg))
+  if(init_mi_repositories(mi, mi_option, &handler_src, &handler_dest, &msg))
     goto err;
 
-  if ((mi_option == MI_REPOSITORY_TABLE) &&
-       change_engine(static_cast<Rpl_info_table *>(mi_table),
-                     master_info_engine, &msg))
+  if (decide_repository(mi, mi_option, &handler_src, &handler_dest, &msg))
     goto err;
 
   DBUG_RETURN(mi);
 
 err:
-  if (mi_file) delete mi_file;
-  if (mi_table) delete mi_table;
+  delete handler_src;
+  delete handler_dest;
   if (mi)
   {
     /*
@@ -135,13 +109,51 @@ err:
       any reference to it.  
     */
     mi->set_rpl_info_handler(NULL);
-    delete (mi);
+    mi->set_rpl_info_type(INVALID_INFO_REPOSITORY);
+    delete mi;
   }
-  sql_print_error("%s", msg);
+  sql_print_error("Error creating master info: %s.", msg);
   DBUG_RETURN(NULL);
 }
 
 /**
+  Allows to change the master info repository after startup.
+
+  @param[in]  mi        Pointer to Master_info.
+  @param[in]  mi_option Type of the repository, e.g. FILE TABLE.
+  @param[out] msg       Error message if something goes wrong.
+
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/
+bool Rpl_info_factory::change_mi_repository(Master_info *mi,
+                                            const uint mi_option,
+                                            const char **msg)
+{
+  DBUG_ENTER("Rpl_info_factory::change_mi_repository");
+
+  Rpl_info_handler*  handler_src= mi->get_rpl_info_handler();
+  Rpl_info_handler*  handler_dest= NULL;
+
+  if (mi->get_rpl_info_type()  == mi_option)
+    DBUG_RETURN(FALSE);
+
+  if (init_mi_repositories(mi, mi_option, NULL, &handler_dest, msg))
+    goto err;
+
+  if (change_repository(mi, mi_option, &handler_src, &handler_dest, msg))
+    goto err;
+
+  DBUG_RETURN(FALSE);
+
+err:
+  delete handler_dest;
+
+  sql_print_error("Error changing the type of master info's repository: %s.", *msg);
+  DBUG_RETURN(TRUE);
+}
+
+/**
   Creates a Relay log info repository whose type is defined as a parameter.
   
   @param[in]  rli_option        Type of the Relay log info repository
@@ -160,8 +172,8 @@ err:
 Relay_log_info *Rpl_info_factory::create_rli(uint rli_option, bool is_slave_recovery)
 {
   Relay_log_info *rli= NULL;
-  Rpl_info_file* rli_file= NULL;
-  Rpl_info_table* rli_table= NULL;
+  Rpl_info_handler* handler_src= NULL;
+  Rpl_info_handler* handler_dest= NULL;
   const char *msg= "Failed to allocate memory for the relay log info "
                    "structure";
 
@@ -178,36 +190,17 @@ Relay_log_info *Rpl_info_factory::create
                                )))
     goto err;
 
-  /*
-    Now we instantiate all info repos and later decide which one to take,
-    but not without first checking if there is already existing data for
-    a repo different from the one that is being requested.
-  */
-  if (!(rli_file= new Rpl_info_file(rli->get_number_info_rli_fields(),
-                                    relay_log_info_file)))
-    goto err;
-
-  if (!(rli_table= new Rpl_info_table(rli->get_number_info_rli_fields() + 1,
-                                      RLI_FIELD_ID, RLI_SCHEMA, RLI_TABLE)))
-    goto err;
-
-  DBUG_ASSERT(rli_option == RLI_REPOSITORY_FILE ||
-              rli_option == RLI_REPOSITORY_TABLE);
-
-  if (decide_repository(rli, &rli_table, &rli_file,
-                        rli_option == RLI_REPOSITORY_TABLE, &msg))
+  if(init_rli_repositories(rli, rli_option, &handler_src, &handler_dest, &msg))
     goto err;
 
-  if ((rli_option == RLI_REPOSITORY_TABLE) &&
-      change_engine(static_cast<Rpl_info_table *>(rli_table),
-                    relay_log_info_engine, &msg))
+  if (decide_repository(rli, rli_option, &handler_src, &handler_dest, &msg))
     goto err;
 
   DBUG_RETURN(rli);
 
 err:
-  if (rli_file) delete rli_file;
-  if (rli_table) delete rli_table;
+  delete handler_src;
+  delete handler_dest;
   if (rli) 
   {
     /*
@@ -215,142 +208,324 @@ err:
       any reference to it.  
     */
     rli->set_rpl_info_handler(NULL);
-    delete (rli);
+    rli->set_rpl_info_type(INVALID_INFO_REPOSITORY);
+    delete rli;
   }
-  sql_print_error("%s", msg);
+  sql_print_error("Error creating relay log info: %s.", msg);
   DBUG_RETURN(NULL);
 }
 
 /**
-  Decides what repository will be used based on the following decision table:
+  Allows to change the relay log info repository after startup.
 
-  \code
-  |--------------+-----------------------+-----------------------|
-  | Exists \ Opt |         TABLE         |          FILE         |
-  |--------------+-----------------------+-----------------------|
-  | ~is_t,  is_f | Update T and delete F | Read F                |
-  |  is_t,  is_f | ERROR                 | ERROR                 |
-  | ~is_t, ~is_f | Fill in T             | Create and Fill in F  |
-  |  is_t, ~is_f | Read T                | Update F and delete T |
-  |--------------+-----------------------+-----------------------|
-  \endcode
+  @param[in]  mi        Pointer to Relay_log_info.
+  @param[in]  mi_option Type of the repository, e.g. FILE TABLE.
+  @param[out] msg       Error message if something goes wrong.
 
-  <ul>
-    \li F     --> file
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/
+bool Rpl_info_factory::change_rli_repository(Relay_log_info *rli,
+                                             const uint rli_option,
+                                             const char **msg)
+{
+  DBUG_ENTER("Rpl_info_factory::change_rli_repository");
+
+  Rpl_info_handler*  handler_src= rli->get_rpl_info_handler();
+  Rpl_info_handler*  handler_dest= NULL;
+
+  if (rli->get_rpl_info_type()  == rli_option)
+    DBUG_RETURN(FALSE);
+
+  if (init_rli_repositories(rli, rli_option, NULL, &handler_dest, msg))
+    goto err;
+
+  if (change_repository(rli, rli_option, &handler_src, &handler_dest, msg))
+    goto err;
 
-    \li T     --> table
+  DBUG_RETURN(FALSE);
 
-    \li is_t  --> table with data
+err:
+  delete handler_dest;
+  handler_dest= NULL;
 
-    \li is_f  --> file with data
+  sql_print_error("Error changing the type of relay log info's repository: %s.", *msg);
+  DBUG_RETURN(TRUE);
+}
 
-    \li ~is_t --> no data in the table
+/**
+  Decides during startup what repository will be used based on the following
+  decision table:
 
-    \li ~is_f --> no file
-  </ul> 
+  \code
+  |--------------+-----------------------+-----------------------|
+  | Exists \ Opt |         SOURCE        |      DESTINATION      |
+  |--------------+-----------------------+-----------------------|
+  | ~is_s, ~is_d |            -          | Create/Update D       |
+  | ~is_s,  is_d |            -          | Continue with D       |
+  |  is_s, ~is_d | Copy S into D         | Create/Update D       |
+  |  is_s,  is_d | Error                 | Error                 |
+  |--------------+-----------------------+-----------------------|
+  \endcode
 
-  @param[in] info     Either master info or relay log info.
-  @param[in] table    Table handler.
-  @param[in] file     File handler.
-  @param[in] is_table True if a table handler was requested.
-  @param[out] msg     Message specifying what went wrong, if there is any error.
+  @param[in]  info         Either master info or relay log info.
+  @param[in]  option       Identifies the type of the repository that will
+                           be used, i.e., destination repository.
+  @param[out] handler_src  Source repository from where information is
+                           copied into the destination repository.
+  @param[out] handler_dest Destination repository to where informaiton is
+                           copied.
+  @param[out] msg          Error message if something goes wrong.
 
   @retval FALSE No error
   @retval TRUE  Failure
 */
-bool Rpl_info_factory::decide_repository(Rpl_info *info, Rpl_info_table **table,
-                                         Rpl_info_file **file, bool is_table,
+bool Rpl_info_factory::decide_repository(Rpl_info *info,
+                                         uint option,
+                                         Rpl_info_handler **handler_src,
+                                         Rpl_info_handler **handler_dest,
                                          const char **msg)
 {
 
   DBUG_ENTER("Rpl_info_factory::decide_repository");
  
   bool error= TRUE;
-  bool is_t= !((*table)->check_info());
-  bool is_f= !((*file)->check_info());
+  bool is_src= !((*handler_src)->check_info());
+  bool is_dest= !((*handler_dest)->check_info());
 
-  if (is_t && is_f)
+  DBUG_ASSERT((*handler_dest) != NULL && (*handler_dest) != NULL);
+  if (is_src && is_dest)
   {
     *msg= "Multiple replication metadata repository instances "
           "found with data in them. Unable to decide which is "
-          "the correct one to choose.";
+          "the correct one to choose";
     DBUG_RETURN(error);
   }
 
-  if (is_table)
+  if (!is_dest && is_src)
   {
-    if (!is_t && is_f)
+    if ((*handler_src)->init_info() || (*handler_dest)->init_info())
     {
-      if ((*table)->init_info() || (*file)->init_info())
-      {
-        *msg= "Error transfering information from a file to a table.";
-        goto err;
-      }
-      /*
-        Transfer the information from the file to the table and delete the
-        file, i.e. Update the table (T) and delete the file (F).
-      */
-      if (info->copy_info(*file, *table) || (*file)->remove_info())
-      {
-        *msg= "Error transfering information from a file to a table.";
-        goto err;
-      }
+      *msg= "Error transfering information";
+      goto err;
+    }
+    /*
+      Transfer the information from source to destination and delete the
+      source. Note this is not fault-tolerant and a crash before removing
+      source may cause the next restart to fail as is_src and is_dest may
+      be true. Moreover, any failure in removing the source may lead to
+      the same.
+
+      /Alfranio
+    */
+    if (info->copy_info(*handler_src, *handler_dest) || (*handler_src)->remove_info())
+    {
+      *msg= "Error transfering information";
+      goto err;
+    }
+  }
+
+  delete (*handler_src);
+  *handler_src= NULL;
+  info->set_rpl_info_handler(*handler_dest);
+  info->set_rpl_info_type(option);
+  error= FALSE;
+
+err:
+  DBUG_RETURN(error); 
+}
+
+/**
+  Changes the type of the repository after startup based on the following
+  decision table:
+
+  \code
+  |--------------+-----------------------+-----------------------|
+  | Exists \ Opt |         SOURCE        |      DESTINATION      |
+  |--------------+-----------------------+-----------------------|
+  | ~is_s, ~is_d |            -          | Create/Update D       |
+  | ~is_s,  is_d |            -          | Continue with D       |
+  |  is_s, ~is_d | Copy S into D         | Create/Update D       |
+  |  is_s,  is_d | Copy S into D         | Continue with D       |
+  |--------------+-----------------------+-----------------------|
+  \endcode
+
+  @param[in]  info         Either master info or relay log info.
+  @param[in]  option       Identifies the type of the repository that will
+                           be used, i.e., destination repository.
+  @param[out] handler_src  Source repository from where information is
+                           copied into the destination repository.
+  @param[out] handler_dest Destination repository to where informaiton is
+                           copied.
+  @param[out] msg          Error message if something goes wrong.
+
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/
+bool Rpl_info_factory::change_repository(Rpl_info *info,
+                                         uint option,
+                                         Rpl_info_handler **handler_src,
+                                         Rpl_info_handler **handler_dest,
+                                         const char **msg)
+{
+  bool error= TRUE;
+
+  DBUG_ENTER("Rpl_info_factory::change_repository");
+
+  DBUG_ASSERT((*handler_dest) != NULL && (*handler_dest) != NULL);
+  if (!(*handler_src)->check_info())
+  {
+    if ((*handler_dest)->init_info())
+    {
+      *msg= "Error initializing new repository";
+      goto err;
+    }
+
+    /*
+      Transfer the information from source to destination and delete the
+      source. Note this is not fault-tolerant and a crash before removing
+      source may cause the next restart to fail as is_src and is_dest may
+      be true. Moreover, any failure in removing the source may lead to
+      the same.
+
+      /Alfranio
+    */
+    if (info->copy_info(*handler_src, *handler_dest) || (*handler_src)->remove_info())
+    {
+      *msg= "Error transfering information";
+      goto err;
     }
-    delete (*file);
-    info->set_rpl_info_handler(*table);
-    error= FALSE;
-    *file= NULL;
   }
   else
   {
-    if (is_t && !is_f)
+    if ((*handler_src)->remove_info())
     {
-      if ((*table)->init_info() || (*file)->init_info())
-      {
-        *msg= "Error transfering information from a file to a table.";
+      *msg= "Error removing old repository";
+      goto err;
+    }
+  }
+
+  info->set_rpl_info_handler(NULL);
+  delete (*handler_src);
+  *handler_src= NULL;
+  info->set_rpl_info_handler(*handler_dest);
+  info->set_rpl_info_type(option);
+  error= FALSE;
+
+err:
+  DBUG_RETURN(error);
+}
+
+/**
+  Creates repositories that will be associated to the master info.
+
+  @param[in] mi            Pointer to the class Master info.
+  @param[in] rli_option    Identifies the type of the repository that will
+                           be used, i.e., destination repository.
+  @param[out] handler_src  Source repository from where information is
+                           copied into the destination repository.
+  @param[out] handler_dest Destination repository to where informaiton is
+                           copied.
+  @param[out] msg          Error message if something goes wrong.
+
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/
+bool Rpl_info_factory::init_mi_repositories(Master_info *mi,
+                                            uint mi_option,
+                                            Rpl_info_handler **handler_src,
+                                            Rpl_info_handler **handler_dest,
+                                            const char **msg)
+{
+  bool error= TRUE;
+  *msg= "Failed to allocate memory for relay log info repositories";
+
+  DBUG_ENTER("Rpl_info_factory::init_rli_repositories");
+
+  DBUG_ASSERT(handler_dest != NULL);
+  switch (mi_option)
+  {
+    case MI_REPOSITORY_FILE:
+      if (!(*handler_dest= new Rpl_info_file(mi->get_number_info_mi_fields(),
+                                             master_info_file)))
         goto err;
-      }
-      /*
-        Transfer the information from the table to the file and delete 
-        entries in the table, i.e. Update the file (F) and delete the
-        table (T).
-      */
-      if (info->copy_info(*table, *file) || (*table)->remove_info())
-      {
-        *msg= "Error transfering information from a table to a file.";
+      if (handler_src &&
+          !(*handler_src= new Rpl_info_table(mi->get_number_info_mi_fields() + 1,
+                                             MI_FIELD_ID, MYSQL_SCHEMA_NAME.str, MI_INFO_NAME.str)))
         goto err;
-      } 
-    }
-    delete (*table);
-    info->set_rpl_info_handler(*file);
-    error= FALSE;
-    *table= NULL;
+    break;
+
+    case MI_REPOSITORY_TABLE:
+      if (!(*handler_dest= new Rpl_info_table(mi->get_number_info_mi_fields() + 1,
+                                              MI_FIELD_ID, MYSQL_SCHEMA_NAME.str, MI_INFO_NAME.str)))
+        goto err;
+      if (handler_src &&
+          !(*handler_src= new Rpl_info_file(mi->get_number_info_mi_fields(),
+                                            master_info_file)))
+        goto err;
+    break;
+    default:
+      DBUG_ASSERT(0);
   }
+  error= FALSE;
 
 err:
-  DBUG_RETURN(error); 
+  DBUG_RETURN(error);
 }
 
 /**
-  Changes the engine in use by a handler.
-  
-  @param[in]  handler Reference to a handler.
-  @param[in]  engine  Type of the engine, e.g. Innodb, MyIsam.
-  @param[out] msg     Message specifying what went wrong, if there is any error.
+  Creates repositories that will be associated to the relay log info.
+
+  @param[in] rli           Pointer to the class Relay_log_info.
+  @param[in] rli_option    Identifies the type of the repository that will
+                           be used, i.e., destination repository.
+  @param[out] handler_src  Source repository from where information is
+                           copied into the destination repository.
+  @param[out] handler_dest Destination repository to where informaiton is
+                           copied.
+  @param[out] msg          Error message if something goes wrong.
 
   @retval FALSE No error
   @retval TRUE  Failure
 */
-bool Rpl_info_factory::change_engine(Rpl_info_table *table, const char *engine,
-                                     const char **msg)
+bool Rpl_info_factory::init_rli_repositories(Relay_log_info *rli,
+                                             uint rli_option,
+                                             Rpl_info_handler **handler_src,
+                                             Rpl_info_handler **handler_dest,
+                                             const char **msg)
 {
-  DBUG_ENTER("Rpl_info_factory::decide_engine");
+  bool error= TRUE;
+  *msg= "Failed to allocate memory for relay log info repositories";
+
+  DBUG_ENTER("Rpl_info_factory::init_rli_repositories");
 
-  if (engine && table->change_engine(engine))
+  DBUG_ASSERT(handler_dest != NULL);
+  switch (rli_option)
   {
-    *msg= "Error changing the engine for a respository.";
-    DBUG_RETURN(TRUE);
+    case RLI_REPOSITORY_FILE:
+      if (!(*handler_dest= new Rpl_info_file(rli->get_number_info_rli_fields(),
+                                             relay_log_info_file)))
+        goto err;
+      if (handler_src &&
+          !(*handler_src= new Rpl_info_table(rli->get_number_info_rli_fields() + 1,
+                                             RLI_FIELD_ID, MYSQL_SCHEMA_NAME.str, RLI_INFO_NAME.str)))
+        goto err;
+    break;
+
+    case RLI_REPOSITORY_TABLE:
+      if (!(*handler_dest= new Rpl_info_table(rli->get_number_info_rli_fields() + 1,
+                                              RLI_FIELD_ID, MYSQL_SCHEMA_NAME.str, RLI_INFO_NAME.str)))
+        goto err;
+      if (handler_src &&
+          !(*handler_src= new Rpl_info_file(rli->get_number_info_rli_fields(),
+                                            relay_log_info_file)))
+        goto err;
+    break;
+    default:
+      DBUG_ASSERT(0);
   }
+  error= FALSE;
 
-  DBUG_RETURN(FALSE);
+err:
+  DBUG_RETURN(error);
 }

=== modified file 'sql/rpl_info_factory.h'
--- a/sql/rpl_info_factory.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_factory.h	2011-01-17 10:16:47 +0000
@@ -16,6 +16,7 @@
 #ifndef RPL_INFO_FACTORY_H
 #define RPL_INFO_FACTORY_H
 
+#include "table.h"
 #include "rpl_info.h"
 #include "rpl_mi.h"
 #include "rpl_rli.h"
@@ -38,27 +39,39 @@ enum enum_rli_repository
 extern ulong opt_rli_repository_id;
 
 #define MI_FIELD_ID 0
-
-#define MI_SCHEMA "mysql"
-#define MI_TABLE  "slave_master_info"
-
 #define RLI_FIELD_ID 0
 
-#define RLI_SCHEMA "mysql"
-#define RLI_TABLE  "slave_relay_log_info"
-
 class Rpl_info_factory
 {
-  public:
-
+public:
   static bool create(uint mi_option, Master_info **mi,
                      uint rli_option, Relay_log_info **rli);
   static Master_info *create_mi(uint rli_option);
+  static bool change_mi_repository(Master_info *mi, uint mi_option,
+                                   const char **msg);
   static Relay_log_info *create_rli(uint rli_option, bool is_slave_recovery);
-  static bool decide_repository(Rpl_info *info, Rpl_info_table **table,
-                                Rpl_info_file **file, bool is_table,
+  static bool change_rli_repository(Relay_log_info *mi, uint mi_option,
+                                    const char **msg);
+private:
+  static bool decide_repository(Rpl_info *info,
+                                uint option,
+                                Rpl_info_handler **handler_src,
+                                Rpl_info_handler **handler_dest,
+                                const char **msg);
+  static bool change_repository(Rpl_info *info,
+                                uint option,
+                                Rpl_info_handler **handler_src,
+                                Rpl_info_handler **handler_dest,
                                 const char **msg);
-  static bool change_engine(Rpl_info_table *table, const char *engine,
-                            const char **msg);
+  static bool init_mi_repositories(Master_info *mi,
+                                   uint mi_option,
+                                   Rpl_info_handler **handler_src,
+                                   Rpl_info_handler **handler_dest,
+                                   const char **msg);
+  static bool init_rli_repositories(Relay_log_info *rli,
+                                    uint rli_option,
+                                    Rpl_info_handler **handler_src,
+                                    Rpl_info_handler **handler_dest,
+                                    const char **msg);
 };
 #endif

=== modified file 'sql/rpl_info_file.cc'
--- a/sql/rpl_info_file.cc	2010-10-29 09:07:21 +0000
+++ b/sql/rpl_info_file.cc	2011-01-17 10:16:47 +0000
@@ -122,6 +122,11 @@ int Rpl_info_file::do_prepare_info_for_w
 
 int Rpl_info_file::do_check_info()
 {
+  /*
+    We need to improve this in order to distinguish the case
+    that the file does not exist from the case that it is not
+    possible to access due to any problem. / Alfranio 
+  */
   return (access(info_fname,F_OK));
 }
 
@@ -294,6 +299,11 @@ bool Rpl_info_file::do_is_transactional(
 {
   return FALSE;
 }
+
+bool Rpl_info_file::do_update_transactional()
+{
+  return FALSE;
+}
 
 int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
                           const char *default_val)

=== modified file 'sql/rpl_info_file.h'
--- a/sql/rpl_info_file.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_file.h	2011-01-17 10:16:47 +0000
@@ -20,13 +20,16 @@
 #include <sql_priv.h>
 #include "rpl_info_handler.h"
 
+class Rpl_info_factory;
+
 /**
   Defines a file hander.
 */
 class Rpl_info_file : public Rpl_info_handler
 {
+  friend class Rpl_info_factory;
+
 public:
-  Rpl_info_file(int const nparam, const char* param_info_fname);
   virtual ~Rpl_info_file() { };
 
 private:
@@ -66,8 +69,11 @@ private:
                    const Server_ids *default_value);
   char* do_get_description_info();
   bool do_is_transactional();
+  bool do_update_transactional();
 
-  Rpl_info_file& operator=(const Rpl_info_file& info);
+  Rpl_info_file(int const nparam, const char* param_info_fname);
   Rpl_info_file(const Rpl_info_file& info);
+
+  Rpl_info_file& operator=(const Rpl_info_file& info);
 };
 #endif /* RPL_INFO_FILE_H */

=== modified file 'sql/rpl_info_handler.cc'
--- a/sql/rpl_info_handler.cc	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_handler.cc	2011-01-17 10:16:47 +0000
@@ -35,10 +35,7 @@ Rpl_info_handler::Rpl_info_handler(const
 
 Rpl_info_handler::~Rpl_info_handler()
 {
-  if (field_values)
-  {
-    delete field_values;
-  }
+  delete field_values;
 }
 
 void Rpl_info_handler::set_sync_period(uint period)

=== modified file 'sql/rpl_info_handler.h'
--- a/sql/rpl_info_handler.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_handler.h	2011-01-17 10:16:47 +0000
@@ -23,9 +23,6 @@
 class Rpl_info_handler
 {
 public:
-  Rpl_info_handler(const int nparam);
-  virtual ~Rpl_info_handler();
-
   /**
     After creating an object and assembling components, this method is
     used to initialize internal structures. Everything that does not
@@ -260,6 +257,21 @@ public:
   */
   bool is_transactional() { return do_is_transactional(); }
 
+  /**
+    Updates the value returned by the member function is_transactional()
+    because it may be expensive to compute it whenever is_transactional()
+    is called.
+
+    In the current implementation, the type of the repository can only be
+    changed when replication, i.e. slave, is stopped. For that reason,
+    this member function, i.e. update_transactional(), must be called when
+    slave is started.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  bool update_transactional() { return do_update_transactional(); }
+
   /*                                                                                                                                    
     Pre-store information before writing it to the repository and if
     necessary after reading it from the repository. The decision is
@@ -267,6 +279,8 @@ public:
   */
   Rpl_info_values *field_values;
 
+  virtual ~Rpl_info_handler();
+
 protected:
   /* Number of fields to be stored in the repository. */
   int ninfo;
@@ -289,6 +303,8 @@ protected:
   */
   uint sync_period;
 
+  Rpl_info_handler(const int nparam);
+
 private:
   virtual int do_init_info()= 0;
   virtual int do_check_info()= 0;
@@ -315,8 +331,10 @@ private:
                            const Server_ids *default_value)= 0;
   virtual char* do_get_description_info()= 0;
   virtual bool do_is_transactional()= 0;
+  virtual bool do_update_transactional()= 0;
 
-  Rpl_info_handler& operator=(const Rpl_info_handler& handler);
   Rpl_info_handler(const Rpl_info_handler& handler);
+
+  Rpl_info_handler& operator=(const Rpl_info_handler& handler);
 };
 #endif /* RPL_INFO_HANDLER_H */

=== modified file 'sql/rpl_info_table.cc'
--- a/sql/rpl_info_table.cc	2010-12-03 00:15:40 +0000
+++ b/sql/rpl_info_table.cc	2011-01-17 10:16:47 +0000
@@ -15,12 +15,12 @@
 
 #include "rpl_info_table.h"
 #include "rpl_utility.h"
-#include "sql_parse.h"
 
 Rpl_info_table::Rpl_info_table(uint nparam, uint param_field_idx,
                                const char* param_schema,
                                const char *param_table)
-:Rpl_info_handler(nparam), field_idx(param_field_idx)
+:Rpl_info_handler(nparam), field_idx(param_field_idx),
+ is_transactional(FALSE)
 {
   str_schema.str= str_table.str= NULL;
   str_schema.length= str_table.length= 0;
@@ -52,17 +52,13 @@ Rpl_info_table::Rpl_info_table(uint npar
 
 Rpl_info_table::~Rpl_info_table()
 {
-  if (access)
-    delete access;
+  delete access;
   
-  if (description)
-    my_free(description);
+  my_free(description);
 
-  if (str_table.str)
-    my_free(str_table.str);
+  my_free(str_table.str);
 
-  if (str_schema.str)
-    my_free(str_schema.str);
+  my_free(str_schema.str);
 }
 
 int Rpl_info_table::do_init_info()
@@ -447,47 +443,35 @@ char* Rpl_info_table::do_get_description
 
 bool Rpl_info_table::do_is_transactional()
 {
-  ulong saved_mode;
-  TABLE *table= NULL;
-  Open_tables_backup backup;
-  bool is_trans= FALSE;
-
-  DBUG_ENTER("Rpl_info_table::do_is_transactional");
-
-  THD *thd= access->create_thd();
-
-  saved_mode= thd->variables.sql_mode;
-
-  /*
-    Opens and locks the rpl_info table before accessing it.
-  */
-  if (!access->open_table(thd, str_schema, str_table,
-                          get_number_info(), TL_READ,
-                          &table, &backup))
-    is_trans= table->file->has_transactions();
-
-  access->close_table(thd, table, &backup, 0);
-  thd->variables.sql_mode= saved_mode;
-  access->drop_thd(thd);
-  DBUG_RETURN(is_trans);
+  return is_transactional;
 }
 
-bool Rpl_info_table::change_engine(const char *engine)
+bool Rpl_info_table::do_update_transactional()
 {
   bool error= TRUE;
   ulong saved_mode;
-
-  DBUG_ENTER("Rpl_info_table::do_check_info");
+  TABLE *table= NULL;
+  Open_tables_backup backup;
+ 
+  DBUG_ENTER("Rpl_info_table::do_update_transactional");
 
   THD *thd= access->create_thd();
-
   saved_mode= thd->variables.sql_mode;
   tmp_disable_binlog(thd);
 
-  /* TODO: Change the engine using internal functions */
-
+  /*
+    Opens and locks the rpl_info table before accessing it.
+  */
+  if (access->open_table(thd, str_schema, str_table,
+                         get_number_info(), TL_READ,
+                         &table, &backup))
+    goto end;
+ 
+  is_transactional= table->file->has_transactions();
   error= FALSE;
 
+end:
+  access->close_table(thd, table, &backup, 0);
   reenable_binlog(thd);
   thd->variables.sql_mode= saved_mode;
   access->drop_thd(thd);

=== modified file 'sql/rpl_info_table.h'
--- a/sql/rpl_info_table.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_table.h	2011-01-17 10:16:47 +0000
@@ -19,22 +19,15 @@
 #include "rpl_info_handler.h"
 #include "rpl_info_table_access.h"
 
+class Rpl_info_factory;
+
 class Rpl_info_table : public Rpl_info_handler
 {
+  friend class Rpl_info_factory;
+
 public:
-  Rpl_info_table(uint nparam, uint param_field_id, const char* param_schema,
-                 const char *param_table);
   virtual ~Rpl_info_table();
-  /*
-    This enables to change the engine in use by internally executing
-    an ALTER TABLE ENGINE= engine.
-
-    @param[in]  engine  Type of the engine, e.g. Innodb, MyIsam.
 
-    @retval FALSE No error
-    @retval TRUE  Failure
-  */
-  bool change_engine(const char* engine);
 private:
   /*
     This property identifies the name of the schema where a
@@ -65,6 +58,12 @@ private:
   */
   Rpl_info_table_access *access;
 
+  /*
+    Identifies if a table is transactional or non-transactional.
+    This is used to provide a crash-safe behaviour.
+  */
+  bool is_transactional;
+
   int do_init_info();
   int do_check_info();
   void do_end_info();
@@ -90,9 +89,12 @@ private:
                    const Server_ids *default_value);
   char* do_get_description_info();
   bool do_is_transactional();
+  bool do_update_transactional();
 
-  Rpl_info_table& operator=(const Rpl_info_table& info);
+  Rpl_info_table(uint nparam, uint param_field_id, const char* param_schema,
+                 const char *param_table);
   Rpl_info_table(const Rpl_info_table& info);
-};
 
+  Rpl_info_table& operator=(const Rpl_info_table& info);
+};
 #endif /* RPL_INFO_TABLE_H */

=== modified file 'sql/rpl_info_table_access.cc'
--- a/sql/rpl_info_table_access.cc	2010-10-27 11:20:32 +0000
+++ b/sql/rpl_info_table_access.cc	2011-01-17 10:16:47 +0000
@@ -288,6 +288,8 @@ THD *Rpl_info_table_access::create_thd()
     thd= new THD;
     thd->thread_stack= (char*) &thd;
     thd->store_globals();
+    thd->security_ctx->skip_grants();
+    thd->system_thread= SYSTEM_THREAD_INFO_REPOSITORY;
   }
   else
     thd= current_thd;

=== modified file 'sql/rpl_info_values.cc'
--- a/sql/rpl_info_values.cc	2010-10-27 09:04:21 +0000
+++ b/sql/rpl_info_values.cc	2011-01-17 10:16:47 +0000
@@ -39,8 +39,5 @@ bool Rpl_info_values::init()
 
 Rpl_info_values::~Rpl_info_values()
 {
-  for (int pos= 0; pos < ninfo; pos++)
-    value[pos].~String();
-
   delete [] value;
 }

=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h	2010-12-21 09:33:41 +0000
+++ b/sql/rpl_mi.h	2011-01-17 10:16:47 +0000
@@ -27,6 +27,7 @@
 #include "my_sys.h"
 
 typedef struct st_mysql MYSQL;
+class Rpl_info_factory;
 
 /*****************************************************************************
   Replication IO Thread
@@ -62,18 +63,9 @@ typedef struct st_mysql MYSQL;
 
 class Master_info : public Rpl_info
 {
- public:
-  Master_info(
-#ifdef HAVE_PSI_INTERFACE
-              PSI_mutex_key *param_key_info_run_lock,
-              PSI_mutex_key *param_key_info_data_lock,
-              PSI_mutex_key *param_key_info_data_cond,
-              PSI_mutex_key *param_key_info_start_cond,
-              PSI_mutex_key *param_key_info_stop_cond
-#endif
-             );
-  virtual ~Master_info();
+  friend class Rpl_info_factory;
 
+public:
   /* the variables below are needed because we can change masters on the fly */
   char host[HOSTNAME_LENGTH+1];
   char user[USERNAME_LENGTH+1];
@@ -120,6 +112,8 @@ class Master_info : public Rpl_info
 
   bool shall_ignore_server_id(ulong s_id);
 
+  virtual ~Master_info();
+
 protected:
   char master_log_name[FN_REFLEN];
   my_off_t master_log_pos;
@@ -146,8 +140,18 @@ private:
   bool read_info(Rpl_info_handler *from);
   bool write_info(Rpl_info_handler *to, bool force);
 
-  Master_info& operator=(const Master_info& info);
+  Master_info(
+#ifdef HAVE_PSI_INTERFACE
+              PSI_mutex_key *param_key_info_run_lock,
+              PSI_mutex_key *param_key_info_data_lock,
+              PSI_mutex_key *param_key_info_data_cond,
+              PSI_mutex_key *param_key_info_start_cond,
+              PSI_mutex_key *param_key_info_stop_cond
+#endif
+             );
   Master_info(const Master_info& info);
+
+  Master_info& operator=(const Master_info& info);
 };
 int change_master_server_id_cmp(ulong *id1, ulong *id2);
 

=== modified file 'sql/rpl_rli.h'
--- a/sql/rpl_rli.h	2010-12-21 09:33:41 +0000
+++ b/sql/rpl_rli.h	2011-01-17 10:16:47 +0000
@@ -28,6 +28,7 @@
 
 struct RPL_TABLE_LIST;
 class Master_info;
+class Rpl_info_factory;
 extern uint sql_slave_skip_counter;
 
 /*******************************************************************************
@@ -104,6 +105,8 @@ tables along with the --relay-log-recove
 *******************************************************************************/
 class Relay_log_info : public Rpl_info
 {
+  friend class Rpl_info_factory;
+
 public:
   /**
      Flags for the state of the replication.
@@ -328,17 +331,6 @@ public:
   char slave_patternload_file[FN_REFLEN]; 
   size_t slave_patternload_file_size;  
 
-  Relay_log_info(bool is_slave_recovery
-#ifdef HAVE_PSI_INTERFACE
-                 ,PSI_mutex_key *param_key_info_run_lock,
-                 PSI_mutex_key *param_key_info_data_lock,
-                 PSI_mutex_key *param_key_info_data_cond,
-                 PSI_mutex_key *param_key_info_start_cond,
-                 PSI_mutex_key *param_key_info_stop_cond
-#endif
-                );
-  virtual ~Relay_log_info();
-
   /**
     Invalidates cached until_log_name and group_relay_log_name comparison
     result. Should be called after any update of group_realy_log_name if
@@ -585,8 +577,9 @@ public:
   void set_sql_delay(time_t _sql_delay) { sql_delay= _sql_delay; }
   time_t get_sql_delay_end() { return sql_delay_end; }
 
-private:
+  virtual ~Relay_log_info();
 
+private:
   /**
     Delay slave SQL thread by this amount, compared to master (in
     seconds). This is set with CHANGE MASTER TO MASTER_DELAY=X.
@@ -610,6 +603,7 @@ private:
   */
   time_t sql_delay_end;
 
+  uint32 m_flags;
   /*
     Before the MASTER_DELAY parameter was added (WL#344), relay_log.info
     had 4 lines. Now it has 5 lines.
@@ -619,10 +613,18 @@ private:
   bool read_info(Rpl_info_handler *from);
   bool write_info(Rpl_info_handler *to, bool force);
 
-  Relay_log_info& operator=(const Relay_log_info& info);
+  Relay_log_info(bool is_slave_recovery
+#ifdef HAVE_PSI_INTERFACE
+                 ,PSI_mutex_key *param_key_info_run_lock,
+                 PSI_mutex_key *param_key_info_data_lock,
+                 PSI_mutex_key *param_key_info_data_cond,
+                 PSI_mutex_key *param_key_info_start_cond,
+                 PSI_mutex_key *param_key_info_stop_cond
+#endif
+                );
   Relay_log_info(const Relay_log_info& info);
 
-  uint32 m_flags;
+  Relay_log_info& operator=(const Relay_log_info& info);
 };
 
 bool mysql_show_relaylog_events(THD* thd);

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2010-12-10 16:55:50 +0000
+++ b/sql/rpl_slave.cc	2011-01-17 10:16:47 +0000
@@ -3596,7 +3596,7 @@ pthread_handler_t handle_slave_sql(void
 
   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
   my_thread_init();
   DBUG_ENTER("handle_slave_sql");
@@ -3658,6 +3658,20 @@ pthread_handler_t handle_slave_sql(void
   */
   rli->clear_error();
 
+  if (rli->update_transactional())
+  {
+    mysql_cond_broadcast(&rli->start_cond);
+    mysql_mutex_unlock(&rli->run_lock);
+    rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, 
+                "Error checking if the relay log repository is transactional.");
+    goto err;
+  }
+
+  if (!rli->is_transactional())
+    rli->report(WARNING_LEVEL, 0, 
+    "If a crash happens this configuration does not guarantee that the relay "
+    "log info will be consistent");
+
   mysql_mutex_unlock(&rli->run_lock);
   mysql_cond_broadcast(&rli->start_cond);
 

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2010-12-05 22:51:49 +0000
+++ b/sql/share/errmsg-utf8.txt	2011-01-17 10:16:47 +0000
@@ -6444,13 +6444,15 @@ ER_NO_SUCH_KEY_VALUE
 ER_RPL_INFO_DATA_TOO_LONG
   eng "Data for column '%s' too long"
 ER_CANT_LOCK_RPL_INFO_TABLE
-        eng "You can't use locks with rpl info tables."
+  eng "You can't use locks with rpl info tables."
 ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
   eng "Replication event checksum verification failed while reading from network."
 ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE
   eng "Replication event checksum verification failed while reading from a log file."
 
 ER_STMT_CACHE_FULL  
-        eng "Multi-row statements required more than 'max_binlog_stmt_cache_size' bytes of storage; increase this mysqld variable and try again"
+   eng "Multi-row statements required more than 'max_binlog_stmt_cache_size' bytes of storage; increase this mysqld variable and try again"
 ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX
   eng "Option binlog_stmt_cache_size (%lu) is greater than max_binlog_stmt_cache_size (%lu); setting binlog_stmt_cache_size equal to max_binlog_stmt_cache_size."
+ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE
+  eng "Failure while changing the type of replication repository: %s."

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-12-29 00:38:59 +0000
+++ b/sql/sql_class.h	2011-01-17 10:16:47 +0000
@@ -1195,7 +1195,8 @@ enum enum_thread_type
   SYSTEM_THREAD_SLAVE_SQL= 4,
   SYSTEM_THREAD_NDBCLUSTER_BINLOG= 8,
   SYSTEM_THREAD_EVENT_SCHEDULER= 16,
-  SYSTEM_THREAD_EVENT_WORKER= 32
+  SYSTEM_THREAD_EVENT_WORKER= 32,
+  SYSTEM_THREAD_INFO_REPOSITORY= 64
 };
 
 inline char const *
@@ -1211,6 +1212,7 @@ show_system_thread(enum_thread_type thre
     RETURN_NAME_AS_STRING(SYSTEM_THREAD_NDBCLUSTER_BINLOG);
     RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_SCHEDULER);
     RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_WORKER);
+    RETURN_NAME_AS_STRING(SYSTEM_THREAD_INFO_REPOSITORY);
   default:
     sprintf(buf, "<UNKNOWN SYSTEM THREAD: %d>", thread);
     return buf;

=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc	2010-12-10 12:52:55 +0000
+++ b/sql/sql_db.cc	2011-01-17 10:16:47 +0000
@@ -37,6 +37,7 @@
 #include <m_ctype.h>
 #include "log.h"
 #include "binlog.h"                             // mysql_bin_log
+#include "rpl_slave.h"
 #ifdef __WIN__
 #include <direct.h>
 #endif
@@ -760,6 +761,7 @@ bool mysql_rm_db(THD *thd,char *db,bool
 {
   ulong deleted_tables= 0;
   bool error= true;
+  int table_rpl_kind= 0;
   char	path[FN_REFLEN+16];
   MY_DIR *dirp;
   uint length;
@@ -813,6 +815,26 @@ bool mysql_rm_db(THD *thd,char *db,bool
         my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
         goto exit;
       }
+
+      if (!table_rpl_kind && check_if_rpl_table(table->db_length, table->db,
+                                                table->table_name_length,
+                                                table->table_name))
+      {
+#ifdef HAVE_REPLICATION
+        int running= 0;
+        mysql_mutex_lock(&LOCK_active_mi);
+        lock_slave_threads(active_mi);
+        init_thread_mask(&running, active_mi, FALSE);
+        if (running)
+        {
+          unlock_slave_threads(active_mi);
+          mysql_mutex_unlock(&LOCK_active_mi);
+          my_error(ER_SLAVE_MUST_STOP, MYF(0));
+          goto exit;
+        }
+        table_rpl_kind= 1;
+#endif
+      }
     }
   }
 
@@ -986,6 +1008,13 @@ exit:
   if (thd->db && !strcmp(thd->db, db) && !error)
     mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
   my_dirend(dirp);
+#ifdef HAVE_REPLICATION
+  if (table_rpl_kind)
+  {
+    unlock_slave_threads(active_mi);
+    mysql_mutex_unlock(&LOCK_active_mi);
+  }
+#endif
   DBUG_RETURN(error);
 }
 

=== modified file 'sql/sql_partition_admin.cc'
--- a/sql/sql_partition_admin.cc	2010-12-03 10:05:56 +0000
+++ b/sql/sql_partition_admin.cc	2011-01-17 10:16:47 +0000
@@ -31,6 +31,7 @@
 #include "ha_partition.h"                   // ha_partition
 #endif
 #include "sql_base.h"                       // open_and_lock_tables
+#include "rpl_slave.h"
 
 #ifndef WITH_PARTITION_STORAGE_ENGINE
 
@@ -487,6 +488,7 @@ bool Sql_cmd_alter_table_exchange_partit
   MDL_ticket *swap_table_mdl_ticket= NULL;
   MDL_ticket *part_table_mdl_ticket= NULL;
   bool error= TRUE;
+  int table_rpl_kind= 0;
   DBUG_ENTER("mysql_exchange_partition");
   DBUG_ASSERT(alter_info->flags & ALTER_EXCHANGE_PARTITION);
 
@@ -505,6 +507,26 @@ bool Sql_cmd_alter_table_exchange_partit
     DBUG_RETURN(TRUE);
   }
 
+  table_rpl_kind= check_if_rpl_table(swap_table_list->db_length, swap_table_list->db,
+                                     swap_table_list->table_name_length,
+                                     swap_table_list->table_name);
+  if (table_rpl_kind)
+  {
+#ifdef HAVE_REPLICATION
+    int running= 0;
+    mysql_mutex_lock(&LOCK_active_mi);
+    lock_slave_threads(active_mi);
+    init_thread_mask(&running, active_mi, FALSE);
+    if (running)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+      my_error(ER_SLAVE_MUST_STOP, MYF(0));
+      DBUG_RETURN(TRUE);
+    }
+#endif
+  }
+
   /*
     Currently no MDL lock that allows both read and write and is upgradeable
     to exclusive, so leave the lock type to TL_WRITE_ALLOW_READ also on the
@@ -523,14 +545,32 @@ bool Sql_cmd_alter_table_exchange_partit
   */
   if (open_and_lock_tables(thd, table_list, FALSE, 0,
                            &alter_prelocking_strategy))
+  {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
+  }
 
   part_table= table_list->table;
   swap_table= swap_table_list->table;
   table_hton= swap_table->file->ht;
 
   if (check_exchange_partition(swap_table, part_table))
+  {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
+  }
 
   thd_proc_info(thd, "verifying table");
 
@@ -561,6 +601,13 @@ bool Sql_cmd_alter_table_exchange_partit
   {
     my_error(ER_UNKNOWN_PARTITION, MYF(0), partition_name,
              part_table->alias);
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
   }
 
@@ -568,18 +615,43 @@ bool Sql_cmd_alter_table_exchange_partit
   {
     DBUG_ASSERT(part_table->part_info->is_sub_partitioned());
     my_error(ER_PARTITION_INSTEAD_OF_SUBPARTITION, MYF(0));
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
   }
 
   if (compare_table_with_partition(thd, swap_table, part_table, part_elem))
+  {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
+  }
 
   /* Table and partition has same structure/options, OK to exchange */
 
   thd_proc_info(thd, "verifying data with partition");
 
   if (verify_data_with_partition(swap_table, part_table, swap_part_id))
+  {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
+  }
 
   /*
     Get exclusive mdl lock on both tables, alway the non partitioned table
@@ -643,6 +715,13 @@ err:
   table_list->next_local->table= NULL;
   query_cache_invalidate3(thd, table_list, FALSE);
 
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
   DBUG_RETURN(error);
 }
 

=== modified file 'sql/sql_rename.cc'
--- a/sql/sql_rename.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_rename.cc	2011-01-17 10:16:47 +0000
@@ -28,6 +28,7 @@
 #include "sql_base.h"   // tdc_remove_table, lock_table_names,
 #include "sql_handler.h"                        // mysql_ha_rm_tables
 #include "datadict.h"
+#include "rpl_slave.h"
 
 static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
 				 bool skip_error);
@@ -46,6 +47,7 @@ bool mysql_rename_tables(THD *thd, TABLE
   TABLE_LIST *ren_table= 0;
   int to_table;
   char *rename_log_table[2]= {NULL, NULL};
+  int table_rpl_kind= 0;
   DBUG_ENTER("mysql_rename_tables");
 
   /*
@@ -57,7 +59,31 @@ bool mysql_rename_tables(THD *thd, TABLE
   {
     my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
                ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
-    DBUG_RETURN(1);
+    DBUG_RETURN(TRUE);
+  }
+
+  for (ren_table= table_list; ren_table;
+       ren_table= ren_table->next_local)
+  {
+    if (!table_rpl_kind && check_if_rpl_table(ren_table->db_length, ren_table->db,
+                                              ren_table->table_name_length,
+                                              ren_table->table_name))
+    {
+#ifdef HAVE_REPLICATION
+      int running= 0;
+      mysql_mutex_lock(&LOCK_active_mi);
+      lock_slave_threads(active_mi);
+      init_thread_mask(&running, active_mi, FALSE);
+      if (running)
+      {
+        unlock_slave_threads(active_mi);
+        mysql_mutex_unlock(&LOCK_active_mi);
+        my_error(ER_SLAVE_MUST_STOP, MYF(0));
+        DBUG_RETURN(TRUE);
+      }
+      table_rpl_kind= 1;
+#endif
+    }
   }
 
   mysql_ha_rm_tables(thd, table_list);
@@ -185,6 +211,13 @@ bool mysql_rename_tables(THD *thd, TABLE
     query_cache_invalidate3(thd, table_list, 0);
 
 err:
+#ifdef HAVE_REPLICATION
+  if (table_rpl_kind)
+  {
+    unlock_slave_threads(active_mi);
+    mysql_mutex_unlock(&LOCK_active_mi);
+  }
+#endif
   DBUG_RETURN(error || binlog_error);
 }
 

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-12-17 18:43:38 +0000
+++ b/sql/sql_table.cc	2011-01-17 10:16:47 +0000
@@ -51,6 +51,7 @@
 #include "sql_show.h"
 #include "transaction.h"
 #include "datadict.h"  // dd_frm_type()
+#include "rpl_slave.h"
 
 #ifdef __WIN__
 #include <io.h>
@@ -2036,6 +2037,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
                     my_bool drop_temporary)
 {
   bool error;
+  int table_rpl_kind= 0;
   Drop_table_error_handler err_handler;
   TABLE_LIST *table;
 
@@ -2050,6 +2052,25 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
       my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
       DBUG_RETURN(true);
     }
+    if (!table_rpl_kind && check_if_rpl_table(table->db_length, table->db,
+                                              table->table_name_length,
+                                              table->table_name))
+    {
+#ifdef HAVE_REPLICATION
+      int running= 0;
+      mysql_mutex_lock(&LOCK_active_mi);
+      lock_slave_threads(active_mi);
+      init_thread_mask(&running, active_mi, FALSE);
+      if (running)
+      {
+        unlock_slave_threads(active_mi);
+        mysql_mutex_unlock(&LOCK_active_mi);
+        my_error(ER_SLAVE_MUST_STOP, MYF(0));
+        DBUG_RETURN(TRUE);
+      }
+      table_rpl_kind= 1;
+#endif
+    }
   }
 
   mysql_ha_rm_tables(thd, tables);
@@ -2060,7 +2081,16 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
     {
       if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout,
                            MYSQL_OPEN_SKIP_TEMPORARY))
+      {
+#ifdef HAVE_REPLICATION
+        if (table_rpl_kind)
+        {
+          unlock_slave_threads(active_mi);
+          mysql_mutex_unlock(&LOCK_active_mi);
+        }
+#endif
         DBUG_RETURN(true);
+      }
       for (table= tables; table; table= table->next_local)
         tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
                          false);
@@ -2098,7 +2128,16 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
           table->table= find_table_for_mdl_upgrade(thd->open_tables, table->db,
                                                    table->table_name, false);
           if (!table->table)
+          {
+#ifdef HAVE_REPLICATION
+            if (table_rpl_kind)
+            {
+              unlock_slave_threads(active_mi);
+              mysql_mutex_unlock(&LOCK_active_mi);
+            }
+#endif
             DBUG_RETURN(true);
+          }
           table->mdl_request.ticket= table->table->mdl_ticket;
         }
     }
@@ -2110,6 +2149,14 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
                                  false, false);
   thd->pop_internal_handler();
 
+#ifdef HAVE_REPLICATION
+  if (table_rpl_kind)
+  {
+    unlock_slave_threads(active_mi);
+    mysql_mutex_unlock(&LOCK_active_mi);
+  }
+#endif
+
   if (error)
     DBUG_RETURN(TRUE);
   my_ok(thd);
@@ -5887,6 +5934,8 @@ bool mysql_alter_table(THD *thd,char *ne
   uint *index_add_buffer= NULL;
   uint candidate_key_count= 0;
   bool no_pk;
+  int table_log_kind= 0, table_rpl_kind= 0;
+
   DBUG_ENTER("mysql_alter_table");
 
   /*
@@ -5897,16 +5946,13 @@ bool mysql_alter_table(THD *thd,char *ne
   */
   if (table_list && table_list->db && table_list->table_name)
   {
-    int table_kind= 0;
-
-    table_kind= check_if_log_table(table_list->db_length, table_list->db,
-                                   table_list->table_name_length,
-                                   table_list->table_name, 0);
-
-    if (table_kind)
+    table_log_kind= check_if_log_table(table_list->db_length, table_list->db,
+                                       table_list->table_name_length,
+                                       table_list->table_name, 0);
+    if (table_log_kind)
     {
       /* Disable alter of enabled log tables */
-      if (logger.is_log_table_enabled(table_kind))
+      if (logger.is_log_table_enabled(table_log_kind))
       {
         my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
         DBUG_RETURN(TRUE);
@@ -5929,6 +5975,41 @@ bool mysql_alter_table(THD *thd,char *ne
       }
 #endif
     }
+
+    table_rpl_kind= check_if_rpl_table(table_list->db_length, table_list->db,
+                                       table_list->table_name_length,
+                                       table_list->table_name);
+    if (table_rpl_kind)
+    {
+      if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
+          !create_info->db_type)
+      {
+        my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
+        DBUG_RETURN(TRUE);
+      }
+
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+      if (alter_info->flags & ALTER_PARTITION)
+      {
+        my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "replication table");
+        DBUG_RETURN(TRUE);
+      }
+#endif
+
+#ifdef HAVE_REPLICATION
+      int running= 0;
+      mysql_mutex_lock(&LOCK_active_mi);
+      lock_slave_threads(active_mi);
+      init_thread_mask(&running, active_mi, FALSE);
+      if (running)
+      {
+        unlock_slave_threads(active_mi);
+        mysql_mutex_unlock(&LOCK_active_mi);
+        my_error(ER_SLAVE_MUST_STOP, MYF(0));
+        DBUG_RETURN(TRUE);
+      }
+#endif
+    }
   }
 
   /*
@@ -5950,8 +6031,18 @@ bool mysql_alter_table(THD *thd,char *ne
   /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
   if (alter_info->tablespace_op != NO_TABLESPACE_OP)
     /* Conditionally writes to binlog. */
-    DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
-						   alter_info->tablespace_op));
+  {
+    int ret= mysql_discard_or_import_tablespace(thd,table_list,
+                                                   alter_info->tablespace_op);
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
+    DBUG_RETURN(ret);
+  }
 
   /*
     Code below can handle only base tables so ensure that we won't open a view.
@@ -5970,6 +6061,13 @@ bool mysql_alter_table(THD *thd,char *ne
 
   if (error)
   {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
   }
 
@@ -5988,6 +6086,13 @@ bool mysql_alter_table(THD *thd,char *ne
       (create_info->used_fields & HA_CREATE_USED_UNION) &&
       (table->s->tmp_table == NO_TMP_TABLE))
   {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
     DBUG_RETURN(TRUE);
   }
@@ -6022,6 +6127,13 @@ bool mysql_alter_table(THD *thd,char *ne
       {
 	if (find_temporary_table(thd,new_db,new_name_buff))
 	{
+#ifdef HAVE_REPLICATION
+          if (table_rpl_kind)
+          {
+            unlock_slave_threads(active_mi);
+            mysql_mutex_unlock(&LOCK_active_mi);
+          }
+#endif
 	  my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 	  DBUG_RETURN(TRUE);
 	}
@@ -6039,9 +6151,25 @@ bool mysql_alter_table(THD *thd,char *ne
                                                    MDL_INTENTION_EXCLUSIVE));
 
         if (thd->mdl_context.try_acquire_lock(&target_mdl_request))
+        {
+#ifdef HAVE_REPLICATION
+          if (table_rpl_kind)
+          {
+            unlock_slave_threads(active_mi);
+            mysql_mutex_unlock(&LOCK_active_mi);
+          }
+#endif
           DBUG_RETURN(TRUE);
+        }
         if (target_mdl_request.ticket == NULL)
         {
+#ifdef HAVE_REPLICATION
+          if (table_rpl_kind)
+          {
+            unlock_slave_threads(active_mi);
+            mysql_mutex_unlock(&LOCK_active_mi);
+          }
+#endif
           /* Table exists and is locked by some thread. */
 	  my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 	  DBUG_RETURN(TRUE);
@@ -6237,6 +6365,13 @@ bool mysql_alter_table(THD *thd,char *ne
       else
         mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
     }
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(error);
   }
 
@@ -6480,11 +6615,19 @@ bool mysql_alter_table(THD *thd,char *ne
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   if (table_for_fast_alter_partition)
-  {
-    DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info,
-                                           create_info, table_list,
-                                           db, table_name,
-                                           table_for_fast_alter_partition));
+  { 
+    uint ret= fast_alter_partition_table(thd, table, alter_info,
+                                         create_info, table_list,
+                                         db, table_name,
+                                         table_for_fast_alter_partition);
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
+    DBUG_RETURN(ret);
   }
 #endif
 
@@ -6747,7 +6890,16 @@ bool mysql_alter_table(THD *thd,char *ne
     /* We don't replicate alter table statement on temporary tables */
     if (!thd->is_current_stmt_binlog_format_row() &&
         write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
+    {
+#ifdef HAVE_REPLICATION
+      if (table_rpl_kind)
+      {
+        unlock_slave_threads(active_mi);
+        mysql_mutex_unlock(&LOCK_active_mi);
+      }
+#endif
       DBUG_RETURN(TRUE);
+    }
     goto end_temporary;
   }
 
@@ -6908,7 +7060,16 @@ bool mysql_alter_table(THD *thd,char *ne
                 thd->is_current_stmt_binlog_format_row() &&
                 (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
   if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
+  {
+#ifdef HAVE_REPLICATION
+    if (table_rpl_kind)
+    {
+      unlock_slave_threads(active_mi);
+      mysql_mutex_unlock(&LOCK_active_mi);
+    }
+#endif
     DBUG_RETURN(TRUE);
+  }
 
   if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
   {
@@ -6948,6 +7109,13 @@ end_temporary:
 	      (ulong) (copied + deleted), (ulong) deleted,
 	      (ulong) thd->warning_info->statement_warn_count());
   my_ok(thd, copied + deleted, 0L, tmp_name);
+#ifdef HAVE_REPLICATION
+  if (table_rpl_kind)
+  {
+    unlock_slave_threads(active_mi);
+    mysql_mutex_unlock(&LOCK_active_mi);
+  }
+#endif
   DBUG_RETURN(FALSE);
 
 err_new_table_cleanup:
@@ -6999,7 +7167,13 @@ err:
                                  alter_info->datetime_field->field_name);
     thd->abort_on_warning= save_abort_on_warning;
   }
-
+#ifdef HAVE_REPLICATION
+  if (table_rpl_kind)
+  {
+    unlock_slave_threads(active_mi);
+    mysql_mutex_unlock(&LOCK_active_mi);
+  }
+#endif
   DBUG_RETURN(TRUE);
 
 err_with_mdl:
@@ -7011,6 +7185,13 @@ err_with_mdl:
   */
   thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
   thd->mdl_context.release_all_locks_for_name(mdl_ticket);
+#ifdef HAVE_REPLICATION
+  if (table_rpl_kind)
+  {
+    unlock_slave_threads(active_mi);
+    mysql_mutex_unlock(&LOCK_active_mi);
+  }
+#endif
   DBUG_RETURN(TRUE);
 }
 /* mysql_alter_table */
@@ -7484,3 +7665,30 @@ static bool check_engine(THD *thd, const
   }
   return FALSE;
 }
+
+int check_if_rpl_table(size_t db_len, const char *db, size_t table_name_len,
+                       const char *table_name)
+{
+  if (db_len == MYSQL_SCHEMA_NAME.length &&
+      !(lower_case_table_names ?
+        my_strcasecmp(system_charset_info, db, MYSQL_SCHEMA_NAME.str) :
+        strcmp(db, MYSQL_SCHEMA_NAME.str)))
+  {
+    if (table_name_len == RLI_INFO_NAME.length && !(lower_case_table_names ?
+                                  my_strcasecmp(system_charset_info,
+                                                table_name, RLI_INFO_NAME.str) :
+                                  strcmp(table_name, RLI_INFO_NAME.str)))
+    {
+      return 1;
+    }
+
+    if (table_name_len == MI_INFO_NAME.length && !(lower_case_table_names ?
+      my_strcasecmp(system_charset_info, table_name, MI_INFO_NAME.str) :
+      strcmp(table_name, MI_INFO_NAME.str)))
+    {
+      return 1;
+    }
+  }
+  return 0;
+}
+

=== modified file 'sql/sql_table.h'
--- a/sql/sql_table.h	2010-11-22 14:57:22 +0000
+++ b/sql/sql_table.h	2011-01-17 10:16:47 +0000
@@ -217,6 +217,8 @@ void release_ddl_log();
 void execute_ddl_log_recovery();
 bool execute_ddl_log_entry(THD *thd, uint first_entry);
 bool check_duplicate_warning(THD *thd, char *msg, ulong length);
+int check_if_rpl_table(size_t db_len, const char *db, size_t table_name_len,
+                       const char *table_name);
 
 /*
   These prototypes where under INNODB_COMPATIBILITY_HOOKS.

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2010-12-20 13:26:51 +0000
+++ b/sql/sys_vars.cc	2011-01-17 10:16:47 +0000
@@ -36,6 +36,8 @@
 #include <thr_alarm.h>
 #include "rpl_slave.h"
 #include "rpl_mi.h"
+#include "rpl_rli.h"
+#include "rpl_slave.h"
 #include "rpl_info_factory.h"
 #include "transaction.h"
 #include "mysqld.h"
@@ -431,6 +433,86 @@ static Sys_var_mybool Sys_binlog_direct(
        CMD_LINE(OPT_ARG), DEFAULT(FALSE),
        NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(binlog_direct_check));
 
+static bool master_info_repository_check(sys_var *self, THD *thd, set_var *var)
+{
+  bool ret= FALSE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  if (!(thd->security_ctx->master_access & SUPER_ACL))
+  {
+    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
+    return TRUE;
+  }
+#endif
+#ifdef HAVE_REPLICATION
+  int running= 0;
+  const char *msg= NULL;
+  mysql_mutex_lock(&LOCK_active_mi);
+  if (active_mi)
+  {
+    lock_slave_threads(active_mi);
+    init_thread_mask(&running, active_mi, FALSE);
+    if(!running)
+    {
+      if (Rpl_info_factory::change_mi_repository(active_mi,
+                                                 var->save_result.ulonglong_value,
+                                                 &msg))
+      {
+        ret= TRUE;
+        my_error(ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE, MYF(0), msg);
+      }
+    }
+    else
+    {
+      ret= TRUE;
+      my_error(ER_SLAVE_MUST_STOP, MYF(0));
+    }
+    unlock_slave_threads(active_mi);
+  }
+  mysql_mutex_unlock(&LOCK_active_mi);
+#endif
+  return ret;
+}
+
+static bool relay_log_info_repository_check(sys_var *self, THD *thd, set_var *var)
+{
+  bool ret= FALSE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  if (!(thd->security_ctx->master_access & SUPER_ACL))
+  {
+    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
+    return TRUE;
+  }
+#endif
+#ifdef HAVE_REPLICATION
+  int running= 0;
+  const char *msg= NULL;
+  mysql_mutex_lock(&LOCK_active_mi);
+  if (active_mi)
+  {
+    lock_slave_threads(active_mi);
+    init_thread_mask(&running, active_mi, FALSE);
+    if(!running)
+    {
+      if (Rpl_info_factory::change_rli_repository(active_mi->rli,
+                                                  var->save_result.ulonglong_value,
+                                                  &msg))
+      {
+        ret= TRUE;
+        my_error(ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE, MYF(0), msg);
+      }
+    }
+    else
+    {
+      ret= TRUE;
+      my_error(ER_SLAVE_MUST_STOP, MYF(0));
+    }
+    unlock_slave_threads(active_mi);
+  }
+  mysql_mutex_unlock(&LOCK_active_mi);
+#endif
+  return ret;
+}
+
 static const char *repository_names[]=
 {
   "FILE", "TABLE", 0
@@ -440,15 +522,19 @@ ulong opt_mi_repository_id;
 static Sys_var_enum Sys_mi_repository(
        "master_info_repository",
        "Defines the type of the repository for the master information."
-       , READ_ONLY GLOBAL_VAR(opt_mi_repository_id), CMD_LINE(REQUIRED_ARG),
-       repository_names, DEFAULT(0));
+       ,GLOBAL_VAR(opt_mi_repository_id), CMD_LINE(REQUIRED_ARG),
+       repository_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+       ON_CHECK(master_info_repository_check),
+       ON_UPDATE(0));
 
 ulong opt_rli_repository_id;
 static Sys_var_enum Sys_rli_repository(
        "relay_log_info_repository",
        "Defines the type of the repository for the relay log information."
-       , READ_ONLY GLOBAL_VAR(opt_rli_repository_id), CMD_LINE(REQUIRED_ARG),
-       repository_names, DEFAULT(0));
+       ,GLOBAL_VAR(opt_rli_repository_id), CMD_LINE(REQUIRED_ARG),
+       repository_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+       ON_CHECK(relay_log_info_repository_check),
+       ON_UPDATE(0));
 
 static Sys_var_mybool Sys_binlog_rows_query(
        "binlog_rows_query_log_events",

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-12-29 00:38:59 +0000
+++ b/sql/table.h	2011-01-17 10:16:47 +0000
@@ -2169,6 +2169,10 @@ extern LEX_STRING SLOW_LOG_NAME;
 extern LEX_STRING INFORMATION_SCHEMA_NAME;
 extern LEX_STRING MYSQL_SCHEMA_NAME;
 
+/* replication's tables */
+extern LEX_STRING RLI_INFO_NAME;
+extern LEX_STRING MI_INFO_NAME;
+
 inline bool is_infoschema_db(const char *name, size_t len)
 {
   return (INFORMATION_SCHEMA_NAME.length == len &&

No bundle (reason: revision is a merge).
Thread
bzr commit into mysql-trunk-bugfixing branch (alfranio.correia:3475)Bug#58897Alfranio Correia17 Jan