List:Internals« Previous MessageNext Message »
From:Lars Thalmann Date:April 25 2005 10:31pm
Subject:bk commit into 5.1 tree (lars:1.1800)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of lars. When lars does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1800 05/04/26 00:31:13 lars@stripped +22 -0
  After-merge fixes

  sql/share/errmsg.txt
    1.18 05/04/26 00:31:04 lars@stripped +0 -12
    After-merge fixes

  sql/set_var.cc
    1.107 05/04/26 00:31:04 lars@stripped +0 -20
    After-merge fixes

  sql/rpl/slave.h
    1.88 05/04/26 00:31:04 lars@stripped +0 -2
    After-merge fixes

  sql/rpl/slave.cc
    1.246 05/04/26 00:31:04 lars@stripped +0 -7
    After-merge fixes

  sql/sql_yacc.yy
    1.356 05/04/25 23:34:26 lars@stripped +0 -0
    Auto merged

  sql/sql_show.cc
    1.228 05/04/25 23:34:26 lars@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.444 05/04/25 23:34:25 lars@stripped +0 -0
    Auto merged

  sql/sql_load.cc
    1.79 05/04/25 23:34:25 lars@stripped +0 -0
    Auto merged

  sql/sql_lex.h
    1.163 05/04/25 23:34:24 lars@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.233 05/04/25 23:34:24 lars@stripped +0 -0
    Auto merged

  sql/sql_class.cc
    1.165 05/04/25 23:34:23 lars@stripped +0 -0
    Auto merged

  sql/sql_acl.h
    1.37 05/04/25 23:34:23 lars@stripped +0 -0
    Auto merged

  sql/set_var.h
    1.64 05/04/25 23:34:23 lars@stripped +0 -0
    Auto merged

  sql/mysqld.cc
    1.446 05/04/25 23:34:23 lars@stripped +0 -0
    Auto merged

  sql/log_event.h
    1.110 05/04/25 23:34:22 lars@stripped +0 -0
    Auto merged

  sql/log_event.cc
    1.176 05/04/25 23:34:22 lars@stripped +0 -0
    Auto merged

  sql/log.cc
    1.162 05/04/25 23:34:21 lars@stripped +0 -0
    Auto merged

  sql/item_func.h
    1.107 05/04/25 23:34:21 lars@stripped +0 -0
    Auto merged

  sql/item_func.cc
    1.182 05/04/25 23:34:21 lars@stripped +0 -0
    Auto merged

  sql/ha_innodb.cc
    1.196 05/04/25 23:34:21 lars@stripped +0 -0
    Auto merged

  sql/Makefile.am
    1.104 05/04/25 23:34:20 lars@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.sh
    1.259 05/04/25 23:34:20 lars@stripped +0 -0
    Auto merged

  sql/rpl/slave.h
    1.82.1.7 05/04/25 23:33:59 lars@stripped +0 -0
    Merge rename: sql/slave.h -> sql/rpl/slave.h

  sql/rpl/slave.cc
    1.242.1.2 05/04/25 23:33:59 lars@stripped +0 -0
    Merge rename: sql/slave.cc -> sql/rpl/slave.cc

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	lars
# Host:	goldfish.(none)
# Root:	/home/bk/w1697-5.1/RESYNC

--- 1.258/mysql-test/mysql-test-run.sh	Mon Apr 25 23:21:23 2005
+++ 1.259/mysql-test/mysql-test-run.sh	Mon Apr 25 23:34:20 2005
@@ -222,6 +222,7 @@
 EXTRA_MASTER_OPT=""
 EXTRA_MYSQL_TEST_OPT=""
 EXTRA_MYSQLDUMP_OPT=""
+EXTRA_MYSQLSHOW_OPT=""
 EXTRA_MYSQLBINLOG_OPT=""
 USE_RUNNING_SERVER=0
 USE_NDBCLUSTER=@USE_NDBCLUSTER@
@@ -238,7 +239,7 @@
 SLEEP_TIME_FOR_FIRST_MASTER=400		# Enough time to create innodb tables
 SLEEP_TIME_FOR_SECOND_MASTER=400
 SLEEP_TIME_FOR_FIRST_SLAVE=400
-SLEEP_TIME_FOR_SECOND_SLAVE=30
+SLEEP_TIME_FOR_SECOND_SLAVE=300
 CHARACTER_SET=latin1
 DBUSER=""
 START_WAIT_TIMEOUT=10
@@ -246,7 +247,6 @@
 MYSQL_TEST_SSL_OPTS=""
 USE_TIMER=""
 USE_EMBEDDED_SERVER=""
-RESULT_EXT=""
 TEST_MODE=""
 
 NDB_MGM_EXTRA_OPTS=
@@ -259,7 +259,6 @@
       USE_EMBEDDED_SERVER=1
       USE_MANAGER=0 NO_SLAVE=1
       USE_RUNNING_SERVER=0
-      RESULT_EXT=".es"
       TEST_MODE="$TEST_MODE embedded" ;;
     --purify)
       USE_PURIFY=1
@@ -417,7 +416,7 @@
       fi
       # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr
       valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck"
-      VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16"
+      VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp"
       EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb"
       EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb"
       SLEEP_TIME_AFTER_RESTART=10
@@ -453,6 +452,8 @@
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqltest.trace"
       EXTRA_MYSQLDUMP_OPT="$EXTRA_MYSQLDUMP_OPT \
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqldump.trace"
+      EXTRA_MYSQLSHOW_OPT="$EXTRA_MYSQLSHOW_OPT \
+       --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlshow.trace"
       EXTRA_MYSQLBINLOG_OPT="$EXTRA_MYSQLBINLOG_OPT \
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlbinlog.trace"
       EXTRA_MYSQL_CLIENT_TEST_OPT="--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysql_client_test.trace"
@@ -556,6 +557,11 @@
  else
    MYSQL_DUMP="$BASEDIR/client/mysqldump"
  fi
+ if [ -f "$BASEDIR/client/.libs/mysqlshow" ] ; then
+   MYSQL_SHOW="$BASEDIR/client/.libs/mysqlshow"
+ else
+   MYSQL_SHOW="$BASEDIR/client/mysqlshow"
+ fi
  if [ -f "$BASEDIR/client/.libs/mysqlbinlog" ] ; then
    MYSQL_BINLOG="$BASEDIR/client/.libs/mysqlbinlog"
  else
@@ -568,9 +574,9 @@
  CLIENT_BINDIR="$BASEDIR/client"
  MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
  WAIT_PID="$BASEDIR/extra/mysql_waitpid"
- MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqlmanagerc"
- MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
- MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqlmanager-pwgen"
+ MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc"
+ MYSQL_MANAGER="$BASEDIR/tools/mysqltestmanager"
+ MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen"
  MYSQL="$CLIENT_BINDIR/mysql"
  LANGUAGE="$BASEDIR/sql/share/english/"
  CHARSETSDIR="$BASEDIR/sql/share/charsets"
@@ -627,12 +633,13 @@
  fi
  MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
  MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
+ MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow"
  MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
  MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
  WAIT_PID="$CLIENT_BINDIR/mysql_waitpid"
- MYSQL_MANAGER="$CLIENT_BINDIR/mysqlmanager"
- MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqlmanagerc"
- MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqlmanager-pwgen"
+ MYSQL_MANAGER="$CLIENT_BINDIR/mysqltestmanager"
+ MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc"
+ MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen"
  MYSQL="$CLIENT_BINDIR/mysql"
  INSTALL_DB="./install_test_db --bin"
  MYSQL_FIX_SYSTEM_TABLES="$CLIENT_BINDIR/mysql_fix_privilege_tables"
@@ -697,10 +704,11 @@
 
 MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT"
 MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
+MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT"
 MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR  --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
 MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
 MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
-export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
+export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
 export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR
 export NDB_TOOLS_DIR
 export NDB_MGM
@@ -731,7 +739,7 @@
   XTERM=`which xterm`
 fi
 
-export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR MASTER_MYSOCK
+export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR MASTER_MYSOCK
 
 #++
 # Function Definitions
@@ -751,13 +759,6 @@
   result_file=r/$1.result
   eval_file=r/$1.eval
 
-  # If we have an special externsion for result files we use it if we are recording
-  # or a result file with that extension exists.
-  if [ -n "$RESULT_EXT" -a \( x$RECORD = x1 -o -f "$result_file$RESULT_EXT" \) ]
-  then
-    result_file="$result_file$RESULT_EXT"
-  fi
-
   if [ -f $eval_file ]
   then
     result_file=$eval_file
@@ -1180,7 +1181,7 @@
           --default-character-set=$CHARACTER_SET \
           --tmpdir=$MYSQL_TMP_DIR \
           --language=$LANGUAGE \
-          --innodb_data_file_path=ibdata1:50M \
+          --innodb_data_file_path=ibdata1:128M:autoextend \
 	  --open-files-limit=1024 \
 	   $MASTER_40_ARGS \
            $SMALL_SERVER \
@@ -1201,7 +1202,7 @@
           $USE_NDBCLUSTER \
           --tmpdir=$MYSQL_TMP_DIR \
           --language=$LANGUAGE \
-          --innodb_data_file_path=ibdata1:50M \
+          --innodb_data_file_path=ibdata1:128M:autoextend \
 	   $MASTER_40_ARGS \
            $SMALL_SERVER \
            $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
@@ -1502,9 +1503,6 @@
  result_file="r/$tname.result"
  echo $tname > $CURRENT_TEST
  SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0 \& \( $tname : federated \) = 0`
- if [ -n "$RESULT_EXT" -a \( x$RECORD = x1 -o -f "$result_file$RESULT_EXT" \) ] ; then
-   result_file="$result_file$RESULT_EXT"
- fi
  if [ "$USE_MANAGER" = 1 ] ; then
   many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)`
  fi
@@ -1562,33 +1560,8 @@
  # script soon anyway so it is not worth it spending the time
  if [ "x$USE_EMBEDDED_SERVER" = "x1" -a -z "$DO_TEST" ] ; then
    for t in \
-        "alter_table" \
-	"bdb-deadlock" \
-	"connect" \
-        "ctype_latin1_de" \
-        "ctype_ucs" \
-	"flush_block_commit" \
-	"grant2" \
-	"grant_cache" \
-	"grant" \
-	"init_connect" \
-	"init_file" \
-        "innodb" \
-	"innodb-deadlock" \
-	"innodb-lock" \
-	"mix_innodb_myisam_binlog" \
-	"mysqlbinlog2" \
-	"mysqlbinlog" \
-	"mysqldump" \
-	"mysql_protocols" \
-        "packet" \
-	"ps_1general" \
-	"rename" \
-	"show_check" \
-        "system_mysql_db_fix" \
-        "timezone2" \
-	"user_var" \
-	"variables"
+       "init_connect" \
+       "init_file"
    do
      if [ "$tname" = "$t" ] ; then
        skip_test $tname
@@ -1612,10 +1585,8 @@
        --result-file=*)
          result_file=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--result-file=;;"`
          result_file="r/$result_file.result"
-         if [ -n "$RESULT_EXT" -a \( x$RECORD = x1 -o -f "$result_file$RESULT_EXT" \) ] ; then
-	   result_file="$result_file$RESULT_EXT"
-	 fi
-	 # Note that this must be set to space, not "" for test-reset to work
+         # Note that this must be set to space, not "" for test-reset to
+# work
 	 EXTRA_MASTER_OPT=" "
          ;;
      esac

--- 1.103/sql/Makefile.am	Mon Apr 25 23:21:23 2005
+++ 1.104/sql/Makefile.am	Mon Apr 25 23:34:20 2005
@@ -49,7 +49,7 @@
 			mysql_priv.h item_geofunc.h sql_bitmap.h \
 			procedure.h sql_class.h sql_lex.h sql_list.h \
 			sql_manager.h sql_map.h sql_string.h unireg.h \
-			field.h handler.h mysqld_suffix.h \
+			sql_error.h field.h handler.h mysqld_suffix.h \
 			ha_myisammrg.h\
 			ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
 			ha_ndbcluster.h opt_range.h protocol.h \
@@ -64,9 +64,8 @@
 			sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
 			parse_file.h sql_view.h	sql_trigger.h \
 			examples/ha_example.h examples/ha_archive.h \
-			examples/ha_tina.h \
+			examples/ha_tina.h ha_blackhole.h  \
 			ha_federated.h
-
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
 			item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -103,7 +102,7 @@
 			sp_head.cc sp_pcontext.cc  sp_rcontext.cc sp.cc \
 			sp_cache.cc parse_file.cc sql_trigger.cc \
 			examples/ha_example.cc examples/ha_archive.cc \
-			examples/ha_tina.cc \
+			examples/ha_tina.cc ha_blackhole.cc \
 			ha_federated.cc
 
 gen_lex_hash_SOURCES =	gen_lex_hash.cc

--- 1.181/sql/item_func.cc	Wed Apr 20 19:08:27 2005
+++ 1.182/sql/item_func.cc	Mon Apr 25 23:34:21 2005
@@ -22,7 +22,8 @@
 #endif
 
 #include "mysql_priv.h"
-#include "slave.h"				// for wait_for_master_pos
+#include <rpl/slave.h>				// for wait_for_master_pos
+#include <rpl/mic.h>				// for wait_for_master_pos
 #include <m_ctype.h>
 #include <hash.h>
 #include <time.h>
@@ -2891,6 +2892,8 @@
 
 longlong Item_master_pos_wait::val_int()
 {
+  DBUG_ENTER("Item_master_pos_wait::val_int");
+  DBUG_PRINT("enter", ("channel: %s", channel));
   DBUG_ASSERT(fixed == 1);
   THD* thd = current_thd;
   String *log_name = args[0]->val_str(&value);
@@ -2899,19 +2902,28 @@
   null_value=0;
   if (thd->slave_thread || !log_name || !log_name->length())
   {
+    DBUG_PRINT("info", ("Not a slave or illegal log_name"));
     null_value = 1;
-    return 0;
+    DBUG_RETURN(0);
   }
   longlong pos = (ulong)args[1]->val_int();
   longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
 #ifdef HAVE_REPLICATION
-  if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
+  Master_info *mi;
+  pthread_mutex_lock(&LOCK_active_mi);
+  if (!(mi= mic.get_master_info(channel))) {
+    DBUG_PRINT("info", ("Did not find mi"));
+    DBUG_RETURN(0); 
+  }
+  pthread_mutex_unlock(&LOCK_active_mi);
+  if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
   {
+    DBUG_PRINT("info", ("rli.wait_for_pos failed"));
     null_value = 1;
     event_count=0;
   }
 #endif
-  return event_count;
+  DBUG_RETURN(event_count);
 }
 
 #ifdef EXTRA_DEBUG

--- 1.106/sql/item_func.h	Wed Apr 20 19:08:27 2005
+++ 1.107/sql/item_func.h	Mon Apr 25 23:34:21 2005
@@ -1050,9 +1050,18 @@
 class Item_master_pos_wait :public Item_int_func
 {
   String value;
+  const char* channel;
  public:
-  Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
-  Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
+  Item_master_pos_wait(const char *a, Item *b,Item *c) 
+    :Item_int_func(b,c) {
+    // LARS: Do I need to copy here?
+    channel= a;
+  }
+  Item_master_pos_wait(const char *a, Item *b,Item *c,Item *d)
+    :Item_int_func(b,c,d) {
+    // LARS: Do I need to copy here?
+    channel= a;
+  }
   longlong val_int();
   const char *func_name() const { return "master_pos_wait"; }
   void fix_length_and_dec() { max_length=21; maybe_null=1;}

--- 1.161/sql/log.cc	Mon Apr 25 22:18:29 2005
+++ 1.162/sql/log.cc	Mon Apr 25 23:34:21 2005
@@ -23,8 +23,8 @@
 #endif
 
 #include "mysql_priv.h"
-#include "sql_repl.h"
-#include "rpl_filter.h"
+#include <rpl/master.h>
+#include <rpl/filter.h>
 
 #include <my_dir.h>
 #include <stdarg.h>
@@ -1007,7 +1007,7 @@
 
 #ifdef HAVE_REPLICATION
 
-int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included) 
+int MYSQL_LOG::purge_first_log(Relay_log_info* rli, bool included) 
 {
   int error;
   DBUG_ENTER("purge_first_log");
@@ -1072,7 +1072,7 @@
   }
 
   /* Store where we are in the new file for the execution thread */
-  flush_relay_log_info(rli);
+  rli->storage_flush();
 
 err:
   pthread_mutex_unlock(&LOCK_index);

--- 1.175/sql/log_event.cc	Fri Apr  1 22:17:23 2005
+++ 1.176/sql/log_event.cc	Mon Apr 25 23:34:22 2005
@@ -20,8 +20,8 @@
 #pragma implementation				// gcc: Class implementation
 #endif
 #include  "mysql_priv.h"
-#include "slave.h"
-#include "rpl_filter.h"
+#include <rpl/slave.h>
+#include <rpl/filter.h>
 #include <my_dir.h>
 #endif /* MYSQL_CLIENT */
 
@@ -59,7 +59,7 @@
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
 
