summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/lib/My/ConfigFactory.pm11
-rw-r--r--mysql-test/r/partition_column.result22
-rw-r--r--mysql-test/suite/rpl/r/rpl_semi_sync_event.result46
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event.test108
-rw-r--r--mysql-test/t/partition_column.test17
-rw-r--r--plugin/semisync/CMakeLists.txt2
-rw-r--r--plugin/semisync/Makefile.am4
-rw-r--r--plugin/semisync/semisync_master.cc87
-rw-r--r--plugin/semisync/semisync_master.h23
-rw-r--r--sql/partition_info.cc2
-rw-r--r--sql/rpl_handler.cc35
13 files changed, 258 insertions, 101 deletions
diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm
index 916dc055c19..8431a88ef1e 100644
--- a/mysql-test/lib/My/ConfigFactory.pm
+++ b/mysql-test/lib/My/ConfigFactory.pm
@@ -358,11 +358,14 @@ sub post_check_client_group {
if (IS_WINDOWS)
{
- # Shared memory base may or may not be defined (e.g not defined in embedded)
- my $shm = $group_to_copy_from->option("shared-memory-base-name");
- if (defined $shm)
+ if (! $self->{ARGS}->{embedded})
{
- $config->insert($client_group_name,"shared-memory-base-name", $shm->value());
+ # Shared memory base may or may not be defined (e.g not defined in embedded)
+ my $shm = $group_to_copy_from->option("shared-memory-base-name");
+ if (defined $shm)
+ {
+ $config->insert($client_group_name,"shared-memory-base-name", $shm->value());
+ }
}
}
}
diff --git a/mysql-test/r/partition_column.result b/mysql-test/r/partition_column.result
index 249de9f3496..784df3045f0 100644
--- a/mysql-test/r/partition_column.result
+++ b/mysql-test/r/partition_column.result
@@ -1,4 +1,14 @@
drop table if exists t1;
+create table t1 (a int, b int)
+partition by range columns (a,b)
+( partition p0 values less than (maxvalue, 10),
+partition p1 values less than (maxvalue, maxvalue));
+ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
+create table t1 (a int, b int, c int)
+partition by range columns (a,b,c)
+( partition p0 values less than (1, maxvalue, 10),
+partition p1 values less than (1, maxvalue, maxvalue));
+ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
create table t1 (a varchar(1) character set latin1 collate latin1_general_ci)
partition by range columns(a)
( partition p0 values less than ('a'),
@@ -89,7 +99,7 @@ subpartition by hash (to_seconds(d))
subpartitions 4
( partition p0 values less than (1, '0', MAXVALUE, '1900-01-01'),
partition p1 values less than (1, 'a', MAXVALUE, '1999-01-01'),
-partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+partition p2 values less than (1, 'b', MAXVALUE, MAXVALUE),
partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
@@ -102,10 +112,10 @@ RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
-RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'b',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'b',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'b',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'b',MAXVALUE,MAXVALUE
RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
@@ -123,7 +133,7 @@ SUBPARTITION BY HASH (to_seconds(d))
SUBPARTITIONS 4
(PARTITION p0 VALUES LESS THAN (1,'0',MAXVALUE,'1900-01-01') ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1,'a',MAXVALUE,'1999-01-01') ENGINE = MyISAM,
- PARTITION p2 VALUES LESS THAN (1,'a',MAXVALUE,MAXVALUE) ENGINE = MyISAM,
+ PARTITION p2 VALUES LESS THAN (1,'b',MAXVALUE,MAXVALUE) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (1,MAXVALUE,MAXVALUE,MAXVALUE) ENGINE = MyISAM) */
drop table t1;
create table t1 (a int, b int)
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_event.result b/mysql-test/suite/rpl/r/rpl_semi_sync_event.result
new file mode 100644
index 00000000000..f3f5aa1559d
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_event.result
@@ -0,0 +1,46 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+include/stop_slave.inc
+include/start_slave.inc
+SET GLOBAL event_scheduler = ON;
+CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=ENGINE_TYPE;
+INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a');
+INSERT INTO t1 SELECT i+5, f FROM t1;
+INSERT INTO t1 SELECT i+10, f FROM t1;
+CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND
+DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID()));
+CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND
+DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev2_',CONNECTION_ID()));
+STOP SLAVE IO_THREAD;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 20;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 19;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 18;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 17;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 16;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 15;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 14;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 13;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 12;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 11;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 10;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 9;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 8;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 7;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 6;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 5;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 4;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 3;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 2;
+UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 1;
+SET GLOBAL event_scheduler = OFF;
+include/stop_slave.inc
+UNINSTALL PLUGIN rpl_semi_sync_slave;
+UNINSTALL PLUGIN rpl_semi_sync_master;
+include/start_slave.inc
+DROP EVENT ev1;
+DROP EVENT ev2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt
new file mode 100644
index 00000000000..3c4a05d640c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt
@@ -0,0 +1 @@
+$SEMISYNC_PLUGIN_OPT --max-connections=23
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event-slave.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_event-slave.opt
new file mode 100644
index 00000000000..58029d28ace
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event-slave.opt
@@ -0,0 +1 @@
+$SEMISYNC_PLUGIN_OPT
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test
new file mode 100644
index 00000000000..b08e1b49ea2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test
@@ -0,0 +1,108 @@
+source include/have_semisync_plugin.inc;
+source include/not_embedded.inc;
+source include/master-slave.inc;
+source include/have_innodb.inc;
+
+let $engine_type= InnoDB;
+
+# Suppress warnings that might be generated during the test
+disable_query_log;
+connection master;
+call mtr.add_suppression("Timeout waiting for reply of binlog");
+call mtr.add_suppression("Semi-sync master .* waiting for slave reply");
+call mtr.add_suppression("Read semi-sync reply");
+connection slave;
+call mtr.add_suppression("Master server does not support semi-sync");
+call mtr.add_suppression("Semi-sync slave .* reply");
+enable_query_log;
+
+connection master;
+disable_query_log;
+let $value = query_get_value(show variables like 'rpl_semi_sync_master_enabled', Value, 1);
+if (`select '$value' = 'No such row'`)
+{
+ set sql_log_bin=0;
+ eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN';
+ SET GLOBAL rpl_semi_sync_master_enabled = 1;
+ set sql_log_bin=1;
+}
+enable_query_log;
+
+connection slave;
+source include/stop_slave.inc;
+
+disable_query_log;
+let $value= query_get_value(show variables like 'rpl_semi_sync_slave_enabled', Value, 1);
+if (`select '$value' = 'No such row'`)
+{
+ set sql_log_bin=0;
+ eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN';
+ SET GLOBAL rpl_semi_sync_slave_enabled = 1;
+ set sql_log_bin=1;
+}
+enable_query_log;
+
+source include/start_slave.inc;
+
+connection master;
+SET GLOBAL event_scheduler = ON;
+
+replace_result $engine_type ENGINE_TYPE;
+eval CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=$engine_type;
+INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a');
+INSERT INTO t1 SELECT i+5, f FROM t1;
+INSERT INTO t1 SELECT i+10, f FROM t1;
+
+CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND
+DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID()));
+CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND
+DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev2_',CONNECTION_ID()));
+
+connection slave;
+STOP SLAVE IO_THREAD;
+
+connection master;
+let $run = 20;
+while ($run)
+{
+ connect (m$run,localhost,root,,);
+ connection m$run;
+ send;
+ eval UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = $run;
+ connection master;
+ dec $run;
+}
+
+connection master;
+SET GLOBAL event_scheduler = OFF;
+
+let $run = 20;
+while ($run)
+{
+ connection m$run;
+ reap;
+ disconnect m$run;
+ dec $run;
+}
+
+#
+# Clean up
+#
+connection slave;
+source include/stop_slave.inc;
+
+disable_warnings;
+UNINSTALL PLUGIN rpl_semi_sync_slave;
+
+connection master;
+UNINSTALL PLUGIN rpl_semi_sync_master;
+enable_warnings;
+
+connection slave;
+source include/start_slave.inc;
+
+connection master;
+DROP EVENT ev1;
+DROP EVENT ev2;
+DROP TABLE t1;
+sync_slave_with_master;
diff --git a/mysql-test/t/partition_column.test b/mysql-test/t/partition_column.test
index 7577325234f..9e47b94b036 100644
--- a/mysql-test/t/partition_column.test
+++ b/mysql-test/t/partition_column.test
@@ -9,6 +9,21 @@ drop table if exists t1;
--enable_warnings
#
+# BUG#49180, Possible to define empty intervals for column list partitioning
+#
+--error ER_RANGE_NOT_INCREASING_ERROR
+create table t1 (a int, b int)
+partition by range columns (a,b)
+( partition p0 values less than (maxvalue, 10),
+ partition p1 values less than (maxvalue, maxvalue));
+
+--error ER_RANGE_NOT_INCREASING_ERROR
+create table t1 (a int, b int, c int)
+partition by range columns (a,b,c)
+( partition p0 values less than (1, maxvalue, 10),
+ partition p1 values less than (1, maxvalue, maxvalue));
+
+#
# BUG#48161, Delivering too few records using collate syntax with partitions
#
# Test case from BUG#48447 with some extension
@@ -78,7 +93,7 @@ subpartition by hash (to_seconds(d))
subpartitions 4
( partition p0 values less than (1, '0', MAXVALUE, '1900-01-01'),
partition p1 values less than (1, 'a', MAXVALUE, '1999-01-01'),
- partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+ partition p2 values less than (1, 'b', MAXVALUE, MAXVALUE),
partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
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
diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc
index cc83978ad4e..c2e329e1fe4 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,14 +275,12 @@ 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;
}
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_)
{
@@ -325,10 +292,6 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name,
while (curr_node != new_front)
{
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. */
@@ -350,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_);
}
@@ -391,8 +354,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 +375,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 +397,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();
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 355a4ba6b68..56d79ac0d45 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -801,7 +801,7 @@ int partition_info::compare_column_values(const void *first_arg,
if (first->max_value || second->max_value)
{
if (first->max_value && second->max_value)
- continue;
+ return 0;
if (second->max_value)
return -1;
else
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index b8b82bc2f98..ebd6e4e0c0b 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -137,28 +137,53 @@ void delegates_destroy()
*/
#define FOREACH_OBSERVER(r, f, thd, args) \
param.server_id= thd->server_id; \
+ /*
+ Use a struct to make sure that they are allocated adjacent, check
+ delete_dynamic().
+ */ \
+ struct { \
+ DYNAMIC_ARRAY plugins; \
+ /* preallocate 8 slots */ \
+ plugin_ref plugins_buffer[8]; \
+ } s; \
+ DYNAMIC_ARRAY *plugins= &s.plugins; \
+ plugin_ref *plugins_buffer= s.plugins_buffer; \
+ my_init_dynamic_array2(plugins, sizeof(plugin_ref), \
+ plugins_buffer, 8, 8); \
read_lock(); \
Observer_info_iterator iter= observer_info_iter(); \
Observer_info *info= iter++; \
for (; info; info= iter++) \
{ \
plugin_ref plugin= \
- my_plugin_lock(thd, &info->plugin); \
+ my_plugin_lock(0, &info->plugin); \
if (!plugin) \
{ \
- r= 1; \
+ /* plugin is not intialized or deleted, this is not an error */ \
+ r= 0; \
break; \
} \
+ insert_dynamic(plugins, (uchar *)&plugin); \
if (((Observer *)info->observer)->f \
&& ((Observer *)info->observer)->f args) \
{ \
r= 1; \
- plugin_unlock(thd, plugin); \
+ sql_print_error("Run function '" #f "' in plugin '%s' failed", \
+ info->plugin_int->name.str); \
break; \
} \
- plugin_unlock(thd, plugin); \
} \
- unlock()
+ unlock(); \
+ /*
+ Unlock plugins should be done after we released the Delegate lock
+ to avoid possible deadlock when this is the last user of the
+ plugin, and when we unlock the plugin, it will try to
+ deinitialize the plugin, which will try to lock the Delegate in
+ order to remove the observers.
+ */ \
+ plugin_unlock_list(0, (plugin_ref*)plugins->buffer, \
+ plugins->elements); \
+ delete_dynamic(plugins)
int Trans_delegate::after_commit(THD *thd, bool all)