List:Commits« Previous MessageNext Message »
From:hezhenxing Date:July 5 2007 10:35am
Subject:bk commit into 5.2 tree (hezx:1.2510)
View as plain text  
Below is the list of changes that have just been committed into a local
5.2 repository of hezx. When hezx 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@stripped, 2007-07-05 16:33:31+08:00, hezx@hezx.(none) +7 -0
  use masters table to store user defined master names

  scripts/mysql_system_tables.sql@stripped, 2007-07-05 16:09:46+08:00, hezx@hezx.(none) +2 -0
    use a system table 'masters' to store user defined master names

  sql/slave.cc@stripped, 2007-07-05 16:09:57+08:00, hezx@hezx.(none) +59 -49
    use a system table 'masters' to store user defined master names

  sql/slave.h@stripped, 2007-07-05 16:09:57+08:00, hezx@hezx.(none) +1 -1
    use a system table 'masters' to store user defined master names

  sql/slave.h@stripped, 2007-07-03 16:15:07+08:00, hezx@hezx.(none) +1 -1
    *** empty log message ***

  sql/sql_parse.cc@stripped, 2007-06-29 13:55:41+08:00, hezx@hezx.(none) +1 -1
    fixed create/drop master for multi-master

  sql/sql_repl.cc@stripped, 2007-07-05 16:09:59+08:00, hezx@hezx.(none) +185 -53
    use a system table 'masters' to store user defined master names

  sql/sql_repl.cc@stripped, 2007-06-29 13:55:41+08:00, hezx@hezx.(none) +24 -11
    fixed create/drop master for multi-master

  sql/sql_repl.h@stripped, 2007-07-05 16:09:59+08:00, hezx@hezx.(none) +91 -3
    use a system table 'masters' to store user defined master names

  sql/sql_repl.h@stripped, 2007-06-29 13:55:42+08:00, hezx@hezx.(none) +2 -1
    fixed create/drop master for multi-master

  sql/sql_yacc.yy@stripped, 2007-06-29 13:55:43+08:00, hezx@hezx.(none) +15 -16
    fixed create/drop master for multi-master

# 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:	hezx
# Host:	hezx.(none)
# Root:	/media/hda5/work/mysql/mysql-5.2

--- 1.310/sql/slave.cc	2007-07-05 16:34:46 +08:00
+++ 1.311/sql/slave.cc	2007-07-05 16:34:46 +08:00
@@ -32,6 +32,7 @@
 
 #include "rpl_tblmap.h"
 
+
 int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
 static Log_event* next_event(RELAY_LOG_INFO* rli);
 
@@ -184,74 +185,82 @@
   DBUG_RETURN(1);
 }
 
-int init_slave()
+int init_main_master()
 {
-  int fd;
-  IO_CACHE ic;
-  
-  DBUG_ENTER("init_slave");
-
-  pthread_mutex_lock(&LOCK_active_mi);
-
-  /* Create the default master info structure */
-
   MASTER_INFO *mi= new MASTER_INFO;
-  init_sql_alloc(&slave_mem_root, 1024, 0);
-
-  //mi->set_name("MAIN");
   active_mi= mi;
   master_list.push_back(mi, &slave_mem_root);
 
-  init_one_master(mi);
+  return init_one_master(mi);
+}
+
+int init_masters()
+{
+  int error= 1;
+  TABLE_LIST tables;
+  TABLE *table;
+  READ_RECORD read_record_info;
+  MEM_ROOT mem;
+  MASTER_INFO *mi;
+  THD *thd = new THD;
   
-  if (access(master_list_file, F_OK))
-  {
+  thd->thread_stack= (char *)&thd;
+  thd->store_globals();
+
+  init_sql_alloc(&slave_mem_root, 1024, 0);
+  init_sql_alloc(&mem, 1024, 0);
+  
+  if (init_main_master())
     goto out;
-  }
-  fd = my_open(master_list_file, O_RDONLY|O_BINARY, MYF(MY_WME));
-  if (fd < 0)
-  {
-    sql_print_error("Failed to open master list file '%s', errno %d",
-		    master_list_file, my_errno);
-    goto open_err;
-  }
 
-  if (init_io_cache(&ic, fd, IO_SIZE * 2,
-		    READ_CACHE, 0L, 0, MYF(MY_WME)))
+  bzero((char*) &tables, sizeof(tables));
+  tables.db= (char*) "mysql";
+  tables.alias= tables.table_name= (char*) "masters";
+  
+  if (simple_open_n_lock_tables(thd, &tables))
   {
-    sql_print_error("Failed to create a cache on master list file '%s'",
-		    master_list_file);
-    goto init_io_err;
+    sql_print_error("Can't open and lock privilege tables: %s",
+		    thd->net.last_error);
+    goto out;
   }
 
-  while (true)
+  table= tables.table;
+  table->use_all_columns();
+  
+  init_read_record(&read_record_info,thd,
+		   table, NULL, 1, 0);
+  while (!(read_record_info.read_record(&read_record_info)))
   {
-    char name[MASTER_NAME_LEN + 1];
-    if (init_strvar_from_file(name, sizeof(name), &ic, ""))
-    {
-      goto err;
-    }
-    if (name[0] == '\0')
-      break;
+    char *name= get_field(&mem, table->field[0]);
     mi = new MASTER_INFO;
     mi->set_name(name);
+    
     master_list.push_back(mi, &slave_mem_root);
     init_one_master(mi);
   }
-
+  
+  end_read_record(&read_record_info);
 out:
-  pthread_mutex_unlock(&LOCK_active_mi);
-  DBUG_RETURN(0);
+  free_root(&mem, MYF(0));
+  close_thread_tables(thd);
+  /* Remember that we don't have a THD */
+  delete thd;
+  my_pthread_setspecific_ptr(THR_THD,  0);
+  return error;
+}
 