-static void clear_all_errors(THD *thd, struct st_relay_log_info *rli)
+static void clear_all_errors(THD *thd, Relay_log_info *rli)
 {
   thd->query_error = 0;
   thd->clear_error();
@@ -390,7 +390,7 @@
   Log_event::exec_event()
 */
 
-int Log_event::exec_event(struct st_relay_log_info* rli)
+int Log_event::exec_event(Relay_log_info* rli)
 {
   DBUG_ENTER("Log_event::exec_event");
 
@@ -438,7 +438,7 @@
     else
     {
       rli->inc_group_relay_log_pos(log_pos);
-      flush_relay_log_info(rli);
+      rli->storage_flush();
       /* 
          Note that Rotate_log_event::exec_event() does not call this
          function, so there is no chance that a fake rotate event resets
@@ -1490,13 +1490,14 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Query_log_event::exec_event(struct st_relay_log_info* rli)
+int Query_log_event::exec_event(Relay_log_info* rli)
 {
   return exec_event(rli, query, q_len);
 }
 
 
-int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query_arg, uint32 q_len_arg)
+int Query_log_event::exec_event(Relay_log_info* rli, const char *query_arg, 
+				uint32 q_len_arg)
 {
   int expected_error,actual_error= 0;
   /*
@@ -1854,7 +1855,7 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Start_log_event_v3::exec_event(struct st_relay_log_info* rli)
+int Start_log_event_v3::exec_event(Relay_log_info* rli)
 {
   DBUG_ENTER("Start_log_event_v3::exec_event");
   switch (binlog_version)
@@ -2077,7 +2078,7 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
+int Format_description_log_event::exec_event(Relay_log_info* rli)
 {
   DBUG_ENTER("Format_description_log_event::exec_event");
 
@@ -2127,7 +2128,7 @@
     else
     {
       rli->inc_group_relay_log_pos(0);
-      flush_relay_log_info(rli);
+      rli->storage_flush();
     }
     DBUG_RETURN(0);
   }
@@ -2641,7 +2642,7 @@
     1    	Failure
 */
 
-int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, 
+int Load_log_event::exec_event(NET* net, Relay_log_info* rli, 
 			       bool use_rli_only_for_errors)
 {
   thd->db_length= db_len;
@@ -2968,7 +2969,7 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
+int Rotate_log_event::exec_event(Relay_log_info* rli)
 {
   DBUG_ENTER("Rotate_log_event::exec_event");
 
@@ -3013,7 +3014,7 @@
   }
   pthread_mutex_unlock(&rli->data_lock);
   pthread_cond_broadcast(&rli->data_cond);
-  flush_relay_log_info(rli);
+  rli->storage_flush();
   DBUG_RETURN(0);
 }
 #endif
@@ -3121,7 +3122,7 @@
 */
 
 #if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
-int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
+int Intvar_log_event::exec_event(Relay_log_info* rli)
 {
   switch (type) {
   case LAST_INSERT_ID_EVENT:
@@ -3194,7 +3195,7 @@
 
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Rand_log_event::exec_event(struct st_relay_log_info* rli)
+int Rand_log_event::exec_event(Relay_log_info* rli)
 {
   thd->rand.seed1= (ulong) seed1;
   thd->rand.seed2= (ulong) seed2;
@@ -3265,7 +3266,7 @@
 
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Xid_log_event::exec_event(struct st_relay_log_info* rli)
+int Xid_log_event::exec_event(Relay_log_info* rli)
 {
   /* For a slave Xid_log_event is COMMIT */
   mysql_log.write(thd,COM_QUERY,"COMMIT /* implicit, from Xid_log_event */");
@@ -3547,7 +3548,7 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int User_var_log_event::exec_event(struct st_relay_log_info* rli)
+int User_var_log_event::exec_event(Relay_log_info* rli)
 {
   Item *it= 0;
   CHARSET_INFO *charset;
@@ -3649,15 +3650,14 @@
 
 
 #ifndef MYSQL_CLIENT
-Slave_log_event::Slave_log_event(THD* thd_arg,
-				 struct st_relay_log_info* rli)
+Slave_log_event::Slave_log_event(THD* thd_arg, Relay_log_info* rli)
   :Log_event(thd_arg, 0, 0) , mem_pool(0), master_host(0)
 {
   DBUG_ENTER("Slave_log_event");
-  if (!rli->inited)				// QQ When can this happen ?
+  if (!rli->is_inited())                          // QQ When can this happen ?
     DBUG_VOID_RETURN;
 
-  MASTER_INFO* mi = rli->mi;
+  Master_info* mi = rli->mi;
   // TODO: re-write this better without holding both locks at the same time
   pthread_mutex_lock(&mi->data_lock);
   pthread_mutex_lock(&rli->data_lock);
@@ -3759,7 +3759,7 @@
 
 
 #ifndef MYSQL_CLIENT
-int Slave_log_event::exec_event(struct st_relay_log_info* rli)
+int Slave_log_event::exec_event(Relay_log_info* rli)
 {
   if (mysql_bin_log.is_open())
     mysql_bin_log.write(this);
@@ -3804,7 +3804,7 @@
 */
 
 #ifndef MYSQL_CLIENT
-int Stop_log_event::exec_event(struct st_relay_log_info* rli)
+int Stop_log_event::exec_event(Relay_log_info* rli)
 {
   /*
     We do not want to update master_log pos because we get a rotate event
@@ -3818,7 +3818,7 @@
   else
   {
     rli->inc_group_relay_log_pos(0);
-    flush_relay_log_info(rli);
+    rli->storage_flush();
   }
   return 0;
 }
@@ -4014,7 +4014,7 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
+int Create_file_log_event::exec_event(Relay_log_info* rli)
 {
   char proc_info[17+FN_REFLEN+10], *fname_buf= proc_info+17;
   char *p;
@@ -4185,7 +4185,7 @@
   Append_block_log_event::exec_event()
 */
 
-int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
+int Append_block_log_event::exec_event(Relay_log_info* rli)
 {
   char proc_info[17+FN_REFLEN+10], *fname= proc_info+17;
   char *p= slave_load_file_stem(fname, file_id, server_id);
@@ -4317,7 +4317,7 @@
 */
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
+int Delete_file_log_event::exec_event(Relay_log_info* rli)
 {
   char fname[FN_REFLEN+10];
   char *p= slave_load_file_stem(fname, file_id, server_id);
@@ -4413,7 +4413,7 @@
   Execute_load_log_event::exec_event()
 */
 
-int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
+int Execute_load_log_event::exec_event(Relay_log_info* rli)
 {
   char fname[FN_REFLEN+10];
   char *p= slave_load_file_stem(fname, file_id, server_id);
@@ -4659,7 +4659,7 @@
 
 
 int
-Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli)
+Execute_load_query_log_event::exec_event(Relay_log_info* rli)
 {
   char *p;
   char *buf;

--- 1.109/sql/log_event.h	Wed Mar 30 22:41:38 2005
+++ 1.110/sql/log_event.h	Mon Apr 25 23:34:22 2005
@@ -444,8 +444,6 @@
 
 class Format_description_log_event;
 
-struct st_relay_log_info;
-
 #ifdef MYSQL_CLIENT
 /*
   A structure for mysqlbinlog to remember the last db, flags2, sql_mode etc; it
@@ -574,7 +572,7 @@
     The SQL slave thread calls exec_event() to execute the event; this is where
     the slave's data is modified.
   */
-  virtual int exec_event(struct st_relay_log_info* rli);
+  virtual int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
   virtual const char* get_db()
   {
@@ -743,8 +741,8 @@
   const char* get_db() { return db; }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
-  int exec_event(struct st_relay_log_info* rli, const char *query_arg,
+  int exec_event(Relay_log_info* rli);
+  int exec_event(Relay_log_info* rli, const char *query_arg,
                  uint32 q_len_arg);
 #endif /* HAVE_REPLICATION */
 #else
@@ -799,9 +797,9 @@
   uint16 master_port;
 
 #ifndef MYSQL_CLIENT
-  Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
+  Slave_log_event(THD* thd_arg, Relay_log_info* rli);
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
 #endif
@@ -882,11 +880,11 @@
   const char* get_db() { return db; }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli)
+  int exec_event(Relay_log_info* rli)
   {
     return exec_event(thd->slave_net,rli,0);
   }
-  int exec_event(NET* net, struct st_relay_log_info* rli,
+  int exec_event(NET* net, Relay_log_info* rli,
 		 bool use_rli_only_for_errors);
 #endif /* HAVE_REPLICATION */
 #else
@@ -976,7 +974,7 @@
   Start_log_event_v3();
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   Start_log_event_v3() {}
@@ -1023,7 +1021,7 @@
 
 #ifndef MYSQL_CLIENT
 #ifdef HAVE_REPLICATION
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #endif
 
@@ -1072,7 +1070,7 @@
   {}
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1113,7 +1111,7 @@
   {}
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1150,7 +1148,7 @@
   Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg,0,0), xid(x) {}
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1196,7 +1194,7 @@
     val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg)
     { is_null= !val; }
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
 #endif
@@ -1222,7 +1220,7 @@
 #ifndef MYSQL_CLIENT
   Stop_log_event() :Log_event()
   {}
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
 #endif
@@ -1260,7 +1258,7 @@
   {}
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1313,7 +1311,7 @@
 			bool using_trans);
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1379,7 +1377,7 @@
   Append_block_log_event(THD* thd, const char* db_arg, char* block_arg,
 			 uint block_len_arg, bool using_trans);
 #ifdef HAVE_REPLICATION
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
   void pack_info(Protocol* protocol);
   virtual int get_create_or_append() const;
 #endif /* HAVE_REPLICATION */
@@ -1416,7 +1414,7 @@
   Delete_file_log_event(THD* thd, const char* db_arg, bool using_trans);
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1452,7 +1450,7 @@
   Execute_load_log_event(THD* thd, const char* db_arg, bool using_trans);
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1537,7 +1535,7 @@
                        bool using_trans, bool suppress_use);
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
-  int exec_event(struct st_relay_log_info* rli);
+  int exec_event(Relay_log_info* rli);
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0,

--- 1.445/sql/mysqld.cc	Mon Apr 25 23:21:24 2005
+++ 1.446/sql/mysqld.cc	Mon Apr 25 23:34:23 2005
@@ -32,9 +32,6 @@
 #include "ha_innodb.h"
 #endif
 #include "ha_myisam.h"
-#ifdef HAVE_ISAM
-#include "ha_isam.h"
-#endif
 #ifdef HAVE_NDBCLUSTER_DB
 #include "ha_ndbcluster.h"
 #endif
@@ -49,11 +46,6 @@
 #else
 #define OPT_BDB_DEFAULT 0
 #endif
-#ifdef HAVE_ISAM_DB
-#define OPT_ISAM_DEFAULT 1
-#else
-#define OPT_ISAM_DEFAULT 0
-#endif
 #ifdef HAVE_NDBCLUSTER_DB
 #define OPT_NDBCLUSTER_DEFAULT 0
 #if defined(NOT_ENOUGH_TESTED) \
@@ -66,7 +58,6 @@
 #define OPT_NDBCLUSTER_DEFAULT 0
 #endif
 
-#include <nisam.h>
 #include <thr_alarm.h>
 #include <ft_global.h>
 #include <errmsg.h>
@@ -420,6 +411,7 @@
 SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
 SHOW_COMP_OPTION have_crypt, have_compress;
+SHOW_COMP_OPTION have_blackhole_db;
 
 /* Thread specific variables */
 
@@ -800,15 +792,6 @@
       CloseHandle(hEvent);
     */
   }
-#ifdef HAVE_SMEM
-    /*
-     Send event to smem_event_connect_request for aborting
-    */
-    if (!SetEvent(smem_event_connect_request))
-    {
-      DBUG_PRINT("error",("Got error: %ld from SetEvent of smem_event_connect_request",GetLastError()));
-    }
-#endif  
 #endif
 #elif defined(OS2)
   pthread_cond_signal(&eventShutdown);		// post semaphore
@@ -862,6 +845,18 @@
   else
     sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
 
+#if defined(HAVE_SMEM) && defined(__WIN__)    
+  /*    
+   Send event to smem_event_connect_request for aborting    
+   */    
+  if (!SetEvent(smem_event_connect_request))    
+  {      
+	  DBUG_PRINT("error",
+		("Got error: %ld from SetEvent of smem_event_connect_request",
+		 GetLastError()));    
+  }
+#endif  
+  
 #if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
   my_thread_init();				// If this is a new thread
 #endif
@@ -1036,8 +1031,8 @@
     (void) my_delete(pidfile_name,MYF(0));	// This may not always exist
 #endif
   finish_client_errs();
-  const char **errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
-  x_free((gptr) errmsgs);	/* Free messages */
+  my_free((gptr) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
+          MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
   DBUG_PRINT("quit", ("Error messages freed"));
   /* Tell main we are ready */
   (void) pthread_mutex_lock(&LOCK_thread_count);
@@ -1191,6 +1186,7 @@
 
 err:
   sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
+  unireg_abort(1);
 #endif
   return NULL;
 }
@@ -1519,6 +1515,7 @@
       thd=thread_cache.get();
       thd->real_id=pthread_self();
       (void) thd->store_globals();
+      thd->thr_create_time= time(NULL);
       threads.append(thd);
       pthread_mutex_unlock(&LOCK_thread_count);
       DBUG_VOID_RETURN;
@@ -2441,8 +2438,10 @@
   {
     struct tm tm_tmp;
     localtime_r(&start_time,&tm_tmp);
-    strmov(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
-  }
+    strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
+            sizeof(system_time_zone)-1);
+
+ }
 #endif
   /*
     We set SYSTEM time zone as reasonable default and 
@@ -3132,11 +3131,21 @@
 #endif
   if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
     opt_skip_slave_start= 1;
-  /* init_slave() must be called after the thread keys are created */
-  init_slave();
+  /*
+    init_slave() must be called after the thread keys are created.
+    Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
+    places) assume that active_mi != 0, so let's fail if it's 0 (out of
+    memory); a message has already been printed.
+  */
+  if (init_slave() && !active_mi)
+  {
+    end_thr_alarm(1);				// Don't allow alarms
+    unireg_abort(1);
+  }
 
   if (opt_bootstrap)
   {
+    select_thread_in_use= 0;                    // Allow 'kill' to work
     bootstrap(stdin);
     end_thr_alarm(1);				// Don't allow alarms
     unireg_abort(bootstrap_error ? 1 : 0);
@@ -3307,9 +3316,10 @@
 
 int main(int argc, char **argv)
 {
-  /* When several instances are running on the same machine, we
-     need to have an  unique  named  hEventShudown  through the
-     application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
+  /*
+    When several instances are running on the same machine, we
+    need to have an  unique  named  hEventShudown  through the
+    application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
   */
   int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
                                                   "MySQLShutdown"), 10);
@@ -3888,10 +3898,19 @@
   char *suffix_pos;
   char connect_number_char[22], *p;
   const char *errmsg= 0;
+  SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
   my_thread_init();
   DBUG_ENTER("handle_connections_shared_memorys");
   DBUG_PRINT("general",("Waiting for allocated shared memory."));
 
+  if (my_security_attr_create(&sa_event, &errmsg,
+                              GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
+    goto error;
+
+  if (my_security_attr_create(&sa_mapping, &errmsg,
+                             GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
+    goto error;
+
   /*
     The name of event and file-mapping events create agree next rule:
       shared_memory_base_name+unique_part
@@ -3901,22 +3920,22 @@
   */
   suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
   strmov(suffix_pos, "CONNECT_REQUEST");
-  if ((smem_event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+  if ((smem_event_connect_request= CreateEvent(sa_event,
+                                               FALSE, FALSE, tmp)) == 0)
   {
     errmsg= "Could not create request event";
     goto error;
   }
   strmov(suffix_pos, "CONNECT_ANSWER");
-  if ((event_connect_answer= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+  if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
   {
     errmsg="Could not create answer event";
     goto error;
   }
   strmov(suffix_pos, "CONNECT_DATA");
-  if ((handle_connect_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0,
-						   PAGE_READWRITE,
-						   0,sizeof(connect_number),
-						   tmp)) == 0)
+  if ((handle_connect_file_map=
+       CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
+                         PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
   {
     errmsg= "Could not create file mapping";
     goto error;
@@ -3961,10 +3980,9 @@
     suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
 			 "_",NullS);
     strmov(suffix_pos, "DATA");
-    if ((handle_client_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0,
-						    PAGE_READWRITE,0,
-						    smem_buffer_length,
-						    tmp)) == 0)
+    if ((handle_client_file_map=
+         CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
+                           PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
     {
       errmsg= "Could not create file mapping";
       goto errorconn;
@@ -3977,31 +3995,33 @@
       goto errorconn;
     }
     strmov(suffix_pos, "CLIENT_WROTE");
-    if ((event_client_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create client write event";
       goto errorconn;
     }
     strmov(suffix_pos, "CLIENT_READ");
-    if ((event_client_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create client read event";
       goto errorconn;
     }
     strmov(suffix_pos, "SERVER_READ");
-    if ((event_server_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create server read event";
       goto errorconn;
     }
     strmov(suffix_pos, "SERVER_WROTE");
-    if ((event_server_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_server_wrote= CreateEvent(sa_event,
+                                         FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create server write event";
       goto errorconn;
     }
     strmov(suffix_pos, "CONNECTION_CLOSED");
-    if ((event_conn_closed= CreateEvent(0, TRUE , FALSE, tmp)) == 0)
+    if ((event_conn_closed= CreateEvent(sa_event,
+                                        TRUE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create closed connection event";
       goto errorconn;
@@ -4076,6 +4096,8 @@
     strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
     sql_perror(buff);
   }
+  my_security_attr_free(sa_event);
+  my_security_attr_free(sa_mapping);
   if (handle_connect_map)	UnmapViewOfFile(handle_connect_map);
   if (handle_connect_file_map)	CloseHandle(handle_connect_file_map);
   if (event_connect_answer)	CloseHandle(event_connect_answer);
@@ -4316,7 +4338,7 @@
    "Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG,
    NO_ARG, 0, 0, 0, 0, 0, 0},
   {"bdb-no-sync", OPT_BDB_NOSYNC,
-   "Disable synchronously flushing logs. This option is deprecated, use --skip-sync-bdb-logs or sync-bdb-logs=0 instead",
+   "This option is deprecated, use --skip-sync-bdb-logs instead",
    //   (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"bdb-shared-data", OPT_BDB_SHARED,
@@ -4473,8 +4495,24 @@
 Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
    (gptr*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
   {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
-   "Speeds up server shutdown process.", (gptr*) &innobase_fast_shutdown,
-   (gptr*) &innobase_fast_shutdown, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+   "Speeds up the shutdown process of the InnoDB storage engine. Possible "
+   "values are 0, 1 (faster)"
+   /*
+     NetWare can't close unclosed files, can't automatically kill remaining
+     threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
+   */
+#ifndef __NETWARE__
+   " or 2 (fastest - crash-like)"
+#endif
+   ".",
+   (gptr*) &innobase_fast_shutdown,
+   (gptr*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0,
+#ifndef __NETWARE__
+   2,
+#else
+   1,
+#endif
+   0, 0, 0},
   {"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
    "Stores each InnoDB table to an .ibd file in the database dir.",
    (gptr*) &innobase_file_per_table,
@@ -4525,9 +4563,8 @@
    (gptr*) &global_system_variables.innodb_support_xa,
    0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
 #endif /* End HAVE_INNOBASE_DB */
-  {"isam", OPT_ISAM, "Enable ISAM (if this version of MySQL supports it). \
-Disable with --skip-isam.",
-   (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, OPT_ISAM_DEFAULT, 0, 0,
+  {"isam", OPT_ISAM, "Obsolete. ISAM storage engine is no longer supported.",
+   (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 0, 0, 0,
    0, 0, 0},
   {"language", 'L',
    "Client error messages in given language. May be given as a full path.",
@@ -4676,7 +4713,7 @@
    "Specify number of autoincrement values that are prefetched.",
    (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
    (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
-   0, GET_INT, REQUIRED_ARG, 32, 1, 256, 0, 0, 0},
+   0, GET_ULONG, REQUIRED_ARG, 32, 1, 256, 0, 0, 0},
   {"ndb-force-send", OPT_NDB_FORCE_SEND,
    "Force send of buffers to ndb immediately without waiting for "
    "other threads.",
@@ -5143,7 +5180,7 @@
    (gptr*) &dflt_key_cache_var.param_buff_size,
    (gptr*) 0,
    0, (GET_ULL | GET_ASK_ADDR),
-   REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, UINT_MAX32, MALLOC_OVERHEAD,
+   REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, MALLOC_OVERHEAD,
    IO_SIZE, 0},
   {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
    "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
@@ -5210,7 +5247,7 @@
    "Max number of errors/warnings to store for a statement.",
    (gptr*) &global_system_variables.max_error_count,
    (gptr*) &max_system_variables.max_error_count,
-   0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 1, 65535, 0, 1, 0},
+   0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0},
   {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
    "Don't allow creation of heap tables bigger than this.",
    (gptr*) &global_system_variables.max_heap_table_size,
@@ -5432,36 +5469,35 @@
    1, 0},
 #ifdef HAVE_BERKELEY_DB
   {"sync-bdb-logs", OPT_BDB_SYNC,
-   "Synchronously flush logs. Enabled by default",
+   "Synchronously flush Berkeley DB logs. Enabled by default",
    (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
    NO_ARG, 1, 0, 0, 0, 0, 0},
 #endif /* HAVE_BERKELEY_DB */
   {"sync-binlog", OPT_SYNC_BINLOG,
-   "Sync the binlog to disk after every #th event. \
-#=0 (the default) does no sync. Syncing slows MySQL down",
-   (gptr*) &sync_binlog_period,
-   (gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1,
-   0},
+   "Synchronously flush binary log to disk after every #th event. "
+   "Use 0 (default) to disable synchronous flushing.",
+   (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG,
+   REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
+  {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.",
+   (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
+   0, 0, 0, 0},
 #ifdef DOES_NOTHING_YET
   {"sync-replication", OPT_SYNC_REPLICATION,
-   "Enable synchronous replication",
+   "Enable synchronous replication.",
    (gptr*) &global_system_variables.sync_replication,
    (gptr*) &global_system_variables.sync_replication,
    0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
   {"sync-replication-slave-id", OPT_SYNC_REPLICATION_SLAVE_ID,
-   "Synchronous replication is wished for this slave",
+   "Synchronous replication is wished for this slave.",
    (gptr*) &global_system_variables.sync_replication_slave_id,
    (gptr*) &global_system_variables.sync_replication_slave_id,
    0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
   {"sync-replication-timeout", OPT_SYNC_REPLICATION_TIMEOUT,
-   "Synchronous replication timeout",
+   "Synchronous replication timeout.",
    (gptr*) &global_system_variables.sync_replication_timeout,
    (gptr*) &global_system_variables.sync_replication_timeout,
    0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0},
 #endif
-  {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default",
-   (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
-   0, 0, 0, 0},
   {"table_cache", OPT_TABLE_CACHE,
    "The number of open tables for all threads.", (gptr*) &table_cache_size,
    (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
@@ -5675,7 +5711,8 @@
   {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS},
   {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS},
   {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_LONG},
-  {"Slave_running",            (char*) 0, SHOW_SLAVE_RUNNING},
+  {"Slave_running",            (char*) 0,                       SHOW_SLAVE_RUNNING},
+  {"Slave_retried_transactions",(char*) 0,                      SHOW_SLAVE_RETRIED_TRANS},
   {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
   {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
   {"Sort_merge_passes",	       (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS},
@@ -5915,11 +5952,7 @@
 #else
   have_innodb=SHOW_OPTION_NO;
 #endif
-#ifdef HAVE_ISAM
-  have_isam=SHOW_OPTION_YES;
-#else
   have_isam=SHOW_OPTION_NO;
-#endif
 #ifdef HAVE_EXAMPLE_DB
   have_example_db= SHOW_OPTION_YES;
 #else
@@ -5930,6 +5963,11 @@
 #else
   have_archive_db= SHOW_OPTION_NO;
 #endif
+#ifdef HAVE_BLACKHOLE_DB
+  have_blackhole_db= SHOW_OPTION_YES;
+#else
+  have_blackhole_db= SHOW_OPTION_NO;
+#endif
 #ifdef HAVE_FEDERATED_DB
   have_federated_db= SHOW_OPTION_YES;
 #else
@@ -6064,16 +6102,6 @@
     sf_malloc_mem_limit = atoi(argument);
 #endif
     break;
-#ifdef EMBEDDED_LIBRARY
-  case OPT_MAX_ALLOWED_PACKET:
-    max_allowed_packet= atoi(argument);
-    global_system_variables.max_allowed_packet= max_allowed_packet;
-    break;
-  case OPT_NET_BUFFER_LENGTH:
-    net_buffer_length=  atoi(argument);
-    global_system_variables.net_buffer_length= net_buffer_length;
-    break;
-#endif
 #include <sslopt-case.h>
   case 'V':
     print_version();
@@ -6304,9 +6332,6 @@
       opt_error_log= 0;			// Force logs to stdout
     break;
   case (int) OPT_FLUSH:
-#ifdef HAVE_ISAM
-    nisam_flush=1;
-#endif
     myisam_flush=1;
     flush_time=0;			// No auto flush
     break;
@@ -6320,9 +6345,10 @@
   case OPT_STORAGE_ENGINE:
   {
     if ((enum db_type)((global_system_variables.table_type=
-	  ha_resolve_by_name(argument, strlen(argument)))) == DB_TYPE_UNKNOWN)
+                        ha_resolve_by_name(argument, strlen(argument)))) ==
+        DB_TYPE_UNKNOWN)
     {
-      fprintf(stderr,"Unknown table type: %s\n",argument);
+      fprintf(stderr,"Unknown/unsupported table type: %s\n",argument);
       exit(1);
     }
     break;
@@ -6413,14 +6439,6 @@
       have_berkeley_db= SHOW_OPTION_DISABLED;
 #endif
     break;
-  case OPT_ISAM:
-#ifdef HAVE_ISAM
-    if (opt_isam)
-      have_isam= SHOW_OPTION_YES;
-    else
-      have_isam= SHOW_OPTION_DISABLED;
-#endif
-    break;
   case OPT_NDBCLUSTER:
 #ifdef HAVE_NDBCLUSTER_DB
     if (opt_ndbcluster)
@@ -6471,9 +6489,6 @@
   case OPT_INNODB_LOG_ARCHIVE:
     innobase_log_archive= argument ? test(atoi(argument)) : 1;
     break;
-  case OPT_INNODB_FAST_SHUTDOWN:
-    innobase_fast_shutdown= argument ? test(atoi(argument)) : 1;
-    break;
 #endif /* HAVE_INNOBASE_DB */
   case OPT_MYISAM_RECOVER:
   {
@@ -6627,6 +6642,22 @@
     sql_print_warning("this binary does not contain BDB storage engine");
 #endif
 
+  /*
+    Check that the default storage engine is actually available.
+  */
+  if (!ha_storage_engine_is_enabled((enum db_type)
+                                    global_system_variables.table_type))
+  {
+    if (!opt_bootstrap)
+    {
+      sql_print_error("Default storage engine (%s) is not available",
+                      ha_get_storage_engine((enum db_type)
+                                            global_system_variables.table_type));
+      exit(1);
+    }
+    global_system_variables.table_type= DB_TYPE_MYISAM;
+  }
+
   if (argc > 0)
   {
     fprintf(stderr, "%s: Too many arguments (first extra is '%s').\nUse --help to get a list of available options\n", my_progname, *argv);
@@ -6662,6 +6693,9 @@
 #ifndef EMBEDDED_LIBRARY
   if (mysqld_chroot)
     set_root(mysqld_chroot);
+#else
+  max_allowed_packet= global_system_variables.max_allowed_packet;
+  net_buffer_length= global_system_variables.net_buffer_length;
 #endif
   fix_paths();
 

--- 1.242.1.1/sql/slave.cc	Fri Apr  1 22:17:25 2005
+++ 1.246/sql/rpl/slave.cc	Tue Apr 26 00:31:04 2005
@@ -20,9 +20,9 @@
 
 #include <mysql.h>
 #include <myisam.h>
-#include "slave.h"
-#include "sql_repl.h"
-#include "rpl_filter.h"
+#include <rpl/slave.h>
+#include <rpl/mic.h>
+#include <rpl/master.h>
 #include "repl_failsafe.h"
 #include <thr_alarm.h>
 #include <my_dir.h>
@@ -32,65 +32,57 @@
 bool use_slave_mask = 0;
 MY_BITMAP slave_error_mask;
 
-typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
-
-volatile bool slave_sql_running = 0, slave_io_running = 0;
-char* slave_load_tmpdir = 0;
-MASTER_INFO *active_mi;
+/*
+  LARS: These variables should be checked up
+*/
+char* slave_load_tmpdir= 0;
 bool replicate_same_server_id;
-ulonglong relay_log_space_limit = 0;
+ulonglong relay_log_space_limit= 0;
 
 /*
-  When slave thread exits, we need to remember the temporary tables so we
-  can re-use them on slave start.
-
-  TODO: move the vars below under MASTER_INFO
+  Options used by mysql-test for debugging and testing of replication
 */
+int disconnect_slave_event_count= 0;
+int abort_slave_event_count= 0;
+
+typedef enum {SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
 
-int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
-int events_till_abort = -1;
-static int events_till_disconnect = -1;
-
-typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
-
-static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev);
-static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
-static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli);
-static inline bool io_slave_killed(THD* thd,MASTER_INFO* mi);
-static inline bool sql_slave_killed(THD* thd,RELAY_LOG_INFO* rli);
-static int count_relay_log_space(RELAY_LOG_INFO* rli);
+static int process_io_rotate(Master_info* mi, Rotate_log_event* rev);
+static int process_io_create_file(Master_info* mi, Create_file_log_event* cev);
+static bool wait_for_relay_log_space(Relay_log_info* rli);
+static inline bool io_slave_killed(THD* thd,Master_info* mi);
 static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type);
-static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			  bool suppress_warnings);
-static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			     bool reconnect, bool suppress_warnings);
+static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi);
+static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi,
+                          bool suppress_warnings);
+static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
+                             bool reconnect, bool suppress_warnings);
 static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
-		      void* thread_killed_arg);
+                      void* thread_killed_arg);
 static int request_table_dump(MYSQL* mysql, const char* db, const char* table);
 static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
-				  const char* table_name, bool overwrite);
-static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi);
+                                  const char* table_name, bool overwrite);
+static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi);
 
 /*
-  Find out which replications threads are running
+  Find out which replication threads are running
 
   SYNOPSIS
     init_thread_mask()
-    mask		Return value here
-    mi			master_info for slave
-    inverse		If set, returns which threads are not running
+    mask                Return value here
+    mi                  master_info for slave
+    inverse             If set, returns which threads are not running
 
   IMPLEMENTATION
     Get a bit mask for which threads are running so that we can later restart
     these threads.
 
   RETURN
-    mask	If inverse == 0, running threads
-		If inverse == 1, stopped threads    
+    mask        If inverse == 0, running threads
+                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;
   register int tmp_mask=0;
@@ -104,307 +96,82 @@
 }
 
 
-/*
-  lock_slave_threads()
-*/
-
-void lock_slave_threads(MASTER_INFO* mi)
-{
-  //TODO: see if we can do this without dual mutex
-  pthread_mutex_lock(&mi->run_lock);
-  pthread_mutex_lock(&mi->rli.run_lock);
-}
+/* 
+   init_slave()
 
+   This function is called when mysqld starts and before client
+   connections are accepted.
 
-/*
-  unlock_slave_threads()
+   - Initialize slave structures for all channels that have info files
+   - Start slave threads for these channels
 */
-
-void unlock_slave_threads(MASTER_INFO* mi)
-{
-  //TODO: see if we can do this without dual mutex
-  pthread_mutex_unlock(&mi->rli.run_lock);
-  pthread_mutex_unlock(&mi->run_lock);
-}
-
-
-/* Initialize slave structures */
-
 int init_slave()
 {
+  Master_info *mi;
   DBUG_ENTER("init_slave");
 
   /*
-    This is called when mysqld starts. Before client connections are
-    accepted. However bootstrap may conflict with us if it does START SLAVE.
-    So it's safer to take the lock.
+    This function is called when mysqld starts and before client
+    connections are accepted.  However, bootstrap may conflict with us
+    if it does START SLAVE.  So it's safer to take the lock.
   */
   pthread_mutex_lock(&LOCK_active_mi);
-  /*
-    TODO: re-write this to interate through the list of files
-    for multi-master
-  */
-  active_mi= new MASTER_INFO;
 
-  /*
-    If master_host is not specified, try to read it from the master_info file.
-    If master_host is specified, create the master_info file if it doesn't
-    exists.
-  */
-  if (!active_mi)
-  {
-    sql_print_error("Failed to allocate memory for the master info structure");
-    goto err;
-  }
+  /* Rename files (master.info -> default-master.info, etc) */
+  mic.upgrade51();                    
 
-  if (init_master_info(active_mi,master_info_file,relay_log_info_file,
-		       !master_host, (SLAVE_IO | SLAVE_SQL)))
+  /* Initialize Master_info:s from storage */
+  if (mic.init(mysql_data_home))
   {
-    sql_print_error("Failed to initialize the master info structure");
-    goto err;
+    sql_print_error("Could not initialize master info container");
+    pthread_mutex_unlock(&LOCK_active_mi); 
+    DBUG_RETURN(1);
   }
-
-  if (server_id && !master_host && active_mi->host[0])
-    master_host= active_mi->host;
-
-  /* If server id is not set, start_slave_thread() will say it */
-
-  if (master_host && !opt_skip_slave_start)
+  
+  /* This channel should exist, so lets create it */
+/*
+  if (!mic.get_or_create_master_info("default"))
   {
-    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))
-    {
-      sql_print_error("Failed to create slave threads");
-      goto err;
-    }
+    sql_print_error("Could not initialize 'default' subslave");
+    pthread_mutex_unlock(&LOCK_active_mi); 
+    DBUG_RETURN(1);
   }
-  pthread_mutex_unlock(&LOCK_active_mi);
-  DBUG_RETURN(0);
-
-err:
-  pthread_mutex_unlock(&LOCK_active_mi);
-  DBUG_RETURN(1);
-}
-
-
-/*
-  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
-    rli->cur_log to point to the same IO_CACHE entry.
-  - If not, open the 'log' binary file.
-
-  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
+LARS
 */
-
-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)
-{
-  DBUG_ENTER("init_relay_log_pos");
-  DBUG_PRINT("info", ("pos=%lu", pos));
-
-  *errmsg=0;
-  pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
   
-  if (need_data_lock)
-    pthread_mutex_lock(&rli->data_lock);
-
-  /*
-    Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER
-    is, too, and init_slave() too; these 2 functions allocate a description
-    event in init_relay_log_pos, which is not freed by the terminating SQL slave
-    thread as that thread is not started by these functions. So we have to free
-    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;
-  /*
-    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). 
+  /* LARS: Check this
+     if (init_master_info(active_mi, !master_host, (SLAVE_IO | SLAVE_SQL)))
+     {
+       sql_print_error("Failed to initialize the master info structure");
+       goto err;
+     }
   */
-  rli->relay_log.description_event_for_exec= new
-    Format_description_log_event(3);
   
-  pthread_mutex_lock(log_lock);
-  
-  /* Close log file and free buffers if it's already open */
-  if (rli->cur_log_fd >= 0)
-  {
-    end_io_cache(&rli->cache_buf);
-    my_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
-  }
-  
-  rli->group_relay_log_pos = rli->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))
-  {
-    *errmsg="Could not find first log during relay log initialization";
-    goto err;
-  }
-
-  if (log && rli->relay_log.find_log_pos(&rli->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))
-  {
-    /*
-      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))
-      goto err;
-    rli->cur_log_old_open_count=rli->relay_log.get_open_count();
-  }
-  else
-  {
-    /*
-      Open the relay log and set rli->cur_log to point at this one
-    */
-    if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
-				     rli->linfo.log_file_name,errmsg)) < 0)
-      goto err;
-    rli->cur_log = &rli->cache_buf;
-  }
   /*
-    In all cases, check_binlog_magic() has been called so we're at offset 4 for
-    sure.
+    Auto-start all threads for all defined channels 
+    If server id is not set, start_slave_thread() will say it 
   */
-  if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */
+  if (!opt_skip_slave_start)
   {
-    Log_event* ev;
-    while (look_for_description_event) 
+    for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
     {
-      /*
-        Read the possible Format_description_log_event; if position
-        was 4, no need, it will be read naturally.
-      */
-      DBUG_PRINT("info",("looking for a Format_description_log_event"));
-
-      if (my_b_tell(rli->cur_log) >= pos)
-        break;
+      if (!mi->is_inited()) continue;    // Skip non-initialized 
 
-      /*
-        Because of we have rli->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 (start_slave_threads(1 /* need mutex */,
+                              0 /* no wait for start*/,
+                              mi,
+                              SLAVE_IO | SLAVE_SQL))
       {
-        DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
-                           rli->cur_log->error));
-        if (rli->cur_log->error) /* not EOF */
-        {
-          *errmsg= "I/O error reading event at position 4";
-          goto err;
-        }
-        break;
-      }
-      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;
-        /*
-          As ev was returned by read_log_event, it has passed is_valid(), so
-          my_malloc() in ctor worked, no need to check again.
-        */
-        /*
-          Ok, we found a Format_description event. But it is not sure that this
-          describes the whole relay log; indeed, one can have this sequence
-          (starting from position 4):
-          Format_desc (of slave)
-          Rotate (of master)
-          Format_desc (of master)
-          So the Format_desc which really describes the rest of the relay log
-          is the 3rd event (it can't be further than that, because we rotate
-          the relay log when we queue a Rotate event from the master).
-          But what describes the Rotate is the first Format_desc.
-          So what we do is:
-          go on searching for Format_description events, until you exceed the
-          position (argument 'pos') or until you find another event than Rotate
-          or Format_desc.
-        */
-      }
-      else 
-      {
-        DBUG_PRINT("info",("found event of another type=%d",
-                           ev->get_type_code()));
-        look_for_description_event= (ev->get_type_code() == ROTATE_EVENT);
-        delete ev;
+        sql_print_error("RPL:%s:Failed to create slave threads", 
+                        mi->channel);
+        pthread_mutex_unlock(&LOCK_active_mi); 
+        DBUG_RETURN(1);
       }
     }
-    my_b_seek(rli->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)));
-  }
-#endif
-
   }
 
-err:
-  /*
-    If we don't purge, we can't honour relay_log_space_limit ;
-    silently discard it
-  */
-  if (!relay_log_purge)
-    rli->log_space_limit= 0;
-  pthread_cond_broadcast(&rli->data_cond);
-  
-  pthread_mutex_unlock(log_lock);
-
-  if (need_data_lock)
-    pthread_mutex_unlock(&rli->data_lock);
-  if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
-    *errmsg= "Invalid Format_description log event; could be out of memory";
-
-  DBUG_RETURN ((*errmsg) ? 1 : 0);
+  pthread_mutex_unlock(&LOCK_active_mi);
+  DBUG_RETURN(0);
 }
 
 
@@ -413,7 +180,7 @@
 
   SYNOPSIS
     init_slave_skip_errors()
-    arg		List of errors numbers to skip, separated with ','
+    arg         List of errors numbers to skip, separated with ','
 
   NOTES
     Called from get_options() in mysqld.cc on start-up
@@ -448,157 +215,9 @@
 }
 
 
-void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
-						bool skip_lock)  
+int terminate_slave_threads(Master_info* mi, int thread_mask, bool skip_lock)
 {
-  if (!skip_lock)
-    pthread_mutex_lock(&data_lock);
-  inc_event_relay_log_pos();
-  group_relay_log_pos= event_relay_log_pos;
-  strmake(group_relay_log_name,event_relay_log_name,
-	  sizeof(group_relay_log_name)-1);
-
-  notify_group_relay_log_name_update();
-        
-  /*
-    If the slave does not support transactions and replicates a transaction,
-    users should not trust group_master_log_pos (which they can display with
-    SHOW SLAVE STATUS or read from relay-log.info), because to compute
-    group_master_log_pos the slave relies on log_pos stored in the master's
-    binlog, but if we are in a master's transaction these positions are always
-    the BEGIN's one (excepted for the COMMIT), so group_master_log_pos does
-    not advance as it should on the non-transactional slave (it advances by
-    big leaps, whereas it should advance by small leaps).
-  */
-  /*
-    In 4.x we used the event's len to compute the positions here. This is
-    wrong if the event was 3.23/4.0 and has been converted to 5.0, because
-    then the event's len is not what is was in the master's binlog, so this
-    will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0
-    replication: Exec_master_log_pos is wrong). Only way to solve this is to
-    have the original offset of the end of the event the relay log. This is
-    what we do in 5.0: log_pos has become "end_log_pos" (because the real use
-    of log_pos in 4.0 was to compute the end_log_pos; so better to store
-    end_log_pos instead of begin_log_pos.
-    If we had not done this fix here, the problem would also have appeared
-    when the slave and master are 5.0 but with different event length (for
-    example the slave is more recent than the master and features the event
-    UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in
-    SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this
-    value which would lead to badly broken replication.
-    Even the relay_log_pos will be corrupted in this case, because the len is
-    the relay log is not "val".
-    With the end_log_pos solution, we avoid computations involving lengthes.
-  */
-  DBUG_PRINT("info", ("log_pos: %lu  group_master_log_pos: %lu",
-		      (long) log_pos, (long) group_master_log_pos));
-  if (log_pos) // 3.23 binlogs don't have log_posx
-  {
-    group_master_log_pos= log_pos;
-  }
-  pthread_cond_broadcast(&data_cond);
-  if (!skip_lock)
-    pthread_mutex_unlock(&data_lock);
-}
-
-
-void st_relay_log_info::close_temporary_tables()
-{
-  TABLE *table,*next;
-
-  for (table=save_temporary_tables ; table ; table=next)
-  {
-    next=table->next;
-    /*
-      Don't ask for disk deletion. For now, anyway they will be deleted when
-      slave restarts, but it is a better intention to not delete them.
-    */
-    close_temporary(table, 0);
-  }
-  save_temporary_tables= 0;
-  slave_open_temp_tables= 0;
-}
-
-/*
-  purge_relay_logs()
-
-  NOTES
-    Assumes to have a run lock on rli and that no slave thread are running.
-*/
-
-int purge_relay_logs(RELAY_LOG_INFO* rli, 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.
-  */
-
-  rli->group_master_log_name[0]= 0;
-  rli->group_master_log_pos= 0;
-
-  if (!rli->inited)
-  {
-    DBUG_PRINT("info", ("rli->inited == 0"));
-    DBUG_RETURN(0);
-  }
-
-  DBUG_ASSERT(rli->slave_running == 0);
-  DBUG_ASSERT(rli->mi->slave_running == 0);
-
-  rli->slave_skip_counter=0;
-  pthread_mutex_lock(&rli->data_lock);
-  if (rli->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))
-  {
-    *errmsg= "Error counting relay log space";
-    goto err;
-  }
-  if (!just_reset)
-    error= init_relay_log_pos(rli, rli->group_relay_log_name,
-                              rli->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)));
-  pthread_mutex_unlock(&rli->data_lock);
-  DBUG_RETURN(error);
-}
-
-
-int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
-{
-  if (!mi->inited)
+  if (!mi->is_inited())
     return 0; /* successfully do nothing */
   int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
   pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
@@ -614,25 +233,25 @@
   }
   if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) && mi->slave_running)
   {
-    DBUG_PRINT("info",("Terminating IO thread"));
+    DBUG_PRINT("info",("I/O:%s:Terminating thread", mi->channel));
     mi->abort_slave=1;
     if ((error=terminate_slave_thread(mi->io_thd,io_lock,
-				      io_cond_lock,
-				      &mi->stop_cond,
-				      &mi->slave_running)) &&
-	!force_all)
+                                      io_cond_lock,
+                                      &mi->stop_cond,
+                                      &mi->slave_running)) &&
+        !force_all)
       DBUG_RETURN(error);
   }
   if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) && mi->rli.slave_running)
   {
-    DBUG_PRINT("info",("Terminating SQL thread"));
+    DBUG_PRINT("info",("SQL:%s:Terminating thread", mi->channel));
     DBUG_ASSERT(mi->rli.sql_thd != 0) ;
     mi->rli.abort_slave=1;
     if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
-				      sql_cond_lock,
-				      &mi->rli.stop_cond,
-				      &mi->rli.slave_running)) &&
-	!force_all)
+                                      sql_cond_lock,
+                                      &mi->rli.stop_cond,
+                                      &mi->rli.slave_running)) &&
+        !force_all)
       DBUG_RETURN(error);
   }
   DBUG_RETURN(0);
@@ -640,9 +259,9 @@
 
 
 int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
-			   pthread_mutex_t *cond_lock,
-			   pthread_cond_t* term_cond,
-			   volatile uint *slave_running)
+                           pthread_mutex_t *cond_lock,
+                           pthread_cond_t* term_cond,
+                           volatile uint *slave_running)
 {
   DBUG_ENTER("terminate_slave_thread");
   if (term_lock)
@@ -661,7 +280,7 @@
     be referening freed memory trying to kick it
   */
 
-  while (*slave_running)			// Should always be true
+  while (*slave_running)                        // Should always be true
   {
     DBUG_PRINT("loop", ("killing slave thread"));
     KICK_SLAVE(thd);
@@ -680,16 +299,16 @@
 
 
 int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
-		       pthread_mutex_t *cond_lock,
-		       pthread_cond_t *start_cond,
-		       volatile uint *slave_running,
-		       volatile ulong *slave_run_id,
-		       MASTER_INFO* mi,
+                       pthread_mutex_t *cond_lock,
+                       pthread_cond_t *start_cond,
+                       volatile uint *slave_running,
+                       volatile ulong *slave_run_id,
+                       Master_info* mi,
                        bool high_priority)
 {
   pthread_t th;
   ulong start_id;
-  DBUG_ASSERT(mi->inited);
+  DBUG_ASSERT(mi->is_inited());
   DBUG_ENTER("start_slave_thread");
 
   if (start_lock)
@@ -729,12 +348,12 @@
     {
       DBUG_PRINT("sleep",("Waiting for slave thread to start"));
       const char* old_msg = thd->enter_cond(start_cond,cond_lock,
-					    "Waiting for slave thread to start");
+                                            "Waiting for slave thread to start");
       pthread_cond_wait(start_cond,cond_lock);
       thd->exit_cond(old_msg);
       pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released
       if (thd->killed)
-	DBUG_RETURN(thd->killed_errno());
+        DBUG_RETURN(thd->killed_errno());
     }
   }
   if (start_lock)
