List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:April 4 2011 10:06am
Subject:bzr commit into mysql-trunk branch (alfranio.correia:3357)
View as plain text  
#At file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/bug-58897/mysql-trunk.merge/ based on revid:alfranio.correia@stripped

 3357 Alfranio Correia	2011-04-04 [merge]
      merge mysql-trunk (local) --> mysql-trunk
      
      Conflicts:
        . sql/share/errmsg-utf8.txt

    modified:
      mysql-test/include/mtr_warnings.sql
      mysql-test/suite/rpl/r/rpl_migration_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/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/rpl_slave.h
      sql/share/errmsg-utf8.txt
      sql/sql_binlog.cc
      sql/sql_class.h
      sql/sys_vars.cc
      sql/table.h
=== modified file 'mysql-test/include/mtr_warnings.sql'
--- a/mysql-test/include/mtr_warnings.sql	2011-02-23 20:01:27 +0000
+++ b/mysql-test/include/mtr_warnings.sql	2011-03-23 23:28:49 +0000
@@ -240,6 +240,12 @@ INSERT INTO global_suppressions VALUES
   */
  ("Found lock of type 6 that is write and read locked"),
 
+ /*
+   Warning message is printed out whenever a slave is started with
+   a configuration that is not crash-safe.
+ */
+ (".*If a crash happens this configuration does not guarantee.*"),
+
  ("THE_LAST_SUPPRESSION")||
 
 

=== 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-03-23 23:28:49 +0000
@@ -5,5 +5,10 @@ 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
 DROP TABLE test;

=== 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-03-23 23:28:49 +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;

=== 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-03-23 23:28:49 +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-03-23 23:28:49 +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-03-23 23:28:49 +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-03-23 23:28:49 +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	2011-03-23 23:28:49 +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	2011-03-23 23:28:49 +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/rpl_info.cc'
--- a/sql/rpl_info.cc	2010-12-21 09:33:41 +0000
+++ b/sql/rpl_info.cc	2011-03-23 23:28:49 +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-03-23 23:28:49 +0000
@@ -21,9 +21,18 @@
 #include "rpl_info_handler.h"
 #include "rpl_reporting.h"
 
+enum enum_info_repository
+{
+  INVALID_INFO_REPOSITORY= -1,
+  INFO_REPOSITORY_FILE= 0,
+  INFO_REPOSITORY_TABLE= 1
+};
+
 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 +62,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 +117,11 @@ public:
     return (handler->is_transactional());
   }
 