-err:
-  sql_print_error("Error reading master list file '%s'",
-		  master_list_file);
-  end_io_cache(&ic);
-init_io_err:
-  my_close(fd, MYF(MY_WME));
-open_err:
+int init_slave()
+{
+  int error= 1;
+  
+  DBUG_ENTER("init_slave");
+
+  pthread_mutex_lock(&LOCK_active_mi);
+
+  error= init_masters();
+  
   pthread_mutex_unlock(&LOCK_active_mi);
-  DBUG_RETURN(1);
+  DBUG_RETURN(error);
 }
 #else
 
@@ -1140,7 +1149,8 @@
   if (send_master_info_fields(thd))
     goto err;
   
-  if(slaves_action((SLAVE_ACTION)send_master_info_data, thd, 0))
+  if(slaves_action<bool>(slave_action1<THD*, bool>(send_master_info_data,
thd),
+			  thd, 0))
     goto err;
 
   send_eof(thd);

--- 1.670/sql/sql_parse.cc	2007-07-05 16:34:46 +08:00
+++ 1.671/sql/sql_parse.cc	2007-07-05 16:34:46 +08:00
@@ -1878,7 +1878,7 @@
     if (check_global_access(thd, SUPER_ACL))
       goto error;
     pthread_mutex_lock(&LOCK_active_mi);
-    res= create_master(thd);
+    res= create_masters(thd);
     pthread_mutex_unlock(&LOCK_active_mi);
     break;
   }

--- 1.572/sql/sql_yacc.yy	2007-07-05 16:34:46 +08:00
+++ 1.573/sql/sql_yacc.yy	2007-07-05 16:34:47 +08:00
@@ -1456,7 +1456,7 @@
 	  bzero((char*) &lex->mi, sizeof(lex->mi));
 	  lex->mi.master_list.empty();
         }
-        master_list TO_SYM master_defs
+        master_list_all TO_SYM master_defs
 	{}
        | CHANGE ACTIVE_SYM MASTER_SYM master_name
         {
@@ -1465,17 +1465,20 @@
 	}
        ;
 
-master_list:
-       /* empty */
+master_list_all:
+       master_list
+       | ALL
        {
          LEX *lex = Lex;
-	 lex->mi.all = 0;
+	 lex->mi.all = 1;
 	 lex->mi.master_list.empty();
        }
-       | ALL
+
+master_list:
+       /* empty */
        {
          LEX *lex = Lex;
-	 lex->mi.all = 1;
+	 lex->mi.all = 0;
 	 lex->mi.master_list.empty();
        }
        | master_names
@@ -1500,10 +1503,6 @@
 	}
        ;
 
-master_definition:
-       | AS master_defs
-       ;
-       
 master_defs:
        master_def
        | master_defs ',' master_def;
@@ -1700,7 +1699,7 @@
 	  {
 	    Lex->sql_command= SQLCOM_CREATE_SERVER;
           }
