List:Internals« Previous MessageNext Message »
From:sasha Date:May 6 2002 8:23pm
Subject:bk commit into 4.0 tree
View as plain text  
Below is the list of changes that have just been committed into a
4.0 repository of sasha. When sasha does a push, they will be propogated 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://www.mysql.com/doc/I/n/Installing_source_tree.html

ChangeSet@stripped, 2002-05-06 14:23:26-06:00, sasha@stripped
  initial multi-master work - will not be pushed until 4.0.2 is out

  mysql-test/r/rpl_multi_master.result
    1.1 02/05/06 14:22:51 sasha@stripped +10 -0

  mysql-test/t/rpl_multi_master.test
    1.1 02/05/06 14:22:51 sasha@stripped +6 -0

  mysql-test/r/rpl000015.result
    1.20 02/05/06 14:22:51 sasha@stripped +1 -1
    fixed result

  mysql-test/r/rpl000017.result
    1.5 02/05/06 14:22:51 sasha@stripped +5 -0
    fixed result

  mysql-test/r/rpl_multi_master.result
    1.0 02/05/06 14:22:51 sasha@stripped +0 -0
    BitKeeper file /reiser-data/mysql-multi-master/mysql-test/r/rpl_multi_master.result

  mysql-test/t/rpl000015-slave.sh
    1.4 02/05/06 14:22:51 sasha@stripped +1 -0
    cleanup

  mysql-test/t/rpl000016-slave.sh
    1.5 02/05/06 14:22:51 sasha@stripped +1 -1
    cleanup

  mysql-test/t/rpl000017-slave.sh
    1.9 02/05/06 14:22:51 sasha@stripped +1 -1
    cleanup

  mysql-test/t/rpl000017.test
    1.8 02/05/06 14:22:51 sasha@stripped +5 -0
    cleaner test

  mysql-test/t/rpl_multi_master.test
    1.0 02/05/06 14:22:51 sasha@stripped +0 -0
    BitKeeper file /reiser-data/mysql-multi-master/mysql-test/t/rpl_multi_master.test

  sql/log.cc
    1.81 02/05/06 14:22:51 sasha@stripped +10 -3
    better error messaging/debug info

  sql/slave.cc
    1.167 02/05/06 14:22:51 sasha@stripped +130 -68
    multi-master work

  sql/slave.h
    1.38 02/05/06 14:22:51 sasha@stripped +19 -7
    mutli-master work

  sql/sql_lex.h
    1.67 02/05/06 14:22:51 sasha@stripped +1 -0
    multi-master

  sql/sql_parse.cc
    1.222 02/05/06 14:22:51 sasha@stripped +8 -3
    mutli-master

  sql/sql_repl.cc
    1.76 02/05/06 14:22:51 sasha@stripped +101 -2
    multi-master

  sql/sql_repl.h
    1.18 02/05/06 14:22:51 sasha@stripped +2 -0
    multi-master

  sql/sql_yacc.yy
    1.155 02/05/06 14:22:51 sasha@stripped +11 -1
    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:	sasha
# Host:	mysql.sashanet.com
# Root:	/reiser-data/mysql-multi-master

--- 1.80/sql/log.cc	Fri Apr 12 12:35:41 2002
+++ 1.81/sql/log.cc	Mon May  6 14:22:51 2002
@@ -173,6 +173,7 @@
   File file= -1;
   bool do_magic;
   int open_flags = O_CREAT | O_APPEND | O_BINARY;
+  DBUG_ENTER("MYSQL_LOG::open");
   if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name))
       no_rotate = 1;
   init(log_type_arg,io_cache_type_arg,no_auto_events_arg);
@@ -255,14 +256,19 @@
     error=(my_write(index_file, (byte*) log_file_name, strlen(log_file_name),
 		    MYF(MY_NABP | MY_WME)) ||
 	   my_write(index_file, (byte*) "\n", 1, MYF(MY_NABP | MY_WME)));