+  bool update_is_transactional()
+  {
+    return (handler->update_is_transactional());
+  }
+
   char *get_description_info()
   {
     return (handler->get_description_info());
@@ -92,21 +135,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-03-23 23:28:49 +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,341 @@ 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.
+
+  @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");
 
-  <ul>
-    \li F     --> file
+  Rpl_info_handler*  handler_src= rli->get_rpl_info_handler();
+  Rpl_info_handler*  handler_dest= NULL;
 
-    \li T     --> table
+  if (rli->get_rpl_info_type()  == rli_option)
+    DBUG_RETURN(FALSE);
 
-    \li is_t  --> table with data
+  if (init_rli_repositories(rli, rli_option, NULL, &handler_dest, msg))
+    goto err;
 
-    \li is_f  --> file with data
+  if (change_repository(rli, rli_option, &handler_src, &handler_dest, msg))
+    goto err;
 
-    \li ~is_t --> no data in the table
+  DBUG_RETURN(FALSE);
 
-    \li ~is_f --> no file
-  </ul> 
+err:
+  delete handler_dest;
+  handler_dest= NULL;
 
-  @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.
+  sql_print_error("Error changing the type of relay log info's repository: %s.", *msg);
+  DBUG_RETURN(TRUE);
+}
+
+/**
+  Decides during startup what repository will be used 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 | Error                 | Error                 |
+  |--------------+-----------------------+-----------------------|
+  \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::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());
+  /*
+    check_info() returns FALSE if the repository exists. If a FILE, 
+    for example, this means that FALSE is returned if a file exists.
+    If a TABLE, for example, this means that FALSE is returned if
+    the table exists and is populated. Otherwise, TRUE is returned.
+
+    The check_info() behavior is odd and we are going to fix this
+    in the future.
+
+    So,
 
-  if (is_t && is_f)
+      . is_src  == TRUE, means that the source repository exists.
+      . is_dest == TRUE, means that the destination repository
+        exists.
+
+    /Alfranio
+  */
+  bool is_src= !((*handler_src)->check_info());
+  bool is_dest= !((*handler_dest)->check_info());
+
+  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 master info repositories";
+
+  DBUG_ENTER("Rpl_info_factory::init_mi_repositories");
+
+  DBUG_ASSERT(handler_dest != NULL);
+  switch (mi_option)
+  {
+    case INFO_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 INFO_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 INFO_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 INFO_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-03-23 23:28:49 +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"
@@ -23,42 +24,43 @@
 #include "rpl_info_table.h"
 #include "rpl_info_handler.h"
 
-enum enum_mi_repository
-{
-  MI_REPOSITORY_FILE= 0,
-  MI_REPOSITORY_TABLE= 1
-};
 extern ulong opt_mi_repository_id;
-
-enum enum_rli_repository
-{
-  RLI_REPOSITORY_FILE= 0,
-  RLI_REPOSITORY_TABLE= 1
-};
 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	2011-04-04 09:42:22 +0000
+++ b/sql/rpl_info_file.cc	2011-04-04 10:06:13 +0000
@@ -313,6 +313,11 @@ bool Rpl_info_file::do_is_transactional(
   return FALSE;
 }
 
+bool Rpl_info_file::do_update_is_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-03-23 23:28:49 +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_is_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-03-23 23:28:49 +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	2011-02-04 11:55:17 +0000
+++ b/sql/rpl_info_handler.h	2011-03-23 23:28:49 +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_is__transactional(), must be called
+    when slave is starting.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  bool update_is_transactional() { return do_update_is_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_is_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	2011-04-04 09:42:22 +0000
+++ b/sql/rpl_info_table.cc	2011-04-04 10:06:13 +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()
@@ -452,47 +448,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_is_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_is_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-03-23 23:28:49 +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_is_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-03-23 23:28:49 +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-03-23 23:28:49 +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-03-23 23:28:49 +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-03-23 23:28:49 +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	2011-04-04 08:47:25 +0000
+++ b/sql/rpl_slave.cc	2011-04-04 10:06:13 +0000
@@ -141,8 +141,6 @@ failed read"
 };
 
 
-typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
-
 static int process_io_rotate(Master_info* mi, Rotate_log_event* rev);
 static int process_io_create_file(Master_info* mi, Create_file_log_event* cev);
 static bool wait_for_relay_log_space(Relay_log_info* rli);
@@ -3534,7 +3532,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");
@@ -3596,6 +3594,20 @@ pthread_handler_t handle_slave_sql(void
   */
   rli->clear_error();
 
+  if (rli->update_is_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/rpl_slave.h'
--- a/sql/rpl_slave.h	2011-03-28 13:19:08 +0000
+++ b/sql/rpl_slave.h	2011-04-04 10:06:13 +0000
@@ -16,6 +16,8 @@
 #ifndef RPL_SLAVE_H
 #define RPL_SLAVE_H
 
+typedef enum {SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
+
 /**
   MASTER_DELAY can be at most (1 << 31) - 1.
 */

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2011-03-25 14:35:13 +0000
+++ b/sql/share/errmsg-utf8.txt	2011-04-04 10:06:13 +0000
@@ -6495,3 +6495,6 @@ ER_TABLE_NEEDS_REBUILD
 
 WARN_OPTION_BELOW_LIMIT
   eng "The value of '%s' should be no less than the value of '%s'"
+
+ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE
+  eng "Failure while changing the type of replication repository: %s."

=== modified file 'sql/sql_binlog.cc'
--- a/sql/sql_binlog.cc	2010-12-02 13:44:21 +0000
+++ b/sql/sql_binlog.cc	2011-03-23 23:28:49 +0000
@@ -158,7 +158,7 @@ void mysql_client_binlog_statement(THD*
   Relay_log_info *rli= thd->rli_fake;
   if (!rli)
   {
-    if ((rli= Rpl_info_factory::create_rli(RLI_REPOSITORY_FILE, FALSE)))
+    if ((rli= Rpl_info_factory::create_rli(INFO_REPOSITORY_FILE, FALSE)))
     {
       thd->rli_fake= rli;
       rli->info_thd= thd;

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-03-24 08:00:03 +0000
+++ b/sql/sql_class.h	2011-04-04 10:06:13 +0000
@@ -1193,7 +1193,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 *
@@ -1209,6 +1210,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/sys_vars.cc'
--- a/sql/sys_vars.cc	2011-03-25 14:35:13 +0000
+++ b/sql/sys_vars.cc	2011-04-04 10:06:13 +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"
@@ -490,6 +492,73 @@ 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 repository_check(sys_var *self, THD *thd, set_var *var, SLAVE_THD_TYPE thread_mask)
+{
+  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)
+    {
+      switch (thread_mask)
+      {
+        case SLAVE_THD_IO:
+        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);
+        }
+        break;
+        case SLAVE_THD_SQL:
+          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);
+          }
+        break;
+        default:
+          assert(0);
+        break;
+      }
+    }
+    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)
+{
+  return repository_check(self, thd, var, SLAVE_THD_SQL);
+}
+
+static bool master_info_repository_check(sys_var *self, THD *thd, set_var *var)
+{
+  return repository_check(self, thd, var, SLAVE_THD_IO);
+}
+
 static const char *repository_names[]=
 {
   "FILE", "TABLE", 0
@@ -499,15 +568,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	2011-04-01 14:04:52 +0000
+++ b/sql/table.h	2011-04-04 10:06:13 +0000
@@ -2203,6 +2203,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 branch (alfranio.correia:3357) Alfranio Correia4 Apr