-	| CREATE MASTER_SYM master_name master_definition
+	| CREATE MASTER_SYM master_names
 	  {
 #ifdef USE_MULTI_MASTER
 	    Lex->sql_command= SQLCOM_CREATE_MASTER;
@@ -5704,7 +5703,7 @@
 */
 
 slave:
-	  START_SYM SLAVE slave_thread_opts master_list
+	  START_SYM SLAVE slave_thread_opts master_list_all
           {
 	    LEX *lex=Lex;
             lex->sql_command = SQLCOM_SLAVE_START;
@@ -5717,14 +5716,14 @@
           }
           slave_until
           {}
-        | STOP_SYM SLAVE slave_thread_opts master_list
+        | STOP_SYM SLAVE slave_thread_opts master_list_all
           {
 	    LEX *lex=Lex;
             lex->sql_command = SQLCOM_SLAVE_STOP;
 	    lex->type = 0;
             /* If you change this code don't forget to update SLAVE STOP too */
           }
-	| SLAVE START_SYM slave_thread_opts master_list
+	| SLAVE START_SYM slave_thread_opts master_list_all
          {
 	   LEX *lex=Lex;
            lex->sql_command = SQLCOM_SLAVE_START;
@@ -5736,7 +5735,7 @@
           }
           slave_until
           {}
-	| SLAVE STOP_SYM slave_thread_opts master_list
+	| SLAVE STOP_SYM slave_thread_opts master_list_all
          {
 	   LEX *lex=Lex;
            lex->sql_command = SQLCOM_SLAVE_STOP;
@@ -8828,7 +8827,7 @@
           {
 	    Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
           }
-        | SLAVE STATUS_SYM master_list
+        | SLAVE STATUS_SYM master_list_all
           {
 	    Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
           }

--- 1.11/scripts/mysql_system_tables.sql	2007-07-05 16:34:47 +08:00
+++ 1.12/scripts/mysql_system_tables.sql	2007-07-05 16:34:47 +08:00
@@ -80,3 +80,5 @@
 
 CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File
VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL,
updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT
UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
 
+CREATE TABLE IF NOT EXISTS masters (name CHAR(64) NOT NULL, PRIMARY KEY(name));
+

--- 1.108/sql/slave.h	2007-07-05 16:34:47 +08:00
+++ 1.110/sql/slave.h	2007-07-05 16:34:47 +08:00
@@ -211,7 +211,7 @@
 #ifdef USE_MULTI_MASTER
 extern MEM_ROOT slave_mem_root;
 extern List<MASTER_INFO> master_list;
-#define MASTER_NAME_LEN 16
+#define MASTER_NAME_LEN 64
 #endif
 
 extern int disconnect_slave_event_count, abort_slave_event_count ;

--- 1.171/sql/sql_repl.cc	2007-07-05 16:34:47 +08:00
+++ 1.173/sql/sql_repl.cc	2007-07-05 16:34:47 +08:00
@@ -761,58 +761,21 @@
 }
 
 #ifdef USE_MULTI_MASTER
-int slaves_action(SLAVE_ACTION slave_action,
-		  THD* thd, bool net_report)
-{
-  MASTER_INFO *mi;
 
-  if (thd->lex->mi.all)
-  {
-    List_iterator<MASTER_INFO> iter(master_list);
-    while ((mi = iter++))
-    {
-      if (slave_action(mi, thd))
-	goto err;
-    }
-  }
-  else if (thd->lex->mi.master_list.is_empty())
-  {
-    if (slave_action(active_mi, thd))
-    {
-      goto err;
-    }
-  }
-  else
-  {
-    List_iterator<LEX_STRING> iter(thd->lex->mi.master_list);
-    LEX_STRING *name;
-    while ((name = iter++))
-    {
-      mi= get_master_info(name->str);
-      if (!mi)
-      {
-	my_error(ER_MASTER_INFO, MYF(0),
-		 "Master '%s' not found", name->str);
-	goto err;
-      }
 
-      if(slave_action(mi, thd))
-      {
-	goto err;
-      }
-    }
-  }
-  if (net_report)
-    send_ok(thd);
-  return FALSE;
-err:
-  return TRUE;
-}
+/* explicitly instantiate the templates we used */
+template class slave_action<int>;
+template class slave_action<bool>;
+template class slave_action1 <TABLE_LIST*>;
+template int slaves_action<int>(const slave_action<int>&, THD*, bool);
+template int slaves_action<bool>(const slave_action<bool>&, THD*, bool);
 
+template class slave_action1<THD*>;
 int start_slaves(THD* thd, bool net_report)
 {
   DBUG_ENTER("start_slaves");
-  int res= slaves_action(start_slave, thd, net_report);
+  int res= slaves_action(slave_action1<THD*>(start_slave, thd),
+			 thd, net_report);
   DBUG_RETURN(res);
 }
 #endif
@@ -958,7 +921,8 @@
   if (!thd)
     thd= current_thd;
 
-  int res= slaves_action(stop_slave, thd, net_report);
+  int res= slaves_action(slave_action1<THD*>(stop_slave, thd),
+			  thd, net_report);
   DBUG_RETURN(res);
 }
 #endif