+    DBUG_PRINT("info",("added %s to index file",log_file_name));
     pthread_mutex_unlock(&LOCK_index);
     if (error)
     {
+      DBUG_PRINT("info",("write error appending %s to log index %s",
+			 log_file_name,index_file_name));
+      sql_print_error("Write error appending %s to log index %s",
+		      log_file_name,index_file_name);
       close_index();
       goto err;
     }
   }
-  return;
+  DBUG_VOID_RETURN;
 
 err:
   sql_print_error("Could not use %s for logging (error %d)", log_name,errno);
@@ -271,7 +277,7 @@
   end_io_cache(&log_file);
   x_free(name); name=0;
   log_type=LOG_CLOSED;
-  return;
+  DBUG_VOID_RETURN;
 }
 
 int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
@@ -375,6 +381,7 @@
   int error=0;
   const char* save_name;
   enum_log_type save_log_type;
+  DBUG_ENTER("MYSQL_LOG::reset_logs");
   pthread_mutex_lock(&LOCK_log);
   if (find_first_log(&linfo,""))
   {
@@ -399,7 +406,7 @@
   my_free((gptr)save_name,MYF(0));
 err:  
   pthread_mutex_unlock(&LOCK_log);
-  return error;
+  DBUG_RETURN(error);
 }
 
 

--- 1.166/sql/slave.cc	Thu Apr 18 18:41:43 2002
+++ 1.167/sql/slave.cc	Mon May  6 14:22:51 2002
@@ -28,6 +28,7 @@
 
 bool use_slave_mask = 0;
 MY_BITMAP slave_error_mask;
+DYNAMIC_ARRAY master_list;
 
 typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
 
@@ -116,6 +117,11 @@
 
 int init_slave()
 {
+  if (init_dynamic_array(&master_list,sizeof(MASTER_INFO*),50,100))
+  {
+    sql_print_error("Could not initialize master list");
+    return 1;
+  }
   // TODO (multi-master): replace this with list initialization
   active_mi = &main_mi;
 
@@ -132,12 +138,13 @@
     MY_STAT stat_area;
     fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
     if (my_stat(fname, &stat_area, MYF(0)) &&
-	!init_master_info(active_mi,master_info_file,relay_log_info_file))
+	!init_master_info(active_mi,master_info_file,relay_log_info_file,0))
       master_host = active_mi->host;
   }
   // slave thread
   if (master_host)
   {
+    // TODO: multi-master re-write
     if (!opt_skip_slave_start && start_slave_threads(1 /* need mutex */,
 						     0 /* no wait for start*/,
 						     active_mi,
@@ -147,7 +154,8 @@
 						     ))
       sql_print_error("Warning: Can't create threads to handle slave");
     else if (opt_skip_slave_start)
-      if (init_master_info(active_mi, master_info_file, relay_log_info_file))
+      if (init_master_info(active_mi, master_info_file,
+			   relay_log_info_file,0))
 	sql_print_error("Warning: failed to initialized master info");
   }
   return 0;
@@ -280,8 +288,11 @@
 int purge_relay_logs(RELAY_LOG_INFO* rli, bool just_reset, const char** errmsg)
 {
   DBUG_ENTER("purge_relay_logs");
+  DBUG_PRINT("info",("rli->inited=%d",rli->inited));
   if (!rli->inited)
-    DBUG_RETURN(0); /* successfully do nothing */
+  {
+    DBUG_RETURN(0);
+  }
   DBUG_ASSERT(rli->slave_running == 0);
   DBUG_ASSERT(rli->mi->slave_running == 0);
   int error=0;
@@ -488,7 +499,7 @@
     lock_cond_io = &mi->run_lock;
     lock_cond_sql = &mi->rli.run_lock;
   }