@@ -753,8 +372,7 @@
 */
 
 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)
 {
   pthread_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0;
   pthread_cond_t* cond_io=0,*cond_sql=0;
@@ -776,15 +394,15 @@
 
   if (thread_mask & SLAVE_IO)
     error=start_slave_thread(handle_slave_io,lock_io,lock_cond_io,
-			     cond_io,
-			     &mi->slave_running, &mi->slave_run_id,
-			     mi, 1); //high priority, to read the most possible
+                             cond_io,
+                             &mi->slave_running, &mi->slave_run_id,
+                             mi, 1); //high priority, to read the most possible
   if (!error && (thread_mask & SLAVE_SQL))
   {
     error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql,
-			     cond_sql,
-			     &mi->rli.slave_running, &mi->rli.slave_run_id,
-			     mi, 0);
+                             cond_sql,
+                             &mi->rli.slave_running, &mi->rli.slave_run_id,
+                             mi, 0);
     if (error)
       terminate_slave_threads(mi, thread_mask & SLAVE_IO, 0);
   }
@@ -792,23 +410,14 @@
 }
 
 
-#ifdef NOT_USED_YET
-static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
-{
-  end_master_info(mi);
-  return 0;
-}
-#endif
-
-
 /*
   Free all resources used by slave
 
   SYNOPSIS
-    end_slave()
+    end_all_channels()
 */
 
-void end_slave()
+void end_all_channels()
 {
   /*
     This is called when the server terminates, in close_connections().
@@ -818,23 +427,17 @@
     returns, then we terminate them here.
   */
   pthread_mutex_lock(&LOCK_active_mi);
-  if (active_mi)
+  Master_info *mi;
+  while ((mi= mic.get_head()))
   {
-    /*
-      TODO: replace the line below with
-      list_walk(&master_list, (list_walk_action)end_slave_on_walk,0);
-      once multi-master code is ready.
-    */
-    terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
-    end_master_info(active_mi);
-    delete active_mi;
-    active_mi= 0;
+    terminate_slave_threads(mi, SLAVE_FORCE_ALL);
+    mic.drop_head_master_info();
   }
   pthread_mutex_unlock(&LOCK_active_mi);
 }
 
 
-static bool io_slave_killed(THD* thd, MASTER_INFO* mi)
+static bool io_slave_killed(THD* thd, Master_info* mi)
 {
   DBUG_ASSERT(mi->io_thd == thd);
   DBUG_ASSERT(mi->slave_running); // tracking buffer overrun
@@ -842,21 +445,13 @@
 }
 
 
-static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli)
-{
-  DBUG_ASSERT(rli->sql_thd == thd);
-  DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun
-  return rli->abort_slave || abort_loop || thd->killed;
-}
-
-
 /*
   Writes an error message to rli->last_slave_error and rli->last_slave_errno
   (which will be displayed by SHOW SLAVE STATUS), and prints it to stderr.
 
   SYNOPSIS
     slave_print_error()
-    rli		
+    rli         
     err_code    The error code
     msg         The error message (usually related to the error code, but can
                 contain more information).
@@ -866,12 +461,12 @@
     void
 */
 
-void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...)
+void slave_print_error(Relay_log_info* rli, int err_code, const char* msg, ...)
 {
   va_list args;
   va_start(args,msg);
   my_vsnprintf(rli->last_slave_error,
-	       sizeof(rli->last_slave_error), msg, args);
+               sizeof(rli->last_slave_error), msg, args);
   rli->last_slave_errno = err_code;
   /* If the error string ends with '.', do not add a ',' it would be ugly */
   if (rli->last_slave_error[0] && 
@@ -894,8 +489,8 @@
 void skip_load_data_infile(NET *net)
 {
   (void)net_request_file(net, "/dev/null");
-  (void)my_net_read(net);				// discard response
-  (void)net_write_command(net, 0, "", 0, "", 0);	// Send ok
+  (void)my_net_read(net);                               // discard response
+  (void)net_write_command(net, 0, "", 0, "", 0);        // Send ok
 }
 
 
@@ -919,52 +514,6 @@
 }
 
 
-static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-				 const char *default_val)
-{
-  uint length;
-  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));
-    }
-    return 0;
-  }
-  else if (default_val)
-  {
-    strmake(var,  default_val, max_size-1);
-    return 0;
-  }
-  return 1;
-}
-
-
-static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
-{
-  char buf[32];
-  
-  if (my_b_gets(f, buf, sizeof(buf))) 
-  {
-    *var = atoi(buf);
-    return 0;
-  }
-  else if (default_val)
-  {
-    *var = default_val;
-    return 0;
-  }
-  return 1;
-}
-
 /*
   Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
   relying on the binlog's version. This is not perfect: imagine an upgrade
@@ -979,7 +528,7 @@
   1       error
 */
 
-static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi)
+static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
 {
   const char* errmsg= 0;
 
@@ -1036,14 +585,16 @@
   
   if (errmsg)
   {
-    sql_print_error(errmsg);
+    sql_print_error("I/O:%s:%s", mi->channel, errmsg);
     return 1;
   }
 
   /* as we are here, we tried to allocate the event */
   if (!mi->rli.relay_log.description_event_for_queue)
   {
-    sql_print_error("Slave I/O thread failed to create a default Format_description_log_event");
+    sql_print_error("I/O:%s:Failed to create a default "
+                    "Format_description_log_event",
+                    mi->channel);
     return 1;
   }
 
@@ -1064,8 +615,10 @@
   else
   {
     mi->clock_diff_with_master= 0; /* The "most sensible" value */
-    sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, \
-do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS");
+    sql_print_warning("I/O:%s:\"SELECT UNIX_TIMESTAMP()\" failed on master, "
+                      "do not trust column Seconds_Behind_Master of "
+                      "SHOW SLAVE STATUS",
+                      mi->channel);
   }
   if (master_res)
     mysql_free_result(master_res);      
@@ -1157,7 +710,7 @@
 err:
   if (errmsg)
   {
-    sql_print_error(errmsg);
+    sql_print_error("I/O:%s:%s", mi->channel, errmsg);
     return 1;
   }
 
@@ -1176,7 +729,7 @@
 */
 
 static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
-				  const char* table_name, bool overwrite)
+                                  const char* table_name, bool overwrite)
 {
   ulong packet_len;
   char *query, *save_db;
@@ -1200,8 +753,8 @@
   {
     char *err_msg; 
     err_msg= (char*) net->read_pos + ((mysql->server_capabilities &
-				       CLIENT_PROTOCOL_41) ?
-				      3+SQLSTATE_LENGTH+1 : 3);
+                                       CLIENT_PROTOCOL_41) ?
+                                      3+SQLSTATE_LENGTH+1 : 3);
     my_error(ER_MASTER, MYF(0), err_msg);
     DBUG_RETURN(1);
   }
@@ -1240,12 +793,12 @@
   DBUG_ASSERT(thd->db != 0);
   thd->db_length= strlen(thd->db);
   mysql_parse(thd, thd->query, packet_len); // run create table
-  thd->db = save_db;		// leave things the way the were before
+  thd->db = save_db;            // leave things the way the were before
   thd->db_length= save_db_length;
   thd->options = save_options;
   
   if (thd->query_error)
-    goto err;			// mysql_parse took care of the error send
+    goto err;                   // mysql_parse took care of the error send
 
   thd->proc_info = "Opening master dump table";
   tables.lock_type = TL_WRITE;
@@ -1289,15 +842,36 @@
 }
 
 
+/*
+  Implements SQL command: LOAD TABLE tablename FROM MASTER channel
+*/
+int load_master_table(THD *thd, const char *db_name, const char *table_name,
+                      const char *channel, MYSQL *mysql, bool overwrite)
+{
+  DBUG_ENTER("load_master_table");
+  DBUG_PRINT("enter", ("channel: '%s', db_name: '%s', table_name: '%s'",
+                       channel, db_name, table_name));
+
+  Master_info *mi;
+  if (!(mi= mic.get_master_info(channel)))
+  {
+    my_error(ER_CHANNEL_NOT_EXISTS, MYF(0), channel);
+    mysql_close(mysql);
+    DBUG_RETURN(1);
+  }
+  return fetch_master_table(thd, db_name, table_name, mi, mysql, overwrite);
+}
+
+
 int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
-		       MASTER_INFO *mi, MYSQL *mysql, bool overwrite)
+                       Master_info *mi, MYSQL *mysql, bool overwrite)
 {
   int error= 1;
   const char *errmsg=0;
   bool called_connected= (mysql != NULL);
-  DBUG_ENTER("fetch_master_table");
-  DBUG_PRINT("enter", ("db_name: '%s'  table_name: '%s'",
-		       db_name,table_name));
+  DBUG_ENTER("load_master_table");
+  DBUG_PRINT("enter", ("db_name: '%s', table_name: '%s'", 
+                       db_name, table_name));
 
   if (!called_connected)
   { 
@@ -1322,7 +896,7 @@
     goto err;
   }
   if (create_table_from_dump(thd, mysql, db_name,
-			     table_name, overwrite))
+                             table_name, overwrite))
     goto err;    // create_table_from_dump have sent the error already
   error = 0;
 
@@ -1332,249 +906,14 @@
     mysql_close(mysql);
   if (errmsg && thd->vio_ok())
     my_message(error, errmsg, MYF(0));
-  DBUG_RETURN(test(error));			// Return 1 on error
+  DBUG_RETURN(test(error));                     // Return 1 on error
 }
 
 
-void end_master_info(MASTER_INFO* mi)
-{
-  DBUG_ENTER("end_master_info");
-
-  if (!mi->inited)
-    DBUG_VOID_RETURN;
-  end_relay_log_info(&mi->rli);
-  if (mi->fd >= 0)
-  {
-    end_io_cache(&mi->file);
-    (void)my_close(mi->fd, MYF(MY_WME));
-    mi->fd = -1;
-  }
-  mi->inited = 0;
-
-  DBUG_VOID_RETURN;
-}
-
-
-static int init_relay_log_info(RELAY_LOG_INFO* rli,
-                               const char* info_fname)
-{
-  char fname[FN_REFLEN+128];
-  int info_fd;
-  const char* msg = 0;
-  int error = 0;
-  DBUG_ENTER("init_relay_log_info");
-
-  if (rli->inited)                       // Set if this function called
-    DBUG_RETURN(0);
-  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
-  pthread_mutex_lock(&rli->data_lock);
-  info_fd = rli->info_fd;
-  rli->cur_log_fd = -1;
-  rli->slave_skip_counter=0;
-  rli->abort_pos_wait=0;
-  rli->log_space_limit= relay_log_space_limit;
-  rli->log_space_total= 0;
-
-  /*
-    The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
-    Note that the I/O thread flushes it to disk after writing every
-    event, in flush_master_info(mi, 1).
-  */
-
-  /*
-    For the maximum log size, we choose max_relay_log_size if it is
-    non-zero, max_binlog_size otherwise. If later the user does SET
-    GLOBAL on one of these variables, fix_max_binlog_size and
-    fix_max_relay_log_size will reconsider the choice (for example
-    if the user changes max_relay_log_size to zero, we have to
-    switch to using max_binlog_size for the relay log) and update
-    rli->relay_log.max_size (and mysql_bin_log.max_size).
-  */
-  {
-    char buf[FN_REFLEN];
-    const char *ln;
-    ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
-                                     1, buf);
-
-    /*
-      note, that if open() fails, we'll still have index file open
-      but a destructor will take care of that
-    */
-    if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) ||
-        rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
-                            (max_relay_log_size ? max_relay_log_size :
-                            max_binlog_size), 1))
-    {
-      pthread_mutex_unlock(&rli->data_lock);
-      sql_print_error("Failed in open_log() called from init_relay_log_info()");
-      DBUG_RETURN(1);
-    }
-  }
-
-  /* if file does not exist */
-  if (access(fname,F_OK))
-  {
-    /*
-      If someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (info_fd >= 0)
-      my_close(info_fd, MYF(MY_WME));
-    if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-    {
-      sql_print_error("Failed to create a new relay log info file (\
-file '%s', errno %d)", fname, my_errno);
-      msg= current_thd->net.last_error;
-      goto err;
-    }
-    if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
-		      MYF(MY_WME))) 
-    {
-      sql_print_error("Failed to create a cache on relay log info file '%s'",
-		      fname);
-      msg= current_thd->net.last_error;
-      goto err;
-    }
-
-    /* Init relay log with first entry in the relay index file */
-    if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
-			   &msg, 0))
-    {
-      sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
-      goto err;
-    }
-    rli->group_master_log_name[0]= 0;
-    rli->group_master_log_pos= 0;		
-    rli->info_fd= info_fd;
-  }
-  else // file exists
-  {
-    if (info_fd >= 0)
-      reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
-    else 
-    {
-      int error=0;
-      if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-      {
-        sql_print_error("\
-Failed to open the existing relay log info file '%s' (errno %d)",
-			fname, my_errno);
-        error= 1;
-      }
-      else if (init_io_cache(&rli->info_file, info_fd,
-                             IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on relay log info file '%s'",
-			fname);
-        error= 1;
-      }
-      if (error)
-      {
-        if (info_fd >= 0)
-          my_close(info_fd, MYF(0));
-        rli->info_fd= -1;
-        rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-        pthread_mutex_unlock(&rli->data_lock);
-        DBUG_RETURN(1);
-      }
-    }
-         
-    rli->info_fd = info_fd;
-    int relay_log_pos, master_log_pos;
-    if (init_strvar_from_file(rli->group_relay_log_name,
-			      sizeof(rli->group_relay_log_name),
-                              &rli->info_file, "") ||
-       init_intvar_from_file(&relay_log_pos,
-			     &rli->info_file, BIN_LOG_HEADER_SIZE) ||
-       init_strvar_from_file(rli->group_master_log_name,
-			     sizeof(rli->group_master_log_name),
-                             &rli->info_file, "") ||
-       init_intvar_from_file(&master_log_pos, &rli->info_file, 0))
-    {
-      msg="Error reading slave log configuration";
-      goto err;
-    }
-    strmake(rli->event_relay_log_name,rli->group_relay_log_name,
-            sizeof(rli->event_relay_log_name)-1);
-    rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos;
-    rli->group_master_log_pos= master_log_pos;
-
-    if (init_relay_log_pos(rli,
-			   rli->group_relay_log_name,
-			   rli->group_relay_log_pos,
-			   0 /* no data lock*/,
-			   &msg, 0))
-    {
-      char llbuf[22];
-      sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
-		      rli->group_relay_log_name,
-		      llstr(rli->group_relay_log_pos, llbuf));
-      goto err;
-    }
-  }
-
-#ifndef DBUG_OFF
-  {
-    char llbuf1[22], llbuf2[22];
-    DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
-                        llstr(my_b_tell(rli->cur_log),llbuf1), 
-                        llstr(rli->event_relay_log_pos,llbuf2)));
-    DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
-    DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
-  }
-#endif
-
-  /*
-    Now change the cache from READ to WRITE - must do this
-    before flush_relay_log_info
-  */
-  reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
-  if ((error= flush_relay_log_info(rli)))
-    sql_print_error("Failed to flush relay log info file");
-  if (count_relay_log_space(rli))
-  {
-    msg="Error counting relay log space";
-    goto err;
-  }
-  rli->inited= 1;
-  pthread_mutex_unlock(&rli->data_lock);
-  DBUG_RETURN(error);
-
-err:
-  sql_print_error(msg);
-  end_io_cache(&rli->info_file);
-  if (info_fd >= 0)
-    my_close(info_fd, MYF(0));
-  rli->info_fd= -1;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  pthread_mutex_unlock(&rli->data_lock);
-  DBUG_RETURN(1);
-}
-
-
-static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
-{
-  MY_STAT s;
-  DBUG_ENTER("add_relay_log");
-  if (!my_stat(linfo->log_file_name,&s,MYF(0)))
-  {
-    sql_print_error("log %s listed in the index, but failed to stat",
-		    linfo->log_file_name);
-    DBUG_RETURN(1);
-  }
-  rli->log_space_total += s.st_size;
-#ifndef DBUG_OFF
-  char buf[22];
-  DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf)));
-#endif  
-  DBUG_RETURN(0);
-}
-
-
-static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
+static bool wait_for_relay_log_space(Relay_log_info* rli)
 {
   bool slave_killed=0;
-  MASTER_INFO* mi = rli->mi;
+  Master_info* mi = rli->mi;
   const char *save_proc_info;
   THD* thd = mi->io_thd;
 
@@ -1582,11 +921,11 @@
 
   pthread_mutex_lock(&rli->log_space_lock);
   save_proc_info= thd->enter_cond(&rli->log_space_cond,
-				  &rli->log_space_lock, 
-				  "\
+                                  &rli->log_space_lock, 
+                                  "\
 Waiting for the slave SQL thread to free enough relay log space");
   while (rli->log_space_limit < rli->log_space_total &&
-	 !(slave_killed=io_slave_killed(thd,mi)) &&
+         !(slave_killed=io_slave_killed(thd,mi)) &&
          !rli->ignore_log_space_limit)
     pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
   thd->exit_cond(save_proc_info);
@@ -1594,300 +933,6 @@
 }
 
 
-static int count_relay_log_space(RELAY_LOG_INFO* rli)
-{
-  LOG_INFO linfo;
-  DBUG_ENTER("count_relay_log_space");
-  rli->log_space_total= 0;
-  if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
-  {
-    sql_print_error("Could not find first log while counting relay log space");
-    DBUG_RETURN(1);
-  }
-  do
-  {
-    if (add_relay_log(rli,&linfo))
-      DBUG_RETURN(1);
-  } while (!rli->relay_log.find_next_log(&linfo, 1));
-  /* 
-     As we have counted everything, including what may have written in a
-     preceding write, we must reset bytes_written, or we may count some space 
-     twice.
-  */
-  rli->relay_log.reset_bytes_written();
-  DBUG_RETURN(0);
-}
-
-
-void init_master_info_with_options(MASTER_INFO* mi)
-{
-  mi->master_log_name[0] = 0;
-  mi->master_log_pos = BIN_LOG_HEADER_SIZE;		// skip magic number
-  
-  if (master_host)
-    strmake(mi->host, master_host, sizeof(mi->host) - 1);
-  if (master_user)
-    strmake(mi->user, master_user, sizeof(mi->user) - 1);
-  if (master_password)
-    strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
-  mi->port = master_port;
-  mi->connect_retry = master_connect_retry;
-  
-  mi->ssl= master_ssl;
-  if (master_ssl_ca)
-    strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1);
-  if (master_ssl_capath)
-    strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1);
-  if (master_ssl_cert)
-    strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1);
-  if (master_ssl_cipher)
-    strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1);
-  if (master_ssl_key)
-    strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1);
-}
-
-void clear_slave_error(RELAY_LOG_INFO* rli)
-{
-  /* Clear the errors displayed by SHOW SLAVE STATUS */
-  rli->last_slave_error[0]= 0;
-  rli->last_slave_errno= 0;
-}
-
-/*
-    Reset UNTIL condition for RELAY_LOG_INFO
-   SYNOPSYS
-    clear_until_condition()
-      rli - RELAY_LOG_INFO structure where UNTIL condition should be reset
- */
-void clear_until_condition(RELAY_LOG_INFO* rli)
-{
-  rli->until_condition= RELAY_LOG_INFO::UNTIL_NONE;
-  rli->until_log_name[0]= 0;
-  rli->until_log_pos= 0;
-}
-
-
-#define LINES_IN_MASTER_INFO_WITH_SSL 14
-
-
-int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
-                     const char* slave_info_fname,
-                     bool abort_if_no_master_info_file,
-                     int thread_mask)
-{
-  int fd,error;
-  char fname[FN_REFLEN+128];
-  DBUG_ENTER("init_master_info");
-
-  if (mi->inited)
-  {
-    /*
-      We have to reset read position of relay-log-bin as we may have
-      already been reading from 'hotlog' when the slave was stopped
-      last time. If this case pos_in_file would be set and we would
-      get a crash when trying to read the signature for the binary
-      relay log.
-
-      We only rewind the read position if we are starting the SQL
-      thread. The handle_slave_sql thread assumes that the read
-      position is at the beginning of the file, and will read the
-      "signature" and then fast-forward to the last position read.
-    */
-    if (thread_mask & SLAVE_SQL)
-    {
-      my_b_seek(mi->rli.cur_log, (my_off_t) 0);
-    }
-    DBUG_RETURN(0);
-  }
-
-  mi->mysql=0;
-  mi->file_id=1;
-  fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
-
-  /*
-    We need a mutex while we are changing master info parameters to
-    keep other threads from reading bogus info
-  */
-
-  pthread_mutex_lock(&mi->data_lock);
-  fd = mi->fd;
-
-  /* does master.info exist ? */
-
-  if (access(fname,F_OK))
-  {
-    if (abort_if_no_master_info_file)
-    {
-      pthread_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)
-      my_close(fd, MYF(MY_WME));
-    if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-    {
-      sql_print_error("Failed to create a new master info file (\
-file '%s', errno %d)", fname, my_errno);
-      goto err;
-    }
-    if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
-		      MYF(MY_WME)))
-    {
-      sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
-      goto err;
-    }
-
-    mi->fd = fd;
-    init_master_info_with_options(mi);
-
-  }
-  else // file exists
-  {
-    if (fd >= 0)
-      reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
-    else
-    {
-      if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-      {
-        sql_print_error("Failed to open the existing master info file (\
-file '%s', errno %d)", fname, my_errno);
-        goto err;
-      }
-      if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
-                        0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
-        goto err;
-      }
-    }
-
-    mi->fd = fd;
-    int port, connect_retry, master_log_pos, ssl= 0, lines;
-    char *first_non_digit;
-
-    /*
-       Starting from 4.1.x master.info has new format. Now its
-       first line contains number of lines in file. By reading this
-       number we will be always distinguish to which version our
-       master.info corresponds to. We can't simply count lines in
-       file since versions before 4.1.x could generate files with more
-       lines than needed.
-       If first line doesn't contain a number or contain number less than
-       14 then such file is treated like file from pre 4.1.1 version.
-       There is no ambiguity when reading an old master.info, as before
-       4.1.1, the first line contained the binlog's name, which is either
-       empty or has an extension (contains a '.'), so can't be confused
-       with an integer.
-
-       So we're just reading first line and trying to figure which version
-       is this.
-    */
-
-    /*
-       The first row is temporarily stored in mi->master_log_name,
-       if it is line count and not binlog name (new format) it will be
-       overwritten by the second row later.
-    */
-    if (init_strvar_from_file(mi->master_log_name,
-			      sizeof(mi->master_log_name), &mi->file,
-			      ""))
-      goto errwithmsg;
-
-    lines= strtoul(mi->master_log_name, &first_non_digit, 10);
-
-    if (mi->master_log_name[0]!='\0' &&
-        *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
-    {                                          // Seems to be new format
-      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,
-			      master_host) ||
-	init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
-			      master_user) ||
-        init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
-                              &mi->file, master_password) ||
-	init_intvar_from_file(&port, &mi->file, master_port) ||
-	init_intvar_from_file(&connect_retry, &mi->file,
-			      master_connect_retry))
-      goto errwithmsg;
-
-    /*
-       If file has ssl part use it even if we have server without
-       SSL support. But these option will be ignored later when
-       slave will try connect to master, so in this case warning
-       is printed.
-     */
-    if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
-        (init_intvar_from_file(&ssl, &mi->file, master_ssl) ||
-         init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
-                               &mi->file, master_ssl_ca) ||
-         init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
-                               &mi->file, master_ssl_capath) ||
-         init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
-                               &mi->file, master_ssl_cert) ||
-         init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
-                               &mi->file, master_ssl_cipher) ||
-         init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
-                              &mi->file, master_ssl_key)))
-      goto errwithmsg;
-#ifndef HAVE_OPENSSL
-    if (ssl)
-      sql_print_warning("SSL information in the master info file "
-                      "('%s') are ignored because this MySQL slave was compiled "
-                      "without SSL support.", fname);
-#endif /* HAVE_OPENSSL */
-
-    /*
-      This has to be handled here as init_intvar_from_file can't handle
-      my_off_t types
-    */
-    mi->master_log_pos= (my_off_t) master_log_pos;
-    mi->port= (uint) port;
-    mi->connect_retry= (uint) connect_retry;
-    mi->ssl= (my_bool) ssl;
-  }
-  DBUG_PRINT("master_info",("log_file_name: %s  position: %ld",
-			    mi->master_log_name,
-			    (ulong) mi->master_log_pos));
-
-  mi->rli.mi = mi;
-  if (init_relay_log_info(&mi->rli, slave_info_fname))
-    goto err;
-
-  mi->inited = 1;
-  // now change cache READ -> WRITE - must do this before flush_master_info
-  reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
-  if ((error=test(flush_master_info(mi, 1))))
-    sql_print_error("Failed to flush master info file");
-  pthread_mutex_unlock(&mi->data_lock);
-  DBUG_RETURN(error);
-
-errwithmsg:
-  sql_print_error("Error reading master configuration");
-
-err:
-  if (fd >= 0)
-  {
-    my_close(fd, MYF(0));
-    end_io_cache(&mi->file);
-  }
-  mi->fd= -1;
-  pthread_mutex_unlock(&mi->data_lock);
-  DBUG_RETURN(1);
-}
-
-
 int register_slave_on_master(MYSQL* mysql)
 {
   char buf[1024], *pos= buf;
@@ -1903,56 +948,59 @@
   /* 30 is a good safety margin */
   if (report_host_len + report_user_len + report_password_len + 30 >
       sizeof(buf))
-    return 0;					// safety
+    return 0;                                   // safety
 
   int4store(pos, server_id); pos+= 4;
   pos= net_store_data(pos, report_host, report_host_len); 
   pos= net_store_data(pos, report_user, report_user_len);
   pos= net_store_data(pos, report_password, report_password_len);
   int2store(pos, (uint16) report_port); pos+= 2;
-  int4store(pos, rpl_recovery_rank);	pos+= 4;
+  int4store(pos, rpl_recovery_rank);    pos+= 4;
   /* The master will fill in master_id */
-  int4store(pos, 0);			pos+= 4;
+  int4store(pos, 0);                    pos+= 4;
 
   if (simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf,
-			(uint) (pos- buf), 0))
+                        (uint) (pos- buf), 0))
   {
     sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'",
-		    mysql_errno(mysql),
-		    mysql_error(mysql));
+                    mysql_errno(mysql),
+                    mysql_error(mysql));
     return 1;
   }
   return 0;
 }
 
 
-bool show_master_info(THD* thd, MASTER_INFO* mi)
+bool show_slave_stat(THD* thd, const char* channel)
 {
-  // TODO: fix this for multi-master
+  DBUG_ENTER("show_slave_stat");
+  DBUG_PRINT("enter",("channel: %s", channel));
+  
+  Master_info *mi;
+
   List<Item> field_list;
   Protocol *protocol= thd->protocol;
-  DBUG_ENTER("show_master_info");
 
   field_list.push_back(new Item_empty_string("Slave_IO_State",
-						     14));
+                                                     14));
   field_list.push_back(new Item_empty_string("Master_Host",
-						     sizeof(mi->host)));
+                                                     sizeof(mi->host)));
   field_list.push_back(new Item_empty_string("Master_User",
-						     sizeof(mi->user)));
+                                                     sizeof(mi->user)));
   field_list.push_back(new Item_return_int("Master_Port", 7,
-					   MYSQL_TYPE_LONG));
+                                           MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("Connect_Retry", 10,
-					   MYSQL_TYPE_LONG));
+                                           MYSQL_TYPE_LONG));
   field_list.push_back(new Item_empty_string("Master_Log_File",
-					     FN_REFLEN));
+                                             FN_REFLEN));
   field_list.push_back(new Item_return_int("Read_Master_Log_Pos", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_empty_string("Relay_Log_File",
-					     FN_REFLEN));
+                                             FN_REFLEN));
   field_list.push_back(new Item_return_int("Relay_Log_Pos", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
-					     FN_REFLEN));
+                                             FN_REFLEN));
   field_list.push_back(new Item_empty_string("Slave_IO_Running", 3));
   field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3));
   field_list.push_back(new Item_empty_string("Replicate_Do_DB", 20));