@@ -1164,28 +1128,122 @@
   return (MASTER_INFO *)NULL;
 }
 
+static void
+store_master_fields(TABLE *table, MASTER_INFO *mi)
+{
+
+  table->use_all_columns();
+
+#if NOT_USED_YET
+  if (mi->master_log_name)
+    table->field[1]->store(mi->master_log_name,
+                           (uint) strlen(mi->master_log_name), system_charset_info);
+  if (mi->master_log_pos)
+    table->field[2]->store(mi->master_log_pos,
+                           (uint) strlen(mi->master_log_pos), system_charset_info);
+  if (mi->host)
+    table->field[3]->store(mi->host,
+                           (uint) strlen(mi->host), system_charset_info);
+  if (mi->user)
+    table->field[4]->store(mi->user,
+                           (uint) strlen(mi->user), system_charset_info);
+  if (mi->password)
+    table->field[5]->store(mi->password,
+                           (uint) strlen(mi->password), system_charset_info);
+  if (mi->port > -1)
+    table->field[6]->store(mi->port);
+
+  if (mi->connect_retry)
+    table->field[7]->store(mi->connect_retry,
+                           (uint) strlen(mi->connect_retry), system_charset_info);
+  if (mi->ssl)
+    table->field[8]->store(mi->ssl,
+                           (uint) strlen(mi->ssl), system_charset_info);
+  if (mi->ssl_ca)
+    table->field[9]->store(mi->ssl_ca,
+                           (uint) strlen(mi->ssl_ca), system_charset_info);
+  if (mi->ssl_capath)
+    table->field[10]->store(mi->ssl_capath,
+                           (uint) strlen(mi->ssl_capath), system_charset_info);
+  if (mi->ssl_cert)
+    table->field[11]->store(mi->ssl_cert,
+                           (uint) strlen(mi->ssl_cert), system_charset_info);
+  if (mi->ssl_key)
+    table->field[12]->store(mi->ssl_key,
+                           (uint) strlen(mi->ssl_key), system_charset_info);
+  if (mi->ssl_cipher)
+    table->field[13]->store(mi->ssl_cipher,
+                           (uint) strlen(mi->ssl_cipher), system_charset_info);
+  if (mi->ssl_verify_server_cert)
+    table->field[14]->store(mi->ssl_verify_server_cert,
+                           (uint) strlen(mi->ssl_verify_serve_cert),
system_charset_info);
+#endif
+}
+
+static
+int insert_master_record(TABLE *table, MASTER_INFO *mi)
+{
+  int error;
+  DBUG_ENTER("insert_master_record");
+  table->use_all_columns();
+
+  empty_record(table);
+
+  /* set the field that's the PK to the value we're looking for */
+  table->field[0]->store(mi->master_name,
+                         strlen(mi->master_name),
+                         system_charset_info);
+
+  /* read index until record is that specified in server_name */
+  if ((error= table->file->index_read_idx(table->record[0], 0,
+                                   (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
+                                   HA_READ_KEY_EXACT)))
+  {
+    /* if not found, err */
+    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
+    {
+      table->file->print_error(error, MYF(0));
+      error= 1;
+    }
+
+    /* store each field to be inserted */
+    store_master_fields(table, mi);
+
+    DBUG_PRINT("info",("record for master '%s' not found!",
+                       mi->master_name));
+    /* write/insert the new master */
+    if ((error=table->file->ha_write_row(table->record[0])))
+    {
+      table->file->print_error(error, MYF(0));
+    }
+    else
+      error= 0;
+  }
+  else
+    error= ER_MASTER_INFO;	// FIXME: define ER_MASTER_INFO_EXISTS for this
+  DBUG_RETURN(error);
+}
+
 /**
    @brief Create a master on slave for replication
 
    @detials Create a master information file on slave for replication.
 
    @param[in] thd The handler thread structure
-   @param[out] mi The master information structure
 
    @reutrn Operation status
      @retval 0   ok
      @retval 1   failed
  */
 
-bool create_master(THD* thd)
+bool create_master(THD* thd, char *name, TABLE_LIST *tables)
 {
   DBUG_ENTER("create_master");
 
-  char *master_name= thd->lex->mi.master_list.head()->str;
-  if (get_master_info(master_name))
+  if (get_master_info(name))
   {
     my_error(ER_MASTER_INFO, MYF(0),
-	     "Master '%s' alread exist", master_name);
+	     "Master '%s' alread exist", name);
     DBUG_RETURN(TRUE);
   }
   MASTER_INFO *mi = new MASTER_INFO;
@@ -1195,26 +1253,87 @@
 	     "Can not allocation memory for master info structure");
     DBUG_RETURN(1);
   }
