List:Commits« Previous MessageNext Message »
From:Marc Alff Date:October 25 2010 1:50pm
Subject:bzr push into mysql-next-mr-wl4816 branch (marc.alff:3204 to 3205)
View as plain text  
 3205 Marc Alff	2010-10-25 [merge]
      Merge mysql-next-mr --> mysql-next-mr-wl4816

    added:
      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
      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/server_ids.h
    modified:
      client/mysql.cc
      client/mysqladmin.cc
      client/mysqlbinlog.cc
      client/mysqlcheck.c
      client/mysqldump.c
      client/mysqlimport.c
      client/mysqlshow.c
      include/mysql.h
      include/mysql.h.pp
      mysql-test/collections/default.experimental
      mysql-test/include/show_binlog_using_logname.inc
      mysql-test/r/mysql.result
      mysql-test/r/mysqladmin.result
      mysql-test/r/mysqld--help-notwin.result
      mysql-test/r/mysqld--help-win.result
      mysql-test/r/mysqldump.result
      mysql-test/r/mysqlshow.result
      mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
      mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result
      mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result
      mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result
      mysql-test/suite/ndb_team/r/rpl_ndb_mix_innodb.result
      mysql-test/suite/rpl/r/rpl_flushlog_loop.result
      mysql-test/suite/rpl/r/rpl_rotate_logs.result
      mysql-test/suite/rpl/r/rpl_stm_auto_increment_bug33029.result
      mysql-test/suite/rpl/t/rpl_rotate_logs.test
      mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test
      mysql-test/suite/rpl_ndb/r/rpl_ndb_stm_innodb.result
      mysql-test/t/mysql.test
      mysql-test/t/mysqladmin.test
      mysql-test/t/mysqlbinlog.test
      mysql-test/t/mysqlcheck.test
      mysql-test/t/mysqldump.test
      mysql-test/t/mysqlshow.test
      mysys/mf_iocache2.c
      sql-common/client.c
      sql/CMakeLists.txt
      sql/Makefile.am
      sql/binlog.cc
      sql/binlog.h
      sql/ha_ndbcluster.cc
      sql/item_func.cc
      sql/lock.cc
      sql/log.cc
      sql/log_event.cc
      sql/log_event_old.cc
      sql/mysqld.cc
      sql/rpl_handler.cc
      sql/rpl_mi.cc
      sql/rpl_mi.h
      sql/rpl_reporting.h
      sql/rpl_rli.cc
      sql/rpl_rli.h
      sql/rpl_slave.cc
      sql/rpl_slave.h
      sql/sql_binlog.cc
      sql/sql_insert.cc
      sql/sql_load.cc
      sql/sys_vars.cc
 3204 Marc Alff	2010-10-25
      Misc cleanup

    modified:
      storage/perfschema/pfs.cc
      storage/perfschema/unittest/pfs-t.cc
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc	2010-09-01 13:46:08 +0000
+++ b/client/mysql.cc	2010-10-18 12:18:18 +0000
@@ -152,6 +152,7 @@ static ulong opt_max_allowed_packet, opt
 static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
 static uint my_end_arg;
 static char * opt_mysql_unix_port=0;
+static char *opt_bind_addr = NULL;
 static int connect_flag=CLIENT_INTERACTIVE;
 static char *current_host,*current_db,*current_user=0,*opt_password=0,
             *current_prompt=0, *delimiter_str= 0,
@@ -1376,6 +1377,9 @@ static struct my_option my_long_options[
   {"batch", 'B',
    "Don't use history file. Disable interactive behavior. (Enables --silent.)",
    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"character-sets-dir", OPT_CHARSETS_DIR,
    "Directory for character set files.", &charsets_dir,
    &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -4265,6 +4269,8 @@ sql_real_connect(char *host,char *databa
     mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT,
 		  (char*) &timeout);
   }
+  if (opt_bind_addr)
+    mysql_options(&mysql, MYSQL_OPT_BIND, opt_bind_addr);
   if (opt_compress)
     mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
   if (opt_secure_auth)

=== modified file 'client/mysqladmin.cc'
--- a/client/mysqladmin.cc	2010-07-15 11:13:30 +0000
+++ b/client/mysqladmin.cc	2010-10-18 12:18:18 +0000
@@ -41,6 +41,7 @@ static my_bool option_force=0,interrupte
 static my_bool debug_info_flag= 0, debug_check_flag= 0;
 static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations;
 static uint opt_count_iterations= 0, my_end_arg;
+static char *opt_bind_addr = NULL;
 static ulong opt_connect_timeout, opt_shutdown_timeout;
 static char * unix_port=0;
 
@@ -116,6 +117,9 @@ static TYPELIB command_typelib=
 
 static struct my_option my_long_options[] =
 {
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"count", 'c',
    "Number of iterations to make. This works with -i (--sleep) only.",
    &nr_iterations, &nr_iterations, 0, GET_UINT,
@@ -318,6 +322,8 @@ int main(int argc,char *argv[])
   (void) signal(SIGINT,endprog);			/* Here if abort */
   (void) signal(SIGTERM,endprog);		/* Here if abort */
 
+  if (opt_bind_addr)
+    mysql_options(&mysql,MYSQL_OPT_BIND,opt_bind_addr);
   if (opt_compress)
     mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
   if (opt_connect_timeout)

=== modified file 'client/mysqlbinlog.cc'
--- a/client/mysqlbinlog.cc	2010-09-01 02:51:08 +0000
+++ b/client/mysqlbinlog.cc	2010-10-18 12:18:18 +0000
@@ -89,6 +89,7 @@ static char *shared_memory_base_name= 0;
 #endif
 static char* user = 0;
 static char* pass = 0;
+static char *opt_bind_addr = NULL;
 static char *charset= 0;
 
 static uint verbose= 0;
@@ -1024,6 +1025,9 @@ static struct my_option my_long_options[
    "argument, 'always' is used.",
    &opt_base64_output_mode_str, &opt_base64_output_mode_str,
    0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   /*
     mysqlbinlog needs charsets knowledge, to be able to convert a charset
     number found in binlog to a charset name (to be able to print things
@@ -1419,6 +1423,8 @@ static Exit_status safe_connect()
 
   if (opt_protocol)
     mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
+  if (opt_bind_addr)
+    mysql_options(mysql, MYSQL_OPT_BIND, opt_bind_addr);
 #ifdef HAVE_SMEM
   if (shared_memory_base_name)
     mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
@@ -1627,9 +1633,9 @@ static Exit_status dump_remote_log_entri
 
   for (;;)
   {
-    const char *error_msg;
-    Log_event *ev;
-    Log_event_type type;
+    const char *error_msg= NULL;
+    Log_event *ev= NULL;
+    Log_event_type type= UNKNOWN_EVENT;
 
     len= cli_safe_read(mysql);
     if (len == packet_error)

=== modified file 'client/mysqlcheck.c'
--- a/client/mysqlcheck.c	2010-07-15 13:47:50 +0000
+++ b/client/mysqlcheck.c	2010-10-18 12:18:18 +0000
@@ -47,6 +47,7 @@ DYNAMIC_ARRAY tables4repair;
 static char *shared_memory_base_name=0;
 #endif
 static uint opt_protocol=0;
+static char *opt_bind_addr = NULL;
 
 enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
 
@@ -66,6 +67,9 @@ static struct my_option my_long_options[
    "If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.",
    &opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
    0, 0, 0, 0, 0},
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"character-sets-dir", OPT_CHARSETS_DIR,
    "Directory for character set files.", &charsets_dir,
    &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -786,6 +790,8 @@ static int dbConnect(char *host, char *u
 #endif
   if (opt_protocol)
     mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+  if (opt_bind_addr)
+    mysql_options(&mysql_connection, MYSQL_OPT_BIND, opt_bind_addr);
 #ifdef HAVE_SMEM
   if (shared_memory_base_name)
     mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);

=== modified file 'client/mysqldump.c'
--- a/client/mysqldump.c	2010-08-30 12:11:53 +0000
+++ b/client/mysqldump.c	2010-10-18 12:18:18 +0000
@@ -125,6 +125,7 @@ static uint opt_mysql_port= 0, opt_maste
 static uint opt_slave_data;
 static uint my_end_arg;
 static char * opt_mysql_unix_port=0;
+static char *opt_bind_addr = NULL;
 static int   first_error=0;
 static DYNAMIC_STRING extended_row;
 #include <sslopt-vars.h>
@@ -214,6 +215,9 @@ static struct my_option my_long_options[
    "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
    &opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG,
    0, 0, 0, 0, 0, 0},
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"character-sets-dir", OPT_CHARSETS_DIR,
    "Directory for character set files.", &charsets_dir,
    &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1449,6 +1453,8 @@ static int connect_to_db(char *host, cha
 #endif
   if (opt_protocol)
     mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+  if (opt_bind_addr)
+    mysql_options(&mysql_connection,MYSQL_OPT_BIND,opt_bind_addr);
 #ifdef HAVE_SMEM
   if (shared_memory_base_name)
     mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);

=== modified file 'client/mysqlimport.c'
--- a/client/mysqlimport.c	2010-07-15 11:13:30 +0000
+++ b/client/mysqlimport.c	2010-10-18 12:18:18 +0000
@@ -57,6 +57,7 @@ static char	*opt_password=0, *current_us
 		*escaped=0, *opt_columns=0, 
 		*default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
 static uint     opt_mysql_port= 0, opt_protocol= 0;
+static char *opt_bind_addr = NULL;
 static char * opt_mysql_unix_port=0;
 static longlong opt_ignore_lines= -1;
 #include <sslopt-vars.h>
@@ -67,6 +68,9 @@ static char *shared_memory_base_name=0;
 
 static struct my_option my_long_options[] =
 {
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"character-sets-dir", OPT_CHARSETS_DIR,
    "Directory for character set files.", &charsets_dir,
    &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -424,6 +428,8 @@ static MYSQL *db_connect(char *host, cha
 #endif
   if (opt_protocol)
     mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+  if (opt_bind_addr)
+    mysql_options(mysql,MYSQL_OPT_BIND,opt_bind_addr);
 #ifdef HAVE_SMEM
   if (shared_memory_base_name)
     mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);

=== modified file 'client/mysqlshow.c'
--- a/client/mysqlshow.c	2010-07-15 13:47:50 +0000
+++ b/client/mysqlshow.c	2010-10-18 12:18:18 +0000
@@ -38,6 +38,7 @@ static char *default_charset= (char*) MY
 static char *shared_memory_base_name=0;
 #endif
 static uint opt_protocol=0;
+static char *opt_bind_addr = NULL;
 
 static void get_options(int *argc,char ***argv);
 static uint opt_mysql_port=0;
@@ -117,6 +118,8 @@ int main(int argc, char **argv)
 #endif
   if (opt_protocol)
     mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+  if (opt_bind_addr)
+    mysql_options(&mysql,MYSQL_OPT_BIND,opt_bind_addr);
 #ifdef HAVE_SMEM
   if (shared_memory_base_name)
     mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
@@ -160,6 +163,9 @@ int main(int argc, char **argv)
 
 static struct my_option my_long_options[] =
 {
+  {"bind-address", 0, "IP address to bind to.",
+   (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"character-sets-dir", 'c', "Directory for character set files.",
    &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
    0, 0, 0, 0, 0},

=== modified file 'include/mysql.h'
--- a/include/mysql.h	2010-09-07 07:49:47 +0000
+++ b/include/mysql.h	2010-10-19 09:54:17 +0000
@@ -167,7 +167,7 @@ enum mysql_option 
   MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
   MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
   MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
-  MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+  MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_OPT_BIND
 };
 
 struct st_mysql_options {
@@ -191,7 +191,20 @@ struct st_mysql_options {
   my_bool unused3;
   my_bool unused4;
   enum mysql_option methods_to_use;
-  char *client_ip;
+  union {
+    /*
+      The ip/hostname to use when authenticating
+      client against embedded server built with
+      grant tables - only used in embedded server
+    */
+    char *client_ip;
+
+    /*
+      The local address to bind when connecting to
+      remote server - not used in embedded server
+    */
+    char *bind_address;
+  } ci;
   /* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
   my_bool secure_auth;
   /* 0 - never report, 1 - always report (default) */

=== modified file 'include/mysql.h.pp'
--- a/include/mysql.h.pp	2010-09-10 08:06:58 +0000
+++ b/include/mysql.h.pp	2010-10-19 09:54:17 +0000
@@ -262,7 +262,7 @@ enum mysql_option
   MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
   MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
   MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
-  MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+  MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_OPT_BIND
 };
 struct st_mysql_options {
   unsigned int connect_timeout, read_timeout, write_timeout;
@@ -285,7 +285,10 @@ struct st_mysql_options {
   my_bool unused3;
   my_bool unused4;
   enum mysql_option methods_to_use;
-  char *client_ip;
+  union {
+    char *client_ip;
+    char *bind_address;
+  } ci;
   my_bool secure_auth;
   my_bool report_data_truncation;
   int (*local_infile_init)(void **, const char *, void *);

=== modified file 'mysql-test/collections/default.experimental'
--- a/mysql-test/collections/default.experimental	2010-09-28 15:30:47 +0000
+++ b/mysql-test/collections/default.experimental	2010-10-18 10:32:23 +0000
@@ -33,6 +33,7 @@ perfschema.server_init                  
 rpl.rpl_heartbeat_basic                  # BUG#54820 2010-06-26 alik rpl.rpl_heartbeat_basic fails sporadically again
 rpl.rpl_innodb_bug28430*                 # Bug#46029
 rpl.rpl_row_sp011* @solaris              # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun
+rpl.rpl_delayed_slave                    # BUG#57514 rpl_delayed_slave fails sporadically in pb
 
 sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun
 sys_vars.slow_query_log_func @solaris         # Bug#54819 2010-06-26 alik sys_vars.slow_query_log_func fails sporadically on Solaris 10

=== modified file 'mysql-test/include/show_binlog_using_logname.inc'
--- a/mysql-test/include/show_binlog_using_logname.inc	2007-06-21 19:58:59 +0000
+++ b/mysql-test/include/show_binlog_using_logname.inc	2010-06-27 01:42:41 +0000
@@ -9,5 +9,5 @@
 --replace_result $start_pos <start_pos> $end_pos <end_pos>
 --replace_column 2 #
 --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
---eval show binlog events in '$log_name'  from $start_pos limit $off_set,1
+--eval show binlog events in '$log_name'  from $start_pos limit $end_pos,1
 

=== modified file 'mysql-test/r/mysql.result'
--- a/mysql-test/r/mysql.result	2010-08-25 08:17:15 +0000
+++ b/mysql-test/r/mysql.result	2010-10-20 10:50:50 +0000
@@ -434,3 +434,5 @@ Bug #47147: mysql client option --skip-c
 1
 
 End of tests
+Connected
+1

=== modified file 'mysql-test/r/mysqladmin.result'
--- a/mysql-test/r/mysqladmin.result	2006-11-10 12:25:10 +0000
+++ b/mysql-test/r/mysqladmin.result	2010-09-30 10:28:49 +0000
@@ -2,3 +2,4 @@ mysqld is alive
 mysqladmin: unknown variable 'database=db1'
 Warning: mysqladmin: unknown variable 'loose-database=db2'
 mysqld is alive
+mysqld is alive

=== modified file 'mysql-test/r/mysqld--help-notwin.result'
--- a/mysql-test/r/mysqld--help-notwin.result	2010-10-11 16:43:09 +0000
+++ b/mysql-test/r/mysqld--help-notwin.result	2010-10-25 13:46:20 +0000
@@ -282,6 +282,9 @@ The following options may be given as th
  The location and name of the file that remembers the
  master and where the I/O replication thread is in the
  master's binlogs.
+ --master-info-repository=name 
+ Defines the type of the repository for the master
+ information.
  --master-retry-count=# 
  The number of tries the slave will make to connect to the
  master before giving up.
@@ -508,6 +511,9 @@ The following options may be given as th
  --relay-log-info-file=name 
  The location and name of the file that remembers where
  the SQL replication thread is in the relay logs
+ --relay-log-info-repository=name 
+ Defines the type of the repository for the relay log
+ information.
  --relay-log-purge   if disabled - do not purge relay logs. if enabled - purge
  them as soon as they are no more needed
  (Defaults to on; use --skip-relay-log-purge to disable.)
@@ -822,6 +828,7 @@ long-query-time 10
 low-priority-updates FALSE
 lower-case-table-names 1
 master-info-file master.info
+master-info-repository FILE
 master-retry-count 86400
 max-allowed-packet 1048576
 max-binlog-cache-size 18446744073709547520
@@ -904,6 +911,7 @@ read-rnd-buffer-size 262144
 relay-log (No default value)
 relay-log-index (No default value)
 relay-log-info-file relay-log.info
+relay-log-info-repository FILE
 relay-log-purge TRUE
 relay-log-recovery FALSE
 relay-log-space-limit 0

=== modified file 'mysql-test/r/mysqld--help-win.result'
--- a/mysql-test/r/mysqld--help-win.result	2010-10-11 16:43:09 +0000
+++ b/mysql-test/r/mysqld--help-win.result	2010-10-25 13:46:20 +0000
@@ -281,6 +281,9 @@ The following options may be given as th
  The location and name of the file that remembers the
  master and where the I/O replication thread is in the
  master's binlogs.
+ --master-info-repository=name 
+ Defines the type of the repository for the master
+ information.
  --master-retry-count=# 
  The number of tries the slave will make to connect to the
  master before giving up.
@@ -508,6 +511,9 @@ The following options may be given as th
  --relay-log-info-file=name 
  The location and name of the file that remembers where
  the SQL replication thread is in the relay logs
+ --relay-log-info-repository=name 
+ Defines the type of the repository for the relay log
+ information.
  --relay-log-purge   if disabled - do not purge relay logs. if enabled - purge
  them as soon as they are no more needed
  (Defaults to on; use --skip-relay-log-purge to disable.)
@@ -825,6 +831,7 @@ long-query-time 10
 low-priority-updates FALSE
 lower-case-table-names 1
 master-info-file master.info
+master-info-repository FILE
 master-retry-count 86400
 max-allowed-packet 1048576
 max-binlog-cache-size 18446744073709547520
@@ -908,6 +915,7 @@ read-rnd-buffer-size 262144
 relay-log (No default value)
 relay-log-index (No default value)
 relay-log-info-file relay-log.info
+relay-log-info-repository FILE
 relay-log-purge TRUE
 relay-log-recovery FALSE
 relay-log-space-limit 0

=== modified file 'mysql-test/r/mysqldump.result'
--- a/mysql-test/r/mysqldump.result	2010-08-30 06:38:09 +0000
+++ b/mysql-test/r/mysqldump.result	2010-10-18 12:18:18 +0000
@@ -4575,6 +4575,11 @@ SELECT LENGTH(a) FROM t2;
 LENGTH(a)
 800
 DROP TABLE t1, t2;
+create table t1 (first char(28) , last varchar(37));
+insert into t1 values ("Magnus", "Bl: 0  Skipped: 0  Warnings: 0
+drop table t1;
 #
 # End of 5.1 tests
 #

=== modified file 'mysql-test/r/mysqlshow.result'
--- a/mysql-test/r/mysqlshow.result	2010-06-10 04:54:54 +0000
+++ b/mysql-test/r/mysqlshow.result	2010-10-18 12:18:18 +0000
@@ -181,4 +181,9 @@ Wildcard: inf_rmation_schema
 +--------------------+
 | information_schema |
 +--------------------+
+Database: test
++--------+
+| Tables |
++--------+
++--------+
 End of 5.0 tests

=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result	2010-01-15 11:42:15 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result	2010-07-06 22:01:07 +0000
@@ -143,6 +143,33 @@ def	mysql	servers	Server_name	1		NO	char
 def	mysql	servers	Socket	7		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)				
 def	mysql	servers	Username	4		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)				
 def	mysql	servers	Wrapper	8		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)				
+def	mysql	slave_master_info	Connect_retry	9	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_master_info	Enabled_ssl	10	NULL	NO	tinyint	NULL	NULL	3	0	NULL	NULL	tinyint(1)				
+def	mysql	slave_master_info	Heartbeat	17	NULL	NO	float	NULL	NULL	12	NULL	NULL	NULL	float				
+def	mysql	slave_master_info	Host	5	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Ignored_server_ids	18	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Master_id	1	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned	PRI			
+def	mysql	slave_master_info	Master_log_name	3	NULL	NO	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Master_log_pos	4	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_master_info	Number_of_lines	2	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_master_info	Port	8	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_master_info	Retry_count	19	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_master_info	Ssl_ca	11	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Ssl_capath	12	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Ssl_cert	13	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Ssl_cipher	14	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Ssl_key	15	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Ssl_verify_servert_cert	16	NULL	NO	tinyint	NULL	NULL	3	0	NULL	NULL	tinyint(1)				
+def	mysql	slave_master_info	User_name	6	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	User_password	7	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_master_info	Uuid	20	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_relay_log_info	Master_id	1	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned	PRI			
+def	mysql	slave_relay_log_info	Master_log_name	5	NULL	NO	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_relay_log_info	Master_log_pos	6	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_relay_log_info	Number_of_lines	2	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_relay_log_info	Relay_log_name	3	NULL	NO	text	65535	65535	NULL	NULL	utf8	utf8_bin	text				
+def	mysql	slave_relay_log_info	Relay_log_pos	4	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
+def	mysql	slave_relay_log_info	Sql_delay	7	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)				
 def	mysql	slow_log	db	7	NULL	NO	varchar	512	1536	NULL	NULL	utf8	utf8_general_ci	varchar(512)				
 def	mysql	slow_log	insert_id	9	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)				
 def	mysql	slow_log	last_insert_id	8	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)				
@@ -265,6 +292,7 @@ ORDER BY CHARACTER_SET_NAME, COLLATION_N
 COL_CML	DATA_TYPE	CHARACTER_SET_NAME	COLLATION_NAME
 NULL	bigint	NULL	NULL
 NULL	datetime	NULL	NULL
+NULL	float	NULL	NULL
 NULL	int	NULL	NULL
 NULL	smallint	NULL	NULL
 NULL	time	NULL	NULL
@@ -427,6 +455,33 @@ NULL	mysql	servers	Port	int	NULL	NULL	NU
 3.0000	mysql	servers	Socket	char	64	192	utf8	utf8_general_ci	char(64)
 3.0000	mysql	servers	Wrapper	char	64	192	utf8	utf8_general_ci	char(64)
 3.0000	mysql	servers	Owner	char	64	192	utf8	utf8_general_ci	char(64)
+NULL	mysql	slave_master_info	Master_id	int	NULL	NULL	NULL	NULL	int(10) unsigned
+NULL	mysql	slave_master_info	Number_of_lines	int	NULL	NULL	NULL	NULL	int(10) unsigned
+1.0000	mysql	slave_master_info	Master_log_name	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_master_info	Master_log_pos	int	NULL	NULL	NULL	NULL	int(10) unsigned
+1.0000	mysql	slave_master_info	Host	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	User_name	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	User_password	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_master_info	Port	int	NULL	NULL	NULL	NULL	int(10) unsigned
+NULL	mysql	slave_master_info	Connect_retry	int	NULL	NULL	NULL	NULL	int(10) unsigned
+NULL	mysql	slave_master_info	Enabled_ssl	tinyint	NULL	NULL	NULL	NULL	tinyint(1)
+1.0000	mysql	slave_master_info	Ssl_ca	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	Ssl_capath	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	Ssl_cert	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	Ssl_cipher	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	Ssl_key	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_master_info	Ssl_verify_servert_cert	tinyint	NULL	NULL	NULL	NULL	tinyint(1)
+NULL	mysql	slave_master_info	Heartbeat	float	NULL	NULL	NULL	NULL	float
+1.0000	mysql	slave_master_info	Ignored_server_ids	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_master_info	Retry_count	int	NULL	NULL	NULL	NULL	int(10) unsigned
+1.0000	mysql	slave_master_info	Uuid	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_relay_log_info	Master_id	int	NULL	NULL	NULL	NULL	int(10) unsigned
+NULL	mysql	slave_relay_log_info	Number_of_lines	int	NULL	NULL	NULL	NULL	int(10) unsigned
+1.0000	mysql	slave_relay_log_info	Relay_log_name	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_relay_log_info	Relay_log_pos	int	NULL	NULL	NULL	NULL	int(10) unsigned
+1.0000	mysql	slave_relay_log_info	Master_log_name	text	65535	65535	utf8	utf8_bin	text
+NULL	mysql	slave_relay_log_info	Master_log_pos	int	NULL	NULL	NULL	NULL	int(10) unsigned
+NULL	mysql	slave_relay_log_info	Sql_delay	int	NULL	NULL	NULL	NULL	int(11)
 NULL	mysql	slow_log	start_time	timestamp	NULL	NULL	NULL	NULL	timestamp
 1.0000	mysql	slow_log	user_host	mediumtext	16777215	16777215	utf8	utf8_general_ci	mediumtext
 NULL	mysql	slow_log	query_time	time	NULL	NULL	NULL	NULL	time

=== modified file 'mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result	2009-10-23 11:02:20 +0000
+++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result	2010-07-06 22:01:07 +0000
@@ -6,108 +6,112 @@ GRANT SELECT ON db_datadict.* TO testuse
 SELECT * FROM information_schema.statistics
 WHERE table_schema = 'mysql'
 ORDER BY table_schema, table_name, index_name, seq_in_index, column_name;
-TABLE_CATALOG	TABLE_SCHEMA	TABLE_NAME	NON_UNIQUE	INDEX_SCHEMA	INDEX_NAME	SEQ_IN_INDEX	COLUMN_NAME	COLLATION	CARDINALITY	SUB_PART	PACKED	NULLABLE	INDEX_TYPE	COMMENT
-def	mysql	columns_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	5	Column_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	1	mysql	User	1	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	event	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	event	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	func	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_category	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_category	0	mysql	PRIMARY	1	help_category_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_keyword	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_keyword	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_relation	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_relation	0	mysql	PRIMARY	2	help_topic_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_topic	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_topic	0	mysql	PRIMARY	1	help_topic_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	host	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	host	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	ndb_binlog_index	0	mysql	PRIMARY	1	epoch	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	plugin	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	proc	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	proc	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	proc	0	mysql	PRIMARY	3	type	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	4	Routine_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	5	Routine_type	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	servers	0	mysql	PRIMARY	1	Server_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_leap_second	0	mysql	PRIMARY	1	Transition_time	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_name	0	mysql	PRIMARY	1	Name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition	0	mysql	PRIMARY	2	Transition_time	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition_type	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition_type	0	mysql	PRIMARY	2	Transition_type_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	user	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	user	0	mysql	PRIMARY	2	User	A	#CARD#	NULL	NULL		BTREE	
+TABLE_CATALOG	TABLE_SCHEMA	TABLE_NAME	NON_UNIQUE	INDEX_SCHEMA	INDEX_NAME	SEQ_IN_INDEX	COLUMN_NAME	COLLATION	CARDINALITY	SUB_PART	PACKED	NULLABLE	INDEX_TYPE	COMMENT	INDEX_COMMENT
+def	mysql	columns_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	5	Column_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	1	mysql	User	1	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	event	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	event	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	func	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_category	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_category	0	mysql	PRIMARY	1	help_category_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_keyword	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_keyword	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_relation	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_relation	0	mysql	PRIMARY	2	help_topic_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_topic	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_topic	0	mysql	PRIMARY	1	help_topic_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	host	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	host	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	ndb_binlog_index	0	mysql	PRIMARY	1	epoch	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	plugin	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	proc	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	proc	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	proc	0	mysql	PRIMARY	3	type	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	4	Routine_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	5	Routine_type	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	servers	0	mysql	PRIMARY	1	Server_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	slave_master_info	0	mysql	PRIMARY	1	Master_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	slave_relay_log_info	0	mysql	PRIMARY	1	Master_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_leap_second	0	mysql	PRIMARY	1	Transition_time	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_name	0	mysql	PRIMARY	1	Name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition	0	mysql	PRIMARY	2	Transition_time	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition_type	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition_type	0	mysql	PRIMARY	2	Transition_type_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	user	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	user	0	mysql	PRIMARY	2	User	A	#CARD#	NULL	NULL		BTREE		
 # Establish connection testuser1 (user=testuser1)
 SELECT * FROM information_schema.statistics
 WHERE table_schema = 'mysql'
 ORDER BY table_schema, table_name, index_name, seq_in_index, column_name;
-TABLE_CATALOG	TABLE_SCHEMA	TABLE_NAME	NON_UNIQUE	INDEX_SCHEMA	INDEX_NAME	SEQ_IN_INDEX	COLUMN_NAME	COLLATION	CARDINALITY	SUB_PART	PACKED	NULLABLE	INDEX_TYPE	COMMENT
-def	mysql	columns_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	columns_priv	0	mysql	PRIMARY	5	Column_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	db	1	mysql	User	1	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	event	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	event	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	func	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_category	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_category	0	mysql	PRIMARY	1	help_category_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_keyword	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_keyword	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_relation	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_relation	0	mysql	PRIMARY	2	help_topic_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_topic	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	help_topic	0	mysql	PRIMARY	1	help_topic_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	host	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	host	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	ndb_binlog_index	0	mysql	PRIMARY	1	epoch	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	plugin	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	proc	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	proc	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	proc	0	mysql	PRIMARY	3	type	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	4	Routine_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	procs_priv	0	mysql	PRIMARY	5	Routine_type	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	servers	0	mysql	PRIMARY	1	Server_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	tables_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_leap_second	0	mysql	PRIMARY	1	Transition_time	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_name	0	mysql	PRIMARY	1	Name	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition	0	mysql	PRIMARY	2	Transition_time	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition_type	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	time_zone_transition_type	0	mysql	PRIMARY	2	Transition_type_id	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	user	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE	
-def	mysql	user	0	mysql	PRIMARY	2	User	A	#CARD#	NULL	NULL		BTREE	
+TABLE_CATALOG	TABLE_SCHEMA	TABLE_NAME	NON_UNIQUE	INDEX_SCHEMA	INDEX_NAME	SEQ_IN_INDEX	COLUMN_NAME	COLLATION	CARDINALITY	SUB_PART	PACKED	NULLABLE	INDEX_TYPE	COMMENT	INDEX_COMMENT
+def	mysql	columns_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	columns_priv	0	mysql	PRIMARY	5	Column_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	db	1	mysql	User	1	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	event	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	event	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	func	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_category	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_category	0	mysql	PRIMARY	1	help_category_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_keyword	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_keyword	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_relation	0	mysql	PRIMARY	1	help_keyword_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_relation	0	mysql	PRIMARY	2	help_topic_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_topic	0	mysql	name	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	help_topic	0	mysql	PRIMARY	1	help_topic_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	host	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	host	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	ndb_binlog_index	0	mysql	PRIMARY	1	epoch	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	plugin	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	proc	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	proc	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	proc	0	mysql	PRIMARY	3	type	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	4	Routine_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	procs_priv	0	mysql	PRIMARY	5	Routine_type	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	servers	0	mysql	PRIMARY	1	Server_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	slave_master_info	0	mysql	PRIMARY	1	Master_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	slave_relay_log_info	0	mysql	PRIMARY	1	Master_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	1	mysql	Grantor	1	Grantor	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	2	Db	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	3	User	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	tables_priv	0	mysql	PRIMARY	4	Table_name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_leap_second	0	mysql	PRIMARY	1	Transition_time	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_name	0	mysql	PRIMARY	1	Name	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition	0	mysql	PRIMARY	2	Transition_time	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition_type	0	mysql	PRIMARY	1	Time_zone_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	time_zone_transition_type	0	mysql	PRIMARY	2	Transition_type_id	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	user	0	mysql	PRIMARY	1	Host	A	#CARD#	NULL	NULL		BTREE		
+def	mysql	user	0	mysql	PRIMARY	2	User	A	#CARD#	NULL	NULL		BTREE		
 # Switch to connection default and close connection testuser1
 DROP USER testuser1@localhost;
 DROP DATABASE db_datadict;

=== modified file 'mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result	2009-10-23 11:02:20 +0000
+++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result	2010-07-06 22:01:07 +0000
@@ -24,6 +24,8 @@ def	mysql	PRIMARY	mysql	plugin	PRIMARY K
 def	mysql	PRIMARY	mysql	proc	PRIMARY KEY
 def	mysql	PRIMARY	mysql	procs_priv	PRIMARY KEY
 def	mysql	PRIMARY	mysql	servers	PRIMARY KEY
+def	mysql	PRIMARY	mysql	slave_master_info	PRIMARY KEY
+def	mysql	PRIMARY	mysql	slave_relay_log_info	PRIMARY KEY
 def	mysql	PRIMARY	mysql	tables_priv	PRIMARY KEY
 def	mysql	PRIMARY	mysql	time_zone	PRIMARY KEY
 def	mysql	PRIMARY	mysql	time_zone_leap_second	PRIMARY KEY
@@ -53,6 +55,8 @@ def	mysql	PRIMARY	mysql	plugin	PRIMARY K
 def	mysql	PRIMARY	mysql	proc	PRIMARY KEY
 def	mysql	PRIMARY	mysql	procs_priv	PRIMARY KEY
 def	mysql	PRIMARY	mysql	servers	PRIMARY KEY
+def	mysql	PRIMARY	mysql	slave_master_info	PRIMARY KEY
+def	mysql	PRIMARY	mysql	slave_relay_log_info	PRIMARY KEY
 def	mysql	PRIMARY	mysql	tables_priv	PRIMARY KEY
 def	mysql	PRIMARY	mysql	time_zone	PRIMARY KEY
 def	mysql	PRIMARY	mysql	time_zone_leap_second	PRIMARY KEY

=== modified file 'mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result	2009-10-23 11:02:20 +0000
+++ b/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result	2010-07-06 22:01:07 +0000
@@ -359,6 +359,52 @@ user_comment	MySQL Foreign Servers table
 Separator	-----------------------------------------------------
 TABLE_CATALOG	def
 TABLE_SCHEMA	mysql
+TABLE_NAME	slave_master_info
+TABLE_TYPE	BASE TABLE
+ENGINE	MyISAM
+VERSION	10
+ROW_FORMAT	Dynamic
+TABLE_ROWS	#TBLR#
+AVG_ROW_LENGTH	#ARL#
+DATA_LENGTH	#DL#
+MAX_DATA_LENGTH	#MDL#
+INDEX_LENGTH	#IL#
+DATA_FREE	#DF#
+AUTO_INCREMENT	NULL
+CREATE_TIME	#CRT#
+UPDATE_TIME	#UT#
+CHECK_TIME	#CT#
+TABLE_COLLATION	utf8_general_ci
+CHECKSUM	NULL
+CREATE_OPTIONS	#CO#
+TABLE_COMMENT	#TC#
+user_comment	Master Information
+Separator	-----------------------------------------------------
+TABLE_CATALOG	NULL
+TABLE_SCHEMA	mysql
+TABLE_NAME	slave_relay_log_info
+TABLE_TYPE	BASE TABLE
+ENGINE	MyISAM
+VERSION	10
+ROW_FORMAT	Dynamic
+TABLE_ROWS	#TBLR#
+AVG_ROW_LENGTH	#ARL#
+DATA_LENGTH	#DL#
+MAX_DATA_LENGTH	#MDL#
+INDEX_LENGTH	#IL#
+DATA_FREE	#DF#
+AUTO_INCREMENT	NULL
+CREATE_TIME	#CRT#
+UPDATE_TIME	#UT#
+CHECK_TIME	#CT#
+TABLE_COLLATION	utf8_general_ci
+CHECKSUM	NULL
+CREATE_OPTIONS	#CO#
+TABLE_COMMENT	#TC#
+user_comment	Relay Log Information
+Separator	-----------------------------------------------------
+TABLE_CATALOG	NULL
+TABLE_SCHEMA	mysql
 TABLE_NAME	slow_log
 TABLE_TYPE	BASE TABLE
 ENGINE	CSV
@@ -904,6 +950,52 @@ user_comment	MySQL Foreign Servers table
 Separator	-----------------------------------------------------
 TABLE_CATALOG	def
 TABLE_SCHEMA	mysql
+TABLE_NAME	slave_master_info
+TABLE_TYPE	BASE TABLE
+ENGINE	MyISAM
+VERSION	10
+ROW_FORMAT	Dynamic
+TABLE_ROWS	#TBLR#
+AVG_ROW_LENGTH	#ARL#
+DATA_LENGTH	#DL#
+MAX_DATA_LENGTH	#MDL#
+INDEX_LENGTH	#IL#
+DATA_FREE	#DF#
+AUTO_INCREMENT	NULL
+CREATE_TIME	#CRT#
+UPDATE_TIME	#UT#
+CHECK_TIME	#CT#
+TABLE_COLLATION	utf8_general_ci
+CHECKSUM	NULL
+CREATE_OPTIONS	#CO#
+TABLE_COMMENT	#TC#
+user_comment	Master Information
+Separator	-----------------------------------------------------
+TABLE_CATALOG	NULL
+TABLE_SCHEMA	mysql
+TABLE_NAME	slave_relay_log_info
+TABLE_TYPE	BASE TABLE
+ENGINE	MyISAM
+VERSION	10
+ROW_FORMAT	Dynamic
+TABLE_ROWS	#TBLR#
+AVG_ROW_LENGTH	#ARL#
+DATA_LENGTH	#DL#
+MAX_DATA_LENGTH	#MDL#
+INDEX_LENGTH	#IL#
+DATA_FREE	#DF#
+AUTO_INCREMENT	NULL
+CREATE_TIME	#CRT#
+UPDATE_TIME	#UT#
+CHECK_TIME	#CT#
+TABLE_COLLATION	utf8_general_ci
+CHECKSUM	NULL
+CREATE_OPTIONS	#CO#
+TABLE_COMMENT	#TC#
+user_comment	Relay Log Information
+Separator	-----------------------------------------------------
+TABLE_CATALOG	NULL
+TABLE_SCHEMA	mysql
 TABLE_NAME	slow_log
 TABLE_TYPE	BASE TABLE
 ENGINE	CSV

=== modified file 'mysql-test/suite/ndb_team/r/rpl_ndb_mix_innodb.result'
--- a/mysql-test/suite/ndb_team/r/rpl_ndb_mix_innodb.result	2010-05-24 13:54:08 +0000
+++ b/mysql-test/suite/ndb_team/r/rpl_ndb_mix_innodb.result	2010-06-27 01:42:41 +0000
@@ -103,9 +103,8 @@ from mysql.ndb_apply_status;
 @log_name:=log_name	@start_pos:=start_pos	@end_pos:=end_pos
 <log_name>	<start_pos>	<end_pos>
 
-show binlog events in 'master-bin.000001'  from <start_pos> limit 9,1;
+show binlog events in 'master-bin.000001'  from <start_pos> limit <end_pos>,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	#	Xid	1	<end_pos>	COMMIT /* XID */
 
 ** Test 3 **
 
@@ -116,9 +115,8 @@ from mysql.ndb_apply_status;
 @log_name:=log_name	@start_pos:=start_pos	@end_pos:=end_pos
 <log_name>	<start_pos>	<end_pos>
 
-show binlog events in 'master-bin.000002'  from <start_pos> limit 9,1;
+show binlog events in 'master-bin.000002'  from <start_pos> limit <end_pos>,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000002	#	Xid	1	<end_pos>	COMMIT /* XID */
 
 ** Test 4 **
 
@@ -134,9 +132,8 @@ from mysql.ndb_apply_status;
 @log_name:=log_name	@start_pos:=start_pos	@end_pos:=end_pos
 <log_name>	<start_pos>	<end_pos>
 
-show binlog events in 'master-bin.000001'  from <start_pos> limit 9,1;
+show binlog events in 'master-bin.000001'  from <start_pos> limit <end_pos>,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	#	Xid	1	<end_pos>	COMMIT /* XID */
 
 *** DUMP MASTER & SLAVE FOR COMPARE ********
 DROP DATABASE tpcb;

=== modified file 'mysql-test/suite/rpl/r/rpl_flushlog_loop.result'
--- a/mysql-test/suite/rpl/r/rpl_flushlog_loop.result	2010-07-27 14:04:13 +0000
+++ b/mysql-test/suite/rpl/r/rpl_flushlog_loop.result	2010-08-05 17:45:25 +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	FILE
 relay_log_purge	ON
 relay_log_recovery	OFF
 relay_log_space_limit	0

=== modified file 'mysql-test/suite/rpl/r/rpl_rotate_logs.result'
--- a/mysql-test/suite/rpl/r/rpl_rotate_logs.result	2010-07-27 14:04:13 +0000
+++ b/mysql-test/suite/rpl/r/rpl_rotate_logs.result	2010-08-05 17:45:25 +0000
@@ -1,5 +1,7 @@
 drop table if exists t1, t2, t3, t4;
 drop table if exists t1, t2, t3, t4;
+CALL mtr.add_suppression("Failed to open the existing info file");
+CALL mtr.add_suppression("Error while reading from master info file");
 start slave;
 Got one of the listed errors
 start slave;

=== modified file 'mysql-test/suite/rpl/r/rpl_stm_auto_increment_bug33029.result'
--- a/mysql-test/suite/rpl/r/rpl_stm_auto_increment_bug33029.result	2010-08-10 11:58:46 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stm_auto_increment_bug33029.result	2010-10-08 14:23:55 +0000
@@ -4,8 +4,12 @@ reset master;
 reset slave;
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
 start slave;
-CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
-CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP TRIGGER IF EXISTS tr1;
+DROP FUNCTION IF EXISTS f1;
 CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY);
 CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY);
 CREATE PROCEDURE p1()

=== modified file 'mysql-test/suite/rpl/t/rpl_rotate_logs.test'
--- a/mysql-test/suite/rpl/t/rpl_rotate_logs.test	2010-06-19 09:24:34 +0000
+++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.test	2010-10-08 16:11:32 +0000
@@ -1,6 +1,5 @@
 # This test uses chmod, can't be run with root permissions
 -- source include/not_as_root.inc
-
 -- source include/have_log_bin.inc
 
 #
@@ -32,6 +31,11 @@ connection slave;
 drop table if exists t1, t2, t3, t4;
 --enable_warnings
 
+--disable_result_log
+CALL mtr.add_suppression("Failed to open the existing info file");
+CALL mtr.add_suppression("Error while reading from master info file");
+--enable_result_log
+
 # START SLAVE will fail because it can't read the file (mode 000)
 # (system error 13)
 --replace_result $MYSQL_TEST_DIR TESTDIR

=== modified file 'mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test'
--- a/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test	2010-04-28 12:47:49 +0000
+++ b/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test	2010-10-08 14:23:55 +0000
@@ -11,11 +11,20 @@
 source include/have_binlog_format_statement.inc;
 source include/master-slave.inc;
 
-CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
---connection slave
-CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP TRIGGER IF EXISTS tr1;
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
+
+--sync_slave_with_master
 --connection master
 
+
 CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY);
 CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY);
 

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_stm_innodb.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_stm_innodb.result	2010-05-24 13:54:08 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_stm_innodb.result	2010-06-27 01:42:41 +0000
@@ -104,9 +104,8 @@ from mysql.ndb_apply_status;
 @log_name:=log_name	@start_pos:=start_pos	@end_pos:=end_pos
 <log_name>	<start_pos>	<end_pos>
 
-show binlog events in 'master-bin.000001'  from <start_pos> limit 6,1;
+show binlog events in 'master-bin.000001'  from <start_pos> limit <end_pos>,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	#	Xid	1	<end_pos>	COMMIT /* XID */
 
 ** Test 3 **
 
@@ -117,9 +116,8 @@ from mysql.ndb_apply_status;
 @log_name:=log_name	@start_pos:=start_pos	@end_pos:=end_pos
 <log_name>	<start_pos>	<end_pos>
 
-show binlog events in 'master-bin.000002'  from <start_pos> limit 6,1;
+show binlog events in 'master-bin.000002'  from <start_pos> limit <end_pos>,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000002	#	Xid	1	<end_pos>	COMMIT /* XID */
 
 ** Test 4 **
 
@@ -135,9 +133,8 @@ from mysql.ndb_apply_status;
 @log_name:=log_name	@start_pos:=start_pos	@end_pos:=end_pos
 <log_name>	<start_pos>	<end_pos>
 
-show binlog events in 'master-bin.000001'  from <start_pos> limit 6,1;
+show binlog events in 'master-bin.000001'  from <start_pos> limit <end_pos>,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	#	Xid	1	<end_pos>	COMMIT /* XID */
 
 *** DUMP MASTER & SLAVE FOR COMPARE ********
 DROP DATABASE tpcb;

=== added file 'mysql-test/suite/sys_vars/r/master_info_repository_basic.result'
--- a/mysql-test/suite/sys_vars/r/master_info_repository_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/master_info_repository_basic.result	2010-07-06 22:01:07 +0000
@@ -0,0 +1,44 @@
+'#---------------------BS_STVARS_002_01----------------------#'
+SELECT @@GLOBAL.master_info_repository;
+@@GLOBAL.master_info_repository
+FILE
+SELECT COUNT(@@GLOBAL.master_info_repository);
+COUNT(@@GLOBAL.master_info_repository)
+1
+1 Expected
+SELECT COUNT(@@SESSION.master_info_repository);
+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
+'#---------------------BS_STVARS_002_03----------------------#'
+SELECT @@GLOBAL.master_info_repository = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='master_info_repository';
+@@GLOBAL.master_info_repository = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.master_info_repository);
+COUNT(@@GLOBAL.master_info_repository)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='master_info_repository';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------BS_STVARS_002_05----------------------#'
+SELECT COUNT(@@master_info_repository);
+COUNT(@@master_info_repository)
+1
+1 Expected
+SELECT COUNT(@@local.master_info_repository);
+ERROR HY000: Variable 'master_info_repository' is a GLOBAL variable
+SELECT COUNT(@@GLOBAL.master_info_repository);
+COUNT(@@GLOBAL.master_info_repository)
+1
+1 Expected

=== added 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	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/relay_log_info_repository_basic.result	2010-07-06 22:01:07 +0000
@@ -0,0 +1,44 @@
+'#---------------------BS_STVARS_002_01----------------------#'
+SELECT @@GLOBAL.relay_log_info_repository;
+@@GLOBAL.relay_log_info_repository
+FILE
+SELECT COUNT(@@GLOBAL.relay_log_info_repository);
+COUNT(@@GLOBAL.relay_log_info_repository)
+1
+1 Expected
+SELECT COUNT(@@SESSION.relay_log_info_repository);
+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
+'#---------------------BS_STVARS_002_03----------------------#'
+SELECT @@GLOBAL.relay_log_info_repository = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='relay_log_info_repository';
+@@GLOBAL.relay_log_info_repository = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.relay_log_info_repository);
+COUNT(@@GLOBAL.relay_log_info_repository)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='relay_log_info_repository';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------BS_STVARS_002_05----------------------#'
+SELECT COUNT(@@relay_log_info_repository);
+COUNT(@@relay_log_info_repository)
+1
+1 Expected
+SELECT COUNT(@@local.relay_log_info_repository);
+ERROR HY000: Variable 'relay_log_info_repository' is a GLOBAL variable
+SELECT COUNT(@@GLOBAL.relay_log_info_repository);
+COUNT(@@GLOBAL.relay_log_info_repository)
+1
+1 Expected

=== added file 'mysql-test/suite/sys_vars/t/master_info_repository_basic.test'
--- a/mysql-test/suite/sys_vars/t/master_info_repository_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/master_info_repository_basic.test	2010-10-08 16:11:32 +0000
@@ -0,0 +1,75 @@
+############## mysql-test\t\master_info_repository_basic.test #################
+#                                                                             #
+# Variable Name: master_info_repository                                       #
+# Scope: Global                                                               #
+# Access Type: Static                                                         #
+# Data Type: enumeration                                                      #
+#                                                                             #
+#                                                                             #
+# Creation Date: 2010-06-19                                                   #
+# Author : Alfranio Correia                                                   #
+#                                                                             #
+#                                                                             #
+# Description:Test Cases of System Variable master_info_repository            #
+#             that checks the behavior of this variable in the following ways #
+#              * Value Check                                                  #
+#              * Scope Check                                                  #
+#                                                                             #
+# Reference:                                                                  #
+#    http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html      #
+#                                                                             #
+###############################################################################
+
+--echo '#---------------------BS_STVARS_002_01----------------------#'
+####################################################################
+#   Displaying default value                                       #
+####################################################################
+SELECT @@GLOBAL.master_info_repository;
+
+SELECT COUNT(@@GLOBAL.master_info_repository);
+--echo 1 Expected
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@SESSION.master_info_repository);
+
+--echo '#---------------------BS_STVARS_002_02----------------------#'
+####################################################################
+#   Check if Value can set                                         #
+####################################################################
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@GLOBAL.master_info_repository= "TABLE";
+
+SELECT @@GLOBAL.master_info_repository;
+
+
+--echo '#---------------------BS_STVARS_002_03----------------------#'
+#################################################################
+# Check if the value in GLOBAL Table matches value in variable  #
+#################################################################
+SELECT @@GLOBAL.master_info_repository = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='master_info_repository';
+--echo 1 Expected
+
+SELECT COUNT(@@GLOBAL.master_info_repository);
+--echo 1 Expected
+
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='master_info_repository';
+--echo 1 Expected
+
+
+--echo '#---------------------BS_STVARS_002_05----------------------#'
+################################################################################
+#   Check if master_info_repository can be accessed with and without @@ sign   #
+################################################################################
+
+SELECT COUNT(@@master_info_repository);
+--echo 1 Expected
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@local.master_info_repository);
+
+SELECT COUNT(@@GLOBAL.master_info_repository);
+--echo 1 Expected

=== added 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	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/relay_log_info_repository_basic.test	2010-10-08 16:11:32 +0000
@@ -0,0 +1,74 @@
+############# mysql-test\t\relay_log_info_repository_basic.test ###############
+#                                                                             #
+# Variable Name: relay_log_info_repository                                    #
+# Scope: Global                                                               #
+# Access Type: Static                                                         #
+# Data Type: enumeration                                                      #
+#                                                                             #
+#                                                                             #
+# Creation Date: 2010-06-19                                                   #
+# Author : Alfranio Correia                                                   #
+#                                                                             #
+#                                                                             #
+# Description:Test Cases of System Variable relay_log_info_repository         #
+#             that checks the behavior of this variable in the following ways #
+#              * Value Check                                                  #
+#              * Scope Check                                                  #
+#                                                                             #
+# Reference:                                                                  #
+#    http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html      #
+#                                                                             #
+###############################################################################
+--echo '#---------------------BS_STVARS_002_01----------------------#'
+####################################################################
+#   Displaying default value                                       #
+####################################################################
+SELECT @@GLOBAL.relay_log_info_repository;
+
+SELECT COUNT(@@GLOBAL.relay_log_info_repository);
+--echo 1 Expected
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@SESSION.relay_log_info_repository);
+
+--echo '#---------------------BS_STVARS_002_02----------------------#'
+####################################################################
+#   Check if Value can set                                         #
+####################################################################
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@GLOBAL.relay_log_info_repository= "TABLE";
+
+SELECT @@GLOBAL.relay_log_info_repository;
+
+
+--echo '#---------------------BS_STVARS_002_03----------------------#'
+#################################################################
+# Check if the value in GLOBAL Table matches value in variable  #
+#################################################################
+SELECT @@GLOBAL.relay_log_info_repository = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='relay_log_info_repository';
+--echo 1 Expected
+
+SELECT COUNT(@@GLOBAL.relay_log_info_repository);
+--echo 1 Expected
+
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='relay_log_info_repository';
+--echo 1 Expected
+
+
+--echo '#---------------------BS_STVARS_002_05----------------------#'
+################################################################################
+# Check if relay_log_info_repository can be accessed with and without @@ sign  #
+################################################################################
+
+SELECT COUNT(@@relay_log_info_repository);
+--echo 1 Expected
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@local.relay_log_info_repository);
+
+SELECT COUNT(@@GLOBAL.relay_log_info_repository);
+--echo 1 Expected

=== modified file 'mysql-test/t/mysql.test'
--- a/mysql-test/t/mysql.test	2010-08-25 08:17:15 +0000
+++ b/mysql-test/t/mysql.test	2010-10-20 10:50:50 +0000
@@ -427,3 +427,10 @@ drop table t1;
 
 --echo
 --echo End of tests
+
+
+#
+# WL#3126 TCP address binding for mysql client library;
+# - running mysql --protocol=tcp --bind-address=127.0.0.1
+#
+--exec $MYSQL --protocol=tcp --bind-address=127.0.0.1 -e "select 1 as Connected"

=== modified file 'mysql-test/t/mysqladmin.test'
--- a/mysql-test/t/mysqladmin.test	2009-10-21 12:59:47 +0000
+++ b/mysql-test/t/mysqladmin.test	2010-09-30 10:28:49 +0000
@@ -33,3 +33,9 @@ EOF
 --exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf --default-character-set=latin1 -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= ping 2>&1
 
 remove_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf;
+
+#
+# WL#3126 TCP address binding for mysql client library;
+# - running mysqladmin --protcol=tcp --bind-address=127.0.0.1
+#
+--exec $MYSQLADMIN --no-defaults --protocol=tcp --bind-address=127.0.0.1 --host=127.0.0.1 -P $MASTER_MYPORT -u root ping 2>&1

=== modified file 'mysql-test/t/mysqlbinlog.test'
--- a/mysql-test/t/mysqlbinlog.test	2010-09-01 02:51:08 +0000
+++ b/mysql-test/t/mysqlbinlog.test	2010-10-18 12:18:18 +0000
@@ -487,3 +487,10 @@ diff_files $MYSQLTEST_VARDIR/tmp/mysqlbi
 # Cleanup for this part of test
 remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn.empty;
 remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn;
+
+#
+# WL#3126 TCP address binding for mysql client library;
+# - running mysqlbinlog --protocol=tcp --bind-address=127.0.0.1
+#
+--exec $MYSQL_BINLOG --short-form --read-from-remote-server --protocol=tcp --bind-address=127.0.0.1 master-bin.000001 > /dev/null
+

=== modified file 'mysql-test/t/mysqlcheck.test'
--- a/mysql-test/t/mysqlcheck.test	2009-10-21 12:59:47 +0000
+++ b/mysql-test/t/mysqlcheck.test	2010-09-30 10:28:49 +0000
@@ -211,4 +211,11 @@ create table `#mysql50#t1-1` (a int);
 show tables like 't1-1';
 drop table `t1-1`;
 
+#
+# WL#3126 TCP address binding for mysql client library;
+# - running mysqlcheck --protcol=tcp --bind-address=127.0.0.1
+#
+--exec $MYSQL_CHECK --protocol=tcp --bind-address=127.0.0.1 --databases test
+
 --echo End of 5.1 tests
+

=== modified file 'mysql-test/t/mysqldump.test'
--- a/mysql-test/t/mysqldump.test	2010-07-05 11:57:49 +0000
+++ b/mysql-test/t/mysqldump.test	2010-10-18 12:18:18 +0000
@@ -2168,6 +2168,18 @@ SELECT LENGTH(a) FROM t2;
 
 DROP TABLE t1, t2;
 
+#
+# WL#3126 TCP address binding for mysql client library;
+# - running mysqldump --protocol=tcp --bind-address=127.0.0.1
+# - running mysqlimport --protocol=tcp --bind-address=127.0.0.1
+#
+create table t1 (first char(28) , last varchar(37));
+insert into t1 values ("Magnus", "Blåudd");
+--exec $MYSQL_DUMP --protocol=tcp --bind-address=127.0.0.1 --tab=$MYSQLTEST_VARDIR/tmp/ test
+truncate table t1;
+--exec $MYSQL_IMPORT --protocol=tcp --bind-address=127.0.0.1 test $MYSQLTEST_VARDIR/tmp/t1.txt
+drop table t1;
+
 ###########################################################################
 --echo #
 --echo # End of 5.1 tests

=== modified file 'mysql-test/t/mysqlshow.test'
--- a/mysql-test/t/mysqlshow.test	2009-08-07 20:04:53 +0000
+++ b/mysql-test/t/mysqlshow.test	2010-09-30 10:28:49 +0000
@@ -35,4 +35,10 @@ DROP TABLE t1, t2;
 --exec $MYSQL_SHOW INFORMATION_SCHEMA
 --exec $MYSQL_SHOW inf_rmation_schema
 
+#
+# WL#3126 TCP address binding for mysql client library;
+# - running mysqlshow --protcol=tcp --bind-address=127.0.0.1
+#
+--exec $MYSQL_SHOW --protocol=tcp --bind-address=127.0.0.1 test
+
 --echo End of 5.0 tests

=== modified file 'mysys/mf_iocache2.c'
--- a/mysys/mf_iocache2.c	2010-07-23 20:16:29 +0000
+++ b/mysys/mf_iocache2.c	2010-10-14 17:20:07 +0000
@@ -418,7 +418,7 @@ process_flags:
     {
       register int iarg;
       size_t length2;
-      char buff[17];
+      char buff[32];
 
       iarg = va_arg(args, int);
       if (*fmt == 'd')
@@ -449,7 +449,7 @@ process_flags:
     {
       register long iarg;
       size_t length2;
-      char buff[17];
+      char buff[32];
 
       iarg = va_arg(args, long);
       if (*++fmt == 'd')

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2010-07-15 11:41:37 +0000
+++ b/sql-common/client.c	2010-10-19 09:54:17 +0000
@@ -1145,7 +1145,7 @@ static const char *default_options[]=
   "connect-timeout", "local-infile", "disable-local-infile",
   "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
   "multi-results", "multi-statements", "multi-queries", "secure-auth",
-  "report-data-truncation",
+  "report-data-truncation", "bind-address",
   NullS
 };
 
@@ -1354,6 +1354,10 @@ void mysql_read_default_options(struct s
         case 31: /* report-data-truncation */
           options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
           break;
+	case 32: /* bind-address */
+          my_free(options->ci.bind_address);
+          options->ci.bind_address= my_strdup(opt_arg, MYF(MY_WME));
+          break;
 	default:
 	  DBUG_PRINT("warning",("unknown option: %s",option[0]));
 	}
@@ -2429,11 +2433,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       (!mysql->options.protocol ||
        mysql->options.protocol == MYSQL_PROTOCOL_TCP))
   {
-    struct addrinfo *res_lst, hints, *t_res;
+    struct addrinfo *res_lst, *client_bind_ai_lst= NULL, hints, *t_res;
     int gai_errno;
     char port_buf[NI_MAXSERV];
     my_socket sock= SOCKET_ERROR;
-    int saved_error= 0, status= -1;
+    int saved_error= 0, status= -1, bind_result= 0;
 
     unix_socket=0;				/* This is not used */
 
@@ -2478,9 +2482,35 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       goto error;
     }
 
+    /* Get address info for client bind name if it is provided */
+    if (mysql->options.ci.bind_address)
+    {
+      int bind_gai_errno= 0;
+
+      DBUG_PRINT("info",("Resolving addresses for client bind: '%s'",
+                         mysql->options.ci.bind_address));
+      /* Lookup address info for name */
+      bind_gai_errno= getaddrinfo(mysql->options.ci.bind_address, 0,
+                                  &hints, &client_bind_ai_lst);
+      if (bind_gai_errno)
+      {
+        DBUG_PRINT("info",("client bind getaddrinfo error %d", bind_gai_errno));
+        set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
+                                 ER(CR_UNKNOWN_HOST),
+                                 mysql->options.ci.bind_address,
+                                 bind_gai_errno);
+
+        freeaddrinfo(res_lst);
+        goto error;
+      }
+      DBUG_PRINT("info", ("  got address info for client bind name"));
+    }
+
     /*
       A hostname might map to multiple IP addresses (IPv4/IPv6). Go over the
       list of IP addresses until a successful connection can be established.
+      For each IP address, attempt to bind the socket to each client address
+      for the client-side bind hostname until the bind is successful.
     */
     DBUG_PRINT("info", ("Try connect on all addresses for host."));
     for (t_res= res_lst; t_res; t_res= t_res->ai_next)
@@ -2488,13 +2518,57 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       DBUG_PRINT("info", ("Create socket, family: %d  type: %d  proto: %d",
                           t_res->ai_family, t_res->ai_socktype,
                           t_res->ai_protocol));
+
       sock= socket(t_res->ai_family, t_res->ai_socktype, t_res->ai_protocol);
       if (sock == SOCKET_ERROR)
       {
+        DBUG_PRINT("info", ("Socket created was invalid"));
+        /* Try next address if there is one */
         saved_error= socket_errno;
         continue;
       }
 
+      if (client_bind_ai_lst)
+      {
+        struct addrinfo* curr_bind_ai= NULL;
+        DBUG_PRINT("info", ("Attempting to bind socket to bind address(es)"));
+
+        /*
+           We'll attempt to bind to each of the addresses returned, until
+           we find one that works.
+           If none works, we'll try the next destination host address
+           (if any)
+        */
+        curr_bind_ai= client_bind_ai_lst;
+
+        while (curr_bind_ai != NULL)
+        {
+          /* Attempt to bind the socket to the given address */
+          bind_result= bind(sock,
+                            curr_bind_ai->ai_addr,
+                            curr_bind_ai->ai_addrlen);
+          if (!bind_result)
+            break;   /* Success */
+
+          DBUG_PRINT("info", ("bind failed, attempting another bind address"));
+          /* Problem with the bind, move to next address if present */
+          curr_bind_ai= curr_bind_ai->ai_next;
+        }
+
+        if (bind_result)
+        {
+          /*
+            Could not bind to any client-side address with this destination
+             Try the next destination address (if any)
+          */
+          DBUG_PRINT("info", ("All bind attempts with this address failed"));
+          saved_error= socket_errno;
+          closesocket(sock);
+          continue;
+        }
+        DBUG_PRINT("info", ("Successfully bound client side of socket"));
+      }
+
       DBUG_PRINT("info", ("Connect socket"));
       status= my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
                          mysql->options.connect_timeout);
@@ -2520,6 +2594,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
                 sock, status, saved_error));
 
     freeaddrinfo(res_lst);
+    if (client_bind_ai_lst)
+      freeaddrinfo(client_bind_ai_lst);
 
     if (sock == SOCKET_ERROR)
     {
@@ -3036,7 +3112,8 @@ static void mysql_close_free_options(MYS
   my_free(mysql->options.my_cnf_group);
   my_free(mysql->options.charset_dir);
   my_free(mysql->options.charset_name);
-  my_free(mysql->options.client_ip);
+  my_free(mysql->options.ci.client_ip);
+  /* ci.bind_adress is union with client_ip, already freed above */
   if (mysql->options.init_commands)
   {
     DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
@@ -3511,7 +3588,7 @@ mysql_options(MYSQL *mysql,enum mysql_op
     mysql->options.methods_to_use= option;
     break;
   case MYSQL_SET_CLIENT_IP:
-    mysql->options.client_ip= my_strdup(arg, MYF(MY_WME));
+    mysql->options.ci.client_ip= my_strdup(arg, MYF(MY_WME));
     break;
   case MYSQL_SECURE_AUTH:
     mysql->options.secure_auth= *(my_bool *) arg;
@@ -3522,6 +3599,10 @@ mysql_options(MYSQL *mysql,enum mysql_op
   case MYSQL_OPT_RECONNECT:
     mysql->reconnect= *(my_bool *) arg;
     break;
+  case MYSQL_OPT_BIND:
+    my_free(mysql->options.ci.bind_address);
+    mysql->options.ci.bind_address= my_strdup(arg, MYF(MY_WME));
+    break;
   case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
     if (*(my_bool*) arg)
       mysql->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2010-09-28 15:30:47 +0000
+++ b/sql/CMakeLists.txt	2010-10-08 16:11:32 +0000
@@ -102,7 +102,9 @@ SET (MASTER_SOURCE rpl_master.cc)
 ADD_DEPENDENCIES(rpl GenError)
 ADD_LIBRARY(master ${MASTER_SOURCE})
 ADD_DEPENDENCIES(master GenError)
-SET (SLAVE_SOURCE rpl_slave.cc rpl_reporting.cc rpl_mi.cc rpl_rli.cc)
+SET (SLAVE_SOURCE rpl_slave.cc rpl_reporting.cc rpl_mi.cc rpl_rli.cc
+		  rpl_info_handler.cc rpl_info_file.cc rpl_info.cc
+                  rpl_info_factory.cc server_ids.h)
 ADD_LIBRARY(slave ${SLAVE_SOURCE})
 ADD_DEPENDENCIES(slave GenError)
 ADD_LIBRARY(sqlgunitlib mdl.cc sql_list.cc sql_string.cc thr_malloc.cc)

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2010-08-20 09:15:16 +0000
+++ b/sql/Makefile.am	2010-10-08 16:11:32 +0000
@@ -107,7 +107,10 @@ noinst_HEADERS =	item.h item_func.h item
 			debug_sync.h \
 			opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \
 			rpl_reporting.h sql_locale.h sql_parse.h \
-			log.h sql_show.h rpl_rli.h rpl_mi.h \
+			rpl_info_handler.h \
+			log.h sql_show.h rpl_info.h rpl_info_file.h \
+			rpl_rli.h rpl_mi.h \
+			rpl_info_factory.h server_ids.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_base.h \
 			sql_table.h key.h lock.h thr_malloc.h strfunc.h \
@@ -188,8 +191,9 @@ libbinlog_la_SOURCES =	log_event.cc log_
 			rpl_utility.cc sql_binlog.cc rpl_injector.cc
 librpl_la_SOURCES    =  rpl_handler.cc rpl_tblmap.cc
 libmaster_la_SOURCES =	rpl_master.cc
-libslave_la_SOURCES = 	rpl_slave.cc rpl_reporting.cc rpl_rli.cc rpl_mi.cc
-
+libslave_la_SOURCES = 	rpl_slave.cc rpl_reporting.cc rpl_rli.cc rpl_mi.cc \
+			rpl_info.cc rpl_info_factory.cc rpl_info_file.cc \
+			rpl_info_handler.cc
 libndb_la_CPPFLAGS=	@ndbcluster_includes@
 libndb_la_SOURCES=	ha_ndbcluster.cc \
 			ha_ndbcluster_binlog.cc \

=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2010-10-03 23:42:39 +0000
+++ b/sql/binlog.cc	2010-10-08 14:35:24 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -22,6 +22,7 @@
 #include "rpl_rli.h"
 #include "sql_plugin.h"
 #include "rpl_handler.h"
+#include "rpl_info_factory.h"
 
 #define MY_OFF_T_UNDEF (~(my_off_t)0UL)
 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
@@ -2097,25 +2098,25 @@ int MYSQL_BIN_LOG::purge_first_log(Relay
 
   DBUG_ASSERT(is_open());
   DBUG_ASSERT(rli->slave_running == 1);
-  DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
+  DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->get_event_relay_log_name()));
 
   mysql_mutex_assert_owner(&rli->data_lock);
 
   mysql_mutex_lock(&LOCK_index);
-  to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0));
+  to_purge_if_included= my_strdup(rli->get_group_relay_log_name(), MYF(0));
 
   /*
     Read the next log file name from the index file and pass it back to
     the caller.
   */
-  if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) || 
+  if((error=find_log_pos(&rli->linfo, rli->get_event_relay_log_name(), 0)) || 
      (error=find_next_log(&rli->linfo, 0)))
   {
     char buff[22];
     sql_print_error("next log error: %d  offset: %s  log: %s included: %d",
                     error,
                     llstr(rli->linfo.index_file_offset,buff),
-                    rli->event_relay_log_name,
+                    rli->get_event_relay_log_name(),
                     included);
     goto err;
   }
@@ -2123,9 +2124,8 @@ int MYSQL_BIN_LOG::purge_first_log(Relay
   /*
     Reset rli's coordinates to the current log.
   */
-  rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
-  strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
-	  sizeof(rli->event_relay_log_name)-1);
+  rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);
+  rli->set_event_relay_log_name(rli->linfo.log_file_name);
 
   /*
     If we removed the rli->group_relay_log_name file,
@@ -2134,14 +2134,13 @@ int MYSQL_BIN_LOG::purge_first_log(Relay
   */
   if (included)
   {
-    rli->group_relay_log_pos = BIN_LOG_HEADER_SIZE;
-    strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
-            sizeof(rli->group_relay_log_name)-1);
+    rli->set_group_relay_log_pos(BIN_LOG_HEADER_SIZE);
+    rli->set_group_relay_log_name(rli->linfo.log_file_name);
     rli->notify_group_relay_log_name_update();
   }
 
   /* Store where we are in the new file for the execution thread */
-  flush_relay_log_info(rli);
+  rli->flush_info(TRUE);
 
   DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_ABORT(););
 
@@ -2163,13 +2162,13 @@ int MYSQL_BIN_LOG::purge_first_log(Relay
    * Need to update the log pos because purge logs has been called 
    * after fetching initially the log pos at the begining of the method.
    */
-  if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)))
+  if((error=find_log_pos(&rli->linfo, rli->get_event_relay_log_name(), 0)))
   {
     char buff[22];
     sql_print_error("next log error: %d  offset: %s  log: %s included: %d",
                     error,
                     llstr(rli->linfo.index_file_offset,buff),
-                    rli->group_relay_log_name,
+                    rli->get_group_relay_log_name(),
                     included);
     goto err;
   }
@@ -2890,7 +2889,7 @@ err:
   DBUG_RETURN(error);
 }
 
-bool MYSQL_BIN_LOG::flush_and_sync(bool *synced)
+bool MYSQL_BIN_LOG::flush_and_sync(bool *synced, const bool force)
 {
   int err=0, fd=log_file.file;
   if (synced)
@@ -2899,7 +2898,8 @@ bool MYSQL_BIN_LOG::flush_and_sync(bool 
   if (flush_io_cache(&log_file))
     return 1;
   uint sync_period= get_sync_period();
-  if (sync_period && ++sync_counter >= sync_period)
+  if (force || 
+      (sync_period && ++sync_counter >= sync_period))
   {
     sync_counter= 0;
     err= mysql_file_sync(fd, MYF(MY_WME));

=== modified file 'sql/binlog.h'
--- a/sql/binlog.h	2010-09-17 13:22:22 +0000
+++ b/sql/binlog.h	2010-10-04 10:16:31 +0000
@@ -194,11 +194,12 @@ public:
      be set to 1, otherwise 0.
 
      @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
+     @param[in] force if TRUE, ignores the 'sync_binlog' and synchronizes the file.
 
      @retval 0 Success
      @retval other Failure
   */
-  bool flush_and_sync(bool *synced);
+  bool flush_and_sync(bool *synced, const bool force=FALSE);
   int purge_logs(const char *to_log, bool included,
                  bool need_mutex, bool need_update_threads,
                  ulonglong *decrease_log_space);

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2010-08-20 09:15:16 +0000
+++ b/sql/ha_ndbcluster.cc	2010-09-06 11:10:01 +0000
@@ -4587,17 +4587,17 @@ static int ndbcluster_update_apply_statu
   // log_name
   char tmp_buf[FN_REFLEN];
   ndb_pack_varchar(ndbtab->getColumn(2u), tmp_buf,
-                   active_mi->rli.group_master_log_name,
-                   strlen(active_mi->rli.group_master_log_name));
+                   active_mi->rli->get_group_master_log_name(),
+                   strlen(active_mi->rli->get_group_master_log_name()));
   r|= op->setValue(2u, tmp_buf);
   DBUG_ASSERT(r == 0);
   // start_pos
-  r|= op->setValue(3u, (Uint64)active_mi->rli.group_master_log_pos);
+  r|= op->setValue(3u, (Uint64)active_mi->rli->get_group_master_log_pos());
   DBUG_ASSERT(r == 0);
   // end_pos
-  r|= op->setValue(4u, (Uint64)active_mi->rli.group_master_log_pos + 
-                   ((Uint64)active_mi->rli.future_event_relay_log_pos -
-                    (Uint64)active_mi->rli.group_relay_log_pos));
+  r|= op->setValue(4u, (Uint64)active_mi->rli->get_group_master_log_pos() +
+                   ((Uint64)active_mi->rli->get_future_event_relay_log_pos() -
+                    (Uint64)active_mi->rli->get_group_relay_log_pos()));
   DBUG_ASSERT(r == 0);
   return 0;
 }

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2010-08-30 08:40:42 +0000
+++ b/sql/item_func.cc	2010-09-06 11:10:01 +0000
@@ -3685,7 +3685,7 @@ longlong Item_master_pos_wait::val_int()
 #ifdef HAVE_REPLICATION
   longlong pos = (ulong)args[1]->val_int();
   longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
-  if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
+  if ((event_count = active_mi->rli->wait_for_pos(thd, log_name, pos, timeout)) == -2)
   {
     null_value = 1;
     event_count=0;

=== modified file 'sql/lock.cc'
--- a/sql/lock.cc	2010-08-20 08:48:59 +0000
+++ b/sql/lock.cc	2010-10-08 16:11:32 +0000
@@ -146,8 +146,8 @@ lock_tables_check(THD *thd, TABLE **tabl
         or hold any type of lock in a session,
         since this would be a DOS attack.
       */
-      if ((t->reginfo.lock_type >= TL_READ_NO_INSERT)
-          || (thd->lex->sql_command == SQLCOM_LOCK_TABLES))
+      if ((t->reginfo.lock_type >= TL_READ_NO_INSERT
+          || thd->lex->sql_command == SQLCOM_LOCK_TABLES))
       {
         my_error(ER_CANT_LOCK_LOG_TABLE, MYF(0));
         DBUG_RETURN(1);

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-09-28 15:30:47 +0000
+++ b/sql/log.cc	2010-10-17 23:27:40 +0000
@@ -1125,7 +1125,7 @@ bool LOGGER::activate_log_handler(THD* t
 void LOGGER::deactivate_log_handler(THD *thd, uint log_type)
 {
   my_bool *tmp_opt= 0;
-  MYSQL_LOG *file_log;
+  MYSQL_LOG *file_log= NULL;
 
   switch (log_type) {
   case QUERY_LOG_SLOW:

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-10-03 23:42:39 +0000
+++ b/sql/log_event.cc	2010-10-17 23:27:40 +0000
@@ -3227,7 +3227,7 @@ int Query_log_event::do_apply_event(Rela
     END of the current log event (COMMIT). We save it in rli so that InnoDB can
     access it.
   */
-  const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos;
+  const_cast<Relay_log_info*>(rli)->set_future_group_master_log_pos(log_pos);
   DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
 
   clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
@@ -3245,8 +3245,8 @@ int Query_log_event::do_apply_event(Rela
       const_cast<Relay_log_info*>(rli)->report(ERROR_LEVEL, error,
                   "Error in cleaning up after an event preceeding the commit; "
                   "the group log file/position: %s %s",
-                  const_cast<Relay_log_info*>(rli)->group_master_log_name,
-                  llstr(const_cast<Relay_log_info*>(rli)->group_master_log_pos,
+                  const_cast<Relay_log_info*>(rli)->get_group_master_log_name(),
+                  llstr(const_cast<Relay_log_info*>(rli)->get_group_master_log_pos(),
                         llbuff));
     }
     /*
@@ -3571,13 +3571,15 @@ int Query_log_event::do_update_pos(Relay
     after a SET ONE_SHOT, because SET ONE_SHOT should not be separated
     from its following updating query.
   */
+  int ret= 0;
   if (thd->one_shot_set)
   {
     rli->inc_event_relay_log_pos();
-    return 0;
   }
   else
-    return Log_event::do_update_pos(rli);
+    ret= Log_event::do_update_pos(rli);
+
+  return ret;
 }
 
 
@@ -4757,7 +4759,7 @@ void Load_log_event::set_fields(const ch
   @param rli
   @param use_rli_only_for_errors     If set to 1, rli is provided to
                                      Load_log_event::exec_event only for this
-                                     function to have RPL_LOG_NAME and
+                                     function to have rli->get_rpl_log_name and
                                      rli->last_slave_error, both being used by
                                      error reports. rli's position advancing
                                      is skipped (done by the caller which is
@@ -4807,7 +4809,7 @@ int Load_log_event::do_apply_event(NET* 
       Saved for InnoDB, see comment in
       Query_log_event::do_apply_event()
     */
-    const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos;
+    const_cast<Relay_log_info*>(rli)->set_future_group_master_log_pos(log_pos);
     DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
   }
  
@@ -4957,7 +4959,8 @@ int Load_log_event::do_apply_event(NET* 
                           "log position %s in log '%s' produced %ld "
                           "warning(s). Default database: '%s'",
                           (char*) table_name,
-                          llstr(log_pos,llbuff), RPL_LOG_NAME, 
+                          llstr(log_pos,llbuff),
+                          const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
                           (ulong) thd->cuted_fields,
                           print_slave_db_safe(thd->db));
       }
@@ -5209,17 +5212,19 @@ int Rotate_log_event::do_update_pos(Rela
     mysql_mutex_lock(&rli->data_lock);
     DBUG_PRINT("info", ("old group_master_log_name: '%s'  "
                         "old group_master_log_pos: %lu",
-                        rli->group_master_log_name,
-                        (ulong) rli->group_master_log_pos));
-    memcpy(rli->group_master_log_name, new_log_ident, ident_len+1);
+                        rli->get_group_master_log_name(),
+                        (ulong) rli->get_group_master_log_pos()));
+    memcpy((void *)rli->get_group_master_log_name(),
+           new_log_ident, ident_len + 1);
     rli->notify_group_master_log_name_update();
     rli->inc_group_relay_log_pos(pos, TRUE /* skip_lock */);
+
     DBUG_PRINT("info", ("new group_master_log_name: '%s'  "
                         "new group_master_log_pos: %lu",
-                        rli->group_master_log_name,
-                        (ulong) rli->group_master_log_pos));
+                        rli->get_group_master_log_name(),
+                        (ulong) rli->get_group_master_log_pos()));
     mysql_mutex_unlock(&rli->data_lock);
-    flush_relay_log_info(rli);
+    rli->flush_info(TRUE);
     
     /*
       Reset thd->variables.option_bits and sql_mode etc, because this could be the signal of
@@ -5581,14 +5586,15 @@ void Xid_log_event::print(FILE* file, PR
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
 int Xid_log_event::do_apply_event(Relay_log_info const *rli)
 {
-  bool res;
+  int error= 0;
+
   /* For a slave Xid_log_event is COMMIT */
   general_log_print(thd, COM_QUERY,
                     "COMMIT /* implicit, from Xid_log_event */");
-  res= trans_commit(thd); /* Automatically rolls back on error. */
+  error= trans_commit(thd); /* Automatically rolls back on error. */
   thd->mdl_context.release_transactional_locks();
 
-  return res;
+  return error;
 }
 
 Log_event::enum_skip_reason
@@ -6076,7 +6082,7 @@ Slave_log_event::Slave_log_event(THD* th
   mysql_mutex_lock(&mi->data_lock);
   mysql_mutex_lock(&rli->data_lock);
   master_host_len = strlen(mi->host);
-  master_log_len = strlen(rli->group_master_log_name);
+  master_log_len = strlen(rli->get_group_master_log_name());
   // on OOM, just do not initialize the structure and print the error
   if ((mem_pool = (char*)my_malloc(get_data_size() + 1,
                                    MYF(MY_WME))))
@@ -6084,9 +6090,9 @@ Slave_log_event::Slave_log_event(THD* th
     master_host = mem_pool + SL_MASTER_HOST_OFFSET ;
     memcpy(master_host, mi->host, master_host_len + 1);
     master_log = master_host + master_host_len + 1;
-    memcpy(master_log, rli->group_master_log_name, master_log_len + 1);
+    memcpy(master_log, rli->get_group_master_log_name(), master_log_len + 1);
     master_port = mi->port;
-    master_pos = rli->group_master_log_pos;
+    master_pos = rli->get_group_master_log_pos();
     DBUG_PRINT("info", ("master_log: %s  pos: %lu", master_log,
                         (ulong) master_pos));
   }
@@ -6235,7 +6241,7 @@ int Stop_log_event::do_update_pos(Relay_
   else
   {
     rli->inc_group_relay_log_pos(0);
-    flush_relay_log_info(rli);
+    rli->flush_info(TRUE);
   }
   return 0;
 }
@@ -6908,8 +6914,7 @@ int Execute_load_log_event::do_apply_eve
     lev->do_apply_event is the place where the table is loaded (it
     calls mysql_load()).
   */
-
-  const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos;
+  const_cast<Relay_log_info*>(rli)->set_future_group_master_log_pos(log_pos);
   if (lev->do_apply_event(0,rli,1)) 
   {
     /*
@@ -7579,7 +7584,7 @@ int Rows_log_event::do_apply_event(Relay
     do_apply_event(). We still check here to prevent future coding
     errors.
   */
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /*
     If there is no locks taken, this is the first binrow event seen
@@ -7810,7 +7815,8 @@ int Rows_log_event::do_apply_event(Relay
           if (global_system_variables.log_warnings)
             slave_rows_error_report(WARNING_LEVEL, error, rli, thd, table,
                                     get_type_str(),
-                                    RPL_LOG_NAME, (ulong) log_pos);
+                                    const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
+                                    (ulong) log_pos);
           clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
           error= 0;
           if (idempotent_error == 0)
@@ -7864,7 +7870,8 @@ int Rows_log_event::do_apply_event(Relay
       if (global_system_variables.log_warnings)
         slave_rows_error_report(WARNING_LEVEL, error, rli, thd, table,
                                 get_type_str(),
-                                RPL_LOG_NAME, (ulong) log_pos);
+                                const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
+                                (ulong) log_pos);
       clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
       error= 0;
     }
@@ -7875,7 +7882,8 @@ int Rows_log_event::do_apply_event(Relay
   {
     slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table,
                              get_type_str(),
-                             RPL_LOG_NAME, (ulong) log_pos);
+                             const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
+                             (ulong) log_pos);
     /*
       @todo We should probably not call
       reset_current_stmt_binlog_format_row() from here.
@@ -8422,7 +8430,7 @@ int Table_map_log_event::do_apply_event(
   size_t dummy_len;
   void *memory;
   DBUG_ENTER("Table_map_log_event::do_apply_event(Relay_log_info*)");
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /* Step the query id to mark what columns that are actually used. */
   thd->set_query_id(next_query_id());
@@ -8446,7 +8454,7 @@ int Table_map_log_event::do_apply_event(
 
   int error= 0;
 
-  if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
+  if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
       (!rpl_filter->db_ok(table_list->db) ||
        (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
   {
@@ -8811,7 +8819,7 @@ Rows_log_event::write_row(const Relay_lo
   auto_afree_ptr<char> key(NULL);
 
   /* fill table->record[0] with default values */
-  bool abort_on_warnings= (rli->sql_thd->variables.sql_mode &
+  bool abort_on_warnings= (rli->info_thd->variables.sql_mode &
                            (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES));
   if ((error= prepare_record(table, &m_cols,
                              table->file->ht->db_type != DB_TYPE_NDBCLUSTER,
@@ -8831,7 +8839,7 @@ Rows_log_event::write_row(const Relay_lo
        the size of the first row and use that value to initialize
        storage engine for bulk insertion */
     DBUG_ASSERT(!(m_curr_row > m_curr_row_end));
-    ulong estimated_rows;
+    ulong estimated_rows= 0;
     if (m_curr_row < m_curr_row_end)
       estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
     else if (m_curr_row == m_curr_row_end)
@@ -9941,7 +9949,7 @@ Update_rows_log_event::do_exec_row(const
 
   store_record(m_table,record[1]);
 
-  bool abort_on_warnings= (rli->sql_thd->variables.sql_mode &
+  bool abort_on_warnings= (rli->info_thd->variables.sql_mode &
                            (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES));
   m_curr_row= m_curr_row_end;
   /* this also updates m_curr_row_end */
@@ -10215,7 +10223,7 @@ Rows_query_log_event::write_data_body(IO
 int Rows_query_log_event::do_apply_event(Relay_log_info const *rli)
 {
   DBUG_ENTER("Rows_query_log_event::do_apply_event");
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
   /* Set query for writing Rows_query log event into binlog later.*/
   thd->set_query(m_rows_query, (uint32) strlen(m_rows_query));
   DBUG_RETURN(0);

=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc	2010-09-04 00:46:58 +0000
+++ b/sql/log_event_old.cc	2010-10-08 14:35:24 +0000
@@ -1,3 +1,17 @@
+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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 "sql_priv.h"
 #ifndef MYSQL_CLIENT
@@ -53,7 +67,7 @@ Old_rows_log_event::do_apply_event(Old_r
     do_apply_event(). We still check here to prevent future coding
     errors.
   */
-  DBUG_ASSERT(rli->sql_thd == ev_thd);
+  DBUG_ASSERT(rli->info_thd == ev_thd);
 
   /*
     If there is no locks taken, this is the first binrow event seen
@@ -1470,7 +1484,7 @@ int Old_rows_log_event::do_apply_event(R
     do_apply_event(). We still check here to prevent future coding
     errors.
   */
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   /*
     If there is no locks taken, this is the first binrow event seen

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-10-03 23:42:39 +0000
+++ b/sql/mysqld.cc	2010-10-08 14:35:24 +0000
@@ -6218,7 +6218,7 @@ static int show_slave_running(THD *thd, 
   var->value= buff;
   *((my_bool *)buff)= (my_bool) (active_mi && 
                                  active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
-                                 active_mi->rli.slave_running);
+                                 active_mi->rli->slave_running);
   mysql_mutex_unlock(&LOCK_active_mi);
   return 0;
 }
@@ -6234,9 +6234,9 @@ static int show_slave_retried_trans(THD 
   {
     var->type= SHOW_LONG;
     var->value= buff;
-    mysql_mutex_lock(&active_mi->rli.data_lock);
-    *((long *)buff)= (long)active_mi->rli.retried_trans;
-    mysql_mutex_unlock(&active_mi->rli.data_lock);
+    mysql_mutex_lock(&active_mi->rli->data_lock);
+    *((long *)buff)= (long)active_mi->rli->retried_trans;
+    mysql_mutex_unlock(&active_mi->rli->data_lock);
   }
   else
     var->type= SHOW_UNDEF;
@@ -6251,9 +6251,9 @@ static int show_slave_received_heartbeat
   {
     var->type= SHOW_LONGLONG;
     var->value= buff;
-    mysql_mutex_lock(&active_mi->rli.data_lock);
+    mysql_mutex_lock(&active_mi->rli->data_lock);
     *((longlong *)buff)= active_mi->received_heartbeats;
-    mysql_mutex_unlock(&active_mi->rli.data_lock);
+    mysql_mutex_unlock(&active_mi->rli->data_lock);
   }
   else
     var->type= SHOW_UNDEF;

=== modified file 'sql/rpl_handler.cc'
--- a/sql/rpl_handler.cc	2010-07-16 21:00:50 +0000
+++ b/sql/rpl_handler.cc	2010-07-27 14:14:21 +0000
@@ -411,8 +411,8 @@ void Binlog_relay_IO_delegate::init_para
   param->user= mi->user;
   param->host= mi->host;
   param->port= mi->port;
-  param->master_log_name= mi->master_log_name;
-  param->master_log_pos= mi->master_log_pos;
+  param->master_log_name= const_cast<char *>(mi->get_master_log_name());
+  param->master_log_pos= mi->get_master_log_pos();
 }
 
 int Binlog_relay_IO_delegate::thread_start(THD *thd, Master_info *mi)

=== added file 'sql/rpl_info.cc'
--- a/sql/rpl_info.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info.cc	2010-07-27 19:26:54 +0000
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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 <sql_priv.h>
+#include "rpl_info.h"
+
+Rpl_info::Rpl_info(const char* type,
+                   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)
+  :Slave_reporting_capability(type),
+  key_info_run_lock(param_key_info_run_lock),
+  key_info_data_lock(param_key_info_data_lock),
+  key_info_data_cond(param_key_info_data_cond),
+  key_info_start_cond(param_key_info_start_cond),
+  key_info_stop_cond(param_key_info_stop_cond),
+  info_thd(0), inited(0), abort_slave(0),
+  slave_running(0), slave_run_id(0),
+  handler(0)
+{
+  mysql_mutex_init(*key_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST);
+  mysql_mutex_init(*key_info_data_lock,
+                   &data_lock, MY_MUTEX_INIT_FAST);
+  mysql_cond_init(*key_info_data_cond, &data_cond, NULL);
+  mysql_cond_init(*key_info_start_cond, &start_cond, NULL);
+  mysql_cond_init(*key_info_stop_cond, &stop_cond, NULL);
+}
+
+Rpl_info::~Rpl_info()
+{
+  DBUG_ENTER("Rpl_info::~Rpl_info");
+
+  mysql_mutex_destroy(&run_lock);
+  mysql_mutex_destroy(&data_lock);
+  mysql_cond_destroy(&data_cond);
+  mysql_cond_destroy(&start_cond);
+  mysql_cond_destroy(&stop_cond);
+
+  if (handler)
+    delete handler;
+
+  DBUG_VOID_RETURN;
+}
+
+void Rpl_info::set_rpl_info_handler(Rpl_info_handler * param_handler)
+{
+  handler= param_handler;
+}

=== added file 'sql/rpl_info.h'
--- a/sql/rpl_info.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info.h	2010-10-08 14:23:55 +0000
@@ -0,0 +1,107 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef RPL_INFO_H
+#define RPL_INFO_H
+
+#include "sql_priv.h"
+#include "sql_class.h"
+#include "rpl_info_handler.h"
+#include "rpl_reporting.h"
+
+class Rpl_info : public Slave_reporting_capability
+{
+public:
+  /*
+    standard lock acquisition order to avoid deadlocks:
+    run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
+  */
+  mysql_mutex_t data_lock,run_lock;
+  /*
+    start_cond is broadcast when SQL thread is started
+    stop_cond - when stopped
+    data_cond - when data protected by data_lock changes
+  */
+  mysql_cond_t data_cond,start_cond,stop_cond;
+
+  PSI_mutex_key *key_info_run_lock, *key_info_data_lock;
+
+  PSI_mutex_key *key_info_data_cond, *key_info_start_cond, *key_info_stop_cond;
+
+  THD *info_thd;
+
+  bool inited;
+  volatile bool abort_slave;
+  volatile uint slave_running;
+  volatile ulong slave_run_id;
+
+#ifndef DBUG_OFF
+  int events_until_exit;
+#endif
+
+  Rpl_info(const char* type,
+           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);
+  virtual ~Rpl_info();
+
+  int check_info()
+  {
+    return (handler->check_info());
+  }
+
+  int reset_info()
+  {
+    return (handler->reset_info());
+  }
+
+  bool is_transactional()
+  {
+    return (handler->is_transactional());
+  }
+
+  char *get_description_info()
+  {
+    return (handler->get_description_info());
+  }
+
+  bool copy_info(Rpl_info_handler *from, Rpl_info_handler *to)
+  {
+    if (read_info(from) || write_info(to, TRUE))
+      return(TRUE);
+
+    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;
+
+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);
+};
+#endif /* RPL_INFO_H */

=== 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	2010-10-08 16:11:32 +0000
@@ -0,0 +1,179 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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 "sql_priv.h"
+#include "rpl_slave.h"
+#include "rpl_info_factory.h"
+#include "rpl_info_file.h"
+#include "rpl_mi.h"
+#include "rpl_rli.h"
+
+/**
+  Creates both a Master info and a Relay log info repository whose types are
+  defined as parameters.
+
+  @todo Make the repository a pluggable component.
+  
+  @param[in]  mi_option  Type of the Master info repository
+  @param[out] mi         Reference to the Master info repository
+  @param[in]  rli_option Type of the Relay log info repository
+  @param[out] rli        Reference to the Relay log info repository
+
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/ 
+bool Rpl_info_factory::create(uint mi_option, Master_info **mi,
+                              uint rli_option, Relay_log_info **rli)
+{
+  bool error= FALSE;
+
+  DBUG_ENTER("Rpl_info_factory::Rpl_info_factory");
+
+  if ((error= Rpl_info_factory::create_mi(mi_option, mi)))
+  {
+    *mi= NULL;
+    DBUG_RETURN(error);
+  }
+    
+  if ((error= Rpl_info_factory::create_rli(rli_option, relay_log_recovery,
+                                           rli)))
+  {
+    delete *mi;
+    *mi= NULL;
+    DBUG_RETURN(error);
+  }
+
+  /*
+    Setting the cross dependency used all over the code.
+  */
+  (*mi)->set_relay_log_info(*rli);
+  (*rli)->set_master_info(*mi);
+
+  DBUG_RETURN(error); 
+}
+
+/**
+  Creates a Master info repository whose type is defined as a parameter.
+  
+  @param[in]  mi_option  Type of the Master info repository
+  @param[out] mi         Reference to the Master info repository
+
+  The execution fails if a user requests a type but a different type
+  already exists in the system. This is done to avoid that a user
+  accidentally accesses the wrong repository and make the slave go out
+  of sync.
+
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/ 
+bool Rpl_info_factory::create_mi(uint mi_option, Master_info **mi)
+{
+  bool error= TRUE;
+  Rpl_info_file*  mi_file= NULL;
+  const char *msg= "Failed to allocate memory for the master info "
+                   "structure";
+
+  DBUG_ENTER("Rpl_info_factory::Rpl_info_factory");
+
+  *mi= new Master_info(&key_master_info_run_lock, &key_master_info_data_lock,
+                       &key_master_info_data_cond, &key_master_info_start_cond,
+                       &key_master_info_stop_cond);
+  if (!(*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.
+  */
+  mi_file= new Rpl_info_file((*mi)->get_number_info_mi_fields(),
+                             master_info_file);
+  if (!mi_file)
+    goto err;
+
+  DBUG_ASSERT(mi_option == MI_REPOSITORY_FILE); 
+
+  (*mi)->set_rpl_info_handler(mi_file);
+  error= FALSE;
+
+  DBUG_RETURN(error);
+
+err:
+  if (*mi) delete (*mi);
+  if (mi_file) delete mi_file;
+  sql_print_error("%s", msg);
+  DBUG_RETURN(error);
+}
+
+/**
+  Creates a Relay log info repository whose type is defined as a parameter.
+  
+  @param[in]  rli_option        Type of the Relay log info repository
+  @param[in]  is_slave_recovery If the slave should try to start a recovery
+                                process to get consistent relay log files
+  @param[out] rli               Reference to the Relay log info repository
+
+  The execution fails if a user requests a type but a different type
+  already exists in the system. This is done to avoid that a user
+  accidentally accesses the wrong repository and make the slave go out
+  of sync.
+
+  @retval FALSE No error
+  @retval TRUE  Failure
+*/ 
+bool Rpl_info_factory::create_rli(uint rli_option, bool is_slave_recovery,
+                                  Relay_log_info **rli)
+{
+  bool error= TRUE;
+  Rpl_info_file* rli_file= NULL;
+  const char *msg= "Failed to allocate memory for the relay log info "
+                   "structure";
+
+  DBUG_ENTER("Rpl_info_factory::create_rli");
+
+  (*rli)=
+    new Relay_log_info(
+      is_slave_recovery,
+      &key_relay_log_info_run_lock, &key_relay_log_info_data_lock,
+      &key_relay_log_info_data_cond, &key_relay_log_info_start_cond,
+      &key_relay_log_info_stop_cond);
+
+  if (!(*rli))
+    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.
+  */
+  rli_file= new Rpl_info_file((*rli)->get_number_info_rli_fields(),
+                              relay_log_info_file);
+  if (!rli_file)
+    goto err;
+
+  DBUG_ASSERT(rli_option == RLI_REPOSITORY_FILE);
+
+  (*rli)->set_rpl_info_handler(rli_file);
+  error= FALSE; 
+
+  DBUG_RETURN(error);
+
+err:
+  if (*rli) delete (*rli);
+  if (rli_file) delete rli_file;
+  sql_print_error("%s", msg);
+  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	2010-10-08 16:11:32 +0000
@@ -0,0 +1,49 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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_info.h"
+#include "rpl_mi.h"
+#include "rpl_rli.h"
+#include "rpl_info_handler.h"
+
+enum enum_mi_repository
+{
+  MI_REPOSITORY_FILE= 0
+};
+extern ulong opt_mi_repository_id;
+
+enum enum_rli_repository
+{
+  RLI_REPOSITORY_FILE= 0
+};
+extern ulong opt_rli_repository_id;
+
+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 decide_repository(Rpl_info *info, Rpl_info_handler *table,
+                                Rpl_info_handler *file, bool is_table,
+                                const char **msg);
+};
+#endif

=== added file 'sql/rpl_info_file.cc'
--- a/sql/rpl_info_file.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_file.cc	2010-09-13 23:30:43 +0000
@@ -0,0 +1,469 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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 <sql_priv.h>
+#include <my_dir.h>
+#include "rpl_info_file.h"
+#include "mysqld.h"
+#include "log.h"
+
+int init_ulongvar_from_file(ulong* var, IO_CACHE* f, ulong default_val);
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+                          const char *default_val);
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
+int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
+bool init_dynarray_intvar_from_file(char *buffer, char **buffer_act, IO_CACHE* f);
+
+Rpl_info_file::Rpl_info_file(const int nparam, const char* param_info_fname)
+  :Rpl_info_handler(nparam), info_fd(-1)
+{
+  DBUG_ENTER("Rpl_info_file::Rpl_info_file");
+
+  bzero((char*) &info_file, sizeof(info_file));
+  fn_format(info_fname, param_info_fname, mysql_data_home, "", 4 + 32);
+
+  DBUG_VOID_RETURN;
+}
+
+int Rpl_info_file::do_init_info()
+{
+  int error= 0;
+
+  /* Don't init if there is no storage */
+  DBUG_ENTER("Rpl_info_file::do_init_info");
+
+  /* does info file exist ? */
+  if (do_check_info())
+  {
+    /*
+      If someone removed the file from underneath our feet, just close
+      the old descriptor and re-create the old file
+    */
+    if (info_fd >= 0)
+      my_close(info_fd, MYF(MY_WME));
+    if ((info_fd = my_open(info_fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
+    {
+      sql_print_error("Failed to create a new info file (\
+file '%s', errno %d)", info_fname, my_errno);
+      error= 1;
+    }
+    else if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
+                      MYF(MY_WME)))
+    {
+      sql_print_error("Failed to create a cache on info file (\
+file '%s')", info_fname);
+      error= 1;
+    }
+    if (error)
+    {
+      if (info_fd >= 0)
+        my_close(info_fd, MYF(0));
+      info_fd= -1;
+    }
+  }
+  /* file exists */
+  else
+  {
+    if (info_fd >= 0)
+      reinit_io_cache(&info_file, READ_CACHE, 0L,0,0);
+    else
+    {
+      if ((info_fd = my_open(info_fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
+      {
+        sql_print_error("Failed to open the existing info file (\
+file '%s', errno %d)", info_fname, my_errno);
+        error= 1;
+      }
+      else if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,
+                        0, MYF(MY_WME)))
+      {
+        sql_print_error("Failed to create a cache on info file (\
+file '%s')", info_fname);
+        error= 1;
+      }
+      if (error)
+      {
+        if (info_fd >= 0)
+          my_close(info_fd, MYF(0));
+        info_fd= -1;
+      }
+    }
+  }
+  DBUG_RETURN(error);
+}
+
+int Rpl_info_file::do_prepare_info_for_read()
+{
+  cursor= 0;
+  prv_error= FALSE;
+  return (reinit_io_cache(&info_file, READ_CACHE, 0L, 0, 0));
+}
+
+int Rpl_info_file::do_prepare_info_for_write()
+{
+  cursor= 0;
+  prv_error= FALSE;
+  return (reinit_io_cache(&info_file, WRITE_CACHE, 0L, 0, 1));
+}
+
+int Rpl_info_file::do_check_info()
+{
+  return (access(info_fname,F_OK));
+}
+
+int Rpl_info_file::do_flush_info(const bool force)
+{
+  int error= 0;
+
+  DBUG_ENTER("Rpl_info_file::do_flush_info");
+
+  if (flush_io_cache(&info_file))
+    error= 1;
+  if (!error && (force ||
+      (sync_period &&
+      ++(sync_counter) >= sync_period)))
+  {
+    if (my_sync(info_fd, MYF(MY_WME)))
+      error= 1;
+    sync_counter= 0;
+  }
+
+  DBUG_RETURN(error);
+}
+
+void Rpl_info_file::do_end_info()
+{
+  DBUG_ENTER("Rpl_info_file::do_end_info");
+
+  if (info_fd >= 0)
+  {
+    end_io_cache(&info_file);
+    my_close(info_fd, MYF(MY_WME));
+    info_fd = -1;
+  }
+
+  DBUG_VOID_RETURN;
+}
+
+int Rpl_info_file::do_reset_info()
+{
+  MY_STAT stat_area;
+  int error= 0;
+
+  DBUG_ENTER("Rpl_info_file::do_reset_info");
+
+  if (my_stat(info_fname, &stat_area, MYF(0)) && my_delete(info_fname, MYF(MY_WME)))
+    error= 1;
+
+  DBUG_RETURN(error);
+}
+
+bool Rpl_info_file::do_set_info(const int pos, const char *value)
+{
+  return (my_b_printf(&info_file, "%s\n", value) > (size_t) 0 ?
+          FALSE : TRUE);
+}
+
+bool Rpl_info_file::do_set_info(const int pos, const ulong value)
+{
+  return (my_b_printf(&info_file, "%lu\n", value) > (size_t) 0 ?
+          FALSE : TRUE);
+}
+
+bool Rpl_info_file::do_set_info(const int pos, const int value)
+{
+  return (my_b_printf(&info_file, "%d\n", value) > (size_t) 0 ?
+          FALSE : TRUE);
+}
+
+bool Rpl_info_file::do_set_info(const int pos, const float value)
+{
+  /*
+    64 bytes provide enough space considering that the precision is 3
+    bytes (See the appropriate set funciton):
+
+    FLT_MAX  The value of this macro is the maximum number representable
+             in type float. It is supposed to be at least 1E+37.
+    FLT_MIN  Similar to the FLT_MAX, we have 1E-37.
+
+    If a file is manually and not properly changed, this function may
+    crash the server.
+  */
+  char buffer[64];
+
+  sprintf(buffer, "%.3f", value);
+
+  return (my_b_printf(&info_file, "%s\n", buffer) > (size_t) 0 ?
+          FALSE : TRUE);
+}
+
+bool Rpl_info_file::do_set_info(const int pos, const Server_ids *value)
+{
+  bool error= TRUE;
+  char *server_ids_buffer= (char*) my_malloc((sizeof(::server_id) * 3 + 1) *
+                                   (1 + value->server_ids.elements), MYF(0));
+
+  if (server_ids_buffer == NULL)
+    return error;
+
+  /*
+    This produces a line listing the total number and all the server_ids.
+  */
+  if (const_cast<Server_ids *>(value)->pack_server_ids(server_ids_buffer))
+    goto err;
+
+  error= (my_b_printf(&info_file, "%s\n", server_ids_buffer) >
+          (size_t) 0 ? FALSE : TRUE);
+
+err:
+  my_free(server_ids_buffer);
+  return error;
+}
+
+bool Rpl_info_file::do_get_info(const int pos, char *value, const size_t size,
+                                const char *default_value)
+{
+  return (init_strvar_from_file(value, size, &info_file,
+                                default_value));
+}
+
+bool Rpl_info_file::do_get_info(const int pos, ulong *value,
+                                const ulong default_value)
+{
+  return (init_ulongvar_from_file(value, &info_file,
+                                  default_value));
+}
+
+bool Rpl_info_file::do_get_info(const int pos, int *value,
+                                const int default_value)
+{
+  return (init_intvar_from_file((int *) value, &info_file, 
+                                (int) default_value));
+}
+
+bool Rpl_info_file::do_get_info(const int pos, float *value,
+                                const float default_value)
+{
+  return (init_floatvar_from_file(value, &info_file,
+                                  default_value));
+}
+
+bool Rpl_info_file::do_get_info(const int pos, Server_ids *value,
+                                const Server_ids *default_value __attribute__((unused)))
+{
+  /*
+    Static buffer to use most of the times. However, if it is not big
+    enough to accommodate the server ids, a new buffer is allocated.
+  */
+  const int array_size= 16 * (sizeof(long) * 4 + 1);
+  char buffer[array_size];
+  char *buffer_act= buffer;
+
+  bool error= init_dynarray_intvar_from_file(buffer, &buffer_act,
+                                             &info_file);
+  if (!error)
+    value->unpack_server_ids(buffer_act);
+
+  if (buffer != buffer_act)
+  {
+    /*
+      Release the buffer allocated while reading the server ids
+      from the file.
+    */
+    my_free(buffer_act);
+  }
+
+  return error;
+}
+
+char* Rpl_info_file::do_get_description_info()
+{
+  return info_fname;
+}
+
+bool Rpl_info_file::do_is_transactional()
+{
+  return FALSE;
+}
+
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+                          const char *default_val)
+{
+  uint length;
+  DBUG_ENTER("init_strvar_from_file");
+
+  if ((length=my_b_gets(f,var, max_size)))
+  {
+    char* last_p = var + length -1;
+    if (*last_p == '\n')
+      *last_p = 0; // if we stopped on newline, kill it
+    else
+    {
+      /*
+        If we truncated a line or stopped on last char, remove all chars
+        up to and including newline.
+      */
+      int c;
+      while (((c=my_b_get(f)) != '\n' && c != my_b_EOF)) ;
+    }
+    DBUG_RETURN(0);
+  }
+  else if (default_val)
+  {
+    strmake(var,  default_val, max_size-1);
+    DBUG_RETURN(0);
+  }
+  DBUG_RETURN(1);
+}
+
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
+{
+  /*
+    32 bytes provide enough space:
+
+    INT_MIN    –2,147,483,648
+    INT_MAX    +2,147,483,647
+  */
+  char buf[32];
+  DBUG_ENTER("init_intvar_from_file");
+
+  if (my_b_gets(f, buf, sizeof(buf)))
+  {
+    *var = atoi(buf);
+    DBUG_RETURN(0);
+  }
+  else if (default_val)
+  {
+    *var = default_val;
+    DBUG_RETURN(0);
+  }
+  DBUG_RETURN(1);
+}
+
+int init_ulongvar_from_file(ulong* var, IO_CACHE* f, ulong default_val)
+{
+  /* 
+    32 bytes provide enough space:
+
+    ULONG_MAX   32 bit compiler   +4,294,967,295
+                64 bit compiler   +18,446,744,073,709,551,615
+  */
+  char buf[32];
+  DBUG_ENTER("init_ulongvar_from_file");
+
+  if (my_b_gets(f, buf, sizeof(buf)))
+  {
+    *var = strtoul(buf, 0, 10);
+    DBUG_RETURN(0);
+  }
+  else if (default_val)
+  {
+    *var = default_val;
+    DBUG_RETURN(0);
+  }
+  DBUG_RETURN(1);
+}
+
+int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val)
+{
+  /*
+    64 bytes provide enough space considering that the precision is 3
+    bytes (See the appropriate set funciton):
+
+    FLT_MAX  The value of this macro is the maximum number representable
+             in type float. It is supposed to be at least 1E+37.
+    FLT_MIN  Similar to the FLT_MAX, we have 1E-37.
+
+    If a file is manually and not properly changed, this function may
+    crash the server.
+  */
+  char buf[64];
+  DBUG_ENTER("init_floatvar_from_file");
+
+  if (my_b_gets(f, buf, sizeof(buf)))
+  {
+    if (sscanf(buf, "%f", var) != 1)
+      DBUG_RETURN(1);
+    else
+      DBUG_RETURN(0);
+  }
+  else if (default_val != 0.0)
+  {
+    *var = default_val;
+    DBUG_RETURN(0);
+  }
+  DBUG_RETURN(1);
+}
+
+/**
+   Particularly, this function is responsible for restoring IGNORE_SERVER_IDS
+   list of servers whose events the slave is going to ignore (to not log them
+   in the relay log).
+
+   Items being read are supposed to be decimal output of values of a  type
+   shorter or equal of @c long and separated by the single space.
+
+   @param  buffer      Put the read values in this static buffer
+   @param  buffer_act  Points to the final buffer as dynamic buffer may
+                       be used if the static buffer is not big enough.
+
+   @retval 0           All OK
+   @retval non-zero  An error
+*/
+bool init_dynarray_intvar_from_file(char *buffer, char **buffer_act, IO_CACHE* f)
+{
+  char *buf= buffer; // actual buffer can be dynamic if static is short
+  char *buf_act= buffer;
+  char *last;
+  uint num_items;     // number of items of `arr'
+  size_t read_size;
+
+  DBUG_ENTER("init_dynarray_intvar_from_file");
+
+  if ((read_size= my_b_gets(f, buf_act, sizeof(buf))) == 0)
+  {
+    DBUG_RETURN(FALSE); // no line in master.info
+  }
+  if (read_size + 1 == sizeof(buf) && buf[sizeof(buf) - 2] != '\n')
+  {
+    /*
+      short read happend; allocate sufficient memory and make the 2nd read
+    */
+    char buf_work[(sizeof(long)*3 + 1)*16];
+    memcpy(buf_work, buf, sizeof(buf_work));
+    num_items= atoi(strtok_r(buf_work, " ", &last));
+    size_t snd_size;
+    /*
+      max size lower bound approximate estimation bases on the formula:
+      (the items number + items themselves) * 
+          (decimal size + space) - 1 + `\n' + '\0'
+    */
+    size_t max_size= (1 + num_items) * (sizeof(long)*3 + 1) + 1;
+    buf_act= (char*) my_malloc(max_size, MYF(MY_WME));
+    buffer_act= &buf_act;
+    memcpy(buf_act, buf, read_size);
+    snd_size= my_b_gets(f, buf_act + read_size, max_size - read_size);
+    if (snd_size == 0 ||
+        ((snd_size + 1 == max_size - read_size) &&  buf[max_size - 2] != '\n'))
+    {
+      /*
+        failure to make the 2nd read or short read again
+      */
+      DBUG_RETURN(TRUE);
+    }
+  }
+  DBUG_RETURN(FALSE);
+}

=== added file 'sql/rpl_info_file.h'
--- a/sql/rpl_info_file.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_file.h	2010-07-06 22:01:07 +0000
@@ -0,0 +1,73 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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_FILE_H
+#define RPL_INFO_FILE_H
+
+#include <my_global.h>
+#include <sql_priv.h>
+#include "rpl_info_handler.h"
+
+/**
+  Defines a file hander.
+*/
+class Rpl_info_file : public Rpl_info_handler
+{
+public:
+  Rpl_info_file(int const nparam, const char* param_info_fname);
+  virtual ~Rpl_info_file() { };
+
+private:
+  char info_fname[FN_REFLEN + 128];
+
+  /*
+    info_fd - file descriptor of the info file. set only during
+    initialization or clean up - safe to read anytime
+  */
+  File info_fd;
+
+  /* IO_CACHE of the info file - set only during init or end */
+  IO_CACHE info_file;
+
+  int do_init_info();
+  int do_check_info();
+  void do_end_info();
+  int do_flush_info(const bool force);
+  int do_reset_info();
+
+  int do_prepare_info_for_read();
+  int do_prepare_info_for_write();
+  bool do_set_info(const int pos, const char *value);
+  bool do_set_info(const int pos, const int value);
+  bool do_set_info(const int pos, const ulong value);
+  bool do_set_info(const int pos, const float value);
+  bool do_set_info(const int pos, const Server_ids *value);
+  bool do_get_info(const int pos, char *value, const size_t size,
+                   const char *default_value);
+  bool do_get_info(const int pos, int *value,
+                   const int default_value);
+  bool do_get_info(const int pos, ulong *value,
+                   const ulong default_value);
+  bool do_get_info(const int pos, float *value,
+                   const float default_value);
+  bool do_get_info(const int pos, Server_ids *value,
+                   const Server_ids *default_value);
+  char* do_get_description_info();
+  bool do_is_transactional();
+
+  Rpl_info_file& operator=(const Rpl_info_file& info);
+  Rpl_info_file(const Rpl_info_file& info);
+};
+#endif /* RPL_INFO_FILE_H */

=== added file 'sql/rpl_info_handler.cc'
--- a/sql/rpl_info_handler.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_handler.cc	2010-10-08 16:11:32 +0000
@@ -0,0 +1,35 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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 <sql_priv.h>
+#include "rpl_info_handler.h"
+
+Rpl_info_handler::Rpl_info_handler(const int nparam)
+  :ninfo(nparam), cursor((my_off_t)0),
+  prv_error(0), sync_counter(0), sync_period(0)
+{  
+  /* Nothing to do here. */
+}
+
+Rpl_info_handler::~Rpl_info_handler()
+{
+  /* Nothing to do here. */
+}
+
+void Rpl_info_handler::set_sync_period(uint period)
+{
+  sync_period= period; 
+}

=== added file 'sql/rpl_info_handler.h'
--- a/sql/rpl_info_handler.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl_info_handler.h	2010-10-17 23:27:40 +0000
@@ -0,0 +1,314 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   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_HANDLER_H
+#define RPL_INFO_HANDLER_H
+
+#include <my_global.h>
+#include <server_ids.h>
+
+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
+    depend on other components (e.g. mutexes) should be placed in the
+    object's constructor though. 
+
+    @retval FALSE success,
+    @retval TRUE  otherwise error.
+  */
+  int init_info()
+  {
+    return do_init_info();
+  }
+
+  /**
+    Checks if any necessary dependency is satisfied such as a
+    file exists.
+
+    @retval FALSE success,
+    @retval TRUE  otherwise error.
+  */
+  int check_info()
+  {
+    return do_check_info();
+  }
+
+  /**
+    Flushes and syncs in-memory information into a stable storage (i.e.
+    repository). Usually, syncing after flushing depends on other options
+    such as @code relay-log-info-sync, master-info-sync. These options
+    dictate after how many events or transactions the information
+    should be synced. We can ignore them and always sync by setting the
+    parameter @code force, which is by default false, to @code true.
+
+    So if the number of events is below a threshold, the parameter
+    @code force is FALSE and we are using a file system as a storage
+    system, it may happen that the changes will only end up in the
+    operating system's cache and a crash may lead to inconsistencies.
+
+    @param[in] force Always sync the information.
+
+    @retval FALSE No error
+    @retval TRUE  Failure
+  */
+  int flush_info(const bool force)
+  {
+    return do_flush_info(force);
+  }
+
+  /**
+    Deletes any information in the repository.
+
+    @retval FALSE No error
+    @retval TRUE  Failure
+  */
+  int reset_info()
+  {
+    return do_reset_info();
+  }
+
+  /**
+    Closes access to the repository.
+
+    @retval FALSE No error
+    @retval TRUE  Failure
+  */
+  void end_info()
+  {
+    do_end_info();
+  }
+
+  /**
+    Enables the storage system to receive reads, i.e.
+    getters.
+ 
+    @retval FALSE No error
+    @retval TRUE  Failure
+  */
+  int prepare_info_for_read()
+  {
+    return (do_prepare_info_for_read());
+  }
+
+  /**
+    Enables the storage system to receive writes, i.e.
+    setters.
+ 
+    @retval FALSE No error
+    @retval TRUE  Failure
+  */
+  int prepare_info_for_write()
+  {
+    return (do_prepare_info_for_write());
+  }
+
+  /**
+    Sets the value of a field to @c value.
+    Any call must be done in the right order which
+    is defined by the caller that wants to persist
+    the information.
+
+    @param[in] value Value to be set.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  template <class TypeHandler>
+  bool set_info(TypeHandler const value)
+  {
+    if (cursor >= ninfo || prv_error)
+      return TRUE;
+
+    if (!(prv_error= do_set_info(cursor, value)))
+      cursor++;
+
+    return(prv_error);
+  }
+
+  /**
+    Returns the value of a field.
+    Any call must be done in the right order which
+    is defined by the caller that wants to return
+    the information.
+
+    @param[in] value Value to be set.
+    @param[in] default_value Returns a default value
+                             if the field is empty.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  template <class TypeHandlerPointer, class TypeHandler>
+  bool get_info(TypeHandlerPointer value,
+                TypeHandler const default_value)
+  {
+    if (cursor >= ninfo || prv_error)
+      return TRUE;
+
+    if (!(prv_error= do_get_info(cursor, value, default_value)))
+      cursor++;
+
+    return(prv_error);
+  }
+
+  /**
+    Returns the value of a string field.
+    Any call must be done in the right order which
+    is defined by the caller that wants to return
+    the information.
+
+    @param[in] value Value to be returned.
+    @param[in] size  Max size of the string to be
+                     returned.
+    @param[in] default_value Returns a default value
+                             if the field is empty.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  bool get_info(char *value, const size_t size,
+                const char *default_value)
+  {
+    if (cursor >= ninfo || prv_error)
+      return TRUE;
+
+    if (!(prv_error= do_get_info(cursor, value, size, default_value)))
+      cursor++;
+
+    return(prv_error);
+  }
+ 
+  /**
+    Returns the value of a Server_id field.
+    Any call must be done in the right order which
+    is defined by the caller that wants to return
+    the information.
+
+    @param[out] value Value to be return.
+    @param[in] default_value Returns a default value
+                             if the field is empty.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  bool get_info(Server_ids *value,
+                const Server_ids *default_value)
+  {
+    if (cursor >= ninfo || prv_error)
+      return TRUE;
+
+    if (!(prv_error= do_get_info(cursor, value, default_value)))
+      cursor++;
+
+    return(prv_error);
+  }
+
+  /**
+    Returns the number of fields handled by this handler.
+
+    @return Number of fields handled by the handler.
+  */
+  int get_number_info() { return ninfo; }
+
+  /**
+    Configures the number of events after which the info (e.g.
+    master info, relay log info) must be synced when flush() is
+    called.
+ 
+    @param[in] period Number of events.
+  */
+  void set_sync_period(uint period);
+
+  /**
+    Returns a string describing the repository. For instance, if the
+    repository is a file, the returned string is path where data is
+    stored.
+
+    @return a pointer to a string.
+  */
+  char *get_description_info()
+  {
+    return (do_get_description_info());
+  }
+
+  /**
+    Any transactional repository may have its updates rolled back in case
+    of a failure. If this is possible, the repository is classified as
+    transactional.
+
+    @retval TRUE If transactional.
+    @retval FALSE Otherwise.
+  */
+  bool is_transactional() { return do_is_transactional(); }
+
+protected:
+  /* Number of fields to be stored in the repository. */
+  int ninfo;
+
+  /* From/To where we should start reading/writing. */
+  int cursor;
+
+  /* Registers if there was failure while accessing a field/information. */
+  bool prv_error;
+
+  /*
+   Keeps track of the number of events before fsyncing. The option
+   --sync-master-info and --sync-relay-log-info determine how many
+   events should be processed before fsyncing.
+  */
+  uint sync_counter;
+
+  /*
+   The number of events after which we should fsync.
+  */
+  uint sync_period;
+
+private:
+  virtual int do_init_info()= 0;
+  virtual int do_check_info()= 0;
+  virtual int do_flush_info(const bool force)= 0;
+  virtual int do_reset_info()= 0;
+  virtual void do_end_info()= 0;
+  virtual int do_prepare_info_for_read()= 0;
+  virtual int do_prepare_info_for_write()= 0;
+
+  virtual bool do_set_info(const int pos, const char *value)= 0;
+  virtual bool do_set_info(const int pos, const ulong value)= 0;
+  virtual bool do_set_info(const int pos, const int value)= 0;
+  virtual bool do_set_info(const int pos, const float value)= 0;
+  virtual bool do_set_info(const int pos, const Server_ids *value)= 0;
+  virtual bool do_get_info(const int pos, char *value, const size_t size,
+                           const char *default_value)= 0;
+  virtual bool do_get_info(const int pos, ulong *value,
+                           const ulong default_value)= 0;
+  virtual bool do_get_info(const int pos, int *value,
+                           const int default_value)= 0;
+  virtual bool do_get_info(const int pos, float *value,
+                           const float default_value)= 0;
+  virtual bool do_get_info(const int pos, Server_ids *value,
+                           const Server_ids *default_value)= 0;
+  virtual char* do_get_description_info()= 0;
+  virtual bool do_is_transactional()= 0;
+
+  Rpl_info_handler& operator=(const Rpl_info_handler& handler);
+  Rpl_info_handler(const Rpl_info_handler& handler);
+};
+#endif /* RPL_INFO_HANDLER_H */

=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc	2010-07-29 09:31:24 +0000
+++ b/sql/rpl_mi.cc	2010-08-24 08:39:26 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -10,8 +10,8 @@
    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,
-   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include <my_global.h> // For HAVE_REPLICATION
 #include "sql_priv.h"
@@ -22,40 +22,83 @@
 
 #ifdef HAVE_REPLICATION
 
-#define DEFAULT_CONNECT_RETRY 60
+enum {
+  LINES_IN_MASTER_INFO_WITH_SSL= 14,
+
+  /* 5.1.16 added value of master_ssl_verify_server_cert */
+  LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT= 15,
+
+  /* 5.5 added value of master_heartbeat_period */
+  LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16,
+
+  /* MySQL Cluster 6.3 added master_bind */
+  LINE_FOR_MASTER_BIND = 17,
 
+  /* 6.0 added value of master_ignore_server_id */
+  LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 18,
+
+  /* 6.0 added value of master_uuid */
+  LINE_FOR_MASTER_UUID= 19,
 
-Master_info::Master_info(bool is_slave_recovery)
-  :Slave_reporting_capability("I/O"),
-   ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), 
-   rli(is_slave_recovery), port(MYSQL_PORT),
-   connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0),
-   slave_running(0), slave_run_id(0), clock_diff_with_master(0), 
-   sync_counter(0), heartbeat_period(0), received_heartbeats(0), 
-   master_id(0), retry_count(master_retry_count)
+  /* line for master_retry_count */
+  LINE_FOR_MASTER_RETRY_COUNT= 20,
+
+  /* Number of lines currently used when saving master info file */
+  LINES_IN_MASTER_INFO= LINE_FOR_MASTER_RETRY_COUNT
+};
+
+/*
+  Please every time you add a new field to the mater info, update
+  what follows. For now, this is just used to get the number of
+  fields.
+*/
+const char *info_mi_fields []=
+{ 
+  "number_of_lines",
+  "master_log_name",
+  "master_log_pos",
+  "host",
+  "user",
+  "password",
+  "port",
+  "connect_retry",
+  "ssl",
+  "ssl_ca",
+  "ssl_capath",
+  "ssl_cert",
+  "ssl_cipher",
+  "ssl_key",
+  "ssl_verify_server_cert",
+  "heartbeat_period",
+  "bind", 
+  "ignore_server_ids",
+  "uuid",
+  "retry_count"
+};
+
+Master_info::Master_info(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)
+   :Rpl_info("I/O", param_key_info_run_lock, param_key_info_data_lock,
+             param_key_info_data_cond, param_key_info_start_cond,
+             param_key_info_stop_cond),
+   ssl(0), ssl_verify_server_cert(0),
+   port(MYSQL_PORT), connect_retry(DEFAULT_CONNECT_RETRY),
+   clock_diff_with_master(0), heartbeat_period(0),
+   received_heartbeats(0), master_id(0), retry_count(master_retry_count)
 {
   host[0] = 0; user[0] = 0; password[0] = 0;
   ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
   ssl_cipher[0]= 0; ssl_key[0]= 0;
-  master_uuid[0]=0;
-
-  my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16);
-  bzero((char*) &file, sizeof(file));
-  mysql_mutex_init(key_master_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST);
-  mysql_mutex_init(key_master_info_data_lock, &data_lock, MY_MUTEX_INIT_FAST);
-  mysql_cond_init(key_master_info_data_cond, &data_cond, NULL);
-  mysql_cond_init(key_master_info_start_cond, &start_cond, NULL);
-  mysql_cond_init(key_master_info_stop_cond, &stop_cond, NULL);
+  master_uuid[0]= 0;
+  ignore_server_ids= new Server_ids();
 }
 
 Master_info::~Master_info()
 {
-  delete_dynamic(&ignore_server_ids);
-  mysql_mutex_destroy(&run_lock);
-  mysql_mutex_destroy(&data_lock);
-  mysql_cond_destroy(&data_cond);
-  mysql_cond_destroy(&start_cond);
-  mysql_cond_destroy(&stop_cond);
+  delete ignore_server_ids;
 }
 
 /**
@@ -70,7 +113,6 @@ int change_master_server_id_cmp(ulong *i
   return *id1 < *id2? -1 : (*id1 > *id2? 1 : 0);
 }
 
-
 /**
    Reports if the s_id server has been configured to ignore events 
    it generates with
@@ -86,484 +128,339 @@ int change_master_server_id_cmp(ulong *i
  */
 bool Master_info::shall_ignore_server_id(ulong s_id)
 {
-  if (likely(ignore_server_ids.elements == 1))
-    return (* (ulong*) dynamic_array_ptr(&ignore_server_ids, 0)) == s_id;
+  if (likely(ignore_server_ids->server_ids.elements == 1))
+    return (* (ulong*)
+      dynamic_array_ptr(&(ignore_server_ids->server_ids), 0)) == s_id;
   else      
     return bsearch((const ulong *) &s_id,
-                   ignore_server_ids.buffer,
-                   ignore_server_ids.elements, sizeof(ulong),
+                   ignore_server_ids->server_ids.buffer,
+                   ignore_server_ids->server_ids.elements, sizeof(ulong),
                    (int (*) (const void*, const void*)) change_master_server_id_cmp)
       != NULL;
 }
 
-void init_master_log_pos(Master_info* mi)
+void Master_info::init_master_log_pos()
 {
-  DBUG_ENTER("init_master_log_pos");
+  DBUG_ENTER("Master_info::init_master_log_pos");
 
-  mi->master_log_name[0] = 0;
-  mi->master_log_pos = BIN_LOG_HEADER_SIZE;             // skip magic number
+  master_log_name[0]= 0;
+  master_log_pos= BIN_LOG_HEADER_SIZE;             // skip magic number
 
   /* Intentionally init ssl_verify_server_cert to 0, no option available  */
-  mi->ssl_verify_server_cert= 0;
+  ssl_verify_server_cert= 0;
   /* 
     always request heartbeat unless master_heartbeat_period is set
     explicitly zero.  Here is the default value for heartbeat period
     if CHANGE MASTER did not specify it.  (no data loss in conversion
     as hb period has a max)
   */
-  mi->heartbeat_period= (float) min(SLAVE_MAX_HEARTBEAT_PERIOD,
-                                    (slave_net_timeout/2.0));
-  DBUG_ASSERT(mi->heartbeat_period > (float) 0.001
-              || mi->heartbeat_period == 0);
+  heartbeat_period= (float) min(SLAVE_MAX_HEARTBEAT_PERIOD,
+                                (slave_net_timeout/2.0));
+  DBUG_ASSERT(heartbeat_period > (float) 0.001
+              || heartbeat_period == 0);
 
   DBUG_VOID_RETURN;
 }
 
-
-enum {
-  LINES_IN_MASTER_INFO_WITH_SSL= 14,
-
-  /* 5.1.16 added value of master_ssl_verify_server_cert */
-  LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT= 15,
-  /* 6.0 added value of master_heartbeat_period */
-  LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16,
-  /* MySQL Cluster 6.3 added master_bind */
-  LINE_FOR_MASTER_BIND = 17,
-  /* 6.0 added value of master_ignore_server_id */
-  LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 18,
-  /* 6.0 added value of master_uuid */
-  LINE_FOR_MASTER_UUID= 19,
-  /* line for master_retry_count */
-  LINE_FOR_MASTER_RETRY_COUNT= 20,
-
-  /* Number of lines currently used when saving master info file */
-  LINES_IN_MASTER_INFO= LINE_FOR_MASTER_RETRY_COUNT
-};
-
-int init_master_info(Master_info* mi, const char* master_info_fname,
-                     const char* slave_info_fname,
-                     bool abort_if_no_master_info_file,
-                     int thread_mask)
+void Master_info::end_info()
 {
-  int fd,error;
-  DBUG_ENTER("init_master_info");
+  DBUG_ENTER("Master_info::end_info");
 
-  if (mi->inited)
-  {
-    /*
-      We have to reset read position of relay-log-bin as we may have
-      already been reading from 'hotlog' when the slave was stopped
-      last time. If this case pos_in_file would be set and we would
-      get a crash when trying to read the signature for the binary
-      relay log.
-
-      We only rewind the read position if we are starting the SQL
-      thread. The handle_slave_sql thread assumes that the read
-      position is at the beginning of the file, and will read the
-      "signature" and then fast-forward to the last position read.
-    */
-    if (thread_mask & SLAVE_SQL)
-    {
-      bool hot_log= FALSE;
-      /* 
-         my_b_seek does an implicit flush_io_cache, so we need to:
-
-         1. check if this log is active (hot)
-         2. if it is we keep log_lock until the seek ends, otherwise 
-            release it right away.
-
-         If we did not take log_lock, SQL thread might race with IO
-         thread for the IO_CACHE mutex.
-
-       */
-      mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock();
-      mysql_mutex_lock(log_lock);
-      hot_log= mi->rli.relay_log.is_active(mi->rli.linfo.log_file_name);
-
-      if (!hot_log)
-        mysql_mutex_unlock(log_lock);
-
-      my_b_seek(mi->rli.cur_log, (my_off_t) 0);
-
-      if (hot_log)
-        mysql_mutex_unlock(log_lock);
-    }
-    DBUG_RETURN(0);
-  }
+  if (!inited)
+    DBUG_VOID_RETURN;
 
-  mi->mysql=0;
-  mi->file_id=1;
-  fn_format(mi->info_file_name, master_info_fname, mysql_data_home, "",
-            MYF(MY_UNPACK_FILENAME|MY_RETURN_REAL_PATH));
+  handler->end_info();
 
-  /*
-    We need a mutex while we are changing master info parameters to
-    keep other threads from reading bogus info
-  */
+  inited = 0;
 
-  mysql_mutex_lock(&mi->data_lock);
-  fd = mi->fd;
+  DBUG_VOID_RETURN;
+}
 
-  /* does master.info exist ? */
+/**
+  Store the file and position where the slave's SQL thread are in the
+   relay log.
 
-  if (access(mi->info_file_name, F_OK))
-  {
-    if (abort_if_no_master_info_file)
-    {
-      mysql_mutex_unlock(&mi->data_lock);
-      DBUG_RETURN(0);
-    }
-    /*
-      if someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (fd >= 0)
-      mysql_file_close(fd, MYF(MY_WME));
-    if ((fd= mysql_file_open(key_file_master_info, mi->info_file_name,
-                             O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-    {
-      sql_print_error("Failed to create a new master info file (\
-file '%s', errno %d)", mi->info_file_name, my_errno);
-      goto err;
-    }
-    if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
-                      MYF(MY_WME)))
-    {
-      sql_print_error("Failed to create a cache on master info file (\
-file '%s')", mi->info_file_name);
-      goto err;
-    }
+  - This function should be called either from the slave SQL thread,
+    or when the slave thread is not running.  (It reads the
+    group_{relay|master}_log_{pos|name} and delay fields in the rli
+    object.  These may only be modified by the slave SQL thread or by
+    a client thread when the slave SQL thread is not running.)
+
+  - If there is an active transaction, then we do not update the
+    position in the relay log.  This is to ensure that we re-execute
+    statements if we die in the middle of an transaction that was
+    rolled back.
+
+  - As a transaction never spans binary logs, we don't have to handle
+    the case where we do a relay-log-rotation in the middle of the
+    transaction.  If transactions could span several binlogs, we would
+    have to ensure that we do not delete the relay log file where the
+    transaction started before switching to a new relay log file.
 
-    mi->fd = fd;
-    init_master_log_pos(mi);
+  - Error can happen if writing to file fails or if flushing the file
+    fails.
 
-  }
-  else // file exists
-  {
-    if (fd >= 0)
-      reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
-    else
-    {
-      if ((fd= mysql_file_open(key_file_master_info,
-                               mi->info_file_name, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-      {
-        sql_print_error("Failed to open the existing master info file (\
-file '%s', errno %d)", mi->info_file_name, my_errno);
-        goto err;
-      }
-      if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
-                        0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on master info file (\
-file '%s')", mi->info_file_name);
-        goto err;
-      }
-    }
-
-    mi->fd = fd;
-    int port, connect_retry, master_log_pos, lines;
-    int ssl= 0, ssl_verify_server_cert= 0;
-    float master_heartbeat_period= 0.0;
-    char *first_non_digit;
-    char dummy_buf[HOSTNAME_LENGTH+1];
-    long retry_count= master_retry_count;
+  @param rli The object representing the Relay_log_info.
 
-    /*
-       Starting from 4.1.x master.info has new format. Now its
-       first line contains number of lines in file. By reading this
-       number we will be always distinguish to which version our
-       master.info corresponds to. We can't simply count lines in
-       file since versions before 4.1.x could generate files with more
-       lines than needed.
-       If first line doesn't contain a number or contain number less than
-       LINES_IN_MASTER_INFO_WITH_SSL then such file is treated like file
-       from pre 4.1.1 version.
-       There is no ambiguity when reading an old master.info, as before
-       4.1.1, the first line contained the binlog's name, which is either
-       empty or has an extension (contains a '.'), so can't be confused
-       with an integer.
+  @todo Change the log file information to a binary format to avoid
+  calling longlong2str.
+*/
+int Master_info::flush_info(bool force)
+{
+  DBUG_ENTER("Master_info::flush_info");
+  DBUG_PRINT("enter",("master_pos: %lu", (ulong) master_log_pos));
 
-       So we're just reading first line and trying to figure which version
-       is this.
-    */
+  /*
+    We update the sync_period at this point because only here we
+    now that we are handling a master info. This needs to be
+    update every time we call flush because the option maybe
+    dinamically set.
+  */
+  handler->set_sync_period(sync_masterinfo_period);
 
-    /*
-       The first row is temporarily stored in mi->master_log_name,
-       if it is line count and not binlog name (new format) it will be
-       overwritten by the second row later.
-    */
-    if (init_strvar_from_file(mi->master_log_name,
-                              sizeof(mi->master_log_name), &mi->file,
-                              ""))
-      goto errwithmsg;
-
-    lines= strtoul(mi->master_log_name, &first_non_digit, 10);
-
-    if (mi->master_log_name[0]!='\0' &&
-        *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
-    {
-      /* Seems to be new format => read master log name from next line */
-      if (init_strvar_from_file(mi->master_log_name,
-            sizeof(mi->master_log_name), &mi->file, ""))
-        goto errwithmsg;
-    }
-    else
-      lines= 7;
-
-    if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
-        init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, 0) ||
-        init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, "test") ||
-        init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
-                              &mi->file, 0) ||
-        init_intvar_from_file(&port, &mi->file, MYSQL_PORT) ||
-        init_intvar_from_file(&connect_retry, &mi->file,
-                              DEFAULT_CONNECT_RETRY))
-      goto errwithmsg;
+  if (write_info(handler, force))
+    goto err;
 
-    /*
-       If file has ssl part use it even if we have server without
-       SSL support. But these options will be ignored later when
-       slave will try connect to master, so in this case warning
-       is printed.
-     */
-    if (lines >= LINES_IN_MASTER_INFO_WITH_SSL)
-    {
-      if (init_intvar_from_file(&ssl, &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
-                                &mi->file, 0) ||
-          init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
-                                &mi->file, 0))
-        goto errwithmsg;
+  DBUG_RETURN(0);
 
-      /*
-        Starting from 5.1.16 ssl_verify_server_cert might be
-        in the file
-      */
-      if (lines >= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT &&
-          init_intvar_from_file(&ssl_verify_server_cert, &mi->file, 0))
-        goto errwithmsg;
-      /*
-        Starting from 6.0 master_heartbeat_period might be
-        in the file
-      */
-      if (lines >= LINE_FOR_MASTER_HEARTBEAT_PERIOD &&
-          init_floatvar_from_file(&master_heartbeat_period, &mi->file, 0.0))
-        goto errwithmsg;
-      /*
-	Starting from MySQL Cluster 6.3 master_bind might be in the file
-	(this is just a reservation to avoid future upgrade problems) 
-       */
-      if (lines >= LINE_FOR_MASTER_BIND &&
-	  init_strvar_from_file(dummy_buf, sizeof(dummy_buf), &mi->file, ""))
-	  goto errwithmsg;
-      /*
-        Starting from 6.0 list of server_id of ignorable servers might be
-        in the file
-      */
-      if (lines >= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS &&
-          init_dynarray_intvar_from_file(&mi->ignore_server_ids, &mi->file))
-      {
-        sql_print_error("Failed to initialize master info ignore_server_ids");
-        goto errwithmsg;
-      }
-
-      if (lines >= LINE_FOR_MASTER_UUID &&
-          init_strvar_from_file(mi->master_uuid, sizeof(mi->master_uuid), &mi->file, 0))
-        goto errwithmsg;
-
-      /* master_retry_count may be in the file. */
-      if (lines >= LINE_FOR_MASTER_RETRY_COUNT &&
-          init_longvar_from_file(&retry_count, &mi->file, master_retry_count))
-      {
-        sql_print_error("Failed to initialize master info master_retry_count");
-        goto errwithmsg;
-      }
+err:
+  sql_print_error("Error writing master configuration");
+  DBUG_RETURN(1);
+}
 
-    }
+void Master_info::set_relay_log_info(Relay_log_info* info)
+{
+  rli= info;
+}
 
+int Master_info::init_info()
+{
+  DBUG_ENTER("Master_info::init_info");
 
-#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.", mi->info_file_name);
-#endif /* HAVE_OPENSSL */
+  if (inited)
+    DBUG_RETURN(0);
 
-    /*
-      This has to be handled here as init_intvar_from_file can't handle
-      my_off_t types
-    */
-    mi->master_log_pos= (my_off_t) master_log_pos;
-    mi->port= (uint) port;
-    mi->connect_retry= (uint) connect_retry;
-    mi->ssl= (my_bool) ssl;
-    mi->ssl_verify_server_cert= ssl_verify_server_cert;
-    mi->heartbeat_period= master_heartbeat_period;
-    mi->retry_count= retry_count;
-  }
-  DBUG_PRINT("master_info",("log_file_name: %s  position: %ld",
-                            mi->master_log_name,
-                            (ulong) mi->master_log_pos));
+  /*
+    The init_info() is used to either create or read information
+    from the repository, in order to initialize the Master_info.
+  */
+  mysql= 0; file_id= 1;
+  int necessary_to_configure= check_info();
+  
+  if (handler->init_info())
+    goto err;
 
-  mi->rli.mi = mi;
-  if (init_relay_log_info(&mi->rli, slave_info_fname))
+  if (necessary_to_configure)
+  {
+    init_master_log_pos();
+    goto end;
+  }
+  else if (read_info(handler))
     goto err;
 
-  mi->inited = 1;
-  mi->rli.is_relay_log_recovery= FALSE;
-  // now change cache READ -> WRITE - must do this before flush_master_info
-  reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
-  if ((error=test(flush_master_info(mi, TRUE, TRUE))))
-    sql_print_error("Failed to flush master info file");
-  mysql_mutex_unlock(&mi->data_lock);
-  DBUG_RETURN(error);
+end:
+  if (flush_info(TRUE))
+    goto err;
 
-errwithmsg:
-  sql_print_error("Error reading master configuration");
+  inited= 1;
+  DBUG_RETURN(0);
 
 err:
-  if (fd >= 0)
-  {
-    mysql_file_close(fd, MYF(0));
-    end_io_cache(&mi->file);
-  }
-  mi->fd= -1;
-  mysql_mutex_unlock(&mi->data_lock);
+  sql_print_error("Error reading master configuration");
   DBUG_RETURN(1);
 }
 
+size_t Master_info::get_number_info_mi_fields()
+{
+  return sizeof(info_mi_fields)/sizeof(info_mi_fields[0]); 
+}
 
-/*
-  RETURN
-     2 - flush relay log failed
-     1 - flush master info failed
-     0 - all ok
-*/
-int flush_master_info(Master_info* mi, 
-                      bool flush_relay_log_cache, 
-                      bool need_lock_relay_log)
-{
-  IO_CACHE* file = &mi->file;
-  char lbuf[22];
-  int err= 0;
+bool Master_info::read_info(Rpl_info_handler *from)
+{
+  int lines= 0;
+  char *first_non_digit= NULL;
+  ulong temp_master_log_pos= 0;
+  int temp_ssl= 0;
 
-  DBUG_ENTER("flush_master_info");
-  DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
+  DBUG_ENTER("Master_info::read_info");
 
   /*
-    Flush the relay log to disk. If we don't do it, then the relay log while
-    have some part (its last kilobytes) in memory only, so if the slave server
-    dies now, with, say, from master's position 100 to 150 in memory only (not
-    on disk), and with position 150 in master.info, then when the slave
-    restarts, the I/O thread will fetch binlogs from 150, so in the relay log
-    we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
-    SQL thread will jump from 100 to 150, and replication will silently break.
+     Starting from 4.1.x master.info has new format. Now its
+     first line contains number of lines in file. By reading this
+     number we will be always distinguish to which version our
+     master.info corresponds to. We can't simply count lines in
+     file since versions before 4.1.x could generate files with more
+     lines than needed.
+     If first line doesn't contain a number or contain number less than
+     LINES_IN_MASTER_INFO_WITH_SSL then such file is treated like file
+     from pre 4.1.1 version.
+     There is no ambiguity when reading an old master.info, as before
+     4.1.1, the first line contained the binlog's name, which is either
+     empty or has an extension (contains a '.'), so can't be confused
+     with an integer.
 
-    When we come to this place in code, relay log may or not be initialized;
-    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
+     So we're just reading first line and trying to figure which version
+     is this.
   */
-  if (flush_relay_log_cache)
-  {
-    mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock();
-    IO_CACHE *log_file= mi->rli.relay_log.get_log_file();
-
-    if (need_lock_relay_log)
-      mysql_mutex_lock(log_lock);
 
-    mysql_mutex_assert_owner(log_lock);
-    err= flush_io_cache(log_file);
+  if (from->prepare_info_for_read() || 
+      from->get_info(master_log_name, sizeof(master_log_name), ""))
+    DBUG_RETURN(TRUE);
 
-    if (need_lock_relay_log)
-      mysql_mutex_unlock(log_lock);
+  lines= strtoul(master_log_name, &first_non_digit, 10);
 
-    if (err)
-      DBUG_RETURN(2);
+  if (master_log_name[0]!='\0' &&
+      *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
+  {
+    /* Seems to be new format => read master log name */
+    if (from->get_info(master_log_name,  sizeof(master_log_name), ""))
+      DBUG_RETURN(TRUE);
   }
-  
+  else 
+    lines= 7;
+
+  if (from->get_info(&temp_master_log_pos,
+                        (ulong) BIN_LOG_HEADER_SIZE) ||
+      from->get_info(host, sizeof(host), 0) ||
+      from->get_info(user, sizeof(user), "test") ||
+      from->get_info(password, sizeof(password), 0) ||
+      from->get_info((int *) &port, (int) MYSQL_PORT) ||
+      from->get_info((int *) &connect_retry,
+                        (int) DEFAULT_CONNECT_RETRY))
+      DBUG_RETURN(TRUE);
+
   /*
-    produce a line listing the total number and all the ignored server_id:s
+    If file has ssl part use it even if we have server without
+    SSL support. But these options will be ignored later when
+    slave will try connect to master, so in this case warning
+    is printed.
   */
-  char* ignore_server_ids_buf;
+  if (lines >= LINES_IN_MASTER_INFO_WITH_SSL)
   {
-    ignore_server_ids_buf=
-      (char *) my_malloc((sizeof(::server_id) * 3 + 1) *
-                         (1 + mi->ignore_server_ids.elements), MYF(MY_WME));
-    if (!ignore_server_ids_buf)
-      DBUG_RETURN(1);
-    ulong cur_len= sprintf(ignore_server_ids_buf, "%u",
-                           mi->ignore_server_ids.elements);
-    for (ulong i= 0; i < mi->ignore_server_ids.elements; i++)
-    {
-      ulong s_id;
-      get_dynamic(&mi->ignore_server_ids, (uchar*) &s_id, i);
-      cur_len+= sprintf(ignore_server_ids_buf + cur_len, " %lu", s_id);
-    }
+    if (from->get_info((int *) &temp_ssl, 0) ||
+        from->get_info(ssl_ca, sizeof(ssl_ca), 0) ||
+        from->get_info(ssl_capath, sizeof(ssl_capath), 0) ||
+        from->get_info(ssl_cert, sizeof(ssl_cert), 0) ||
+        from->get_info(ssl_cipher, sizeof(ssl_cipher), 0) ||
+        from->get_info(ssl_key, sizeof(ssl_key), 0))
+      DBUG_RETURN(TRUE);
   }
 
   /*
-    We flushed the relay log BEFORE the master.info file, because if we crash
-    now, we will get a duplicate event in the relay log at restart. If we
-    flushed in the other order, we would get a hole in the relay log.
-    And duplicate is better than hole (with a duplicate, in later versions we
-    can add detection and scrap one event; with a hole there's nothing we can
-    do).
+    Starting from 5.1.16 ssl_verify_server_cert might be
+    in the file
   */
+  if (lines >= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT)
+  { 
+    if (from->get_info((int *) &ssl_verify_server_cert, 0))
+      DBUG_RETURN(TRUE);
+  }
 
   /*
-     In certain cases this code may create master.info files that seems
-     corrupted, because of extra lines filled with garbage in the end
-     file (this happens if new contents take less space than previous
-     contents of file). But because of number of lines in the first line
-     of file we don't care about this garbage.
+    Starting from 5.5 master_heartbeat_period might be
+    in the file
   */
-  char heartbeat_buf[sizeof(mi->heartbeat_period) * 4]; // buffer to suffice always
-  sprintf(heartbeat_buf, "%.3f", mi->heartbeat_period);
-  my_b_seek(file, 0L);
-  my_b_printf(file,
-              "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n%s\n%ld\n",
-              LINES_IN_MASTER_INFO,
-              mi->master_log_name, llstr(mi->master_log_pos, lbuf),
-              mi->host, mi->user,
-              mi->password, mi->port, mi->connect_retry,
-              (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
-              mi->ssl_cipher, mi->ssl_key, mi->ssl_verify_server_cert,
-              heartbeat_buf, "", ignore_server_ids_buf, mi->master_uuid,
-              mi->retry_count);
-  my_free(ignore_server_ids_buf);
-  err= flush_io_cache(file);
-  if (sync_masterinfo_period && !err && 
-      ++(mi->sync_counter) >= sync_masterinfo_period)
+  if (lines >= LINE_FOR_MASTER_HEARTBEAT_PERIOD)
   {
-    err= my_sync(mi->fd, MYF(MY_WME));
-    mi->sync_counter= 0;
+    if (from->get_info(&heartbeat_period, (float) 0.0))
+      DBUG_RETURN(TRUE);
   }
-  DBUG_RETURN(-err);
-}
 
+  /*
+    Starting from 5.5 master_bind might be in the file
+  */
+  if (lines >= LINE_FOR_MASTER_BIND)
+  {
+    /*
+      This is a placeholder for the bind option.
+      Please, update this after WL#3126 and
+      WL#3127.
+    */
+    char fake_bind[2];
+    if (from->get_info(fake_bind, sizeof(fake_bind), ""))
+      DBUG_RETURN(TRUE);
+  }
 
-void end_master_info(Master_info* mi)
-{
-  DBUG_ENTER("end_master_info");
+  /*
+    Starting from 5.5 list of server_id of ignorable servers might be
+    in the file
+  */
+  if (lines >= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS)
+  {
+     if (from->get_info(ignore_server_ids, (Server_ids *) NULL))
+      DBUG_RETURN(TRUE);
+  }
 
-  if (!mi->inited)
-    DBUG_VOID_RETURN;
-  end_relay_log_info(&mi->rli);
-  if (mi->fd >= 0)
+  /* Starting from 5.5 the master_uuid may be in the repository. */
+  if (lines >= LINE_FOR_MASTER_UUID)
   {
-    end_io_cache(&mi->file);
-    mysql_file_close(mi->fd, MYF(MY_WME));
-    mi->fd = -1;
+    if (from->get_info(master_uuid, sizeof(master_uuid), 0))
+      DBUG_RETURN(TRUE);
   }
-  mi->inited = 0;
 
-  DBUG_VOID_RETURN;
+  /* Starting from 5.5 the master_retry_count may be in the repository. */
+  retry_count= master_retry_count;
+  if (lines >= LINE_FOR_MASTER_RETRY_COUNT)
+  {
+    if (from->get_info(&retry_count, master_retry_count))
+      DBUG_RETURN(TRUE);
+  }
+
+  ssl= (my_bool) temp_ssl;
+  master_log_pos= (my_off_t) temp_master_log_pos;
+#ifndef HAVE_OPENSSL
+  if (ssl)
+    sql_print_warning("SSL information in the master info file "
+                      "are ignored because this MySQL slave was "
+                      "compiled without SSL support.");
+#endif /* HAVE_OPENSSL */
+
+  DBUG_RETURN(FALSE);
 }
 
+bool Master_info::write_info(Rpl_info_handler *to, bool force)
+{
+  DBUG_ENTER("Master_info::write_info");
 
+  /*
+     In certain cases this code may create master.info files that seems
+     corrupted, because of extra lines filled with garbage in the end
+     file (this happens if new contents take less space than previous
+     contents of file). But because of number of lines in the first line
+     of file we don't care about this garbage.
+  */
+
+  if (to->prepare_info_for_write() ||
+      to->set_info((int) LINES_IN_MASTER_INFO) ||
+      to->set_info(master_log_name) ||
+      to->set_info((ulong)master_log_pos) ||
+      to->set_info(host) ||
+      to->set_info(user) ||
+      to->set_info(password) ||
+      to->set_info((int) port) ||
+      to->set_info((int) connect_retry) ||
+      to->set_info((int) ssl) ||
+      to->set_info(ssl_ca) ||
+      to->set_info(ssl_capath) ||
+      to->set_info(ssl_cert) ||
+      to->set_info(ssl_cipher) ||
+      to->set_info(ssl_key) ||
+      to->set_info(ssl_verify_server_cert) ||
+      to->set_info(heartbeat_period) ||
+      /*
+        This is a placeholder for the bind option.
+        Please, update this after WL#3126 and
+        WL#3127.
+      */
+      to->set_info("") || 
+      to->set_info(ignore_server_ids) ||
+      to->set_info(master_uuid) ||
+      to->set_info(retry_count))
+    DBUG_RETURN(TRUE);
+
+  if (to->flush_info(force))
+    DBUG_RETURN(TRUE);
+
+  DBUG_RETURN(FALSE);
+}
 #endif /* HAVE_REPLICATION */

=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h	2010-07-29 09:31:24 +0000
+++ b/sql/rpl_mi.h	2010-08-05 17:45:25 +0000
@@ -18,8 +18,12 @@
 
 #ifdef HAVE_REPLICATION
 
+#include <my_global.h>
+#include <sql_priv.h>
+
+#define DEFAULT_CONNECT_RETRY 60
+
 #include "rpl_rli.h"
-#include "rpl_reporting.h"
 #include "my_sys.h"
 
 typedef struct st_mysql MYSQL;
@@ -33,12 +37,12 @@ typedef struct st_mysql MYSQL;
     - current master log offset
     - misc control variables
 
-  Master_info is initialized once from the master.info file if such
+  Master_info is initialized once from the master.info repository if such
   exists. Otherwise, data members corresponding to master.info fields
   are initialized with defaults specified by master-* options. The
-  initialization is done through init_master_info() call.
+  initialization is done through init_info() call.
 
-  The format of master.info file:
+  Logically, the format of master.info repository is presented as follows:
 
   log_name
   log_pos
@@ -48,23 +52,25 @@ typedef struct st_mysql MYSQL;
   master_port
   master_connect_retry
 
-  To write out the contents of master.info file to disk ( needed every
-  time we read and queue data from the master ), a call to
-  flush_master_info() is required.
+  To write out the contents of master.info to disk a call to flush_info()
+  is required. Currently, it is needed every time we read and queue data
+  from the master.
 
-  To clean up, call end_master_info()
+  To clean up, call end_info()
 
 *****************************************************************************/
 
-class Master_info : public Slave_reporting_capability
+class Master_info : public Rpl_info
 {
  public:
-  Master_info(bool is_slave_recovery);
-  ~Master_info();
-  bool shall_ignore_server_id(ulong s_id);
+  Master_info(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);
+  virtual ~Master_info();
 
   /* the variables below are needed because we can change masters on the fly */
-  char master_log_name[FN_REFLEN];
   char host[HOSTNAME_LENGTH+1];
   char user[USERNAME_LENGTH+1];
   char password[MAX_PASSWORD_LENGTH+1];
@@ -73,25 +79,11 @@ class Master_info : public Slave_reporti
   char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
   my_bool ssl_verify_server_cert;
 
-  my_off_t master_log_pos;
-  File fd; // we keep the file open, so we need to remember the file pointer
-  IO_CACHE file;
-
-  mysql_mutex_t data_lock, run_lock;
-  mysql_cond_t data_cond, start_cond, stop_cond;
-  THD *io_thd;
   MYSQL* mysql;
   uint32 file_id;				/* for 3.23 load data infile */
-  Relay_log_info rli;
+  Relay_log_info *rli;
   uint port;
   uint connect_retry;
-#ifndef DBUG_OFF
-  int events_till_disconnect;
-#endif
-  bool inited;
-  volatile bool abort_slave;
-  volatile uint slave_running;
-  volatile ulong slave_run_id;
   /*
      The difference in seconds between the clock of the master and the clock of
      the slave (second - first). It must be signed as it may be <0 or >0.
@@ -102,29 +94,49 @@ class Master_info : public Slave_reporti
 
   */
   long clock_diff_with_master;
-  /*
-    Keeps track of the number of events before fsyncing.
-    The option --sync-master-info determines how many
-    events should happen before fsyncing.
-  */
-  uint sync_counter;
   float heartbeat_period;         // interface with CHANGE MASTER or master.info
   ulonglong received_heartbeats;  // counter of received heartbeat events
-  DYNAMIC_ARRAY ignore_server_ids;
+  Server_ids *ignore_server_ids;
   ulong master_id;
   ulong retry_count;
   char master_uuid[UUID_LENGTH+1];
-  char info_file_name[FN_REFLEN + 128];
+
+  int init_info();
+  void end_info();
+  int flush_info(bool force= FALSE);
+  void set_relay_log_info(Relay_log_info *info);
+
+  bool shall_ignore_server_id(ulong s_id);
+
+protected:
+  char master_log_name[FN_REFLEN];
+  my_off_t master_log_pos;
+
+public:
+  void init_master_log_pos();
+  inline const char* get_master_log_name() { return master_log_name; }
+  inline ulonglong get_master_log_pos() { return master_log_pos; }
+  inline void set_master_log_name(const char *log_file_name)
+  {
+     strmake(master_log_name, log_file_name, sizeof(master_log_name) - 1);
+  }
+  inline void set_master_log_pos(ulonglong log_pos)
+  {
+    master_log_pos= log_pos;
+  }
+  inline const char* get_io_rpl_log_name()
+  {
+    return (master_log_name[0] ? master_log_name : "FIRST");
+  }
+  size_t get_number_info_mi_fields();
+
+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(const Master_info& info);
 };
-void init_master_log_pos(Master_info* mi);
-int init_master_info(Master_info* mi, const char* master_info_fname,
-		     const char* slave_info_fname,
-		     bool abort_if_no_master_info_file,
-		     int thread_mask);
-void end_master_info(Master_info* mi);
-int flush_master_info(Master_info* mi, 
-                      bool flush_relay_log_cache, 
-                      bool need_lock_relay_log);
 int change_master_server_id_cmp(ulong *id1, ulong *id2);
 
 #endif /* HAVE_REPLICATION */

=== modified file 'sql/rpl_reporting.h'
--- a/sql/rpl_reporting.h	2010-07-27 14:04:13 +0000
+++ b/sql/rpl_reporting.h	2010-08-05 17:45:25 +0000
@@ -94,13 +94,13 @@ public:
       localtime_r(&skr, &tm_tmp);
       start=&tm_tmp;
 
-      sprintf(timestamp, "%02d%02d%02d %02d:%02d:%02d", 
-                         start->tm_year % 100,
-                         start->tm_mon+1,
-                         start->tm_mday,
-                         start->tm_hour,
-                         start->tm_min,
-                         start->tm_sec);
+      sprintf(timestamp, "%02d%02d%02d %02d:%02d:%02d",
+              start->tm_year % 100,
+              start->tm_mon+1,
+              start->tm_mday,
+              start->tm_hour,
+              start->tm_min,
+              start->tm_sec);
       timestamp[15]= '\0';
     }
 

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2010-09-17 11:32:06 +0000
+++ b/sql/rpl_rli.cc	2010-10-17 23:27:40 +0000
@@ -28,21 +28,40 @@
 #include "sql_parse.h"                          // end_trans, ROLLBACK
 #include "rpl_slave.h"
 
-static int count_relay_log_space(Relay_log_info* rli);
+/*
+  Please every time you add a new field to the relay log info, update
+  what follows. For now, this is just used to get the number of
+  fields.
+*/
+const char* info_rli_fields[]=
+{
+  "number_of_lines",
+  "group_relay_log_name",
+  "group_relay_log_pos",
+  "group_master_log_name",
+  "group_master_log_pos",
+  "sql_delay"
+};
 
 const char *const Relay_log_info::state_delaying_string = "Waiting until MASTER_DELAY seconds after master executed event";
 
-Relay_log_info::Relay_log_info(bool is_slave_recovery)
-  :Slave_reporting_capability("SQL"),
+Relay_log_info::Relay_log_info(bool is_slave_recovery,
+                               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)
+   :Rpl_info("SQL", param_key_info_run_lock, param_key_info_data_lock,
+             param_key_info_data_cond, param_key_info_start_cond,
+             param_key_info_stop_cond),
    replicate_same_server_id(::replicate_same_server_id),
-   info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
-   sync_counter(0), is_relay_log_recovery(is_slave_recovery),
+   cur_log_fd(-1), relay_log(&sync_relaylog_period),
+   is_relay_log_recovery(is_slave_recovery),
    save_temporary_tables(0),
    cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),
    group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
    last_master_timestamp(0), slave_skip_counter(0),
-   abort_pos_wait(0), slave_run_id(0), sql_thd(0),
-   inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
+   abort_pos_wait(0), until_condition(UNTIL_NONE),
    until_log_pos(0), retried_trans(0),
    tables_to_lock(0), tables_to_lock_count(0),
    rows_query_ev(NULL), last_event_start_time(0),
@@ -54,382 +73,26 @@ Relay_log_info::Relay_log_info(bool is_s
   group_relay_log_name[0]= event_relay_log_name[0]=
     group_master_log_name[0]= 0;
   until_log_name[0]= ign_master_log_name_end[0]= 0;
-  bzero((char*) &info_file, sizeof(info_file));
   bzero((char*) &cache_buf, sizeof(cache_buf));
   cached_charset_invalidate();
-  mysql_mutex_init(key_relay_log_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST);
-  mysql_mutex_init(key_relay_log_info_data_lock,
-                   &data_lock, MY_MUTEX_INIT_FAST);
   mysql_mutex_init(key_relay_log_info_log_space_lock,
                    &log_space_lock, MY_MUTEX_INIT_FAST);
-  mysql_cond_init(key_relay_log_info_data_cond, &data_cond, NULL);
-  mysql_cond_init(key_relay_log_info_start_cond, &start_cond, NULL);
-  mysql_cond_init(key_relay_log_info_stop_cond, &stop_cond, NULL);
   mysql_cond_init(key_relay_log_info_log_space_cond, &log_space_cond, NULL);
   relay_log.init_pthread_objects();
   DBUG_VOID_RETURN;
 }
 
-
 Relay_log_info::~Relay_log_info()
 {
   DBUG_ENTER("Relay_log_info::~Relay_log_info");
 
-  mysql_mutex_destroy(&run_lock);
-  mysql_mutex_destroy(&data_lock);
   mysql_mutex_destroy(&log_space_lock);
-  mysql_cond_destroy(&data_cond);
-  mysql_cond_destroy(&start_cond);
-  mysql_cond_destroy(&stop_cond);
   mysql_cond_destroy(&log_space_cond);
   relay_log.cleanup();
-  DBUG_VOID_RETURN;
-}
-
-
-/**
-  Wrapper around Relay_log_info::init(const char *).
-
-  @todo Remove this and replace all calls to it by calls to
-  Relay_log_info::init(const char *). /SVEN
-*/
-int init_relay_log_info(Relay_log_info* rli,
-			const char* info_fname)
-{
-  return rli->init(info_fname);
-}
-
-
-/**
-  Read the relay_log.info file.
-
-  @param info_fname The name of the file to read from.
-  @retval 0 success
-  @retval 1 failure
-*/
-int Relay_log_info::init(const char* info_fname)
-{
-  char fname[FN_REFLEN+128];
-  const char* msg = 0;
-  int error = 0;
-  DBUG_ENTER("init_relay_log_info");
-
-  /*
-    Should not read RLI from file in client threads. Client threads
-    only use RLI to execute BINLOG statements.
-
-    @todo Uncomment the following assertion. Currently,
-    Relay_log_info::init() is called from init_master_info() before
-    the THD object Relay_log_info::sql_thd is created. That means we
-    cannot call belongs_to_client() since belongs_to_client()
-    dereferences Relay_log_info::sql_thd. So we need to refactor
-    slightly: the THD object should be created by Relay_log_info
-    constructor (or passed to it), so that we are guaranteed that it
-    exists at this point. /Sven
-  */
-  // DBUG_ASSERT(!belongs_to_client());
-
-  if (inited)                       // Set if this function called
-    DBUG_RETURN(0);
-  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
-  mysql_mutex_lock(&data_lock);
-  cur_log_fd = -1;
-  slave_skip_counter=0;
-  abort_pos_wait=0;
-  log_space_limit= relay_log_space_limit;
-  log_space_total= 0;
-  tables_to_lock= 0;
-  tables_to_lock_count= 0;
-
-  char pattern[FN_REFLEN];
-  (void) my_realpath(pattern, slave_load_tmpdir, 0);
-  if (fn_format(pattern, PREFIX_SQL_LOAD, pattern, "",
-            MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS)
-  {
-    mysql_mutex_unlock(&data_lock);
-    sql_print_error("Unable to use slave's temporary directory %s",
-                    slave_load_tmpdir);
-    DBUG_RETURN(1);
-  }
-  unpack_filename(slave_patternload_file, pattern);
-  slave_patternload_file_size= strlen(slave_patternload_file);
-
-  /*
-    The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
-    Note that the I/O thread flushes it to disk after writing every
-    event, in flush_master_info(mi, 1, ?).
-  */
-
-  /*
-    For the maximum log size, we choose max_relay_log_size if it is
-    non-zero, max_binlog_size otherwise. If later the user does SET
-    GLOBAL on one of these variables, fix_max_binlog_size and
-    fix_max_relay_log_size will reconsider the choice (for example
-    if the user changes max_relay_log_size to zero, we have to
-    switch to using max_binlog_size for the relay log) and update
-    relay_log.max_size (and mysql_bin_log.max_size).
-  */
-  {
-    /* Reports an error and returns, if the --relay-log's path 
-       is a directory.*/
-    if (opt_relay_logname && 
-        opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR)
-    {
-      mysql_mutex_unlock(&data_lock);
-      sql_print_error("Path '%s' is a directory name, please specify \
-a file name for --relay-log option", opt_relay_logname);
-      DBUG_RETURN(1);
-    }
-
-    /* Reports an error and returns, if the --relay-log-index's path 
-       is a directory.*/
-    if (opt_relaylog_index_name && 
-        opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1] 
-        == FN_LIBCHAR)
-    {
-      mysql_mutex_unlock(&data_lock);
-      sql_print_error("Path '%s' is a directory name, please specify \
-a file name for --relay-log-index option", opt_relaylog_index_name);
-      DBUG_RETURN(1);
-    }
-
-    char buf[FN_REFLEN];
-    const char *ln;
-    static bool name_warning_sent= 0;
-    ln= relay_log.generate_name(opt_relay_logname, "-relay-bin",
-                                     1, buf);
-    /* We send the warning only at startup, not after every RESET SLAVE */
-    if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent)
-    {
-      /*
-        User didn't give us info to name the relay log index file.
-        Picking `hostname`-relay-bin.index like we do, causes replication to
-        fail if this slave's hostname is changed later. So, we would like to
-        instead require a name. But as we don't want to break many existing
-        setups, we only give warning, not error.
-      */
-      sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
-                        " so replication "
-                        "may break when this MySQL server acts as a "
-                        "slave and has his hostname changed!! Please "
-                        "use '--relay-log=%s' to avoid this problem.", ln);
-      name_warning_sent= 1;
-    }
-    /*
-      note, that if open() fails, we'll still have index file open
-      but a destructor will take care of that
-    */
-    if (relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE) ||
-        relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
-                       (max_relay_log_size ? max_relay_log_size :
-                        max_binlog_size), 1, TRUE))
-    {
-      mysql_mutex_unlock(&data_lock);
-      sql_print_error("Failed in open_log() called from init_relay_log_info()");
-      DBUG_RETURN(1);
-    }
-    relay_log.is_relay_log= TRUE;
-  }
-
-  /* if file does not exist */
-  if (access(fname,F_OK))
-  {
-    /*
-      If someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (info_fd >= 0)
-      mysql_file_close(info_fd, MYF(MY_WME));
-    if ((info_fd= mysql_file_open(key_file_relay_log_info,
-                                  fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-    {
-      sql_print_error("Failed to create a new relay log info file (\
-file '%s', errno %d)", fname, my_errno);
-      msg= current_thd->stmt_da->message();
-      goto err;
-    }
-    if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
-                      MYF(MY_WME)))
-    {
-      sql_print_error("Failed to create a cache on relay log info file '%s'",
-                      fname);
-      msg= current_thd->stmt_da->message();
-      goto err;
-    }
-
-    /* Init relay log with first entry in the relay index file */
-    if (init_relay_log_pos(this,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
-                           &msg, 0))
-    {
-      sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
-      goto err;
-    }
-    group_master_log_name[0]= 0;
-    group_master_log_pos= 0;
-  }
-  else // file exists
-  {
-    if (info_fd >= 0)
-      reinit_io_cache(&info_file, READ_CACHE, 0L,0,0);
-    else
-    {
-      int error=0;
-      if ((info_fd= mysql_file_open(key_file_relay_log_info,
-                                    fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-      {
-        sql_print_error("\
-Failed to open the existing relay log info file '%s' (errno %d)",
-                        fname, my_errno);
-        error= 1;
-      }
-      else if (init_io_cache(&info_file, info_fd,
-                             IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on relay log info file '%s'",
-                        fname);
-        error= 1;
-      }
-      if (error)
-      {
-        if (info_fd >= 0)
-          mysql_file_close(info_fd, MYF(0));
-        info_fd= -1;
-        relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-        mysql_mutex_unlock(&data_lock);
-        DBUG_RETURN(1);
-      }
-    }
-
-    int relay_log_pos, master_log_pos, lines;
-    char *first_non_digit;
-
-    /*
-      Starting from 5.1.x, relay-log.info has a new format. Now, its
-      first line contains the number of lines in the file. By reading
-      this number we can determine which version our master.info comes
-      from. We can't simply count the lines in the file, since
-      versions before 5.1.x could generate files with more lines than
-      needed. If first line doesn't contain a number, or if it
-      contains a number less than LINES_IN_RELAY_LOG_INFO_WITH_DELAY,
-      then the file is treated like a file from pre-5.1.x version.
-      There is no ambiguity when reading an old master.info: before
-      5.1.x, the first line contained the binlog's name, which is
-      either empty or has an extension (contains a '.'), so can't be
-      confused with an integer.
-
-      So we're just reading first line and trying to figure which
-      version is this.
-    */
-
-    /*
-      The first row is temporarily stored in mi->master_log_name, if
-      it is line count and not binlog name (new format) it will be
-      overwritten by the second row later.
-    */
-    if (init_strvar_from_file(group_relay_log_name,
-                              sizeof(group_relay_log_name),
-                              &info_file, ""))
-    {
-      msg="Error reading slave log configuration";
-      goto err;
-    }
 
-    lines= strtoul(group_relay_log_name, &first_non_digit, 10);
-
-    if (group_relay_log_name[0] != '\0' &&
-        *first_non_digit == '\0' &&
-        lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
-    {
-      DBUG_PRINT("info", ("relay_log_info file is in new format."));
-      /* Seems to be new format => read relay log name from next line */
-      if (init_strvar_from_file(group_relay_log_name,
-                                sizeof(group_relay_log_name),
-                                &info_file, ""))
-      {
-        msg="Error reading slave log configuration";
-        goto err;
-      }
-    }
-    else
-      DBUG_PRINT("info", ("relay_log_info file is in old format."));
-
-    if (init_intvar_from_file(&relay_log_pos,
-                              &info_file, BIN_LOG_HEADER_SIZE) ||
-        init_strvar_from_file(group_master_log_name,
-                              sizeof(group_master_log_name),
-                              &info_file, "") ||
-        init_intvar_from_file(&master_log_pos, &info_file, 0) ||
-        (lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY &&
-         init_intvar_from_file(&sql_delay, &info_file, 0)))
-    {
-      msg="Error reading slave log configuration";
-      goto err;
-    }
-
-    strmake(event_relay_log_name,group_relay_log_name,
-            sizeof(event_relay_log_name)-1);
-    group_relay_log_pos= event_relay_log_pos= relay_log_pos;
-    group_master_log_pos= master_log_pos;
-
-    if (is_relay_log_recovery && init_recovery(mi, &msg))
-      goto err;
-
-    if (init_relay_log_pos(this,
-                           group_relay_log_name,
-                           group_relay_log_pos,
-                           0 /* no data lock*/,
-                           &msg, 0))
-    {
-      char llbuf[22];
-      sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
-                      group_relay_log_name,
-                      llstr(group_relay_log_pos, llbuf));
-      goto err;
-    }
-  }
-
-#ifndef DBUG_OFF
-  {
-    char llbuf1[22], llbuf2[22];
-    DBUG_PRINT("info", ("my_b_tell(cur_log)=%s event_relay_log_pos=%s",
-                        llstr(my_b_tell(cur_log),llbuf1),
-                        llstr(event_relay_log_pos,llbuf2)));
-    DBUG_ASSERT(event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
-    DBUG_ASSERT(my_b_tell(cur_log) == event_relay_log_pos);
-  }
-#endif
-
-  /*
-    Now change the cache from READ to WRITE - must do this
-    before flush_relay_log_info
-  */
-  reinit_io_cache(&info_file, WRITE_CACHE,0L,0,1);
-  if ((error= flush_relay_log_info(this)))
-  {
-    msg= "Failed to flush relay log info file";
-    goto err;
-  }
-  if (count_relay_log_space(this))
-  {
-    msg="Error counting relay log space";
-    goto err;
-  }
-  inited= 1;
-  mysql_mutex_unlock(&data_lock);
-  DBUG_RETURN(error);
-
-err:
-  sql_print_error("%s", msg);
-  end_io_cache(&info_file);
-  if (info_fd >= 0)
-    mysql_file_close(info_fd, MYF(0));
-  info_fd= -1;
-  relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  mysql_mutex_unlock(&data_lock);
-  DBUG_RETURN(1);
+  DBUG_VOID_RETURN;
 }
 
-
 static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo)
 {
   MY_STAT s;
@@ -449,38 +112,32 @@ static inline int add_relay_log(Relay_lo
   DBUG_RETURN(0);
 }
 
-
-static int count_relay_log_space(Relay_log_info* rli)
+int Relay_log_info::count_relay_log_space()
 {
-  LOG_INFO linfo;
-  DBUG_ENTER("count_relay_log_space");
-  rli->log_space_total= 0;
-  if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
+  LOG_INFO flinfo;
+  DBUG_ENTER("Relay_log_info::count_relay_log_space");
+  log_space_total= 0;
+  if (relay_log.find_log_pos(&flinfo, NullS, 1))
   {
     sql_print_error("Could not find first log while counting relay log space");
     DBUG_RETURN(1);
   }
   do
   {
-    if (add_relay_log(rli,&linfo))
+    if (add_relay_log(this, &flinfo))
       DBUG_RETURN(1);
-  } while (!rli->relay_log.find_next_log(&linfo, 1));
+  } while (!relay_log.find_next_log(&flinfo, 1));
   /*
      As we have counted everything, including what may have written in a
      preceding write, we must reset bytes_written, or we may count some space
      twice.
   */
-  rli->relay_log.reset_bytes_written();
+  relay_log.reset_bytes_written();
   DBUG_RETURN(0);
 }
 
-
-/*
-   Reset UNTIL condition for Relay_log_info
-
-   SYNOPSYS
-    clear_until_condition()
-      rli - Relay_log_info structure where UNTIL condition should be reset
+/**
+   Resets UNTIL condition for Relay_log_info
  */
 
 void Relay_log_info::clear_until_condition()
@@ -493,52 +150,46 @@ void Relay_log_info::clear_until_conditi
   DBUG_VOID_RETURN;
 }
 
+/**
+  Opens and intialize the given relay log. Specifically, it does what follows:
 
-/*
-  Open the given relay log
-
-  SYNOPSIS
-    init_relay_log_pos()
-    rli                 Relay information (will be initialized)
-    log                 Name of relay log file to read from. NULL = First log
-    pos                 Position in relay log file
-    need_data_lock      Set to 1 if this functions should do mutex locks
-    errmsg              Store pointer to error message here
-    look_for_description_event
-                        1 if we should look for such an event. We only need
-                        this when the SQL thread starts and opens an existing
-                        relay log and has to execute it (possibly from an
-                        offset >4); then we need to read the first event of
-                        the relay log to be able to parse the events we have
-                        to execute.
-
-  DESCRIPTION
-  - Close old open relay log files.
-  - If we are using the same relay log as the running IO-thread, then set
+  - Closes old open relay log files.
+  - If we are using the same relay log as the running IO-thread, then sets.
     rli->cur_log to point to the same IO_CACHE entry.
-  - If not, open the 'log' binary file.
+  - If not, opens the 'log' binary file.
+
+  @todo check proper initialization of group_master_log_name/group_master_log_pos.
 
-  TODO
-    - check proper initialization of group_master_log_name/group_master_log_pos
 
-  RETURN VALUES
-    0   ok
-    1   error.  errmsg is set to point to the error message
+  @param  rli[in]                 Relay information (will be initialized)
+  @param  log[in]                 Name of relay log file to read from. NULL = First log
+  @param  pos[in]                 Position in relay log file
+  @param  need_data_lock[in]      Set to 1 if this functions should do mutex locks
+  @param  errmsg[out]             Store pointer to error message here
+  @param  look_for_description_event[in]
+                                  1 if we should look for such an event. We only need
+                                  this when the SQL thread starts and opens an existing
+                                  relay log and has to execute it (possibly from an
+                                  offset >4); then we need to read the first event of
+                                  the relay log to be able to parse the events we have
+                                  to execute.
+  @retval 0 ok,
+  @retval 1 otherwise error, where errmsg is set to point to the error message.
 */
 
-int init_relay_log_pos(Relay_log_info* rli,const char* log,
-                       ulonglong pos, bool need_data_lock,
-                       const char** errmsg,
-                       bool look_for_description_event)
+int Relay_log_info::init_relay_log_pos(const char* log,
+                                       ulonglong pos, bool need_data_lock,
+                                       const char** errmsg,
+                                       bool look_for_description_event)
 {
-  DBUG_ENTER("init_relay_log_pos");
+  DBUG_ENTER("Relay_log_info::init_relay_log_pos");
   DBUG_PRINT("info", ("pos: %lu", (ulong) pos));
 
   *errmsg=0;
-  mysql_mutex_t *log_lock= rli->relay_log.get_log_lock();
+  mysql_mutex_t *log_lock= relay_log.get_log_lock();
 
   if (need_data_lock)
-    mysql_mutex_lock(&rli->data_lock);
+    mysql_mutex_lock(&data_lock);
 
   /*
     Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER
@@ -548,68 +199,70 @@ int init_relay_log_pos(Relay_log_info* r
     the description_event here, in case, so that there is no memory leak in
     running, say, CHANGE MASTER.
   */
-  delete rli->relay_log.description_event_for_exec;
+  delete relay_log.description_event_for_exec;
   /*
     By default the relay log is in binlog format 3 (4.0).
     Even if format is 4, this will work enough to read the first event
     (Format_desc) (remember that format 4 is just lenghtened compared to format
     3; format 3 is a prefix of format 4).
   */
-  rli->relay_log.description_event_for_exec= new
+  relay_log.description_event_for_exec= new
     Format_description_log_event(3);
 
   mysql_mutex_lock(log_lock);
 
   /* Close log file and free buffers if it's already open */
-  if (rli->cur_log_fd >= 0)
+  if (cur_log_fd >= 0)
   {
-    end_io_cache(&rli->cache_buf);
-    mysql_file_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
+    end_io_cache(&cache_buf);
+    mysql_file_close(cur_log_fd, MYF(MY_WME));
+    cur_log_fd = -1;
   }
 
-  rli->group_relay_log_pos = rli->event_relay_log_pos = pos;
+  group_relay_log_pos= event_relay_log_pos= pos;
 
   /*
     Test to see if the previous run was with the skip of purging
     If yes, we do not purge when we restart
   */
-  if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1))
+  if (relay_log.find_log_pos(&linfo, NullS, 1))
   {
     *errmsg="Could not find first log during relay log initialization";
     goto err;
   }
 
-  if (log && rli->relay_log.find_log_pos(&rli->linfo, log, 1))
+  if (log && relay_log.find_log_pos(&linfo, log, 1))
   {
     *errmsg="Could not find target log during relay log initialization";
     goto err;
   }
-  strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
-          sizeof(rli->group_relay_log_name)-1);
-  strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
-          sizeof(rli->event_relay_log_name)-1);
-  if (rli->relay_log.is_active(rli->linfo.log_file_name))
+
+  strmake(group_relay_log_name, linfo.log_file_name,
+          sizeof(group_relay_log_name) - 1);
+  strmake(event_relay_log_name, linfo.log_file_name,
+          sizeof(event_relay_log_name) - 1);
+
+  if (relay_log.is_active(linfo.log_file_name))
   {
     /*
       The IO thread is using this log file.
       In this case, we will use the same IO_CACHE pointer to
       read data as the IO thread is using to write data.
     */
-    my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0);
-    if (check_binlog_magic(rli->cur_log,errmsg))
+    my_b_seek((cur_log=relay_log.get_log_file()), (off_t)0);
+    if (check_binlog_magic(cur_log, errmsg))
       goto err;
-    rli->cur_log_old_open_count=rli->relay_log.get_open_count();
+    cur_log_old_open_count=relay_log.get_open_count();
   }
   else
   {
     /*
-      Open the relay log and set rli->cur_log to point at this one
+      Open the relay log and set cur_log to point at this one
     */
-    if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
-                                     rli->linfo.log_file_name,errmsg)) < 0)
+    if ((cur_log_fd=open_binlog(&cache_buf,
+                                linfo.log_file_name,errmsg)) < 0)
       goto err;
-    rli->cur_log = &rli->cache_buf;
+    cur_log = &cache_buf;
   }
   /*
     In all cases, check_binlog_magic() has been called so we're at offset 4 for
@@ -626,19 +279,19 @@ int init_relay_log_pos(Relay_log_info* r
       */
       DBUG_PRINT("info",("looking for a Format_description_log_event"));
 
-      if (my_b_tell(rli->cur_log) >= pos)
+      if (my_b_tell(cur_log) >= pos)
         break;
 
       /*
-        Because of we have rli->data_lock and log_lock, we can safely read an
+        Because of we have data_lock and log_lock, we can safely read an
         event
       */
-      if (!(ev=Log_event::read_log_event(rli->cur_log,0,
-                                         rli->relay_log.description_event_for_exec)))
+      if (!(ev=Log_event::read_log_event(cur_log,0,
+                                         relay_log.description_event_for_exec)))
       {
-        DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
-                           rli->cur_log->error));
-        if (rli->cur_log->error) /* not EOF */
+        DBUG_PRINT("info",("could not read event, cur_log->error=%d",
+                           cur_log->error));
+        if (cur_log->error) /* not EOF */
         {
           *errmsg= "I/O error reading event at position 4";
           goto err;
@@ -648,8 +301,8 @@ int init_relay_log_pos(Relay_log_info* r
       else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
       {
         DBUG_PRINT("info",("found Format_description_log_event"));
-        delete rli->relay_log.description_event_for_exec;
-        rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev;
+        delete relay_log.description_event_for_exec;
+        relay_log.description_event_for_exec= (Format_description_log_event*) ev;
         /*
           As ev was returned by read_log_event, it has passed is_valid(), so
           my_malloc() in ctor worked, no need to check again.
@@ -679,13 +332,13 @@ int init_relay_log_pos(Relay_log_info* r
         delete ev;
       }
     }
-    my_b_seek(rli->cur_log,(off_t)pos);
+    my_b_seek(cur_log,(off_t)pos);
 #ifndef DBUG_OFF
   {
     char llbuf1[22], llbuf2[22];
-    DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
-                        llstr(my_b_tell(rli->cur_log),llbuf1),
-                        llstr(rli->event_relay_log_pos,llbuf2)));
+    DBUG_PRINT("info", ("my_b_tell(cur_log)=%s >event_relay_log_pos=%s",
+                        llstr(my_b_tell(cur_log),llbuf1),
+                        llstr(get_event_relay_log_pos(),llbuf2)));
   }
 #endif
 
@@ -697,44 +350,37 @@ err:
     silently discard it
   */
   if (!relay_log_purge)
-    rli->log_space_limit= 0;
-  mysql_cond_broadcast(&rli->data_cond);
+    log_space_limit= 0;
+  mysql_cond_broadcast(&data_cond);
 
   mysql_mutex_unlock(log_lock);
 
   if (need_data_lock)
-    mysql_mutex_unlock(&rli->data_lock);
-  if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
+    mysql_mutex_unlock(&data_lock);
+  if (!relay_log.description_event_for_exec->is_valid() && !*errmsg)
     *errmsg= "Invalid Format_description log event; could be out of memory";
 
-  DBUG_PRINT("info", ("Returning %d from init_relay_log_pos", (*errmsg)?1:0));
-
   DBUG_RETURN ((*errmsg) ? 1 : 0);
 }
 
-
-/*
+/**
   Waits until the SQL thread reaches (has executed up to) the
   log/position or timed out.
 
   SYNOPSIS
-    wait_for_pos()
-    thd             client thread that sent SELECT MASTER_POS_WAIT
-    log_name        log name to wait for
-    log_pos         position to wait for
-    timeout         timeout in seconds before giving up waiting
-
-  NOTES
-    timeout is longlong whereas it should be ulong ; but this is
-    to catch if the user submitted a negative timeout.
+  @param[in]  thd             client thread that sent @c SELECT @c MASTER_POS_WAIT,
+  @param[in]  log_name        log name to wait for,
+  @param[in]  log_pos         position to wait for,
+  @param[in]  timeout         @c timeout in seconds before giving up waiting.
+                              @c timeout is longlong whereas it should be ulong; but this is
+                              to catch if the user submitted a negative timeout.
 
-  RETURN VALUES
-    -2          improper arguments (log_pos<0)
+  @retval  -2   improper arguments (log_pos<0)
                 or slave not running, or master info changed
                 during the function's execution,
-                or client thread killed. -2 is translated to NULL by caller
-    -1          timed out
-    >=0         number of log events the function had to wait
+                or client thread killed. -2 is translated to NULL by caller,
+  @retval  -1   timed out
+  @retval  >=0  number of log events the function had to wait
                 before reaching the desired log/position
  */
 
@@ -917,7 +563,6 @@ improper_arguments: %d  timed_out: %d",
   DBUG_RETURN( error ? error : event_count );
 }
 
-
 void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
                                                 bool skip_lock)
 {
@@ -998,51 +643,55 @@ void Relay_log_info::close_temporary_tab
   DBUG_VOID_RETURN;
 }
 
-/*
-  purge_relay_logs()
+/**
+  Purges relay logs. It assumes to have a run lock on rli and that no
+  slave thread are running.
+
+  @param[in]   THD         connection,
+  @param[in]   just_reset  if false, it tells that logs should be purged
+                           and @c init_relay_log_pos() should be called,
+  @errmsg[out] errmsg      store pointer to an error message.
 
-  NOTES
-    Assumes to have a run lock on rli and that no slave thread are running.
+  @retval 0 successfuly executed,
+  @retval 1 otherwise error, where errmsg is set to point to the error message.
 */
 
-int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
-                     const char** errmsg)
+int Relay_log_info::purge_relay_logs(THD *thd, bool just_reset,
+                                     const char** errmsg)
 {
   int error=0;
   DBUG_ENTER("purge_relay_logs");
 
   /*
-    Even if rli->inited==0, we still try to empty rli->master_log_* variables.
-    Indeed, rli->inited==0 does not imply that they already are empty.
-    It could be that slave's info initialization partly succeeded :
-    for example if relay-log.info existed but *relay-bin*.*
-    have been manually removed, init_relay_log_info reads the old
-    relay-log.info and fills rli->master_log_*, then init_relay_log_info
-    checks for the existence of the relay log, this fails and
-    init_relay_log_info leaves rli->inited to 0.
-    In that pathological case, rli->master_log_pos* will be properly reinited
-    at the next START SLAVE (as RESET SLAVE or CHANGE
-    MASTER, the callers of purge_relay_logs, will delete bogus *.info files
-    or replace them with correct files), however if the user does SHOW SLAVE
-    STATUS before START SLAVE, he will see old, confusing rli->master_log_*.
-    In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
-    to display fine in any case.
-  */
+    Even if inited==0, we still try to empty master_log_* variables. Indeed,
+    inited==0 does not imply that they already are empty.
 
-  rli->group_master_log_name[0]= 0;
-  rli->group_master_log_pos= 0;
+    It could be that slave's info initialization partly succeeded: for example
+    if relay-log.info existed but *relay-bin*.* have been manually removed,
+    init_info reads the old relay-log.info and fills rli->master_log_*, then
+    init_info checks for the existence of the relay log, this fails and 
+    init_info leaves inited to 0.
+    In that pathological case, master_log_pos* will be properly reinited at
+    the next START SLAVE (as RESET SLAVE or CHANGE MASTER, the callers of
+    purge_relay_logs, will delete bogus *.info files or replace them with
+    correct files), however if the user does SHOW SLAVE STATUS before START
+    SLAVE, he will see old, confusing master_log_*. In other words, we reinit
+    master_log_* for SHOW SLAVE STATUS to display fine in any case.
+  */
+  group_master_log_name[0]= 0;
+  group_master_log_pos= 0;
 
-  if (!rli->inited)
+  if (!inited)
   {
-    DBUG_PRINT("info", ("rli->inited == 0"));
+    DBUG_PRINT("info", ("inited == 0"));
     DBUG_RETURN(0);
   }
 
-  DBUG_ASSERT(rli->slave_running == 0);
-  DBUG_ASSERT(rli->mi->slave_running == 0);
+  DBUG_ASSERT(slave_running == 0);
+  DBUG_ASSERT(mi->slave_running == 0);
 
-  rli->slave_skip_counter=0;
-  mysql_mutex_lock(&rli->data_lock);
+  slave_skip_counter= 0;
+  mysql_mutex_lock(&data_lock);
 
   /*
     we close the relay log fd possibly left open by the slave SQL thread,
@@ -1050,77 +699,74 @@ int purge_relay_logs(Relay_log_info* rli
     I/O thread will be closed naturally in reset_logs() by the
     close(LOG_CLOSE_TO_BE_OPENED) call
   */
-  if (rli->cur_log_fd >= 0)
+  if (cur_log_fd >= 0)
   {
-    end_io_cache(&rli->cache_buf);
-    mysql_file_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd= -1;
+    end_io_cache(&cache_buf);
+    my_close(cur_log_fd, MYF(MY_WME));
+    cur_log_fd= -1;
   }
 
-  if (rli->relay_log.reset_logs(thd))
+  if (relay_log.reset_logs(thd))
   {
     *errmsg = "Failed during log reset";
     error=1;
     goto err;
   }
   /* Save name of used relay log file */
-  strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(),
-          sizeof(rli->group_relay_log_name)-1);
-  strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
-          sizeof(rli->event_relay_log_name)-1);
-  rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
-  if (count_relay_log_space(rli))
+  strmake(group_relay_log_name, relay_log.get_log_fname(),
+          sizeof(group_relay_log_name)-1);
+  strmake(event_relay_log_name, relay_log.get_log_fname(),
+          sizeof(event_relay_log_name)-1);
+  group_relay_log_pos= event_relay_log_pos= BIN_LOG_HEADER_SIZE;
+  if (count_relay_log_space())
   {
     *errmsg= "Error counting relay log space";
-    error=1;
+    error= 1;
     goto err;
   }
   if (!just_reset)
-    error= init_relay_log_pos(rli, rli->group_relay_log_name,
-                              rli->group_relay_log_pos,
+    error= init_relay_log_pos(group_relay_log_name,
+                              group_relay_log_pos,
                               0 /* do not need data lock */, errmsg, 0);
 
 err:
 #ifndef DBUG_OFF
   char buf[22];
 #endif
-  DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf)));
-  mysql_mutex_unlock(&rli->data_lock);
+  DBUG_PRINT("info",("log_space_total: %s",llstr(log_space_total,buf)));
+  mysql_mutex_unlock(&data_lock);
   DBUG_RETURN(error);
 }
 
 
-/*
-     Check if condition stated in UNTIL clause of START SLAVE is reached.
-   SYNOPSYS
-     Relay_log_info::is_until_satisfied()
-     master_beg_pos    position of the beginning of to be executed event
-                       (not log_pos member of the event that points to the
-                        beginning of the following event)
-
+/**
+     Checks if condition stated in UNTIL clause of START SLAVE is reached.
 
-   DESCRIPTION
-     Checks if UNTIL condition is reached. Uses caching result of last
-     comparison of current log file name and target log file name. So cached
-     value should be invalidated if current log file name changes
-     (see Relay_log_info::notify_... functions).
+     Specifically, it checks if UNTIL condition is reached. Uses caching result
+     of last comparison of current log file name and target log file name. So
+     cached value should be invalidated if current log file name changes (see
+     @c Relay_log_info::notify_... functions).
 
      This caching is needed to avoid of expensive string comparisons and
-     strtol() conversions needed for log names comparison. We don't need to
+     @c strtol() conversions needed for log names comparison. We don't need to
      compare them each time this function is called, we only need to do this
-     when current log name changes. If we have UNTIL_MASTER_POS condition we
-     need to do this only after Rotate_log_event::do_apply_event() (which is
-     rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS
+     when current log name changes. If we have @c UNTIL_MASTER_POS condition we
+     need to do this only after @c Rotate_log_event::do_apply_event() (which is
+     rare, so caching gives real benifit), and if we have @c UNTIL_RELAY_POS
      condition then we should invalidate cached comarison value after
-     inc_group_relay_log_pos() which called for each group of events (so we
+     @c inc_group_relay_log_pos() which called for each group of events (so we
      have some benefit if we have something like queries that use
      autoincrement or if we have transactions).
 
-     Should be called ONLY if until_condition != UNTIL_NONE !
-   RETURN VALUE
-     true - condition met or error happened (condition seems to have
-            bad log file name)
-     false - condition not met
+     Should be called ONLY if @c until_condition @c != @c UNTIL_NONE !
+
+     @param master_beg_pos    position of the beginning of to be executed event
+                              (not @c log_pos member of the event that points to
+                              the beginning of the following event)
+
+     @retval true   condition met or error happened (condition seems to have
+                    bad log file name),
+     @retval false  condition not met.
 */
 
 bool Relay_log_info::is_until_satisfied(THD *thd, Log_event *ev)
@@ -1258,12 +904,12 @@ void Relay_log_info::stmt_done(my_off_t 
     middle of the "transaction". START SLAVE will resume at BEGIN
     while the MyISAM table has already been updated.
   */
-  if ((sql_thd->variables.option_bits & OPTION_BEGIN) && opt_using_transactions)
+  if ((info_thd->variables.option_bits & OPTION_BEGIN) && opt_using_transactions)
     inc_event_relay_log_pos();
   else
   {
     inc_group_relay_log_pos(event_master_log_pos);
-    flush_relay_log_info(this);
+    flush_info(is_transactional() ? TRUE : FALSE);
   }
 }
 
@@ -1272,7 +918,7 @@ void Relay_log_info::cleanup_context(THD
 {
   DBUG_ENTER("Relay_log_info::cleanup_context");
 
-  DBUG_ASSERT(sql_thd == thd);
+  DBUG_ASSERT(info_thd == thd);
   /*
     1) Instances of Table_map_log_event, if ::do_apply_event() was called on them,
     may have opened tables, which we cannot be sure have been closed (because
@@ -1372,7 +1018,474 @@ bool mysql_show_relaylog_events(THD* thd
   if (!active_mi)
     DBUG_RETURN(TRUE);
   
-  DBUG_RETURN(show_binlog_events(thd, &active_mi->rli.relay_log));
+  DBUG_RETURN(show_binlog_events(thd, &active_mi->rli->relay_log));
 }
 
 #endif
+
+int Relay_log_info::init_info()
+{
+  int error= 0;
+  const char *msg= NULL;
+
+  DBUG_ENTER("Relay_log_info::init_info");
+
+  if (inited)
+  {
+    /*
+      We have to reset read position of relay-log-bin as we may have
+      already been reading from 'hotlog' when the slave was stopped
+      last time. If this case pos_in_file would be set and we would
+      get a crash when trying to read the signature for the binary
+      relay log.
+
+      We only rewind the read position if we are starting the SQL
+      thread. The handle_slave_sql thread assumes that the read
+      position is at the beginning of the file, and will read the
+      "signature" and then fast-forward to the last position read.
+    */
+    bool hot_log= FALSE;
+    /* 
+      my_b_seek does an implicit flush_io_cache, so we need to:
+
+      1. check if this log is active (hot)
+      2. if it is we keep log_lock until the seek ends, otherwise 
+         release it right away.
+
+      If we did not take log_lock, SQL thread might race with IO
+      thread for the IO_CACHE mutex.
+
+    */
+    mysql_mutex_t *log_lock= relay_log.get_log_lock();
+    mysql_mutex_lock(log_lock);
+    hot_log= relay_log.is_active(linfo.log_file_name);
+
+    if (!hot_log)
+      mysql_mutex_unlock(log_lock);
+
+    my_b_seek(cur_log, (my_off_t) 0);
+
+    if (hot_log)
+      mysql_mutex_unlock(log_lock);
+
+    DBUG_RETURN(0);
+  }
+
+  cur_log_fd = -1;
+  slave_skip_counter= 0;
+  abort_pos_wait= 0;
+  log_space_limit= relay_log_space_limit;
+  log_space_total= 0;
+  tables_to_lock= 0;
+  tables_to_lock_count= 0;
+
+  char pattern[FN_REFLEN];
+  (void) my_realpath(pattern, slave_load_tmpdir, 0);
+  if (fn_format(pattern, PREFIX_SQL_LOAD, pattern, "",
+                MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS)
+  {
+    sql_print_error("Unable to use slave's temporary directory %s",
+                    slave_load_tmpdir);
+    DBUG_RETURN(1);
+  }
+  unpack_filename(slave_patternload_file, pattern);
+  slave_patternload_file_size= strlen(slave_patternload_file);
+
+  /*
+    The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
+    Note that the I/O thread flushes it to disk after writing every
+    event, in flush_info within the master info.
+  */
+  /*
+    For the maximum log size, we choose max_relay_log_size if it is
+    non-zero, max_binlog_size otherwise. If later the user does SET
+    GLOBAL on one of these variables, fix_max_binlog_size and
+    fix_max_relay_log_size will reconsider the choice (for example
+    if the user changes max_relay_log_size to zero, we have to
+    switch to using max_binlog_size for the relay log) and update
+    relay_log.max_size (and mysql_bin_log.max_size).
+  */
+  {
+    /* Reports an error and returns, if the --relay-log's path
+       is a directory.*/
+    if (opt_relay_logname &&
+        opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR)
+    {
+      sql_print_error("Path '%s' is a directory name, please specify \
+a file name for --relay-log option", opt_relay_logname);
+      DBUG_RETURN(1);
+    }
+
+    /* Reports an error and returns, if the --relay-log-index's path
+       is a directory.*/
+    if (opt_relaylog_index_name &&
+        opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1]
+        == FN_LIBCHAR)
+    {
+      sql_print_error("Path '%s' is a directory name, please specify \
+a file name for --relay-log-index option", opt_relaylog_index_name);
+      DBUG_RETURN(1);
+    }
+
+    char buf[FN_REFLEN];
+    const char *ln;
+    static bool name_warning_sent= 0;
+    ln= relay_log.generate_name(opt_relay_logname, "-relay-bin",
+                                1, buf);
+    /* We send the warning only at startup, not after every RESET SLAVE */
+    if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent)
+    {
+      /*
+        User didn't give us info to name the relay log index file.
+        Picking `hostname`-relay-bin.index like we do, causes replication to
+        fail if this slave's hostname is changed later. So, we would like to
+        instead require a name. But as we don't want to break many existing
+        setups, we only give warning, not error.
+      */
+      sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
+                        " so replication "
+                        "may break when this MySQL server acts as a "
+                        "slave and has his hostname changed!! Please "
+                        "use '--relay-log=%s' to avoid this problem.", ln);
+      name_warning_sent= 1;
+    }
+    /*
+      note, that if open() fails, we'll still have index file open
+      but a destructor will take care of that
+    */
+    if (relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE) ||
+        relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
+                       (max_relay_log_size ? max_relay_log_size :
+                        max_binlog_size), 1, TRUE))
+    {
+      sql_print_error("Failed in open_log() called from Relay_log_info::init_info()");
+      DBUG_RETURN(1);
+    }
+    relay_log.is_relay_log= TRUE;
+  }
+
+  /*
+    This checks if the repository was created before and thus there
+    will be values to be read. Please, do not move this call after
+    the handler->init_info().
+  */
+  int necessary_to_configure= check_info();
+  if ((error= handler->init_info()))
+  {
+    msg= "Error reading relay log configuration";
+    error= 1;
+    goto err;
+  }
+
+  if (necessary_to_configure)
+  {
+    /* Init relay log with first entry in the relay index file */
+    if (init_relay_log_pos(NullS, BIN_LOG_HEADER_SIZE, 0 /* no data lock */,
+                           &msg, 0))
+    {
+      error= 1;
+      goto err;
+    }
+    group_master_log_name[0]= 0;
+    group_master_log_pos= 0;
+  }
+  else
+  {
+    if (read_info(handler))
+    {
+      msg= "Error reading relay log configuration";
+      error= 1;
+      goto err;
+    }
+
+    if (is_relay_log_recovery && init_recovery(mi, &msg))
+    {
+      error= 1;
+      goto err;
+    }
+
+    if (init_relay_log_pos(group_relay_log_name,
+                           group_relay_log_pos,
+                           0 /* no data lock*/,
+                           &msg, 0))
+    {
+      char llbuf[22];
+      sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
+                      group_relay_log_name,
+                      llstr(group_relay_log_pos, llbuf));
+      error= 1;
+      goto err;
+    }
+
+#ifndef DBUG_OFF
+    {
+      char llbuf1[22], llbuf2[22];
+      DBUG_PRINT("info", ("my_b_tell(cur_log)=%s event_relay_log_pos=%s",
+                          llstr(my_b_tell(cur_log),llbuf1),
+                          llstr(event_relay_log_pos,llbuf2)));
+      DBUG_ASSERT(event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
+      DBUG_ASSERT((my_b_tell(cur_log) == event_relay_log_pos));
+    }
+#endif
+  }
+
+  if ((error= flush_info(TRUE)))
+  {
+    msg= "Error reading relay log configuration";
+    error= 1;
+    goto err;
+  }
+
+  if (count_relay_log_space())
+  {
+    msg= "Error counting relay log space";
+    error= 1;
+    goto err;
+  }
+
+  inited= 1;
+  is_relay_log_recovery= FALSE;
+  DBUG_RETURN(error);
+
+err:
+  sql_print_error("%s", msg);
+  relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+  DBUG_RETURN(error);
+}
+
+void Relay_log_info::end_info()
+{
+  DBUG_ENTER("Relay_log_info::end_info");
+
+  if (!inited)
+    DBUG_VOID_RETURN;
+
+  handler->end_info();
+
+  if (cur_log_fd >= 0)
+  {
+    end_io_cache(&cache_buf);
+    (void)my_close(cur_log_fd, MYF(MY_WME));
+    cur_log_fd= -1;
+  }
+  inited = 0;
+  relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+  relay_log.harvest_bytes_written(&log_space_total);
+  /*
+    Delete the slave's temporary tables from memory.
+    In the future there will be other actions than this, to ensure persistance
+    of slave's temp tables after shutdown.
+  */
+  close_temporary_tables();
+
+  DBUG_VOID_RETURN;
+}
+
+int Relay_log_info::flush_current_log()
+{
+  DBUG_ENTER("Relay_log_info::flush_current_log");
+  /*
+    When we come to this place in code, relay log may or not be initialized;
+    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
+  */
+  IO_CACHE *log_file= relay_log.get_log_file();
+  if (flush_io_cache(log_file))
+    DBUG_RETURN(2);
+
+  DBUG_RETURN(0);
+}
+
+void Relay_log_info::set_master_info(Master_info* info)
+{
+  mi= info;
+}
+
+/**
+  Stores the file and position where the execute-slave thread are in the
+  relay log:
+
+    - As this is only called by the slave thread or on STOP SLAVE, with the
+      log_lock grabbed and the slave thread stopped, we don't need to have
+      a lock here.
+    - If there is an active transaction, then we don't update the position
+      in the relay log.  This is to ensure that we re-execute statements
+      if we die in the middle of an transaction that was rolled back.
+    - As a transaction never spans binary logs, we don't have to handle the
+      case where we do a relay-log-rotation in the middle of the transaction.
+      If this would not be the case, we would have to ensure that we
+      don't delete the relay log file where the transaction started when
+      we switch to a new relay log file.
+
+  @retval  0   ok,
+  @retval  1   write error, otherwise.
+*/
+
+/**
+  Store the file and position where the slave's SQL thread are in the
+  relay log.
+
+  Notes:
+
+  - This function should be called either from the slave SQL thread,
+    or when the slave thread is not running.  (It reads the
+    group_{relay|master}_log_{pos|name} and delay fields in the rli
+    object.  These may only be modified by the slave SQL thread or by
+    a client thread when the slave SQL thread is not running.)
+
+  - If there is an active transaction, then we do not update the
+    position in the relay log.  This is to ensure that we re-execute
+    statements if we die in the middle of an transaction that was
+    rolled back.
+
+  - As a transaction never spans binary logs, we don't have to handle
+    the case where we do a relay-log-rotation in the middle of the
+    transaction.  If transactions could span several binlogs, we would
+    have to ensure that we do not delete the relay log file where the
+    transaction started before switching to a new relay log file.
+
+  - Error can happen if writing to file fails or if flushing the file
+    fails.
+
+  @param rli The object representing the Relay_log_info.
+
+  @todo Change the log file information to a binary format to avoid
+  calling longlong2str.
+
+  @return 0 on success, 1 on error.
+*/
+int Relay_log_info::flush_info(bool force)
+{
+  DBUG_ENTER("Relay_log_info::flush_info");
+
+  /* 
+    We update the sync_period at this point because only here we
+    now that we are handling a relay log info. This needs to be
+    update every time we call flush because the option maybe 
+    dinamically set.
+  */
+  handler->set_sync_period(sync_relayloginfo_period);
+
+  if (write_info(handler, force))
+    goto err;
+
+  DBUG_RETURN(0);
+
+err:
+  sql_print_error("Error writing relay log configuration");
+  DBUG_RETURN(1);
+}
+
+size_t Relay_log_info::get_number_info_rli_fields() 
+{ 
+  return sizeof(info_rli_fields)/sizeof(info_rli_fields[0]);
+}
+
+bool Relay_log_info::read_info(Rpl_info_handler *from)
+{
+  int lines= 0;
+  char *first_non_digit= NULL;
+  ulong temp_group_relay_log_pos= 0;
+  ulong temp_group_master_log_pos= 0;
+  int temp_sql_delay= 0;
+
+  DBUG_ENTER("Relay_log_info::read_info");
+
+  /*
+    Should not read RLI from file in client threads. Client threads
+    only use RLI to execute BINLOG statements.
+
+    @todo Uncomment the following assertion. Currently,
+    Relay_log_info::init() is called from init_master_info() before
+    the THD object Relay_log_info::sql_thd is created. That means we
+    cannot call belongs_to_client() since belongs_to_client()
+    dereferences Relay_log_info::sql_thd. So we need to refactor
+    slightly: the THD object should be created by Relay_log_info
+    constructor (or passed to it), so that we are guaranteed that it
+    exists at this point. /Sven
+  */
+  //DBUG_ASSERT(!belongs_to_client());
+
+  /*
+    Starting from 5.1.x, relay-log.info has a new format. Now, its
+    first line contains the number of lines in the file. By reading
+    this number we can determine which version our master.info comes
+    from. We can't simply count the lines in the file, since
+    versions before 5.1.x could generate files with more lines than
+    needed. If first line doesn't contain a number, or if it
+    contains a number less than LINES_IN_RELAY_LOG_INFO_WITH_DELAY,
+    then the file is treated like a file from pre-5.1.x version.
+    There is no ambiguity when reading an old master.info: before
+    5.1.x, the first line contained the binlog's name, which is
+    either empty or has an extension (contains a '.'), so can't be
+    confused with an integer.
+
+    So we're just reading first line and trying to figure which
+    version is this.
+  */
+
+  /*
+    The first row is temporarily stored in mi->master_log_name, if
+    it is line count and not binlog name (new format) it will be
+    overwritten by the second row later.
+  */
+  if (from->prepare_info_for_read() ||
+      from->get_info(group_relay_log_name, sizeof(group_relay_log_name), ""))
+    DBUG_RETURN(TRUE);
+
+  lines= strtoul(group_relay_log_name, &first_non_digit, 10);
+
+  if (group_relay_log_name[0]!='\0' &&
+      *first_non_digit=='\0' && lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
+  {
+    /* Seems to be new format => read group relay log name */
+    if (from->get_info(group_relay_log_name,  sizeof(group_relay_log_name), ""))
+      DBUG_RETURN(TRUE);
+  }
+  else
+     DBUG_PRINT("info", ("relay_log_info file is in old format."));
+
+  if (from->get_info((ulong *) &temp_group_relay_log_pos,
+                        (ulong) BIN_LOG_HEADER_SIZE) ||
+      from->get_info(group_master_log_name,
+                        sizeof(group_relay_log_name), "") ||
+      from->get_info((ulong *) &temp_group_master_log_pos,
+                        (ulong) 0))
+    DBUG_RETURN(TRUE);
+
+  if (lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
+  {
+    if (from->get_info((int *) &temp_sql_delay,(int) 0))
+      DBUG_RETURN(TRUE);
+  }
+
+  group_relay_log_pos=  temp_group_relay_log_pos;
+  group_master_log_pos= temp_group_master_log_pos;
+  sql_delay= (int32) temp_sql_delay;
+
+  DBUG_RETURN(FALSE);
+}
+
+bool Relay_log_info::write_info(Rpl_info_handler *to, bool force)
+{
+  DBUG_ENTER("Relay_log_info::write_info");
+
+  /*
+    @todo Uncomment the following assertion. See todo in
+    Relay_log_info::read_info() for details. /Sven
+  */
+  //DBUG_ASSERT(!belongs_to_client());
+
+  if (to->prepare_info_for_write() ||
+      to->set_info((int) LINES_IN_RELAY_LOG_INFO_WITH_DELAY) ||
+      to->set_info(group_relay_log_name) ||
+      to->set_info((ulong) group_relay_log_pos) ||
+      to->set_info(group_master_log_name) ||
+      to->set_info((ulong) group_master_log_pos) ||
+      to->set_info((int) sql_delay))
+    DBUG_RETURN(TRUE);
+
+  if (to->flush_info(force))
+    DBUG_RETURN(TRUE);
+
+  DBUG_RETURN(FALSE);
+}

=== modified file 'sql/rpl_rli.h'
--- a/sql/rpl_rli.h	2010-09-01 02:51:08 +0000
+++ b/sql/rpl_rli.h	2010-10-08 16:11:32 +0000
@@ -16,6 +16,9 @@
 #ifndef RPL_RLI_H
 #define RPL_RLI_H
 
+#include "sql_priv.h"
+#include "rpl_info.h"
+#include "rpl_utility.h"
 #include "rpl_tblmap.h"
 #include "rpl_reporting.h"
 #include "rpl_utility.h"
@@ -27,33 +30,21 @@ struct RPL_TABLE_LIST;
 class Master_info;
 extern uint sql_slave_skip_counter;
 
-/****************************************************************************
-
-  Replication SQL Thread
-
-  Relay_log_info contains:
-    - the current relay log
-    - the current relay log offset
-    - master log name
-    - master log sequence corresponding to the last update
-    - misc information specific to the SQL thread
-
-  Relay_log_info is initialized from the slave.info file if such
-  exists.  Otherwise, data members are intialized with defaults. The
-  initialization is done with init_relay_log_info() call.
-
-  The format of slave.info file:
-
-  relay_log_name
-  relay_log_pos
-  master_log_name
-  master_log_pos
-
-  To clean up, call end_relay_log_info()
+/*******************************************************************************
+Replication SQL Thread
 
-*****************************************************************************/
-
-class Relay_log_info : public Slave_reporting_capability
+Relay_log_info contains:
+  - the current relay log
+  - the current relay log offset
+  - master log name
+  - master log sequence corresponding to the last update
+  - misc information specific to the SQL thread
+
+Relay_log_info is initialized from a repository, e.g. table or file, if there is
+one. Otherwise, data members are intialized with defaults by calling
+init_relay_log_info(). Currently, only files are available as repositories.
+*******************************************************************************/
+class Relay_log_info : public Rpl_info
 {
 public:
   /**
@@ -76,8 +67,8 @@ public:
   */
   inline bool belongs_to_client()
   {
-    DBUG_ASSERT(sql_thd);
-    return !sql_thd->slave_thread;
+    DBUG_ASSERT(info_thd);
+    return !info_thd->slave_thread;
   }
 
   /*
@@ -90,14 +81,10 @@ public:
   bool replicate_same_server_id;
 
   /*** The following variables can only be read when protect by data lock ****/
-
   /*
-    info_fd - file descriptor of the info file. set only during
-    initialization or clean up - safe to read anytime
     cur_log_fd - file descriptor of the current read  relay log
   */
-  File info_fd,cur_log_fd;
-
+  File cur_log_fd;
   /*
     Protected with internal locks.
     Must get data_lock when resetting the logs.
@@ -107,23 +94,13 @@ public:
   IO_CACHE cache_buf,*cur_log;
 
   /*
-    Keeps track of the number of transactions that commits
-    before fsyncing. The option --sync-relay-log-info determines 
-    how many transactions should commit before fsyncing.
-  */ 
-  uint sync_counter;
-
-  /*
     Identifies when the recovery process is going on.
     See sql/slave.cc:init_recovery for further details.
-  */ 
+  */
   bool is_relay_log_recovery;
 
   /* The following variables are safe to read any time */
 
-  /* IO_CACHE of the info file - set only during init or end */
-  IO_CACHE info_file;
-
   /*
     When we restart slave thread we need to have access to the previously
     created temporary tables. Modified only on init/end and by the SQL
@@ -131,19 +108,6 @@ public:
   */
   TABLE *save_temporary_tables;
 
-  /*
-    standard lock acquisition order to avoid deadlocks:
-    run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
-  */
-  mysql_mutex_t data_lock, run_lock;
-
-  /*
-    start_cond is broadcast when SQL thread is started
-    stop_cond - when stopped
-    data_cond - when data protected by data_lock changes
-  */
-  mysql_cond_t start_cond, stop_cond, data_cond;
-
   /* parent Master_info structure */
   Master_info *mi;
 
@@ -152,7 +116,7 @@ public:
     a different log under our feet
   */
   uint32 cur_log_old_open_count;
-  
+
   /*
     Let's call a group (of events) :
       - a transaction
@@ -170,19 +134,15 @@ public:
     relay log and finishing (commiting) on another relay log. Case which can
     happen when, for example, the relay log gets rotated because of
     max_binlog_size.
-
-    Note: group_relay_log_name, group_relay_log_pos must only be
-    written from the thread owning the Relay_log_info (SQL thread if
-    !belongs_to_client(); client thread executing BINLOG statement if
-    belongs_to_client()).
   */
+protected:
   char group_relay_log_name[FN_REFLEN];
   ulonglong group_relay_log_pos;
   char event_relay_log_name[FN_REFLEN];
   ulonglong event_relay_log_pos;
   ulonglong future_event_relay_log_pos;
 
-  /* 
+  /*
      Original log name and position of the group we're currently executing
      (whose coordinates are group_relay_log_name/pos in the relay log)
      in the master's binlog. These concern the *group*, because in the master's
@@ -198,15 +158,6 @@ public:
   volatile my_off_t group_master_log_pos;
 
   /*
-    Handling of the relay_log_space_limit optional constraint.
-    ignore_log_space_limit is used to resolve a deadlock between I/O and SQL
-    threads, the SQL thread sets it to unblock the I/O thread and make it
-    temporarily forget about the constraint.
-  */
-  ulonglong log_space_limit,log_space_total;
-  bool ignore_log_space_limit;
-
-  /*
     When it commits, InnoDB internally stores the master log position it has
     processed so far; the position to store is the one of the end of the
     committing event (the COMMIT query event, or the event if in autocommit
@@ -218,9 +169,25 @@ public:
   ulonglong future_group_master_log_pos;
 #endif
 
+public:
+  int init_relay_log_pos(const char* log,
+                         ulonglong pos, bool need_data_lock,
+                         const char** errmsg,
+                         bool look_for_description_event);
+
+  /*
+    Handling of the relay_log_space_limit optional constraint.
+    ignore_log_space_limit is used to resolve a deadlock between I/O and SQL
+    threads, the SQL thread sets it to unblock the I/O thread and make it
+    temporarily forget about the constraint.
+  */
+  ulonglong log_space_limit,log_space_total;
+  bool ignore_log_space_limit;
+
   time_t last_master_timestamp;
 
   void clear_until_condition();
+
   /**
     Reset the delay.
     This is used by RESET SLAVE to clear the delay.
@@ -230,7 +197,6 @@ public:
     sql_delay= 0;
   }
 
-
   /*
     Needed for problems when slave stops and we want to restart it
     skipping one or more events in the master log that have caused
@@ -238,36 +204,19 @@ public:
   */
   volatile uint32 slave_skip_counter;
   volatile ulong abort_pos_wait;	/* Incremented on change master */
-  volatile ulong slave_run_id;		/* Incremented on slave start */
   mysql_mutex_t log_space_lock;
   mysql_cond_t log_space_cond;
-  THD * sql_thd;
-#ifndef DBUG_OFF
-  int events_till_abort;
-#endif  
 
   /*
-    inited changes its value within LOCK_active_mi-guarded critical
-    sections  at times of start_slave_threads() (0->1) and end_slave() (1->0).
-    Readers may not acquire the mutex while they realize potential concurrency
-    issue.
-    If not set, the value of other members of the structure are undefined.
-  */
-  volatile bool inited;
-  volatile bool abort_slave;
-  volatile uint slave_running;
-
-  /* 
      Condition and its parameters from START SLAVE UNTIL clause.
      
-     UNTIL condition is tested with is_until_satisfied() method that is 
+     UNTIL condition is tested with is_until_satisfied() method that is
      called by exec_relay_log_event(). is_until_satisfied() caches the result
      of the comparison of log names because log names don't change very often;
      this cache is invalidated by parts of code which change log names with
      notify_*_log_name_updated() methods. (They need to be called only if SQL
      thread is running).
    */
-  
   enum {UNTIL_NONE= 0, UNTIL_MASTER_POS, UNTIL_RELAY_POS} until_condition;
   char until_log_name[FN_REFLEN];
   ulonglong until_log_pos;
@@ -311,11 +260,16 @@ public:
   char slave_patternload_file[FN_REFLEN]; 
   size_t slave_patternload_file_size;  
 
-  Relay_log_info(bool is_slave_recovery);
-  ~Relay_log_info();
+  Relay_log_info(bool is_slave_recovery,
+                 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);
+  virtual ~Relay_log_info();
 
-  /*
-    Invalidate cached until_log_name and group_relay_log_name comparison 
+  /**
+    Invalidates cached until_log_name and group_relay_log_name comparison
     result. Should be called after any update of group_realy_log_name if
     there chances that sql_thread is running.
   */
@@ -325,8 +279,9 @@ public:
       until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
   }
 
-  /*
-    The same as previous but for group_master_log_name. 
+  /**
+    The same as @c notify_group_relay_log_name_update but for
+    @c group_master_log_name.
   */
   inline void notify_group_master_log_name_update()
   {
@@ -340,7 +295,7 @@ public:
   }
 
   void inc_group_relay_log_pos(ulonglong log_pos,
-                               bool skip_lock= 0);
+			       bool skip_lock= FALSE);
 
   int wait_for_pos(THD* thd, String* log_name, longlong log_pos, 
 		   longlong timeout);
@@ -377,9 +332,9 @@ public:
     return false;
   }
 
-  /*
+  /**
     Last charset (6 bytes) seen by slave SQL thread is cached here; it helps
-    the thread save 3 get_charset() per Query_log_event if the charset is not
+    the thread save 3 @c get_charset() per @c Query_log_event if the charset is not
     changing from event to event (common situation).
     When the 6 bytes are equal to 0 is used to mean "cache is invalidated".
   */
@@ -389,6 +344,7 @@ public:
   void cleanup_context(THD *, bool);
   void slave_close_thread_tables(THD *);
   void clear_tables_to_lock();
+  int purge_relay_logs(THD *thd, bool just_reset, const char** errmsg);
 
   /*
     Used to defer stopping the SQL thread to give it a chance
@@ -456,21 +412,85 @@ public:
      @retval false Replication thread is currently not inside a group
    */
   bool is_in_group() const {
-    return (sql_thd->variables.option_bits & OPTION_BEGIN) ||
+    return (info_thd->variables.option_bits & OPTION_BEGIN) ||
       (m_flags & (1UL << IN_STMT));
   }
 
-  /**
-    Text used in THD::proc_info when the slave SQL thread is delaying.
-  */
-  static const char *const state_delaying_string;
+  int count_relay_log_space();
+
+  int init_info();
+  void end_info();
+  int flush_info(bool force= FALSE);
+  int flush_current_log();
+  void set_master_info(Master_info *info);
+
+  inline ulonglong get_future_event_relay_log_pos() { return future_event_relay_log_pos; }
+  inline void set_future_event_relay_log_pos(ulonglong log_pos)
+  {
+    future_event_relay_log_pos= log_pos;
+  }
+
+  inline const char* get_group_master_log_name() { return group_master_log_name; }
+  inline ulonglong get_group_master_log_pos() { return group_master_log_pos; }
+  inline void set_group_master_log_name(const char *log_file_name)
+  {
+     strmake(group_master_log_name,log_file_name, sizeof(group_master_log_name)-1);
+  }
+  inline void set_group_master_log_pos(ulonglong log_pos)
+  {
+    group_master_log_pos= log_pos;
+  }
+
+  inline const char* get_group_relay_log_name() { return group_relay_log_name; }
+  inline ulonglong get_group_relay_log_pos() { return group_relay_log_pos; }
+  inline void set_group_relay_log_name(const char *log_file_name)
+  {
+     strmake(group_relay_log_name,log_file_name, sizeof(group_relay_log_name)-1);
+  }
+  inline void set_group_relay_log_name(const char *log_file_name, size_t len)
+  {
+     strmake(group_relay_log_name, log_file_name, len);
+  }
+  inline void set_group_relay_log_pos(ulonglong log_pos)
+  {
+    group_relay_log_pos= log_pos;
+  }
 
-  bool flush();
+  inline const char* get_event_relay_log_name() { return event_relay_log_name; }
+  inline ulonglong get_event_relay_log_pos() { return event_relay_log_pos; }
+  inline void set_event_relay_log_name(const char *log_file_name)
+  {
+     strmake(event_relay_log_name,log_file_name, sizeof(event_relay_log_name)-1);
+  }
+  inline void set_event_relay_log_name(const char *log_file_name, size_t len)
+  {
+     strmake(event_relay_log_name,log_file_name, len);
+  }
+  inline void set_event_relay_log_pos(ulonglong log_pos)
+  {
+    event_relay_log_pos= log_pos;
+  }
+  inline const char* get_rpl_log_name()
+  {
+    return (group_master_log_name[0] ? group_master_log_name : "FIRST");
+  }
+
+#if MYSQL_VERSION_ID < 40100
+  inline ulonglong get_future_master_log_pos() { return future_master_log_pos; }
+#else
+  inline ulonglong get_future_group_master_log_pos() { return future_group_master_log_pos; }
+  inline void set_future_group_master_log_pos(ulonglong log_pos)
+  {
+    future_group_master_log_pos= log_pos;
+  }
+#endif
+
+  size_t get_number_info_rli_fields();
 
   /**
-    Reads the relay_log.info file.
+    Text used in THD::proc_info when the slave SQL thread is delaying.
   */
-  int init(const char* info_filename);
+  static const char *const state_delaying_string;
 
   /**
     Indicate that a delay starts.
@@ -487,7 +507,7 @@ public:
   {
     mysql_mutex_assert_owner(&data_lock);
     sql_delay_end= delay_end;
-    thd_proc_info(sql_thd, state_delaying_string);
+    thd_proc_info(info_thd, state_delaying_string);
   }
 
   int32 get_sql_delay() { return sql_delay; }
@@ -505,7 +525,7 @@ private:
     MASTER_DELAY=X.  Read by SQL thread and by client threads
     executing SHOW SLAVE STATUS.  Note: must not be written while the
     slave SQL thread is running, since the SQL thread reads it without
-    a lock when executing flush_relay_log_info().
+    a lock when executing flush_info().
   */
   int sql_delay;
 
@@ -520,33 +540,19 @@ private:
   time_t sql_delay_end;
 
   /*
-    Before the MASTER_DELAY parameter was added (WL#344),
-    relay_log.info had 4 lines. Now it has 5 lines.
+    Before the MASTER_DELAY parameter was added (WL#344), relay_log.info
+    had 4 lines. Now it has 5 lines.
   */
   static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5;
 
-  uint32 m_flags;
-};
+  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(const Relay_log_info& info);
 
-/**
-  Reads the relay_log.info file.
+  uint32 m_flags;
+};
 
-  @todo This is a wrapper around Relay_log_info::init(). It's only
-  kept for historical reasons. It would be good if we removed this
-  function and replaced all calls to it by calls to
-  Relay_log_info::init(). /SVEN
-*/
-int init_relay_log_info(Relay_log_info* rli, const char* info_fname);
-bool flush_relay_log_info(Relay_log_info* rli);
-void end_relay_log_info(Relay_log_info* rli);
-int init_relay_log_pos(Relay_log_info* rli,const char* log,ulonglong pos,
-		       bool need_data_lock, const char** errmsg,
-                       bool look_for_description_event);
-
-int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
-		     const char** errmsg);
-void rotate_relay_log(Master_info* mi);
 bool mysql_show_relaylog_events(THD* thd);
-
 #endif /* RPL_RLI_H */

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2010-09-26 23:56:20 +0000
+++ b/sql/rpl_slave.cc	2010-10-17 23:27:40 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -10,8 +10,8 @@
    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,
-   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 
 /**
@@ -32,6 +32,7 @@
 #include "rpl_mi.h"
 #include "rpl_rli.h"
 #include "rpl_filter.h"
+#include "rpl_info_factory.h"
 #include "transaction.h"
 #include <thr_alarm.h>
 #include <my_dir.h>
@@ -49,6 +50,7 @@
 #include "log_event.h"                          // Rotate_log_event,
                                                 // Create_file_log_event,
                                                 // Format_description_log_event
+#include "server_ids.h"
 
 #ifdef HAVE_REPLICATION
 
@@ -134,7 +136,7 @@ log '%s' at postion %s",
 failed read"
   }
 };
- 
+
 
 typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
 
@@ -182,9 +184,9 @@ static bool check_io_slave_killed(THD *t
                 If inverse == 1, stopped threads
 */
 
-void init_thread_mask(int* mask,Master_info* mi,bool inverse)
+void init_thread_mask(int* mask, Master_info* mi, bool inverse)
 {
-  bool set_io = mi->slave_running, set_sql = mi->rli.slave_running;
+  bool set_io = mi->slave_running, set_sql = mi->rli->slave_running;
   register int tmp_mask=0;
   DBUG_ENTER("init_thread_mask");
 
@@ -209,7 +211,7 @@ void lock_slave_threads(Master_info* mi)
 
   //TODO: see if we can do this without dual mutex
   mysql_mutex_lock(&mi->run_lock);
-  mysql_mutex_lock(&mi->rli.run_lock);
+  mysql_mutex_lock(&mi->rli->run_lock);
   DBUG_VOID_RETURN;
 }
 
@@ -223,7 +225,7 @@ void unlock_slave_threads(Master_info* m
   DBUG_ENTER("unlock_slave_threads");
 
   //TODO: see if we can do this without dual mutex
-  mysql_mutex_unlock(&mi->rli.run_lock);
+  mysql_mutex_unlock(&mi->rli->run_lock);
   mysql_mutex_unlock(&mi->run_lock);
   DBUG_VOID_RETURN;
 }
@@ -256,6 +258,8 @@ int init_slave()
 {
   DBUG_ENTER("init_slave");
   int error= 0;
+  int thread_mask= SLAVE_SQL | SLAVE_IO;
+  Relay_log_info* rli= NULL;
 
 #ifdef HAVE_PSI_INTERFACE
   init_slave_psi_keys();
@@ -267,14 +271,16 @@ int init_slave()
     So it's safer to take the lock.
   */
   mysql_mutex_lock(&LOCK_active_mi);
-  /*
-    TODO: re-write this to interate through the list of files
-    for multi-master
-  */
-  active_mi= new Master_info(relay_log_recovery);
 
   if (pthread_key_create(&RPL_MASTER_INFO, NULL))
+    DBUG_RETURN(1);
+
+  if ((error= Rpl_info_factory::create(opt_mi_repository_id, &active_mi,
+                                       opt_rli_repository_id, &rli)))
+  {
+    error= 1;
     goto err;
+  }
 
   /*
     If --slave-skip-errors=... was not used, the string value for the
@@ -286,35 +292,31 @@ int init_slave()
   }
 
   /*
-    If master_host is not specified, try to read it from the master_info file.
-    If master_host is specified, create the master_info file if it doesn't
-    exists.
+    This is the startup routine and as such we try to
+    configure both the SLAVE_SQL and SLAVE_IO.
   */
-  if (!active_mi)
-  {
-    sql_print_error("Failed to allocate memory for the master info structure");
-    error= 1;
-    goto err;
-  }
-
-  if (init_master_info(active_mi,master_info_file,relay_log_info_file,
-                       1, (SLAVE_IO | SLAVE_SQL)))
+  if (init_info(active_mi, TRUE, thread_mask))
   {
     sql_print_error("Failed to initialize the master info structure");
     error= 1;
     goto err;
   }
 
-  /* If server id is not set, start_slave_thread() will say it */
+  DBUG_PRINT("info", ("init group master %s %lu  group relay %s %lu event %s %lu\n",
+    rli->get_group_master_log_name(),
+    (ulong) rli->get_group_master_log_pos(),
+    rli->get_group_relay_log_name(),
+    (ulong) rli->get_group_relay_log_pos(),
+    rli->get_event_relay_log_name(),
+    (ulong) rli->get_event_relay_log_pos()));
 
+  /* If server id is not set, start_slave_thread() will say it */
   if (active_mi->host[0] && !opt_skip_slave_start)
   {
     if (start_slave_threads(1 /* need mutex */,
                             0 /* no wait for start*/,
                             active_mi,
-                            master_info_file,
-                            relay_log_info_file,
-                            SLAVE_IO | SLAVE_SQL))
+                            thread_mask))
     {
       sql_print_error("Failed to create slave threads");
       error= 1;
@@ -329,21 +331,21 @@ err:
 
 /*
   Updates the master info based on the information stored in the
-  relay info and ignores relay logs previously retrieved by the IO 
-  thread, which thus starts fetching again based on to the  
-  group_master_log_pos and group_master_log_name. Eventually, the old
+  relay info and ignores relay logs previously retrieved by the IO
+  thread, which thus starts fetching again based on to the
+  master_log_pos and master_log_name. Eventually, the old
   relay logs will be purged by the normal purge mechanism.
 
   In the feature, we should improve this routine in order to avoid throwing
-  away logs that are safely stored in the disk. Note also that this recovery 
-  routine relies on the correctness of the relay-log.info and only tolerates 
+  away logs that are safely stored in the disk. Note also that this recovery
+  routine relies on the correctness of the relay-log.info and only tolerates
   coordinate problems in master.info.
-  
-  In this function, there is no need for a mutex as the caller 
+
+  In this function, there is no need for a mutex as the caller
   (i.e. init_slave) already has one acquired.
-  
+
   Specifically, the following structures are updated:
- 
+
   1 - mi->master_log_pos  <-- rli->group_master_log_pos
   2 - mi->master_log_name <-- rli->group_master_log_name
   3 - It moves the relay log to the new relay log file, by
@@ -351,35 +353,154 @@ err:
       rli->event_relay_log_pos  <-- BIN_LOG_HEADER_SIZE;
       rli->group_relay_log_name <-- rli->relay_log.get_log_fname();
       rli->event_relay_log_name <-- rli->relay_log.get_log_fname();
-  
+
    If there is an error, it returns (1), otherwise returns (0).
  */
 int init_recovery(Master_info* mi, const char** errmsg)
 {
   DBUG_ENTER("init_recovery");
- 
-  Relay_log_info *rli= &mi->rli;
-  if (rli->group_master_log_name[0])
-  {
-    mi->master_log_pos= max(BIN_LOG_HEADER_SIZE,
-                             rli->group_master_log_pos);
-    strmake(mi->master_log_name, rli->group_master_log_name,
-            sizeof(mi->master_log_name)-1);
- 
+
+  Relay_log_info *rli= mi->rli;
+  const char *group_master_log_name=  rli->get_group_master_log_name();
+  if (group_master_log_name[0])
+  {
+    mi->set_master_log_pos(max(BIN_LOG_HEADER_SIZE,
+                           rli->get_group_master_log_pos()));
+    mi->set_master_log_name(rli->get_group_master_log_name());
+
     sql_print_warning("Recovery from master pos %ld and file %s.",
-                      (ulong) mi->master_log_pos, mi->master_log_name);
- 
-    strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(),
-            sizeof(rli->group_relay_log_name)-1);
-    strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
-            sizeof(mi->rli.event_relay_log_name)-1);
- 
-    rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
+                      (ulong) mi->get_master_log_pos(), mi->get_master_log_name());
+
+    rli->set_group_relay_log_name(rli->relay_log.get_log_fname());
+    rli->set_event_relay_log_name(rli->relay_log.get_log_fname());
+    rli->set_group_relay_log_pos(BIN_LOG_HEADER_SIZE);
+    rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);
   }
 
   DBUG_RETURN(0);
 }
- 
+
+int init_info(Master_info* mi, bool ignore_if_no_info, int thread_mask)
+{
+  int error= 0;
+  int necessary_to_configure= 0;
+
+  DBUG_ENTER("init_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+
+  /*
+    We need a mutex while we are changing master info parameters to
+    keep other threads from reading bogus info
+  */
+  mysql_mutex_lock(&mi->data_lock);
+  mysql_mutex_lock(&mi->rli->data_lock);
+
+  /*
+    This takes care of the startup dependency between the master_info
+    and relay_info. It initializes the master info if the SLAVE_IO
+    thread is being started and the relay log info if either the
+    SLAVE_SQL thread is being started or was not initialized as it is
+    required by the SLAVE_IO thread.
+  */
+  necessary_to_configure= mi->check_info();
+  if (!(ignore_if_no_info && necessary_to_configure))
+  {
+    if ((thread_mask & SLAVE_IO) != 0 && mi->init_info())
+      error= 1;
+  }
+
+  necessary_to_configure= mi->rli->check_info();
+  if (!(ignore_if_no_info && necessary_to_configure))
+  {
+     if (((thread_mask & SLAVE_SQL) != 0 || !(mi->rli->inited))
+         && mi->rli->init_info())
+    error= 1;
+  }
+
+  mysql_mutex_unlock(&mi->rli->data_lock);
+  mysql_mutex_unlock(&mi->data_lock);
+
+  DBUG_RETURN(error);
+}
+
+void end_info(Master_info* mi)
+{
+  DBUG_ENTER("end_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+
+  /*
+    The previous implementation was not acquiring locks.
+    We do the same here. However, this is quite strange.
+  */
+  mi->end_info();
+  mi->rli->end_info();
+
+  DBUG_VOID_RETURN;
+}
+
+int reset_info(Master_info* mi)
+{
+  int error= 0;
+  DBUG_ENTER("reset_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+
+  /*
+    The previous implementation was not acquiring locks.
+    We do the same here. However, this is quite strange.
+  */
+  /*
+    Reset errors (the idea is that we forget about the
+    old master).
+  */
+  mi->clear_error();
+  mi->rli->clear_error();
+  mi->rli->clear_until_condition();
+  mi->rli->clear_sql_delay();
+
+  mi->end_info();
+  mi->rli->end_info();
+
+  if (mi->reset_info() || mi->rli->reset_info())
+    error= 1;
+
+  DBUG_RETURN(error);
+}
+
+int flush_master_info(Master_info* mi, bool force)
+{
+  DBUG_ENTER("flush_master_info");
+  DBUG_ASSERT(mi != NULL && mi->rli != NULL);
+  /*
+    The previous implementation was not acquiring locks.
+    We do the same here. However, this is quite strange.
+  */
+  /*
+    With the appropriate recovery process, we will not need to flush
+    the content of the current log.
+
+    For now, we flush the relay log BEFORE the master.info file, because
+    if we crash, we will get a duplicate event in the relay log at restart.
+    If we change the order, there might be missing events.
+
+    If we don't do this and the slave server dies when the relay log has
+    some parts (its last kilobytes) in memory only, with, say, from master's
+    position 100 to 150 in memory only (not on disk), and with position 150
+    in master.info, there will be missing information. When the slave restarts,
+    the I/O thread will fetch binlogs from 150, so in the relay log we will
+    have "[0, 100] U [150, infinity[" and nobody will notice it, so the SQL
+    thread will jump from 100 to 150, and replication will silently break.
+  */
+  mysql_mutex_t *log_lock= mi->rli->relay_log.get_log_lock();
+
+  mysql_mutex_lock(log_lock);
+
+  int err=  (mi->rli->flush_current_log() ||  mi->flush_info(force));
+
+  mysql_mutex_unlock(log_lock);
+
+  DBUG_RETURN (err);
+}
+
 /**
   Convert slave skip errors bitmap into a printable string.
 */
@@ -491,7 +612,7 @@ static void set_thd_in_use_temporary_tab
   TABLE *table;
 
   for (table= rli->save_temporary_tables ; table ; table= table->next)
-    table->in_use= rli->sql_thd;
+    table->in_use= rli->info_thd;
 }
 
 int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
@@ -501,14 +622,14 @@ int terminate_slave_threads(Master_info*
   if (!mi->inited)
     DBUG_RETURN(0); /* successfully do nothing */
   int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
-  mysql_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
-  mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock();
+  mysql_mutex_t *sql_lock = &mi->rli->run_lock, *io_lock = &mi->run_lock;
+  mysql_mutex_t *log_lock= mi->rli->relay_log.get_log_lock();
 
   if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL))
   {
     DBUG_PRINT("info",("Terminating IO thread"));
     mi->abort_slave=1;
-    if ((error=terminate_slave_thread(mi->io_thd, io_lock,
+    if ((error=terminate_slave_thread(mi->info_thd,io_lock,
                                       &mi->stop_cond,
                                       &mi->slave_running,
                                       skip_lock)) &&
@@ -517,16 +638,20 @@ int terminate_slave_threads(Master_info*
 
     mysql_mutex_lock(log_lock);
 
-    DBUG_PRINT("info",("Flushing relay log and master info file."));
+    DBUG_PRINT("info",("Flushing relay log and master info repository."));
     if (current_thd)
-      thd_proc_info(current_thd, "Flushing relay log and master info files.");
-    if (flush_master_info(mi, TRUE, FALSE))
-      DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
+      thd_proc_info(current_thd, "Flushing relay log and master info repository.");
 
-    if (my_sync(mi->rli.relay_log.get_log_file()->file, MYF(MY_WME)))
+    /*
+      Flushes the master info regardles of the sync_master_info option.
+    */
+    if (mi->flush_info(TRUE))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
-    if (my_sync(mi->fd, MYF(MY_WME)))
+    /*
+      Flushes the relay log regardles of the sync_relay_log option.
+    */
+    if (mi->rli->relay_log.flush_and_sync(0, TRUE))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
     mysql_mutex_unlock(log_lock);
@@ -534,10 +659,10 @@ int terminate_slave_threads(Master_info*
   if (thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL))
   {
     DBUG_PRINT("info",("Terminating SQL thread"));
-    mi->rli.abort_slave=1;
-    if ((error=terminate_slave_thread(mi->rli.sql_thd, sql_lock,
-                                      &mi->rli.stop_cond,
-                                      &mi->rli.slave_running,
+    mi->rli->abort_slave= 1;
+    if ((error=terminate_slave_thread(mi->rli->info_thd, sql_lock,
+                                      &mi->rli->stop_cond,
+                                      &mi->rli->slave_running,
                                       skip_lock)) &&
         !force_all)
       DBUG_RETURN(error);
@@ -547,15 +672,16 @@ int terminate_slave_threads(Master_info*
     DBUG_PRINT("info",("Flushing relay-log info file."));
     if (current_thd)
       thd_proc_info(current_thd, "Flushing relay-log info file.");
-    if (flush_relay_log_info(&mi->rli))
-      DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
-    
-    if (my_sync(mi->rli.info_fd, MYF(MY_WME)))
+
+    /*
+      Flushes the relay log info regardles of the sync_relay_log_info option.
+    */
+    if (mi->rli->flush_info(TRUE))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
     mysql_mutex_unlock(log_lock);
   }
-  DBUG_RETURN(0); 
+  DBUG_RETURN(0);
 }
 
 
@@ -684,8 +810,6 @@ int start_slave_thread(
   ulong start_id;
   DBUG_ENTER("start_slave_thread");
 
-  DBUG_ASSERT(mi->inited);
-
   if (start_lock)
     mysql_mutex_lock(start_lock);
   if (!server_id)
@@ -750,8 +874,7 @@ int start_slave_thread(
 */
 
 int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
-                        Master_info* mi, const char* master_info_fname,
-                        const char* slave_info_fname, int thread_mask)
+                        Master_info* mi, int thread_mask)
 {
   mysql_mutex_t *lock_io=0, *lock_sql=0, *lock_cond_io=0, *lock_cond_sql=0;
   mysql_cond_t* cond_io=0, *cond_sql=0;
@@ -761,14 +884,14 @@ int start_slave_threads(bool need_slave_
   if (need_slave_mutex)
   {
     lock_io = &mi->run_lock;
-    lock_sql = &mi->rli.run_lock;
+    lock_sql = &mi->rli->run_lock;
   }
   if (wait_for_start)
   {
     cond_io = &mi->start_cond;
-    cond_sql = &mi->rli.start_cond;
+    cond_sql = &mi->rli->start_cond;
     lock_cond_io = &mi->run_lock;
-    lock_cond_sql = &mi->rli.run_lock;
+    lock_cond_sql = &mi->rli->run_lock;
   }
 
   if (thread_mask & SLAVE_IO)
@@ -788,7 +911,7 @@ int start_slave_threads(bool need_slave_
 #endif
                               handle_slave_sql, lock_sql, lock_cond_sql,
                               cond_sql,
-                              &mi->rli.slave_running, &mi->rli.slave_run_id,
+                              &mi->rli->slave_running, &mi->rli->slave_run_id,
                               mi);
     if (error)
       terminate_slave_threads(mi, thread_mask & SLAVE_IO, !need_slave_mutex);
@@ -796,7 +919,6 @@ int start_slave_threads(bool need_slave_
   DBUG_RETURN(error);
 }
 
-
 /*
   Release slave threads at time of executing shutdown.
 
@@ -843,7 +965,9 @@ void close_active_mi()
   mysql_mutex_lock(&LOCK_active_mi);
   if (active_mi)
   {
-    end_master_info(active_mi);
+    end_info(active_mi);
+    if (active_mi->rli)
+      delete active_mi->rli;
     delete active_mi;
     active_mi= 0;
   }
@@ -854,7 +978,7 @@ static bool io_slave_killed(THD* thd, Ma
 {
   DBUG_ENTER("io_slave_killed");
 
-  DBUG_ASSERT(mi->io_thd == thd);
+  DBUG_ASSERT(mi->info_thd == thd);
   DBUG_ASSERT(mi->slave_running); // tracking buffer overrun
   DBUG_RETURN(mi->abort_slave || abort_loop || thd->killed);
 }
@@ -877,7 +1001,7 @@ static bool sql_slave_killed(THD* thd, R
   bool ret= FALSE;
   DBUG_ENTER("sql_slave_killed");
 
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
   DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun
   if (abort_loop || thd->killed || rli->abort_slave)
   {
@@ -987,185 +1111,6 @@ const char *print_slave_db_safe(const ch
   DBUG_RETURN((db ? db : ""));
 }
 
-int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-                                 const char *default_val)
-{
-  uint length;
-  DBUG_ENTER("init_strvar_from_file");
-
-  if ((length=my_b_gets(f,var, max_size)))
-  {
-    char* last_p = var + length -1;
-    if (*last_p == '\n')
-      *last_p = 0; // if we stopped on newline, kill it
-    else
-    {
-      /*
-        If we truncated a line or stopped on last char, remove all chars
-        up to and including newline.
-      */
-      int c;
-      while (((c=my_b_get(f)) != '\n' && c != my_b_EOF)) ;
-    }
-    DBUG_RETURN(0);
-  }
-  else if (default_val)
-  {
-    strmake(var,  default_val, max_size-1);
-    DBUG_RETURN(0);
-  }
-  DBUG_RETURN(1);
-}
-
-
-int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
-{
-  char buf[32];
-  DBUG_ENTER("init_intvar_from_file");
-
-
-  if (my_b_gets(f, buf, sizeof(buf)))
-  {
-    *var = atoi(buf);
-    DBUG_RETURN(0);
-  }
-  else if (default_val)
-  {
-    *var = default_val;
-    DBUG_RETURN(0);
-  }
-  DBUG_RETURN(1);
-}
-
-int init_longvar_from_file(long* var, IO_CACHE* f, long default_val)
-{
-  char buf[32];
-  DBUG_ENTER("init_longvar_from_file");
-
-
-  if (my_b_gets(f, buf, sizeof(buf)))
-  {
-    *var = atol(buf);
-    DBUG_RETURN(0);
-  }
-  else if (default_val)
-  {
-    *var = default_val;
-    DBUG_RETURN(0);
-  }
-  DBUG_RETURN(1);
-}
-
-int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val)
-{
-  char buf[16];
-  DBUG_ENTER("init_floatvar_from_file");
-
-
-  if (my_b_gets(f, buf, sizeof(buf)))
-  {
-    if (sscanf(buf, "%f", var) != 1)
-      DBUG_RETURN(1);
-    else
-      DBUG_RETURN(0);
-  }
-  else if (default_val != 0.0)
-  {
-    *var = default_val;
-    DBUG_RETURN(0);
-  }
-  DBUG_RETURN(1);
-}
-
-
-/**
-   A master info read method
-
-   This function is called from @c init_master_info() along with
-   relatives to restore some of @c active_mi members.
-   Particularly, this function is responsible for restoring
-   IGNORE_SERVER_IDS list of servers whose events the slave is
-   going to ignore (to not log them in the relay log).
-   Items being read are supposed to be decimal output of values of a
-   type shorter or equal of @c long and separated by the single space.
-
-   @param arr         @c DYNAMIC_ARRAY pointer to storage for servers id
-   @param f           @c IO_CACHE pointer to the source file
-
-   @retval 0         All OK
-   @retval non-zero  An error
-*/
-
-int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f)
-{
-  int ret= 0;
-  char buf[16 * (sizeof(long)*4 + 1)]; // static buffer to use most of times
-  char *buf_act= buf; // actual buffer can be dynamic if static is short
-  char *token, *last;
-  uint num_items;     // number of items of `arr'
-  size_t read_size;
-  DBUG_ENTER("init_dynarray_intvar_from_file");
-
-  if ((read_size= my_b_gets(f, buf_act, sizeof(buf))) == 0)
-  {
-    return 0; // no line in master.info
-  }
-  if (read_size + 1 == sizeof(buf) && buf[sizeof(buf) - 2] != '\n')
-  {
-    /*
-      short read happend; allocate sufficient memory and make the 2nd read
-    */
-    char buf_work[(sizeof(long)*3 + 1)*16];
-    memcpy(buf_work, buf, sizeof(buf_work));
-    num_items= atoi(strtok_r(buf_work, " ", &last));
-    size_t snd_size;
-    /*
-      max size lower bound approximate estimation bases on the formula:
-      (the items number + items themselves) * 
-          (decimal size + space) - 1 + `\n' + '\0'
-    */
-    size_t max_size= (1 + num_items) * (sizeof(long)*3 + 1) + 1;
-    buf_act= (char*) my_malloc(max_size, MYF(MY_WME));
-    memcpy(buf_act, buf, read_size);
-    snd_size= my_b_gets(f, buf_act + read_size, max_size - read_size);
-    if (snd_size == 0 ||
-        ((snd_size + 1 == max_size - read_size) &&  buf[max_size - 2] != '\n'))
-    {
-      /*
-        failure to make the 2nd read or short read again
-      */
-      ret= 1;
-      goto err;
-    }
-  }
-  token= strtok_r(buf_act, " ", &last);
-  if (token == NULL)
-  {
-    ret= 1;
-    goto err;
-  }
-  num_items= atoi(token);
-  for (uint i=0; i < num_items; i++)
-  {
-    token= strtok_r(NULL, " ", &last);
-    if (token == NULL)
-    {
-      ret= 1;
-      goto err;
-    }
-    else
-    {
-      ulong val= atol(token);
-      insert_dynamic(arr, (uchar *) &val);
-    }
-  }
-err:
-  if (buf_act != buf)
-    my_free(buf_act);
-  DBUG_RETURN(ret);
-}
-
-
 /*
   Check if the error is caused by network.
   @param[in]   errorno   Number of the error.
@@ -1202,7 +1147,7 @@ int io_thread_init_commands(MYSQL *mysql
 
   sprintf(query, "SET @slave_uuid= '%s'", server_uuid);
   if (mysql_real_query(mysql, query, strlen(query))
-      && !check_io_slave_killed(mi->io_thd, mi, NULL))
+      && !check_io_slave_killed(mi->info_thd, mi, NULL))
     goto err;
 
   mysql_free_result(mysql_store_result(mysql));
@@ -1222,6 +1167,7 @@ err:
     const char *errmsg_fmt=
       "The slave I/O thread stops because a fatal error is encountered "
       "when it tries to send query to master(query: %s).";
+
     sprintf(errmsg, errmsg_fmt, query);
     mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
                errmsg);
@@ -1260,7 +1206,7 @@ static int get_master_uuid(MYSQL *mysql,
       (master_row= mysql_fetch_row(master_res)))
   {
     if (!strcmp(::server_uuid, master_row[1]) &&
-        !mi->rli.replicate_same_server_id)
+        !mi->rli->replicate_same_server_id)
     {
       errmsg= "The slave I/O thread stops because master and slave have equal "
               "MySQL server UUIDs; these UUIDs must be different for "
@@ -1340,8 +1286,8 @@ static int get_master_version_and_clock(
     Free old description_event_for_queue (that is needed if we are in
     a reconnection).
   */
-  delete mi->rli.relay_log.description_event_for_queue;
-  mi->rli.relay_log.description_event_for_queue= 0;
+  delete mi->rli->relay_log.description_event_for_queue;
+  mi->rli->relay_log.description_event_for_queue= 0;
 
   if (!my_isdigit(&my_charset_bin,*mysql->server_version))
   {
@@ -1364,11 +1310,11 @@ static int get_master_version_and_clock(
       sprintf(err_buff, ER(err_code), errmsg);
       break;
     case '3':
-      mi->rli.relay_log.description_event_for_queue= new
+      mi->rli->relay_log.description_event_for_queue= new
         Format_description_log_event(1, mysql->server_version);
       break;
     case '4':
-      mi->rli.relay_log.description_event_for_queue= new
+      mi->rli->relay_log.description_event_for_queue= new
         Format_description_log_event(3, mysql->server_version);
       break;
     default:
@@ -1380,16 +1326,16 @@ static int get_master_version_and_clock(
         (it has the format of the *slave*); it's only good to help know if the
         master is 3.23, 4.0, etc.
       */
-      mi->rli.relay_log.description_event_for_queue= new
+      mi->rli->relay_log.description_event_for_queue= new
         Format_description_log_event(4, mysql->server_version);
       break;
     }
   }
 
   /*
-     This does not mean that a 5.0 slave will be able to read a 6.0 master; but
+     This does not mean that a 5.0 slave will be able to read a 5.5 master; but
      as we don't know yet, we don't want to forbid this for now. If a 5.0 slave
-     can't read a 6.0 master, this will show up when the slave can't read some
+     can't read a 5.5 master, this will show up when the slave can't read some
      events sent by the master, and there will be error messages.
   */
 
@@ -1397,7 +1343,7 @@ static int get_master_version_and_clock(
     goto err;
 
   /* as we are here, we tried to allocate the event */
-  if (!mi->rli.relay_log.description_event_for_queue)
+  if (!mi->rli->relay_log.description_event_for_queue)
   {
     errmsg= "default Format_description_log_event";
     err_code= ER_SLAVE_CREATE_EVENT_FAILURE;
@@ -1430,7 +1376,7 @@ static int get_master_version_and_clock(
       (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
     mysql_mutex_unlock(&mi->data_lock);
   }
-  else if (check_io_slave_killed(mi->io_thd, mi, NULL))
+  else if (check_io_slave_killed(mi->info_thd, mi, NULL))
     goto slave_killed_err;
   else if (is_network_error(mysql_errno(mysql)))
   {
@@ -1481,7 +1427,7 @@ static int get_master_version_and_clock(
       (master_row= mysql_fetch_row(master_res)))
   {
     if ((::server_id == (mi->master_id= strtoul(master_row[1], 0, 10))) &&
-        !mi->rli.replicate_same_server_id)
+        !mi->rli->replicate_same_server_id)
     {
       errmsg= "The slave I/O thread stops because master and slave have equal \
 MySQL server ids; these ids must be different for replication to work (or \
@@ -1494,7 +1440,7 @@ not always make sense; please check the 
   }
   else if (mysql_errno(mysql))
   {
-    if (check_io_slave_killed(mi->io_thd, mi, NULL))
+    if (check_io_slave_killed(mi->info_thd, mi, NULL))
       goto slave_killed_err;
     else if (is_network_error(mysql_errno(mysql)))
     {
@@ -1520,7 +1466,7 @@ maybe it is a *VERY OLD MASTER*.");
     mysql_free_result(master_res);
     master_res= NULL;
   }
-  if (mi->master_id == 0 && mi->ignore_server_ids.elements > 0)
+  if (mi->master_id == 0 && mi->ignore_server_ids->server_ids.elements > 0)
   {
     errmsg= "Slave configured with server id filtering could not detect the master server id.";
     err_code= ER_SLAVE_FATAL_ERROR;
@@ -1567,7 +1513,7 @@ be equal for the Statement-format replic
         goto err;
       }
     }
-    else if (check_io_slave_killed(mi->io_thd, mi, NULL))
+    else if (check_io_slave_killed(mi->info_thd, mi, NULL))
       goto slave_killed_err;
     else if (is_network_error(mysql_errno(mysql)))
     {
@@ -1630,7 +1576,7 @@ be equal for the Statement-format replic
         goto err;
       }
     }
-    else if (check_io_slave_killed(mi->io_thd, mi, NULL))
+    else if (check_io_slave_killed(mi->info_thd, mi, NULL))
       goto slave_killed_err;
     else if (is_network_error(mysql_errno(mysql)))
     {
@@ -1666,7 +1612,7 @@ when it try to get the value of TIME_ZON
     sprintf(query, query_format, llbuf);
 
     if (mysql_real_query(mysql, query, strlen(query))
-        && !check_io_slave_killed(mi->io_thd, mi, NULL))
+        && !check_io_slave_killed(mi->info_thd, mi, NULL))
     {
       errmsg= "The slave I/O thread stops because SET @master_heartbeat_period "
         "on master failed.";
@@ -1707,7 +1653,7 @@ static bool wait_for_relay_log_space(Rel
   bool slave_killed=0;
   Master_info* mi = rli->mi;
   const char *save_proc_info;
-  THD* thd = mi->io_thd;
+  THD* thd = mi->info_thd;
   DBUG_ENTER("wait_for_relay_log_space");
 
   mysql_mutex_lock(&rli->log_space_lock);
@@ -1739,11 +1685,11 @@ Waiting for the slave SQL thread to free
  */
 static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi)
 {
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   mysql_mutex_t *log_lock= rli->relay_log.get_log_lock();
   DBUG_ENTER("write_ignored_events_info_to_relay_log");
 
-  DBUG_ASSERT(thd == mi->io_thd);
+  DBUG_ASSERT(thd == mi->info_thd);
   mysql_mutex_lock(log_lock);
   if (rli->ign_master_log_name_end[0])
   {
@@ -1764,7 +1710,7 @@ static void write_ignored_events_info_to
                    " to the relay log, SHOW SLAVE STATUS may be"
                    " inaccurate");
       rli->relay_log.harvest_bytes_written(&rli->log_space_total);
-      if (flush_master_info(mi, TRUE, TRUE))
+      if (flush_master_info(mi, TRUE))
         sql_print_error("Failed to flush master info file");
       delete ev;
     }
@@ -1841,7 +1787,7 @@ int register_slave_on_master(MYSQL* mysq
     {
       *suppress_warnings= TRUE;                 // Suppress reconnect warning
     }
-    else if (!check_io_slave_killed(mi->io_thd, mi, NULL))
+    else if (!check_io_slave_killed(mi->info_thd, mi, NULL))
     {
       char buf[256];
       my_snprintf(buf, sizeof(buf), "%s (Errno: %d)", mysql_error(mysql), 
@@ -1939,7 +1885,7 @@ bool show_master_info(THD* thd, Master_i
                                            MYSQL_TYPE_LONG));
   field_list.push_back(new Item_empty_string("Master_UUID", UUID_LENGTH));
   field_list.push_back(new Item_empty_string("Master_Info_File",
-                                             sizeof(mi->info_file_name)));
+                                             2 * FN_REFLEN));
   field_list.push_back(new Item_return_int("SQL_Delay", 10, MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("SQL_Remaining_Delay", 8, MYSQL_TYPE_LONG));
   field_list.push_back(new Item_empty_string("Slave_SQL_Running_State", 20));
@@ -1958,31 +1904,32 @@ bool show_master_info(THD* thd, Master_i
 
     /*
       slave_running can be accessed without run_lock but not other
-      non-volotile members like mi->io_thd, which is guarded by the mutex.
+      non-volotile members like mi->info_thd, which is guarded by the mutex.
     */
     mysql_mutex_lock(&mi->run_lock);
-    protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin);
+    protocol->store(mi->info_thd ? mi->info_thd->proc_info : "", &my_charset_bin);
     mysql_mutex_unlock(&mi->run_lock);
 
     mysql_mutex_lock(&mi->data_lock);
-    mysql_mutex_lock(&mi->rli.data_lock);
+    mysql_mutex_lock(&mi->rli->data_lock);
     mysql_mutex_lock(&mi->err_lock);
-    mysql_mutex_lock(&mi->rli.err_lock);
+    mysql_mutex_lock(&mi->rli->err_lock);
+
     protocol->store(mi->host, &my_charset_bin);
     protocol->store(mi->user, &my_charset_bin);
     protocol->store((uint32) mi->port);
     protocol->store((uint32) mi->connect_retry);
-    protocol->store(mi->master_log_name, &my_charset_bin);
-    protocol->store((ulonglong) mi->master_log_pos);
-    protocol->store(mi->rli.group_relay_log_name +
-                    dirname_length(mi->rli.group_relay_log_name),
+    protocol->store(mi->get_master_log_name(), &my_charset_bin);
+    protocol->store((ulonglong) mi->get_master_log_pos());
+    protocol->store(mi->rli->get_group_relay_log_name() +
+                    dirname_length(mi->rli->get_group_relay_log_name()),
                     &my_charset_bin);
-    protocol->store((ulonglong) mi->rli.group_relay_log_pos);
-    protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
+    protocol->store((ulonglong) mi->rli->get_group_relay_log_pos());
+    protocol->store(mi->rli->get_group_master_log_name(), &my_charset_bin);
     protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT ?
                     "Yes" : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ?
                              "Connecting" : "No"), &my_charset_bin);
-    protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin);
+    protocol->store(mi->rli->slave_running ? "Yes":"No", &my_charset_bin);
     protocol->store(rpl_filter->get_do_db());
     protocol->store(rpl_filter->get_ignore_db());
 
@@ -1997,18 +1944,18 @@ bool show_master_info(THD* thd, Master_i
     rpl_filter->get_wild_ignore_table(&tmp);
     protocol->store(&tmp);
 
-    protocol->store(mi->rli.last_error().number);
-    protocol->store(mi->rli.last_error().message, &my_charset_bin);
-    protocol->store((uint32) mi->rli.slave_skip_counter);
-    protocol->store((ulonglong) mi->rli.group_master_log_pos);
-    protocol->store((ulonglong) mi->rli.log_space_total);
+    protocol->store(mi->rli->last_error().number);
+    protocol->store(mi->rli->last_error().message, &my_charset_bin);
+    protocol->store((uint32) mi->rli->slave_skip_counter);
+    protocol->store((ulonglong) mi->rli->get_group_master_log_pos());
+    protocol->store((ulonglong) mi->rli->log_space_total);
 
     protocol->store(
-      mi->rli.until_condition==Relay_log_info::UNTIL_NONE ? "None":
-        ( mi->rli.until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master":
+      mi->rli->until_condition==Relay_log_info::UNTIL_NONE ? "None":
+        ( mi->rli->until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master":
           "Relay"), &my_charset_bin);
-    protocol->store(mi->rli.until_log_name, &my_charset_bin);
-    protocol->store((ulonglong) mi->rli.until_log_pos);
+    protocol->store(mi->rli->until_log_name, &my_charset_bin);
+    protocol->store((ulonglong) mi->rli->until_log_pos);
 
 #ifdef HAVE_OPENSSL
     protocol->store(mi->ssl? "Yes":"No", &my_charset_bin);
@@ -2026,9 +1973,9 @@ bool show_master_info(THD* thd, Master_i
       connected, we can compute it otherwise show NULL (i.e. unknown).
     */
     if ((mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) &&
-        mi->rli.slave_running)
+        mi->rli->slave_running)
     {
-      long time_diff= ((long)(time(0) - mi->rli.last_master_timestamp)
+      long time_diff= ((long)(time(0) - mi->rli->last_master_timestamp)
                        - mi->clock_diff_with_master);
       /*
         Apparently on some systems time_diff can be <0. Here are possible
@@ -2050,7 +1997,7 @@ bool show_master_info(THD* thd, Master_i
         last_master_timestamp == 0 (an "impossible" timestamp 1970) is a
         special marker to say "consider we have caught up".
       */
-      protocol->store((longlong)(mi->rli.last_master_timestamp ?
+      protocol->store((longlong)(mi->rli->last_master_timestamp ?
                                  max(0, time_diff) : 0));
     }
     else
@@ -2073,30 +2020,30 @@ bool show_master_info(THD* thd, Master_i
     else
       protocol->store(mi->last_error().message, &my_charset_bin);
     // Last_SQL_Errno
-    protocol->store(mi->rli.last_error().number);
+    protocol->store(mi->rli->last_error().number);
     // Last_SQL_Error
-    if (*mi->rli.last_error().message != '\0')
+    if (*mi->rli->last_error().message != '\0')
     {
       String msg_buf;
-      msg_buf.append(mi->rli.last_error().timestamp);
+      msg_buf.append(mi->rli->last_error().timestamp);
       msg_buf.append(" ");
-      msg_buf.append(mi->rli.last_error().message);
+      msg_buf.append(mi->rli->last_error().message);
       protocol->store(msg_buf.c_ptr_safe(), &my_charset_bin);
     }
     else
-      protocol->store(mi->rli.last_error().message, &my_charset_bin);
+      protocol->store(mi->rli->last_error().message, &my_charset_bin);
 
     // Replicate_Ignore_Server_Ids
     {
       char buff[FN_REFLEN];
       ulong i, cur_len;
       for (i= 0, buff[0]= 0, cur_len= 0;
-           i < mi->ignore_server_ids.elements; i++)
+           i < mi->ignore_server_ids->server_ids.elements; i++)
       {
         ulong s_id, slen;
         char sbuff[FN_REFLEN];
-        get_dynamic(&mi->ignore_server_ids, (uchar*) &s_id, i);
-        slen= sprintf(sbuff, (i==0? "%lu" : ", %lu"), s_id);
+        get_dynamic(&(mi->ignore_server_ids->server_ids), (uchar*) &s_id, i);
+        slen= sprintf(sbuff, (i == 0 ? "%lu" : ", %lu"), s_id);
         if (cur_len + slen + 4 > FN_REFLEN)
         {
           /*
@@ -2114,16 +2061,16 @@ bool show_master_info(THD* thd, Master_i
     protocol->store((uint32) mi->master_id);
     protocol->store(mi->master_uuid, &my_charset_bin);
     // Master_Info_File
-    protocol->store(mi->info_file_name, &my_charset_bin);
+    protocol->store(mi->get_description_info(), &my_charset_bin);
     // SQL_Delay
-    protocol->store((uint32) mi->rli.get_sql_delay());
+    protocol->store((uint32) mi->rli->get_sql_delay());
     // SQL_Remaining_Delay
     // THD::proc_info is not protected by any lock, so we read it once
     // to ensure that we use the same value throughout this function.
-    const char *slave_sql_running_state= mi->rli.sql_thd ? mi->rli.sql_thd->proc_info : "";
+    const char *slave_sql_running_state= mi->rli->info_thd ? mi->rli->info_thd->proc_info : "";
     if (slave_sql_running_state == Relay_log_info::state_delaying_string)
     {
-      time_t t= my_time(0), sql_delay_end= mi->rli.get_sql_delay_end();
+      time_t t= my_time(0), sql_delay_end= mi->rli->get_sql_delay_end();
       protocol->store((uint32)(t < sql_delay_end ? sql_delay_end - t : 0));
     }
     else
@@ -2133,9 +2080,9 @@ bool show_master_info(THD* thd, Master_i
     // Master_Retry_Count
     protocol->store((ulonglong) mi->retry_count);
 
-    mysql_mutex_unlock(&mi->rli.err_lock);
+    mysql_mutex_unlock(&mi->rli->err_lock);
     mysql_mutex_unlock(&mi->err_lock);
-    mysql_mutex_unlock(&mi->rli.data_lock);
+    mysql_mutex_unlock(&mi->rli->data_lock);
     mysql_mutex_unlock(&mi->data_lock);
 
     if (my_net_write(&thd->net, (uchar*) thd->packet.ptr(), packet->length()))
@@ -2301,7 +2248,7 @@ static int request_dump(THD *thd, MYSQL*
   uchar buf[FN_REFLEN + 10];
   int len;
   ushort binlog_flags = 0; // for now
-  char* logname = mi->master_log_name;
+  const char* logname = mi->get_master_log_name();
   DBUG_ENTER("request_dump");
   
   *suppress_warnings= FALSE;
@@ -2312,7 +2259,7 @@ static int request_dump(THD *thd, MYSQL*
     DBUG_RETURN(1);
   
   // TODO if big log files: Change next to int8store()
-  int4store(buf, (ulong) mi->master_log_pos);
+  int4store(buf, (ulong) mi->get_master_log_pos());
   int2store(buf + 4, binlog_flags);
   int4store(buf + 6, server_id);
   len = (uint) strlen(logname);
@@ -2365,7 +2312,7 @@ static ulong read_event(MYSQL* mysql, Ma
     We check if we were told to die, and if not, try reading again
   */
 #ifndef DBUG_OFF
-  if (disconnect_slave_event_count && !(mi->events_till_disconnect--))
+  if (disconnect_slave_event_count && !(mi->events_until_exit--))
     DBUG_RETURN(packet_error);
 #endif
 
@@ -2581,7 +2528,7 @@ int apply_event_and_update_pos(Log_event
   DBUG_PRINT("info", ("thd->options: %s%s; rli->last_event_start_time: %lu",
                       FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
                       FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
-                      (ulong) rli->last_event_start_time));
+                      rli->last_event_start_time));
 
   /*
     Execute the event to change the database and update the binary
@@ -2617,7 +2564,6 @@ int apply_event_and_update_pos(Log_event
   int reason= ev->shall_skip(rli);
   if (reason == Log_event::EVENT_SKIP_COUNT)
     sql_slave_skip_counter= --rli->slave_skip_counter;
-
   if (reason == Log_event::EVENT_SKIP_NOT)
   {
     // Sleeps if needed, and unlocks rli->data_lock.
@@ -2652,6 +2598,12 @@ int apply_event_and_update_pos(Log_event
   DBUG_PRINT("info", ("apply_event error = %d", exec_res));
   if (exec_res == 0)
   {
+    /*
+      Positions are not updated when an XID is processed, i.e. not skipped.
+      To make the slave crash-safe positions are updated while processing
+      the XID event and as such do not need to be updated again.
+      See sql/rpl_rli.h for further details.
+    */
     int error= ev->update_pos(rli);
 #ifndef DBUG_OFF
     DBUG_PRINT("info", ("update_pos error = %d", error));
@@ -2659,11 +2611,11 @@ int apply_event_and_update_pos(Log_event
     {
       char buf[22];
       DBUG_PRINT("info", ("group %s %s",
-                          llstr(rli->group_relay_log_pos, buf),
-                          rli->group_relay_log_name));
+                          llstr(rli->get_group_relay_log_pos(), buf),
+                          rli->get_group_relay_log_name()));
       DBUG_PRINT("info", ("event %s %s",
-                          llstr(rli->event_relay_log_pos, buf),
-                          rli->event_relay_log_name));
+                          llstr(rli->get_event_relay_log_pos(), buf),
+                          rli->get_event_relay_log_name()));
     }
 #endif
     /*
@@ -2681,8 +2633,8 @@ int apply_event_and_update_pos(Log_event
                   " of the relay log information: the slave may"
                   " be in an inconsistent state."
                   " Stopped in %s position %s",
-                  rli->group_relay_log_name,
-                  llstr(rli->group_relay_log_pos, buf));
+                  rli->get_group_relay_log_name(),
+                  llstr(rli->get_group_relay_log_pos(), buf));
       DBUG_RETURN(2);
     }
   }
@@ -2711,7 +2663,7 @@ int apply_event_and_update_pos(Log_event
      tried slave_trans_retries times.  If the event has been retried
      fewer times, 0 is returned.
 
-   - init_master_info or init_relay_log_pos failed. (These are called
+   - init_info or init_relay_log_pos failed. (These are called
      if a failure occurs when applying the event.)
 
    - An error occurred when updating the binlog position.
@@ -2733,7 +2685,7 @@ static int exec_relay_log_event(THD* thd
 
   Log_event * ev = next_event(rli);
 
-  DBUG_ASSERT(rli->sql_thd==thd);
+  DBUG_ASSERT(rli->info_thd==thd);
 
   if (sql_slave_killed(thd,rli))
   {
@@ -2841,21 +2793,24 @@ static int exec_relay_log_event(THD* thd
 	  Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
 	  there is no rollback since 5.0.13 (ref: manual).
           We have to not only seek but also
-          a) init_master_info(), to seek back to hot relay log's start for later
+          a) init_info(), to seek back to hot relay log's start for later
           (for when we will come back to this hot log after re-processing the
           possibly existing old logs where BEGIN is: check_binlog_magic() will
           then need the cache to be at position 0 (see comments at beginning of
-          init_master_info()).
+          init_info()).
           b) init_relay_log_pos(), because the BEGIN may be an older relay log.
         */
         if (rli->trans_retries < slave_trans_retries)
         {
-          if (init_master_info(rli->mi, 0, 0, 0, SLAVE_SQL))
+          /*
+             We need to figure out if there is a test case that covers
+             this part. \Alfranio.
+          */
+          if (init_info(rli->mi, FALSE, SLAVE_SQL))
             sql_print_error("Failed to initialize the master info structure");
-          else if (init_relay_log_pos(rli,
-                                      rli->group_relay_log_name,
-                                      rli->group_relay_log_pos,
-                                      1, &errmsg, 1))
+          else if (rli->init_relay_log_pos(rli->get_group_relay_log_name(),
+                                           rli->get_group_relay_log_pos(),
+                                           1, &errmsg, 1))
             sql_print_error("Error initializing relay log position: %s",
                             errmsg);
           else
@@ -2883,7 +2838,7 @@ static int exec_relay_log_event(THD* thd
       }
       else if ((exec_res && !temp_err) ||
                (opt_using_transactions &&
-                rli->group_relay_log_pos == rli->event_relay_log_pos))
+                rli->get_group_relay_log_pos() == rli->get_event_relay_log_pos()))
       {
         /*
           Only reset the retry counter if the entire group succeeded
@@ -2912,7 +2867,6 @@ on this slave.\
   DBUG_RETURN(1);
 }
 
-
 static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info)
 {
   if (io_slave_killed(thd, mi))
@@ -2974,7 +2928,8 @@ static int try_to_reconnect(THD *thd, MY
   {
     char buf[256], llbuff[22];
     my_snprintf(buf, sizeof(buf), messages[SLAVE_RECON_MSG_FAILED], 
-                IO_RPL_LOG_NAME, llstr(mi->master_log_pos, llbuff));
+                mi->get_io_rpl_log_name(), llstr(mi->get_master_log_pos(),
+                llbuff));
     /* 
       Raise a warining during registering on master/requesting dump.
       Log a message reading event.
@@ -3013,7 +2968,7 @@ pthread_handler_t handle_slave_io(void *
   THD *thd; // needs to be first for thread_stack
   MYSQL *mysql;
   Master_info *mi = (Master_info*)arg;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   char llbuff[22];
   uint retry_count;
   bool suppress_warnings;
@@ -3034,12 +2989,12 @@ pthread_handler_t handle_slave_io(void *
   mi->slave_run_id++;
 
 #ifndef DBUG_OFF
-  mi->events_till_disconnect = disconnect_slave_event_count;
+  mi->events_until_exit = disconnect_slave_event_count;
 #endif
 
   thd= new THD; // note that contructor of THD uses DBUG_ !
   THD_CHECK_SENTRY(thd);
-  mi->io_thd = thd;
+  mi->info_thd = thd;
 
   pthread_detach_this_thread();
   thd->thread_stack= (char*) &thd; // remember where our stack is
@@ -3060,8 +3015,8 @@ pthread_handler_t handle_slave_io(void *
   mysql_cond_broadcast(&mi->start_cond);
 
   DBUG_PRINT("master_info",("log_file_name: '%s'  position: %s",
-                            mi->master_log_name,
-                            llstr(mi->master_log_pos,llbuff)));
+                            mi->get_master_log_name(),
+                            llstr(mi->get_master_log_pos(), llbuff)));
 
   /* This must be called before run any binlog_relay_io hooks */
   my_pthread_setspecific_ptr(RPL_MASTER_INFO, mi);
@@ -3087,8 +3042,8 @@ pthread_handler_t handle_slave_io(void *
     sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',"
                           "replication started in log '%s' at position %s",
                           mi->user, mi->host, mi->port,
-			  IO_RPL_LOG_NAME,
-			  llstr(mi->master_log_pos,llbuff));
+			  mi->get_io_rpl_log_name(),
+			  llstr(mi->get_master_log_pos(), llbuff));
   /*
     Assign the max_packet_size with the bigger one of the values of
     'max_packet_size' and 'opt_binlog_rows_event_max_size'. So that
@@ -3136,7 +3091,7 @@ connected:
 
   if (ret == 2) 
   { 
-    if (check_io_slave_killed(mi->io_thd, mi, "Slave I/O thread killed"
+    if (check_io_slave_killed(mi->info_thd, mi, "Slave I/O thread killed"
                               "while calling get_master_version_and_clock(...)"))
       goto err;
     suppress_warnings= FALSE;
@@ -3147,7 +3102,7 @@ connected:
     goto connected;
   } 
 
-  if (mi->rli.relay_log.description_event_for_queue->binlog_version > 1)
+  if (mi->rli->relay_log.description_event_for_queue->binlog_version > 1)
   {
     /*
       Register ourselves with the master.
@@ -3295,19 +3250,19 @@ Stopping slave I/O thread due to out-of-
         goto err;
       }
 
-      if (flush_master_info(mi, TRUE, TRUE))
+      if (flush_master_info(mi, FALSE))
       {
         sql_print_error("Failed to flush master info file");
         goto err;
       }
       /*
         See if the relay logs take too much space.
-        We don't lock mi->rli.log_space_lock here; this dirty read saves time
+        We don't lock mi->rli->log_space_lock here; this dirty read saves time
         and does not introduce any problem:
-        - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so
+        - if mi->rli->ignore_log_space_limit is 1 but becomes 0 just after (so
         the clean value is 0), then we are reading only one more event as we
         should, and we'll block only at the next event. No big deal.
-        - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so
+        - if mi->rli->ignore_log_space_limit is 0 but becomes 1 just after (so
         the clean value is 1), then we are going into wait_for_relay_log_space()
         for no reason, but this function will do a clean read, notice the clean
         value and exit immediately.
@@ -3339,7 +3294,7 @@ log space");
 err:
   // print the current replication position
   sql_print_information("Slave I/O thread exiting, read up to log '%s', position %s",
-                  IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
+                  mi->get_io_rpl_log_name(), llstr(mi->get_master_log_pos(), llbuff));
   RUN_HOOK(binlog_relay_io, thread_stop, (thd, mi));
   thd->set_query(NULL, 0);
   thd->reset_db(NULL, 0);
@@ -3364,8 +3319,8 @@ err:
   mysql_mutex_lock(&mi->run_lock);
 
   /* Forget the relay log's format */
-  delete mi->rli.relay_log.description_event_for_queue;
-  mi->rli.relay_log.description_event_for_queue= 0;
+  delete mi->rli->relay_log.description_event_for_queue;
+  mi->rli->relay_log.description_event_for_queue= 0;
   DBUG_ASSERT(thd->net.buff != 0);
   net_end(&thd->net); // destructor will not free it, because net.vio is 0
   mysql_mutex_lock(&LOCK_thread_count);
@@ -3374,7 +3329,7 @@ err:
   mysql_mutex_unlock(&LOCK_thread_count);
   mi->abort_slave= 0;
   mi->slave_running= 0;
-  mi->io_thd= 0;
+  mi->info_thd= 0;
   /*
     Note: the order of the two following calls (first broadcast, then unlock)
     is important. Otherwise a killer_thread can execute between the calls and
@@ -3383,11 +3338,10 @@ err:
   mysql_cond_broadcast(&mi->stop_cond);       // tell the world we are done
   DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5););
   mysql_mutex_unlock(&mi->run_lock);
-
   DBUG_LEAVE;                                   // Must match DBUG_ENTER()
   my_thread_end();
   pthread_exit(0);
-  return 0;                                     // Avoid compiler warnings
+  return(0);                                    // Avoid compiler warnings
 }
 
 /*
@@ -3448,11 +3402,11 @@ pthread_handler_t handle_slave_sql(void 
   char llbuff[22],llbuff1[22];
   char saved_log_name[FN_REFLEN];
   char saved_master_log_name[FN_REFLEN];
-  my_off_t UNINIT_VAR(saved_log_pos);
-  my_off_t UNINIT_VAR(saved_master_log_pos);
+  my_off_t saved_log_pos= 0;
+  my_off_t saved_master_log_pos= 0;
   my_off_t saved_skip= 0;
 
-  Relay_log_info* rli = &((Master_info*)arg)->rli;
+  Relay_log_info* rli = ((Master_info*)arg)->rli;
   const char *errmsg;
 
   // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
@@ -3464,12 +3418,12 @@ pthread_handler_t handle_slave_sql(void 
   DBUG_ASSERT(!rli->slave_running);
   errmsg= 0;
 #ifndef DBUG_OFF
-  rli->events_till_abort = abort_slave_event_count;
+  rli->events_until_exit = abort_slave_event_count;
 #endif
 
   thd = new THD; // note that contructor of THD uses DBUG_ !
   thd->thread_stack = (char*)&thd; // remember where our stack is
-  rli->sql_thd= thd;
+  rli->info_thd= thd;
   
   /* Inform waiting threads that slave has started */
   rli->slave_run_id++;
@@ -3525,11 +3479,10 @@ pthread_handler_t handle_slave_sql(void 
   rli->trans_retries= 0; // start from "no error"
   DBUG_PRINT("info", ("rli->trans_retries: %lu", rli->trans_retries));
 
-  if (init_relay_log_pos(rli,
-                         rli->group_relay_log_name,
-                         rli->group_relay_log_pos,
-                         1 /*need data lock*/, &errmsg,
-                         1 /*look for a description_event*/))
+  if (rli->init_relay_log_pos(rli->get_group_relay_log_name(),
+                              rli->get_group_relay_log_pos(),
+                              1 /*need data lock*/, &errmsg,
+                              1 /*look for a description_event*/))
   { 
     rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, 
                 "Error initializing relay log position: %s", errmsg);
@@ -3541,8 +3494,8 @@ pthread_handler_t handle_slave_sql(void 
     char llbuf1[22], llbuf2[22];
     DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
                         llstr(my_b_tell(rli->cur_log),llbuf1),
-                        llstr(rli->event_relay_log_pos,llbuf2)));
-    DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
+                        llstr(rli->get_event_relay_log_pos(),llbuf2)));
+    DBUG_ASSERT(rli->get_event_relay_log_pos() >= BIN_LOG_HEADER_SIZE);
     /*
       Wonder if this is correct. I (Guilhem) wonder if my_b_tell() returns the
       correct position when it's called just after my_b_seek() (the questionable
@@ -3556,20 +3509,20 @@ pthread_handler_t handle_slave_sql(void 
       DBUG_ASSERT().
     */
 #ifdef SHOULD_BE_CHECKED
-    DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
+    DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->get_event_relay_log_pos());
 #endif
   }
 #endif
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
 
   DBUG_PRINT("master_info",("log_file_name: %s  position: %s",
-                            rli->group_master_log_name,
-                            llstr(rli->group_master_log_pos,llbuff)));
+                            rli->get_group_master_log_name(),
+                            llstr(rli->get_group_master_log_pos(),llbuff)));
   if (global_system_variables.log_warnings)
     sql_print_information("Slave SQL thread initialized, starting replication in \
-log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
-                    llstr(rli->group_master_log_pos,llbuff),rli->group_relay_log_name,
-                    llstr(rli->group_relay_log_pos,llbuff1));
+log '%s' at position %s, relay log '%s' position: %s", rli->get_rpl_log_name(),
+                    llstr(rli->get_group_master_log_pos(),llbuff),rli->get_group_relay_log_name(),
+                    llstr(rli->get_group_relay_log_pos(),llbuff1));
 
   if (check_temp_dir(rli->slave_patternload_file))
   {
@@ -3598,10 +3551,10 @@ log '%s' at position %s, relay log '%s' 
   mysql_mutex_lock(&rli->data_lock);
   if (rli->slave_skip_counter)
   {
-    strmake(saved_log_name, rli->group_relay_log_name, FN_REFLEN - 1);
-    strmake(saved_master_log_name, rli->group_master_log_name, FN_REFLEN - 1);
-    saved_log_pos= rli->group_relay_log_pos;
-    saved_master_log_pos= rli->group_master_log_pos;
+    strmake(saved_log_name, rli->get_group_relay_log_name(), FN_REFLEN - 1);
+    strmake(saved_master_log_name, rli->get_group_master_log_name(), FN_REFLEN - 1);
+    saved_log_pos= rli->get_group_relay_log_pos();
+    saved_master_log_pos= rli->get_group_master_log_pos();
     saved_skip= rli->slave_skip_counter;
   }
   if (rli->until_condition != Relay_log_info::UNTIL_NONE &&
@@ -3620,7 +3573,7 @@ log '%s' at position %s, relay log '%s' 
   while (!sql_slave_killed(thd,rli))
   {
     thd_proc_info(thd, "Reading event from the relay log");
-    DBUG_ASSERT(rli->sql_thd == thd);
+    DBUG_ASSERT(rli->info_thd == thd);
     THD_CHECK_SENTRY(thd);
 
     if (saved_skip && rli->slave_skip_counter == 0)
@@ -3632,8 +3585,8 @@ log '%s' at position %s, relay log '%s' 
         "master_log_pos='%ld' ",
         (ulong) saved_skip, saved_log_name, (ulong) saved_log_pos,
         saved_master_log_name, (ulong) saved_master_log_pos,
-        rli->group_relay_log_name, (ulong) rli->group_relay_log_pos,
-        rli->group_master_log_name, (ulong) rli->group_master_log_pos);
+        rli->get_group_relay_log_name(), (ulong) rli->get_group_relay_log_pos(),
+        rli->get_group_master_log_name(), (ulong) rli->get_group_master_log_pos());
       saved_skip= 0;
     }
     
@@ -3696,13 +3649,14 @@ log '%s' at position %s, relay log '%s' 
           sql_print_error("Error loading user-defined library, slave SQL "
             "thread aborted. Install the missing library, and restart the "
             "slave SQL thread with \"SLAVE START\". We stopped at log '%s' "
-            "position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, 
-            llbuff));
+            "position %s", rli->get_rpl_log_name(),
+            llstr(rli->get_group_master_log_pos(), llbuff));
         else
           sql_print_error("\
 Error running query, slave SQL thread aborted. Fix the problem, and restart \
 the slave SQL thread with \"SLAVE START\". We stopped at log \
-'%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
+'%s' position %s", rli->get_rpl_log_name(),
+llstr(rli->get_group_master_log_pos(), llbuff));
       }
       goto err;
     }
@@ -3711,7 +3665,8 @@ the slave SQL thread with \"SLAVE START\
   /* Thread stopped. Print the current replication position to the log */
   sql_print_information("Slave SQL thread exiting, replication stopped in log "
                         "'%s' at position %s",
-                        RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff));
+                        rli->get_rpl_log_name(),
+                        llstr(rli->get_group_master_log_pos(), llbuff));
 
  err:
 
@@ -3756,10 +3711,10 @@ the slave SQL thread with \"SLAVE START\
   thd->temporary_tables = 0; // remove tempation from destructor to close them
   DBUG_ASSERT(thd->net.buff != 0);
   net_end(&thd->net); // destructor will not free it, because we are weird
-  DBUG_ASSERT(rli->sql_thd == thd);
+  DBUG_ASSERT(rli->info_thd == thd);
   THD_CHECK_SENTRY(thd);
-  rli->sql_thd= 0;
-  set_thd_in_use_temporary_tables(rli);  // (re)set sql_thd in use for saved temp tables
+  rli->info_thd= 0;
+  set_thd_in_use_temporary_tables(rli);  // (re)set info_thd in use for saved temp tables
   mysql_mutex_lock(&LOCK_thread_count);
   THD_CHECK_SENTRY(thd);
   delete thd;
@@ -3773,10 +3728,10 @@ the slave SQL thread with \"SLAVE START\
   DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5););
   mysql_mutex_unlock(&rli->run_lock);  // tell the world we are done
 
-  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
+  DBUG_LEAVE;                            // Must match DBUG_ENTER()
   my_thread_end();
   pthread_exit(0);
-  return 0;                                     // Avoid compiler warnings
+  return 0;                             // Avoid compiler warnings
 }
 
 
@@ -3789,7 +3744,7 @@ static int process_io_create_file(Master
   int error = 1;
   ulong num_bytes;
   bool cev_not_written;
-  THD *thd = mi->io_thd;
+  THD *thd = mi->info_thd;
   NET *net = &mi->mysql->net;
   DBUG_ENTER("process_io_create_file");
 
@@ -3843,21 +3798,21 @@ static int process_io_create_file(Master
           break;
         Execute_load_log_event xev(thd,0,0);
         xev.log_pos = cev->log_pos;
-        if (unlikely(mi->rli.relay_log.append(&xev)))
+        if (unlikely(mi->rli->relay_log.append(&xev)))
         {
           mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
                      ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
                      "error writing Exec_load event to relay log");
           goto err;
         }
-        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        mi->rli->relay_log.harvest_bytes_written(&mi->rli->log_space_total);
         break;
       }
       if (unlikely(cev_not_written))
       {
         cev->block = net->read_pos;
         cev->block_len = num_bytes;
-        if (unlikely(mi->rli.relay_log.append(cev)))
+        if (unlikely(mi->rli->relay_log.append(cev)))
         {
           mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
                      ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
@@ -3865,21 +3820,21 @@ static int process_io_create_file(Master
           goto err;
         }
         cev_not_written=0;
-        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        mi->rli->relay_log.harvest_bytes_written(&mi->rli->log_space_total);
       }
       else
       {
         aev.block = net->read_pos;
         aev.block_len = num_bytes;
         aev.log_pos = cev->log_pos;
-        if (unlikely(mi->rli.relay_log.append(&aev)))
+        if (unlikely(mi->rli->relay_log.append(&aev)))
         {
           mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
                      ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
                      "error writing Append_block event to relay log");
           goto err;
         }
-        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ;
+        mi->rli->relay_log.harvest_bytes_written(&mi->rli->log_space_total);
       }
     }
   }
@@ -3920,17 +3875,18 @@ static int process_io_rotate(Master_info
     DBUG_RETURN(1);
 
   /* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
-  memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
-  mi->master_log_pos= rev->pos;
+  memcpy(const_cast<char *>(mi->get_master_log_name()),
+         rev->new_log_ident, rev->ident_len + 1);
+  mi->set_master_log_pos(rev->pos);
   DBUG_PRINT("info", ("master_log_pos: '%s' %lu",
-                      mi->master_log_name, (ulong) mi->master_log_pos));
+                      mi->get_master_log_name(), (ulong) mi->get_master_log_pos()));
 #ifndef DBUG_OFF
   /*
     If we do not do this, we will be getting the first
     rotate event forever, so we need to not disconnect after one.
   */
   if (disconnect_slave_event_count)
-    mi->events_till_disconnect++;
+    mi->events_until_exit++;
 #endif
 
   /*
@@ -3940,11 +3896,11 @@ static int process_io_rotate(Master_info
     no need to reset description_event_for_queue now. And if it's nothing (same
     master version as before), no need (still using the slave's format).
   */
-  if (mi->rli.relay_log.description_event_for_queue->binlog_version >= 4)
+  if (mi->rli->relay_log.description_event_for_queue->binlog_version >= 4)
   {
-    delete mi->rli.relay_log.description_event_for_queue;
+    delete mi->rli->relay_log.description_event_for_queue;
     /* start from format 3 (MySQL 4.0) again */
-    mi->rli.relay_log.description_event_for_queue= new
+    mi->rli->relay_log.description_event_for_queue= new
       Format_description_log_event(3);
   }
   /*
@@ -3966,7 +3922,7 @@ static int queue_binlog_ver_1_event(Mast
   ulong inc_pos;
   bool ignore_event= 0;
   char *tmp_buf = 0;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   DBUG_ENTER("queue_binlog_ver_1_event");
 
   /*
@@ -4000,18 +3956,18 @@ static int queue_binlog_ver_1_event(Mast
     connected to the master).
   */
   Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
-                                            mi->rli.relay_log.description_event_for_queue);
+                                            mi->rli->relay_log.description_event_for_queue);
   if (unlikely(!ev))
   {
     sql_print_error("Read invalid event from master: '%s',\
  master could be corrupt but a more likely cause of this is a bug",
                     errmsg);
-    my_free(tmp_buf);
+    my_free((char*) tmp_buf);
     DBUG_RETURN(1);
   }
 
   mysql_mutex_lock(&mi->data_lock);
-  ev->log_pos= mi->master_log_pos; /* 3.23 events don't contain log_pos */
+  mi->set_master_log_pos(ev->log_pos); /* 3.23 events don't contain log_pos */
   switch (ev->get_type_code()) {
   case STOP_EVENT:
     ignore_event= 1;
@@ -4040,10 +3996,10 @@ static int queue_binlog_ver_1_event(Mast
     ev->log_pos+= inc_pos;
     int error = process_io_create_file(mi,(Create_file_log_event*)ev);
     delete ev;
-    mi->master_log_pos += inc_pos;
-    DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
+    mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
+    DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
     mysql_mutex_unlock(&mi->data_lock);
-    my_free(tmp_buf);
+    my_free((char*)tmp_buf);
     DBUG_RETURN(error);
   }
   default:
@@ -4067,8 +4023,8 @@ static int queue_binlog_ver_1_event(Mast
     rli->relay_log.harvest_bytes_written(&rli->log_space_total);
   }
   delete ev;
-  mi->master_log_pos+= inc_pos;
-  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
+  mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
+  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
   mysql_mutex_unlock(&mi->data_lock);
   DBUG_RETURN(0);
 }
@@ -4083,18 +4039,18 @@ static int queue_binlog_ver_3_event(Mast
   const char *errmsg = 0;
   ulong inc_pos;
   char *tmp_buf = 0;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   DBUG_ENTER("queue_binlog_ver_3_event");
 
   /* read_log_event() will adjust log_pos to be end_log_pos */
   Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
-                                            mi->rli.relay_log.description_event_for_queue);
+                                            mi->rli->relay_log.description_event_for_queue);
   if (unlikely(!ev))
   {
     sql_print_error("Read invalid event from master: '%s',\
  master could be corrupt but a more likely cause of this is a bug",
                     errmsg);
-    my_free(tmp_buf);
+    my_free((char*) tmp_buf);
     DBUG_RETURN(1);
   }
   mysql_mutex_lock(&mi->data_lock);
@@ -4122,9 +4078,9 @@ static int queue_binlog_ver_3_event(Mast
   }
   rli->relay_log.harvest_bytes_written(&rli->log_space_total);
   delete ev;
-  mi->master_log_pos+= inc_pos;
+  mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
 err:
-  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
+  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
   mysql_mutex_unlock(&mi->data_lock);
   DBUG_RETURN(0);
 }
@@ -4146,7 +4102,7 @@ static int queue_old_event(Master_info *
 {
   DBUG_ENTER("queue_old_event");
 
-  switch (mi->rli.relay_log.description_event_for_queue->binlog_version)
+  switch (mi->rli->relay_log.description_event_for_queue->binlog_version)
   {
   case 1:
       DBUG_RETURN(queue_binlog_ver_1_event(mi,buf,event_len));
@@ -4154,7 +4110,7 @@ static int queue_old_event(Master_info *
       DBUG_RETURN(queue_binlog_ver_3_event(mi,buf,event_len));
   default: /* unsupported format; eg version 2 */
     DBUG_PRINT("info",("unsupported binlog format %d in queue_old_event()",
-                       mi->rli.relay_log.description_event_for_queue->binlog_version));
+                       mi->rli->relay_log.description_event_for_queue->binlog_version));
     DBUG_RETURN(1);
   }
 }
@@ -4174,14 +4130,14 @@ static int queue_event(Master_info* mi,c
   int error= 0;
   String error_msg;
   ulong inc_pos;
-  Relay_log_info *rli= &mi->rli;
+  Relay_log_info *rli= mi->rli;
   mysql_mutex_t *log_lock= rli->relay_log.get_log_lock();
   ulong s_id;
   DBUG_ENTER("queue_event");
 
   LINT_INIT(inc_pos);
 
-  if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
+  if (mi->rli->relay_log.description_event_for_queue->binlog_version<4 &&
       buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */)
     DBUG_RETURN(queue_old_event(mi,buf,event_len));
 
@@ -4197,7 +4153,7 @@ static int queue_event(Master_info* mi,c
       server is shutting down cleanly, it has written all DROP TEMPORARY TABLE
       prepared statements' deletion are TODO only when we binlog prep stmts).
 
-      We don't even increment mi->master_log_pos, because we may be just after
+      We don't even increment mi->get_master_log_pos(), because we may be just after
       a Rotate event. Btw, in a few milliseconds we are going to have a Start
       event from the next binlog (unless the master is presently running
       without --log-bin).
@@ -4205,15 +4161,15 @@ static int queue_event(Master_info* mi,c
     goto err;
   case ROTATE_EVENT:
   {
-    Rotate_log_event rev(buf,event_len,mi->rli.relay_log.description_event_for_queue);
+    Rotate_log_event rev(buf,event_len,mi->rli->relay_log.description_event_for_queue);
     if (unlikely(process_io_rotate(mi,&rev)))
     {
       error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
       goto err;
     }
     /*
-      Now the I/O thread has just changed its mi->master_log_name, so
-      incrementing mi->master_log_pos is nonsense.
+      Now the I/O thread has just changed its mi->get_master_log_name(), so
+      incrementing mi->get_master_log_pos() is nonsense.
     */
     inc_pos= 0;
     break;
@@ -4233,24 +4189,24 @@ static int queue_event(Master_info* mi,c
     const char* errmsg;
     if (!(tmp= (Format_description_log_event*)
           Log_event::read_log_event(buf, event_len, &errmsg,
-                                    mi->rli.relay_log.description_event_for_queue)))
+                                    mi->rli->relay_log.description_event_for_queue)))
     {
       error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
       goto err;
     }
-    delete mi->rli.relay_log.description_event_for_queue;
-    mi->rli.relay_log.description_event_for_queue= tmp;
+    delete mi->rli->relay_log.description_event_for_queue;
+    mi->rli->relay_log.description_event_for_queue= tmp;
     /*
        Though this does some conversion to the slave's format, this will
        preserve the master's binlog format version, and number of event types.
     */
     /*
        If the event was not requested by the slave (the slave did not ask for
-       it), i.e. has end_log_pos=0, we do not increment mi->master_log_pos
+       it), i.e. has end_log_pos=0, we do not increment mi->get_master_log_pos()
     */
     inc_pos= uint4korr(buf+LOG_POS_OFFSET) ? event_len : 0;
     DBUG_PRINT("info",("binlog format is now %d",
-                       mi->rli.relay_log.description_event_for_queue->binlog_version));
+                       mi->rli->relay_log.description_event_for_queue->binlog_version));
 
   }
   break;
@@ -4261,7 +4217,7 @@ static int queue_event(Master_info* mi,c
       HB (heartbeat) cannot come before RL (Relay)
     */
     char  llbuf[22];
-    Heartbeat_log_event hb(buf, event_len, mi->rli.relay_log.description_event_for_queue);
+    Heartbeat_log_event hb(buf, event_len, mi->rli->relay_log.description_event_for_queue);
     if (!hb.is_valid())
     {
       error= ER_SLAVE_HEARTBEAT_FAILURE;
@@ -4280,15 +4236,16 @@ static int queue_event(Master_info* mi,c
        Heartbeat is sent only after an event corresponding to the corrdinates
        the heartbeat carries.
        Slave can not have a difference in coordinates except in the only
-       special case when mi->master_log_name, master_log_pos have never
+       special case when mi->get_master_log_name(), mi->get_master_log_pos() have never
        been updated by Rotate event i.e when slave does not have any history
-       with the master (and thereafter mi->master_log_pos is NULL).
+       with the master (and thereafter mi->get_master_log_pos() is NULL).
 
        TODO: handling `when' for SHOW SLAVE STATUS' snds behind
     */
-    if ((memcmp(mi->master_log_name, hb.get_log_ident(), hb.get_ident_len())
-         && mi->master_log_name != NULL)
-        || mi->master_log_pos != hb.log_pos)
+    if ((memcmp(const_cast<char *>(mi->get_master_log_name()),
+                hb.get_log_ident(), hb.get_ident_len())
+         && mi->get_master_log_name() != NULL)
+        || mi->get_master_log_pos() != hb.log_pos)
     {
       /* missed events of heartbeat from the past */
       error= ER_SLAVE_HEARTBEAT_FAILURE;
@@ -4324,13 +4281,13 @@ static int queue_event(Master_info* mi,c
 
   mysql_mutex_lock(log_lock);
   s_id= uint4korr(buf + SERVER_ID_OFFSET);
-  if ((s_id == ::server_id && !mi->rli.replicate_same_server_id) ||
+  if ((s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
       /*
         the following conjunction deals with IGNORE_SERVER_IDS, if set
         If the master is on the ignore list, execution of
         format description log events and rotate events is necessary.
       */
-      (mi->ignore_server_ids.elements > 0 &&
+      (mi->ignore_server_ids->server_ids.elements > 0 &&
        mi->shall_ignore_server_id(s_id) &&
        /* everything is filtered out from non-master */
        (s_id != mi->master_id ||
@@ -4340,7 +4297,7 @@ static int queue_event(Master_info* mi,c
   {
     /*
       Do not write it to the relay log.
-      a) We still want to increment mi->master_log_pos, so that we won't
+      a) We still want to increment mi->get_master_log_pos(), so that we won't
       re-read this event from the master if the slave IO thread is now
       stopped/restarted (more efficient if the events we are ignoring are big
       LOAD DATA INFILE).
@@ -4350,32 +4307,32 @@ static int queue_event(Master_info* mi,c
       ignored.
       But events which were generated by this slave and which do not exist in
       the master's binlog (i.e. Format_desc, Rotate & Stop) should not increment
-      mi->master_log_pos.
+      mi->get_master_log_pos().
       If the event is originated remotely and is being filtered out by
-      IGNORE_SERVER_IDS it increments mi->master_log_pos
+      IGNORE_SERVER_IDS it increments mi->get_master_log_pos()
       as well as rli->group_relay_log_pos.
     */
-    if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) ||
+    if (!(s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
         (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT &&
          buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT &&
          buf[EVENT_TYPE_OFFSET] != STOP_EVENT))
     {
-      mi->master_log_pos+= inc_pos;
-      memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN);
+      mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
+      memcpy(rli->ign_master_log_name_end, mi->get_master_log_name(), FN_REFLEN);
       DBUG_ASSERT(rli->ign_master_log_name_end[0]);
-      rli->ign_master_log_pos_end= mi->master_log_pos;
+      rli->ign_master_log_pos_end= mi->get_master_log_pos();
     }
     rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
     DBUG_PRINT("info", ("master_log_pos: %lu, event originating from %u server, ignored",
-                        (ulong) mi->master_log_pos, uint4korr(buf + SERVER_ID_OFFSET)));
+                        (ulong) mi->get_master_log_pos(), uint4korr(buf + SERVER_ID_OFFSET)));
   }
   else
   {
     /* write the event to the relay log */
     if (likely(!(rli->relay_log.appendv(buf,event_len,0))))
     {
-      mi->master_log_pos+= inc_pos;
-      DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
+      mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
+      DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
       rli->relay_log.harvest_bytes_written(&rli->log_space_total);
     }
     else
@@ -4399,38 +4356,6 @@ err:
   DBUG_RETURN(error);
 }
 
-
-void end_relay_log_info(Relay_log_info* rli)
-{
-  DBUG_ENTER("end_relay_log_info");
-
-  if (!rli->inited)
-    DBUG_VOID_RETURN;
-  if (rli->info_fd >= 0)
-  {
-    end_io_cache(&rli->info_file);
-    mysql_file_close(rli->info_fd, MYF(MY_WME));
-    rli->info_fd = -1;
-  }
-  if (rli->cur_log_fd >= 0)
-  {
-    end_io_cache(&rli->cache_buf);
-    mysql_file_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
-  }
-  rli->inited = 0;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  rli->relay_log.harvest_bytes_written(&rli->log_space_total);
-  /*
-    Delete the slave's temporary tables from memory.
-    In the future there will be other actions than this, to ensure persistance
-    of slave's temp tables after shutdown.
-  */
-  rli->close_temporary_tables();
-  DBUG_VOID_RETURN;
-}
-
-
 /**
   Hook to detach the active VIO before closing a connection handle.
 
@@ -4491,12 +4416,12 @@ static int connect_to_master(THD* thd, M
 {
   int slave_was_killed;
   int last_errno= -2;                           // impossible error
-  ulong err_count= 0;
+  ulong err_count=0;
   char llbuff[22];
   DBUG_ENTER("connect_to_master");
 
 #ifndef DBUG_OFF
-  mi->events_till_disconnect = disconnect_slave_event_count;
+  mi->events_until_exit = disconnect_slave_event_count;
 #endif
   ulong client_flag= CLIENT_REMEMBER_OPTIONS;
   if (opt_slave_compressed_protocol)
@@ -4540,7 +4465,7 @@ static int connect_to_master(THD* thd, M
                " - retry-time: %d  retries: %lu",
                (reconnect ? "reconnecting" : "connecting"),
                mi->user, mi->host, mi->port,
-               mi->connect_retry, err_count+1);
+               mi->connect_retry, err_count + 1);
     /*
       By default we try forever. The reason is that failure will trigger
       master election, so if the user did not set mi->retry_count we
@@ -4565,8 +4490,8 @@ static int connect_to_master(THD* thd, M
         sql_print_information("Slave: connected to master '%s@%s:%d',\
 replication resumed in log '%s' at position %s", mi->user,
                         mi->host, mi->port,
-                        IO_RPL_LOG_NAME,
-                        llstr(mi->master_log_pos,llbuff));
+                        mi->get_io_rpl_log_name(),
+                        llstr(mi->get_master_log_pos(),llbuff));
     }
     else
     {
@@ -4664,95 +4589,6 @@ MYSQL *rpl_connect_master(MYSQL *mysql)
   return mysql;
 }
 
-/**
-  Store the file and position where the slave's SQL thread are in the
-  relay log.
-
-  Notes:
-
-  - This function should be called either from the slave SQL thread,
-    or when the slave thread is not running.  (It reads the
-    group_{relay|master}_log_{pos|name} and delay fields in the rli
-    object.  These may only be modified by the slave SQL thread or by
-    a client thread when the slave SQL thread is not running.)
-
-  - If there is an active transaction, then we do not update the
-    position in the relay log.  This is to ensure that we re-execute
-    statements if we die in the middle of an transaction that was
-    rolled back.
-
-  - As a transaction never spans binary logs, we don't have to handle
-    the case where we do a relay-log-rotation in the middle of the
-    transaction.  If transactions could span several binlogs, we would
-    have to ensure that we do not delete the relay log file where the
-    transaction started before switching to a new relay log file.
-
-  - Error can happen if writing to file fails or if flushing the file
-    fails.
-
-  @param rli The object representing the Relay_log_info.
-
-  @todo Change the log file information to a binary format to avoid
-  calling longlong2str.
-
-  @todo Move the member function into rpl_rli.cc and get rid of the
-  global function. /SVEN
-
-  @return 0 on success, 1 on error.
-*/
-bool flush_relay_log_info(Relay_log_info* rli)
-{
-  return rli->flush();
-}
-
-bool Relay_log_info::flush()
-{
-  bool error=0;
-
-  DBUG_ENTER("Relay_log_info::flush()");
-
-  /*
-    @todo Uncomment the following assertion. See todo in
-    Relay_log_info::init() for details. /Sven
-  */
-  //DBUG_ASSERT(!belongs_to_client());
-
-  IO_CACHE *file = &info_file;
-  // 2*file name, 2*long long, 2*unsigned long, 6*'\n'
-  char buff[FN_REFLEN * 2 + 22 * 2 + 10 * 2 + 6], *pos;
-  my_b_seek(file, 0L);
-  pos= longlong2str(LINES_IN_RELAY_LOG_INFO_WITH_DELAY, buff, 10);
-  *pos++='\n';
-  pos=strmov(pos, group_relay_log_name);
-  *pos++='\n';
-  pos=longlong2str(group_relay_log_pos, pos, 10);
-  *pos++='\n';
-  pos=strmov(pos, group_master_log_name);
-  *pos++='\n';
-  pos=longlong2str(group_master_log_pos, pos, 10);
-  *pos++= '\n';
-  pos= longlong2str(sql_delay, pos, 10);
-  *pos= '\n';
-  if (my_b_write(file, (uchar*) buff, (size_t) (pos-buff)+1))
-    error=1;
-  if (flush_io_cache(file))
-    error=1;
-  if (sync_relayloginfo_period &&
-      !error &&
-      ++sync_counter >= sync_relayloginfo_period)
-  {
-    if (my_sync(info_fd, MYF(MY_WME)))
-      error=1;
-    sync_counter= 0;
-  }
-  /* 
-    Flushing the relay log is done by the slave I/O thread 
-    or by the user on STOP SLAVE. 
-   */
-  DBUG_RETURN(error);
-}
-
-
 /*
   Called when we notice that the current "hot" log got rotated under our feet.
 */
@@ -4764,7 +4600,7 @@ static IO_CACHE *reopen_relay_log(Relay_
   DBUG_ASSERT(rli->cur_log_fd == -1);
 
   IO_CACHE *cur_log = rli->cur_log=&rli->cache_buf;
-  if ((rli->cur_log_fd=open_binlog(cur_log,rli->event_relay_log_name,
+  if ((rli->cur_log_fd=open_binlog(cur_log,rli->get_event_relay_log_name(),
                                    errmsg)) <0)
     DBUG_RETURN(0);
   /*
@@ -4772,8 +4608,9 @@ static IO_CACHE *reopen_relay_log(Relay_
     relay_log_pos       Current log pos
     pending             Number of bytes already processed from the event
   */
-  rli->event_relay_log_pos= max(rli->event_relay_log_pos, BIN_LOG_HEADER_SIZE);
-  my_b_seek(cur_log,rli->event_relay_log_pos);
+  rli->set_event_relay_log_pos(max(rli->get_event_relay_log_pos(),
+                                   BIN_LOG_HEADER_SIZE));
+  my_b_seek(cur_log,rli->get_event_relay_log_pos());
   DBUG_RETURN(cur_log);
 }
 
@@ -4794,13 +4631,13 @@ static Log_event* next_event(Relay_log_i
   IO_CACHE* cur_log = rli->cur_log;
   mysql_mutex_t *log_lock = rli->relay_log.get_log_lock();
   const char* errmsg=0;
-  THD* thd = rli->sql_thd;
+  THD* thd = rli->info_thd;
   DBUG_ENTER("next_event");
 
   DBUG_ASSERT(thd != 0);
 
 #ifndef DBUG_OFF
-  if (abort_slave_event_count && !rli->events_till_abort--)
+  if (abort_slave_event_count && !rli->events_until_exit--)
     DBUG_RETURN(0);
 #endif
 
@@ -4855,13 +4692,26 @@ static Log_event* next_event(Relay_log_i
       goto err;
 #ifndef DBUG_OFF
     {
+      DBUG_PRINT("info", ("assertion skip %lu file pos %lu event relay log pos %lu file %s\n",
+        (ulong) rli->slave_skip_counter, (ulong) my_b_tell(cur_log),
+        (ulong) rli->get_event_relay_log_pos(),
+        rli->get_event_relay_log_name()));
+
       /* This is an assertion which sometimes fails, let's try to track it */
       char llbuf1[22], llbuf2[22];
       DBUG_PRINT("info", ("my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
                           llstr(my_b_tell(cur_log),llbuf1),
-                          llstr(rli->event_relay_log_pos,llbuf2)));
+                          llstr(rli->get_event_relay_log_pos(),llbuf2)));
       DBUG_ASSERT(my_b_tell(cur_log) >= BIN_LOG_HEADER_SIZE);
-      DBUG_ASSERT(my_b_tell(cur_log) == rli->event_relay_log_pos);
+      DBUG_ASSERT(my_b_tell(cur_log) == rli->get_event_relay_log_pos());
+
+      DBUG_PRINT("info", ("next_event group master %s %lu group relay %s %lu event %s %lu\n",
+        rli->get_group_master_log_name(),
+        (ulong) rli->get_group_master_log_pos(),
+        rli->get_group_relay_log_name(),
+        (ulong) rli->get_group_relay_log_pos(),
+        rli->get_event_relay_log_name(),
+        (ulong) rli->get_event_relay_log_pos()));
     }
 #endif
     /*
@@ -4878,19 +4728,18 @@ static Log_event* next_event(Relay_log_i
     */
     if ((ev=Log_event::read_log_event(cur_log,0,
                                       rli->relay_log.description_event_for_exec)))
-
     {
-      DBUG_ASSERT(thd==rli->sql_thd);
+      DBUG_ASSERT(thd==rli->info_thd);
       /*
         read it while we have a lock, to avoid a mutex lock in
         inc_event_relay_log_pos()
       */
-      rli->future_event_relay_log_pos= my_b_tell(cur_log);
+      rli->set_future_event_relay_log_pos(my_b_tell(cur_log));
       if (hot_log)
         mysql_mutex_unlock(log_lock);
       DBUG_RETURN(ev);
     }
-    DBUG_ASSERT(thd==rli->sql_thd);
+    DBUG_ASSERT(thd==rli->info_thd);
     if (opt_reckless_slave)                     // For mysql-test
       cur_log->error = 0;
     if (cur_log->error < 0)
@@ -4999,7 +4848,7 @@ static Log_event* next_event(Relay_log_i
         mysql_mutex_unlock(&rli->log_space_lock);
         mysql_cond_broadcast(&rli->log_space_cond);
         // Note that wait_for_update_relay_log unlocks lock_log !
-        rli->relay_log.wait_for_update_relay_log(rli->sql_thd);
+        rli->relay_log.wait_for_update_relay_log(rli->info_thd);
         // re-acquire data lock since we released it earlier
         mysql_mutex_lock(&rli->data_lock);
         continue;
@@ -5029,12 +4878,19 @@ static Log_event* next_event(Relay_log_i
         */
         if (rli->relay_log.purge_first_log
             (rli,
-             rli->group_relay_log_pos == rli->event_relay_log_pos
-             && !strcmp(rli->group_relay_log_name,rli->event_relay_log_name)))
+             rli->get_group_relay_log_pos() == rli->get_event_relay_log_pos()
+             && !strcmp(rli->get_group_relay_log_name(),rli->get_event_relay_log_name())))
         {
           errmsg = "Error purging processed logs";
           goto err;
         }
+        DBUG_PRINT("info", ("next_event group master %s %lu  group relay %s %lu event %s %lu\n",
+          rli->get_group_master_log_name(),
+          (ulong) rli->get_group_master_log_pos(),
+          rli->get_group_relay_log_name(),
+          (ulong) rli->get_group_relay_log_pos(),
+          rli->get_event_relay_log_name(),
+          (ulong) rli->get_event_relay_log_pos()));
       }
       else
       {
@@ -5050,10 +4906,9 @@ static Log_event* next_event(Relay_log_i
           errmsg = "error switching to the next log";
           goto err;
         }
-        rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE;
-        strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
-                sizeof(rli->event_relay_log_name)-1);
-        flush_relay_log_info(rli);
+        rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);
+        rli->set_event_relay_log_name(rli->linfo.log_file_name);
+        rli->flush_info();
       }
 
       /*
@@ -5126,7 +4981,7 @@ static Log_event* next_event(Relay_log_i
 event(errno: %d  cur_log->error: %d)",
                       my_errno,cur_log->error);
       // set read position to the beginning of the event
-      my_b_seek(cur_log,rli->event_relay_log_pos);
+      my_b_seek(cur_log,rli->get_event_relay_log_pos());
       /* otherwise, we have had a partial read */
       errmsg = "Aborting slave SQL thread because of partial event read";
       break;                                    // To end of function
@@ -5156,7 +5011,7 @@ err:
 void rotate_relay_log(Master_info* mi)
 {
   DBUG_ENTER("rotate_relay_log");
-  Relay_log_info* rli= &mi->rli;
+  Relay_log_info* rli= mi->rli;
 
   DBUG_EXECUTE_IF("crash_before_rotate_relaylog", abort(););
 
@@ -5283,9 +5138,9 @@ bool rpl_master_has_bug(const Relay_log_
  */
 bool rpl_master_erroneous_autoinc(THD *thd)
 {
-  if (active_mi && active_mi->rli.sql_thd == thd)
+  if (active_mi && active_mi->rli->info_thd == thd)
   {
-    Relay_log_info *rli= &active_mi->rli;
+    Relay_log_info *rli= active_mi->rli;
     DBUG_EXECUTE_IF("simulate_bug33029", return TRUE;);
     return rpl_master_has_bug(rli, 33029, FALSE, NULL, NULL);
   }
@@ -5339,8 +5194,7 @@ int start_slave(THD* thd , Master_info* 
     thread_mask&= thd->lex->slave_thd_opt;
   if (thread_mask) //some threads are stopped, start them
   {
-    if (init_master_info(mi,master_info_file,relay_log_info_file, 0,
-			 thread_mask))
+    if (init_info(mi, FALSE, thread_mask))
       slave_errno=ER_MASTER_INFO;
     else if (server_id_supplied && *mi->host)
     {
@@ -5351,38 +5205,38 @@ int start_slave(THD* thd , Master_info* 
       */
       if (thread_mask & SLAVE_SQL)
       {
-        mysql_mutex_lock(&mi->rli.data_lock);
+        mysql_mutex_lock(&mi->rli->data_lock);
 
         if (thd->lex->mi.pos)
         {
-          mi->rli.until_condition= Relay_log_info::UNTIL_MASTER_POS;
-          mi->rli.until_log_pos= thd->lex->mi.pos;
+          mi->rli->until_condition= Relay_log_info::UNTIL_MASTER_POS;
+          mi->rli->until_log_pos= thd->lex->mi.pos;
           /*
              We don't check thd->lex->mi.log_file_name for NULL here
              since it is checked in sql_yacc.yy
           */
-          strmake(mi->rli.until_log_name, thd->lex->mi.log_file_name,
-                  sizeof(mi->rli.until_log_name)-1);
+          strmake(mi->rli->until_log_name, thd->lex->mi.log_file_name,
+                  sizeof(mi->rli->until_log_name)-1);
         }
         else if (thd->lex->mi.relay_log_pos)
         {
-          mi->rli.until_condition= Relay_log_info::UNTIL_RELAY_POS;
-          mi->rli.until_log_pos= thd->lex->mi.relay_log_pos;
-          strmake(mi->rli.until_log_name, thd->lex->mi.relay_log_name,
-                  sizeof(mi->rli.until_log_name)-1);
+          mi->rli->until_condition= Relay_log_info::UNTIL_RELAY_POS;
+          mi->rli->until_log_pos= thd->lex->mi.relay_log_pos;
+          strmake(mi->rli->until_log_name, thd->lex->mi.relay_log_name,
+                  sizeof(mi->rli->until_log_name)-1);
         }
         else
-          mi->rli.clear_until_condition();
+          mi->rli->clear_until_condition();
 
-        if (mi->rli.until_condition != Relay_log_info::UNTIL_NONE)
+        if (mi->rli->until_condition != Relay_log_info::UNTIL_NONE)
         {
           /* Preparing members for effective until condition checking */
-          const char *p= fn_ext(mi->rli.until_log_name);
+          const char *p= fn_ext(mi->rli->until_log_name);
           char *p_end;
           if (*p)
           {
             //p points to '.'
-            mi->rli.until_log_name_extension= strtoul(++p,&p_end, 10);
+            mi->rli->until_log_name_extension= strtoul(++p,&p_end, 10);
             /*
               p_end points to the first invalid character. If it equals
               to p, no digits were found, error. If it contains '\0' it
@@ -5395,7 +5249,7 @@ int start_slave(THD* thd , Master_info* 
             slave_errno=ER_BAD_SLAVE_UNTIL_COND;
 
           /* mark the cached result of the UNTIL comparison as "undefined" */
-          mi->rli.until_log_names_cmp_result=
+          mi->rli->until_log_names_cmp_result=
             Relay_log_info::UNTIL_LOG_NAMES_CMP_UNKNOWN;
 
           /* Issuing warning then started without --skip-slave-start */
@@ -5405,7 +5259,7 @@ int start_slave(THD* thd , Master_info* 
                          ER(ER_MISSING_SKIP_SLAVE));
         }
 
-        mysql_mutex_unlock(&mi->rli.data_lock);
+        mysql_mutex_unlock(&mi->rli->data_lock);
       }
       else if (thd->lex->mi.pos || thd->lex->mi.relay_log_pos)
         push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_UNTIL_COND_IGNORED,
@@ -5415,7 +5269,6 @@ int start_slave(THD* thd , Master_info* 
         slave_errno = start_slave_threads(0 /*no mutex */,
 					1 /* wait for start */,
 					mi,
-					master_info_file,relay_log_info_file,
 					thread_mask);
     }
     else
@@ -5521,8 +5374,6 @@ int stop_slave(THD* thd, Master_info* mi
 */
 int reset_slave(THD *thd, Master_info* mi)
 {
-  MY_STAT stat_area;
-  char fname[FN_REFLEN];
   int thread_mask= 0, error= 0;
   uint sql_errno=ER_UNKNOWN_ERROR;
   const char* errmsg= "Unknown error occured while reseting slave";
@@ -5540,41 +5391,20 @@ int reset_slave(THD *thd, Master_info* m
   ha_reset_slave(thd);
 
   // delete relay logs, clear relay log coordinates
-  if ((error= purge_relay_logs(&mi->rli, thd,
-			       1 /* just reset */,
-			       &errmsg)))
+  if ((error= mi->rli->purge_relay_logs(thd,
+                                        1 /* just reset */,
+                                        &errmsg)))
   {
     sql_errno= ER_RELAY_LOG_FAIL;
     goto err;
   }
 
   /* Clear master's log coordinates */
-  init_master_log_pos(mi);
-  /*
-     Reset errors (the idea is that we forget about the
-     old master).
-  */
-  mi->clear_error();
-  mi->rli.clear_error();
-  mi->rli.clear_until_condition();
-  mi->rli.clear_sql_delay();
-
-  // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
-  end_master_info(mi);
-  // and delete these two files
-  fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
-  if (mysql_file_stat(key_file_master_info, fname, &stat_area, MYF(0)) &&
-      mysql_file_delete(key_file_master_info, fname, MYF(MY_WME)))
-  {
-    error=1;
-    goto err;
-  }
-  // delete relay_log_info_file
-  fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-  if (mysql_file_stat(key_file_relay_log_info, fname, &stat_area, MYF(0)) &&
-      mysql_file_delete(key_file_relay_log_info, fname, MYF(MY_WME)))
+  mi->init_master_log_pos();
+
+  if (reset_info(mi))
   {
-    error=1;
+    error= 1;
     goto err;
   }
 
@@ -5603,11 +5433,13 @@ bool change_master(THD* thd, Master_info
   int thread_mask;
   const char* errmsg= 0;
   bool need_relay_log_purge= 1;
+  char *var_master_log_name= NULL, *var_group_master_log_name= NULL;
   bool ret= FALSE;
   char saved_host[HOSTNAME_LENGTH + 1];
-  uint saved_port;
+  uint saved_port= 0;
   char saved_log_name[FN_REFLEN];
-  my_off_t saved_log_pos;
+  my_off_t saved_log_pos= 0;
+
   DBUG_ENTER("change_master");
 
   lock_slave_threads(mi);
@@ -5619,6 +5451,7 @@ bool change_master(THD* thd, Master_info
     ret= TRUE;
     goto err;
   }
+  thread_mask= SLAVE_IO | SLAVE_SQL;
 
   thd_proc_info(thd, "Changing master");
   /* 
@@ -5634,9 +5467,7 @@ bool change_master(THD* thd, Master_info
     unlock_slave_threads(mi);
     DBUG_RETURN(TRUE);
   }
-  // TODO: see if needs re-write
-  if (init_master_info(mi, master_info_file, relay_log_info_file, 0,
-		       thread_mask))
+  if (init_info(mi, FALSE, thread_mask))
   {
     my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
     ret= TRUE;
@@ -5654,8 +5485,8 @@ bool change_master(THD* thd, Master_info
   */
   strmake(saved_host, mi->host, HOSTNAME_LENGTH);
   saved_port= mi->port;
-  strmake(saved_log_name, mi->master_log_name, FN_REFLEN - 1);
-  saved_log_pos= mi->master_log_pos;
+  strmake(saved_log_name, mi->get_master_log_name(), FN_REFLEN - 1);
+  saved_log_pos= mi->get_master_log_pos();
 
   /*
     If the user specified host or port without binlog or position,
@@ -5671,18 +5502,18 @@ bool change_master(THD* thd, Master_info
 
   if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
   {
-    mi->master_log_name[0] = 0;
-    mi->master_log_pos= BIN_LOG_HEADER_SIZE;
+    var_master_log_name= const_cast<char*>(mi->get_master_log_name());
+    var_master_log_name[0]= '\0';
+    mi->set_master_log_pos(BIN_LOG_HEADER_SIZE);
   }
 
   if (lex_mi->log_file_name)
-    strmake(mi->master_log_name, lex_mi->log_file_name,
-	    sizeof(mi->master_log_name)-1);
+    mi->set_master_log_name(lex_mi->log_file_name);
   if (lex_mi->pos)
   {
-    mi->master_log_pos= lex_mi->pos;
+    mi->set_master_log_pos(lex_mi->pos);
   }
-  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
+  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
 
   if (lex_mi->host)
     strmake(mi->host, lex_mi->host, sizeof(mi->host)-1);
@@ -5694,7 +5525,7 @@ bool change_master(THD* thd, Master_info
     mi->port = lex_mi->port;
   if (lex_mi->connect_retry)
     mi->connect_retry = lex_mi->connect_retry;
-  if (lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
+  if (lex_mi->retry_count_opt !=  LEX_MASTER_INFO::LEX_MI_UNCHANGED)
     mi->retry_count = lex_mi->retry_count;
   if (lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
     mi->heartbeat_period = lex_mi->heartbeat_period;
@@ -5707,7 +5538,7 @@ bool change_master(THD* thd, Master_info
     is mentioning IGNORE_SERVER_IDS= (...)
   */
   if (lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE)
-    reset_dynamic(&mi->ignore_server_ids);
+    reset_dynamic(&mi->ignore_server_ids->server_ids);
   for (uint i= 0; i < lex_mi->repl_ignore_server_ids.elements; i++)
   {
     ulong s_id;
@@ -5721,20 +5552,20 @@ bool change_master(THD* thd, Master_info
     else
     {
       if (bsearch((const ulong *) &s_id,
-                  mi->ignore_server_ids.buffer,
-                  mi->ignore_server_ids.elements, sizeof(ulong),
+                  mi->ignore_server_ids->server_ids.buffer,
+                  mi->ignore_server_ids->server_ids.elements, sizeof(ulong),
                   (int (*) (const void*, const void*))
                   change_master_server_id_cmp) == NULL)
-        insert_dynamic(&mi->ignore_server_ids, (uchar*) &s_id);
+        insert_dynamic(&mi->ignore_server_ids->server_ids, (uchar*) &s_id);
     }
   }
-  sort_dynamic(&mi->ignore_server_ids, (qsort_cmp) change_master_server_id_cmp);
+  sort_dynamic(&mi->ignore_server_ids->server_ids, (qsort_cmp) change_master_server_id_cmp);
 
   if (lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
     mi->ssl= (lex_mi->ssl == LEX_MASTER_INFO::LEX_MI_ENABLE);
 
   if (lex_mi->sql_delay != -1)
-    mi->rli.set_sql_delay(lex_mi->sql_delay);
+    mi->rli->set_sql_delay(lex_mi->sql_delay);
 
   if (lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
     mi->ssl_verify_server_cert=
@@ -5762,17 +5593,17 @@ bool change_master(THD* thd, Master_info
   {
     need_relay_log_purge= 0;
     char relay_log_name[FN_REFLEN];
-    mi->rli.relay_log.make_log_name(relay_log_name, lex_mi->relay_log_name);
-    strmake(mi->rli.group_relay_log_name, relay_log_name,
-	    sizeof(mi->rli.group_relay_log_name)-1);
-    strmake(mi->rli.event_relay_log_name, relay_log_name,
-	    sizeof(mi->rli.event_relay_log_name)-1);
+
+    mi->rli->relay_log.make_log_name(relay_log_name, lex_mi->relay_log_name);
+    mi->rli->set_group_relay_log_name(relay_log_name);
+    mi->rli->set_event_relay_log_name(relay_log_name);
   }
 
   if (lex_mi->relay_log_pos)
   {
     need_relay_log_purge= 0;
-    mi->rli.group_relay_log_pos= mi->rli.event_relay_log_pos= lex_mi->relay_log_pos;
+    mi->rli->set_group_relay_log_pos(lex_mi->relay_log_pos);
+    mi->rli->set_event_relay_log_pos(lex_mi->relay_log_pos);
   }
 
   /*
@@ -5800,16 +5631,15 @@ bool change_master(THD* thd, Master_info
        of replication is not 100% clear, so we guard against problems using
        max().
       */
-     mi->master_log_pos = max(BIN_LOG_HEADER_SIZE,
-			      mi->rli.group_master_log_pos);
-     strmake(mi->master_log_name, mi->rli.group_master_log_name,
-             sizeof(mi->master_log_name)-1);
+     mi->set_master_log_pos(max(BIN_LOG_HEADER_SIZE,
+                           mi->rli->get_group_master_log_pos()));
+     mi->set_master_log_name(mi->rli->get_group_master_log_name());
   }
   /*
     Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never
     a slave before).
   */
-  if (flush_master_info(mi, FALSE, FALSE))
+  if (flush_master_info(mi, FALSE))
   {
     my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file");
     ret= TRUE;
@@ -5819,9 +5649,9 @@ bool change_master(THD* thd, Master_info
   {
     relay_log_purge= 1;
     thd_proc_info(thd, "Purging old relay logs");
-    if (purge_relay_logs(&mi->rli, thd,
-			 0 /* not only reset, but also reinit */,
-			 &errmsg))
+    if (mi->rli->purge_relay_logs(thd,
+                                  0 /* not only reset, but also reinit */,
+                                  &errmsg))
     {
       my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
       ret= TRUE;
@@ -5833,11 +5663,10 @@ bool change_master(THD* thd, Master_info
     const char* msg;
     relay_log_purge= 0;
     /* Relay log is already initialized */
-    if (init_relay_log_pos(&mi->rli,
-			   mi->rli.group_relay_log_name,
-			   mi->rli.group_relay_log_pos,
-			   0 /*no data lock*/,
-			   &msg, 0))
+    if (mi->rli->init_relay_log_pos(mi->rli->get_group_relay_log_name(),
+                                    mi->rli->get_group_relay_log_pos(),
+                                    0 /*no data lock*/,
+                                    &msg, 0))
     {
       my_error(ER_RELAY_LOG_INIT, MYF(0), msg);
       ret= TRUE;
@@ -5854,27 +5683,27 @@ bool change_master(THD* thd, Master_info
     ''/0: we have lost all copies of the original good coordinates.
     That's why we always save good coords in rli.
   */
-  mi->rli.group_master_log_pos= mi->master_log_pos;
-  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
-  strmake(mi->rli.group_master_log_name,mi->master_log_name,
-	  sizeof(mi->rli.group_master_log_name)-1);
-
-  if (!mi->rli.group_master_log_name[0]) // uninitialized case
-    mi->rli.group_master_log_pos=0;
+  mi->rli->set_group_master_log_pos(mi->get_master_log_pos());
+  DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
+  mi->rli->set_group_master_log_name(mi->get_master_log_name());
+
+  var_group_master_log_name=  const_cast<char *>(mi->rli->get_group_master_log_name());
+  if (!var_group_master_log_name[0]) // uninitialized case
+    mi->rli->set_group_master_log_pos(0);
 
-  mysql_mutex_lock(&mi->rli.data_lock);
-  mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */
+  mysql_mutex_lock(&mi->rli->data_lock);
+  mi->rli->abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */
   /* Clear the errors, for a clean start */
-  mi->rli.clear_error();
-  mi->rli.clear_until_condition();
+  mi->rli->clear_error();
+  mi->rli->clear_until_condition();
 
   sql_print_information("'CHANGE MASTER TO executed'. "
     "Previous state master_host='%s', master_port='%u', master_log_file='%s', "
     "master_log_pos='%ld'. "
     "New state master_host='%s', master_port='%u', master_log_file='%s', "
     "master_log_pos='%ld'.", saved_host, saved_port, saved_log_name,
-    (ulong) saved_log_pos, mi->host, mi->port, mi->master_log_name,
-    (ulong) mi->master_log_pos);
+    (ulong) saved_log_pos, mi->host, mi->port, mi->get_master_log_name(),
+    (ulong) mi->get_master_log_pos());
 
   /*
     If we don't write new coordinates to disk now, then old will remain in
@@ -5883,9 +5712,9 @@ bool change_master(THD* thd, Master_info
     in-memory value at restart (thus causing errors, as the old relay log does
     not exist anymore).
   */
-  flush_relay_log_info(&mi->rli);
+  ret= mi->rli->flush_info(TRUE);
   mysql_cond_broadcast(&mi->data_cond);
-  mysql_mutex_unlock(&mi->rli.data_lock);
+  mysql_mutex_unlock(&mi->rli->data_lock);
 
 err:
   unlock_slave_threads(mi);
@@ -5899,5 +5728,63 @@ err:
 /**
   @} (end of group Replication)
 */
-
 #endif /* HAVE_REPLICATION */
+
+Server_ids::Server_ids()
+{
+  my_init_dynamic_array(&server_ids, sizeof(::server_id), 16, 16);
+}
+
+Server_ids::~Server_ids()
+{
+  delete_dynamic(&server_ids);
+}
+
+bool Server_ids::unpack_server_ids(const char *param_server_ids)
+{
+  char *token, *last;
+  uint num_items;
+
+  DBUG_ENTER("Server_ids::unpack_server_ids");
+
+  token= strtok_r((char *)const_cast<const char*>(param_server_ids),
+                  " ", &last);
+
+  if (token == NULL)
+    DBUG_RETURN(TRUE);
+
+  num_items= atoi(token);
+  for (uint i=0; i < num_items; i++)
+  {
+    token= strtok_r(NULL, " ", &last);
+    if (token == NULL)
+      DBUG_RETURN(TRUE);
+    else
+    {
+      ulong val= atol(token);
+      insert_dynamic(&server_ids, (uchar *) &val);
+    }
+  }
+  DBUG_RETURN(FALSE);
+}
+
+bool Server_ids::pack_server_ids(char *buffer)
+{
+  DBUG_ENTER("Server_ids::pack_server_ids");
+
+  if (!buffer)
+    DBUG_RETURN(TRUE);
+
+  for (ulong i= 0, cur_len= sprintf(buffer,
+                                    "%u",
+                                    server_ids.elements);
+       i < server_ids.elements; i++)
+  {
+    ulong s_id;
+    get_dynamic(&server_ids, (uchar*) &s_id, i);
+    cur_len +=sprintf(buffer + cur_len,
+                      " %lu", s_id);
+  }
+
+  DBUG_RETURN(FALSE);
+}

=== modified file 'sql/rpl_slave.h'
--- a/sql/rpl_slave.h	2010-07-27 14:04:13 +0000
+++ b/sql/rpl_slave.h	2010-08-06 18:09:14 +0000
@@ -145,11 +145,6 @@ extern ulonglong relay_log_space_limit;
 #define MYSQL_SLAVE_RUN_NOT_CONNECT 1
 #define MYSQL_SLAVE_RUN_CONNECT     2
 
-#define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
- "FIRST")
-#define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\
- "FIRST")
-
 /*
   If the following is set, if first gives an error, second will be
   tried. Otherwise, if first fails, we fail.
@@ -164,13 +159,16 @@ int cmp_master_pos(const char* log_file_
 int reset_slave(THD *thd, Master_info* mi);
 int init_slave();
 int init_recovery(Master_info* mi, const char** errmsg);
+int init_info(Master_info* mi, bool ignore_if_no_info, int thread_mask);
+void end_info(Master_info* mi);
+int reset_info(Master_info* mi);
+int flush_master_info(Master_info* mi, bool force);
 void init_slave_skip_errors(const char* arg);
 int register_slave_on_master(MYSQL* mysql);
 int terminate_slave_threads(Master_info* mi, int thread_mask,
 			     bool skip_lock = 0);
 int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
-			Master_info* mi, const char* master_info_fname,
-			const char* slave_info_fname, int thread_mask);
+			Master_info* mi, int thread_mask);
 /*
   cond_lock is usually same as start_lock. It is needed for the case when
   start_lock is 0 which happens if start_slave_thread() is called already
@@ -212,20 +210,14 @@ void init_thread_mask(int* mask,Master_i
 void set_slave_thread_options(THD* thd);
 void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli);
 int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli);
-
-int init_longvar_from_file(long* var, IO_CACHE* f, long default_val);
-int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
-int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
-int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-                          const char *default_val);
-int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f);
+void rotate_relay_log(Master_info* mi);
 
 pthread_handler_t handle_slave_io(void *arg);
 pthread_handler_t handle_slave_sql(void *arg);
 bool net_request_file(NET* net, const char* fname);
 
 extern bool volatile abort_loop;
-extern Master_info main_mi, *active_mi; /* active_mi for multi-master */
+extern Master_info *active_mi;      /* active_mi  for multi-master */
 extern LIST master_list;
 extern my_bool replicate_same_server_id;
 
@@ -252,5 +244,4 @@ extern I_List<THD> threads;
 /**
   @} (end of group Replication)
 */
-
 #endif

=== added file 'sql/server_ids.h'
--- a/sql/server_ids.h	1970-01-01 00:00:00 +0000
+++ b/sql/server_ids.h	2010-05-24 10:48:30 +0000
@@ -0,0 +1,19 @@
+#ifndef SERVER_ID_H
+
+#define SERVER_ID_H
+
+#include "my_sys.h"
+
+class Server_ids
+{
+  public:
+    DYNAMIC_ARRAY server_ids;
+
+    Server_ids();
+    ~Server_ids();
+
+    bool pack_server_ids(char *buffer);
+    bool unpack_server_ids(const char *param_server_ids);
+};
+
+#endif

=== modified file 'sql/sql_binlog.cc'
--- a/sql/sql_binlog.cc	2010-09-21 11:32:50 +0000
+++ b/sql/sql_binlog.cc	2010-10-04 10:16:31 +0000
@@ -17,7 +17,8 @@
 #include "sql_binlog.h"
 #include "sql_parse.h"
 #include "sql_acl.h"
-#include "rpl_rli.h"
+#include "rpl_info.h"
+#include "rpl_info_factory.h"
 #include "base64.h"
 #include "rpl_slave.h"                              // apply_event_and_update_pos
 #include "log_event.h"                          // Format_description_log_event,
@@ -146,12 +147,17 @@ void mysql_client_binlog_statement(THD* 
   /*
     Allocation
   */
-
   int err= 0;
-  Relay_log_info *rli;
-  rli= thd->rli_fake;
-  if (!rli && (rli= thd->rli_fake= new Relay_log_info(FALSE)))
-    rli->sql_thd= thd;
+  Relay_log_info *rli= thd->rli_fake;
+  if (!rli)
+  {
+    Rpl_info_factory::create_rli(RLI_REPOSITORY_FILE, FALSE, &rli);
+    if (rli)
+    {
+      thd->rli_fake= rli;
+      rli->info_thd= thd;
+    }
+  }
 
   const char *error= 0;
   char *buf= (char *) my_malloc(decoded_len, MYF(MY_WME));

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-10-03 23:42:39 +0000
+++ b/sql/sql_insert.cc	2010-10-08 14:35:24 +0000
@@ -804,7 +804,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   if (thd->slave_thread &&
       (info.handle_duplicates == DUP_UPDATE) &&
       (table->next_number_field != NULL) &&
-      rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL))
+      rpl_master_has_bug(active_mi->rli, 24432, TRUE, NULL, NULL))
     goto abort;
 #endif
 
@@ -3306,7 +3306,7 @@ select_insert::prepare(List<Item> &value
   if (thd->slave_thread &&
       (info.handle_duplicates == DUP_UPDATE) &&
       (table->next_number_field != NULL) &&
-      rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL))
+      rpl_master_has_bug(active_mi->rli, 24432, TRUE, NULL, NULL))
     DBUG_RETURN(1);
 #endif
 

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2010-08-16 06:58:42 +0000
+++ b/sql/sql_load.cc	2010-08-23 16:13:25 +0000
@@ -385,11 +385,11 @@ int mysql_load(THD *thd,sql_exchange *ex
       if (thd->slave_thread)
       {
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-        if (strncmp(active_mi->rli.slave_patternload_file, name, 
-            active_mi->rli.slave_patternload_file_size))
+        if (strncmp(active_mi->rli->slave_patternload_file, name,
+            active_mi->rli->slave_patternload_file_size))
         {
           /*
-            LOAD DATA INFILE in the slave SQL Thread can only read from 
+            LOAD DATA INFILE in the slave SQL Thread can only read from
             --slave-load-tmpdir". This should never happen. Please, report a bug.
            */
 

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2010-10-11 16:43:09 +0000
+++ b/sql/sys_vars.cc	2010-10-25 13:46:20 +0000
@@ -36,6 +36,7 @@
 #include <thr_alarm.h>
 #include "rpl_slave.h"
 #include "rpl_mi.h"
+#include "rpl_info_factory.h"
 #include "transaction.h"
 #include "mysqld.h"
 #include "lock.h"
@@ -408,6 +409,25 @@ 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 const char *repository_names[]=
+{
+  "FILE", 0
+};
+
+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));
+
+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));
+
 static Sys_var_mybool Sys_binlog_rows_query(
        "binlog_rows_query_log_events",
        "Allow writing of Rows_query_log events into binary log.",
@@ -1104,7 +1124,7 @@ static bool fix_max_binlog_size(sys_var 
   mysql_bin_log.set_max_size(max_binlog_size);
 #ifdef HAVE_REPLICATION
   if (!max_relay_log_size)
-    active_mi->rli.relay_log.set_max_size(max_binlog_size);
+    active_mi->rli->relay_log.set_max_size(max_binlog_size);
 #endif
   return false;
 }
@@ -1238,7 +1258,7 @@ static Sys_var_ulong Sys_max_prepared_st
 static bool fix_max_relay_log_size(sys_var *self, THD *thd, enum_var_type type)
 {
 #ifdef HAVE_REPLICATION
-  active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
+  active_mi->rli->relay_log.set_max_size(max_relay_log_size ?
                                         max_relay_log_size: max_binlog_size);
 #endif
   return false;
@@ -3009,32 +3029,32 @@ static bool check_slave_skip_counter(sys
 {
   bool result= false;
   mysql_mutex_lock(&LOCK_active_mi);
-  mysql_mutex_lock(&active_mi->rli.run_lock);
-  if (active_mi->rli.slave_running)
+  mysql_mutex_lock(&active_mi->rli->run_lock);
+  if (active_mi->rli->slave_running)
   {
     my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
     result= true;
   }
-  mysql_mutex_unlock(&active_mi->rli.run_lock);
+  mysql_mutex_unlock(&active_mi->rli->run_lock);
   mysql_mutex_unlock(&LOCK_active_mi);
   return result;
 }
 static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type)
 {
   mysql_mutex_lock(&LOCK_active_mi);
-  mysql_mutex_lock(&active_mi->rli.run_lock);
+  mysql_mutex_lock(&active_mi->rli->run_lock);
   /*
     The following test should normally never be true as we test this
     in the check function;  To be safe against multiple
     SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
   */
-  if (!active_mi->rli.slave_running)
+  if (!active_mi->rli->slave_running)
   {
-    mysql_mutex_lock(&active_mi->rli.data_lock);
-    active_mi->rli.slave_skip_counter= sql_slave_skip_counter;
-    mysql_mutex_unlock(&active_mi->rli.data_lock);
+    mysql_mutex_lock(&active_mi->rli->data_lock);
+    active_mi->rli->slave_skip_counter= sql_slave_skip_counter;
+    mysql_mutex_unlock(&active_mi->rli->data_lock);
   }
-  mysql_mutex_unlock(&active_mi->rli.run_lock);
+  mysql_mutex_unlock(&active_mi->rli->run_lock);
   mysql_mutex_unlock(&LOCK_active_mi);
   return 0;
 }

Attachment: [text/bzr-bundle] bzr/marc.alff@oracle.com-20101025134620-e2qs25lvjmhakt3t.bundle
Thread
bzr push into mysql-next-mr-wl4816 branch (marc.alff:3204 to 3205) Marc Alff25 Oct