@@ -1961,15 +1009,15 @@
   field_list.push_back(new Item_empty_string("Replicate_Ignore_Table", 23));
   field_list.push_back(new Item_empty_string("Replicate_Wild_Do_Table", 24));
   field_list.push_back(new Item_empty_string("Replicate_Wild_Ignore_Table",
-					     28));
+                                             28));
   field_list.push_back(new Item_return_int("Last_Errno", 4, MYSQL_TYPE_LONG));
   field_list.push_back(new Item_empty_string("Last_Error", 20));
   field_list.push_back(new Item_return_int("Skip_Counter", 10,
-					   MYSQL_TYPE_LONG));
+                                           MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("Exec_Master_Log_Pos", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_return_int("Relay_Log_Space", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_empty_string("Until_Condition", 6));
   field_list.push_back(new Item_empty_string("Until_Log_File", FN_REFLEN));
   field_list.push_back(new Item_return_int("Until_Log_Pos", 10, 
@@ -1992,7 +1040,7 @@
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     DBUG_RETURN(TRUE);
 
-  if (mi->host[0])
+  if ((mi= mic.get_master_info(channel)))
   {
     DBUG_PRINT("info",("host is set: '%s'", mi->host));
     String *packet= &thd->packet;
@@ -2014,8 +1062,8 @@
     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),
-		    &my_charset_bin);
+                    dirname_length(mi->rli.group_relay_log_name),
+                    &my_charset_bin);
     protocol->store((ulonglong) mi->rli.group_relay_log_pos);
     protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
     protocol->store(mi->slave_running ? "Yes":"No", &my_charset_bin);
@@ -2041,8 +1089,8 @@
     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);
@@ -2104,299 +1152,6 @@
   DBUG_RETURN(FALSE);
 }
 
-
-bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
-{
-  IO_CACHE* file = &mi->file;
-  char lbuf[22];
-  DBUG_ENTER("flush_master_info");
-  DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
-
-  /*
-    Flush the relay log to disk. If we don't do it, then the relay log while
-    have some part (its last kilobytes) in memory only, so if the slave server
-    dies now, with, say, from master's position 100 to 150 in memory only (not
-    on disk), and with position 150 in master.info, then when the slave
-    restarts, the I/O thread will fetch binlogs from 150, so in the relay log
-    we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
-    SQL thread will jump from 100 to 150, and replication will silently break.
-
-    When we come to this place in code, relay log may or not be initialized;
-    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
-  */
-  if (flush_relay_log_cache)
-    flush_io_cache(mi->rli.relay_log.get_log_file());
-
-  /*
-    We flushed the relay log BEFORE the master.info file, because if we crash
-    now, we will get a duplicate event in the relay log at restart. If we
-    flushed in the other order, we would get a hole in the relay log.
-    And duplicate is better than hole (with a duplicate, in later versions we
-    can add detection and scrap one event; with a hole there's nothing we can
-    do).
-  */
-
-  /*
-     In certain cases this code may create master.info files that seems 
-     corrupted, because of extra lines filled with garbage in the end 
-     file (this happens if new contents take less space than previous 
-     contents of file). But because of number of lines in the first line 
-     of file we don't care about this garbage.
-  */
-  
-  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",
-	      LINES_IN_MASTER_INFO_WITH_SSL,
-              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);
-  flush_io_cache(file);
-  DBUG_RETURN(0);
-}
-
-
-st_relay_log_info::st_relay_log_info()
-  :info_fd(-1), cur_log_fd(-1), save_temporary_tables(0),
-   cur_log_old_open_count(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), last_slave_errno(0),
-   inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
-   until_log_pos(0), retried_trans(0)
-{
-  group_relay_log_name[0]= event_relay_log_name[0]=
-    group_master_log_name[0]= 0;
-  last_slave_error[0]=0; until_log_name[0]= 0;
-
-  bzero((char*) &info_file, sizeof(info_file));
-  bzero((char*) &cache_buf, sizeof(cache_buf));
-  cached_charset_invalidate();
-  pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
-  pthread_cond_init(&data_cond, NULL);
-  pthread_cond_init(&start_cond, NULL);
-  pthread_cond_init(&stop_cond, NULL);
-  pthread_cond_init(&log_space_cond, NULL);
-  relay_log.init_pthread_objects();
-}
-
-
-st_relay_log_info::~st_relay_log_info()
-{
-  pthread_mutex_destroy(&run_lock);
-  pthread_mutex_destroy(&data_lock);
-  pthread_mutex_destroy(&log_space_lock);
-  pthread_cond_destroy(&data_cond);
-  pthread_cond_destroy(&start_cond);
-  pthread_cond_destroy(&stop_cond);
-  pthread_cond_destroy(&log_space_cond);
-  relay_log.cleanup();
-}
-
-/*
-  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.
-
-  RETURN VALUES
-    -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
-                before reaching the desired log/position
- */
-
-int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
-                                    longlong log_pos,
-                                    longlong timeout)
-{
-  if (!inited)
-    return -1;
-  int event_count = 0;
-  ulong init_abort_pos_wait;
-  int error=0;
-  struct timespec abstime; // for timeout checking
-  const char *msg;
-  DBUG_ENTER("wait_for_pos");
-  DBUG_PRINT("enter",("log_name: '%s'  log_pos: %lu  timeout: %lu",
-                      log_name->c_ptr(), (ulong) log_pos, (ulong) timeout));
-
-  set_timespec(abstime,timeout);
-  pthread_mutex_lock(&data_lock);
-  msg= thd->enter_cond(&data_cond, &data_lock,
-                       "Waiting for the slave SQL thread to "
-                       "advance position");
-  /* 
-     This function will abort when it notices that some CHANGE MASTER or
-     RESET MASTER has changed the master info.
-     To catch this, these commands modify abort_pos_wait ; We just monitor
-     abort_pos_wait and see if it has changed.
-     Why do we have this mechanism instead of simply monitoring slave_running
-     in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that
-     the SQL thread be stopped?
-     This is becasue if someones does:
-     STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE;
-     the change may happen very quickly and we may not notice that
-     slave_running briefly switches between 1/0/1.
-  */
-  init_abort_pos_wait= abort_pos_wait;
-
-  /*
-    We'll need to
-    handle all possible log names comparisons (e.g. 999 vs 1000).
-    We use ulong for string->number conversion ; this is no
-    stronger limitation than in find_uniq_filename in sql/log.cc
-  */
-  ulong log_name_extension;
-  char log_name_tmp[FN_REFLEN]; //make a char[] from String
-
-  strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1));
-
-  char *p= fn_ext(log_name_tmp);
-  char *p_end;
-  if (!*p || log_pos<0)
-  {
-    error= -2; //means improper arguments
-    goto err;
-  }
-  // Convert 0-3 to 4
-  log_pos= max(log_pos, BIN_LOG_HEADER_SIZE);
-  /* p points to '.' */
-  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 means conversion went ok.
-  */
-  if (p_end==p || *p_end)
-  {
-    error= -2;
-    goto err;
-  }    
-
-  /* The "compare and wait" main loop */
-  while (!thd->killed &&
-         init_abort_pos_wait == abort_pos_wait &&
-         slave_running)
-  {
-    bool pos_reached;
-    int cmp_result= 0;
-
-    DBUG_PRINT("info",
-               ("init_abort_pos_wait: %ld  abort_pos_wait: %ld",
-                init_abort_pos_wait, abort_pos_wait));
-    DBUG_PRINT("info",("group_master_log_name: '%s'  pos: %lu",
-                       group_master_log_name, (ulong) group_master_log_pos));
-
-    /*
-      group_master_log_name can be "", if we are just after a fresh
-      replication start or after a CHANGE MASTER TO MASTER_HOST/PORT
-      (before we have executed one Rotate event from the master) or
-      (rare) if the user is doing a weird slave setup (see next
-      paragraph).  If group_master_log_name is "", we assume we don't
-      have enough info to do the comparison yet, so we just wait until
-      more data. In this case master_log_pos is always 0 except if
-      somebody (wrongly) sets this slave to be a slave of itself
-      without using --replicate-same-server-id (an unsupported
-      configuration which does nothing), then group_master_log_pos
-      will grow and group_master_log_name will stay "".
-    */
-    if (*group_master_log_name)
-    {
-      char *basename= (group_master_log_name +
-                       dirname_length(group_master_log_name));
-      /*
-        First compare the parts before the extension.
-        Find the dot in the master's log basename,
-        and protect against user's input error :
-        if the names do not match up to '.' included, return error
-      */
-      char *q= (char*)(fn_ext(basename)+1);
-      if (strncmp(basename, log_name_tmp, (int)(q-basename)))
-      {
-        error= -2;
-        break;
-      }
-      // Now compare extensions.
-      char *q_end;
-      ulong group_master_log_name_extension= strtoul(q, &q_end, 10);
-      if (group_master_log_name_extension < log_name_extension)
-        cmp_result= -1 ;
-      else
-        cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ;
-
-      pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) ||
-                    cmp_result > 0);
-      if (pos_reached || thd->killed)
-        break;
-    }
-
-    //wait for master update, with optional timeout.
-    
-    DBUG_PRINT("info",("Waiting for master update"));
-    /*
-      We are going to pthread_cond_(timed)wait(); if the SQL thread stops it
-      will wake us up.
-    */
-    if (timeout > 0)
-    {
-      /*
-        Note that pthread_cond_timedwait checks for the timeout
-        before for the condition ; i.e. it returns ETIMEDOUT 
-        if the system time equals or exceeds the time specified by abstime
-        before the condition variable is signaled or broadcast, _or_ if
-        the absolute time specified by abstime has already passed at the time
-        of the call.
-        For that reason, pthread_cond_timedwait will do the "timeoutting" job
-        even if its condition is always immediately signaled (case of a loaded
-        master).
-      */
-      error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime);
-    }
-    else
-      pthread_cond_wait(&data_cond, &data_lock);
-    DBUG_PRINT("info",("Got signal of master update or timed out"));
-    if (error == ETIMEDOUT || error == ETIME)
-    {
-      error= -1;
-      break;
-    }
-    error=0;
-    event_count++;
-    DBUG_PRINT("info",("Testing if killed or SQL thread not running"));
-  }
-
-err:
-  thd->exit_cond(msg);
-  DBUG_PRINT("exit",("killed: %d  abort: %d  slave_running: %d \
-improper_arguments: %d  timed_out: %d",
-                     thd->killed_errno(),
-                     (int) (init_abort_pos_wait != abort_pos_wait),
-                     (int) slave_running,
-                     (int) (error == -2),
-                     (int) (error == -1)));
-  if (thd->killed || init_abort_pos_wait != abort_pos_wait ||
-      !slave_running) 
-  {
-    error= -2;
-  }
-  DBUG_RETURN( error ? error : event_count );
-}
-
 void set_slave_thread_options(THD* thd)
 {
   thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) |
@@ -2459,7 +1214,7 @@
 
 #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
   sigset_t set;
-  VOID(sigemptyset(&set));			// Get mask in use
+  VOID(sigemptyset(&set));                      // Get mask in use
   VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
 #endif
 
@@ -2474,7 +1229,7 @@
 
 
 static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
-		      void* thread_killed_arg)
+                      void* thread_killed_arg)
 {
   int nap_time;
   thr_alarm_t alarmed;
@@ -2502,8 +1257,8 @@
 }
 
 
-static int request_dump(MYSQL* mysql, MASTER_INFO* mi,
-			bool *suppress_warnings)
+static int request_dump(MYSQL* mysql, Master_info* mi,
+                        bool *suppress_warnings)
 {
   char buf[FN_REFLEN + 10];
   int len;
@@ -2525,11 +1280,11 @@
       now we just fill up the error log :-)
     */
     if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
-      *suppress_warnings= 1;			// Suppress reconnect warning
+      *suppress_warnings= 1;                    // Suppress reconnect warning
     else
       sql_print_error("Error on COM_BINLOG_DUMP: %d  %s, will retry in %d secs",
-		      mysql_errno(mysql), mysql_error(mysql),
-		      master_connect_retry);
+                      mysql_errno(mysql), mysql_error(mysql),
+                      mi->connect_retry);
     DBUG_RETURN(1);
   }
 
@@ -2571,19 +1326,19 @@
   
   SYNOPSIS
     read_event()
-    mysql		MySQL connection
-    mi			Master connection information
-    suppress_warnings	TRUE when a normal net read timeout has caused us to
-			try a reconnect.  We do not want to print anything to
-			the error log in this case because this a anormal
-			event in an idle server.
+    mysql               MySQL connection
+    mi                  Master connection information
+    suppress_warnings   TRUE when a normal net read timeout has caused us to
+                        try a reconnect.  We do not want to print anything to
+                        the error log in this case because this a anormal
+                        event in an idle server.
 
     RETURN VALUES
-    'packet_error'	Error
-    number		Length of packet
+    'packet_error'      Error
+    number              Length of packet
 */
 
-static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
+static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings)
 {
   ulong len;
 
@@ -2591,11 +1346,9 @@
   /*
     my_real_read() will time us out
     We check if we were told to die, and if not, try reading again
-
-    TODO:  Move 'events_till_disconnect' to the MASTER_INFO structure
   */
 #ifndef DBUG_OFF
-  if (disconnect_slave_event_count && !(events_till_disconnect--))
+  if (disconnect_slave_event_count && !(mi->events_till_disconnect--))
     return packet_error;      
 #endif
   
@@ -2605,34 +1358,36 @@
     if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
     {
       /*
-	We are trying a normal reconnect after a read timeout;
-	we suppress prints to .err file as long as the reconnect
-	happens without problems
+        We are trying a normal reconnect after a read timeout;
+        we suppress prints to .err file as long as the reconnect
+        happens without problems
       */
       *suppress_warnings= TRUE;
     }
     else
-      sql_print_error("Error reading packet from server: %s ( server_errno=%d)",
-		      mysql_error(mysql), mysql_errno(mysql));
+      sql_print_error("I/O:%s:Error reading packet from server: %s "
+                      "(server_errno=%d)",
+                      mi->channel,
+                      mysql_error(mysql), mysql_errno(mysql));
     return packet_error;
   }
 
   /* Check if eof packet */
   if (len < 8 && mysql->net.read_pos[0] == 254)
   {
-    sql_print_information("Slave: received end packet from server, apparent "
+    sql_print_information("I/O:%s:Received end packet from server, apparent "
                           "master shutdown: %s",
-		     mysql_error(mysql));
+                          mi->channel, mysql_error(mysql));
      return packet_error;
   }
   
   DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n",
-		      len, mysql->net.read_pos[4]));
+                      len, mysql->net.read_pos[4]));
   return len - 1;   
 }
 
 
-int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
+int check_expected_error(THD* thd, Relay_log_info* rli, int expected_error)
 {
   switch (expected_error) {
   case ER_NET_READ_ERROR:
@@ -2645,316 +1400,13 @@
   }
 }
 
-/*
-     Check if condition stated in UNTIL clause of START SLAVE is reached.
-   SYNOPSYS
-     st_relay_log_info::is_until_satisfied()
-   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 st_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
-     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::exec_event() (which is 
-     rare, so caching gives real benifit), and if we have 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
-     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
-*/
-
-bool st_relay_log_info::is_until_satisfied()
-{
-  const char *log_name;
-  ulonglong log_pos;
-
-  DBUG_ASSERT(until_condition != UNTIL_NONE);
-  
-  if (until_condition == UNTIL_MASTER_POS)
-  {
-    log_name= group_master_log_name;
-    log_pos= group_master_log_pos;
-  }
-  else
-  { /* until_condition == UNTIL_RELAY_POS */
-    log_name= group_relay_log_name;
-    log_pos= group_relay_log_pos;
-  }
-  
-  if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN)
-  {
-    /*
-      We have no cached comparison results so we should compare log names
-      and cache result.
-      If we are after RESET SLAVE, and the SQL slave thread has not processed
-      any event yet, it could be that group_master_log_name is "". In that case,
-      just wait for more events (as there is no sensible comparison to do).
-    */
-
-    if (*log_name)
-    {
-      const char *basename= log_name + dirname_length(log_name);
-      
-      const char *q= (const char*)(fn_ext(basename)+1);
-      if (strncmp(basename, until_log_name, (int)(q-basename)) == 0)
-      {
-        /* Now compare extensions. */
-        char *q_end;
-        ulong log_name_extension= strtoul(q, &q_end, 10);
-        if (log_name_extension < until_log_name_extension)
-          until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_LESS;
-        else
-          until_log_names_cmp_result= 
-            (log_name_extension > until_log_name_extension) ? 
-            UNTIL_LOG_NAMES_CMP_GREATER : UNTIL_LOG_NAMES_CMP_EQUAL ;
-      }
-      else  
-      {
-        /* Probably error so we aborting */
-        sql_print_error("Slave SQL thread is stopped because UNTIL "
-                        "condition is bad.");
-        return TRUE;
-      }
-    }
-    else
-      return until_log_pos == 0;
-  }
-    
-  return ((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && 
-           log_pos >= until_log_pos) ||
-          until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER);
-}
-
-
-void st_relay_log_info::cached_charset_invalidate()
-{
-  /* Full of zeroes means uninitialized. */
-  bzero(cached_charset, sizeof(cached_charset));
-}
-
-
-bool st_relay_log_info::cached_charset_compare(char *charset)
-{
-  if (bcmp(cached_charset, charset, sizeof(cached_charset)))
-  {
-    memcpy(cached_charset, charset, sizeof(cached_charset));
-    return 1;
-  }
-  return 0;
-}
-
-
-static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
-{
-  /*
-     We acquire this mutex since we need it for all operations except
-     event execution. But we will release it in places where we will
-     wait for something for example inside of next_event().
-   */
-  pthread_mutex_lock(&rli->data_lock);
-
-  if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE &&
-      rli->is_until_satisfied())
-  {
-    sql_print_error("Slave SQL thread stopped because it reached its"
-                    " UNTIL position %ld", (long) rli->until_pos());
-    /*
-      Setting abort_slave flag because we do not want additional message about
-      error in query execution to be printed.
-    */
-    rli->abort_slave= 1;
-    pthread_mutex_unlock(&rli->data_lock);
-    return 1;
-  }
-
-  Log_event * ev = next_event(rli);
-
-  DBUG_ASSERT(rli->sql_thd==thd);
-
-  if (sql_slave_killed(thd,rli))
-  {
-    pthread_mutex_unlock(&rli->data_lock);
-    delete ev;
-    return 1;
-  }
-  if (ev)
-  {
-    int type_code = ev->get_type_code();
-    int exec_res;
-
-    /*
-      Queries originating from this server must be skipped.
-      Low-level events (Format_desc, Rotate, Stop) from this server
-      must also be skipped. But for those we don't want to modify
-      group_master_log_pos, because these events did not exist on the master.
-      Format_desc is not completely skipped.
-      Skip queries specified by the user in slave_skip_counter.
-      We can't however skip events that has something to do with the
-      log files themselves.
-      Filtering on own server id is extremely important, to ignore execution of
-      events created by the creation/rotation of the relay log (remember that
-      now the relay log starts with its Format_desc, has a Rotate etc).
-    */
-
-    DBUG_PRINT("info",("type_code=%d, server_id=%d",type_code,ev->server_id));
-
-    if ((ev->server_id == (uint32) ::server_id &&
-         !replicate_same_server_id &&
-         type_code != FORMAT_DESCRIPTION_EVENT) ||
-        (rli->slave_skip_counter &&
-         type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
-         type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
-    {
-      DBUG_PRINT("info", ("event skipped"));
-      if (thd->options & OPTION_BEGIN)
-        rli->inc_event_relay_log_pos();
-      else
-      {
-        rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
-                                      type_code == STOP_EVENT ||
-                                      type_code == FORMAT_DESCRIPTION_EVENT) ?
-                                     LL(0) : ev->log_pos,
-                                     1/* skip lock*/);
-        flush_relay_log_info(rli);
-      }
-
-      /*
-        Protect against common user error of setting the counter to 1
-        instead of 2 while recovering from an insert which used auto_increment,
-        rand or user var.
-      */
-      if (rli->slave_skip_counter &&
-          !((type_code == INTVAR_EVENT ||
-             type_code == RAND_EVENT ||
-             type_code == USER_VAR_EVENT) &&
-            rli->slave_skip_counter == 1) &&
-          /*
-            The events from ourselves which have something to do with the relay
-            log itself must be skipped, true, but they mustn't decrement
-            rli->slave_skip_counter, because the user is supposed to not see
-            these events (they are not in the master's binlog) and if we
-            decremented, START SLAVE would for example decrement when it sees
-            the Rotate, so the event which the user probably wanted to skip
-            would not be skipped.
-          */
-          !(ev->server_id == (uint32) ::server_id &&
-            (type_code == ROTATE_EVENT || type_code == STOP_EVENT ||
-             type_code == START_EVENT_V3 || type_code == FORMAT_DESCRIPTION_EVENT)))
-        --rli->slave_skip_counter;
-      pthread_mutex_unlock(&rli->data_lock);
-      delete ev;
-      return 0;                                 // avoid infinite update loops
-    }
-    pthread_mutex_unlock(&rli->data_lock);
-
-    thd->server_id = ev->server_id; // use the original server id for logging
-    thd->set_time();				// time the query
-    thd->lex->current_select= 0;
-    if (!ev->when)
-      ev->when = time(NULL);
-    ev->thd = thd;
-    exec_res = ev->exec_event(rli);
-    DBUG_ASSERT(rli->sql_thd==thd);
-    /*
-       Format_description_log_event should not be deleted because it will be
-       used to read info about the relay log's format; it will be deleted when
-       the SQL thread does not need it, i.e. when this thread terminates.
-    */
-    if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
-    {
-      DBUG_PRINT("info", ("Deleting the event after it has been executed"));
-      delete ev;
-    }
-    if (slave_trans_retries)
-    {
-      if (exec_res &&
-          (thd->net.last_errno == ER_LOCK_DEADLOCK ||
-           thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) &&
-          !thd->is_fatal_error)
-      {
-        const char *errmsg;
-        /*
-          We were in a transaction which has been rolled back because of a
-          deadlock (currently, InnoDB deadlock detected by InnoDB) or lock
-          wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to
-          BEGIN log event and retry it all again.
-          We have to not only seek but also
-          a) init_master_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()).
-          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))
-            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))
-            sql_print_error("Error initializing relay log position: %s",
-                            errmsg);
-          else
-          {
-            exec_res= 0;
-	    /* chance for concurrent connection to get more locks */
-            safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
-		       (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);
-            pthread_mutex_lock(&rli->data_lock); // because of SHOW STATUS
-	    rli->trans_retries++;
-            rli->retried_trans++;
-            pthread_mutex_unlock(&rli->data_lock);
-            DBUG_PRINT("info", ("Slave retries transaction "
-                                "rli->trans_retries: %lu", rli->trans_retries));
-	  }
-        }
-        else
-          sql_print_error("Slave SQL thread retried transaction %lu time(s) "
-                          "in vain, giving up. Consider raising the value of "
-                          "the slave_transaction_retries variable.",
-                          slave_trans_retries);
-      }
-      if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
-         rli->trans_retries= 0; // restart from fresh
-     }
-    return exec_res;
-  }
-  else
-  {
-    pthread_mutex_unlock(&rli->data_lock);
-    slave_print_error(rli, 0, "\
-Could not parse relay log event entry. The possible reasons are: the master's \
-binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
-binary log), the slave's relay log is corrupted (you can check this by running \
-'mysqlbinlog' on the relay log), a network problem, or a bug in the master's \
-or slave's MySQL code. If you want to check the master's binary log or slave's \
-relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \
-on this slave.\
-");
-    return 1;
-  }
-}
-
-
 /* Slave I/O Thread entry point */
 
 extern "C" pthread_handler_decl(handle_slave_io,arg)
 {
   THD *thd; // needs to be first for thread_stack
   MYSQL *mysql;
-  MASTER_INFO *mi = (MASTER_INFO*)arg;
+  Master_info *mi = (Master_info*)arg;
   char llbuff[22];
   uint retry_count;
 
@@ -2965,7 +1417,7 @@
 #ifndef DBUG_OFF
 slave_begin:
 #endif
-  DBUG_ASSERT(mi->inited);
+  DBUG_ASSERT(mi->is_inited());
   mysql= NULL ;
   retry_count= 0;
 
@@ -2974,7 +1426,8 @@
   mi->slave_run_id++;
 
 #ifndef DBUG_OFF
-  mi->events_till_abort = abort_slave_event_count;
+  /* Initialize event_till_abort for this subslave */
+  mi->events_till_abort= abort_slave_event_count;
 #endif
 
   thd= new THD; // note that contructor of THD uses DBUG_ !
@@ -2999,8 +1452,8 @@
   pthread_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->master_log_name,
+                            llstr(mi->master_log_pos,llbuff)));
 
   if (!(mi->mysql = mysql = mysql_init(NULL)))
   {
@@ -3011,14 +1464,16 @@
   thd->proc_info = "Connecting to master";
   // we can get killed during safe_connect
   if (!safe_connect(thd, mysql, mi))
-    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));
+    sql_print_information("I/O:%s:Connected to '%s@%s:%d', position '%s:%s'",
+                          mi->channel,
+                          mi->user,
+                          mi->host, mi->port,
+                          IO_RPL_LOG_NAME,
+                          llstr(mi->master_log_pos,llbuff));
   else
   {
-    sql_print_information("Slave I/O thread killed while connecting to master");
+    sql_print_information("I/O:%s:killed while connecting to master",
+                          mi->channel);
     goto err;
   }
 
@@ -3053,9 +1508,9 @@
       sql_print_error("Failed on request_dump()");
       if (io_slave_killed(thd,mi))
       {
-	sql_print_information("Slave I/O thread killed while requesting master \
-dump");
-	goto err;
+        sql_print_information("I/O:%s:killed while requesting master dump",
+                              mi->channel);
+        goto err;
       }
 
       mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
@@ -3065,41 +1520,43 @@
 #endif
       end_server(mysql);
       /*
-	First time retry immediately, assuming that we can recover
-	right away - if first time fails, sleep between re-tries
-	hopefuly the admin can fix the problem sometime
+        First time retry immediately, assuming that we can recover
+        right away - if first time fails, sleep between re-tries
+        hopefuly the admin can fix the problem sometime
       */
       if (retry_count++)
       {
-	if (retry_count > master_retry_count)
-	  goto err;				// Don't retry forever
-	safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-		   (void*)mi);
+        if (retry_count > master_retry_count)
+          goto err;                             // Don't retry forever
+        safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
+                   (void*)mi);
       }
-      if (io_slave_killed(thd,mi))
+      if (io_slave_killed(thd, mi))
       {
-	sql_print_information("Slave I/O thread killed while retrying master \
-dump");
-	goto err;
+        sql_print_information("I/O:%s:Killed while retrying master dump",
+                              mi->channel);
+        goto err;
       }
 
       thd->proc_info = "Reconnecting after a failed binlog dump request";
       if (!suppress_warnings)
-	sql_print_error("Slave I/O thread: failed dump request, \
-reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
-			llstr(mi->master_log_pos,llbuff));
+        sql_print_error("I/O:%s:Failed dump request, "
+                        "reconnecting to retry, position '%s:%s'",
+                        mi->channel,
+                        IO_RPL_LOG_NAME,
+                        llstr(mi->master_log_pos,llbuff));
       if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
-	  io_slave_killed(thd,mi))
+          io_slave_killed(thd,mi))
       {
-	sql_print_information("Slave I/O thread killed during or \
-after reconnect");
-	goto err;
+        sql_print_information("I/O:%s:Killed during or after reconnect",
+                              mi->channel);
+        goto err;
       }
 
       goto connected;
     }
 