-  mi->set_name(master_name);
+  mi->set_name(name);
   int res = init_master_info(mi, master_info_file,
 			     relay_log_info_file, 0, 0);
   if (res)
   {
     my_error(ER_MASTER_INFO, MYF(0),
-	     "Initial master info failed for '%s'", master_name);
+	     "Initial master info failed for '%s'", name);
     delete mi;
     DBUG_RETURN(1);
   }
-  
+
+  int error;
+  if ((error= insert_master_record(tables[0].table, mi)))
+    DBUG_RETURN(error);
   master_list.push_back(mi, &slave_mem_root);
-  send_ok(thd);
   DBUG_RETURN(0);
 }
 
-bool drop_master(MASTER_INFO *mi, THD *thd)
+bool create_masters(THD *thd)
+{
+  DBUG_ENTER("create_masters");
+
+  LEX_STRING *name;
+  List_iterator<LEX_STRING> iter(thd->lex->mi.master_list);
+
+  TABLE_LIST tables;
+  TABLE *table;
+  bzero((char*) &tables, sizeof(tables));
+  tables.db= (char*) "mysql";
+  tables.alias= tables.table_name= (char*) "masters";
+
+  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
+    DBUG_RETURN(1);
+  
+  while ((name= iter++))
+  {
+    if (create_master(thd, name->str, &tables))
+      goto err;
+  }
+  send_ok(thd);
+  close_thread_tables(thd);
+  DBUG_RETURN(FALSE);
+err:
+  close_thread_tables(thd);
+  DBUG_RETURN(TRUE);
+}
+
+static int 
+delete_master_record(TABLE *table,
+                     char *master_name)
+{
+  int error;
+  DBUG_ENTER("delete_master_record");
+  table->use_all_columns();
+
+  /* set the field that's the PK to the value we're looking for */
+  table->field[0]->store(master_name, strlen(master_name), system_charset_info);
+
+  if ((error= table->file->index_read_idx(table->record[0], 0,
+                                   (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
+                                   HA_READ_KEY_EXACT)))
+  {
+    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
+      table->file->print_error(error, MYF(0));
+    DBUG_PRINT("info",("master not found!"));
+    error= ER_MASTER_INFO;	// FIXME
+  }
+  else
+  {
+    if ((error= table->file->ha_delete_row(table->record[0])))
+      table->file->print_error(error, MYF(0));
+  }
+
+  DBUG_RETURN(error);
+}
+
+int drop_master(MASTER_INFO *mi, TABLE_LIST *tables)
 {
+  TABLE *table= tables[0].table;
   int thread_mask= 0;
-  MASTER_INFO *m;
+  int error;
   List_iterator<MASTER_INFO> element;
   
   DBUG_ENTER("drop_master");
@@ -1240,6 +1359,15 @@
 
   unlock_slave_threads(mi);
   element.remove();		// remove current node
+
+  error= delete_master_record(table, mi->master_name);
+  if (error)
+  {
+    my_error(error, MYF(0),
+	     "Delete master from masters table failed!");
+    goto err;
+  }
+
   DBUG_RETURN(FALSE);
 err_locked:
   unlock_slave_threads(mi);
@@ -1251,11 +1379,27 @@
 {
   DBUG_ENTER("drop_masters");
 
-  if(slaves_action((SLAVE_ACTION)drop_master, thd, 1))
+  TABLE_LIST tables;
+  TABLE *table;
+  
+  bzero((char*) &tables, sizeof(tables));
+  tables.db= (char*) "mysql";
+  tables.alias= tables.table_name= (char*) "masters";
+  
+  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
+  {
+    my_error(my_errno, MYF(0),
+	     "Open masters table failed!");
+    goto err;
+  }
+
+  if(slaves_action(slave_action1<TABLE_LIST*>(drop_master, &tables), thd, 1))
     goto err;
 
   DBUG_RETURN(FALSE);
+  close_thread_tables(thd);
 err:
+  close_thread_tables(thd);
   DBUG_RETURN(TRUE);
 }
 
@@ -1279,11 +1423,12 @@
   DBUG_RETURN(FALSE);
 }
 
+template class slave_action1<THD*, bool>;
 bool change_masters(THD* thd)
 {
   DBUG_ENTER("change_masters");
 
-  if (slaves_action((SLAVE_ACTION)change_master, thd, 1))
+  if (slaves_action<bool>(slave_action1<THD*, bool>(change_master, thd), thd,
1))
     DBUG_RETURN(TRUE);
   DBUG_RETURN(FALSE);
 }

--- 1.46/sql/sql_repl.h	2007-07-05 16:34:47 +08:00
+++ 1.48/sql/sql_repl.h	2007-07-05 16:34:47 +08:00
@@ -43,10 +43,99 @@
                         } while(0)
 
 #ifdef USE_MULTI_MASTER
