sql_repl.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:21k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. // Sasha Pachev <sasha@mysql.com> is currently in charge of this file
  14. // Do not mess with it without his permission!
  15. #include "mysql_priv.h"
  16. #include "sql_repl.h"
  17. #include "sql_acl.h"
  18. #include "log_event.h"
  19. #include <thr_alarm.h>
  20. #include <my_dir.h>
  21. extern const char* any_db;
  22. extern pthread_handler_decl(handle_slave,arg);
  23. static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
  24.      const char**errmsg)
  25. {
  26.   char header[LOG_EVENT_HEADER_LEN];
  27.   memset(header, 0, 4); // when does not matter
  28.   header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
  29.   char* p = strrchr(log_file_name, FN_LIBCHAR);
  30.   // find the last slash
  31.   if(p)
  32.     p++;
  33.   else
  34.     p = log_file_name;
  35.   uint ident_len = (uint) strlen(p);
  36.   ulong event_len = ident_len + sizeof(header);
  37.   int4store(header + EVENT_TYPE_OFFSET + 1, server_id);
  38.   int4store(header + EVENT_LEN_OFFSET, event_len);
  39.   packet->append(header, sizeof(header));
  40.   packet->append(p,ident_len);
  41.   if(my_net_write(net, (char*)packet->ptr(), packet->length()))
  42.     {
  43.       *errmsg = "failed on my_net_write()";
  44.       return -1;
  45.     }
  46.   return 0;
  47. }
  48. static int send_file(THD *thd)
  49. {
  50.   NET* net = &thd->net;
  51.   int fd = -1,bytes, error = 1;
  52.   char fname[FN_REFLEN+1];
  53.   char *buf;
  54.   const char *errmsg = 0;
  55.   int old_timeout;
  56.   uint packet_len;
  57.   DBUG_ENTER("send_file");
  58.   // the client might be slow loading the data, give him wait_timeout to do
  59.   // the job
  60.   old_timeout = thd->net.timeout;
  61.   thd->net.timeout = thd->inactive_timeout;
  62.   // spare the stack
  63.   if(!(buf = alloc_root(&thd->mem_root,IO_SIZE)))
  64.     {
  65.       errmsg = "Out of memory";
  66.       goto err;
  67.     }
  68.   // we need net_flush here because the client will not know it needs to send
  69.   // us the file name until it has processed the load event entry
  70.   if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error)
  71.   {
  72.     errmsg = "Failed reading file name";
  73.     goto err;
  74.   }
  75.   *((char*)net->read_pos +  packet_len) = 0; // terminate with 
  76.    //for fn_format
  77.   fn_format(fname, (char*)net->read_pos + 1, "", "", 4);
  78.   // this is needed to make replicate-ignore-db
  79.   if (!strcmp(fname,"/dev/null"))
  80.     goto end;
  81.   if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0)
  82.   {
  83.     errmsg = "Failed on my_open()";
  84.     goto err;
  85.   }
  86.   while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE,
  87. MYF(MY_WME))) > 0)
  88.   {
  89.     if (my_net_write(net, buf, bytes))
  90.     {
  91.       errmsg = "Failed on my_net_write()";
  92.       goto err;
  93.     }
  94.   }
  95.  end:
  96.   if (my_net_write(net, "", 0) || net_flush(net) ||
  97.       (my_net_read(net) == packet_error))
  98.   {
  99.     errmsg = "failed negotiating file transfer close";
  100.     goto err;
  101.   }
  102.   error = 0;
  103.  err:
  104.   thd->net.timeout = old_timeout;
  105.   if(fd >= 0)
  106.     (void) my_close(fd, MYF(MY_WME));
  107.   if (errmsg)
  108.   {
  109.     sql_print_error("failed in send_file() : %s", errmsg);
  110.     DBUG_PRINT("error", (errmsg));
  111.   }
  112.   DBUG_RETURN(error);
  113. }
  114. static File open_log(IO_CACHE *log, const char *log_file_name,
  115.      const char **errmsg)
  116. {
  117.   File file;
  118.   char magic[4];
  119.   if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 ||
  120.       init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
  121.     MYF(MY_WME)))
  122.   {
  123.     *errmsg = "Could not open log file"; // This will not be sent
  124.     goto err;
  125.   }
  126.   
  127.   if (my_b_read(log, (byte*) magic, sizeof(magic)))
  128.   {
  129.     *errmsg = "I/O error reading binlog magic number";
  130.     goto err;
  131.   }
  132.   if (memcmp(magic, BINLOG_MAGIC, 4))
  133.   {
  134.     *errmsg = "Binlog has bad magic number, fire your magician";
  135.     goto err;
  136.   }
  137.   return file;
  138. err:
  139.   if (file > 0)
  140.     my_close(file,MYF(0));
  141.   end_io_cache(log);
  142.   return -1;
  143. }
  144. void adjust_linfo_offsets(my_off_t purge_offset)
  145. {
  146.   THD *tmp;
  147.   
  148.   pthread_mutex_lock(&LOCK_thread_count);
  149.   I_List_iterator<THD> it(threads);
  150.   
  151.   while((tmp=it++))
  152.     {
  153.       LOG_INFO* linfo;
  154. if((linfo = tmp->current_linfo))
  155. {
  156.   pthread_mutex_lock(&linfo->lock);
  157.   // no big deal if we just started reading the log
  158.   // nothing to adjust
  159.   if(linfo->index_file_offset < purge_offset)
  160.     linfo->fatal = (linfo->index_file_offset != 0);
  161.   else
  162.     linfo->index_file_offset -= purge_offset;
  163.   pthread_mutex_unlock(&linfo->lock);
  164. }
  165.    }
  166.   pthread_mutex_unlock(&LOCK_thread_count);
  167. }
  168. bool log_in_use(const char* log_name)
  169. {
  170.   int log_name_len = strlen(log_name) + 1;
  171.   THD *tmp;
  172.   bool result = 0;
  173.   
  174.   pthread_mutex_lock(&LOCK_thread_count);
  175.   I_List_iterator<THD> it(threads);
  176.   
  177.   while((tmp=it++))
  178.     {
  179.       LOG_INFO* linfo;
  180.       if((linfo = tmp->current_linfo))
  181. {
  182.   pthread_mutex_lock(&linfo->lock);
  183.   result = !memcmp(log_name, linfo->log_file_name, log_name_len);
  184.   pthread_mutex_unlock(&linfo->lock);
  185.   if(result) break;
  186. }
  187.    }
  188.   pthread_mutex_unlock(&LOCK_thread_count);
  189.   return result;
  190. }
  191. int purge_master_logs(THD* thd, const char* to_log)
  192. {
  193.   char search_file_name[FN_REFLEN];
  194.   mysql_bin_log.make_log_name(search_file_name, to_log);
  195.   int res = mysql_bin_log.purge_logs(thd, search_file_name);
  196.   const char* errmsg = 0;
  197.   switch(res)
  198.     {
  199.     case 0: break;
  200.     case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break;
  201.     case LOG_INFO_IO: errmsg = "I/O error reading log index file"; break;
  202.     case LOG_INFO_INVALID: errmsg = "Server configuration does not permit 
  203. binlog purge"; break;
  204.     case LOG_INFO_SEEK: errmsg = "Failed on fseek()"; break;
  205.     case LOG_INFO_PURGE_NO_ROTATE: errmsg = "Cannot purge unrotatable log";
  206.       break;
  207.     case LOG_INFO_MEM: errmsg = "Out of memory"; break;
  208.     case LOG_INFO_FATAL: errmsg = "Fatal error during purge"; break;
  209.     case LOG_INFO_IN_USE: errmsg = "A purgeable log is in use, will not purge";
  210.       break;
  211.     default:
  212.       errmsg = "Unknown error during purge"; break;
  213.     }
  214.   
  215.   if(errmsg)
  216.     {
  217.      send_error(&thd->net, 0, errmsg);
  218.      return 1;
  219.     }
  220.   else
  221.     send_ok(&thd->net);
  222.   
  223.   return 0;
  224. }
  225. void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
  226. {
  227.   LOG_INFO linfo;
  228.   char *log_file_name = linfo.log_file_name;
  229.   char search_file_name[FN_REFLEN];
  230.   IO_CACHE log;
  231.   File file = -1;
  232.   String* packet = &thd->packet;
  233.   int error;
  234.   const char *errmsg = "Unknown error";
  235.   NET* net = &thd->net;
  236.   DBUG_ENTER("mysql_binlog_send");
  237.   bzero((char*) &log,sizeof(log));
  238.   if(!mysql_bin_log.is_open())
  239.   {
  240.     errmsg = "Binary log is not open";
  241.     goto err;
  242.   }
  243.   if(!server_id_supplied)
  244.     {
  245.       errmsg = "Misconfigured master - server id was not set";
  246.       goto err;
  247.     }
  248.   
  249.   if (log_ident[0])
  250.     mysql_bin_log.make_log_name(search_file_name, log_ident);
  251.   else
  252.     search_file_name[0] = 0;
  253.   
  254.   linfo.index_file_offset = 0;
  255.   thd->current_linfo = &linfo;
  256.   if (mysql_bin_log.find_first_log(&linfo, search_file_name))
  257.   {
  258.     errmsg = "Could not find first log";
  259.     goto err;
  260.   }
  261.   if ((file=open_log(&log, log_file_name, &errmsg)) < 0)
  262.     goto err;
  263.   if(pos < 4)
  264.   {
  265.     errmsg = "Congratulations! You have hit the magic number and can win 
  266. sweepstakes if you report the bug";
  267.     goto err;
  268.   }
  269.  
  270.   my_b_seek(&log, pos); // Seek will done on next read
  271.   packet->length(0);
  272.   packet->append("", 1);
  273.   // we need to start a packet with something other than 255
  274.   // to distiquish it from error
  275.   // tell the client log name with a fake rotate_event
  276.   // if we are at the start of the log
  277.   if(pos == 4) 
  278.   {
  279.     if (fake_rotate_event(net, packet, log_file_name, &errmsg))
  280.       goto err;
  281.     packet->length(0);
  282.     packet->append("", 1);
  283.   }
  284.   while (!net->error && net->vio != 0 && !thd->killed)
  285.   {
  286.     pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
  287.       
  288.     while (!(error = Log_event::read_log_event(&log, packet, log_lock)))
  289.     {
  290.       if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
  291.       {
  292. errmsg = "Failed on my_net_write()";
  293. goto err;
  294.       }
  295.       DBUG_PRINT("info", ("log event code %d",
  296.   (*packet)[LOG_EVENT_OFFSET+1] ));
  297.       if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
  298.       {
  299. if(send_file(thd))
  300. {
  301.   errmsg = "failed in send_file()";
  302.   goto err;
  303. }
  304.       }
  305.       packet->length(0);
  306.       packet->append("",1);
  307.     }
  308.     
  309.     if (error != LOG_READ_EOF)
  310.     {
  311.       switch(error)
  312.       {
  313.       case LOG_READ_BOGUS: 
  314. errmsg = "bogus data in log event";
  315. break;
  316.       case LOG_READ_TOO_LARGE: 
  317. errmsg = "log event entry exceeded max_allowed_packet -
  318.  increase max_allowed_packet on master";
  319. break;
  320.       case LOG_READ_IO:
  321. errmsg = "I/O error reading log event";
  322. break;
  323.       case LOG_READ_MEM:
  324. errmsg = "memory allocation failed reading log event";
  325. break;
  326.       case LOG_READ_TRUNC:
  327. errmsg = "binlog truncated in the middle of event";
  328. break;
  329.       default:
  330. errmsg = "unknown error reading log event on the master";
  331. break;
  332.       }
  333.       goto err;
  334.     }
  335.     if(!(flags & BINLOG_DUMP_NON_BLOCK) &&
  336.        mysql_bin_log.is_active(log_file_name))
  337.       // block until there is more data in the log
  338.       // unless non-blocking mode requested
  339.     {
  340.       if(net_flush(net))
  341.       {
  342. errmsg = "failed on net_flush()";
  343. goto err;
  344.       }
  345.       // we may have missed the update broadcast from the log
  346.       // that has just happened, let's try to catch it if it did
  347.       // if we did not miss anything, we just wait for other threads
  348.       // to signal us
  349.       {
  350. log.error=0;
  351. // tell the kill thread how to wake us up
  352. pthread_mutex_lock(&thd->mysys_var->mutex);
  353. thd->mysys_var->current_mutex = log_lock;
  354. thd->mysys_var->current_cond = &COND_binlog_update;
  355. const char* proc_info = thd->proc_info;
  356. thd->proc_info = "Slave connection: waiting for binlog update";
  357. pthread_mutex_unlock(&thd->mysys_var->mutex);
  358. bool read_packet = 0, fatal_error = 0;
  359. // no one will update the log while we are reading
  360. // now, but we'll be quick and just read one record
  361. pthread_mutex_lock(log_lock);
  362. switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0))
  363. {
  364. case 0:
  365.   read_packet = 1;
  366.   // we read successfully, so we'll need to send it to the
  367.   // slave
  368.   break;
  369. case LOG_READ_EOF:
  370.   DBUG_PRINT("wait",("waiting for data on binary log"));
  371.   pthread_cond_wait(&COND_binlog_update, log_lock);
  372.   break;
  373. default:
  374.   fatal_error = 1;
  375.   break;
  376. }
  377. pthread_mutex_unlock(log_lock);
  378. pthread_mutex_lock(&thd->mysys_var->mutex);
  379. thd->mysys_var->current_mutex= 0;
  380. thd->mysys_var->current_cond= 0;
  381. thd->proc_info= proc_info;
  382. pthread_mutex_unlock(&thd->mysys_var->mutex);
  383. if(read_packet)
  384. {
  385.   thd->proc_info = "sending update to slave";
  386.   if(my_net_write(net, (char*)packet->ptr(), packet->length()) )
  387.   {
  388.     errmsg = "Failed on my_net_write()";
  389.     goto err;
  390.   }
  391.   if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
  392.   {
  393.     if(send_file(thd))
  394.     {
  395.       errmsg = "failed in send_file()";
  396.       goto err;
  397.     }
  398.   }
  399.   packet->length(0);
  400.   packet->append("",1);
  401.   // no need to net_flush because we will get to flush later when
  402.   // we hit EOF pretty quick
  403. }
  404. if(fatal_error)
  405. {
  406.   errmsg = "error reading log entry";
  407.   goto err;
  408. }
  409. log.error=0;
  410.       }
  411.     }
  412.     else
  413.     {
  414.       bool loop_breaker = 0;
  415.       // need this to break out of the for loop from switch
  416.       thd->proc_info = "switching to next log";
  417.       switch(mysql_bin_log.find_next_log(&linfo))
  418.       {
  419.       case LOG_INFO_EOF:
  420. loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
  421. break;
  422.       case 0:
  423. break;
  424.       default:
  425. errmsg = "could not find next log";
  426. goto err;
  427.       }
  428.       if(loop_breaker)
  429. break;
  430.       end_io_cache(&log);
  431.       (void) my_close(file, MYF(MY_WME));
  432.       
  433.       // fake Rotate_log event just in case it did not make it to the log
  434.       // otherwise the slave make get confused about the offset
  435.       if ((file=open_log(&log, log_file_name, &errmsg)) < 0 ||
  436.   fake_rotate_event(net, packet, log_file_name, &errmsg))
  437. goto err;
  438.       packet->length(0);
  439.       packet->append("",1);
  440.     }
  441.   }
  442.   end_io_cache(&log);
  443.   (void)my_close(file, MYF(MY_WME));
  444.   
  445.   send_eof(&thd->net);
  446.   thd->proc_info = "waiting to finalize termination";
  447.   pthread_mutex_lock(&LOCK_thread_count);
  448.   thd->current_linfo = 0;
  449.   pthread_mutex_unlock(&LOCK_thread_count);
  450.   DBUG_VOID_RETURN;
  451.  err:
  452.   thd->proc_info = "waiting to finalize termination";
  453.   end_io_cache(&log);
  454.   pthread_mutex_lock(&LOCK_thread_count);
  455.   // exclude  iteration through thread list
  456.   // this is needed for purge_logs() - it will iterate through
  457.   // thread list and update thd->current_linfo->index_file_offset
  458.   // this mutex will make sure that it never tried to update our linfo
  459.   // after we return from this stack frame
  460.   thd->current_linfo = 0;
  461.   pthread_mutex_unlock(&LOCK_thread_count);
  462.   if (file >= 0)
  463.     (void) my_close(file, MYF(MY_WME));
  464.   send_error(&thd->net, my_errno, errmsg);
  465.   DBUG_VOID_RETURN;
  466. }
  467. int start_slave(THD* thd , bool net_report)
  468. {
  469.   if(!thd) thd = current_thd;
  470.   NET* net = &thd->net;
  471.   int slave_errno = 0;
  472.   if (check_access(thd, PROCESS_ACL, any_db))
  473.     return 1;
  474.   pthread_mutex_lock(&LOCK_slave);
  475.   if(!slave_running)
  476.     {
  477.       if(init_master_info(&glob_mi))
  478. slave_errno = ER_MASTER_INFO;
  479.       else if(server_id_supplied && *glob_mi.host)
  480. {
  481.   pthread_t hThread;
  482.   if(pthread_create(&hThread, &connection_attrib, handle_slave, 0))
  483.     {
  484.       slave_errno = ER_SLAVE_THREAD;
  485.     }
  486.   while(!slave_running) // slave might already be running by now
  487.    pthread_cond_wait(&COND_slave_start, &LOCK_slave);
  488. }
  489.       else
  490. slave_errno = ER_BAD_SLAVE;
  491.     }
  492.   else
  493.     slave_errno = ER_SLAVE_MUST_STOP;
  494.   pthread_mutex_unlock(&LOCK_slave);
  495.   if(slave_errno)
  496.     {
  497.       if(net_report) send_error(net, slave_errno);
  498.       return 1;
  499.     }
  500.   else if(net_report)
  501.     send_ok(net);
  502.   return 0;
  503. }
  504. int stop_slave(THD* thd, bool net_report )
  505. {
  506.   if(!thd) thd = current_thd;
  507.   NET* net = &thd->net;
  508.   int slave_errno = 0;
  509.   
  510.   if (check_access(thd, PROCESS_ACL, any_db))
  511.     return 1;
  512.   pthread_mutex_lock(&LOCK_slave);
  513.   if (slave_running)
  514.   {
  515.     abort_slave = 1;
  516.     thr_alarm_kill(slave_real_id);
  517. #ifdef SIGNAL_WITH_VIO_CLOSE
  518.     slave_thd->close_active_vio();
  519. #endif    
  520.     // do not abort the slave in the middle of a query, so we do not set
  521.     // thd->killed for the slave thread
  522.     thd->proc_info = "waiting for slave to die";
  523.     while(slave_running) 
  524.       pthread_cond_wait(&COND_slave_stopped, &LOCK_slave);
  525.   }
  526.   else
  527.     slave_errno = ER_SLAVE_NOT_RUNNING;
  528.   pthread_mutex_unlock(&LOCK_slave);
  529.   thd->proc_info = 0;
  530.   if(slave_errno)
  531.     {
  532.      if(net_report) send_error(net, slave_errno);
  533.      return 1;
  534.     }
  535.   else if(net_report)
  536.     send_ok(net);
  537.   return 0;
  538. }
  539. void reset_slave()
  540. {
  541.   MY_STAT stat_area;
  542.   char fname[FN_REFLEN];
  543.   bool slave_was_running ;
  544.   pthread_mutex_lock(&LOCK_slave);
  545.   if((slave_was_running = slave_running))
  546.     {
  547.       pthread_mutex_unlock(&LOCK_slave);
  548.       stop_slave(0,0);
  549.     }
  550.   else
  551.     pthread_mutex_unlock(&LOCK_slave);
  552.   
  553.   end_master_info(&glob_mi);
  554.   fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
  555.   if(my_stat(fname, &stat_area, MYF(0)))
  556.     if(my_delete(fname, MYF(MY_WME)))
  557.         return;
  558.   if(slave_was_running)
  559.     start_slave(0,0);
  560. }
  561. void kill_zombie_dump_threads(uint32 slave_server_id)
  562. {
  563.   pthread_mutex_lock(&LOCK_thread_count);
  564.   I_List_iterator<THD> it(threads);
  565.   THD *tmp;
  566.   while((tmp=it++))
  567.     {
  568.       if(tmp->command == COM_BINLOG_DUMP &&
  569.  tmp->server_id == slave_server_id)
  570. {
  571.   // here we do not call kill_one_thread()
  572.   // it will be slow because it will iterate through the list
  573.   // again. Plus it double-locks LOCK_thread_count, which
  574.   // make safe_mutex complain and abort
  575.   // so we just to our own thread murder
  576.   
  577.   thr_alarm_kill(tmp->real_id);
  578.   tmp->killed = 1;
  579.   pthread_mutex_lock(&tmp->mysys_var->mutex);
  580.           tmp->mysys_var->abort = 1;
  581.   if(tmp->mysys_var->current_mutex)
  582.     {
  583.       pthread_mutex_lock(tmp->mysys_var->current_mutex);
  584.       pthread_cond_broadcast(tmp->mysys_var->current_cond);
  585.       pthread_mutex_unlock(tmp->mysys_var->current_mutex);
  586.     }
  587.   pthread_mutex_unlock(&tmp->mysys_var->mutex);
  588. }
  589.    }
  590.   
  591.   pthread_mutex_unlock(&LOCK_thread_count);
  592. }
  593. int change_master(THD* thd)
  594. {
  595.   bool slave_was_running;
  596.   // kill slave thread
  597.   pthread_mutex_lock(&LOCK_slave);
  598.   if((slave_was_running = slave_running))
  599.     {
  600.       abort_slave = 1;
  601.       thr_alarm_kill(slave_real_id);
  602.       thd->proc_info = "waiting for slave to die";
  603.       while(slave_running)
  604.        pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done
  605.     }
  606.   pthread_mutex_unlock(&LOCK_slave);
  607.   thd->proc_info = "changing master";
  608.   LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
  609.   if(init_master_info(&glob_mi))
  610.     {
  611.       send_error(&thd->net, 0, "Could not initialize master info");
  612.       return 1;
  613.     }
  614.   
  615.   pthread_mutex_lock(&glob_mi.lock);
  616.   if((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
  617.     {
  618.       // if we change host or port, we must reset the postion
  619.       glob_mi.log_file_name[0] = 0;
  620.       glob_mi.pos = 4; // skip magic number
  621.     }
  622.   if(lex_mi->log_file_name)
  623.     strmake(glob_mi.log_file_name, lex_mi->log_file_name,
  624.     sizeof(glob_mi.log_file_name));
  625.   if(lex_mi->pos)
  626.     glob_mi.pos = lex_mi->pos;
  627.   if(lex_mi->host)
  628.     strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host));
  629.   if(lex_mi->user)
  630.     strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user));
  631.   if(lex_mi->password)
  632.     strmake(glob_mi.password, lex_mi->password, sizeof(glob_mi.password));
  633.   if(lex_mi->port)
  634.     glob_mi.port = lex_mi->port;
  635.   if(lex_mi->connect_retry)
  636.     glob_mi.connect_retry = lex_mi->connect_retry;
  637.   flush_master_info(&glob_mi);
  638.   pthread_mutex_unlock(&glob_mi.lock);
  639.   thd->proc_info = "starting slave";
  640.   if(slave_was_running)
  641.     start_slave(0,0);
  642.   thd->proc_info = 0;
  643.   send_ok(&thd->net);
  644.   return 0;
  645. }
  646. void reset_master()
  647. {
  648.   if(!mysql_bin_log.is_open())
  649.   {
  650.     my_error(ER_FLUSH_MASTER_BINLOG_CLOSED,  MYF(ME_BELL+ME_WAITTANG));
  651.     return;
  652.   }
  653.   LOG_INFO linfo;
  654.   if (mysql_bin_log.find_first_log(&linfo, ""))
  655.     return;
  656.   for(;;)
  657.   {
  658.     my_delete(linfo.log_file_name, MYF(MY_WME));
  659.     if (mysql_bin_log.find_next_log(&linfo))
  660.       break;
  661.   }
  662.   mysql_bin_log.close(1); // exiting close
  663.   my_delete(mysql_bin_log.get_index_fname(), MYF(MY_WME));
  664.   mysql_bin_log.open(opt_bin_logname,LOG_BIN);
  665. }
  666. int show_binlog_info(THD* thd)
  667. {
  668.   DBUG_ENTER("show_binlog_info");
  669.   List<Item> field_list;
  670.   field_list.push_back(new Item_empty_string("File", FN_REFLEN));
  671.   field_list.push_back(new Item_empty_string("Position",20));
  672.   field_list.push_back(new Item_empty_string("Binlog_do_db",20));
  673.   field_list.push_back(new Item_empty_string("Binlog_ignore_db",20));
  674.   if(send_fields(thd, field_list, 1))
  675.     DBUG_RETURN(-1);
  676.   String* packet = &thd->packet;
  677.   packet->length(0);
  678.   if(mysql_bin_log.is_open())
  679.     {
  680.       LOG_INFO li;
  681.       mysql_bin_log.get_current_log(&li);
  682.       int dir_len = dirname_length(li.log_file_name);
  683.       net_store_data(packet, li.log_file_name + dir_len);
  684.       net_store_data(packet, (longlong)li.pos);
  685.       net_store_data(packet, &binlog_do_db);
  686.       net_store_data(packet, &binlog_ignore_db);
  687.     }
  688.   else
  689.     {
  690.       net_store_null(packet);
  691.       net_store_null(packet);
  692.       net_store_null(packet);
  693.       net_store_null(packet);
  694.     }
  695.   if(my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
  696.     DBUG_RETURN(-1);
  697.   send_eof(&thd->net);
  698.   DBUG_RETURN(0);
  699. }
  700. int show_binlogs(THD* thd)
  701. {
  702.   const char* errmsg = 0;
  703.   File index_file;
  704.   char fname[FN_REFLEN];
  705.   NET* net = &thd->net;
  706.   List<Item> field_list;
  707.   String* packet = &thd->packet;
  708.   IO_CACHE io_cache;
  709.   uint length;
  710.   
  711.   if(!mysql_bin_log.is_open())
  712.   {
  713.     errmsg = "binlog is not open";
  714.     goto err;
  715.   }
  716.   field_list.push_back(new Item_empty_string("Log_name", 128));
  717.   if(send_fields(thd, field_list, 1))
  718.   {
  719.     sql_print_error("Failed in send_fields");
  720.     return 1;
  721.   }
  722.   
  723.   mysql_bin_log.lock_index();
  724.   index_file = mysql_bin_log.get_index_file();
  725.   if (index_file < 0)
  726.   {
  727.     errmsg = "Uninitialized index file pointer";
  728.     goto err2;
  729.   }
  730.   if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, 0, 0,
  731.    MYF(MY_WME)))
  732.   {
  733.     errmsg = "Failed on init_io_cache()";
  734.     goto err2;
  735.   }
  736.   while ((length=my_b_gets(&io_cache, fname, sizeof(fname))))
  737.   {
  738.     fname[--length]=0;
  739.     int dir_len = dirname_length(fname);
  740.     packet->length(0);
  741.     net_store_data(packet, fname + dir_len, length-dir_len);
  742.     if(my_net_write(net, (char*) packet->ptr(), packet->length()))
  743.     {
  744.       sql_print_error("Failed in my_net_write");
  745.       end_io_cache(&io_cache);
  746.       mysql_bin_log.unlock_index();
  747.       return 1;
  748.     }
  749.   }
  750.   
  751.   mysql_bin_log.unlock_index();
  752.   end_io_cache(&io_cache);
  753.   send_eof(net);   
  754.   return 0;
  755. err2:
  756.   mysql_bin_log.unlock_index();
  757.   end_io_cache(&io_cache);
  758. err:
  759.   send_error(net, 0, errmsg);
  760.   return 1;
  761. }