-  if (init_master_info(mi,master_info_fname,slave_info_fname))
+  if (init_master_info(mi,master_info_fname,slave_info_fname,0))
     return ER_MASTER_INFO;
 
   if ((thread_mask & SLAVE_IO) &&
@@ -625,11 +636,18 @@
 
 void end_slave()
 {
-  // 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);
+  end_master_info(&main_mi);
+  uint i;
+  for (i=0;i<master_list.elements;i++)
+  {
+    MASTER_INFO* mi;
+    get_dynamic(&master_list,(gptr)&mi,i);
+    terminate_slave_threads(mi,SLAVE_FORCE_ALL);
+    end_master_info(mi);
+    delete mi;
+  }
+  
   if (do_table_inited)
     hash_free(&replicate_do_table);
   if (ignore_table_inited)
@@ -973,7 +991,8 @@
   mi->inited = 0;
 }
 
-int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
+int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname,
+			const char* master_ident)
 {
   DBUG_ENTER("init_relay_log_info");
   if (rli->inited)
@@ -983,6 +1002,8 @@
   int info_fd;
   const char* msg = 0;
   int error = 0;
+  const char* relay_log_base = opt_relay_logname,
+    *relay_log_index = opt_relaylog_index_name;
   fn_format(fname, info_fname,
 	    mysql_data_home, "", 4+32);
   pthread_mutex_lock(&rli->data_lock);
@@ -995,19 +1016,51 @@
   rli->skip_log_purge=0;
   rli->log_space_limit = relay_log_space_limit;
   rli->log_space_total = 0;
+  rli->last_slave_error[0]=0;
+  rli->last_slave_errno=0;
+
   // TODO: make this work with multi-master
-  if (!opt_relay_logname)
+  char tmp[FN_REFLEN],tmp1[FN_REFLEN];
+  int master_ident_len=0;
+  if (master_ident)
+    master_ident_len=strlen(master_ident)+1;
+
+  // TODO: see if the code below can be put into a function
+  if (!relay_log_base || master_ident_len)
+  {
+    char* p = tmp;
+    p = strmake(p,glob_hostname,FN_REFLEN-10);
+    if (p-tmp > FN_REFLEN-10-master_ident_len)
+    {
+      sql_print_error("relay log name too long");
+      return 1;
+    }
+    if (master_ident_len)
+    {
+      *p++ = '-';
+      p=strmov(p,master_ident);
+    }
+    
+    strmov(p,"-relay-bin");
+    relay_log_base=tmp;
+  }
+  
+  if (!relay_log_index || master_ident_len)
   {
-    char tmp[FN_REFLEN];
-    /* TODO: The following should be using fn_format();  We just need to
-       first change fn_format() to cut the file name if it's too long.
-    */
-    strmake(tmp,glob_hostname,FN_REFLEN-5);
-    strmov(strcend(tmp,'.'),"-relay-bin");
-    opt_relay_logname=my_strdup(tmp,MYF(MY_WME));
+    char* p = tmp;
+    p=strmake(p,"relay-log",FN_REFLEN-6);
+    if (master_ident_len)
+    {
+      *p++ = '-';
+      p=strmov(p,master_ident);
+    }
+    
+    strmov(p,".index");
+    relay_log_index=tmp;
   }
-  rli->relay_log.set_index_file_name(opt_relaylog_index_name);
-  open_log(&rli->relay_log, glob_hostname, opt_relay_logname, "-relay-bin",
+  
+  rli->relay_log.set_index_file_name(relay_log_index);
+  open_log(&rli->relay_log, glob_hostname, relay_log_base, "-relay-bin",
 	   LOG_BIN, 1 /* read_append cache */,
 	   1 /* no auto events*/);
   
@@ -1154,11 +1207,12 @@
 }
 
 int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
-		     const char* slave_info_fname)
+		     const char* slave_info_fname,
+		     const char* master_ident)
 {
   if (mi->inited)
     return 0;
-  if (init_relay_log_info(&mi->rli, slave_info_fname))
+  if (init_relay_log_info(&mi->rli, slave_info_fname, master_ident))
     return 1;
   mi->rli.mi = mi;
   mi->mysql=0;
@@ -1303,37 +1357,9 @@
   return 0;
 }
 
