MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:December 15 2009 2:40am
Subject:bzr commit into mysql-5.1-rep+3 branch (alfranio.correia:3124) WL#2775
View as plain text  
#At file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/wl-2775/mysql-5.1-rep%2B3/ based on revid:alfranio.correia@stripped

 3124 Alfranio Correia	2009-12-15
      WL#2775 System tables for master.info, relay_log.info
      
      Missing:
      
      1 - doxygen's comments yet.

    added:
      sql/rpl_info_factory.cc
      sql/rpl_info_factory.h
      sql/rpl_info_table.cc
      sql/rpl_info_table.h
      sql/rpl_mi_table.cc
      sql/rpl_mi_table.h
      sql/rpl_rli_table.cc
      sql/rpl_rli_table.h
    modified:
      mysql-test/r/1st.result
      mysql-test/r/connect.result
      mysql-test/r/information_schema.result
      mysql-test/r/mysql_upgrade.result
      mysql-test/r/mysqlcheck.result
      mysql-test/r/system_mysql_db.result
      mysql-test/suite/rpl/r/rpl_flushlog_loop.result
      mysql-test/t/system_mysql_db_fix30020.test
      mysql-test/t/system_mysql_db_fix40123.test
      mysql-test/t/system_mysql_db_fix50030.test
      mysql-test/t/system_mysql_db_fix50117.test
      scripts/mysql_install_db.pl.in
      scripts/mysql_install_db.sh
      scripts/mysql_system_tables.sql
      sql/CMakeLists.txt
      sql/Makefile.am
      sql/log.cc
      sql/mysql_priv.h
      sql/mysqld.cc
      sql/set_var.cc
      sql/share/errmsg.txt
      sql/slave.cc
      sql/slave.h
      sql/sql_binlog.cc
=== modified file 'mysql-test/r/1st.result'
--- a/mysql-test/r/1st.result	2008-04-02 08:06:36 +0000
+++ b/mysql-test/r/1st.result	2009-12-15 02:40:10 +0000
@@ -16,10 +16,12 @@ help_keyword
 help_relation
 help_topic
 host
+mi_info
 ndb_binlog_index
 plugin
 proc
 procs_priv
+rli_info
 servers
 slow_log
 tables_priv

=== modified file 'mysql-test/r/connect.result'
--- a/mysql-test/r/connect.result	2009-03-06 14:56:17 +0000
+++ b/mysql-test/r/connect.result	2009-12-15 02:40:10 +0000
@@ -11,10 +11,12 @@ help_keyword
 help_relation
 help_topic
 host
+mi_info
 ndb_binlog_index
 plugin
 proc
 procs_priv
+rli_info
 servers
 slow_log
 tables_priv
@@ -44,10 +46,12 @@ help_keyword
 help_relation
 help_topic
 host
+mi_info
 ndb_binlog_index
 plugin
 proc
 procs_priv
+rli_info
 servers
 slow_log
 tables_priv
@@ -85,10 +89,12 @@ help_keyword
 help_relation
 help_topic
 host
+mi_info
 ndb_binlog_index
 plugin
 proc
 procs_priv
+rli_info
 servers
 slow_log
 tables_priv

=== modified file 'mysql-test/r/information_schema.result'
--- a/mysql-test/r/information_schema.result	2009-05-15 12:57:51 +0000
+++ b/mysql-test/r/information_schema.result	2009-12-15 02:40:10 +0000
@@ -81,9 +81,11 @@ help_keyword
 help_relation
 help_topic
 host
+mi_info
 plugin
 proc
 procs_priv
+rli_info
 servers
 slow_log
 tables_priv
@@ -853,7 +855,7 @@ flush privileges;
 SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
 table_schema	count(*)
 information_schema	28
-mysql	22
+mysql	24
 create table t1 (i int, j int);
 create trigger trg1 before insert on t1 for each row
 begin

=== modified file 'mysql-test/r/mysql_upgrade.result'
--- a/mysql-test/r/mysql_upgrade.result	2009-01-26 14:20:33 +0000
+++ b/mysql-test/r/mysql_upgrade.result	2009-12-15 02:40:10 +0000
@@ -13,10 +13,12 @@ mysql.help_keyword                      
 mysql.help_relation                                OK
 mysql.help_topic                                   OK
 mysql.host                                         OK
+mysql.mi_info                                      OK
 mysql.ndb_binlog_index                             OK
 mysql.plugin                                       OK
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
+mysql.rli_info                                     OK
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
@@ -45,10 +47,12 @@ mysql.help_keyword                      
 mysql.help_relation                                OK
 mysql.help_topic                                   OK
 mysql.host                                         OK
+mysql.mi_info                                      OK
 mysql.ndb_binlog_index                             OK
 mysql.plugin                                       OK
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
+mysql.rli_info                                     OK
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
@@ -77,10 +81,12 @@ mysql.help_keyword                      
 mysql.help_relation                                OK
 mysql.help_topic                                   OK
 mysql.host                                         OK
+mysql.mi_info                                      OK
 mysql.ndb_binlog_index                             OK
 mysql.plugin                                       OK
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
+mysql.rli_info                                     OK
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
@@ -111,10 +117,12 @@ mysql.help_keyword                      
 mysql.help_relation                                OK
 mysql.help_topic                                   OK
 mysql.host                                         OK
+mysql.mi_info                                      OK
 mysql.ndb_binlog_index                             OK
 mysql.plugin                                       OK
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
+mysql.rli_info                                     OK
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.

=== modified file 'mysql-test/r/mysqlcheck.result'
--- a/mysql-test/r/mysqlcheck.result	2009-07-14 17:08:38 +0000
+++ b/mysql-test/r/mysqlcheck.result	2009-12-15 02:40:10 +0000
@@ -14,10 +14,12 @@ mysql.help_keyword                      
 mysql.help_relation                                OK
 mysql.help_topic                                   OK
 mysql.host                                         OK
+mysql.mi_info                                      OK
 mysql.ndb_binlog_index                             OK
 mysql.plugin                                       OK
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
+mysql.rli_info                                     OK
 mysql.servers                                      OK
 mysql.slow_log
 note     : The storage engine for the table doesn't support optimize
@@ -39,10 +41,12 @@ mysql.help_keyword                      
 mysql.help_relation                                OK
 mysql.help_topic                                   OK
 mysql.host                                         OK
+mysql.mi_info                                      OK
 mysql.ndb_binlog_index                             OK
 mysql.plugin                                       OK
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
+mysql.rli_info                                     OK
 mysql.servers                                      OK
 mysql.slow_log
 note     : The storage engine for the table doesn't support optimize

=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result	2009-03-11 20:30:56 +0000
+++ b/mysql-test/r/system_mysql_db.result	2009-12-15 02:40:10 +0000
@@ -10,10 +10,12 @@ help_keyword
 help_relation
 help_topic
 host
+mi_info
 ndb_binlog_index
 plugin
 proc
 procs_priv
+rli_info
 servers
 slow_log
 tables_priv

=== modified file 'mysql-test/suite/rpl/r/rpl_flushlog_loop.result'
--- a/mysql-test/suite/rpl/r/rpl_flushlog_loop.result	2009-10-01 17:22:44 +0000
+++ b/mysql-test/suite/rpl/r/rpl_flushlog_loop.result	2009-12-15 02:40:10 +0000
@@ -9,6 +9,7 @@ Variable_name	Value
 relay_log	MYSQLD_DATADIR/relay-log
 relay_log_index	
 relay_log_info_file	relay-log.info
+relay_log_info_repository	
 relay_log_purge	ON
 relay_log_recovery	OFF
 relay_log_space_limit	0

