From 886a489bc3ad882ebf52bce1e496f2b28d427133 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 27 Nov 2009 16:49:45 +0800 Subject: Bug#48351 Inconsistent library names for semisync plugin The semisync plugin library names on Unix like systems were prefixed with 'lib', which did not follow the conventions. Fix the problem by removing the 'lib' prefix on Unix systems. mysql-test/mysql-test-run.pl: Remove 'lib' prefix for semisync plugin library names plugin/semisync/Makefile.am: Remove 'lib' prefix for semisync plugin library names plugin/semisync/plug.in: Remove 'lib' prefix for semisync plugin library names --- plugin/semisync/Makefile.am | 18 +++++++++--------- plugin/semisync/plug.in | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'plugin') diff --git a/plugin/semisync/Makefile.am b/plugin/semisync/Makefile.am index 25949485987..27ff89aae88 100644 --- a/plugin/semisync/Makefile.am +++ b/plugin/semisync/Makefile.am @@ -23,16 +23,16 @@ INCLUDES = -I$(top_srcdir)/include \ noinst_HEADERS = semisync.h semisync_master.h semisync_slave.h -pkgplugin_LTLIBRARIES = libsemisync_master.la libsemisync_slave.la +pkgplugin_LTLIBRARIES = semisync_master.la semisync_slave.la -libsemisync_master_la_LDFLAGS = -module -libsemisync_master_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -libsemisync_master_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -libsemisync_master_la_SOURCES = semisync.cc semisync_master.cc semisync_master_plugin.cc +semisync_master_la_LDFLAGS = -module +semisync_master_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +semisync_master_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +semisync_master_la_SOURCES = semisync.cc semisync_master.cc semisync_master_plugin.cc -libsemisync_slave_la_LDFLAGS = -module -libsemisync_slave_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -libsemisync_slave_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -libsemisync_slave_la_SOURCES = semisync.cc semisync_slave.cc semisync_slave_plugin.cc +semisync_slave_la_LDFLAGS = -module +semisync_slave_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +semisync_slave_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +semisync_slave_la_SOURCES = semisync.cc semisync_slave.cc semisync_slave_plugin.cc EXTRA_DIST= CMakeLists.txt plug.in diff --git a/plugin/semisync/plug.in b/plugin/semisync/plug.in index 917c8950f02..82bd9772644 100644 --- a/plugin/semisync/plug.in +++ b/plugin/semisync/plug.in @@ -1,3 +1,3 @@ MYSQL_PLUGIN(semisync,[Semi-synchronous Replication Plugin], [Semi-synchronous replication plugin.]) -MYSQL_PLUGIN_DYNAMIC(semisync, [libsemisync_master.la libsemisync_slave.la]) +MYSQL_PLUGIN_DYNAMIC(semisync, [semisync_master.la semisync_slave.la]) -- cgit v1.2.1 From c926610d7cdf88bf7133a3609d70fe3cf292b0db Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 4 Dec 2009 09:46:33 +0800 Subject: Bug#49020 Semi-sync master crashed with free_pool == NULL, assertion `free_pool_' Before this patch, semisync assumed transactions running in parallel can not be larger than max_connections, but this is not true when the event scheduler is executing events, and cause semisync run out of preallocated transaction nodes. Fix the problem by allocating transaction nodes dynamically. This patch also fixed a possible deadlock when running UNINSTALL PLUGIN rpl_semi_sync_master and updating in parallel. Fixed by releasing the internal Delegate lock before unlock the plugins. mysql-test/suite/rpl/t/rpl_semi_sync_event.test: Add test case for bug#49020 plugin/semisync/semisync_master.cc: Allocating TranxNode dynamically plugin/semisync/semisync_master.h: Allocating TranxNode dynamically sql/rpl_handler.cc: Unlock plugins after we have released the Delegate lock to avoid possible deadlock when uninstalling semisync master plugin and doing update in parallel. --- plugin/semisync/semisync_master.cc | 84 ++++++++++---------------------------- plugin/semisync/semisync_master.h | 23 +++-------- 2 files changed, 27 insertions(+), 80 deletions(-) (limited to 'plugin') diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc index cc83978ad4e..526797a3c4a 100644 --- a/plugin/semisync/semisync_master.cc +++ b/plugin/semisync/semisync_master.cc @@ -63,29 +63,14 @@ static int gettimeofday(struct timeval *tv, void *tz) * ******************************************************************************/ -ActiveTranx::ActiveTranx(int max_connections, - pthread_mutex_t *lock, +ActiveTranx::ActiveTranx(pthread_mutex_t *lock, unsigned long trace_level) - : Trace(trace_level), num_transactions_(max_connections), - num_entries_(max_connections << 1), + : Trace(trace_level), + num_entries_(max_connections << 1), /* Transaction hash table size + * is set to double the size + * of max_connections */ lock_(lock) { - /* Allocate the memory for the array */ - node_array_ = new TranxNode[num_transactions_]; - for (int idx = 0; idx < num_transactions_; ++idx) - { - node_array_[idx].log_pos_ = 0; - node_array_[idx].hash_next_ = NULL; - node_array_[idx].next_ = node_array_ + idx + 1; - - node_array_[idx].log_name_ = new char[FN_REFLEN]; - node_array_[idx].log_name_[0] = '\x0'; - } - node_array_[num_transactions_-1].next_ = NULL; - - /* All nodes in the array go to the pool initially. */ - free_pool_ = node_array_; - /* No transactions are in the list initially. */ trx_front_ = NULL; trx_rear_ = NULL; @@ -95,24 +80,13 @@ ActiveTranx::ActiveTranx(int max_connections, for (int idx = 0; idx < num_entries_; ++idx) trx_htb_[idx] = NULL; - sql_print_information("Semi-sync replication initialized for %d " - "transactions.", num_transactions_); + sql_print_information("Semi-sync replication initialized for transactions."); } ActiveTranx::~ActiveTranx() { - for (int idx = 0; idx < num_transactions_; ++idx) - { - delete [] node_array_[idx].log_name_; - node_array_[idx].log_name_ = NULL; - } - - delete [] node_array_; delete [] trx_htb_; - - node_array_ = NULL; trx_htb_ = NULL; - num_transactions_ = 0; num_entries_ = 0; } @@ -143,26 +117,21 @@ unsigned int ActiveTranx::get_hash_value(const char *log_file_name, ActiveTranx::TranxNode* ActiveTranx::alloc_tranx_node() { - TranxNode *ptr = free_pool_; - - if (free_pool_) - { - free_pool_ = free_pool_->next_; - ptr->next_ = NULL; - ptr->hash_next_ = NULL; - } - else + MYSQL_THD thd= (MYSQL_THD)current_thd; + /* The memory allocated for TranxNode will be automatically freed at + the end of the command of current THD. And because + ha_autocommit_or_rollback() will always be called before that, so + we are sure that the node will be removed from the active list + before it get freed. */ + TranxNode *trx_node = (TranxNode *)thd_alloc(thd, sizeof(TranxNode)); + if (trx_node) { - /* - free_pool should never be NULL here, because we have - max_connections number of pre-allocated nodes. - */ - sql_print_error("You have encountered a semi-sync bug (free_pool == NULL), " - "please report to http://bugs.mysql.com"); - assert(free_pool_); + trx_node->log_name_[0] = '\0'; + trx_node->log_pos_= 0; + trx_node->next_= 0; + trx_node->hash_next_= 0; } - - return ptr; + return trx_node; } int ActiveTranx::compare(const char *log_file_name1, my_off_t log_file_pos1, @@ -306,8 +275,6 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, /* Clear the active transaction list. */ if (trx_front_ != NULL) { - trx_rear_->next_ = free_pool_; - free_pool_ = trx_front_; trx_front_ = NULL; trx_rear_ = NULL; } @@ -326,11 +293,6 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, { next_node = curr_node->next_; - /* Put the node in the memory pool. */ - curr_node->next_ = free_pool_; - free_pool_ = curr_node; - n_frees++; - /* Remove the node from the hash table. */ unsigned int hash_val = get_hash_value(curr_node->log_name_, curr_node->log_pos_); TranxNode **hash_ptr = &(trx_htb_[hash_val]); @@ -391,8 +353,7 @@ ReplSemiSyncMaster::ReplSemiSyncMaster() wait_file_pos_(0), master_enabled_(false), wait_timeout_(0L), - state_(0), - max_transactions_(0L) + state_(0) { strcpy(reply_file_name_, ""); strcpy(wait_file_name_, ""); @@ -413,7 +374,6 @@ int ReplSemiSyncMaster::initObject() /* References to the parameter works after set_options(). */ setWaitTimeout(rpl_semi_sync_master_timeout); setTraceLevel(rpl_semi_sync_master_trace_level); - max_transactions_ = (int)max_connections; /* Mutex initialization can only be done after MY_INIT(). */ pthread_mutex_init(&LOCK_binlog_, MY_MUTEX_INIT_FAST); @@ -436,9 +396,7 @@ int ReplSemiSyncMaster::enableMaster() if (!getMasterEnabled()) { - active_tranxs_ = new ActiveTranx(max_connections, - &LOCK_binlog_, - trace_level_); + active_tranxs_ = new ActiveTranx(&LOCK_binlog_, trace_level_); if (active_tranxs_ != NULL) { commit_file_name_inited_ = false; diff --git a/plugin/semisync/semisync_master.h b/plugin/semisync/semisync_master.h index d2b87745600..bfb1cb74cd0 100644 --- a/plugin/semisync/semisync_master.h +++ b/plugin/semisync/semisync_master.h @@ -23,31 +23,26 @@ /** This class manages memory for active transaction list. - We record each active transaction with a TranxNode. Because each - session can only have only one open transaction, the total active - transaction nodes can not exceed the maximum sessions. Currently - in MySQL, sessions are the same as connections. + We record each active transaction with a TranxNode, each session + can have only one open transaction. Because of EVENT, the total + active transaction nodes can exceed the maximum allowed + connections. */ class ActiveTranx :public Trace { private: struct TranxNode { - char *log_name_; + char log_name_[FN_REFLEN]; my_off_t log_pos_; struct TranxNode *next_; /* the next node in the sorted list */ struct TranxNode *hash_next_; /* the next node during hash collision */ }; - /* The following data structure maintains an active transaction list. */ - TranxNode *node_array_; - TranxNode *free_pool_; - /* These two record the active transaction list in sort order. */ TranxNode *trx_front_, *trx_rear_; TranxNode **trx_htb_; /* A hash table on active transactions. */ - int num_transactions_; /* maximum transactions */ int num_entries_; /* maximum hash table entries */ pthread_mutex_t *lock_; /* mutex lock */ @@ -74,8 +69,7 @@ private: } public: - ActiveTranx(int max_connections, pthread_mutex_t *lock, - unsigned long trace_level); + ActiveTranx(pthread_mutex_t *lock, unsigned long trace_level); ~ActiveTranx(); /* Insert an active transaction node with the specified position. @@ -177,11 +171,6 @@ class ReplSemiSyncMaster bool state_; /* whether semi-sync is switched */ - /* The number of maximum active transactions. This should be the same as - * maximum connections because MySQL does not do connection sharing now. - */ - int max_transactions_; - void lock(); void unlock(); void cond_broadcast(); -- cgit v1.2.1 From 30d2870a9c0999c615a07f93194e6d8b20e5d9d6 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 4 Dec 2009 13:43:38 +0800 Subject: Post fix for previous patch of Bug#49020 Added back n_frees, use 'clear' instead of 'free' since memory is not freed here. plugin/semisync/semisync_master.cc: Added back n_frees, use 'clear' instead of 'free' in the message since memory is not freed here. --- plugin/semisync/semisync_master.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'plugin') diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc index 526797a3c4a..c2e329e1fe4 100644 --- a/plugin/semisync/semisync_master.cc +++ b/plugin/semisync/semisync_master.cc @@ -280,7 +280,7 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, } if (trace_level_ & kTraceDetail) - sql_print_information("%s: free all nodes back to free list", kWho); + sql_print_information("%s: cleared all nodes", kWho); } else if (new_front != trx_front_) { @@ -292,6 +292,7 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, while (curr_node != new_front) { next_node = curr_node->next_; + n_frees++; /* Remove the node from the hash table. */ unsigned int hash_val = get_hash_value(curr_node->log_name_, curr_node->log_pos_); @@ -312,7 +313,7 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, trx_front_ = new_front; if (trace_level_ & kTraceDetail) - sql_print_information("%s: free %d nodes back until pos (%s, %lu)", + sql_print_information("%s: cleared %d nodes back until pos (%s, %lu)", kWho, n_frees, trx_front_->log_name_, (unsigned long)trx_front_->log_pos_); } -- cgit v1.2.1 From dae2b4442750a2a70859242c65f2154ab96d8503 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 4 Dec 2009 17:54:11 +0800 Subject: Postfix after merge patch for Bug#49020 plugin/semisync/CMakeLists.txt: Add mysqlservices to link libraries plugin/semisync/Makefile.am: Add mysqlservices to link libraries --- plugin/semisync/CMakeLists.txt | 2 +- plugin/semisync/Makefile.am | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'plugin') diff --git a/plugin/semisync/CMakeLists.txt b/plugin/semisync/CMakeLists.txt index d42510fab18..ad26298b0b7 100644 --- a/plugin/semisync/CMakeLists.txt +++ b/plugin/semisync/CMakeLists.txt @@ -29,7 +29,7 @@ SET(SEMISYNC_SLAVE_SOURCES semisync.cc semisync_slave.cc semisync_slave_plugin.c ADD_DEFINITIONS(-DMYSQL_DYNAMIC_PLUGIN) ADD_LIBRARY(semisync_master SHARED ${SEMISYNC_MASTER_SOURCES}) -TARGET_LINK_LIBRARIES(semisync_master mysqld) +TARGET_LINK_LIBRARIES(semisync_master mysqlservices mysqld) ADD_LIBRARY(semisync_slave SHARED ${SEMISYNC_SLAVE_SOURCES}) TARGET_LINK_LIBRARIES(semisync_slave mysqld) MESSAGE("build SEMISYNC as DLL") diff --git a/plugin/semisync/Makefile.am b/plugin/semisync/Makefile.am index 25949485987..8a10b9ac738 100644 --- a/plugin/semisync/Makefile.am +++ b/plugin/semisync/Makefile.am @@ -25,12 +25,12 @@ noinst_HEADERS = semisync.h semisync_master.h semisync_slave.h pkgplugin_LTLIBRARIES = libsemisync_master.la libsemisync_slave.la -libsemisync_master_la_LDFLAGS = -module +libsemisync_master_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices libsemisync_master_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN libsemisync_master_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN libsemisync_master_la_SOURCES = semisync.cc semisync_master.cc semisync_master_plugin.cc -libsemisync_slave_la_LDFLAGS = -module +libsemisync_slave_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices libsemisync_slave_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN libsemisync_slave_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN libsemisync_slave_la_SOURCES = semisync.cc semisync_slave.cc semisync_slave_plugin.cc -- cgit v1.2.1