-int show_master_info(THD* thd, MASTER_INFO* mi)
+static int show_master_info_row(THD* thd, MASTER_INFO* mi)
 {
-  // TODO: fix this for multi-master
-  DBUG_ENTER("show_master_info");
-  List<Item> field_list;
-  field_list.push_back(new Item_empty_string("Master_Host",
-						     sizeof(mi->host)));
-  field_list.push_back(new Item_empty_string("Master_User",
-						     sizeof(mi->user)));
-  field_list.push_back(new Item_empty_string("Master_Port", 6));
-  field_list.push_back(new Item_empty_string("Connect_retry", 6));
-  field_list.push_back(new Item_empty_string("Master_Log_File",
-						     FN_REFLEN));
-  field_list.push_back(new Item_empty_string("Read_Master_Log_Pos", 12));
-  field_list.push_back(new Item_empty_string("Relay_Log_File",
-						     FN_REFLEN));
-  field_list.push_back(new Item_empty_string("Relay_Log_Pos", 12));
-  field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
-						     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));
-  field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20));
-  field_list.push_back(new Item_empty_string("Last_errno", 4));
-  field_list.push_back(new Item_empty_string("Last_error", 20));
-  field_list.push_back(new Item_empty_string("Skip_counter", 12));
-  field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12));
-  field_list.push_back(new Item_empty_string("Relay_log_space", 12));
-  if(send_fields(thd, field_list, 1))
-    DBUG_RETURN(-1);
-
+  DBUG_ENTER("show_master_info_row");
   String* packet = &thd->packet;
   packet->length(0);
   
@@ -1363,7 +1389,54 @@
   
   if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
     DBUG_RETURN(-1);
+  
+  DBUG_RETURN(0);
+}
+
+int show_master_info(THD* thd)
+{
+  // TODO: fix this for multi-master
+  DBUG_ENTER("show_master_info");
+  List<Item> field_list;
+  field_list.push_back(new Item_empty_string("Master_Host",
+						     sizeof(main_mi.host)));
+  field_list.push_back(new Item_empty_string("Master_User",
+						     sizeof(main_mi.user)));
+  field_list.push_back(new Item_empty_string("Master_Port", 6));
+  field_list.push_back(new Item_empty_string("Connect_retry", 6));
+  field_list.push_back(new Item_empty_string("Master_Log_File",
+						     FN_REFLEN));
+  field_list.push_back(new Item_empty_string("Read_Master_Log_Pos", 12));
+  field_list.push_back(new Item_empty_string("Relay_Log_File",
+						     FN_REFLEN));
+  field_list.push_back(new Item_empty_string("Relay_Log_Pos", 12));
+  field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
+						     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));
+  field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20));
+  field_list.push_back(new Item_empty_string("Last_errno", 4));
+  field_list.push_back(new Item_empty_string("Last_error", 20));
+  field_list.push_back(new Item_empty_string("Skip_counter", 12));
+  field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12));
+  field_list.push_back(new Item_empty_string("Relay_log_space", 12));
+  if(send_fields(thd, field_list, 1))
+    DBUG_RETURN(-1);
 
+  
+  if (show_master_info_row(thd,&main_mi))
+    DBUG_RETURN(-1);
+
+  uint i;
+  for (i=0;i<master_list.elements;i++)
+  {
+    MASTER_INFO *mi;
+    get_dynamic(&master_list, (gptr)&mi, i);
+    if (show_master_info_row(thd,mi))
+      DBUG_RETURN(-1);
+  }
+  
   send_eof(&thd->net);
   DBUG_RETURN(0);
 }
@@ -1567,10 +1640,7 @@
 
 static ulong read_event(MYSQL* mysql, MASTER_INFO *mi)
 {
-  ulong len = packet_error;
-  // for convinience lets think we start by
-  // being in the interrupted state :-)
-  int read_errno = EINTR;
+  ulong len;
 
   // my_real_read() will time us out
   // we check if we were told to die, and if not, try reading again
@@ -1579,27 +1649,20 @@
     return packet_error;      
 #endif
   
-  while (!abort_loop && !mi->abort_slave && len == packet_error &&
-	 read_errno == EINTR )
-  {
-    len = mc_net_safe_read(mysql);
-    read_errno = errno;
-  }
-  if (abort_loop || mi->abort_slave)
-    return packet_error;
+  len = mc_net_safe_read(mysql);
   if (len == packet_error || (long) len < 1)
   {
-    sql_print_error("Error reading packet from server: %s (read_errno %d,\
+    sql_print_error("Error reading packet from server: %s (\
 server_errno=%d)",
-		    mc_mysql_error(mysql), read_errno, mc_mysql_errno(mysql));
+		    mc_mysql_error(mysql),mc_mysql_errno(mysql));
     return packet_error;
   }
 
   if (len == 1)
   {
      sql_print_error("Slave: received 0 length packet from server, apparent\
- master shutdown: %s (%d)",
-		     mc_mysql_error(mysql), read_errno);
+ master shutdown: %s",
+		     mc_mysql_error(mysql));
      return packet_error;
   }
   