=== modified file 'mysql-test/t/system_mysql_db_fix30020.test'
--- a/mysql-test/t/system_mysql_db_fix30020.test	2009-02-02 11:36:03 +0000
+++ b/mysql-test/t/system_mysql_db_fix30020.test	2009-12-15 02:40:10 +0000
@@ -97,7 +97,7 @@ INSERT INTO user VALUES ('localhost','',
 DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv,
 procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc,
 time_zone, time_zone_leap_second, time_zone_name, time_zone_transition,
-time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index;
+time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, mi_info, rli_info;
 
 -- enable_query_log
 

=== modified file 'mysql-test/t/system_mysql_db_fix40123.test'
--- a/mysql-test/t/system_mysql_db_fix40123.test	2007-12-12 17:19:24 +0000
+++ b/mysql-test/t/system_mysql_db_fix40123.test	2009-12-15 02:40:10 +0000
@@ -72,7 +72,7 @@ CREATE TABLE time_zone_leap_second (   T
 -- disable_query_log
 
 # Drop all tables created by this test
-DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index;
+DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, mi_info, rli_info;
 
 -- enable_query_log
 

=== modified file 'mysql-test/t/system_mysql_db_fix50030.test'
--- a/mysql-test/t/system_mysql_db_fix50030.test	2008-08-04 05:04:47 +0000
+++ b/mysql-test/t/system_mysql_db_fix50030.test	2009-12-15 02:40:10 +0000
@@ -78,7 +78,7 @@ INSERT INTO servers VALUES ('test','loca
 -- disable_query_log
 
 # Drop all tables created by this test
-DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index;
+DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, mi_info, rli_info;
 
 -- enable_query_log
 

=== modified file 'mysql-test/t/system_mysql_db_fix50117.test'
--- a/mysql-test/t/system_mysql_db_fix50117.test	2008-08-04 05:04:47 +0000
+++ b/mysql-test/t/system_mysql_db_fix50117.test	2009-12-15 02:40:10 +0000
@@ -97,7 +97,7 @@ CREATE TABLE IF NOT EXISTS ndb_binlog_in
 -- disable_query_log
 
 # Drop all tables created by this test
-DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index;
+DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, mi_info, rli_info;
 
 -- enable_query_log
 

=== modified file 'scripts/mysql_install_db.pl.in'
--- a/scripts/mysql_install_db.pl.in	2007-12-28 00:02:28 +0000
+++ b/scripts/mysql_install_db.pl.in	2009-12-15 02:40:10 +0000
@@ -79,6 +79,11 @@ 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.
+  --engine_rep=engine  The type of the engine where the mysql.mi_info and
+                       mysql.rli_info tables will be created. By default both
+                       tables will be created in the MyIsam engine. However, a
+                       user may choose any available engine. If a crash-safe
+                       slave is desired the engine must be transactional.
 
 All other options are passed to the mysqld program
 
@@ -117,6 +122,7 @@ sub parse_arguments
              "builddir=s",      # FIXME not documented
              "srcdir=s",
              "ldata|datadir=s",
+             "engine_rep=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/
@@ -453,6 +459,29 @@ if ( open(PIPE, "| $mysqld_install_cmd_l
   report_verbose($opt,"OK");
 
   # ----------------------------------------------------------------------
+  # Pipe ALTER TABLE mysql.mi|rli_info to "mysqld --bootstrap"
+  # ----------------------------------------------------------------------
+
+  if ($engine_rep)
+  {
+    report_verbose_wait($opt,"Filling help tables...");
+    if ( open(PIPE, "| $mysqld_install_cmd_line") )
+    {
+      print PIPE "use mysql;\n";
+      print PIPE "ALTER TABLE mysql.mi_info ENGINE= " . $engine_rep . ";\n";
+      print PIPE "ALTER TABLE mysql.rli_info ENGINE= " . $engine_rep . ";\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	2009-01-06 15:08:15 +0000
+++ b/scripts/mysql_install_db.sh	2009-12-15 02:40:10 +0000
@@ -63,6 +63,11 @@ 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.
+  --engine_rep=engine  The type of the engine where the mysql.mi_info and
+                       mysql.rli_info tables will be created. By default both
+                       tables will be created in the MyIsam engine. However, a
+                       user may choose any available engine. If a crash-safe
+                       slave is desired the engine must be transactional.
 
 All other options are passed to the mysqld program
 
@@ -115,6 +120,8 @@ parse_arguments()
       --no-defaults|--defaults-file=*|--defaults-extra-file=*)
         defaults="$arg" ;;
 
+      --engine_rep=*) engine_rep=`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
@@ -422,6 +429,19 @@ else
   exit 1
 fi
 
+if { -n "$engine_rep" }
+then
+  s_echo "Setting engine for mysql.mi_info mysql.rli_info tables..."
+  if { echo "use mysql;"; echo "ALTER TABLE mysql.mi_info ENGINE= $engine_rep;"; echo "ALTER TABLE mysql.rli_info ENGINE= $engine_rep;"; } | $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 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql	2009-05-15 12:57:51 +0000
+++ b/scripts/mysql_system_tables.sql	2009-12-15 02:40:10 +0000
@@ -80,8 +80,11 @@ PREPARE stmt FROM @str;
 EXECUTE stmt;
 DROP PREPARE stmt;
 
-CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode  set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','!
 NOT_USED'
 
+CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode  set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','!
 NOT_USED'
 
 CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
 
+CREATE TABLE IF NOT EXISTS rli_info (master_id TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, rli_master_log_pos TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, rli_relay_log_pos TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, PRIMARY KEY(master_id(128))) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT 'Relay Log Information';
+
+CREATE TABLE IF NOT EXISTS mi_info (master_id TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, mi_master_log_pos TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, mi_host TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_user TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_password TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_port INTEGER UNSIGNED NOT NULL DEFAULT 0, mi_connect_retry INTEGER UNSIGNED NOT NULL DEFAULT 0, mi_ssl BOOLEAN NOT NULL DEFAULT 0, mi_ssl_ca TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_ssl_capath TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_ssl_cert TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_ssl_key TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_ssl_cipher TEXT CHARACTER SET utf8 COLLATE utf8_bin, mi_ssl_verify_servert_cert BOOLEAN NOT NULL DEFAULT 0, mi_heartbeat FLOAT NOT NULL DEFAULT 0.0, mi_ignore_server_ids TEXT CHARACTER SET utf8 COLLATE utf8_bin, PRIMARY KEY(master_id(128))) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT 'Master Information';

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2009-12-11 20:59:37 +0000
+++ b/sql/CMakeLists.txt	2009-12-15 02:40:10 +0000
@@ -76,6 +76,9 @@ SET (SQL_SOURCE
                rpl_info.h rpl_info.cc
                rpl_rli.h rpl_rli.cc rpl_mi.h rpl_mi.cc
                rpl_rli_file.h rpl_rli_file.cc rpl_mi_file.h rpl_mi_file.cc
+               rpl_info_table.h rpl_info_table.cc
+               rpl_info_factory.h rpl_info_factory.cc
+               rpl_rli_table.h rpl_rli_table.cc rpl_mi_table.h rpl_mi_table.cc
                sql_servers.cc
                sql_connect.cc scheduler.cc 
                sql_profile.cc event_parse_data.cc

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2009-12-11 20:59:37 +0000
+++ b/sql/Makefile.am	2009-12-15 02:40:10 +0000
@@ -63,6 +63,8 @@ noinst_HEADERS =	item.h item_func.h item
 			rpl_reporting.h \
 			log.h sql_show.h rpl_info.h \
 			rpl_rli.h rpl_rli_file.h rpl_mi.h rpl_mi_file.h \
+			rpl_info_factory.h rpl_info_table.h \
+                        rpl_mi_table.h rpl_rli_table.h \
 			sql_select.h structs.h table.h sql_udf.h hash_filo.h \
 			lex.h lex_symbol.h sql_acl.h sql_crypt.h  \
 			sql_repl.h slave.h rpl_filter.h rpl_injector.h \
@@ -112,7 +114,8 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \
 			rpl_utility.cc rpl_injector.cc rpl_rli.cc rpl_mi.cc \
 			rpl_info.cc rpl_rli_file.cc rpl_mi_file.c \
-			rpl_reporting.cc \
+			rpl_reporting.cc rpl_info_table.cc rpl_mi_table.cc \
+			rpl_info_factory.cc rpl_rli_table.cc \
                         sql_union.cc sql_derived.cc \
 			sql_client.cc \
 			repl_failsafe.h repl_failsafe.cc \

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2009-12-11 20:59:37 +0000
+++ b/sql/log.cc	2009-12-15 02:40:10 +0000
@@ -5818,6 +5818,9 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_
   Xid_log_event xle(thd, xid);
   binlog_cache_mngr *cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+  DBUG_EXECUTE_IF("crash_safe_slave", abort(););
+
   /*
     We always commit the entire transaction when writing an XID. Also
     note that the return value is inverted.

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2009-11-10 18:45:15 +0000
+++ b/sql/mysql_priv.h	2009-12-15 02:40:10 +0000
@@ -1875,6 +1875,10 @@ extern ulong opt_tc_log_size, tc_log_max
 extern ulong tc_log_page_waits;
 extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
 extern my_bool relay_log_recovery;
+extern ulong opt_mi_repository_id;
+extern const char *opt_mi_repository;
+extern ulong opt_rli_repository_id;
+extern const char *opt_rli_repository;
 extern uint test_flags,select_errors,ha_open_options;
 extern uint protocol_version, mysqld_port, dropping_tables;
 extern uint delay_key_write_options;

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2009-12-11 20:59:37 +0000
+++ b/sql/mysqld.cc	2009-12-15 02:40:10 +0000
@@ -510,6 +510,18 @@ TYPELIB binlog_format_typelib=
     binlog_format_names, NULL };
 ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC;
 const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id];
+const char *mi_repository_names[]= {"FILE", "TABLE", NullS};
+TYPELIB mi_repository_typelib=
+  { array_elements(mi_repository_names) - 1, "",
+    mi_repository_names, NULL };
+ulong opt_mi_repository_id= (ulong) MI_REPOSITORY_UNSPEC;
+const char *opt_mi_repository= mi_repository_names[opt_mi_repository_id];
+const char *rli_repository_names[]= {"FILE", "TABLE", NullS};
+TYPELIB rli_repository_typelib=
+  { array_elements(rli_repository_names) - 1, "",
+    rli_repository_names, NULL };
+ulong opt_rli_repository_id= (ulong) RLI_REPOSITORY_UNSPEC;
+const char *opt_rli_repository= rli_repository_names[opt_rli_repository_id];
 #ifdef HAVE_INITGROUPS
 static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */
 #endif
@@ -5575,6 +5587,8 @@ enum options_mysqld
   OPT_REPLICATE_IGNORE_DB,     OPT_LOG_SLAVE_UPDATES,
   OPT_BINLOG_DO_DB,            OPT_BINLOG_IGNORE_DB,
   OPT_BINLOG_FORMAT,
+  OPT_MI_REPOSITORY,
+  OPT_RLI_REPOSITORY,
 #ifndef DBUG_OFF
   OPT_BINLOG_SHOW_XID,
 #endif
@@ -5780,6 +5794,14 @@ struct my_option my_long_options[] =
 #endif
    ,(uchar**) &opt_binlog_format, (uchar**) &opt_binlog_format,
    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"master_info_repository", OPT_MI_REPOSITORY,
+   "Tell the slave how the position information should be stored: either file or table. "
+   ,(uchar**) &opt_mi_repository, (uchar**) &opt_mi_repository,
+   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"relay_log_info_repository", OPT_RLI_REPOSITORY,
+   "Tell the slave how the position information should be stored: either file or table. "
+   ,(uchar**) &opt_rli_repository, (uchar**) &opt_rli_repository,
+   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"binlog-do-db", OPT_BINLOG_DO_DB,
    "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -8086,6 +8108,20 @@ mysqld_get_one_option(int optid,
     global_system_variables.binlog_format= opt_binlog_format_id= id - 1;
     break;
   }
+  case OPT_MI_REPOSITORY:
+  {
+    int id;
+    id= find_type_or_exit(argument, &mi_repository_typelib, opt->name);
+    opt_mi_repository_id= id - 1;
+    break;
+  }
+  case OPT_RLI_REPOSITORY:
+  {
+    int id;
+    id= find_type_or_exit(argument, &rli_repository_typelib, opt->name);
+    opt_rli_repository_id= id - 1;
+    break;
+  }
   case (int)OPT_BINLOG_DO_DB:
   {
     binlog_filter->add_do_db(argument);

=== added file 'sql/rpl_info_factory.cc'
--- a/sql/rpl_info_factory.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_factory.cc	2009-12-15 02:40:10 +0000
@@ -0,0 +1,169 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <my_global.h>
+#include "mysql_priv.h"
+#include "rpl_info_factory.h"
+#include "rpl_mi_file.h"
+#include "rpl_rli_file.h"
+#include "rpl_mi_table.h"
+#include "rpl_rli_table.h"
+
+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");
+
+  bool error= Rpl_info_factory::create_mi(mi_option, mi) ||
+         Rpl_info_factory::create_rli(rli_option, relay_log_recovery, rli);
+
+  DBUG_RETURN(error); 
+}
+
+bool Rpl_info_factory::create_mi(uint mi_option, Master_info **mi)
+{
+  bool error= TRUE;
+  Master_info* mi_file= NULL;
+  Master_info* mi_table= NULL;
+
+  DBUG_ENTER("Rpl_info_factory::Rpl_info_factory");
+
+  mi_file= new Master_info_file(master_info_file);
+  if (!mi_file)
+  {
+    sql_print_error("Failed to allocate memory for the master info "
+                    "structure");
+    goto err;
+  }
+
+  mi_table= new Master_info_table();
+  if (!mi_table)
+  {
+    sql_print_error("Failed to allocate memory for the master info "
+                    "structure");
+    goto err;
+  }
+
+  if (mi_option == MI_REPOSITORY_FILE ||
+      mi_option == MI_REPOSITORY_UNSPEC)
+  {
+    if (!mi_table->check())
+    {
+      sql_print_error("We cannot use a file as repository to store master "
+                      "info positions because a table is active.");
+      goto err;
+    }
+
+    *mi= mi_file;
+    delete mi_table;
+  }
+  else if (mi_option == MI_REPOSITORY_TABLE)
+  {
+    if (!mi_file->check())
+    {
+      sql_print_error("We cannot use a table as repository to store master "
+                      "info positions because a file is active.");
+      goto err;
+    }
+
+    *mi= mi_table;
+    delete mi_file;
+  }
+  error= FALSE;
+
+err:
+  DBUG_RETURN(error);
+}
+
+bool Rpl_info_factory::create_rli(uint rli_option, bool is_slave_recovery,
+                                  Relay_log_info **rli)
+{
+  bool error= TRUE;
+  Relay_log_info* rli_file= NULL;
+  Relay_log_info* rli_table= NULL;
+
+  DBUG_ENTER("Rpl_info_factory::create_rli");
+
+  rli_file= new Relay_log_info_file(is_slave_recovery,
+                                    relay_log_info_file);
+  if (!rli_file)
+  {
+    sql_print_error("Failed to allocate memory for the relay log info "
+                    "structure");
+    goto err;
+  }
+
+  rli_table= new Relay_log_info_table(is_slave_recovery);
+  if (!rli_table)
+  {
+    sql_print_error("Failed to allocate memory for the relay log info "
+                    "structure");
+    goto err;
+  }
+
+  if (rli_option == RLI_REPOSITORY_FILE ||
+      rli_option == RLI_REPOSITORY_UNSPEC)
+  {
+    if (!rli_table->check())
+    {
+      sql_print_error("We cannot use a file as repository to store relay log "
+                      "info positions because a table is active");
+      goto err;
+    }
+
+    *rli= rli_file;
+    delete rli_table;
+  }
+  else if (rli_option == RLI_REPOSITORY_TABLE)
+  {
+    if (!rli_file->check())
+    {
+      sql_print_error("We cannot use a table as repository to store relay log "
+                      "info positions because a file is active.");
+      goto err;
+    }
+
+    *rli= rli_table;
+    delete rli_file;
+  }
+  error= FALSE;
+
+err:
+  DBUG_RETURN(error);
+}
+
+bool Rpl_info_factory::create_file_rli(bool is_slave_recovery,
+                                       const char* relay_log,
+                                       Relay_log_info **rli)
+{
+  bool error= TRUE;
+  Relay_log_info* rli_file= NULL;
+
+  DBUG_ENTER("Rpl_info_factory::create_file_rli");
+
+  rli_file= new Relay_log_info_file(is_slave_recovery,
+                                    relay_log);
+  if (!rli_file)
+  {
+    sql_print_error("Failed to allocate memory for the relay log info "
+                    "structure");
+    goto err;
+  }
+  *rli= rli_file;
+  error= FALSE;
+
+err:
+  DBUG_RETURN(error);
+}

=== added file 'sql/rpl_info_factory.h'
--- a/sql/rpl_info_factory.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_factory.h	2009-12-15 02:40:10 +0000
@@ -0,0 +1,36 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_INFO_FACTORY_H
+#define RPL_INFO_FACTORY_H
+
+#include "rpl_mi.h"
+#include "rpl_rli.h"
+
+class Rpl_info_factory
+{
+  public:
+
+  bool static create(uint mi_option, Master_info **mi,
+                     uint rli_option, Relay_log_info **rli);
+  bool static create_mi(uint rli_option, Master_info **rli);
+  bool static create_rli(uint rli_option, bool is_slave_recovery,
+                         Relay_log_info **rli);
+  bool static create_file_rli(bool is_slave_recovery, const char* relay_log,
+                              Relay_log_info **rli);
+};
+#endif
+
+

=== added file 'sql/rpl_info_table.cc'
--- a/sql/rpl_info_table.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_table.cc	2009-12-15 02:40:10 +0000
@@ -0,0 +1,248 @@
+/* Copyright 2004-2009 MySQL AB, 2008 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include "mysql_priv.h"
+#include "rpl_info_table.h"
+#include "rpl_utility.h"
+#include "handler.h"
+
+#ifdef HAVE_REPLICATION
+Rpl_info_table::Rpl_info_table()
+{
+  init_sql_alloc(&mem_root, 256, 512);
+}
+
+Rpl_info_table::~Rpl_info_table()
+{
+  free_root(&mem_root, MYF(0));
+}
+
+/**
+  Opens and locks a table.
+
+  It's assumed that the caller knows what they are doing:
+  - whether it was necessary to reset-and-backup the open tables state
+  - whether the requested lock does not lead to a deadlock
+  - whether this open mode would work under LOCK TABLES, or inside a
+  stored function or trigger.
+
+  Note that if the table can't be locked successfully this operation will
+  close it. Therefore it provides guarantee that it either opens and locks
+  table or fails without leaving any tables open.
+
+  @param[in]  thd Thread requesting to open the table
+  @param[in]  dbstr Database
+  @param[in]  tbstr Table
+  @param[in]  max_num_field Maximum number of fields
+  @param[in]  lock_type  How to lock the table
+  @param[out] table  We will store the open table here
+  @param[out] backup Save the lock info. here
+
+  @retval TRUE open and lock failed - an error message is pushed into the
+                                      stack
+  @retval FALSE success
+*/
+bool Rpl_info_table::open_table(THD *thd,
+                                const char *dbstr,
+                                const char *tbstr,
+                                uint max_num_field,
+                                enum thr_lock_type lock_type,
+                                TABLE **table,
+                                Open_tables_state *backup)
+{
+  TABLE_LIST tables;
+  DBUG_ENTER("Master_info_table::open_table");
+
+  thd->reset_n_backup_open_tables_state(backup);
+
+  tables.init_one_table(dbstr, tbstr, lock_type);
+
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    close_thread_tables(thd);
+    my_error(ER_NO_SUCH_TABLE, MYF(0), dbstr, tbstr);
+    DBUG_RETURN(TRUE);
+  }
+
+  if (tables.table->s->fields < max_num_field)
+  {
+    /*
+      Safety: this can only happen if someone started the server and then
+      altered the table.
+    */
+    my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, MYF(0), tables.table->alias,
+             max_num_field, tables.table->s->fields);
+    close_thread_tables(thd);
+    DBUG_RETURN(TRUE);
+  }
+
+  *table= tables.table;
+  tables.table->use_all_columns();
+  DBUG_RETURN(FALSE);
+}
+
+bool Rpl_info_table::close_table(THD *thd, TABLE* table,
+                                 Open_tables_state *backup)
+{
+  DBUG_ENTER("Rpl_info_table::close_table");
+
+  if (table)
+  {
+    close_thread_tables(thd);
+    thd->restore_backup_open_tables_state(backup);
+  }
+
+  DBUG_RETURN(FALSE);
+}
+
+/**
+  Positions the internal pointer of `table` to the place where (id)
+  is stored.
+
+  In case search succeeded, the table cursor points at the found row.
+
+  @param[in]      idx    Index field
+  @param[in]      id     Server id
+  @param[in,out]  table  Table
+
+
+  @retval FALSE  an entry with such id key exists
+  @retval  TRUE  no entry found or an error occured.
+*/
+bool Rpl_info_table::find_info_id(uint idx, LEX_STRING id, TABLE *table)
+{
+  uchar key[MAX_KEY_LENGTH];
+  DBUG_ENTER("Relay_log_info_table::find_info_id");
+  DBUG_PRINT("enter", ("name: %.*s", (int) id.length, id.str));
+
+  /*
+    Create key to find row. We have to use field->store() to be able to
+    handle VARCHAR and CHAR fields.
+  */
+  if (id.length > table->field[idx]->field_length)
+    DBUG_RETURN(TRUE);
+
+  table->field[idx]->store(id.str, id.length, &my_charset_bin);
+
+  if (!table->key_info ||
+      DBUG_EVALUATE_IF("fault_injection_Rpl_info_table::find_id_info", 1, 0))
+    DBUG_RETURN(TRUE);
+  
+  key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
+
+  if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
+                                      HA_READ_KEY_EXACT))
+  {
+    DBUG_PRINT("info", ("Row not found"));
+    DBUG_RETURN(TRUE);
+  }
+
+  DBUG_PRINT("info", ("Row found!"));
+  DBUG_RETURN(FALSE);
+}
+
+bool Rpl_info_table::load_info_fields(uint max_num_field, Field **fields, ...)
+{
+  va_list args;
+  uint field_idx;
+  LEX_STRING *field_value;
+
+  DBUG_ENTER("Rpl_info_table::load_info_fields");
+
+  va_start(args, fields);
+  field_idx= (uint) va_arg(args, int);
+  while (field_idx < max_num_field)
+  {
+    field_value= va_arg(args, LEX_STRING *);
+    field_value->str= get_field(&mem_root, fields[field_idx]);
+    field_value->length= field_value->str ? strlen(field_value->str) : 0;
+    field_idx= (uint) va_arg(args, int);
+  }
+  va_end(args);
+
+  DBUG_RETURN(FALSE);
+}
+
+bool Rpl_info_table::store_info_fields(uint max_num_field, Field **fields, ...)
+{
+  va_list args;
+  uint field_idx;
+  LEX_STRING *field_value;
+
+  DBUG_ENTER("Rpl_info_table::load_info_fields");
+
+  va_start(args, fields);
+  field_idx= (uint) va_arg(args, int);
+  while (field_idx < max_num_field)
+  {
+    field_value= va_arg(args, LEX_STRING *);
+    fields[field_idx]->set_notnull();
+    if (fields[field_idx]->store(field_value->str,
+                                 field_value->length,
+                                 &my_charset_bin))
+    {
+      my_error(ER_INFO_DATA_TOO_LONG, MYF(0),
+               fields[field_idx]->field_name);
+      DBUG_RETURN(TRUE);
+    }
+    field_idx= (uint) va_arg(args, int);
+  }
+  va_end(args);
+
+  DBUG_RETURN(FALSE);
+}
+
+THD *Rpl_info_table::create_fake_thd()
+{
+  THD *thd= NULL;
+  saved_current_thd= current_thd;
+
+ if (!current_thd)
+  {
+    thd= new THD;
+    thd->thread_stack= (char*) &thd;
+    thd->store_globals();
+    lex_start(thd);
+  }
+  else
+  {
+    thd= current_thd;
+  }
+
+ return(thd);
+}
+
+bool Rpl_info_table::drop_fake_thd(THD *thd, bool error)
+{
+  DBUG_ENTER("Rpl_info::drop_fake_thd");
+
+  if (error)
+    ha_rollback_trans(thd, FALSE);
+  else
+    ha_commit_trans(thd, FALSE);
+
+  if (saved_current_thd != current_thd)
+  {
+    if (error)
+      ha_rollback_trans(thd, TRUE);
+    else
+      ha_commit_trans(thd, TRUE);
+    delete thd;
+    my_pthread_setspecific_ptr(THR_THD,  NULL);
+  }
+
+  DBUG_RETURN(FALSE);
+}
+#endif /* HAVE_REPLICATION */

=== added file 'sql/rpl_info_table.h'
--- a/sql/rpl_info_table.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_table.h	2009-12-15 02:40:10 +0000
@@ -0,0 +1,45 @@
+/* Copyright 2004-2009 MySQL AB, 2008 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+#ifndef RPL_INFO_TABLE_H
+#define RPL_INFO_TABLE_H
+
+#define NULL_TABLE_INFO "0"
+
+class Rpl_info_table
+{
+public:
+  Rpl_info_table();
+  virtual ~Rpl_info_table();
+
+protected:
+  THD *saved_current_thd;
+  bool open_table(THD* thd, const char *dbstr, const char *tbstr,
+                  uint max_num_field, enum thr_lock_type lock_type,
+                  TABLE** table, Open_tables_state* backup);
+  bool close_table(THD* thd, TABLE* table, Open_tables_state* backup);
+  bool find_info_id(uint idx, LEX_STRING, TABLE*);
+  bool load_info_fields(uint max_num_field, Field **fields, ...);
+  bool store_info_fields(uint max_num_field, Field **fields, ...);
+
+  THD *create_fake_thd();
+  bool drop_fake_thd(THD* thd, bool error);
+
+private:
+  MEM_ROOT mem_root;
+
+  Rpl_info_table& operator=(const Rpl_info_table& info);
+  Rpl_info_table(const Rpl_info_table& info);
+};
+#endif /* RPL_INFO_TABLE_H */

=== added file 'sql/rpl_mi_table.cc'
--- a/sql/rpl_mi_table.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_mi_table.cc	2009-12-15 02:40:10 +0000
@@ -0,0 +1,514 @@
+/* Copyright 2004-2009 MySQL AB, 2008 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include "mysql_priv.h"
+#include "rpl_mi_table.h"
+#include "rpl_utility.h"
+
+#ifdef HAVE_REPLICATION
+static
+const TABLE_FIELD_W_TYPE master_info_table_fields[MI_FIELD_COUNT] =
+{
+  {
+    { C_STRING_WITH_LEN("master_id") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_master_log_pos") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_host") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_user") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_password") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_port") },
+    { C_STRING_WITH_LEN("integer") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_connect_retry") },
+    { C_STRING_WITH_LEN("integer") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl") },
+    { C_STRING_WITH_LEN("bool") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl_ca") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl_capath") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl_cert") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl_key") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl_cipher") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ssl_verify_server_cert") },
+    { C_STRING_WITH_LEN("bool") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_heartbeat") },
+    { C_STRING_WITH_LEN("float") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("mi_ignore_server_ids") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  }
+};
+
+int Master_info_table::do_init_info()
+{
+  int error= 1;
+  TABLE *table= NULL;
+  ulong saved_mode;
+  bool saved_format= FALSE;
+  Open_tables_state backup;
+  struct_store_mi store_mi;
+  store_mi.ignore_server_ids_field= NULL;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Master_info_table::do_init_info");
+
+  saved_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
+  saved_format= thd->is_current_stmt_binlog_format_row();
+  thd->clear_current_stmt_binlog_format_row();
+
+  if (open_table(thd, MI_SCHEMA, MI_TABLE, MI_FIELD_COUNT, TL_WRITE,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (!find_info_id(MI_FIELD_ID, id_field_lex, table))
+  {
+    if (!read_info(table, &store_mi))
+    {
+#ifndef HAVE_OPENSSL
+      if (ssl)
+        sql_print_warning("SSL information in the master info file "
+                          "('%s') are ignored because this MySQL slave was "
+                          "compiled without SSL support.", fname);
+#endif /* HAVE_OPENSSL */
+    }
+    else
+      goto end;
+  }
+  else
+  {
+    init_master_log_pos(this);
+
+    restore_record(table, s->default_values);
+
+    if (write_info(table, &store_mi))
+      goto end;
+
+    if (table->file->ha_write_row(table->record[0]))
+    {
+      ha_rollback_trans(thd, FALSE);
+      table->file->print_error(error, MYF(0));
+      goto end;
+    }
+  }
+  ha_commit_trans(thd, FALSE);
+  error= 0;
+
+end:
+  if (store_mi.ignore_server_ids_field)
+    my_free((void *)const_cast<const char*>(store_mi.ignore_server_ids_field),
+            MYF(0));
+  if (saved_format)
+    thd->set_current_stmt_binlog_format_row();
+  thd->variables.sql_mode= saved_mode;
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+int Master_info_table::do_flush_info(const bool force)
+{
+  int error= 1;
+  TABLE *table= NULL;
+  ulong saved_mode;
+  bool saved_format= FALSE;
+  Open_tables_state backup;
+  struct_store_mi store_mi;
+  store_mi.ignore_server_ids_field= NULL;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Master_info_table::do_flush_info");
+
+  if (thd->lex->requires_prelocking())
+    DBUG_RETURN(0);
+
+  saved_mode= thd->variables.sql_mode;
+  saved_format= thd->is_current_stmt_binlog_format_row();
+  thd->clear_current_stmt_binlog_format_row();
+
+  if (open_table(thd, MI_SCHEMA, MI_TABLE, MI_FIELD_COUNT, TL_WRITE,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (find_info_id(MI_FIELD_ID, id_field_lex, table))
+  {
+    my_error(ER_NO_SUCH_KEY_VALUE, MYF(0), id_field_lex.str,
+             MI_SCHEMA, MI_TABLE);
+    goto end;
+  }
+
+  store_record(table, record[1]);
+  /* 
+    Don't update create on row update.
+  */
+  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
+  if (write_info(table, &store_mi))
+    goto end;
+
+  if ((error= table->file->ha_update_row(table->record[1], table->record[0])) &&
+      error != HA_ERR_RECORD_IS_THE_SAME)
+  {
+    ha_rollback_trans(thd, FALSE);
+    table->file->print_error(error, MYF(0));
+    goto end;
+  }
+  ha_commit_trans(thd, FALSE);
+  error= 0;
+
+end:
+  if (store_mi.ignore_server_ids_field)
+    my_free((void *)const_cast<const char*>(store_mi.ignore_server_ids_field),
+            MYF(0));
+  if (saved_format)
+    thd->set_current_stmt_binlog_format_row();
+  thd->variables.sql_mode= saved_mode;
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+bool Master_info_table::read_info(TABLE *table, ptr_struct_store_mi store_mi)
+{
+  DBUG_ENTER("Master_info_table::read_info");
+
+  if (load_info_fields(MI_FIELD_COUNT, table->field,
+                       MI_FIELD_MASTER_LOG_POS, &store_mi->master_field_lex,
+                       MI_FIELD_HOST, &store_mi->host_field_lex,
+                       MI_FIELD_USER, &store_mi->user_field_lex,
+                       MI_FIELD_PASSWORD, &store_mi->password_field_lex,
+                       MI_FIELD_PORT, &store_mi->port_field_lex,
+                       MI_FIELD_CONNECT_RETRY, &store_mi->connect_retry_field_lex,
+                       MI_FIELD_SSL, &store_mi->ssl_field_lex,
+                       MI_FIELD_SSL_CA, &store_mi->ssl_ca_field_lex,
+                       MI_FIELD_SSL_CAPATH, &store_mi->ssl_capath_field_lex,
+                       MI_FIELD_SSL_CERT, &store_mi->ssl_cert_field_lex,
+                       MI_FIELD_SSL_CIPHER, &store_mi->ssl_cipher_field_lex,
+                       MI_FIELD_SSL_KEY, &store_mi->ssl_key_field_lex,
+                       MI_FIELD_SSL_VERIFY_SERVER_CERT, &store_mi->ssl_verify_server_cert_field_lex,
+                       MI_FIELD_HEARTBEAT, &store_mi->heartbeat_field_lex,
+                       MI_FIELD_IGNORE_SERVER_IDS, &store_mi->ignore_server_ids_field_lex,
+                       MI_FIELD_COUNT))
+    DBUG_RETURN(TRUE);
+  
+  char *pos= index(store_mi->master_field_lex.str, ':');
+  *pos++= 0;
+  strmov(master_log_name, store_mi->master_field_lex.str);
+  master_log_pos= atoll(pos);
+  strmov(host, 
+         (store_mi->host_field_lex.length ? store_mi->host_field_lex.str :
+         (master_host ? master_host : NULL_TABLE_INFO)));
+  strmov(user,
+         (store_mi->user_field_lex.length ? store_mi->user_field_lex.str :
+         (master_user ? master_user : NULL_TABLE_INFO)));
+  strmov(password,
+         (store_mi->password_field_lex.length ? store_mi->password_field_lex.str :
+         (master_password ? master_password : NULL_TABLE_INFO)));
+  port= (uint) (store_mi->port_field_lex.length ?
+                atoi(store_mi->port_field_lex.str) : master_port);
+  connect_retry= uint (store_mi->connect_retry_field_lex.length ?
+                       atoi(store_mi->connect_retry_field_lex.str) :
+                       master_connect_retry);
+  ssl= (my_bool) (store_mi->ssl_field_lex.length ?
+                  atoi(store_mi->ssl_field_lex.str) : master_ssl);
+  ssl= (my_bool) (store_mi->ssl_field_lex.length ?
+                  atoi(store_mi->ssl_field_lex.str) : master_ssl);
+  strmov(ssl_ca,
+         (store_mi->ssl_ca_field_lex.length ? store_mi->ssl_ca_field_lex.str :
+         (master_ssl_ca ? master_ssl_ca : NULL_TABLE_INFO)));
+  strmov(ssl_capath,
+         (store_mi->ssl_capath_field_lex.length ? store_mi->ssl_capath_field_lex.str :
+         (master_ssl_capath ? master_ssl_capath: NULL_TABLE_INFO)));
+  strmov(ssl_cert,
+         (store_mi->ssl_cert_field_lex.length ? store_mi->ssl_cert_field_lex.str :
+         (master_ssl_cert ? master_ssl_cert : NULL_TABLE_INFO)));
+  strmov(ssl_cipher,
+         (store_mi->ssl_cipher_field_lex.length ? store_mi->ssl_cipher_field_lex.str :
+         (master_ssl_cipher ? master_ssl_cipher : NULL_TABLE_INFO)));
+  strmov(ssl_key,
+         (store_mi->ssl_key_field_lex.length ? store_mi->ssl_key_field_lex.str :
+         (master_ssl_key ? master_ssl_key : NULL_TABLE_INFO)));
+  ssl_verify_server_cert= (my_bool) (store_mi->ssl_verify_server_cert_field_lex.length ?
+                                     atoi (store_mi->ssl_verify_server_cert_field_lex.str)
+                                     : 0);
+  if (store_mi->heartbeat_field_lex.length)
+    sscanf(store_mi->heartbeat_field_lex.str, "%f", &heartbeat_period);
+  else
+    heartbeat_period= 0.0;
+
+  unpack_ignore_server_ids(store_mi->ignore_server_ids_field_lex.str);
+
+  DBUG_RETURN(FALSE);
+}
+
+bool Master_info_table::write_info(TABLE *table, ptr_struct_store_mi store_mi)
+{
+  char *pos= NULL;
+
+  DBUG_ENTER("Master_info_table::write_info");
+
+  longlong2str(server_id, store_mi->id_field, 10);
+  store_mi->id_field_lex.str= store_mi->id_field;
+  store_mi->id_field_lex.length= strlen(store_mi->id_field);
+
+  pos= strmov(store_mi->master_field, master_log_name);
+  *pos++= ':';
+  pos= longlong2str(master_log_pos, pos, 10);
+  store_mi->master_field_lex.str= store_mi->master_field;
+  store_mi->master_field_lex.length= strlen(store_mi->master_field);
+
+  store_mi->host_field_lex.str= host;
+  store_mi->host_field_lex.length= strlen(host);
+
+  store_mi->user_field_lex.str= user;
+  store_mi->user_field_lex.length= strlen(user);
+
+  store_mi->password_field_lex.str= password;
+  store_mi->password_field_lex.length= strlen(password);
+
+  longlong2str(port, store_mi->port_field, 10);
+  store_mi->port_field_lex.str= store_mi->port_field;
+  store_mi->port_field_lex.length= strlen(store_mi->port_field);
+
+  longlong2str(connect_retry, store_mi->connect_retry_field, 10);
+  store_mi->connect_retry_field_lex.str= store_mi->connect_retry_field;
+  store_mi->connect_retry_field_lex.length= strlen(store_mi->connect_retry_field);
+
+  longlong2str(ssl, store_mi->ssl_field, 10);
+  store_mi->ssl_field_lex.str= store_mi->ssl_field;
+  store_mi->ssl_field_lex.length= strlen(store_mi->ssl_field);
+
+  store_mi->ssl_ca_field_lex.str= ssl_ca;
+  store_mi->ssl_ca_field_lex.length= strlen(ssl_ca);
+
+  store_mi->ssl_capath_field_lex.str= ssl_capath;
+  store_mi->ssl_capath_field_lex.length= strlen(ssl_capath);
+
+  store_mi->ssl_cert_field_lex.str= ssl_cert;
+  store_mi->ssl_cert_field_lex.length= strlen(ssl_cert);
+
+  store_mi->ssl_cipher_field_lex.str= ssl_cipher;
+  store_mi->ssl_cipher_field_lex.length= strlen(ssl_cipher);
+
+  store_mi->ssl_key_field_lex.str= ssl_key;
+  store_mi->ssl_key_field_lex.length= strlen(ssl_key);
+
+  longlong2str(ssl_verify_server_cert, store_mi->ssl_verify_server_cert_field,
+               10);
+  store_mi->ssl_verify_server_cert_field_lex.str=
+    store_mi->ssl_verify_server_cert_field;
+  store_mi->ssl_verify_server_cert_field_lex.length=
+    strlen(store_mi->ssl_verify_server_cert_field);
+
+  my_sprintf(store_mi->heartbeat_field, (store_mi->heartbeat_field, "%.3f",
+             heartbeat_period));
+  store_mi->heartbeat_field_lex.str= store_mi->heartbeat_field;
+  store_mi->heartbeat_field_lex.length= strlen(store_mi->heartbeat_field);
+
+  store_mi->ignore_server_ids_field= (char *)
+    const_cast<const char*>(pack_ignore_server_ids());
+  store_mi->ignore_server_ids_field_lex.str=
+    (char *)const_cast<const char*>(store_mi->ignore_server_ids_field);
+  store_mi->ignore_server_ids_field_lex.length=
+    strlen(store_mi->ignore_server_ids_field);
+
+  if (store_info_fields(MI_FIELD_COUNT, table->field,
+                        MI_FIELD_ID, &store_mi->id_field_lex,
+                        MI_FIELD_MASTER_LOG_POS, &store_mi->master_field_lex,
+                        MI_FIELD_HOST, &store_mi->host_field_lex,
+                        MI_FIELD_USER, &store_mi->user_field_lex,
+                        MI_FIELD_PASSWORD, &store_mi->password_field_lex,
+                        MI_FIELD_PORT, &store_mi->port_field_lex,
+                        MI_FIELD_CONNECT_RETRY, &store_mi->connect_retry_field_lex,
+                        MI_FIELD_SSL, &store_mi->ssl_field_lex,
+                        MI_FIELD_SSL_CA, &store_mi->ssl_ca_field_lex,
+                        MI_FIELD_SSL_CAPATH, &store_mi->ssl_capath_field_lex,
+                        MI_FIELD_SSL_CERT, &store_mi->ssl_cert_field_lex,
+                        MI_FIELD_SSL_CIPHER, &store_mi->ssl_cipher_field_lex,
+                        MI_FIELD_SSL_KEY, &store_mi->ssl_key_field_lex,
+                        MI_FIELD_SSL_VERIFY_SERVER_CERT, &store_mi->ssl_verify_server_cert_field_lex,
+                        MI_FIELD_HEARTBEAT, &store_mi->heartbeat_field_lex,
+                        MI_FIELD_IGNORE_SERVER_IDS, &store_mi->ignore_server_ids_field_lex,
+                        MI_FIELD_COUNT))
+    DBUG_RETURN(TRUE);
+
+  DBUG_RETURN(FALSE);
+}
+
+int Master_info_table::do_reset_info()
+{
+  int error= 1;
+  TABLE *table= NULL;
+  ulong saved_mode;
+  bool saved_format= FALSE;
+  Open_tables_state backup;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Master_info_table::do_reset_info");
+
+  saved_mode= thd->variables.sql_mode;
+  saved_format= thd->is_current_stmt_binlog_format_row();
+  thd->clear_current_stmt_binlog_format_row();
+
+  if (open_table(thd, MI_SCHEMA, MI_TABLE, MI_FIELD_COUNT, TL_WRITE,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (!find_info_id(MI_FIELD_ID, id_field_lex, table))
+  {
+    if ((error= table->file->ha_delete_row(table->record[0])))
+    {
+      ha_rollback_trans(thd, FALSE);
+      table->file->print_error(error, MYF(0));
+      goto end;
+    }
+  }
+  ha_commit_trans(thd, FALSE);
+  error= 0;
+
+end:
+  if (saved_format) 
+    thd->set_current_stmt_binlog_format_row();
+  thd->variables.sql_mode= saved_mode;
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+int Master_info_table::do_check()
+{
+  int error= 1;
+  TABLE *table= NULL;
+  Open_tables_state backup;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Master_info_table::do_check_info");
+
+  if (open_table(thd, MI_SCHEMA, MI_TABLE, MI_FIELD_COUNT, TL_READ,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (find_info_id(MI_FIELD_ID, id_field_lex, table))
+  {
+    my_error(ER_NO_SUCH_KEY_VALUE, MYF(0), id_field_lex.str,
+             MI_SCHEMA, MI_TABLE);
+    goto end;
+  }
+
+  error= 0;
+
+end:
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+int Master_info_table::do_prepare_info()
+{
+  /*
+    This should not be called if the the master.info is
+    stored in a table.
+  */
+  DBUG_ASSERT(0);
+
+  return(0);
+}
+
+void Master_info_table::do_end_info()
+{
+  return;
+}
+
+#endif /* HAVE_REPLICATION */

=== added file 'sql/rpl_mi_table.h'
--- a/sql/rpl_mi_table.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_mi_table.h	2009-12-15 02:40:10 +0000
@@ -0,0 +1,97 @@
+/* Copyright 2004-2009 MySQL AB, 2008 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_MI_TABLE_H
+#define RPL_MI_TABLE_H
+
+#include "rpl_mi.h"
+#include "rpl_info_table.h"
+
+#define MI_SCHEMA "mysql"
+#define MI_TABLE "mi_info"
+
+enum enum_master_info_table_field
+{
+  MI_FIELD_ID = 0,
+  MI_FIELD_MASTER_LOG_POS,
+  MI_FIELD_HOST,
+  MI_FIELD_USER,
+  MI_FIELD_PASSWORD,
+  MI_FIELD_PORT,
+  MI_FIELD_CONNECT_RETRY,
+  MI_FIELD_SSL,
+  MI_FIELD_SSL_CA,
+  MI_FIELD_SSL_CAPATH,
+  MI_FIELD_SSL_CERT,
+  MI_FIELD_SSL_KEY,
+  MI_FIELD_SSL_CIPHER,
+  MI_FIELD_SSL_VERIFY_SERVER_CERT,
+  MI_FIELD_HEARTBEAT,
+  MI_FIELD_IGNORE_SERVER_IDS,
+  MI_FIELD_COUNT
+};
+
+struct store_master_info
+{
+  char id_field[FN_REFLEN];
+  char master_field[FN_REFLEN];
+  char port_field[FN_REFLEN];
+  char connect_retry_field[FN_REFLEN];
+  char ssl_field[FN_REFLEN];
+  char ssl_verify_server_cert_field[FN_REFLEN];
+  char heartbeat_field[FN_REFLEN];
+  char *ignore_server_ids_field;
+
+  LEX_STRING id_field_lex;
+  LEX_STRING master_field_lex;
+  LEX_STRING host_field_lex;
+  LEX_STRING user_field_lex;
+  LEX_STRING password_field_lex;
+  LEX_STRING port_field_lex;
+  LEX_STRING connect_retry_field_lex;
+  LEX_STRING ssl_field_lex;
+  LEX_STRING ssl_ca_field_lex;
+  LEX_STRING ssl_capath_field_lex;
+  LEX_STRING ssl_cert_field_lex;
+  LEX_STRING ssl_cipher_field_lex;
+  LEX_STRING ssl_key_field_lex;
+  LEX_STRING ssl_verify_server_cert_field_lex;
+  LEX_STRING heartbeat_field_lex;
+  LEX_STRING ignore_server_ids_field_lex;
+};
+typedef struct store_master_info* ptr_struct_store_mi;
+typedef struct store_master_info struct_store_mi;
+
+class Master_info_table : public Master_info, public Rpl_info_table
+{
+public:
+  Master_info_table() { };
+
+private:
+  bool read_info(TABLE *table, ptr_struct_store_mi store_mi);
+  bool write_info(TABLE *table, ptr_struct_store_mi store_mi);
+
+  int do_check();
+  int do_init_info();
+  int do_prepare_info();
+  int do_flush_info(const bool force);
+  void do_end_info();
+  int do_reset_info();
+
+  Master_info_table& operator=(const Master_info_table& info);
+  Master_info_table(const Master_info_table& info);
+};
+
+#endif /* RPL_MI_TABLE_H */

=== added file 'sql/rpl_rli_table.cc'
--- a/sql/rpl_rli_table.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_rli_table.cc	2009-12-15 02:40:10 +0000
@@ -0,0 +1,342 @@
+/* Copyright 2004-2009 MySQL AB, 2008 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include "mysql_priv.h"
+#include "rpl_rli_table.h"
+#include "rpl_utility.h"
+
+static
+const TABLE_FIELD_W_TYPE relay_info_table_fields[RLI_FIELD_COUNT] =
+{
+  {
+    { C_STRING_WITH_LEN("master_id") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("rli_master_log_pos") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("rli_relay_log_pos") },
+    { C_STRING_WITH_LEN("text") },
+    { C_STRING_WITH_LEN("utf8") }
+  }
+};
+
+int Relay_log_info_table::do_init_info()
+{
+  int error= 1;
+  TABLE *table= NULL;
+  ulong saved_mode;
+  bool saved_format= FALSE;
+  Open_tables_state backup;
+  struct_store_rli store_rli;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+  const char* errmsg= NULL;
+  
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Relay_log_info_table::do_init_info");
+
+  saved_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
+  saved_format= thd->is_current_stmt_binlog_format_row();
+  thd->clear_current_stmt_binlog_format_row();
+
+  if (open_table(thd, RLI_SCHEMA, RLI_TABLE, RLI_FIELD_COUNT, TL_WRITE,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (!find_info_id(RLI_FIELD_ID, id_field_lex, table))
+  {
+    if (!read_info(table, &store_rli))
+    {
+      if (is_relay_log_recovery && init_recovery(mi, &errmsg))
+        goto end;
+
+      if (init_relay_log_pos(this,
+                             group_relay_log_name,
+                             group_relay_log_pos,
+                             0 /* no data lock*/,
+                             &errmsg, 0))
+      {
+        char llbuf[22];
+        sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
+                        group_relay_log_name,
+                        llstr(group_relay_log_pos, llbuf));
+        goto end;
+      }
+    }
+    else 
+      goto end;
+  }
+  else
+  {
+    if (init_relay_log_pos(this, NullS, BIN_LOG_HEADER_SIZE, 0 /* no data lock */,
+                           &errmsg, 0))
+    {
+      sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
+      goto end;
+    }
+    group_master_log_name[0]= 0;
+    group_master_log_pos= 0;
+
+    restore_record(table, s->default_values);
+
+    if (write_info(table, &store_rli))
+      goto end;
+
+    if (table->file->ha_write_row(table->record[0]))
+    {
+      table->file->print_error(error, MYF(0));
+      goto end;
+    }
+  }
+  error= 0;
+
+end:
+  if (saved_format)
+    thd->set_current_stmt_binlog_format_row();
+  thd->variables.sql_mode= saved_mode;
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+
+int Relay_log_info_table::do_flush_info(bool force)
+{
+  int error= 1;
+  TABLE *table= NULL;
+  ulong saved_mode;
+  bool saved_format= FALSE;
+  Open_tables_state backup;
+  struct_store_rli store_rli;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Relay_log_info_table::do_flush_info");
+
+  if (thd->lex->requires_prelocking())
+    DBUG_RETURN(0);
+
+  saved_mode= thd->variables.sql_mode;
+  saved_format= thd->is_current_stmt_binlog_format_row();
+  thd->clear_current_stmt_binlog_format_row();
+
+  if (open_table(thd, RLI_SCHEMA, RLI_TABLE, RLI_FIELD_COUNT, TL_WRITE,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (find_info_id(RLI_FIELD_ID, id_field_lex, table))
+  {
+    my_error(ER_NO_SUCH_KEY_VALUE, MYF(0), id_field_lex.str,
+             RLI_SCHEMA, RLI_TABLE);
+    goto end;
+  }
+
+  store_record(table, record[1]);
+  /* 
+    Don't update create on row update.
+  */
+  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
+  if (write_info(table, &store_rli))
+    goto end;
+
+  if ((error= table->file->ha_update_row(table->record[1], table->record[0])) &&
+      error != HA_ERR_RECORD_IS_THE_SAME)
+  {
+    table->file->print_error(error, MYF(0));
+    goto end;
+  }
+  error= 0;
+
+end:
+  if (saved_format)
+    thd->set_current_stmt_binlog_format_row();
+  thd->variables.sql_mode= saved_mode;
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+bool Relay_log_info_table::read_info(TABLE *table, ptr_struct_store_rli store_rli)
+{
+  DBUG_ENTER("Relay_log_info_table::read_info");
+
+  if (load_info_fields(RLI_FIELD_COUNT, table->field,
+                       RLI_FIELD_MASTER_LOG_POS, &store_rli->master_field_lex,
+                       RLI_FIELD_RELAY_LOG_POS, &store_rli->relay_field_lex,
+                       RLI_FIELD_COUNT))
+    DBUG_RETURN(TRUE);
+
+  char *pos= index(store_rli->master_field_lex.str, ':');
+  *pos++= 0;
+  strmov(group_master_log_name, store_rli->master_field_lex.str);
+  group_master_log_pos= atoll(pos);
+
+  pos= index(store_rli->relay_field_lex.str, ':');
+  *pos++= 0;
+  strmov(group_relay_log_name, store_rli->relay_field_lex.str);
+  group_relay_log_pos= atoll(pos);
+
+  DBUG_RETURN(FALSE);
+}
+
+bool Relay_log_info_table::write_info(TABLE *table, ptr_struct_store_rli store_rli)
+{
+  char *pos= NULL;
+
+  DBUG_ENTER("Relay_log_info_table::write_info");
+
+  longlong2str(server_id, store_rli->id_field, 10);
+  store_rli->id_field_lex.str= store_rli->id_field;
+  store_rli->id_field_lex.length= strlen(store_rli->id_field);
+
+  pos= strmov(store_rli->master_field, group_master_log_name);
+  *pos++= ':';
+  pos= longlong2str(group_master_log_pos, pos, 10);
+  store_rli->master_field_lex.str= store_rli->master_field;
+  store_rli->master_field_lex.length= strlen(store_rli->master_field);
+
+  pos= strmov(store_rli->relay_field, group_relay_log_name);
+  *pos++= ':';
+  pos= longlong2str(group_relay_log_pos, pos, 10);
+  store_rli->relay_field_lex.str= store_rli->relay_field;
+  store_rli->relay_field_lex.length= strlen(store_rli->relay_field);
+
+  if (store_info_fields(RLI_FIELD_COUNT, table->field,
+                        RLI_FIELD_ID, &store_rli->id_field_lex,
+                        RLI_FIELD_MASTER_LOG_POS, &store_rli->master_field_lex,
+                        RLI_FIELD_RELAY_LOG_POS, &store_rli->relay_field_lex,
+                        RLI_FIELD_COUNT))
+    DBUG_RETURN(TRUE);
+
+  DBUG_RETURN(FALSE);
+}
+
+/**
+  Delete relay info record from mysql.rli_info table.
+
+  @retval FALSE success
+  @retval TRUE error (reported)
+*/
+
+int Relay_log_info_table::do_reset_info()
+{
+  int error= 1;
+  TABLE *table= NULL;
+  ulong saved_mode;
+  bool saved_format= FALSE;
+  Open_tables_state backup;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Relay_log_info_table::do_reset_info");
+
+  saved_mode= thd->variables.sql_mode;
+  saved_format= thd->is_current_stmt_binlog_format_row();
+  thd->clear_current_stmt_binlog_format_row();
+
+  if (open_table(thd, RLI_SCHEMA, RLI_TABLE, RLI_FIELD_COUNT, TL_WRITE,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (!find_info_id(RLI_FIELD_ID, id_field_lex, table))
+  {
+    if ((error= table->file->ha_delete_row(table->record[0])))
+    {
+      table->file->print_error(error, MYF(0));
+      goto end;
+    }
+  }
+  error= 0;
+
+end:
+  if (saved_format)
+    thd->set_current_stmt_binlog_format_row();
+  thd->variables.sql_mode= saved_mode;
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+int Relay_log_info_table::do_check()
+{
+  int error= 1;
+  TABLE *table= NULL;
+  Open_tables_state backup;
+  char id_field[FN_REFLEN];
+  LEX_STRING id_field_lex;
+
+  THD *thd= create_fake_thd();
+
+  DBUG_ENTER("Relay_log_info_table::do_check_info");
+
+  if (open_table(thd, RLI_SCHEMA, RLI_TABLE, RLI_FIELD_COUNT, TL_READ,
+                 &table, &backup))
+    goto end;
+
+  longlong2str(server_id, id_field, 10);
+  id_field_lex.str= id_field;
+  id_field_lex.length= strlen(id_field);
+
+  if (find_info_id(RLI_FIELD_ID, id_field_lex, table))
+  {
+    my_error(ER_NO_SUCH_KEY_VALUE, MYF(0), id_field_lex.str,
+             RLI_SCHEMA, RLI_TABLE);
+    goto end;
+  }
+
+  error= 0;
+
+end:
+  close_table(thd, table, &backup);
+  drop_fake_thd(thd, error);
+  DBUG_RETURN(test(error));
+}
+
+int Relay_log_info_table::do_prepare_info()
+{
+  /*
+    This should not be called if the the master.info is
+    stored in a table.
+  */
+  return(0);
+}
+
+void Relay_log_info_table::do_end_info()
+{
+}

=== added file 'sql/rpl_rli_table.h'
--- a/sql/rpl_rli_table.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_rli_table.h	2009-12-15 02:40:10 +0000
@@ -0,0 +1,66 @@
+/* Copyright 2004-2009 MySQL AB, 2008 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_RLI_TABLE_H
+#define RPL_RLI_TABLE_H
+
+#include "rpl_rli.h"
+#include "rpl_info_table.h"
+
+#define RLI_SCHEMA "mysql"
+#define RLI_TABLE  "rli_info"
+
+enum enum_relay_info_table_field
+{
+  RLI_FIELD_ID = 0,
+  RLI_FIELD_MASTER_LOG_POS,
+  RLI_FIELD_RELAY_LOG_POS,
+  RLI_FIELD_COUNT
+};
+
+struct store_relay_info
+{
+  char id_field[FN_REFLEN];
+  char master_field[FN_REFLEN];
+  char relay_field[FN_REFLEN];
+
+  LEX_STRING id_field_lex;
+  LEX_STRING master_field_lex;
+  LEX_STRING relay_field_lex;
+};
+typedef struct store_relay_info* ptr_struct_store_rli;
+typedef struct store_relay_info struct_store_rli;
+
+class Relay_log_info_table : public Relay_log_info, public Rpl_info_table
+{
+public:
+  Relay_log_info_table(bool is_slave_recovery)
+    :Relay_log_info(is_slave_recovery) { };
+
+private:
+  bool read_info(TABLE *table, ptr_struct_store_rli store_rli);
+  bool write_info(TABLE *table, ptr_struct_store_rli store_rli);
+
+  int do_check();
+  int do_init_info();
+  int do_prepare_info();
+  int do_flush_info(const bool force);
+  void do_end_info();
+  int do_reset_info();
+
+  Relay_log_info_table& operator=(const Relay_log_info_table& info);
+  Relay_log_info_table(const Relay_log_info_table& info);
+};
+#endif /* RPL_RLI_TABLE_H */

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2009-12-11 20:59:37 +0000
+++ b/sql/set_var.cc	2009-12-15 02:40:10 +0000
@@ -180,6 +180,12 @@ static sys_var_long_ptr	sys_binlog_cache
 					      &binlog_cache_size);
 static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format",
                                             &SV::binlog_format);
+static sys_var_const sys_mi_repository(&vars, "master_info_repository",
+                                       OPT_GLOBAL, SHOW_CHAR,
+                                      (uchar *) opt_mi_repository);
+static sys_var_const sys_rli_repository(&vars, "relay_log_info_repository",
+                                        OPT_GLOBAL, SHOW_CHAR,
+                                        (uchar *) opt_rli_repository);
 static sys_var_thd_ulong	sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size",
 						  &SV::bulk_insert_buff_size);
 static sys_var_const_os         sys_character_sets_dir(&vars,

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2009-11-10 18:45:15 +0000
+++ b/sql/share/errmsg.txt	2009-12-15 02:40:10 +0000
@@ -6249,3 +6249,8 @@ ER_DEBUG_SYNC_TIMEOUT
 ER_DEBUG_SYNC_HIT_LIMIT
   eng "debug sync point hit limit reached"
   ger "Debug Sync Point Hit Limit erreicht"
+
+ER_NO_SUCH_KEY_VALUE
+  eng "Key value '%-.192s' was not found in table '%-.192s.%-.192s'"
+ER_INFO_DATA_TOO_LONG
+  eng "Data for column '%s' too long"

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2009-12-11 20:59:37 +0000
+++ b/sql/slave.cc	2009-12-15 02:40:10 +0000
@@ -30,11 +30,10 @@
 #include <myisam.h>
 #include "slave.h"
 #include "rpl_mi.h"
-#include "rpl_mi_file.h"
 #include "rpl_rli.h"
-#include "rpl_rli_file.h"
 #include "sql_repl.h"
 #include "rpl_filter.h"
+#include "rpl_info_factory.h"
 #include "repl_failsafe.h"
 #include <thr_alarm.h>
 #include <my_dir.h>
@@ -231,8 +230,6 @@ int init_slave()
   int error= 0;
   int thread_mask= SLAVE_SQL | SLAVE_IO;
   Relay_log_info* rli= NULL;
-  Relay_log_info* rli_file= NULL;
-  Master_info* mi_file= NULL;
 
   /*
     This is called when mysqld starts. Before client connections are
@@ -247,26 +244,13 @@ int init_slave()
     goto err;
   }
 
-  mi_file= new Master_info_file(master_info_file);
-  if (!mi_file)
+  if ((error= Rpl_info_factory::create(opt_mi_repository_id, &active_mi,
+                                       opt_rli_repository_id, &rli)))
   {
-    sql_print_error("Failed to allocate memory for the master info structure");
     error= 1;
     goto err;
   }
 
-  rli_file= new Relay_log_info_file(relay_log_recovery,
-                                    relay_log_info_file);
-  if (!rli_file)
-  {
-    sql_print_error("Failed to allocate memory for the master info structure");
-    error= 1;
-    goto err;
-  }
-
-  rli= rli_file;
-  active_mi= mi_file;
-
   /*
     If --slave-skip-errors=... was not used, the string value for the
     system variable has not been set up yet. Do it now.

=== modified file 'sql/slave.h'
--- a/sql/slave.h	2009-12-11 20:59:37 +0000
+++ b/sql/slave.h	2009-12-15 02:40:10 +0000
@@ -33,6 +33,34 @@
 */
 #define SLAVE_MAX_HEARTBEAT_PERIOD 4294967
 
+enum enum_mi_repository
+{
+  MI_REPOSITORY_FILE= 0,
+  MI_REPOSITORY_TABLE= 1,
+  /*
+    This value is last, after the end of slave_repository_typelib: it has no
+    corresponding cell in this typelib. We use this value to be able to know
+    if the user has explicitely specified a the type of repository at startup
+    or not.
+  */
+  MI_REPOSITORY_UNSPEC= 2
+};
+extern TYPELIB mi_repository_typelib;
+
+enum enum_rli_repository
+{
+  RLI_REPOSITORY_FILE= 0,
+  RLI_REPOSITORY_TABLE= 1,
+  /*
+    This value is last, after the end of slave_repository_typelib: it has no
+    corresponding cell in this typelib. We use this value to be able to know
+    if the user has explicitely specified a the type of repository at startup
+    or not.
+  */
+  RLI_REPOSITORY_UNSPEC= 2
+};
+extern TYPELIB rli_repository_typelib;
+
 #ifdef HAVE_REPLICATION
 
 #include "log.h"

=== modified file 'sql/sql_binlog.cc'
--- a/sql/sql_binlog.cc	2009-12-11 20:59:37 +0000
+++ b/sql/sql_binlog.cc	2009-12-15 02:40:10 +0000
@@ -14,7 +14,8 @@
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
 #include "mysql_priv.h"
-#include "rpl_rli_file.h"
+#include "rpl_info.h"
+#include "rpl_info_factory.h"
 #include "base64.h"
 
 /**
@@ -61,7 +62,8 @@ void mysql_client_binlog_statement(THD* 
   rli= thd->rli_fake;
   if (!rli)
   {
-    rli= thd->rli_fake= new Relay_log_info_file(FALSE, "fake");
+    Rpl_info_factory::create_file_rli(FALSE, "fake", &thd->rli_fake);
+    rli= thd->rli_fake;
 #ifdef HAVE_purify
     thd->rli_fake->is_fake= TRUE;
 #endif
@@ -215,7 +217,6 @@ void mysql_client_binlog_statement(THD* 
 #else
       err= 0;
 #endif
-
       /*
         Format_description_log_event should not be deleted because it
         will be used to read info about the relay log's format; it


Attachment: [text/bzr-bundle]
Thread
bzr commit into mysql-5.1-rep+3 branch (alfranio.correia:3124) WL#2775Alfranio Correia15 Dec