--- a/sql/sql_lex.h 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/sql_lex.h 2012-05-21 14:38:12.000000000 +0800 @@ -216,6 +216,7 @@ char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher; char *relay_log_name; ulong relay_log_pos; + char *sign; // Multi-Master By P.Linux } LEX_MASTER_INFO; --- a/sql/sql_yacc.yy 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/sql_yacc.yy 2012-05-21 14:42:23.000000000 +0800 @@ -1724,9 +1724,21 @@ LEX *lex = Lex; lex->sql_command = SQLCOM_CHANGE_MASTER; bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = NULL; // Multi-Master By P.Linux } master_defs {} + /* Multi-Master By P.Linux */ + | CHANGE MASTER_SYM TEXT_STRING_sys TO_SYM + { + LEX *lex = Lex; + lex->sql_command = SQLCOM_CHANGE_MASTER; + bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = $3.str; + } + master_defs + {} + /* End */ ; master_defs: @@ -6251,6 +6263,7 @@ /* We'll use mi structure for UNTIL options */ bzero((char*) &lex->mi, sizeof(lex->mi)); /* If you change this code don't forget to update SLAVE START too */ + lex->mi.sign = NULL; // Multi-Master By P.Linux } slave_until {} @@ -6259,7 +6272,9 @@ LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_STOP; lex->type = 0; + bzero((char*) &lex->mi, sizeof(lex->mi)); // Multi-Master By P.Linux /* If you change this code don't forget to update SLAVE STOP too */ + lex->mi.sign = NULL; // Multi-Master By P.Linux } | SLAVE START_SYM slave_thread_opts { @@ -6268,6 +6283,7 @@ lex->type = 0; /* We'll use mi structure for UNTIL options */ bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = NULL; // Multi-Master By P.Linux } slave_until {} @@ -6276,7 +6292,51 @@ LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_STOP; lex->type = 0; + bzero((char*) &lex->mi, sizeof(lex->mi)); // Multi-Master By P.Linux + lex->mi.sign = NULL; // Multi-Master By P.Linux } + /* Multi-Master By P.Linux */ + | START_SYM SLAVE TEXT_STRING_sys slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_START; + lex->type = 0; + /* We'll use mi structure for UNTIL options */ + bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = $3.str; + /* If you change this code don't forget to update SLAVE START too */ + } + slave_until + {} + | STOP_SYM SLAVE TEXT_STRING_sys slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_STOP; + lex->type = 0; + bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = $3.str; + /* If you change this code don't forget to update SLAVE STOP too */ + } + | SLAVE TEXT_STRING_sys START_SYM slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_START; + lex->type = 0; + /* We'll use mi structure for UNTIL options */ + bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = $2.str; + } + slave_until + {} + | SLAVE TEXT_STRING_sys STOP_SYM slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_STOP; + lex->type = 0; + bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = $2.str; + } + /* End */ ; start: @@ -10365,7 +10425,17 @@ | SLAVE STATUS_SYM { Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; + Lex->mi.sign = NULL; // Multi-Master By P.Linux } + /* Multi-Master By P.Linux */ + | SLAVE TEXT_STRING_sys STATUS_SYM // Multi-Master By P.Linux + { + LEX *lex = Lex; + lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; + bzero((char*) &lex->mi, sizeof(lex->mi)); + lex->mi.sign = $2.str; + } + /* End */ | CREATE PROCEDURE sp_name { LEX *lex= Lex; @@ -10606,6 +10676,14 @@ SLAVE { Lex->type|= REFRESH_SLAVE; } | MASTER_SYM { Lex->type|= REFRESH_MASTER; } | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;} + /* Multi-Master By P.Linux */ + | SLAVE TEXT_STRING_sys + { + Lex->type|= REFRESH_SLAVE; + bzero((char*) &Lex->mi, sizeof(Lex->mi)); + Lex->mi.sign = $2.str; + } + /* End */ ; purge: --- a/sql/sql_repl.cc 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/sql_repl.cc 2012-05-21 14:38:12.000000000 +0800 @@ -1081,19 +1081,41 @@ // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0 end_master_info(mi); // and delete these two files - fn_format(fname, master_info_file, mysql_data_home, "", 4+32); + /* Multi-Master By P.Linux */ + char buf_master_info_file[FN_REFLEN]; + char buf_relay_log_info_file[FN_REFLEN]; + if (mi->sign != '\0') // if use CHANGE MASTER 'xxx' TO + { + concat_signed_file_name(buf_master_info_file, master_info_file, ".", mi->sign); + concat_signed_file_name(buf_relay_log_info_file, relay_log_info_file, ".", mi->sign); + } + else + { + strmake(buf_master_info_file, master_info_file, sizeof(buf_master_info_file)-1); + strmake(buf_relay_log_info_file, relay_log_info_file, sizeof(buf_relay_log_info_file)-1); + } + fn_format(fname, buf_master_info_file, mysql_data_home, "", 4+32); + /* End */ if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME))) { error=1; goto err; } + /* Multi-Master By P.Linux */ + else + sql_print_information("[Multi-Master] Delete Master_info File '%s'.", fname); + /* END */ // delete relay_log_info_file - fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32); + /* Multi-Master By P.Linux */ + fn_format(fname, buf_relay_log_info_file, mysql_data_home, "", 4+32); if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME))) { error=1; goto err; } + else + sql_print_information("[Multi-Master] Delete Relay_log_info File '%s'.", fname); + /* END */ err: unlock_slave_threads(mi); @@ -1185,8 +1207,37 @@ thd_proc_info(thd, "Changing master"); LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + /* Multi-Master By P.Linux */ + char buf_master_info_file[FN_REFLEN]; + char buf_relay_log_info_file[FN_REFLEN]; + if (lex_mi->sign != NULL ) // if use CHANGE MASTER 'xxx' TO + { + strmake(mi->sign, lex_mi->sign, sizeof(mi->sign)-1); + concat_signed_file_name(buf_master_info_file, + master_info_file, ".", mi->sign); + concat_signed_file_name(buf_relay_log_info_file, + relay_log_info_file, ".", mi->sign); + /* if new Master_info not in HASH, add it */ + if (!master_info_index->get_master_info_from_hash(mi->sign)) + { + if (master_info_index->add_master_info_to_hash(mi, TRUE)) + { + my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); + unlock_slave_threads(mi); + DBUG_RETURN(TRUE); + } + } + sql_print_information("Sign:%s, Master_info:%s, Relay_info:%s", + mi->sign, buf_master_info_file, buf_relay_log_info_file); + } + else // if use CHANGE MASTER TO + { + strmake(buf_master_info_file, master_info_file, sizeof(buf_master_info_file)-1); + strmake(buf_relay_log_info_file, relay_log_info_file, sizeof(buf_relay_log_info_file)-1); + } + /* End */ // TODO: see if needs re-write - if (init_master_info(mi, master_info_file, relay_log_info_file, 0, + if (init_master_info(mi, buf_master_info_file, buf_relay_log_info_file, 0, // Multi-Master By P.Linux thread_mask)) { my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); --- a/sql/sql_parse.cc 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/sql_parse.cc 2012-05-21 14:45:52.000000000 +0800 @@ -18,6 +18,7 @@ #define MYSQL_LEX 1 #include "mysql_priv.h" #include "sql_repl.h" +#include "rpl_mi.h" #include "rpl_filter.h" #include "repl_failsafe.h" #include @@ -2509,7 +2510,14 @@ if (check_global_access(thd, SUPER_ACL)) goto error; pthread_mutex_lock(&LOCK_active_mi); - res = change_master(thd,active_mi); + /* Multi-Master By P.Linux */ + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi= (lex_mi->sign == NULL) ? active_mi : + master_info_index->get_master_info_from_hash(lex_mi->sign); + if (mi == NULL) // if a new Replication created + mi= new Master_info; + res = change_master(thd, mi); + /* End */ pthread_mutex_unlock(&LOCK_active_mi); break; } @@ -2519,9 +2527,13 @@ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) goto error; pthread_mutex_lock(&LOCK_active_mi); - if (active_mi != NULL) + /* Multi-Master By P.Linux */ + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi= (lex_mi->sign == NULL) ? active_mi : + master_info_index->get_master_info_from_hash(lex_mi->sign); + if (mi != NULL) { - res = show_master_info(thd, active_mi); + res = show_master_info(thd, mi); } else { @@ -2529,6 +2541,7 @@ WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO)); my_ok(thd); } + /* End */ pthread_mutex_unlock(&LOCK_active_mi); break; } @@ -2909,7 +2922,21 @@ case SQLCOM_SLAVE_START: { pthread_mutex_lock(&LOCK_active_mi); - start_slave(thd,active_mi,1 /* net report*/); + /* Multi-Master By P.Linux */ + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi= (lex_mi->sign == NULL) ? active_mi : + master_info_index->get_master_info_from_hash(lex_mi->sign); + if (mi != NULL) + { + start_slave(thd,mi,1); + } + else + { + my_message(ER_BAD_SLAVE, ER(ER_BAD_SLAVE), MYF(0)); + pthread_mutex_unlock(&LOCK_active_mi); + break; + } + /* End */ pthread_mutex_unlock(&LOCK_active_mi); break; } @@ -2935,7 +2962,21 @@ } { pthread_mutex_lock(&LOCK_active_mi); - stop_slave(thd,active_mi,1/* net report*/); + /* Multi-Master By P.Linux */ + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi= (lex_mi->sign == NULL) ? active_mi : + master_info_index->get_master_info_from_hash(lex_mi->sign); + if (mi != NULL) + { + stop_slave(thd,mi,1); + } + else + { + my_message(ER_BAD_SLAVE, ER(ER_BAD_SLAVE), MYF(0)); + pthread_mutex_unlock(&LOCK_active_mi); + break; + } + /* End */ pthread_mutex_unlock(&LOCK_active_mi); break; } @@ -7138,11 +7179,24 @@ { tmp_write_to_binlog= 0; pthread_mutex_lock(&LOCK_active_mi); - if (reset_slave(thd, active_mi)) + /* Multi-Master By P.Linux */ + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + Master_info *mi= (lex_mi->sign == NULL) ? active_mi : + master_info_index->get_master_info_from_hash(lex_mi->sign); + + result=1; + if (mi && !reset_slave(thd, mi)) { /* NOTE: my_error() has been already called by reset_slave(). */ - result= 1; + result=0; } + + if (result != 1 && lex_mi->sign) + { + master_info_index->remove_master_info_from_hash(lex_mi->sign); + } + /* End */ + pthread_mutex_unlock(&LOCK_active_mi); } #endif --- a/sql/rpl_rli.cc 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/rpl_rli.cc 2012-05-21 14:38:12.000000000 +0800 @@ -180,11 +180,30 @@ "use '--relay-log=%s' to avoid this problem.", ln); name_warning_sent= 1; } + /* Multi-Master By P.Linux */ + Master_info* mi= rli->mi; + char *buf_relay_logname= 0; + char *buf_relaylog_index_name= 0; + if (mi->sign[0] != '\0') + { + buf_relay_logname= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE)); + ln= concat_signed_file_name(buf_relay_logname, ln, "-", mi->sign); + + if (opt_relaylog_index_name) + { + buf_relaylog_index_name= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE)); + concat_signed_file_name(buf_relaylog_index_name, + opt_relaylog_index_name, "-", mi->sign); + } + } else { + buf_relaylog_index_name= opt_relaylog_index_name; + } + /* End */ /* 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, TRUE) || + if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) || // Multi-Master By P.Linux rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0, (max_relay_log_size ? max_relay_log_size : max_binlog_size), 1, TRUE)) --- a/sql/rpl_mi.h 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/rpl_mi.h 2012-05-21 14:38:12.000000000 +0800 @@ -68,6 +68,7 @@ char host[HOSTNAME_LENGTH+1]; char user[USERNAME_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; + char sign[FN_REFLEN]; // Multi-Master By P.Linux 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]; @@ -113,5 +114,39 @@ int flush_master_info(Master_info* mi, bool flush_relay_log_cache, bool need_lock_relay_log); + +/* Multi-Master By P.Linux */ +class MASTER_INFO_INDEX +{ + private: + IO_CACHE index_file; + char index_file_name[FN_REFLEN]; + HASH master_info_hash; + + public: + MASTER_INFO_INDEX(); + ~MASTER_INFO_INDEX(); + + bool init_all_master_info(); + bool write_master_sign_to_index_file(const char *sign); + + bool add_master_info_to_hash(Master_info *mi, bool write_to_file); + bool remove_master_info_from_hash(const char *sign); + /* Get a Master_info class via mi->sign */ + Master_info* get_master_info_from_hash(const char *sign) + { + Master_info* mi= (Master_info*) hash_search(&master_info_hash, (uchar*) sign, strlen(sign)); + return mi; + } +}; + +char *concat_signed_file_name(char *res_file_name ,const char *info_file, + const char *separator, const char *sign, + uint length= FN_REFLEN); + +uchar *get_key_master_info(Master_info *mi, size_t *length, + my_bool not_used __attribute__((unused))); +void free_key_master_info(Master_info *mi); +/* End */ #endif /* HAVE_REPLICATION */ #endif /* RPL_MI_H */ --- a/sql/rpl_mi.cc 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/rpl_mi.cc 2012-05-21 14:38:12.000000000 +0800 @@ -38,6 +38,7 @@ 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; + sign[0]= 0; // Multi-Master By P.Linux bzero((char*) &file, sizeof(file)); pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); @@ -429,5 +430,282 @@ DBUG_VOID_RETURN; } +/* Multi-Master By P.Linux */ +uchar *get_key_master_info(Master_info *mi, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length = strlen(mi->sign); + return (uchar*)mi->sign; +} + +void free_key_master_info(Master_info *mi) +{ + DBUG_ENTER("free_key_master_info"); + terminate_slave_threads(mi,SLAVE_FORCE_ALL); + if (mi) + { + delete mi; + mi= NULL; + } + DBUG_VOID_RETURN; +} + +char *concat_signed_file_name(char *res_file_name ,const char *info_file, + const char *separator, const char *sign, + uint length) +{ + if (!res_file_name || !info_file || + !info_file || !separator || !sign) + { + return NULL; + } + + char *p= res_file_name; + p= strmake(p, info_file, length); + p= strmake(p, separator, length - (p - res_file_name)); + p= strmake(p, sign, length - (p - res_file_name)); + + return res_file_name; +} + +MASTER_INFO_INDEX::MASTER_INFO_INDEX() +{ + DBUG_ENTER("MASTER_INFO_INDEX::MASTER_INFO_INDEX"); + + index_file_name[0] = 0; + bzero((char*) &index_file, sizeof(index_file)); + + /* Create Master_info Index File */ + File index_file_nr= -1; + DBUG_ASSERT(!my_b_inited(&index_file)); + + fn_format(index_file_name, master_info_file, mysql_data_home, + ".index", MY_UNPACK_FILENAME | MY_APPEND_EXT); + + if ((index_file_nr= my_open(index_file_name, + O_RDWR | O_CREAT | O_BINARY , + MYF(MY_WME))) < 0 || + my_sync(index_file_nr, MYF(MY_WME)) || + init_io_cache(&index_file, index_file_nr, + IO_SIZE, READ_CACHE, + my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), + 0, MYF(MY_WME | MY_WAIT_IF_FULL))) + { + if (index_file_nr>= 0) + my_close(index_file_nr,MYF(0)); + + sql_print_error("[Multi-Master] Create Master Info Index '%s' Error", index_file_name); + exit(1); + } + sql_print_information("[Multi-Master] Created Master Info Index '%s'", index_file_name); + + /* Initialize Master_info Hash Table */ + if (hash_init(&master_info_hash, system_charset_info, + MAX_REPLICATION_THREAD, 0, 0, + (hash_get_key)get_key_master_info, + (hash_free_key)free_key_master_info, 1)) + { + sql_print_error("[Multi-Master] Initializing Master_info hash table failed."); + exit(1); + } else + { + sql_print_information("[Multi-Master] Initialized Master_info hash table."); + } +} + +MASTER_INFO_INDEX::~MASTER_INFO_INDEX() +{ + hash_free(&master_info_hash); + end_io_cache(&index_file); + my_close(index_file.file, MYF(MY_WME)); +} + +/* Load All Master_info from master.info.index File + * RETURN: + * 0 - All Success + * 1 - All Fail + * 2 - Some Success, Some Fail +*/ +bool MASTER_INFO_INDEX::init_all_master_info() +{ + int thread_mask; + int err_num= 0, succ_num= 0; // The number of success read Master_info + char sign[FN_REFLEN]; + DBUG_ENTER("init_all_master_info"); + + if (access(index_file_name,F_OK)) // if master.info.index not exist + DBUG_RETURN(1); + + reinit_io_cache(&index_file, READ_CACHE, 0L,0,0); + while(!init_strvar_from_file(sign, sizeof(sign), + &index_file, NULL)) + { + Master_info *mi = new Master_info; + lock_slave_threads(mi); + init_thread_mask(&thread_mask,mi,0 /*not inverse*/); + + strmake(mi->sign, sign, sizeof(sign)-1); + + char buf_master_info_file[FN_REFLEN]; + char buf_relay_log_info_file[FN_REFLEN]; + concat_signed_file_name(buf_master_info_file, + master_info_file, ".", mi->sign); + concat_signed_file_name(buf_relay_log_info_file, + relay_log_info_file, ".", mi->sign); + sql_print_information("[Multi-Master] Reading Master_info:'%s', Relay_info:'%s' ...", + buf_master_info_file, buf_relay_log_info_file); + + if (init_master_info(mi, buf_master_info_file, buf_relay_log_info_file, + 0, thread_mask)) + { + err_num+= 1; + sql_print_error("[Multi-Master] Initialized Master_info from '%s' fail!", + buf_master_info_file); + unlock_slave_threads(mi); + delete mi; + continue; + } + else // if read Master_info success add it to HASH + { + sql_print_information("[Multi-Master] Initialized Master_info from '%s' success!", + buf_master_info_file); + if (!master_info_index->get_master_info_from_hash(mi->sign)) // Master_info not in HASH + { + if (master_info_index->add_master_info_to_hash(mi, FALSE)) + exit(1); + succ_num+= 1; + unlock_slave_threads(mi); + } + else // Master_info already in HASH + { + sql_print_error("[Multi-Master] Duplicate Master_info sign: '%s'", + mi->sign); + unlock_slave_threads(mi); + delete mi; + continue; + } + if (!opt_skip_slave_start) + { + if (start_slave_threads(1 /* need mutex */, + 0 /* no wait for start*/, + mi, + buf_master_info_file, + buf_relay_log_info_file, + SLAVE_IO | SLAVE_SQL)) + { + sql_print_error("[Multi-Master] Failed to create slave '%s' threads", mi->sign); + unlock_slave_threads(mi); + continue; + } + sql_print_information("[Multi-Master] Start Replication '%s' Success!", mi->sign); + unlock_slave_threads(mi); + } + } + } + if (!err_num) // No Error on read Master_info + { + sql_print_information("[Multi-Master] Read all Master_info Success!"); + DBUG_RETURN(0); + } + else if (succ_num) // Have some Error and some Success + { + sql_print_warning("[Multi-Master] Read Some Master_info Error!"); + DBUG_RETURN(2); + } + else // All Success + { + sql_print_error("[Multi-Master] Read all Master_info Failed!"); + DBUG_RETURN(1); + } +} + +/* Write new master.info to master.info.index File */ +bool MASTER_INFO_INDEX::write_master_sign_to_index_file(const char *sign) +{ + DBUG_ENTER("write_master_sign_to_index_file"); + + DBUG_ASSERT(my_b_inited(&index_file) != 0); + reinit_io_cache(&index_file, WRITE_CACHE, + my_b_filelength(&index_file), 0, 0); + + if (my_b_write(&index_file, (uchar*) sign, strlen(sign)) || + my_b_write(&index_file, (uchar*) "\n", 1) || + flush_io_cache(&index_file) || + my_sync(index_file.file, MYF(MY_WME))) + { + sql_print_error("[Multi-Master] Write new Master_info '%s' to index file failed!", sign); + DBUG_RETURN(1); + } + + DBUG_RETURN(0); +} + +/* Add a Master_info class to Hash Table */ +bool MASTER_INFO_INDEX::add_master_info_to_hash(Master_info *mi, bool write_to_file) +{ + if (!my_hash_insert(&master_info_hash, (uchar*) mi)) + { + sql_print_information("[Multi-Master] Add new Master_info '%s' To Hash table.", mi->sign); + if (write_to_file) + return write_master_sign_to_index_file(mi->sign); + return FALSE; + } + else + { + sql_print_error("[Multi-Master] Create new Master_info '%s' Failed!", mi->sign); + return TRUE; + } +} + +/* Remove a Master_info class From Hash Table */ +bool MASTER_INFO_INDEX::remove_master_info_from_hash(const char *sign) +{ + DBUG_ENTER("remove_master_info_from_hash"); + + Master_info* mi= get_master_info_from_hash(sign); + if (mi) + { + // Delete Master_info and rewrite others to file + if (!my_hash_delete(&master_info_hash, (uchar*) mi)) + { + // Close IO_CACHE and FILE handler fisrt + end_io_cache(&index_file); + my_close(index_file.file, MYF(MY_WME)); + + // Reopen File and truncate it + File index_file_nr= -1; + + fn_format(index_file_name, master_info_file, mysql_data_home, + ".index", MY_UNPACK_FILENAME | MY_APPEND_EXT); + + if ((index_file_nr= my_open(index_file_name, + O_RDWR | O_CREAT | O_TRUNC | O_BINARY , + MYF(MY_WME))) < 0 || + my_sync(index_file_nr, MYF(MY_WME)) || + init_io_cache(&index_file, index_file_nr, + IO_SIZE, WRITE_CACHE, + my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), + 0, MYF(MY_WME | MY_WAIT_IF_FULL))) + { + if (index_file_nr>= 0) + my_close(index_file_nr,MYF(0)); + + sql_print_error("[Multi-Master] Create Master Info Index '%s' Error", index_file_name); + DBUG_RETURN(TRUE); + } + + // Rewrite Master_info.index + int i; + Master_info *tmp_mi= 0; + for (i= 0; i< master_info_hash.records; ++i) + { + tmp_mi= (Master_info *)my_hash_element(&master_info_hash, i); + write_master_sign_to_index_file(tmp_mi->sign); + } + } + } + DBUG_RETURN(TRUE); +} +/* End */ #endif /* HAVE_REPLICATION */ --- a/sql/slave.h 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/slave.h 2012-05-21 14:38:12.000000000 +0800 @@ -34,11 +34,14 @@ #define SLAVE_NET_TIMEOUT 3600 #define MAX_SLAVE_ERROR 2000 - +/* Multi-Master By P.Linux */ +#define MAX_REPLICATION_THREAD 64 +/* End */ // Forward declarations class Relay_log_info; class Master_info; +class MASTER_INFO_INDEX; // P.Linux /***************************************************************************** @@ -198,6 +201,7 @@ pthread_handler_t handle_slave_sql(void *arg); extern bool volatile abort_loop; extern Master_info main_mi, *active_mi; /* active_mi for multi-master */ +extern MASTER_INFO_INDEX *master_info_index; // Multi-Master By P.Linux extern LIST master_list; extern my_bool replicate_same_server_id; --- a/sql/slave.cc 2012-04-16 14:50:06.000000000 +0800 +++ b/sql/slave.cc 2012-05-21 14:38:12.000000000 +0800 @@ -59,6 +59,7 @@ char* slave_load_tmpdir = 0; Master_info *active_mi= 0; +MASTER_INFO_INDEX *master_info_index; // Multi-Master By P.Linux my_bool replicate_same_server_id; ulonglong relay_log_space_limit = 0; @@ -235,6 +236,12 @@ for multi-master */ active_mi= new Master_info; + master_info_index= new MASTER_INFO_INDEX; // Multi-Master By P.Linux + + /* Multi-Master By P.Linux */ + if (master_info_index->init_all_master_info()) + goto err; + /* End */ /* If --slave-skip-errors=... was not used, the string value for the @@ -703,6 +710,10 @@ */ terminate_slave_threads(active_mi,SLAVE_FORCE_ALL); } + /* Multi-Master By P.Linux */ + if (master_info_index) + delete master_info_index; + /* End */ pthread_mutex_unlock(&LOCK_active_mi); DBUG_VOID_RETURN; }