@@ -2641,7 +2704,6 @@
   sql_print_error("Error reading relay log event: %s", errmsg);
   return 0;
 }
-
 
 #ifdef __GNUC__
 template class I_List_iterator<i_string>;

--- 1.66/sql/sql_lex.h	Fri Mar 15 18:44:43 2002
+++ 1.67/sql/sql_lex.h	Mon May  6 14:22:51 2002
@@ -57,6 +57,7 @@
   SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
   SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
   SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
+  SQLCOM_NEW_MASTER,
   SQLCOM_EMPTY_QUERY,
   SQLCOM_END
 };

--- 1.221/sql/sql_parse.cc	Tue Apr  2 07:54:57 2002
+++ 1.222/sql/sql_parse.cc	Mon May  6 14:22:51 2002
@@ -1317,6 +1317,13 @@
       delete result;
     break;
   }
+  case SQLCOM_NEW_MASTER:
+  {
+    if (check_process_priv(thd))
+      goto error;
+    res = add_new_master(thd, &lex->mi);
+    break;
+  }
   case SQLCOM_DO:
     res=mysql_do(thd, *lex->insert_list);
     break;
@@ -1385,9 +1392,7 @@
   {
     if (check_process_priv(thd))
       goto error;
-    LOCK_ACTIVE_MI;
-    res = show_master_info(thd,active_mi);
-    UNLOCK_ACTIVE_MI;
+    res = show_master_info(thd);
     break;
   }
   case SQLCOM_SHOW_MASTER_STAT:

--- 1.154/sql/sql_yacc.yy	Mon Apr 15 17:09:29 2002
+++ 1.155/sql/sql_yacc.yy	Mon May  6 14:22:51 2002
@@ -589,7 +589,7 @@
 	table_to_table_list table_to_table opt_table_list opt_as
 	handler_rkey_function handler_read_or_scan
 	single_multi table_wild_list table_wild_one opt_wild union union_list
-	precision union_option
+	precision union_option new
 END_OF_INPUT
 
 %type <NONE>
@@ -634,6 +634,7 @@
 	| load
 	| lock
 	| kill
+	| new
 	| optimize
 	| purge  
 	| rename
@@ -774,6 +775,15 @@
 	    lex->udf.returns=(Item_result) $7;
 	    lex->udf.dl=$9.str;
 	  };
+new:
+         NEW_SYM MASTER_SYM
+          {
+	    LEX *lex = Lex;
+	    lex->sql_command = SQLCOM_NEW_MASTER;
+	    memset(&lex->mi, 0, sizeof(lex->mi));
+          } 
+          master_defs;   
+
 
 create2:
 	'(' field_list ')' opt_create_table_options create3 {}

--- 1.37/sql/slave.h	Mon Apr 15 17:09:29 2002
+++ 1.38/sql/slave.h	Mon May  6 14:22:51 2002
@@ -159,7 +159,7 @@
   pthread_cond_t log_space_cond;
   
   st_relay_log_info():info_fd(-1),cur_log_fd(-1),inited(0),