-    while (!io_slave_killed(thd,mi))
+    while (!io_slave_killed(thd, mi))
     {
       bool suppress_warnings= 0;
       /*
@@ -3112,74 +1569,81 @@
       ulong event_len = read_event(mysql, mi, &suppress_warnings);
       if (io_slave_killed(thd,mi))
       {
-	if (global_system_variables.log_warnings)
-	  sql_print_information("Slave I/O thread killed while reading event");
-	goto err;
+        if (global_system_variables.log_warnings)
+          sql_print_information("I/O:%s:Killed while reading event",
+                                mi->channel);
+        goto err;
       }
 
       if (event_len == packet_error)
       {
-	uint mysql_error_number= mysql_errno(mysql);
-	if (mysql_error_number == ER_NET_PACKET_TOO_LARGE)
-	{
-	  sql_print_error("\
-Log entry on master is longer than max_allowed_packet (%ld) on \
-slave. If the entry is correct, restart the server with a higher value of \
-max_allowed_packet",
-			  thd->variables.max_allowed_packet);
-	  goto err;
-	}
-	if (mysql_error_number == ER_MASTER_FATAL_ERROR_READING_BINLOG)
-	{
-	  sql_print_error(ER(mysql_error_number), mysql_error_number,
-			  mysql_error(mysql));
-	  goto err;
-	}
+        uint mysql_error_number= mysql_errno(mysql);
+        if (mysql_error_number == ER_NET_PACKET_TOO_LARGE)
+        {
+          sql_print_error("I/O:%s:Log entry on master is longer than "
+                          "max_allowed_packet (%ld) on slave. "
+                          "If the entry is correct, restart the server "
+                          "with a higher value of max_allowed_packet",
+                          mi->channel,
+                          thd->variables.max_allowed_packet);
+          goto err;
+        }
+        if (mysql_error_number == ER_MASTER_FATAL_ERROR_READING_BINLOG)
+        {
+          sql_print_error(ER(mysql_error_number), mysql_error_number,
+                          mysql_error(mysql));
+          goto err;
+        }
         mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
-	thd->proc_info = "Waiting to reconnect after a failed master event read";
+        thd->proc_info = "Waiting to reconnect after a failed master event read";
 #ifdef SIGNAL_WITH_VIO_CLOSE
         thd->clear_active_vio();
 #endif
-	end_server(mysql);
-	if (retry_count++)
-	{
-	  if (retry_count > master_retry_count)
-	    goto err;				// Don't retry forever
-	  safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-		     (void*) mi);
-	}
-	if (io_slave_killed(thd,mi))
-	{
-	  if (global_system_variables.log_warnings)
-	    sql_print_information("Slave I/O thread killed while waiting to \
-reconnect after a failed read");
-	  goto err;
-	}
-	thd->proc_info = "Reconnecting after a failed master event read";
-	if (!suppress_warnings)
-	  sql_print_information("Slave I/O thread: Failed reading log event, \
-reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
-			  llstr(mi->master_log_pos, llbuff));
-	if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
-	    io_slave_killed(thd,mi))
-	{
-	  if (global_system_variables.log_warnings)
-	    sql_print_information("Slave I/O thread killed during or after a \
-reconnect done to recover from failed read");
-	  goto err;
-	}
-	goto connected;
+        end_server(mysql);
+        if (retry_count++)
+        {
+          if (retry_count > master_retry_count)
+            goto err;                           // Don't retry forever
+          safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
+                     (void*) mi);
+        }
+        if (io_slave_killed(thd,mi))
+        {
+          if (global_system_variables.log_warnings)
+            sql_print_information("I/O:%s:Killed while waiting to reconnect "
+                                  "after a failed read",
+                                  mi->channel);
+          goto err;
+        }
+        thd->proc_info = "Reconnecting after a failed master event read";
+        if (!suppress_warnings)
+          sql_print_information("I/O:%s:Failed reading log event, "
+                                "reconnecting to retry, position '%s:%s'", 
+                                mi->channel,
+                                IO_RPL_LOG_NAME,
+                                llstr(mi->master_log_pos, llbuff));
+        if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
+            io_slave_killed(thd,mi))
+        {
+          if (global_system_variables.log_warnings)
+            sql_print_information("I/O:%s:Killed during or after a "
+                                  "reconnect done to recover from failed read",
+                                  mi->channel);
+          goto err;
+        }
+        goto connected;
       } // if (event_len == packet_error)
 
-      retry_count=0;			// ok event, reset retry counter
+      retry_count=0;                    // ok event, reset retry counter
       thd->proc_info = "Queueing master event to the relay log";
       if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
-		      event_len))
+                      event_len))
       {
-	sql_print_error("Slave I/O thread could not queue event from master");
-	goto err;
+        sql_print_error("I/O:%s:Could not queue event from master",
+                        mi->channel);
+        goto err;
       }
-      flush_master_info(mi, 1); /* sure that we can flush the relay log */
+      mi->storage_flush(1); /* sure that we can flush the relay log */
       /*
         See if the relay logs take too much space.
         We don't lock mi->rli.log_space_lock here; this dirty read saves time
@@ -3195,8 +1659,8 @@
 #ifndef DBUG_OFF
       {
         char llbuf1[22], llbuf2[22];
-        DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s \
-ignore_log_space_limit=%d",
+        DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s "
+                            "ignore_log_space_limit=%d",
                             llstr(mi->rli.log_space_limit,llbuf1),
                             llstr(mi->rli.log_space_total,llbuf2),
                             (int) mi->rli.ignore_log_space_limit)); 
@@ -3204,30 +1668,31 @@
 #endif
 
       if (mi->rli.log_space_limit && mi->rli.log_space_limit <
-	  mi->rli.log_space_total &&
+          mi->rli.log_space_total &&
           !mi->rli.ignore_log_space_limit)
-	if (wait_for_relay_log_space(&mi->rli))
-	{
-	  sql_print_error("Slave I/O thread aborted while waiting for relay \
-log space");
-	  goto err;
-	}
-      // TODO: check debugging abort code
+        if (wait_for_relay_log_space(&mi->rli))
+        {
+          sql_print_error("I/O:%s:Thread aborted while waiting for relay "
+                          "log space", mi->channel);
+          goto err;
+        }
 #ifndef DBUG_OFF
-      if (abort_slave_event_count && !--events_till_abort)
+      if (abort_slave_event_count && 0 /*! LARS: --events_till_abort*/)
       {
-	sql_print_error("Slave I/O thread: debugging abort");
-	goto err;
+        sql_print_information("I/O:%s:Forced resurrection of I/O thread "
+                              "(--abort-slave-event-count=%d)",
+                              mi->channel, abort_slave_event_count);
+        goto err;
       }
 #endif
     } 
-  }
+  } 
 
-  // error = 0;
 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));
+  sql_print_information("I/O:%s:Exiting, read up to position '%s:%s'",
+                        mi->channel,
+                        IO_RPL_LOG_NAME, 
+                        llstr(mi->master_log_pos,llbuff));
   VOID(pthread_mutex_lock(&LOCK_thread_count));
   thd->query = thd->db = 0; // extra safety
   thd->query_length= thd->db_length= 0;
@@ -3244,7 +1709,7 @@
   /* Forget the relay log's format */
   delete mi->rli.relay_log.description_event_for_queue;
   mi->rli.relay_log.description_event_for_queue= 0;
-  // TODO: make rpl_status part of MASTER_INFO
+  // TODO: make rpl_status part of Master_info
   change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
   mi->abort_slave = 0; // TODO: check if this is needed
   DBUG_ASSERT(thd->net.buff != 0);
@@ -3253,15 +1718,15 @@
   THD_CHECK_SENTRY(thd);
   delete thd;
   pthread_mutex_unlock(&LOCK_thread_count);
-  pthread_cond_broadcast(&mi->stop_cond);	// tell the world we are done
+  pthread_cond_broadcast(&mi->stop_cond);       // tell the world we are done
   pthread_mutex_unlock(&mi->run_lock);
 #ifndef DBUG_OFF
-  if (abort_slave_event_count && !events_till_abort)
+  if (abort_slave_event_count && !mi->events_till_abort)
     goto slave_begin;
 #endif  
   my_thread_end();
   pthread_exit(0);
-  DBUG_RETURN(0);				// Can't return anything here
+  DBUG_RETURN(0);                               // Can't return anything here
 }
 
 
@@ -3269,9 +1734,10 @@
 
 extern "C" pthread_handler_decl(handle_slave_sql,arg)
 {
-  THD *thd;			/* needs to be first for thread_stack */
+  THD *thd;                     /* needs to be first for thread_stack */
   char llbuff[22],llbuff1[22];
-  RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli; 
+  Master_info* mi= (Master_info*) arg;
+  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
@@ -3282,12 +1748,12 @@
 slave_begin:  
 #endif  
 
-  DBUG_ASSERT(rli->inited);
+  DBUG_ASSERT(rli->is_inited());
   pthread_mutex_lock(&rli->run_lock);
   DBUG_ASSERT(!rli->slave_running);
   errmsg= 0;
 #ifndef DBUG_OFF  
-  rli->events_till_abort = abort_slave_event_count;
+  ((Master_info*)arg)->events_till_abort = abort_slave_event_count;
 #endif  
 
   thd = new THD; // note that contructor of THD uses DBUG_ !
@@ -3305,7 +1771,8 @@
     */
     pthread_cond_broadcast(&rli->start_cond);
     pthread_mutex_unlock(&rli->run_lock);
-    sql_print_error("Failed during slave thread initialization");
+    sql_print_error("SQL:%s:Failed during thread initialization",
+                    mi->channel);
     goto err;
   }
   thd->init_for_queries();
@@ -3337,7 +1804,7 @@
     now.
     But the master timestamp is reset by RESET SLAVE & CHANGE MASTER.
   */
-  clear_slave_error(rli);
+  rli->clear_slave_error();
 
   //tell the I/O thread to take relay_log_space_limit into account from now on
   pthread_mutex_lock(&rli->log_space_lock);
@@ -3345,14 +1812,13 @@
   pthread_mutex_unlock(&rli->log_space_lock);
   rli->trans_retries= 0; // start from "no error"
 
-  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->group_relay_log_name,
+                              rli->group_relay_log_pos,
+                              1 /*need data lock*/, &errmsg,
+                              1 /*look for a description_event*/))
   {
-    sql_print_error("Error initializing relay log position: %s",
-		    errmsg);
+    sql_print_error("SQL:%s:Error initializing relay log position: %s",
+                    mi->channel, errmsg);
     goto err;
   }
   THD_CHECK_SENTRY(thd);
@@ -3383,13 +1849,15 @@
   DBUG_ASSERT(rli->sql_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->group_master_log_name,
+                            llstr(rli->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));
+    sql_print_information("SQL:%s:Started at position '%s:%s', relay '%s:%s'",
+                          rli->mi->channel,
+                          RPL_LOG_NAME, 
+                          llstr(rli->group_master_log_pos,llbuff),
+                          rli->group_relay_log_name,
+                          llstr(rli->group_relay_log_pos,llbuff1));
 
   /* execute init_slave variable */
   if (sys_init_slave.value_length)
@@ -3397,35 +1865,39 @@
     execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave);
     if (thd->query_error)
     {
-      sql_print_error("\
-Slave SQL thread aborted. Can't execute init_slave query");
+      sql_print_error("SQL:%s:Slave SQL thread aborted. "
+                      "Can't execute init_slave query", mi->channel);
       goto err;
     }
   }
 
   /* Read queries from the IO/THREAD until this thread is killed */
 
-  while (!sql_slave_killed(thd,rli))
+  while (!rli->sql_slave_killed(thd))
   {
     thd->proc_info = "Reading event from the relay log";
     DBUG_ASSERT(rli->sql_thd == thd);
     THD_CHECK_SENTRY(thd);
-    if (exec_relay_log_event(thd,rli))
+    if (rli->exec_relay_log_event(thd))
     {
       // do not scare the user if SQL thread was simply killed or stopped
-      if (!sql_slave_killed(thd,rli))
-        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));
+      if (!rli->sql_slave_killed(thd))
+        sql_print_error("SQL:%s:Query execution error, slave SQL thread stopped "
+                        "at position %s:%s. "
+                        "Fix the problem, and restart the slave SQL thread with "
+                        "\"SLAVE START FOR MASTER '%s'\".", 
+                        mi->channel, mi->channel,
+                        RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
       goto err;
     }
   }
 
   /* 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));
+  sql_print_information("SQL:%s:Exiting, replication stopped at "
+                        "position '%s:%s'",
+                        mi->channel,
+                        RPL_LOG_NAME, 
+                        llstr(rli->group_master_log_pos,llbuff));
 
  err:
   VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -3449,7 +1921,9 @@
   rli->relay_log.description_event_for_exec= 0;
   /* Wake up master_pos_wait() */
   pthread_mutex_unlock(&rli->data_lock);
-  DBUG_PRINT("info",("Signaling possibly waiting master_pos_wait() functions"));
+  DBUG_PRINT("info",("SQL:%s:Signaling possibly waiting master_pos_wait() "
+                     "functions",
+                     rli->mi->channel));
   pthread_cond_broadcast(&rli->data_cond);
   rli->ignore_log_space_limit= 0; /* don't need any lock */
   /* we die so won't remember charset - re-update them on next thread start */
@@ -3474,12 +1948,12 @@
   // tell the world we are done
   pthread_mutex_unlock(&rli->run_lock);
 #ifndef DBUG_OFF // TODO: reconsider the code below
-  if (abort_slave_event_count && !rli->events_till_abort)
+  if (abort_slave_event_count && !((Master_info*)arg)->events_till_abort)
     goto slave_begin;
 #endif  
   my_thread_end();
   pthread_exit(0);
-  DBUG_RETURN(0);				// Can't return anything here
+  DBUG_RETURN(0);                               // Can't return anything here
 }
 
 
@@ -3487,7 +1961,7 @@
   process_io_create_file()
 */
 
-static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
+static int process_io_create_file(Master_info* mi, Create_file_log_event* cev)
 {
   int error = 1;
   ulong num_bytes;
@@ -3511,8 +1985,8 @@
   
   if (unlikely(net_request_file(net,cev->fname)))
   {
-    sql_print_error("Slave I/O: failed requesting download of '%s'",
-		    cev->fname);
+    sql_print_error("I/O:%s:Failed requesting download of '%s'",
+                    mi->channel, cev->fname);
     goto err;
   }
 
@@ -3528,13 +2002,13 @@
     {
       if (unlikely((num_bytes=my_net_read(net)) == packet_error))
       {
-	sql_print_error("Network read error downloading '%s' from master",
-			cev->fname);
-	goto err;
+        sql_print_error("I/O:%s:Network read error downloading '%s' "
+                        "from master", mi->channel, cev->fname);
+        goto err;
       }
       if (unlikely(!num_bytes)) /* eof */
       {
-	net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
+        net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
         /*
           If we wrote Create_file_log_event, then we need to write
           Execute_load_log_event. If we did not write Create_file_log_event,
@@ -3542,43 +2016,43 @@
           INFILE had not existed, i.e. write nothing.
         */
         if (unlikely(cev_not_written))
-	  break;
-	Execute_load_log_event xev(thd,0,0);
-	xev.log_pos = cev->log_pos;
-	if (unlikely(mi->rli.relay_log.append(&xev)))
-	{
-	  sql_print_error("Slave I/O: error writing Exec_load event to \
-relay log");
-	  goto err;
-	}
-	mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
-	break;
+          break;
+        Execute_load_log_event xev(thd,0,0);
+        xev.log_pos = cev->log_pos;
+        if (unlikely(mi->rli.relay_log.append(&xev)))
+        {
+          sql_print_error("I/O:%s:Error writing Exec_load event to "
+                          "relay log", mi->channel);
+          goto err;
+        }
+        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        break;
       }
       if (unlikely(cev_not_written))
       {
-	cev->block = (char*)net->read_pos;
-	cev->block_len = num_bytes;
-	if (unlikely(mi->rli.relay_log.append(cev)))
-	{
-	  sql_print_error("Slave I/O: error writing Create_file event to \
-relay log");
-	  goto err;
-	}
-	cev_not_written=0;
-	mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        cev->block = (char*)net->read_pos;
+        cev->block_len = num_bytes;
+        if (unlikely(mi->rli.relay_log.append(cev)))
+        {
+          sql_print_error("I/O:%s:Error writing Create_file event to "
+                          "relay log", mi->channel);
+          goto err;
+        }
+        cev_not_written=0;
+        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
       }
       else
       {
-	aev.block = (char*)net->read_pos;
-	aev.block_len = num_bytes;
-	aev.log_pos = cev->log_pos;
-	if (unlikely(mi->rli.relay_log.append(&aev)))
-	{
-	  sql_print_error("Slave I/O: error writing Append_block event to \
-relay log");
-	  goto err;
-	}
-	mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ;
+        aev.block = (char*)net->read_pos;
+        aev.block_len = num_bytes;
+        aev.log_pos = cev->log_pos;
+        if (unlikely(mi->rli.relay_log.append(&aev)))
+        {
+          sql_print_error("I/O:%s:Error writing Append_block event to "
+                          "relay log", mi->channel);
+          goto err;
+        }
+        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ;
       }
     }
   }
@@ -3593,8 +2067,8 @@
 
   SYNOPSIS
     process_io_rotate()
-    mi			master_info for the slave
-    rev			The rotate log event read from the binary log
+    mi                  master_info for the slave
+    rev                 The rotate log event read from the binary log
 
   DESCRIPTION
     Updates the master info with the place in the next binary
@@ -3605,12 +2079,12 @@
     We assume we already locked mi->data_lock
 
   RETURN VALUES
-    0		ok
-    1	        Log event is illegal
+    0           ok
+    1           Log event is illegal
 
 */
 
-static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
+static int process_io_rotate(Master_info *mi, Rotate_log_event *rev)
 {
   DBUG_ENTER("process_io_rotate");
   safe_mutex_assert_owner(&mi->data_lock);
@@ -3621,14 +2095,14 @@
   memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
   mi->master_log_pos= rev->pos;
   DBUG_PRINT("info", ("master_log_pos: '%s' %d",
-		      mi->master_log_name, (ulong) mi->master_log_pos));
+                      mi->master_log_name, (ulong) mi->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)
-    events_till_disconnect++;
+    mi->events_till_disconnect++;
 #endif
 
   /*
@@ -3657,14 +2131,14 @@
   Reads a 3.23 event and converts it to the slave's format. This code was
   copied from MySQL 4.0.
 */
-static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
-			   ulong event_len)
+static int queue_binlog_ver_1_event(Master_info *mi, const char *buf,
+                           ulong event_len)
 {
   const char *errmsg = 0;
   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");
 
   /*
@@ -3675,7 +2149,8 @@
   {
     if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
     {
-      sql_print_error("Slave I/O: out of memory for Load event");
+      sql_print_error("I/O:%s:Out of memory for Load event",
+                      mi->channel);
       DBUG_RETURN(1);
     }
     memcpy(tmp_buf,buf,event_len);
@@ -3693,16 +2168,18 @@
   /*
     This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to
     send the loaded file, and write it to the relay log in the form of
-    Append_block/Exec_load (the SQL thread needs the data, as that thread is not
-    connected to the master).
+    Append_block/Exec_load (the SQL thread needs the data, as that thread is 
+    not connected to the master).
   */
-  Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
-                                            mi->rli.relay_log.description_event_for_queue);
+  Log_event *ev = 
+    Log_event::read_log_event(buf,event_len, &errmsg,
+                              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);
+    sql_print_error("I/O:%s:Read invalid event from master: '%s', "
+                    "master could be corrupt but a more likely cause "
+                    "of this is a bug",
+                    mi->channel, errmsg);
     my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
     DBUG_RETURN(1);
   }
@@ -3773,13 +2250,13 @@
   Reads a 4.0 event and converts it to the slave's format. This code was copied
   from queue_binlog_ver_1_event(), with some affordable simplifications.
 */
-static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf,
-			   ulong event_len)
+static int queue_binlog_ver_3_event(Master_info *mi, const char *buf,
+                           ulong event_len)
 {
   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 */
@@ -3787,9 +2264,9 @@
                                             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);
+    sql_print_error("I/O:%s:Read invalid event from master: '%s',"
+                    "master could be corrupt but a more likely cause of this is a bug",
+                    mi->channel, errmsg);
     my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
     DBUG_RETURN(1);
   }
@@ -3837,8 +2314,8 @@
     setup with 3.23 master or 4.0 master
 */
 
-static int queue_old_event(MASTER_INFO *mi, const char *buf,
-			   ulong event_len)
+static int queue_old_event(Master_info *mi, const char *buf,
+                           ulong event_len)
 {
   switch (mi->rli.relay_log.description_event_for_queue->binlog_version)
   {
@@ -3863,11 +2340,11 @@
   any >=5.0.0 format.
 */
 
-int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
+int queue_event(Master_info* mi,const char* buf, ulong event_len)
 {
   int error= 0;
   ulong inc_pos;
-  RELAY_LOG_INFO *rli= &mi->rli;
+  Relay_log_info *rli= &mi->rli;
   DBUG_ENTER("queue_event");
 
   if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
@@ -4003,51 +2480,21 @@
 }
 
 
-void end_relay_log_info(RELAY_LOG_INFO* rli)
-{
-  DBUG_ENTER("end_relay_log_info");
-
-  if (!rli->inited)
-    DBUG_VOID_RETURN;
-  if (rli->info_fd >= 0)
-  {
-    end_io_cache(&rli->info_file);
-    (void) my_close(rli->info_fd, MYF(MY_WME));
-    rli->info_fd = -1;
-  }
-  if (rli->cur_log_fd >= 0)
-  {
-    end_io_cache(&rli->cache_buf);
-    (void)my_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
-  }
-  rli->inited = 0;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  rli->relay_log.harvest_bytes_written(&rli->log_space_total);
-  /*
-    Delete the slave's temporary tables from memory.
-    In the future there will be other actions than this, to ensure persistance
-    of slave's temp tables after shutdown.
-  */
-  rli->close_temporary_tables();
-  DBUG_VOID_RETURN;
-}
-
 /*
   Try to connect until successful or slave killed
 
   SYNPOSIS
     safe_connect()
-    thd			Thread handler for slave
-    mysql		MySQL connection handle
-    mi			Replication handle
+    thd                 Thread handler for slave
+    mysql               MySQL connection handle
+    mi                  Replication handle
 
   RETURN
-    0	ok
-    #	Error
+    0   ok
+    #   Error
 */
 
-static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi)
 {
   return connect_to_master(thd, mysql, mi, 0, 0);
 }
@@ -4062,21 +2509,21 @@
     master_retry_count times
 */
 
-static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			     bool reconnect, bool suppress_warnings)
+static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
+                             bool reconnect, bool suppress_warnings)
 {
   int slave_was_killed;
-  int last_errno= -2;				// impossible error
+  int last_errno= -2;                           // impossible error
   ulong err_count=0;
   char llbuff[22];
   DBUG_ENTER("connect_to_master");
 
 #ifndef DBUG_OFF
-  events_till_disconnect = disconnect_slave_event_count;
+  mi->events_till_disconnect = disconnect_slave_event_count;
 #endif
   ulong client_flag= CLIENT_REMEMBER_OPTIONS;
   if (opt_slave_compressed_protocol)
-    client_flag=CLIENT_COMPRESS;		/* We will use compression */
+    client_flag=CLIENT_COMPRESS;                /* We will use compression */
 
   mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
   mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
@@ -4096,23 +2543,23 @@
   mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
 
   while (!(slave_was_killed = io_slave_killed(thd,mi)) &&
-	 (reconnect ? mysql_reconnect(mysql) != 0 :
-	  mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
-			     mi->port, 0, client_flag) == 0))
+         (reconnect ? mysql_reconnect(mysql) != 0 :
+          mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
+                             mi->port, 0, client_flag) == 0))
   {
     /* Don't repeat last error */
     if ((int)mysql_errno(mysql) != last_errno)
     {
       last_errno=mysql_errno(mysql);
       suppress_warnings= 0;
-      sql_print_error("Slave I/O thread: error %s to master \
-'%s@%s:%d': \
-Error: '%s'  errno: %d  retry-time: %d  retries: %d",
-		      (reconnect ? "reconnecting" : "connecting"),
-		      mi->user,mi->host,mi->port,
-		      mysql_error(mysql), last_errno,
-		      mi->connect_retry,
-		      master_retry_count);
+      sql_print_error("I/O:%s:Error %s to master '%s@%s:%d': "
+                      "Error: '%s'  errno: %d  retry-time: %d  retries: %d",
+                      mi->channel,
+                      (reconnect ? "reconnecting" : "connecting"),
+                      mi->user,mi->host,mi->port,
+                      mysql_error(mysql), last_errno,
+                      mi->connect_retry,
+                      master_retry_count);
     }
     /*
       By default we try forever. The reason is that failure will trigger
@@ -4128,7 +2575,7 @@
       break;
     }
     safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-	       (void*)mi);
+               (void*)mi);
   }
 
   if (!slave_was_killed)
@@ -4136,17 +2583,19 @@
     if (reconnect)
     { 
       if (!suppress_warnings && global_system_variables.log_warnings)
-	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));
+        sql_print_information("I/O:%s:Connected to master '%s@%s:%d', "
+                              "replication resumed at position '%s:%s'", 
+                              mi->channel,
+                              mi->user,
+                              mi->host, mi->port,
+                              IO_RPL_LOG_NAME,
+                              llstr(mi->master_log_pos,llbuff));
     }
     else
     {
       change_rpl_status(RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE);
       mysql_log.write(thd, COM_CONNECT_OUT, "%s@%s:%d",
-		      mi->user, mi->host, mi->port);
+                      mi->user, mi->host, mi->port);
     }
 #ifdef SIGNAL_WITH_VIO_CLOSE
     thd->set_active_vio(mysql->net.vio);
@@ -4166,415 +2615,35 @@
     master_retry_count times
 */
 
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			  bool suppress_warnings)
+static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi,
+                          bool suppress_warnings)
 {
   DBUG_ENTER("safe_reconnect");
   DBUG_RETURN(connect_to_master(thd, mysql, mi, 1, suppress_warnings));
 }
 
 
-/*
-  Store the file and position where the execute-slave thread are in the
-  relay log.
-
-  SYNOPSIS
-    flush_relay_log_info()
-    rli			Relay log information
-
-  NOTES
-    - As this is only called by the slave thread, we don't need to
-      have a lock on this.
-    - If there is an active transaction, then we don't update the position
-      in the relay log.  This is to ensure that we re-execute statements
-      if we die in the middle of an transaction that was rolled back.
-    - As a transaction never spans binary logs, we don't have to handle the
-      case where we do a relay-log-rotation in the middle of the transaction.
-      If this would not be the case, we would have to ensure that we
-      don't delete the relay log file where the transaction started when
-      we switch to a new relay log file.
-
-  TODO
-    - Change the log file information to a binary format to avoid calling
-      longlong2str.
-
-  RETURN VALUES
-    0	ok
-    1	write error
-*/
-
-bool flush_relay_log_info(RELAY_LOG_INFO* rli)
-{
-  bool error=0;
-  IO_CACHE *file = &rli->info_file;
-  char buff[FN_REFLEN*2+22*2+4], *pos;
-
-  my_b_seek(file, 0L);
-  pos=strmov(buff, rli->group_relay_log_name);
-  *pos++='\n';
-  pos=longlong2str(rli->group_relay_log_pos, pos, 10);
-  *pos++='\n';
-  pos=strmov(pos, rli->group_master_log_name);
-  *pos++='\n';
-  pos=longlong2str(rli->group_master_log_pos, pos, 10);
-  *pos='\n';
-  if (my_b_write(file, (byte*) buff, (ulong) (pos-buff)+1))
-    error=1;
-  if (flush_io_cache(file))
-    error=1;
-  /* Flushing the relay log is done by the slave I/O thread */
-  return error;
-}
-
-
-/*
-  Called when we notice that the current "hot" log got rotated under our feet.
-*/
-
-static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
+void rotate_all_relay_logs() 
 {
-  DBUG_ASSERT(rli->cur_log != &rli->cache_buf);
-  DBUG_ASSERT(rli->cur_log_fd == -1);
-  DBUG_ENTER("reopen_relay_log");
-
-  IO_CACHE *cur_log = rli->cur_log=&rli->cache_buf;
-  if ((rli->cur_log_fd=open_binlog(cur_log,rli->event_relay_log_name,
-				   errmsg)) <0)
-    DBUG_RETURN(0);
-  /*
-    We want to start exactly where we was before:
-    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);
-  DBUG_RETURN(cur_log);
-}
-
-
-Log_event* next_event(RELAY_LOG_INFO* rli)
-{
-  Log_event* ev;
-  IO_CACHE* cur_log = rli->cur_log;
-  pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); 
-  const char* errmsg=0;
-  THD* thd = rli->sql_thd;
-  
-  DBUG_ENTER("next_event");
-  DBUG_ASSERT(thd != 0);
-
-  /*
-    For most operations we need to protect rli members with data_lock,
-    so we assume calling function acquired this mutex for us and we will
-    hold it for the most of the loop below However, we will release it
-    whenever it is worth the hassle,  and in the cases when we go into a
-    pthread_cond_wait() with the non-data_lock mutex
-  */
-  safe_mutex_assert_owner(&rli->data_lock);
-  
-  while (!sql_slave_killed(thd,rli))
-  {
-    /*
-      We can have two kinds of log reading:
-      hot_log:
-        rli->cur_log points at the IO_CACHE of relay_log, which
-        is actively being updated by the I/O thread. We need to be careful
-        in this case and make sure that we are not looking at a stale log that
-        has already been rotated. If it has been, we reopen the log.
-
-      The other case is much simpler:
-        We just have a read only log that nobody else will be updating.
-    */
-    bool hot_log;
-    if ((hot_log = (cur_log != &rli->cache_buf)))
-    {
-      DBUG_ASSERT(rli->cur_log_fd == -1); // foreign descriptor
-      pthread_mutex_lock(log_lock);
-
-      /*
-	Reading xxx_file_id is safe because the log will only
-	be rotated when we hold relay_log.LOCK_log
-      */
-      if (rli->relay_log.get_open_count() != rli->cur_log_old_open_count)
-      {
-	// The master has switched to a new log file; Reopen the old log file
-	cur_log=reopen_relay_log(rli, &errmsg);
-	pthread_mutex_unlock(log_lock);
-	if (!cur_log)				// No more log files
-	  goto err;
-	hot_log=0;				// Using old binary log
-      }
-    }
-
-#ifndef DBUG_OFF
-    {
-      /* 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)));
-      DBUG_ASSERT(my_b_tell(cur_log) >= BIN_LOG_HEADER_SIZE);
-      DBUG_ASSERT(my_b_tell(cur_log) == rli->event_relay_log_pos);
-    }
-#endif
-    /*
-      Relay log is always in new format - if the master is 3.23, the
-      I/O thread will convert the format for us.
-      A problem: the description event may be in a previous relay log. So if
-      the slave has been shutdown meanwhile, we would have to look in old relay
-      logs, which may even have been deleted. So we need to write this
-      description event at the beginning of the relay log.
-      When the relay log is created when the I/O thread starts, easy: the
-      master will send the description event and we will queue it.
-      But if the relay log is created by new_file(): then the solution is:
-      MYSQL_LOG::open() will write the buffered description event.
-    */
-    if ((ev=Log_event::read_log_event(cur_log,0,
-                                      rli->relay_log.description_event_for_exec)))
-
-    {
-      DBUG_ASSERT(thd==rli->sql_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);
-      if (hot_log)
-	pthread_mutex_unlock(log_lock);
-      DBUG_RETURN(ev);
-    }
-    DBUG_ASSERT(thd==rli->sql_thd);
-    if (opt_reckless_slave)			// For mysql-test
-      cur_log->error = 0;
-    if (cur_log->error < 0)
-    {
-      errmsg = "slave SQL thread aborted because of I/O error";
-      if (hot_log)
-	pthread_mutex_unlock(log_lock);
-      goto err;
-    }
-    if (!cur_log->error) /* EOF */
-    {
-      /*
-	On a hot log, EOF means that there are no more updates to
-	process and we must block until I/O thread adds some and
-	signals us to continue
-      */
-      if (hot_log)
-      {
-        /*
-          We say in Seconds_Behind_Master that we have "caught up". Note that
-          for example if network link is broken but I/O slave thread hasn't
-          noticed it (slave_net_timeout not elapsed), then we'll say "caught
-          up" whereas we're not really caught up. Fixing that would require
-          internally cutting timeout in smaller pieces in network read, no
-          thanks. Another example: SQL has caught up on I/O, now I/O has read
-          a new event and is queuing it; the false "0" will exist until SQL
-          finishes executing the new event; it will be look abnormal only if
-          the events have old timestamps (then you get "many", 0, "many").
-          Transient phases like this can't really be fixed.
-        */
-        time_t save_timestamp= rli->last_master_timestamp;
-        rli->last_master_timestamp= 0;
-
-	DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count);
-	/*
-	  We can, and should release data_lock while we are waiting for
-	  update. If we do not, show slave status will block
-	*/
-	pthread_mutex_unlock(&rli->data_lock);
-
-        /*
-          Possible deadlock : 
-          - the I/O thread has reached log_space_limit
-          - the SQL thread has read all relay logs, but cannot purge for some
-          reason:
-            * it has already purged all logs except the current one
-            * there are other logs than the current one but they're involved in
-            a transaction that finishes in the current one (or is not finished)
-          Solution :
-          Wake up the possibly waiting I/O thread, and set a boolean asking
-          the I/O thread to temporarily ignore the log_space_limit
-          constraint, because we do not want the I/O thread to block because of
-          space (it's ok if it blocks for any other reason (e.g. because the
-          master does not send anything). Then the I/O thread stops waiting 
-          and reads more events.
-          The SQL thread decides when the I/O thread should take log_space_limit
-          into account again : ignore_log_space_limit is reset to 0 
-          in purge_first_log (when the SQL thread purges the just-read relay
-          log), and also when the SQL thread starts. We should also reset
-          ignore_log_space_limit to 0 when the user does RESET SLAVE, but in
-          fact, no need as RESET SLAVE requires that the slave
-          be stopped, and the SQL thread sets ignore_log_space_limit to 0 when
-          it stops.
-        */
-        pthread_mutex_lock(&rli->log_space_lock);
-        // prevent the I/O thread from blocking next times
-        rli->ignore_log_space_limit= 1; 
-        /*
-          If the I/O thread is blocked, unblock it.
-          Ok to broadcast after unlock, because the mutex is only destroyed in
-          ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be
-          destroyed before we exit the present function.
-        */
-        pthread_mutex_unlock(&rli->log_space_lock);
-        pthread_cond_broadcast(&rli->log_space_cond);
-        // Note that wait_for_update unlocks lock_log !
-        rli->relay_log.wait_for_update(rli->sql_thd, 1);
-        // re-acquire data lock since we released it earlier
-        pthread_mutex_lock(&rli->data_lock);
-        rli->last_master_timestamp= save_timestamp;
-	continue;
-      }
-      /*
-	If the log was not hot, we need to move to the next log in
-	sequence. The next log could be hot or cold, we deal with both
-	cases separately after doing some common initialization
-      */
-      end_io_cache(cur_log);
-      DBUG_ASSERT(rli->cur_log_fd >= 0);
-      my_close(rli->cur_log_fd, MYF(MY_WME));
-      rli->cur_log_fd = -1;
-	
-      if (relay_log_purge)
-      {
-	/*
-          purge_first_log will properly set up relay log coordinates in rli.
-          If the group's coordinates are equal to the event's coordinates
-          (i.e. the relay log was not rotated in the middle of a group),
-          we can purge this relay log too.
-          We do ulonglong and string comparisons, this may be slow but
-          - purging the last relay log is nice (it can save 1GB of disk), so we
-          like to detect the case where we can do it, and given this,
-          - I see no better detection method
-          - purge_first_log is not called that often
-        */
-	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)))
-	{
-	  errmsg = "Error purging processed logs";
-	  goto err;
-	}
-      }
-      else
-      {
-	/*
-	  If hot_log is set, then we already have a lock on
-	  LOCK_log.  If not, we have to get the lock.
-
-	  According to Sasha, the only time this code will ever be executed
-	  is if we are recovering from a bug.
-	*/
-	if (rli->relay_log.find_next_log(&rli->linfo, !hot_log))
-	{
-	  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);
-      }
-
-      /*
-        Now we want to open this next log. To know if it's a hot log (the one
-        being written by the I/O thread now) or a cold log, we can use
-        is_active(); if it is hot, we use the I/O cache; if it's cold we open
-        the file normally. But if is_active() reports that the log is hot, this
-        may change between the test and the consequence of the test. So we may
-        open the I/O cache whereas the log is now cold, which is nonsense.
-        To guard against this, we need to have LOCK_log.
-      */
-
-      DBUG_PRINT("info",("hot_log: %d",hot_log));
-      if (!hot_log) /* if hot_log, we already have this mutex */
-        pthread_mutex_lock(log_lock);
-      if (rli->relay_log.is_active(rli->linfo.log_file_name))
-      {
-#ifdef EXTRA_DEBUG
-	if (global_system_variables.log_warnings)
-	  sql_print_information("next log '%s' is currently active",
-                                rli->linfo.log_file_name);
-#endif	  
-	rli->cur_log= cur_log= rli->relay_log.get_log_file();
-	rli->cur_log_old_open_count= rli->relay_log.get_open_count();
-	DBUG_ASSERT(rli->cur_log_fd == -1);
-	  
-	/*
-	  Read pointer has to be at the start since we are the only
-	  reader.
-          We must keep the LOCK_log to read the 4 first bytes, as this is a hot
-          log (same as when we call read_log_event() above: for a hot log we
-          take the mutex).
-	*/
-	if (check_binlog_magic(cur_log,&errmsg))
-        {
-          if (!hot_log) pthread_mutex_unlock(log_lock);
-	  goto err;
-        }
-        if (!hot_log) pthread_mutex_unlock(log_lock);
-	continue;
-      }
-      if (!hot_log) pthread_mutex_unlock(log_lock);
-      /*
-	if we get here, the log was not hot, so we will have to open it
-	ourselves. We are sure that the log is still not hot now (a log can get
-	from hot to cold, but not from cold to hot). No need for LOCK_log.
-      */
-#ifdef EXTRA_DEBUG
-      if (global_system_variables.log_warnings)
-	sql_print_information("next log '%s' is not active",
-                              rli->linfo.log_file_name);
-#endif	  
-      // open_binlog() will check the magic header
-      if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
-				       &errmsg)) <0)
-	goto err;
-    }
-    else
-    {
-      /*
-	Read failed with a non-EOF error.
-	TODO: come up with something better to handle this error
-      */
-      if (hot_log)
-	pthread_mutex_unlock(log_lock);
-      sql_print_error("Slave SQL thread: I/O error reading \
-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);
-      /* otherwise, we have had a partial read */
-      errmsg = "Aborting slave SQL thread because of partial event read";
-      break;					// To end of function
-    }
-  }
-  if (!errmsg && global_system_variables.log_warnings)
+  DBUG_ENTER("rotate_all_relay_logs");
+  Master_info *mi;
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
   {
-    sql_print_information("Error reading relay log event: %s", 
-                          "slave SQL thread was killed");
-    DBUG_RETURN(0);
+    rotate_relay_log(mi);
   }