+
+template <class R=int>class slave_action
+{
+public:
+  typedef R result_type;
+  typedef result_type (*action_type)(MASTER_INFO*);
+
+protected:
+  slave_action() :action(0) {}
+public:
+  slave_action(action_type _action)
+    :action(_action)
+  {}
+  virtual result_type operator()(MASTER_INFO* mi) const
+  {
+    return action(mi);
+  }
+  virtual ~slave_action() {}
+private:
+  action_type action;
+};
+
+template <class A, class R=int> class slave_action1 :public slave_action<R> {
+public:
+  typedef R result_type;
+  typedef A arg1_type;
+  typedef result_type (*action_type)(MASTER_INFO*, A);
+
+  slave_action1(action_type _action, arg1_type _arg1)
+     :action(_action), arg1(_arg1)
+  {}
+  virtual result_type operator() (MASTER_INFO *mi) const
+  {
+    return action(mi, arg1);
+  }
+  virtual ~slave_action1() {}
+private:
+  action_type action;
+  arg1_type arg1;
+};
+
+template <class R> int
+slaves_action(const slave_action<R>& action,
+	       THD *thd, bool net_report)
+{
+  MASTER_INFO *mi;
+
+  if (thd->lex->mi.all)
+  {
+    List_iterator<MASTER_INFO> iter(master_list);
+    while ((mi = iter++))
+    {
+      if (action(mi))
+	goto err;
+    }
+  }
+  else if (thd->lex->mi.master_list.is_empty())
+  {
+    if (action(active_mi))
+    {
+      goto err;
+    }
+  }
+  else
+  {
+    List_iterator<LEX_STRING> iter(thd->lex->mi.master_list);
+    LEX_STRING *name;
+    while ((name = iter++))
+    {
+      mi= get_master_info(name->str);
+      if (!mi)
+      {
+	my_error(ER_MASTER_INFO, MYF(0),
+		 "Master '%s' not found", name->str);
+	goto err;
+      }
+
+      if(action(mi))
+      {
+	goto err;
+      }
+    }
+  }
+  if (net_report)
+    send_ok(thd);
+  return FALSE;
+err:
+  return TRUE;
+}
+
 MASTER_INFO *get_master_info(char *name);
-typedef int (*SLAVE_ACTION)(MASTER_INFO*, THD*);
-int slaves_action(SLAVE_ACTION slave_action, THD* thd, bool net_report);
-bool create_master(THD* thd);
+bool create_masters(THD* thd);
+bool create_master(THD* thd, char *name, TABLE_LIST* tables);
 bool drop_masters(THD* thd);
 int start_slave(MASTER_INFO*, THD*);
 int stop_slave(MASTER_INFO*, THD*);
Thread
bk commit into 5.2 tree (hezx:1.2510)hezhenxing5 Jul