-		      cur_log_init_count(0),
+		      cur_log_init_count(0),abort_slave(0),slave_running(0),
 		      log_pos_current(0),abort_pos_wait(0),
 		      skip_log_purge(0)
     {
@@ -278,9 +278,19 @@
   bool old_format;			// master binlog is in 3.23 format
   volatile bool abort_slave, slave_running;
   bool ignore_stop_event;
+
+  static void* operator new(size_t size)
+    {
+      return (void*)my_malloc((uint)size, MYF(MY_WME|MY_FAE));
+    }
+
+  static void operator delete(void* ptr, size_t size)
+    {
+      my_free((gptr)ptr,MYF(MY_WME));
+    }
   
-  
-  st_master_info():fd(-1), io_thd(0), inited(0), old_format(0)
+  st_master_info():fd(-1), io_thd(0), inited(0), old_format(0),
+		   abort_slave(0),slave_running(0)
   {
     host[0] = 0; user[0] = 0; password[0] = 0;
     bzero(&file,sizeof(file));
@@ -364,7 +374,7 @@
 int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
 		       MASTER_INFO* mi, MYSQL* mysql);
 
-int show_master_info(THD* thd, MASTER_INFO* mi);
+int show_master_info(THD* thd);
 int show_binlog_info(THD* thd);
 
 // See if the query uses any tables that should not be replicated
@@ -388,9 +398,11 @@
 
 void end_slave(); // clean up
 int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
-		     const char* slave_info_fname);
+		     const char* slave_info_fname,
+		     const char* master_ident);
 void end_master_info(MASTER_INFO* mi);
-int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
+int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname,
+			const char* master_ident);
 void end_relay_log_info(RELAY_LOG_INFO* rli);
 void lock_slave_threads(MASTER_INFO* mi);
 void unlock_slave_threads(MASTER_INFO* mi);
@@ -406,7 +418,7 @@
 extern bool volatile abort_loop;
 extern MASTER_INFO main_mi, *active_mi; // active_mi for multi-master
 extern volatile int active_mi_in_use;
-extern LIST master_list;
+extern DYNAMIC_ARRAY master_list;
 extern HASH replicate_do_table, replicate_ignore_table;
 extern DYNAMIC_ARRAY  replicate_wild_do_table, replicate_wild_ignore_table;
 extern bool do_table_inited, ignore_table_inited,

--- 1.19/mysql-test/r/rpl000015.result	Mon Apr  1 21:46:21 2002
+++ 1.20/mysql-test/r/rpl000015.result	Mon May  6 14:22:51 2002
@@ -5,7 +5,7 @@
 reset slave;
 show slave status;
 Master_Host	Master_User	Master_Port	Connect_retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_do_db	Replicate_ignore_db	Last_errno	Last_error	Skip_counter	Exec_master_log_pos	Relay_log_space
-		0	0		0		0		No	No			0		0	0	0
+	test	3306	7		4	slave-relay-bin.001	4		No	No			0		0	0	4
 change master to master_host='127.0.0.1';
 show slave status;
 Master_Host	Master_User	Master_Port	Connect_retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_do_db	Replicate_ignore_db	Last_errno	Last_error	Skip_counter	Exec_master_log_pos	Relay_log_space

--- 1.4/mysql-test/r/rpl000017.result	Wed Oct 10 18:59:44 2001
+++ 1.5/mysql-test/r/rpl000017.result	Mon May  6 14:22:51 2002
@@ -2,6 +2,11 @@
 grant file on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
 grant file on *.* to replicate@stripped identified by 'aaaaaaaaaaaaaaab';
 slave start;
+slave stop;
+reset slave;
+change master to master_host='127.0.0.1',master_user='replicate',
+master_password='aaaaaaaaaaaaaaab';
+slave start;
 drop table if exists t1;
 create table t1(n int);
 insert into t1 values(24);
--- New file ---
+++ mysql-test/r/rpl_multi_master.result	02/05/06 14:22:51
slave stop;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
slave start;
new master master_host='127.0.0.1',master_user='root',master_port=9308;
show slave status;
Master_Host	Master_User	Master_Port	Connect_retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_do_db	Replicate_ignore_db	Last_errno	Last_error	Skip_counter	Exec_master_log_pos	Relay_log_space
127.0.0.1	root	9306	1		4	slave-relay-bin.001	4		Yes	Yes			0		0	0	8
127.0.0.1	root	9308	1		4	relay-log-127.0.0.1,9308	4		No	No			0		0	0	4