-
-err:
-  if (errmsg)
-    sql_print_error("Error reading relay log event: %s", errmsg);
-  DBUG_RETURN(0);
 }
 
+
 /*
   Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
   because of size is simpler because when we do it we already have all relevant
   locks; here we don't, so this function is mainly taking locks). 
   Returns nothing as we cannot catch any error (MYSQL_LOG::new_file() is void).
 */
-
-void rotate_relay_log(MASTER_INFO* mi)
+void rotate_relay_log(Master_info *mi)
 {
   DBUG_ENTER("rotate_relay_log");
-  RELAY_LOG_INFO* rli= &mi->rli;
+  Relay_log_info* rli= &mi->rli;
 
   /* We don't lock rli->run_lock. This would lead to deadlocks. */
   pthread_mutex_lock(&mi->run_lock);
@@ -4583,9 +2652,9 @@
      We need to test inited because otherwise, new_file() will attempt to lock
      LOCK_log, which may not be inited (if we're not a slave).
   */
-  if (!rli->inited)
+  if (!rli->is_inited())
   {
-    DBUG_PRINT("info", ("rli->inited == 0"));
+    DBUG_PRINT("info", ("rli->is_inited() == 0"));
     goto end;
   }
 

--- 1.36/sql/sql_acl.h	Fri Apr  1 22:32:05 2005
+++ 1.37/sql/sql_acl.h	Mon Apr 25 23:34:23 2005
@@ -14,7 +14,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
-#include "slave.h" // for tables_ok(), rpl_filter
+#include <rpl/slave.h> // for tables_ok(), rpl_filter
 
 #define SELECT_ACL	(1L << 0)
 #define INSERT_ACL	(1L << 1)

--- 1.164/sql/sql_class.cc	Mon Apr 25 23:21:24 2005
+++ 1.165/sql/sql_class.cc	Mon Apr 25 23:34:23 2005
@@ -161,7 +161,8 @@
   :user_time(0), global_read_lock(0), is_fatal_error(0),
    rand_used(0), time_zone_used(0),
    last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
-   in_lock_tables(0), bootstrap(0), spcont(NULL)
+   in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
+   spcont(NULL)
 {
   current_arena= this;
 #ifndef DBUG_OFF
@@ -193,6 +194,7 @@
   variables.pseudo_thread_id= 0;
   one_shot_set= 0;
   file_id = 0;
+  query_id= 0;
   warn_id= 0;
   db_charset= global_system_variables.collation_database;
   bzero(ha_data, sizeof(ha_data));
@@ -200,10 +202,11 @@
 #ifndef DBUG_OFF
   dbug_sentry=THD_SENTRY_MAGIC;
 #endif
-#ifndef EMBEDDED_LIBRARY  
+#ifndef EMBEDDED_LIBRARY
   net.vio=0;
 #endif
-  net.last_error[0]=0;				// If error on boot
+  net.last_error[0]=0;                          // If error on boot
+  net.query_cache_query=0;                      // If error on boot
   ull=0;
   system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0;
   peer_port= 0;					// For SHOW PROCESSLIST
@@ -212,7 +215,7 @@
 #endif
 #ifdef SIGNAL_WITH_VIO_CLOSE
   active_vio = 0;
-#endif  
+#endif
   pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
 
   /* Variables with default values */
@@ -342,7 +345,10 @@
 void THD::cleanup(void)
 {
   DBUG_ENTER("THD::cleanup");
-  ha_rollback(this);
+#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
+  if (transaction.xa_state != XA_PREPARED)
+#endif
+    ha_rollback(this);
   if (locked_tables)
   {
     lock=locked_tables; locked_tables=0;
@@ -384,17 +390,17 @@
   add_to_status(&global_status_var, &status_var);
 
   /* Close connection */
-#ifndef EMBEDDED_LIBRARY  
+#ifndef EMBEDDED_LIBRARY
   if (net.vio)
   {
     vio_delete(net.vio);
-    net_end(&net); 
+    net_end(&net);
   }
 #endif
   if (!cleanup_done)
     cleanup();
 
-    ha_close_connection(this);
+  ha_close_connection(this);
 
   sp_cache_clear(&sp_proc_cache);
   sp_cache_clear(&sp_func_cache);

--- 1.232/sql/sql_class.h	Tue Apr 19 11:07:39 2005
+++ 1.233/sql/sql_class.h	Mon Apr 25 23:34:24 2005
@@ -14,6 +14,8 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+#ifndef SQL_CLASS_H
+#define SQL_CLASS_H
 
 /* Classes in mysql */
 
@@ -29,6 +31,7 @@
 class Format_description_log_event;
 class sp_rcontext;
 class sp_cache;
+class THD;
 
 enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
 enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
@@ -152,7 +155,7 @@
 #define LOG_CLOSE_TO_BE_OPENED	2
 #define LOG_CLOSE_STOP_EVENT	4
 
-struct st_relay_log_info;
+class Relay_log_info;
 
 typedef struct st_log_info
 {
@@ -332,7 +335,7 @@
                  bool need_mutex, bool need_update_threads,
                  ulonglong *decrease_log_space);
   int purge_logs_before_date(time_t purge_time);
-  int purge_first_log(struct st_relay_log_info* rli, bool included);
+  int purge_first_log(Relay_log_info* rli, bool included);
   bool reset_logs(THD* thd);
   void close(uint exiting);
 
@@ -584,6 +587,8 @@
   DATE_TIME_FORMAT *date_format;
   DATE_TIME_FORMAT *datetime_format;
   DATE_TIME_FORMAT *time_format;
+
+  const char* master;
 };
 
 
@@ -1923,3 +1928,5 @@
 /* Functions in sql_class.cc */
 
 void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
+
+#endif

--- 1.162/sql/sql_lex.h	Mon Apr 25 23:21:25 2005
+++ 1.163/sql/sql_lex.h	Mon Apr 25 23:34:24 2005
@@ -437,13 +437,13 @@
   void exclude_tree();
 
   /* UNION methods */
-  bool prepare(THD *thd, select_result *result, ulong additional_options);
+  bool prepare(THD *thd, select_result *result, ulong additional_options,
+               const char *tmp_table_alias);
   bool exec();
   bool cleanup();
   inline void unclean() { cleaned= 0; }
   void reinit_exec_mechanism();
 
-  bool check_updateable(char *db, char *table);
   void print(String *str);
 
   ulong init_prepare_fake_select_lex(THD *thd);
@@ -526,6 +526,8 @@
   bool first_cond_optimization;
   /* do not wrap view fields with Item_ref */
   bool no_wrap_view_item;
+  /* exclude this select from check of unique_table() */
+  bool exclude_from_table_unique_test;
 
   /* 
      SELECT for SELECT command st_select_lex. Used to privent scaning
@@ -616,8 +618,6 @@
     init_select();
   }
   bool setup_ref_array(THD *thd, uint order_group_num);
-  bool check_updateable(char *db, char *table);
-  bool check_updateable_in_subqueries(char *db, char *table);
   void print(THD *thd, String *str);
   static void print_order(String *str, ORDER *order);
   void print_limit(THD *thd, String *str);
@@ -696,14 +696,16 @@
   Item *default_value, *on_update_value;
   LEX_STRING comment, ident;
   LEX_USER *grant_user;
+  XID *xid;
   gptr yacc_yyss,yacc_yyvs;
   THD *thd;
   CHARSET_INFO *charset;
   TABLE_LIST *query_tables;	/* global list of all tables in this query */
   /*
     last element next_global of previous list (used only for list building
-    during parsing and VIEW processing. This pointer is not valid in
-    mysql_execute_command
+    during parsing and VIEW processing. This pointer could be invalid during
+    processing of information schema tables(see get_schema_tables_result
+    function)
   */
   TABLE_LIST **query_tables_last;
   TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */
@@ -732,14 +734,14 @@
   USER_RESOURCES mqh;
   ulong type;
   enum_sql_command sql_command, orig_sql_command;
-  thr_lock_type lock_option, multi_lock_option;
+  thr_lock_type lock_option;
   enum SSL_type ssl_type;			/* defined in violite.h */
   enum my_lex_states next_state;
   enum enum_duplicates duplicates;
   enum enum_tx_isolation tx_isolation;
   enum enum_ha_read_modes ha_read_mode;
   union {
-  enum ha_rkey_function ha_rkey_mode;
+    enum ha_rkey_function ha_rkey_mode;
     enum xa_option_words xa_opt;
   };
   enum enum_var_type option_type;
@@ -765,15 +767,15 @@
   ALTER_INFO alter_info;
   /* Prepared statements SQL syntax:*/
   LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
-  /* 
+  /*
     Prepared statement query text or name of variable that holds the
     prepared statement (in PREPARE ... queries)
   */
-  LEX_STRING prepared_stmt_code; 
+  LEX_STRING prepared_stmt_code;
   /* If true, prepared_stmt_code is a name of variable that holds the query */
   bool prepared_stmt_code_is_varref;
   /* Names of user variables holding parameters (in EXECUTE) */
-  List<LEX_STRING> prepared_stmt_params; 
+  List<LEX_STRING> prepared_stmt_params;
   /*
     Points to part of global table list which contains time zone tables
     implicitly used by the statement.
@@ -899,6 +901,8 @@
   }
   static void operator delete(void *ptr,size_t size)
   { TRASH(ptr, size); }
+  static void operator delete(void *ptr, MEM_ROOT *mem_root)
+  { /* Never called */ }
 };
 
 void lex_init(void);

--- 1.78/sql/sql_load.cc	Fri Apr  1 14:04:44 2005
+++ 1.79/sql/sql_load.cc	Mon Apr 25 23:34:25 2005
@@ -20,7 +20,7 @@
 #include "mysql_priv.h"
 #include <my_dir.h>
 #include <m_ctype.h>
-#include "sql_repl.h"
+#include <rpl/master.h>
 
 class READ_INFO {
   File	file;

--- 1.443/sql/sql_parse.cc	Mon Apr 25 22:18:31 2005
+++ 1.444/sql/sql_parse.cc	Mon Apr 25 23:34:25 2005
@@ -15,8 +15,8 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include "mysql_priv.h"
-#include "sql_repl.h"
-#include "rpl_filter.h"
+#include <rpl/master.h>
+#include <rpl/filter.h>
 #include "repl_failsafe.h"
 #include <m_ctype.h>
 #include <myisam.h>
@@ -2652,7 +2652,7 @@
     if (check_global_access(thd, SUPER_ACL))
       goto error;
     pthread_mutex_lock(&LOCK_active_mi);
-    res = change_master(thd,active_mi);
+    res= change_master(thd, lex->channel);
     pthread_mutex_unlock(&LOCK_active_mi);
     break;
   }
@@ -2662,10 +2662,20 @@
     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
       goto error;
     pthread_mutex_lock(&LOCK_active_mi);
-    res = show_master_info(thd,active_mi);
+    res= show_slave_stat(thd, lex->channel);
     pthread_mutex_unlock(&LOCK_active_mi);
     break;
   }
+  case SQLCOM_SHOW_SLAVE_STAT_ALL:
+  {
+    printf("LARS: NOT YET IMPLEMENTED!\n"); // DUMMY CODE
+    Protocol *dummy_code= thd->protocol; List<Item> field_list;
+    field_list.push_back(new Item_empty_string("NOT YET IMPLEMENTED", FN_REFLEN));
+    if (dummy_code->send_fields(&field_list, Protocol::SEND_EOF))
+    { res= TRUE; break; } dummy_code->prepare_for_resend();
+    send_eof(thd); res= FALSE;
+    break; 
+  }
   case SQLCOM_SHOW_MASTER_STAT:
   {
     /* Accept one of two privileges */
@@ -2674,14 +2684,13 @@
     res = show_binlog_info(thd);
     break;
   }
-
   case SQLCOM_LOAD_MASTER_DATA: // sync with master
     if (check_global_access(thd, SUPER_ACL))
       goto error;
     if (end_active_trans(thd))
       goto error;
     else
-      res = load_master_data(thd);
+      res= load_master_data(thd, lex->channel);
     break;
 #endif /* HAVE_REPLICATION */
 #ifdef HAVE_INNOBASE_DB
@@ -2725,8 +2734,8 @@
       fetch_master_table will send the error to the client on failure.
       Give error if the table already exists.
     */
-    if (!fetch_master_table(thd, first_table->db, first_table->table_name,
-			    active_mi, 0, 0))
+    if (!load_master_table(thd, first_table->db, first_table->table_name,
+			   lex->channel, 0, 0))
     {
       send_ok(thd);
     }
@@ -2865,7 +2874,7 @@
   case SQLCOM_SLAVE_START:
   {
     pthread_mutex_lock(&LOCK_active_mi);
-    start_slave(thd,active_mi,1 /* net report*/);
+    start_channel(thd, lex->channel, 1 /* net report*/);
     pthread_mutex_unlock(&LOCK_active_mi);
     break;
   }
@@ -2891,7 +2900,7 @@
   }
   {
     pthread_mutex_lock(&LOCK_active_mi);
-    stop_slave(thd,active_mi,1/* net report*/);
+    stop_channel(thd, lex->channel, 1/* net report*/);
     pthread_mutex_unlock(&LOCK_active_mi);
     break;
   }
@@ -6192,7 +6201,7 @@
     mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
 #ifdef HAVE_REPLICATION
     pthread_mutex_lock(&LOCK_active_mi);
-    rotate_relay_log(active_mi);
+    rotate_all_relay_logs();
     pthread_mutex_unlock(&LOCK_active_mi);
 #endif
     if (ha_flush_logs())
@@ -6265,7 +6274,7 @@
  {
    tmp_write_to_binlog= 0;
    pthread_mutex_lock(&LOCK_active_mi);
-   if (reset_slave(thd, active_mi))
+   if (reset_slave(thd, thd->lex->channel))
      result=1;
    pthread_mutex_unlock(&LOCK_active_mi);
  }

--- 1.227/sql/sql_show.cc	Mon Apr 25 23:21:25 2005
+++ 1.228/sql/sql_show.cc	Mon Apr 25 23:34:26 2005
@@ -41,6 +41,7 @@
 store_create_info(THD *thd, TABLE_LIST *table_list, String *packet);
 static int
 view_store_create_info(THD *thd, TABLE_LIST *table, String *packet);
+static bool schema_table_store_record(THD *thd, TABLE *table);
 
 
 /***************************************************************************
@@ -102,6 +103,7 @@
   {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"},
   {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
   {"Create view", "Tables",  "To create new views"},
+  {"Create user", "Server Admin",  "To create new users"},
   {"Delete", "Tables",  "To delete existing rows"},
   {"Drop", "Databases,Tables", "To drop databases, tables, and views"},
   {"Execute", "Functions,Procedures", "To execute stored routines"},
@@ -977,7 +979,7 @@
       packet->append(buff, (uint) (end- buff));
     }
 
-    if (share->max_rows)
+    if (share->max_rows && !table_list->schema_table)
     {
       packet->append(" MAX_ROWS=", 10);
       end= longlong10_to_str(share->max_rows, buff, 10);
@@ -1334,6 +1336,19 @@
           pthread_mutex_unlock(&LOCK_active_mi);
           break;
         }
+        case SHOW_SLAVE_RETRIED_TRANS:
+        {
+          /*
+            TODO: in 5.1 with multimaster, have one such counter per line in SHOW
+            SLAVE STATUS, and have the sum over all lines here.
+          */
+	  pthread_mutex_lock(&LOCK_active_mi);
+          pthread_mutex_lock(&active_mi->rli.data_lock);
+	  end= int10_to_str(active_mi->rli.retried_trans, buff, 10);
+          pthread_mutex_unlock(&active_mi->rli.data_lock);
+	  pthread_mutex_unlock(&LOCK_active_mi);
+	  break;
+        }
 #endif /* HAVE_REPLICATION */
         case SHOW_OPENTABLES:
           end= int10_to_str((long) cached_tables(), buff, 10);
@@ -1540,7 +1555,8 @@
         table->field[0]->store(name_buffer, strlen(name_buffer),
                                system_charset_info);
         table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
-        table->file->write_row(table->record[0]);        
+        if (schema_table_store_record(thd, table))
+          DBUG_RETURN(TRUE);
       }
     }
   }
@@ -1596,6 +1612,34 @@
 } INDEX_FIELD_VALUES;
 
 
+/*
+  Store record to I_S table, convert HEAP table
+  to MyISAM if necessary
+
+  SYNOPSIS
+    schema_table_store_record()
+    thd                   thread handler
+    table                 Information schema table to be updated
+
+  RETURN
+    0	                  success
+    1	                  error
+*/
+
+static bool schema_table_store_record(THD *thd, TABLE *table)
+{
+  int error;
+  if ((error= table->file->write_row(table->record[0])))
+  {
+    if (create_myisam_from_heap(thd, table, 
+                                table->pos_in_table_list->schema_table_param,
+                                error, 0))
+      return 1;
+  }
+  return 0;
+}
+
+
 void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
 {
   const char *wild= lex->wild ? lex->wild->ptr() : NullS;
@@ -1664,6 +1708,8 @@
                                strlen(item_field->field_name), 0)))
       return 0;
   }
+  else if (item->type() == Item::REF_ITEM)
+    return uses_only_table_name_fields(item->real_item(), table);
   if (item->type() == Item::SUBSELECT_ITEM &&
       !item->const_item())
     return 0;
@@ -1919,7 +1965,8 @@
                 }
               }
             }
-            table->file->write_row(table->record[0]);
+            if (schema_table_store_record(thd, table))
+              goto err;
           }
           else
           {
@@ -1956,13 +2003,13 @@
 }
 
 
-void store_schema_shemata(TABLE *table, const char *db_name,
+bool store_schema_shemata(THD* thd, TABLE *table, const char *db_name,
                           const char* cs_name)
 {
   restore_record(table, s->default_values);
   table->field[1]->store(db_name, strlen(db_name), system_charset_info);
   table->field[2]->store(cs_name, strlen(cs_name), system_charset_info);
-  table->file->write_row(table->record[0]);
+  return schema_table_store_record(thd, table);
 }
 
 
@@ -1991,7 +2038,9 @@
   {
     if (with_i_schema)       // information schema name is always first in list
     {
-      store_schema_shemata(table, file_name, system_charset_info->csname);
+      if (store_schema_shemata(thd, table, file_name,
+                               system_charset_info->csname))
+        DBUG_RETURN(1);
       with_i_schema= 0;
       continue;
     }
@@ -2014,8 +2063,9 @@
 	path[length-1]= FN_LIBCHAR;
       strmov(path+length, MY_DB_OPT_FILE);
       load_db_opt(thd, path, &create);
-      store_schema_shemata(table, file_name,
-                           create.default_table_charset->csname);
+      if (store_schema_shemata(thd, table, file_name, 
+                               create.default_table_charset->csname))
+        DBUG_RETURN(1);
     }
   }
   DBUG_RETURN(0);
@@ -2200,8 +2250,7 @@
       }
     }
   }
-  table->file->write_row(table->record[0]);
-  DBUG_RETURN(0);
+  DBUG_RETURN(schema_table_store_record(thd, table));
 }
 
 
@@ -2247,8 +2296,32 @@
       char tmp[MAX_FIELD_WIDTH];
       char tmp1[MAX_FIELD_WIDTH];
       String type(tmp,sizeof(tmp), system_charset_info);
+      char *end= tmp;
       count++;
       restore_record(table, s->default_values);
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+      uint col_access;
+      check_access(thd,SELECT_ACL | EXTRA_ACL, base_name,
+                   &tables->grant.privilege, 0, 0);
+      col_access= get_column_grant(thd, &tables->grant, tables->db,
+                                   tables->table_name,
+                                   field->field_name) & COL_ACLS;
+      if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS  && !col_access)
+        continue;
+      for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
+      {
+        if (col_access & 1)
+        {
+          *end++=',';
+          end=strmov(end,grant_types.type_names[bitnr]);
+        }
+      }
+#else
+      *end= 0;
+#endif
+      table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
+
       table->field[1]->store(base_name, strlen(base_name), cs);
       table->field[2]->store(file_name, strlen(file_name), cs);
       table->field[3]->store(field->field_name, strlen(field->field_name),
@@ -2292,11 +2365,13 @@
       table->field[6]->store((const char*) pos,
                              strlen((const char*) pos), cs);
       if (field->has_charset())
+      {
         table->field[8]->store((longlong) field->representation_length()/
                                field->charset()->mbmaxlen);
-      else
-        table->field[8]->store((longlong) field->representation_length());
-      table->field[9]->store((longlong) field->representation_length());
+        table->field[8]->set_notnull();
+        table->field[9]->store((longlong) field->representation_length());
+        table->field[9]->set_notnull();
+      }
 
       {
         uint dec =field->decimals();
@@ -2353,33 +2428,15 @@
                    (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
       table->field[15]->store((const char*) pos,
                               strlen((const char*) pos), cs);
-      char *end= tmp;
+      end= tmp;
       if (field->unireg_check == Field::NEXT_NUMBER)
         end=strmov(tmp,"auto_increment");
       table->field[16]->store(tmp, (uint) (end-tmp), cs);
 
       end=tmp;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-      uint col_access;
-      check_access(thd,SELECT_ACL | EXTRA_ACL, base_name,
-                   &tables->grant.privilege, 0, 0);
-      col_access= get_column_grant(thd, &tables->grant, tables->db,
-                                   tables->table_name,
-                                   field->field_name) & COL_ACLS;
-      for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
-      {
-        if (col_access & 1)
-        {
-          *end++=',';
-          end=strmov(end,grant_types.type_names[bitnr]);
-        }
-      }
-#else
-      end=strmov(end,"");
-#endif
-      table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
       table->field[18]->store(field->comment.str, field->comment.length, cs);
-      table->file->write_row(table->record[0]);
+      if (schema_table_store_record(thd, table))
+        DBUG_RETURN(1);
     }
   }
   DBUG_RETURN(0);
@@ -2408,7 +2465,8 @@
 			     strlen(tmp_cs->comment ? tmp_cs->comment : ""),
                              scs);
       table->field[3]->store((longlong) tmp_cs->mbmaxlen);
-      table->file->write_row(table->record[0]);
+      if (schema_table_store_record(thd, table))
+        return 1;
     }
   }
   return 0;
@@ -2447,7 +2505,8 @@
         tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
 	table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
         table->field[5]->store((longlong) tmp_cl->strxfrm_multiply);
-	table->file->write_row(table->record[0]);
+        if (schema_table_store_record(thd, table))
+          return 1;
       }
     }
   }
@@ -2476,14 +2535,15 @@
       restore_record(table, s->default_values);
       table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
       table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
-      table->file->write_row(table->record[0]);
+      if (schema_table_store_record(thd, table))
+        return 1;
     }
   }
   return 0;
 }
 
 
-void store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
+bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
                        const char *wild, bool full_access, const char *sp_user)
 {
   String tmp_string;
@@ -2497,7 +2557,7 @@
   if (!full_access)
     full_access= !strcmp(sp_user, definer);
   if (!full_access && check_some_routine_access(thd, sp_db, sp_name))
-    return;
+    return 0;
 
   if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
       proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
@@ -2546,9 +2606,10 @@
       get_field(thd->mem_root, proc_table->field[15], &tmp_string);
       table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
       table->field[19]->store(definer, strlen(definer), cs);
-      table->file->write_row(table->record[0]);
+      return schema_table_store_record(thd, table);
     }
   }
+  return 0;
 }
 
 
@@ -2581,9 +2642,19 @@
     res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
     goto err;
   }
-  store_schema_proc(thd, table, proc_table, wild, full_access, definer);
+  if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
+  {
+    res= 1;
+    goto err;
+  }
   while (!proc_table->file->index_next(proc_table->record[0]))
-    store_schema_proc(thd, table, proc_table, wild, full_access, definer);
+  {
+    if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
+    {
+      res= 1;
+      goto err;
+    }
+  }
 
 err:
   proc_table->file->ha_index_end();
@@ -2673,7 +2744,8 @@
         else
           table->field[14]->store("", 0, cs);
         table->field[14]->set_notnull();
-        table->file->write_row(table->record[0]);
+        if (schema_table_store_record(thd, table))
+          DBUG_RETURN(1);
       }
     }
   }
@@ -2712,7 +2784,7 @@
         table->field[5]->store("YES", 3, cs);
       else
         table->field[5]->store("NO", 2, cs);
-      table->file->write_row(table->record[0]);
+      DBUG_RETURN(schema_table_store_record(thd, table));
     }
   }
   else
@@ -2726,9 +2798,9 @@
 }
 
 
-void store_constraints(TABLE *table, const char*db, const char *tname,
-                       const char *key_name, uint key_len,
-                       const char *con_type, uint con_len)
+bool store_constraints(THD *thd, TABLE *table, const char *db,
+                       const char *tname, const char *key_name,
+                       uint key_len, const char *con_type, uint con_len)
 {
   CHARSET_INFO *cs= system_charset_info;
   restore_record(table, s->default_values);
@@ -2737,7 +2809,7 @@
   table->field[3]->store(db, strlen(db), cs);
   table->field[4]->store(tname, strlen(tname), cs);
   table->field[5]->store(con_type, con_len, cs);
-  table->file->write_row(table->record[0]);
+  return schema_table_store_record(thd, table);
 }
 
 
@@ -2770,11 +2842,17 @@
         continue;
 
       if (i == primary_key && !strcmp(key_info->name, primary_key_name))
-        store_constraints(table, base_name, file_name, key_info->name,
-                          strlen(key_info->name), "PRIMARY KEY", 11);
+      {
+        if (store_constraints(thd, table, base_name, file_name, key_info->name,
+                              strlen(key_info->name), "PRIMARY KEY", 11))
+          DBUG_RETURN(1);
+      }
       else if (key_info->flags & HA_NOSAME)
-        store_constraints(table, base_name, file_name, key_info->name,
-                          strlen(key_info->name), "UNIQUE", 6);        
+      {
+        if (store_constraints(thd, table, base_name, file_name, key_info->name,
+                              strlen(key_info->name), "UNIQUE", 6))
+          DBUG_RETURN(1);
+      }
     }
 
     show_table->file->get_foreign_key_list(thd, &f_key_list);
@@ -2782,8 +2860,11 @@
     List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
     while ((f_key_info=it++))
     {
-      store_constraints(table, base_name, file_name, f_key_info->forein_id->str,
-                        strlen(f_key_info->forein_id->str), "FOREIGN KEY", 11);
+      if (store_constraints(thd, table, base_name, file_name, 
+                            f_key_info->forein_id->str,
+                            strlen(f_key_info->forein_id->str),
+                            "FOREIGN KEY", 11))
+        DBUG_RETURN(1);
     }
   }
   DBUG_RETURN(res);
@@ -2846,7 +2927,8 @@
                                  key_part->field->field_name, 
                                  strlen(key_part->field->field_name),
                                  (longlong) f_idx);
-          table->file->write_row(table->record[0]);
+          if (schema_table_store_record(thd, table))
+            DBUG_RETURN(1);
         }
       }
     }
@@ -2872,7 +2954,8 @@
                                (longlong) f_idx);
         table->field[8]->store((longlong) f_idx);
         table->field[8]->set_notnull();
-        table->file->write_row(table->record[0]);
+        if (schema_table_store_record(thd, table))
+          DBUG_RETURN(1);
       }
     }
   }
@@ -2897,7 +2980,8 @@
     table->field[1]->store(open_list->table, strlen(open_list->table), cs);
     table->field[2]->store((longlong) open_list->in_use);
     table->field[3]->store((longlong)  open_list->locked);
-    table->file->write_row(table->record[0]);
+    if (schema_table_store_record(thd, table))
+      DBUG_RETURN(1);
   }
   DBUG_RETURN(0);
 }
@@ -3038,6 +3122,7 @@
                                  TMP_TABLE_ALL_COLUMNS),
                                 HA_POS_ERROR, table_list->alias)))
     DBUG_RETURN(0);
+  table_list->schema_table_param= tmp_table_param;
   DBUG_RETURN(table);
 }
 
@@ -3363,12 +3448,11 @@
     TABLE_LIST *table_list= tab->table->pos_in_table_list;
     if (table_list->schema_table && thd->fill_derived_tables())
     {
-      TABLE_LIST *save_next_global= table_list->next_global;
       TABLE_LIST **query_tables_last= lex->query_tables_last;
       TABLE *old_derived_tables= thd->derived_tables;
       MYSQL_LOCK *sql_lock= thd->lock;
       lex->sql_command= SQLCOM_SHOW_FIELDS;
-
+      DBUG_ASSERT(!*query_tables_last);
       if (&lex->unit != lex->current_select->master_unit()) // is subselect
       {
         table_list->table->file->extra(HA_EXTRA_RESET_STATE);
@@ -3387,8 +3471,8 @@
       thd->lock= sql_lock;
       lex->sql_command= SQLCOM_SELECT;
       thd->derived_tables= old_derived_tables;
-      table_list->next_global= save_next_global;
       lex->query_tables_last= query_tables_last;
+      *query_tables_last= 0;
     }
   }
   thd->no_warnings_for_error= 0;