--- 1.3/mysql-test/t/rpl000015-slave.sh	Sun Nov  4 06:48:14 2001
+++ 1.4/mysql-test/t/rpl000015-slave.sh	Mon May  6 14:22:51 2002
@@ -1 +1,2 @@
 rm -f $MYSQL_TEST_DIR/var/slave-data/master.info
+rm -f $MYSQL_TEST_DIR/var/log/*relay*

--- 1.4/mysql-test/t/rpl000016-slave.sh	Sat Jan 19 19:16:48 2002
+++ 1.5/mysql-test/t/rpl000016-slave.sh	Mon May  6 14:22:51 2002
@@ -1,2 +1,2 @@
 rm -f $MYSQL_TEST_DIR/var/slave-data/master.info
-rm -f $MYSQL_TEST_DIR/var/slave-data/*relay*
+rm -f $MYSQL_TEST_DIR/var/log/*relay*

--- 1.8/mysql-test/t/rpl000017-slave.sh	Sat Jan 26 22:26:22 2002
+++ 1.9/mysql-test/t/rpl000017-slave.sh	Mon May  6 14:22:51 2002
@@ -1,5 +1,5 @@
 rm -f $MYSQL_TEST_DIR/var/log/*relay*
-rm -f $MYSQL_TEST_DIR/var/slave-data/relay-log.info
+rm -f $MYSQL_TEST_DIR/var/slave-data/relay-log.*
 cat > $MYSQL_TEST_DIR/var/slave-data/master.info <<EOF
 master-bin.001
 4

--- 1.7/mysql-test/t/rpl000017.test	Wed Oct 10 18:59:42 2001
+++ 1.8/mysql-test/t/rpl000017.test	Mon May  6 14:22:51 2002
@@ -5,6 +5,11 @@
 grant file on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
 grant file on *.* to replicate@stripped identified by 'aaaaaaaaaaaaaaab';
 connection slave;
+!slave start;
+!slave stop;
+reset slave;
+change master to master_host='127.0.0.1',master_user='replicate',
+ master_password='aaaaaaaaaaaaaaab';
 slave start;
 connection master;
 drop table if exists t1;
--- New file ---
+++ mysql-test/t/rpl_multi_master.test	02/05/06 14:22:51
require_manager;
source include/master-slave.inc;
connection slave;
#TODO: change 9308 to be env variable
new master master_host='127.0.0.1',master_user='root',master_port=9308;
show slave status;


--- 1.75/sql/sql_repl.cc	Mon Apr  1 21:46:22 2002
+++ 1.76/sql/sql_repl.cc	Mon May  6 14:22:51 2002
@@ -630,11 +630,14 @@
   char fname[FN_REFLEN];
   int restart_thread_mask = 0,error=0;
   const char* errmsg=0;
+  const char* master_ident = 0; //TODO - initialize it to the active mi ident
+  bool delayed_relay_purge = !mi->rli.inited;
   
   lock_slave_threads(mi);
   init_thread_mask(&restart_thread_mask,mi,0 /* not inverse */);
   if ((error=terminate_slave_threads(mi,restart_thread_mask,1 /*skip lock*/))
-      || (error=purge_relay_logs(&mi->rli,1 /*just reset*/,&errmsg)))
+      || (!delayed_relay_purge &&
+	  (error=purge_relay_logs(&mi->rli,1 /*just reset*/,&errmsg))))
     goto err;
   
   end_master_info(mi);
@@ -650,6 +653,13 @@
     error=1;
     goto err;
   }
+  if (init_master_info(mi,master_info_file,relay_log_info_file,master_ident)
+      || (delayed_relay_purge &&
+	  purge_relay_logs(&mi->rli,1/*just reset*/,&errmsg)))
+  {
+    error=1;
+    goto err;
+  }
   if (restart_thread_mask)
       error=start_slave_threads(0 /* mutex not needed*/,
 			  1 /* wait for start*/,
@@ -707,7 +717,7 @@
   thd->proc_info = "changing master";
   LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
   // TODO: see if needs re-write
-  if (init_master_info(mi,master_info_file,relay_log_info_file))
+  if (init_master_info(mi,master_info_file,relay_log_info_file,0))
   {
     send_error(&thd->net, 0, "Could not initialize master info");
     unlock_slave_threads(mi);
@@ -1070,3 +1080,92 @@
   }
   return 0;
 }