@@ -3443,8 +3527,8 @@
   {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"},
   {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
   {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
-  {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
+  {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+  {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
   {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
   {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
   {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0},

--- 1.355/sql/sql_yacc.yy	Mon Apr 25 23:21:25 2005
+++ 1.356/sql/sql_yacc.yy	Mon Apr 25 23:34:26 2005
@@ -47,13 +47,13 @@
 
 #define yyoverflow(A,B,C,D,E,F) {ulong val= *(F); if(my_yyoverflow((B), (D), &val)) { yyerror((char*) (A)); return 2; } else { *(F)= (YYSIZE_T)val; }}
 
-#define WARN_DEPRECATED(A,B) \
+#define WARN_DEPRECATED(A,B)                                        \
   push_warning_printf(((THD *)yythd), MYSQL_ERROR::WARN_LEVEL_WARN, \
-		      ER_WARN_DEPRECATED_SYNTAX, \
+		      ER_WARN_DEPRECATED_SYNTAX,                    \
 		      ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
 
-#define TEST_ASSERT(A) \
-  if (!(A)) \
+#define TEST_ASSERT(A)                  \
+  if (!(A))                             \
   {					\
     yyerror(ER(ER_SYNTAX_ERROR));	\
     YYABORT;				\
@@ -243,7 +243,6 @@
 %token  DUPLICATE_SYM
 %token  DYNAMIC_SYM
 %token  EACH_SYM
-%token  EALLOCATE_SYM
 %token  ELSEIF_SYM
 %token  ELT_FUNC
 %token  ENABLE_SYM
@@ -703,7 +702,7 @@
         union_opt select_derived_init
 
 %type <ulong_num>
-	ULONG_NUM raid_types merge_insert_types
+	ulong_num raid_types merge_insert_types
 
 %type <ulonglong_number>
 	ulonglong_num
@@ -1048,16 +1047,16 @@
 	 Lex->mi.password = $3.str;
        }
        |
-       MASTER_PORT_SYM EQ ULONG_NUM
+       MASTER_PORT_SYM EQ ulong_num
        {
 	 Lex->mi.port = $3;
        }
        |
-       MASTER_CONNECT_RETRY_SYM EQ ULONG_NUM
+       MASTER_CONNECT_RETRY_SYM EQ ulong_num
        {
 	 Lex->mi.connect_retry = $3;
        }
-       | MASTER_SSL_SYM EQ ULONG_NUM
+       | MASTER_SSL_SYM EQ ulong_num
          {
            Lex->mi.ssl= $3 ? 
                LEX_MASTER_INFO::SSL_ENABLE : LEX_MASTER_INFO::SSL_DISABLE;
@@ -1111,7 +1110,7 @@
          {
            Lex->mi.relay_log_name = $3.str;
          }
-       | RELAY_LOG_POS_SYM EQ ULONG_NUM
+       | RELAY_LOG_POS_SYM EQ ulong_num
          {
            Lex->mi.relay_log_pos = $3;
            /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
@@ -1338,12 +1337,12 @@
         ;
 
 sp_name:
-	  IDENT_sys '.' IDENT_sys
+	  ident '.' ident
 	  {
 	    $$= new sp_name($1, $3);
 	    $$->init_qname(YYTHD);
 	  }
-	| IDENT_sys
+	| ident
 	  {
 	    $$= sp_name_current_db_new(YYTHD, $1);
 	  }
@@ -1407,7 +1406,7 @@
 	    uint unused1= 0;
 	    int unused2= 0;
 
-	    if (!(new_field= new_create_field(YYTHD, "",
+	    if (!(new_field= new_create_field(YYTHD, (char*) "",
 					      (enum enum_field_types)$8,
 			  		      lex->length, lex->dec, lex->type,
 			  		      (Item *)0, (Item *) 0, &cmt, 0,
@@ -1417,6 +1416,16 @@
 					      lex->uint_geom_type)))
 	      YYABORT;
 
+	    sp->m_returns_cs= new_field->charset;
+
+            if (new_field->sql_type == FIELD_TYPE_SET ||
+                new_field->sql_type == FIELD_TYPE_ENUM)
+            {
+	      new_field->interval= 
+                sp->create_typelib(&new_field->interval_list);
+            }
+            sp_prepare_create_field(YYTHD, new_field);
+
 	    if (prepare_create_field(new_field, &unused1, &unused2, &unused2,
 				     0))
 	      YYABORT;
@@ -1425,8 +1434,8 @@
 	    sp->m_returns_cs= new_field->charset;
 	    sp->m_returns_len= new_field->length;
 	    sp->m_returns_pack= new_field->pack_flag;
-	    sp->m_returns_typelib= 
-              sp->create_typelib(&new_field->interval_list);
+            sp->m_returns_typelib= new_field->interval;
+            new_field->interval= NULL;
 
 	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
 	  }
@@ -1691,7 +1700,6 @@
 
 	    sp->add_instr(i);
 	    sp->push_backpatch(i, ctx->push_label((char *)"", 0));
-	    ctx->add_handler();
 	    sp->m_in_handler= TRUE;
 	  }
 	  sp_hcond_list sp_proc_stmt
@@ -1719,6 +1727,7 @@
 	    sp->m_in_handler= FALSE;
 	    $$.vars= $$.conds= $$.curs= 0;
 	    $$.hndlrs= $6;
+	    ctx->add_handlers($6);
 	  }
 	| DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
 	  {
@@ -1784,24 +1793,48 @@
 	  {
 	    LEX *lex= Lex;
 	    sp_head *sp= lex->sphead;
-	    sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
+	    sp_pcontext *ctx= lex->spcont;
 
-	    i->add_condition($1);
-	    $$= 1;
+	    if (ctx->find_handler($1))
+	    {
+	      my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
+	      YYABORT;
+	    }
+	    else
+	    {
+	      sp_instr_hpush_jump *i=
+                (sp_instr_hpush_jump *)sp->last_instruction();
+
+	      i->add_condition($1);
+	      ctx->push_handler($1);
+	      $$= 1;
+	    }
 	  }
 	| sp_hcond_list ',' sp_hcond
 	  {
 	    LEX *lex= Lex;
 	    sp_head *sp= lex->sphead;
-	    sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
+	    sp_pcontext *ctx= lex->spcont;
 
-	    i->add_condition($3);
-	    $$= $1 + 1;
+	    if (ctx->find_handler($3))
+	    {
+	      my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
+	      YYABORT;
+	    }
+	    else
+	    {
+	      sp_instr_hpush_jump *i=
+	        (sp_instr_hpush_jump *)sp->last_instruction();
+
+	      i->add_condition($3);
+	      ctx->push_handler($3);
+	      $$= $1 + 1;
+	    }
 	  }
 	;
 
 sp_cond:
-	  ULONG_NUM
+	  ulong_num
 	  {			/* mysql errno */
 	    $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
 	    $$->type= sp_cond_type_t::number;
@@ -2587,18 +2620,18 @@
 	| TYPE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine");   Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
 	| MAX_ROWS opt_equal ulonglong_num	{ Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
 	| MIN_ROWS opt_equal ulonglong_num	{ Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
-	| AVG_ROW_LENGTH opt_equal ULONG_NUM	{ Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
+	| AVG_ROW_LENGTH opt_equal ulong_num	{ Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
 	| PASSWORD opt_equal TEXT_STRING_sys	{ Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; }
 	| COMMENT_SYM opt_equal TEXT_STRING_sys	{ Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; }
 	| AUTO_INC opt_equal ulonglong_num	{ Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
-	| PACK_KEYS_SYM opt_equal ULONG_NUM	{ Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
+	| PACK_KEYS_SYM opt_equal ulong_num	{ Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
 	| PACK_KEYS_SYM opt_equal DEFAULT	{ Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
-	| CHECKSUM_SYM opt_equal ULONG_NUM	{ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; }
-	| DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE;  Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; }
+	| CHECKSUM_SYM opt_equal ulong_num	{ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; }
+	| DELAY_KEY_WRITE_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE;  Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; }
 	| ROW_FORMAT_SYM opt_equal row_types	{ Lex->create_info.row_type= $3;  Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; }
 	| RAID_TYPE opt_equal raid_types	{ Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
-	| RAID_CHUNKS opt_equal ULONG_NUM	{ Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
-	| RAID_CHUNKSIZE opt_equal ULONG_NUM	{ Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+	| RAID_CHUNKS opt_equal ulong_num	{ Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+	| RAID_CHUNKSIZE opt_equal ulong_num	{ Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
 	| UNION_SYM opt_equal '(' table_list ')'
 	  {
 	    /* Move the union list to the merge_list */
@@ -2675,7 +2708,7 @@
 raid_types:
 	RAID_STRIPED_SYM { $$= RAID_TYPE_0; }
 	| RAID_0_SYM	 { $$= RAID_TYPE_0; }
-	| ULONG_NUM	 { $$=$1;};
+	| ulong_num	 { $$=$1;};
 
 merge_insert_types:
        NO_SYM            { $$= MERGE_INSERT_DISABLED; }
@@ -3291,6 +3324,11 @@
 	  {
 	    LEX *lex= Lex;
 
+	    if (lex->sphead)
+	    {
+	      my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
+	      YYABORT;
+	    }
 	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
           }
 	  sp_a_chistics
@@ -3304,6 +3342,11 @@
 	  {
 	    LEX *lex= Lex;
 
+	    if (lex->sphead)
+	    {
+	      my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
+	      YYABORT;
+	    }
 	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
           }
 	  sp_a_chistics
@@ -3695,9 +3738,15 @@
 check:
 	CHECK_SYM table_or_tables
 	{
-	   LEX *lex=Lex;
-	   lex->sql_command = SQLCOM_CHECK;
-	   lex->check_opt.init();
+	  LEX *lex=Lex;
+
+	  if (lex->sphead)
+	  {
+	    my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK");
+	    YYABORT;
+	  }
+	  lex->sql_command = SQLCOM_CHECK;
+	  lex->check_opt.init();
 	}
 	table_list opt_mi_check_type
 	{}
@@ -3928,7 +3977,6 @@
 	{
 	  LEX *lex= Lex;
 	  SELECT_LEX *sel= lex->current_select;
-	  lex->lock_option= TL_READ;
 	  if (sel->linkage != UNION_TYPE)
 	    mysql_init_select(lex);
 	  lex->current_select->parsing_place= SELECT_LIST;
@@ -4594,14 +4642,16 @@
 	  { $$= new Item_int((char*) "TRUE",1,1); }
 	| ident '.' ident '(' udf_expr_list ')'
 	  {
+	    LEX *lex= Lex;
 	    sp_name *name= new sp_name($1, $3);
 
 	    name->init_qname(YYTHD);
-	    sp_add_to_hash(&Lex->spfuns, name);
+	    sp_add_to_hash(&lex->spfuns, name);
 	    if ($5)
 	      $$= new Item_func_sp(name, *$5);
 	    else
 	      $$= new Item_func_sp(name);
+	    lex->safe_to_cache_query=0;
 	  }
 	| IDENT_sys '(' udf_expr_list ')'
           {
@@ -4682,13 +4732,15 @@
             else
 #endif /* HAVE_DLOPEN */
             {
+	      LEX *lex= Lex;
               sp_name *name= sp_name_current_db_new(YYTHD, $1);
 
-              sp_add_to_hash(&Lex->spfuns, name);
+              sp_add_to_hash(&lex->spfuns, name);
               if ($3)
                 $$= new Item_func_sp(name, *$3);
               else
                 $$= new Item_func_sp(name);
+	      lex->safe_to_cache_query=0;
 	    }
           }
 	| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
@@ -4723,7 +4775,7 @@
 	  { $$= new Item_func_yearweek($3,new Item_int((char*) "0",0,1)); }
 	| YEARWEEK '(' expr ',' expr ')'
 	  { $$= new Item_func_yearweek($3, $5); }
-	| BENCHMARK_SYM '(' ULONG_NUM ',' expr ')'
+	| BENCHMARK_SYM '(' ulong_num ',' expr ')'
 	  {
 	    $$=new Item_func_benchmark($3,$5);
 	    Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -5008,7 +5060,7 @@
 join_table_list:
 	derived_table_list		{ TEST_ASSERT($$=$1); }
 	;
-        
+
 /* Warning - may return NULL in case of incomplete SELECT */
 derived_table_list:
         table_ref { $$=$1; }
@@ -5052,7 +5104,7 @@
 	    $$=$6;
 	  }
 	| table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr
-          { 
+          {
 	    LEX *lex= Lex;
             TEST_ASSERT($1 && $5);
             if (!($$= lex->current_select->convert_right_join()))
@@ -5066,7 +5118,7 @@
             sel->save_names_for_using_list($1, $5);
 	  }
 	  USING '(' using_list ')'
-          { 
+          {
 	    LEX *lex= Lex;
             if (!($$= lex->current_select->convert_right_join()))
               YYABORT;
@@ -5082,7 +5134,7 @@
 	  }
 	| table_ref NATURAL JOIN_SYM table_factor
 	  { TEST_ASSERT($1 && ($$=$4)); add_join_natural($1,$4); };
-        
+
 
 normal_join:
 	JOIN_SYM		{}
@@ -5128,9 +5180,9 @@
                    sel->master_unit()->fake_select_lex;
             }
             if ($2->init_nested_join(lex->thd))
-              YYABORT;            
+              YYABORT;
             $$= 0;
-            /* incomplete derived tables return NULL, we must be 
+            /* incomplete derived tables return NULL, we must be
                nested in select_derived rule to be here. */
           }
 	| '(' get_select_lex select_derived union_opt ')' opt_table_alias
@@ -5138,7 +5190,7 @@
           /* Use $2 instead of Lex->current_select as derived table will
              alter value of Lex->current_select. */
 
-          if (!($3 || $6) && $2->embedding && 
+          if (!($3 || $6) && $2->embedding &&
               !$2->embedding->nested_join->join_list.elements)
           {
             /* we have a derived table ($3 == NULL) but no alias,
@@ -5163,7 +5215,7 @@
 	                            (List<String> *)0)))
 
 	      YYABORT;
-            sel->add_joined_table($$);           
+            sel->add_joined_table($$);
           }
 	  else
           if ($4 || $6)
@@ -5190,7 +5242,7 @@
             LEX *lex= Lex;
             /* for normal joins, $3 != NULL and end_nested_join() != NULL,
                for derived tables, both must equal NULL */
-            
+
             if (!($$= $1->end_nested_join(lex->thd)) && $3)
               YYABORT;
             if (!$3 && $$)
@@ -5234,7 +5286,7 @@
           SELECT_SYM
           {
             LEX *lex= Lex;
-            SELECT_LEX *sel= lex->current_select;        
+            SELECT_LEX *sel= lex->current_select;
             TABLE_LIST *embedding;
             if (!sel->embedding || sel->end_nested_join(lex->thd))
 	    {
@@ -5507,21 +5559,21 @@
 	;
 
 limit_options:
-	ULONG_NUM
+	ulong_num
 	  {
             SELECT_LEX *sel= Select;
             sel->select_limit= $1;
             sel->offset_limit= 0L;
 	    sel->explicit_limit= 1;
 	  }
-	| ULONG_NUM ',' ULONG_NUM
+	| ulong_num ',' ulong_num
 	  {
 	    SELECT_LEX *sel= Select;
 	    sel->select_limit= $3;
 	    sel->offset_limit= $1;
 	    sel->explicit_limit= 1;
 	  }
-	| ULONG_NUM OFFSET_SYM ULONG_NUM
+	| ulong_num OFFSET_SYM ulong_num
 	  {
 	    SELECT_LEX *sel= Select;
 	    sel->select_limit= $1;
@@ -5544,11 +5596,12 @@
 	  sel->explicit_limit= 1;
 	};
 
-ULONG_NUM:
-	NUM	        { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ulong_num:
+          NUM           { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+	| HEX_NUM       { int error; $$= (ulong) strtol($1.str, (char**) 0, 16); }
 	| LONG_NUM      { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
 	| ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
-        | DECIMAL_NUM 	{ int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+        | DECIMAL_NUM   { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
 	| FLOAT_NUM	{ int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
 	;
 
@@ -5964,10 +6017,7 @@
 	{
 	  LEX *lex= Lex;
           if (lex->select_lex.table_list.elements > 1)
-	  {
             lex->sql_command= SQLCOM_UPDATE_MULTI;
-	    lex->multi_lock_option= $3;
-	  }
 	  else if (lex->select_lex.get_table_list()->derived)
 	  {
 	    /* it is single table update and it is update of derived table */
@@ -5975,8 +6025,12 @@
                      lex->select_lex.get_table_list()->alias, "UPDATE");
 	    YYABORT;
 	  }
-	  else
-	    Select->set_lock_for_tables($3);
+          /*
+            In case of multi-update setting write lock for all tables may
+            be too pessimistic. We will decrease lock level if possible in
+            mysql_multi_update().
+          */
+          Select->set_lock_for_tables($3);
 	}
 	where_clause opt_order_clause delete_limit_clause {}
 	;
@@ -6158,7 +6212,7 @@
         | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
 	  TEXT_STRING_sys AND_SYM MASTER_LOG_POS_SYM EQ ulonglong_num
 	  AND_SYM MASTER_SERVER_ID_SYM EQ
-	ULONG_NUM
+	ulong_num
           {
 	    Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
 	    Lex->mi.log_file_name = $8.str;
@@ -6734,7 +6788,7 @@
         | field_or_var
           { Lex->field_list.push_back($1); }
         ;
-        
+
 field_or_var:
         simple_ident_nospvar {$$= $1;}
         | '@' ident_or_text
@@ -6882,9 +6936,9 @@
 	   }
 	}
 	;
-	
+
 /**********************************************************************
-** Createing different items.
+** Creating different items.
 **********************************************************************/
 
 insert_ident:
@@ -6900,8 +6954,8 @@
 	| ident '.' ident '.' '*'
 	{
 	  $$ = new Item_field((YYTHD->client_capabilities &
-   			     CLIENT_NO_SCHEMA ? NullS : $1.str),
-			     $3.str,"*");
+                             CLIENT_NO_SCHEMA ? NullS : $1.str),
+                             $3.str,"*");
 	  Lex->current_select->with_wild++;
 	}
 	;
@@ -6944,53 +6998,53 @@
 	      (Item*) new Item_ref(NullS,NullS,$1.str);
 	}
 	| simple_ident_q { $$= $1; }
-	;	
+	;
 
 simple_ident_q:
 	ident '.' ident
 	{
 	  THD *thd= YYTHD;
 	  LEX *lex= thd->lex;
-         
+
           /*
             FIXME This will work ok in simple_ident_nospvar case because
             we can't meet simple_ident_nospvar in trigger now. But it
             should be changed in future.
           */
           if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
-              (!my_strcasecmp(system_charset_info, $1.str, "NEW") || 
+              (!my_strcasecmp(system_charset_info, $1.str, "NEW") ||
                !my_strcasecmp(system_charset_info, $1.str, "OLD")))
           {
             Item_trigger_field *trg_fld;
             bool new_row= ($1.str[0]=='N' || $1.str[0]=='n');
-            
+
             if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
                 !new_row)
             {
               my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
               YYABORT;
             }
-            
+
             if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
                 new_row)
             {
               my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
               YYABORT;
             }
-            
+
             if (!(trg_fld= new Item_trigger_field(new_row ?
                                                   Item_trigger_field::NEW_ROW:
                                                   Item_trigger_field::OLD_ROW,
                                                   $3.str)))
               YYABORT;
-          
+
             /*
               Let us add this item to list of all Item_trigger_field objects
               in trigger.
             */
             lex->trg_table_fields.link_in_list((byte *)trg_fld,
               (byte**)&trg_fld->next_trg_field);
-            
+
             $$= (Item *)trg_fld;
           }
           else
@@ -7066,9 +7120,10 @@
 	    if (thd->charset_is_system_charset)
             {
               CHARSET_INFO *cs= system_charset_info;
+              int dummy_error;
               uint wlen= cs->cset->well_formed_len(cs, $1.str,
                                                    $1.str+$1.length,
-                                                   $1.length);
+                                                   $1.length, &dummy_error);
               if (wlen < $1.length)
               {
                 my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
@@ -7119,7 +7174,7 @@
 	;
 
 ident_or_text:
-	ident 			{ $$=$1;}
+        ident                   { $$=$1;}
 	| TEXT_STRING_sys	{ $$=$1;}
 	| LEX_HOSTNAME		{ $$=$1;};
 
@@ -7297,7 +7352,7 @@
 	| MULTILINESTRING	{}
 	| MULTIPOINT		{}
 	| MULTIPOLYGON		{}
-  | MUTEX_SYM   {}
+        | MUTEX_SYM             {}
 	| NAME_SYM              {}
 	| NAMES_SYM		{}
 	| NATIONAL_SYM		{}
@@ -7389,8 +7444,8 @@
 	| TIMESTAMP_ADD		{}
 	| TIMESTAMP_DIFF	{}
 	| TIME_SYM		{}
-	| TYPE_SYM		{}
 	| TYPES_SYM		{}
+        | TYPE_SYM              {}
         | UDF_RETURNS_SYM       {}
 	| FUNCTION_SYM		{}
 	| UNCOMMITTED_SYM	{}
@@ -7772,7 +7827,7 @@
 
 	  if (lex->sphead)
 	  {
-	    my_message(ER_SP_BADSTATEMENT, ER(ER_SP_BADSTATEMENT), MYF(0));
+	    my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK");
 	    YYABORT;
 	  }
 	  lex->sql_command= SQLCOM_LOCK_TABLES;
@@ -7811,7 +7866,7 @@
 
 	  if (lex->sphead)
 	  {
-	    my_message(ER_SP_BADSTATEMENT, ER(ER_SP_BADSTATEMENT), MYF(0));
+	    my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK");
 	    YYABORT;
 	  }
 	  lex->sql_command= SQLCOM_UNLOCK_TABLES;
@@ -7956,6 +8011,7 @@
 	| SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
 	| CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
 	| ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
+	| CREATE USER { Lex->grant |= CREATE_USER_ACL; }
 	;
 
 
@@ -8170,25 +8226,25 @@
 
 grant_option:
 	GRANT OPTION { Lex->grant |= GRANT_ACL;}
-        | MAX_QUERIES_PER_HOUR ULONG_NUM
+        | MAX_QUERIES_PER_HOUR ulong_num
         {
 	  LEX *lex=Lex;
 	  lex->mqh.questions=$2;
 	  lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR;
 	}
-        | MAX_UPDATES_PER_HOUR ULONG_NUM
+        | MAX_UPDATES_PER_HOUR ulong_num
         {
 	  LEX *lex=Lex;
 	  lex->mqh.updates=$2;
 	  lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR;
 	}
-        | MAX_CONNECTIONS_PER_HOUR ULONG_NUM
+        | MAX_CONNECTIONS_PER_HOUR ulong_num
         {
 	  LEX *lex=Lex;
 	  lex->mqh.conn_per_hour= $2;
 	  lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
 	}
-        | MAX_USER_CONNECTIONS_SYM ULONG_NUM
+        | MAX_USER_CONNECTIONS_SYM ulong_num
         {
 	  LEX *lex=Lex;
           lex->mqh.user_conn= $2;
@@ -8459,38 +8515,52 @@
 
 xa: XA_SYM begin_or_start xid opt_join_or_resume
       {
-        LEX *lex= Lex;
-        lex->sql_command = SQLCOM_XA_START;
+        Lex->sql_command = SQLCOM_XA_START;
       }
     | XA_SYM END xid opt_suspend_or_migrate
       {
-        LEX *lex= Lex;
-        lex->sql_command = SQLCOM_XA_END;
+        Lex->sql_command = SQLCOM_XA_END;
       }
     | XA_SYM PREPARE_SYM xid
       {
-        LEX *lex= Lex;
-        lex->sql_command = SQLCOM_XA_PREPARE;
+        Lex->sql_command = SQLCOM_XA_PREPARE;
       }
     | XA_SYM COMMIT_SYM xid opt_one_phase
       {
-        LEX *lex= Lex;
-        lex->sql_command = SQLCOM_XA_COMMIT;
+        Lex->sql_command = SQLCOM_XA_COMMIT;
       }
     | XA_SYM ROLLBACK_SYM xid
       {
-        LEX *lex= Lex;
-        lex->sql_command = SQLCOM_XA_ROLLBACK;
+        Lex->sql_command = SQLCOM_XA_ROLLBACK;
       }
     | XA_SYM RECOVER_SYM
       {
-        LEX *lex= Lex;
-        lex->sql_command = SQLCOM_XA_RECOVER;
+        Lex->sql_command = SQLCOM_XA_RECOVER;
       }
     ;
 
-xid: ident_or_text              { Lex->ident=$1; }
-    ;
+xid: text_string
+     {
+       TEST_ASSERT($1->length() <= MAXGTRIDSIZE);
+       if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+         YYABORT;
+       Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
+     }
+     | text_string ',' text_string
+     {
+       TEST_ASSERT($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+       if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+         YYABORT;
+       Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
+     }
+     | text_string ',' text_string ',' ulong_num
+     {
+       TEST_ASSERT($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+       if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+         YYABORT;
+       Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
+     }
+     ;
 
 begin_or_start:   BEGIN_SYM {}
     |             START_SYM {}

--- 1.17/sql/share/errmsg.txt	Mon Apr 25 23:21:24 2005
+++ 1.18/sql/share/errmsg.txt	Tue Apr 26 00:31:04 2005
@@ -1214,30 +1214,30 @@
 	swe "Tabellen '%-.64s' finns redan"
 ER_BAD_TABLE_ERROR 42S02 
-	dan "Ukendt tabel '%-.64s'"
-	nla "Onbekende tabel '%-.64s'"
-	eng "Unknown table '%-.64s'"
-	est "Tundmatu tabel '%-.64s'"
-	fre "Table '%-.64s' inconnue"
-	ger "Unbekannte Tabelle '%-.64s'"
-	hun "Ervenytelen tabla: '%-.64s'"
-	ita "Tabella '%-.64s' sconosciuta"
-	nor "Ukjent tabell '%-.64s'"
-	norwegian-ny "Ukjent tabell '%-.64s'"
-	pol "Nieznana tabela '%-.64s'"
-	por "Tabela '%-.64s' desconhecida"
-	rum "Tabela '%-.64s' este invalida"
-	serbian "Nepoznata tabela '%-.64s'"
-	spa "Tabla '%-.64s' desconocida"
+	dan "Ukendt tabel '%-.100s'"
+	nla "Onbekende tabel '%-.100s'"
+	eng "Unknown table '%-.100s'"
+	est "Tundmatu tabel '%-.100s'"
+	fre "Table '%-.100s' inconnue"
+	ger "Unbekannte Tabelle '%-.100s'"
+	hun "Ervenytelen tabla: '%-.100s'"
+	ita "Tabella '%-.100s' sconosciuta"
+	nor "Ukjent tabell '%-.100s'"
+	norwegian-ny "Ukjent tabell '%-.100s'"
+	pol "Nieznana tabela '%-.100s'"
+	por "Tabela '%-.100s' desconhecida"
+	rum "Tabela '%-.100s' este invalida"
+	serbian "Nepoznata tabela '%-.100s'"
+	spa "Tabla '%-.100s' desconocida"
 ER_NON_UNIQ_ERROR 23000 
 	dan "Felt: '%-.64s' i tabel %s er ikke entydigt"
@@ -1774,7 +1774,7 @@
 	nla "Te grote kolomlengte voor '%-.64s' (max = %d). Maak hiervoor gebruik van het type BLOB"
-	eng "Column length too big for column '%-.64s' (max = %d); use BLOB instead"
+	eng "Column length too big for column '%-.64s' (max = %d); use BLOB or TEXT instead"
 	fre "Champ '%-.64s' trop long (max = %d). Utilisez un BLOB"
@@ -1789,7 +1789,7 @@
 	por "Comprimento da coluna '%-.64s' grande demais (max = %d); use BLOB em seu lugar"
 	rum "Lungimea coloanei '%-.64s' este prea lunga (maximum = %d). Foloseste BLOB mai bine"
 	spa "Longitud de columna demasiado grande para la columna '%-.64s' (maximo = %d).Usar BLOB en su lugar"
@@ -4637,7 +4637,7 @@
 	spa "Usuario '%-.64s' ha excedido el recurso '%s' (actual valor: %ld)"
-ER_SPECIFIC_ACCESS_DENIED_ERROR  
+ER_SPECIFIC_ACCESS_DENIED_ERROR 42000 
 	nla "Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie"
 	eng "Access denied; you need the %-.128s privilege for this operation"
@@ -5094,7 +5094,7 @@
 ER_SP_BADRETURN 42000 
 	eng "RETURN is only allowed in a FUNCTION"
 ER_SP_BADSTATEMENT 0A000 
-	eng "LOCK and UNLOCK tables are not allowed in stored procedures"
+	eng "%s is not allowed in stored procedures"
 ER_UPDATE_LOG_DEPRECATED_IGNORED 42000 
 	eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored"
 ER_UPDATE_LOG_DEPRECATED_TRANSLATED 42000 
@@ -5213,7 +5213,7 @@
 	eng "View '%-.64s.%-.64s' references invalid table(s) or column(s) or function(s)"
 ER_SP_NO_DROP_SP  
-	eng "Can't drop a %s from within another stored routine"
+	eng "Can't drop or alter a %s from within another stored routine"
 ER_SP_GOTO_IN_HNDLR  
 	eng "GOTO is not allowed in a stored procedure handler"
 ER_TRG_ALREADY_EXISTS  
@@ -5332,5 +5332,13 @@
 	eng "%s: ready for connections.\nVersion: '%s'  socket: '%s'  port: %d  %s"
 ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR
         eng "Can't load value from file with fixed size rows to variable"
-ER_CHANNEL_NOT_EXISTS
-	eng "Named master '%s' does not exist"
+ER_CANT_CREATE_USER_WITH_GRANT 42000
+	eng "You are not allowed to create a user with GRANT"
+ER_WRONG_VALUE_FOR_TYPE  
+	eng "Incorrect %-.32s value: '%-.128s' for function %-.32s"
+ER_TABLE_DEF_CHANGED
+	eng "Table definition has changed, please retry transaction"
+ER_SP_DUP_HANDLER 42000
+	eng "Duplicate handler declared in the same block"
+ER_SP_NOT_VAR_ARG 42000
+	eng "OUT or INOUT argument %d for routine %s is not a variable"

--- 1.195/sql/ha_innodb.cc	Tue Apr 19 08:38:11 2005
+++ 1.196/sql/ha_innodb.cc	Mon Apr 25 23:34:21 2005
@@ -32,7 +32,7 @@
 #endif
 
 #include "mysql_priv.h"
-#include "slave.h"
+#include <rpl/slave.h>
 
 #ifdef HAVE_INNOBASE_DB
 #include <m_ctype.h>
@@ -1374,6 +1374,24 @@
 #ifdef HAVE_REPLICATION
         THD *thd=current_thd;
 
+/*
+  TODO:
+  Since we now have multi-master, it is not possible to do save the 
+  binary position in this way.  What is needed is something 
+  similar to this:
+
+  MASTER_INFO *mi;  int i=0;
+  for (mi= mic.get_head(); mi; mi= mic.get_next(), i++)
+  { 
+    trx->channel[i]= mi->channel;
+    trx->mysql_master_log_file_name[i]= mi->rli.group_master_log_name;
+    trx->mysql_master_log_pos[i]=
+      ((ib_longlong) mi->rli.future_group_master_log_pos);
+  }
+
+  /LARS
+*/
+#if 0
         if (thd && thd->slave_thread) {
                 /* Update the replication position info inside InnoDB */
 
@@ -1382,6 +1400,7 @@
                 trx->mysql_master_log_pos = ((ib_longlong)
                                 active_mi->rli.future_group_master_log_pos);
         }
+#endif /* 0 */
 #endif /* HAVE_REPLICATION */
 
 	trx_commit_for_mysql(trx);

--- 1.106/sql/set_var.cc	Sat Apr 23 00:05:00 2005
+++ 1.107/sql/set_var.cc	Tue Apr 26 00:31:04 2005
@@ -54,7 +54,8 @@
 
 #include "mysql_priv.h"
 #include <mysql.h>
-#include "slave.h"
+#include <rpl/slave.h>
+#include <rpl/mic.h>
 #include <my_getopt.h>
 #include <thr_alarm.h>
 #include <myisam.h>
@@ -121,6 +122,8 @@
 void fix_sql_mode_var(THD *thd, enum_var_type type);
 static byte *get_error_count(THD *thd);
 static byte *get_warning_count(THD *thd);
+static bool sys_update_master(THD *thd, set_var *var);
+static int  sys_check_master(THD *thd, set_var *var);
 
 /*
   Variable definition list
@@ -495,6 +498,14 @@
 					  OPTION_RELAXED_UNIQUE_CHECKS,
 					  1);
 
+/* Variables that are strings in THD */
+
+#ifdef HAVE_REPLICATION
+static sys_var_thd_str	sys_master("master", 
+				   sys_check_master,
+				   sys_update_master);
+#endif
+
 /* Local state variables */
 
 static sys_var_thd_ha_rows	sys_select_limit("sql_select_limit",
@@ -598,6 +609,7 @@
   &sys_log_warnings,
   &sys_long_query_time,
   &sys_low_priority_updates,
+  &sys_master,
   &sys_max_allowed_packet,
   &sys_max_binlog_cache_size,
   &sys_max_binlog_size,
@@ -852,6 +864,9 @@
   {sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS},
   {"lower_case_file_system",  (char*) &lower_case_file_system,      SHOW_MY_BOOL},
   {"lower_case_table_names",  (char*) &lower_case_table_names,      SHOW_INT},
+#ifdef HAVE_REPLICATION
+  {"master",                  (char*) &sys_master,                  SHOW_SYS},
+#endif
   {sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet,	    SHOW_SYS},
   {sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS},
   {sys_max_binlog_size.name,    (char*) &sys_max_binlog_size,	    SHOW_SYS},
@@ -1273,8 +1288,13 @@
                      max_binlog_size, max_relay_log_size));
   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);
+  Master_info *mi;
+  // Lets make all relay logs have this max size
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
+  {
+    if (!max_relay_log_size)
+      mi->rli.relay_log.set_max_size(max_binlog_size);
+  }
 #endif
   DBUG_VOID_RETURN;
 }
@@ -1285,8 +1305,13 @@
   DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
                      max_binlog_size, max_relay_log_size));
 #ifdef HAVE_REPLICATION
-  active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
-                                        max_relay_log_size: max_binlog_size);
+  Master_info *mi;
+  // Lets make all relay logs have this max size
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
+  {
+    mi->rli.relay_log.set_max_size(max_relay_log_size ?
+				   max_relay_log_size: max_binlog_size);
+  }
 #endif
   DBUG_VOID_RETURN;
 }
@@ -1780,7 +1805,6 @@
   return (byte*) &thd->sys_var_tmp.my_bool_value;
 }
 
-
 /* Update a date_time format variable based on given value */
 
 void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type,
@@ -2192,7 +2216,6 @@
  }
 }
 
-
 bool sys_var_collation_server::update(THD *thd, set_var *var)
 {
   if (var->type == OPT_GLOBAL)
@@ -2383,6 +2406,54 @@
   return error;
 }
 
+bool sys_var_thd_str::check(THD *thd, set_var *var)
+{
+  int res;
+  if (!check_func)
+    return 0;
+
+  if ((res=(*check_func)(thd, var)) < 0)
+    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+             name, var->value->str_value.ptr());
+  return res;
+}
+
+
+static int sys_check_master(THD *thd, set_var *var)
+{
+  printf("LARS: sys_check_master var->value->str_value.c_ptr()=%s\n",
+	var->value->str_value.c_ptr());
+  printf("LARS: thd->variables.master=%s\n", thd->variables.master);
+  var->save_result.str_value= var->value->str_value.c_ptr();
+  return 0;
+}
+
+
+static bool sys_update_master(THD *thd, set_var *var)
+{
+  const char *res= 0;
+  pthread_mutex_lock(&LOCK_active_mi);
+  String *str= &var->value->str_value;
+  printf("LARS: sys_update_master var->value->str_value->ptr()=%s\n", str->ptr());
+  printf("LARS: thd->variables.master2=%s\n", thd->variables.master);
+  if (!(res= my_strdup_with_length(str->ptr(), str->length(), MYF(0))))
+    return 1;
+
+  my_free((char *) thd->variables.master, MYF(MY_ALLOW_ZERO_PTR));
+  thd->variables.master= res;
+  printf("LARS: thd->variables.master3=%s\n", thd->variables.master);
+
+  pthread_mutex_unlock(&LOCK_active_mi);
+  return 0;
+}
+
+
+// LARS: Generalize this... And SHOW VARIABLES does not work...
+byte *sys_var_thd_str::value_ptr(THD *thd, enum_var_type type,
+				 LEX_STRING *base)
+{
+  return (byte*) &thd->variables.master;
+}
 
 /*****************************************************************************
   Functions to handle SET NAMES and SET CHARACTER SET
@@ -2461,13 +2532,18 @@
 {
   int result= 0;
   pthread_mutex_lock(&LOCK_active_mi);
-  pthread_mutex_lock(&active_mi->rli.run_lock);
-  if (active_mi->rli.slave_running)
+  /* Check if any channel is running */
+  Master_info *mi;
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
   {
-    my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
-    result=1;
+    pthread_mutex_lock(&mi->rli.run_lock);
+    if (mi->rli.slave_running)
+    {
+      my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
+      result=1;
+    }
+    pthread_mutex_unlock(&mi->rli.run_lock);
   }
-  pthread_mutex_unlock(&active_mi->rli.run_lock);
   pthread_mutex_unlock(&LOCK_active_mi);
   var->save_result.ulong_value= (ulong) var->value->val_int();
   return result;
@@ -2477,19 +2553,24 @@
 bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
 {
   pthread_mutex_lock(&LOCK_active_mi);
-  pthread_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)
+  /* Check if any channel is running */
+  Master_info *mi;
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
   {
-    pthread_mutex_lock(&active_mi->rli.data_lock);
-    active_mi->rli.slave_skip_counter= var->save_result.ulong_value;
-    pthread_mutex_unlock(&active_mi->rli.data_lock);
+    pthread_mutex_lock(&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 (!mi->rli.slave_running)
+    {
+      pthread_mutex_lock(&mi->rli.data_lock);
+      mi->rli.slave_skip_counter= var->save_result.ulong_value;
+      pthread_mutex_unlock(&mi->rli.data_lock);
+    }
+    pthread_mutex_unlock(&mi->rli.run_lock);
   }
-  pthread_mutex_unlock(&active_mi->rli.run_lock);
   pthread_mutex_unlock(&LOCK_active_mi);
   return 0;
 }
@@ -2887,8 +2968,8 @@
     First run a check of all variables that all updates will go ok.
     If yes, then execute all updates, returning an error if any one failed.
 
-    This should ensure that in all normal cases none all or variables are
-    updated
+    This should ensure that in all normal cases either none or all of the 
+    variables are updated.
 
     RETURN VALUE
     0	ok
@@ -2912,7 +2993,12 @@
   {
     it.rewind();
     while ((var= it++))
+    {
+      printf("LARS: sql_set_variables\n");
+      //printf("LARS: Set var value: %s\n", var->value->val_str(NULL));
+
       error|= var->update(thd);         // Returns 0, -1 or 1
+    }
   }
 
 err:

--- 1.63/sql/set_var.h	Tue Mar 22 00:24:59 2005
+++ 1.64/sql/set_var.h	Mon Apr 25 23:34:23 2005
@@ -20,6 +20,8 @@
 #pragma interface			/* gcc class implementation */
 #endif
 
+#include <rpl/mic.h>
+
 /****************************************************************************
   Variables that are changable runtime are declared using the
   following classes
@@ -419,6 +421,30 @@
   byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
 };
 
+class sys_var_thd_str :public sys_var_thd
+{
+  sys_check_func check_func;
+  sys_update_func update_func;
+public:
+//  const char *value;
+  sys_var_thd_str(const char *name_arg, 
+                  sys_check_func c_func, 
+		  sys_update_func u_func)
+    :sys_var_thd(name_arg), check_func(c_func), update_func(u_func)
+  {}
+  bool check(THD *thd, set_var *var);
+  bool update(THD *thd, set_var *var)
+  {
+    return (*update_func)(thd, var);
+  }
+  bool check_update_type(Item_result type) { return 0; }
+  // LARS: Check this...
+  bool check_type(enum_var_type type) { return type == OPT_SESSION; }
+//  byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+//  { return (byte*) value; }
+  SHOW_TYPE type() { return SHOW_CHAR; }
+  byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+};
 
 /* some variables that require special handling */
 
@@ -770,6 +796,7 @@
     ulonglong ulonglong_value;
     DATE_TIME_FORMAT *date_time_format;
     Time_zone *time_zone;
+    const char *str_value;
   } save_result;
   LEX_STRING base;			/* for structs */
 

--- 1.82.1.6/sql/slave.h	Fri Apr  1 22:17:26 2005
+++ 1.88/sql/rpl/slave.h	Tue Apr 26 00:31:04 2005
@@ -16,16 +16,14 @@
 
 #ifdef HAVE_REPLICATION
 
-#ifndef SLAVE_H
-#define SLAVE_H
+#ifndef _slave_h
+#define _slave_h
 
 #include "mysql.h"
 #include "my_list.h"
-#include "rpl_filter.h"
-
-#define SLAVE_NET_TIMEOUT  3600
-#define MAX_SLAVE_ERRMSG   1024
-#define MAX_SLAVE_ERROR    2000
+#include <rpl/filter.h>
+#include <rpl/rli.h>
+#include <rpl/mi.h>
 
 /*****************************************************************************
 
@@ -36,11 +34,11 @@
     I/O Thread - One of these threads is started for each master server.
                  They maintain a connection to their master server, read log
                  events from the master as they arrive, and queues them into
-                 a single, shared relay log file.  A MASTER_INFO struct
+                 a single, shared relay log file.  A Master_info class
                  represents each of these threads.
 
     SQL Thread - One of these threads is started and reads from the relay log
-                 file, executing each event.  A RELAY_LOG_INFO struct
+                 file, executing each event.  A Relay_log_info class
                  represents this thread.
 
   Buffering in the relay log file makes it unnecessary to reread events from
@@ -48,33 +46,32 @@
   the master where long-running updates and event logging are concerned--ie
   it can continue to log new events while a slow query executes on the slave.
 
-*****************************************************************************/
-
-/*
   MUTEXES in replication:
 
-  LOCK_active_mi: [note: this was originally meant for multimaster, to switch
-  from a master to another, to protect active_mi] It is used to SERIALIZE ALL
-  administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE
-  MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not
-  need it it's called early]. Any of these commands holds the mutex from the
-  start till the end. This thus protects us against a handful of deadlocks
-  (consider start_slave_thread() which, when starting the I/O thread, releases
-  mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock).
-
-  Currently active_mi never moves (it's created at startup and deleted at
-  shutdown, and not changed: it always points to the same MASTER_INFO struct),
-  because we don't have multimaster. So for the moment, mi does not move, and
-  mi->rli does not either.
-
-  In MASTER_INFO: run_lock, data_lock
-  run_lock protects all information about the run state: slave_running, and the
-  existence of the I/O thread (to stop/start it, you need this mutex).
-  data_lock protects some moving members of the struct: counters (log name,
-  position) and relay log (MYSQL_LOG object).
-
-  In RELAY_LOG_INFO: run_lock, data_lock
-  see MASTER_INFO
+  - LOCK_active_mi
+    Used to serialize all administrative replication commands: 
+    START SLAVE, STOP SLAVE, CHANGE MASTER, RESET SLAVE,
+    end_all_channels() (when mysqld stops) [init_slave() does not need it
+    since it is called early].
+
+    All of these commands hold the mutex from start until end. This
+    protects us against a handful of deadlocks (consider
+    start_slave_thread() which, when starting the I/O thread, releases
+    mi->run_lock, keeps rli->run_lock, and tries to re-acquire
+    mi->run_lock).
+
+  - Master_info::run_lock
+    Protects all information about the run state: slave_running, and
+    the existence of the I/O thread (to stop/start it, you need this
+    mutex).
+  
+  - Master_info::data_lock 
+    Protects some moving members of the struct: 
+    counters (log name, position) and relay log (MYSQL_LOG object).
+
+  - Relay_log_info::run_lock
+  - Relay_log_info::data_lock
+    See Master_info
   
   Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
   must acquire LOCK_active_mi first.
@@ -82,7 +79,8 @@
   In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log
   LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
   (so that you have to update the .index file).
-*/
+
+*****************************************************************************/
 
 extern ulong master_retry_count;
 extern MY_BITMAP slave_error_mask;
@@ -93,377 +91,6 @@
 extern my_bool opt_skip_slave_start, opt_reckless_slave;
 extern my_bool opt_log_slave_updates;
 extern ulonglong relay_log_space_limit;
-struct st_master_info;
-
-/*
-  3 possible values for MASTER_INFO::slave_running and
-  RELAY_LOG_INFO::slave_running.
-  The values 0,1,2 are very important: to keep the diff small, I didn't
-  substitute places where we use 0/1 with the newly defined symbols. So don't change
-  these values.
-  The same way, code is assuming that in RELAY_LOG_INFO we use only values
-  0/1.
-  I started with using an enum, but
-  enum_variable=1; is not legal so would have required many line changes.
-*/
-#define MYSQL_SLAVE_NOT_RUN         0
-#define MYSQL_SLAVE_RUN_NOT_CONNECT 1
-#define MYSQL_SLAVE_RUN_CONNECT     2
-
-/****************************************************************************
-
-  Replication SQL Thread
-
-  st_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
-
-  st_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()
-
-*****************************************************************************/
-
-typedef struct st_relay_log_info
-{
-  /*** 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;
-
-  /*
-    Protected with internal locks.
-    Must get data_lock when resetting the logs.
-  */
-  MYSQL_LOG relay_log;
-  LOG_INFO linfo;
-  IO_CACHE cache_buf,*cur_log;
-
-  /* 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
-    thread, read only by SQL thread.
-  */
-  TABLE *save_temporary_tables;
-
-  /*
-    standard lock acquistion order to avoid deadlocks:
-    run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
-  */
-  pthread_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
-  */
-  pthread_cond_t start_cond, stop_cond, data_cond;
-
-  /* parent master info structure */
-  struct st_master_info *mi;
-
-  /*
-    Needed to deal properly with cur_log getting closed and re-opened with
-    a different log under our feet
-  */
-  uint32 cur_log_old_open_count;
-  
-  /*
-    Let's call a group (of events) :
-      - a transaction
-      or
-      - an autocommiting query + its associated events (INSERT_ID,
-    TIMESTAMP...)
-    We need these rli coordinates :
-    - relay log name and position of the beginning of the group we currently are
-    executing. Needed to know where we have to restart when replication has
-    stopped in the middle of a group (which has been rolled back by the slave).
-    - relay log name and position just after the event we have just
-    executed. This event is part of the current group.
-    Formerly we only had the immediately above coordinates, plus a 'pending'
-    variable, but this dealt wrong with the case of a transaction starting on a
-    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.
-  */
-  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
-     binlog the log_pos that comes with each event is the position of the
-     beginning of the group.
-  */
-  char group_master_log_name[FN_REFLEN];
-  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
-    mode).
-  */
-#if MYSQL_VERSION_ID < 40100
-  ulonglong future_master_log_pos;
-#else
-  ulonglong future_group_master_log_pos;
-#endif
-
-  time_t last_master_timestamp; 
-
-  /*
-    Needed for problems when slave stops and we want to restart it
-    skipping one or more events in the master log that have caused
-    errors, and have been manually applied by DBA already.
-  */
-  volatile uint32 slave_skip_counter;
-  volatile ulong abort_pos_wait;	/* Incremented on change master */
-  volatile ulong slave_run_id;		/* Incremented on slave start */
-  pthread_mutex_t log_space_lock;
-  pthread_cond_t log_space_cond;
-  THD * sql_thd;
-  int last_slave_errno;
-#ifndef DBUG_OFF
-  int events_till_abort;
-#endif  
-  char last_slave_error[MAX_SLAVE_ERRMSG];
-
-  /* if not set, the value of other members of the structure are undefined */
-  bool inited;
-  volatile bool abort_slave;
-  volatile uint slave_running;
-
-  /* 
-     Condition and its parameters from START SLAVE UNTIL clause.
-     
-     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;
-  /* extension extracted from log_name and converted to int */
-  ulong until_log_name_extension;   
-  /* 
-     Cached result of comparison of until_log_name and current log name
-     -2 means unitialised, -1,0,1 are comarison results 
-  */
-  enum 
-  { 
-    UNTIL_LOG_NAMES_CMP_UNKNOWN= -2, UNTIL_LOG_NAMES_CMP_LESS= -1,
-    UNTIL_LOG_NAMES_CMP_EQUAL= 0, UNTIL_LOG_NAMES_CMP_GREATER= 1
-  } until_log_names_cmp_result;
-
-  char cached_charset[6];
-  /*
-    trans_retries varies between 0 to slave_transaction_retries and counts how
-    many times the slave has retried the present transaction; gets reset to 0
-    when the transaction finally succeeds. retried_trans is a cumulative
-    counter: how many times the slave has retried a transaction (any) since
-    slave started.
-  */
-  ulong trans_retries, retried_trans;
-
-  st_relay_log_info();
-  ~st_relay_log_info();
-
-  /*
-    Invalidate 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.
-  */
-  inline void notify_group_relay_log_name_update()
-  {
-    if (until_condition==UNTIL_RELAY_POS)
-      until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
-  }
-
-  /*
-    The same as previous but for group_master_log_name. 
-  */
-  inline void notify_group_master_log_name_update()
-  {
-    if (until_condition==UNTIL_MASTER_POS)
-      until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
-  }
-  
-  inline void inc_event_relay_log_pos()
-  {
-    event_relay_log_pos= future_event_relay_log_pos;
-  }
-
-  void inc_group_relay_log_pos(ulonglong log_pos,
-			       bool skip_lock=0);
-
-  int wait_for_pos(THD* thd, String* log_name, longlong log_pos, 
-		   longlong timeout);
-  void close_temporary_tables();
-
-  /* Check if UNTIL condition is satisfied. See slave.cc for more. */
-  bool is_until_satisfied();
-  inline ulonglong until_pos()
-  {
-    return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
-	    group_relay_log_pos);
-  }
-  /*
-    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
-    changing from event to event (common situation).
-    When the 6 bytes are equal to 0 is used to mean "cache is invalidated".
-  */
-  void cached_charset_invalidate();
-  bool cached_charset_compare(char *charset);
-} RELAY_LOG_INFO;
-
-
-Log_event* next_event(RELAY_LOG_INFO* rli);
-
-/*****************************************************************************
-
-  Replication IO Thread
-
-  st_master_info contains:
-    - information about how to connect to a master
-    - current master log name
-    - current master log offset
-    - misc control variables
-
-  st_master_info is initialized once from the master.info file 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.
-
-  The format of master.info file:
-
-  log_name
-  log_pos
-  master_host
-  master_user
-  master_pass
-  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 clean up, call end_master_info()
-
-*****************************************************************************/
-
-typedef struct st_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];
-  my_bool ssl; // enables use of SSL connection if true
-  char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
-  char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
-
-  my_off_t master_log_pos;
-  File fd; // we keep the file open, so we need to remember the file pointer
-  IO_CACHE file;
-
-  pthread_mutex_t data_lock,run_lock;
-  pthread_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;
-  uint port;
-  uint connect_retry;
-#ifndef DBUG_OFF
-  int events_till_abort;
-#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.
-     clock_diff_with_master is computed when the I/O thread starts; for this the
-     I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
-     "how late the slave is compared to the master" is computed like this:
-     clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
-
-  */
-  long clock_diff_with_master;
-
-  st_master_info()
-    :ssl(0), fd(-1),  io_thd(0), inited(0),
-     abort_slave(0),slave_running(0), slave_run_id(0)
-  {
-    host[0] = 0; user[0] = 0; password[0] = 0;
-    ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
-    ssl_cipher[0]= 0; ssl_key[0]= 0;
-
-    bzero((char*) &file, sizeof(file));
-    pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
-    pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
-    pthread_cond_init(&data_cond, NULL);
-    pthread_cond_init(&start_cond, NULL);
-    pthread_cond_init(&stop_cond, NULL);
-  }
-
-  ~st_master_info()
-  {
-    pthread_mutex_destroy(&run_lock);
-    pthread_mutex_destroy(&data_lock);
-    pthread_cond_destroy(&data_cond);
-    pthread_cond_destroy(&start_cond);
-    pthread_cond_destroy(&stop_cond);
-  }
-
-} MASTER_INFO;
-
-
-int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
-
-#define MAX_SLAVE_ERRMSG      1024
 
 #define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
  "FIRST")
@@ -482,18 +109,15 @@
 
 int init_slave();
 void init_slave_skip_errors(const char* arg);
-bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache);
-bool flush_relay_log_info(RELAY_LOG_INFO* rli);
 int register_slave_on_master(MYSQL* mysql);
-int terminate_slave_threads(MASTER_INFO* mi, int thread_mask,
-			     bool skip_lock = 0);
+int terminate_slave_threads(Master_info* mi, int thread_mask,
+                             bool skip_lock = 0);
 int terminate_slave_thread(THD* thd, pthread_mutex_t* term_mutex,
-			   pthread_mutex_t* cond_lock,
-			   pthread_cond_t* term_cond,
-			   volatile uint* slave_running);
+                           pthread_mutex_t* cond_lock,
+                           pthread_cond_t* term_cond,
+                           volatile uint* slave_running);
 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
@@ -501,74 +125,58 @@
   pthread_cond_wait() on start_cond,start_lock
 */
 int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
-		       pthread_mutex_t *cond_lock,
-		       pthread_cond_t* start_cond,
-		       volatile uint *slave_running,
-		       volatile ulong *slave_run_id,
-		       MASTER_INFO* mi,
+                       pthread_mutex_t *cond_lock,
+                       pthread_cond_t* start_cond,
+                       volatile uint *slave_running,
+                       volatile ulong *slave_run_id,
+                       Master_info* mi,
                        bool high_priority);
 
 /* If fd is -1, dump to NET */
 int mysql_table_dump(THD* thd, const char* db,
-		     const char* tbl_name, int fd = -1);
+                     const char* tbl_name, int fd = -1);
 
 /* retrieve table from master and copy to slave*/
+int load_master_table(THD* thd, const char* db_name, const char* table_name,
+                      const char* channel, MYSQL* mysql, bool overwrite);
 int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
-		       MASTER_INFO* mi, MYSQL* mysql, bool overwrite);
+                       Master_info* mi, MYSQL* mysql, bool overwrite);
 
-bool show_master_info(THD* thd, MASTER_INFO* mi);
+bool show_slave_stat(THD* thd, const char* channel);
 bool show_binlog_info(THD* thd);
 
 const char *print_slave_db_safe(const char *db);
-int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
+int check_expected_error(THD* thd, Relay_log_info* rli, int error_code);
 void skip_load_data_infile(NET* net);
-void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...);
+void slave_print_error(Relay_log_info* rli, int err_code, const char* msg, ...);
 
-void end_slave(); /* clean up */
-void init_master_info_with_options(MASTER_INFO* mi);
-void clear_until_condition(RELAY_LOG_INFO* rli);
-void clear_slave_error(RELAY_LOG_INFO* rli);
-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);
-void end_relay_log_info(RELAY_LOG_INFO* rli);
-void lock_slave_threads(MASTER_INFO* mi);
-void unlock_slave_threads(MASTER_INFO* mi);
-void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse);
-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);
+void end_all_channels(); /* clean up */
+void init_thread_mask(int* mask,Master_info* mi,bool inverse);
 
-int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
-		     const char** errmsg);
 void set_slave_thread_options(THD* thd);
 void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli);
-void rotate_relay_log(MASTER_INFO* mi);
+void rotate_all_relay_logs();
+void rotate_relay_log(Master_info* mi);
 
 extern "C" pthread_handler_decl(handle_slave_io,arg);
 extern "C" pthread_handler_decl(handle_slave_sql,arg);
 extern bool volatile abort_loop;
-extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
-extern LIST master_list;
+
 extern bool replicate_same_server_id;
 
-extern int disconnect_slave_event_count, abort_slave_event_count ;
+extern int disconnect_slave_event_count, abort_slave_event_count;
 
 /* the master variables are defaults read from my.cnf or command line */
-extern uint master_port, master_connect_retry, report_port;
-extern my_string master_user, master_password, master_host,
-       master_info_file, relay_log_info_file, report_user, report_host,
-       report_password;
-
-extern my_bool master_ssl;
-extern my_string master_ssl_ca, master_ssl_capath, master_ssl_cert,
-       master_ssl_cipher, master_ssl_key;
-       
+extern uint report_port;
+extern my_string master_info_file;
+extern my_string relay_log_info_file;
+extern my_string report_user;
+extern my_string report_host;
+extern my_string report_password;
+
 extern I_List<THD> threads;
 
-#endif
+#endif /* SLAVE_H */
 #else
 #define SLAVE_IO  1
 #define SLAVE_SQL 2
Thread
bk commit into 5.1 tree (lars:1.1800)Lars Thalmann26 Apr