+
+int mk_info_fname(char* buf, char* master_ident, char* base)
+{
+  char tmp[FN_REFLEN];
+  char* p;
+  // TODO: check for off-by-one bugs in the code below
+  strmake(tmp,base,FN_REFLEN);
+  p = strcend(tmp,'.');
+  if (p-tmp >= FN_REFLEN-7) // TODO: check if 7 is correct and explain why
+    return 1;
+  *p++ = '-';
+  strmake(p,master_ident,FN_REFLEN-(p-tmp));
+  return fn_format(buf,tmp,mysql_data_home,".info",
+	   MYF(MY_SAFE_PATH|MY_UNPACK_FILENAME
+	       |MY_RETURN_REAL_PATH|MY_REPLACE_EXT)) == 0;
+}
+
+int add_new_master(THD* thd, LEX_MASTER_INFO* lex_mi)
+{
+  const char* errmsg=0;
+  MASTER_INFO* mi = 0;
+  char* p;
+  char mi_fname[FN_REFLEN+128],
+     rli_fname[FN_REFLEN+128],
+     master_ident[FN_REFLEN]; //TODO: explain why 128 
+  
+  if (!lex_mi->host)
+  {
+    errmsg = "Missing master host";
+    goto err;
+  }
+  if (!lex_mi->user)
+  {
+    errmsg = "Missing master user";
+    goto err;
+  }
+
+  mi = new MASTER_INFO; // TODO - put this in a list 
+
+  p=strmake(master_ident,lex_mi->host,sizeof(master_ident)-6);
+  if (lex_mi->port)
+  {
+    *p++=',';
+    llstr(lex_mi->port,p);
+  }
+  
+  if (mk_info_fname(mi_fname,master_ident,master_info_file) ||
+      mk_info_fname(rli_fname,master_ident,relay_log_info_file))
+  {
+    errmsg = "Hostname too long";
+    goto err;
+  }
+  if (init_master_info(mi,mi_fname,rli_fname,master_ident))
+  {
+    errmsg = "Could not initialize master info structure";
+    goto err;
+  }
+  strmake(mi->host,lex_mi->host,sizeof(mi->host));
+  strmake(mi->user, lex_mi->user, sizeof(mi->user));
+  if (!lex_mi->log_file_name)
+    mi->master_log_name[0]=0;
+  else
+    strmake(mi->master_log_name, lex_mi->log_file_name,
+	    sizeof(mi->master_log_name));
+
+  mi->master_log_pos = lex_mi->pos ? lex_mi->pos : 4;
+
+  if (lex_mi->password)
+    strmake(mi->password, lex_mi->password, sizeof(mi->password));
+  if (lex_mi->port)
+    mi->port = lex_mi->port;
+  if (lex_mi->connect_retry)
+    mi->connect_retry = lex_mi->connect_retry;
+
+  if (flush_master_info(mi))
+  {
+    errmsg = "Error syncing master info to disk";
+    goto err;
+  }
+
+  insert_dynamic(&master_list,(gptr)&mi);
+  send_ok(&thd->net);
+  return 0;
+err:
+  delete mi;
+  send_error(&thd->net,0,errmsg);
+  return 1;
+}
+

--- 1.17/sql/sql_repl.h	Sat Jan 19 19:16:50 2002
+++ 1.18/sql/sql_repl.h	Mon May  6 14:22:51 2002
@@ -46,6 +46,8 @@
 extern int init_master_info(MASTER_INFO* mi);
 void kill_zombie_dump_threads(uint32 slave_server_id);
 int check_binlog_magic(IO_CACHE* log, const char** errmsg);
+int add_new_master(THD* thd, LEX_MASTER_INFO* lex_mi);
+int mk_info_fname(char* buf, char* master_ident, char* base);
 
 typedef struct st_load_file_info
 {
Thread
bk commit into 4.0 treesasha6 May