summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/rpl/disabled.def1
-rw-r--r--mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result59
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test59
-rw-r--r--sql/replication.h14
-rw-r--r--sql/rpl_handler.cc79
-rw-r--r--sql/rpl_handler.h5
-rw-r--r--sql/slave.cc3
7 files changed, 99 insertions, 121 deletions
diff --git a/mysql-test/suite/rpl/disabled.def b/mysql-test/suite/rpl/disabled.def
index 687930e1524..f9af9c30f5c 100644
--- a/mysql-test/suite/rpl/disabled.def
+++ b/mysql-test/suite/rpl/disabled.def
@@ -1,4 +1,3 @@
-rpl_semi_sync_uninstall_plugin: waiting for the fix
##############################################################################
#
# List the test cases that are to be disabled temporarily.
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
index bd659e71600..c1d09e04cd0 100644
--- a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
@@ -1,36 +1,61 @@
include/master-slave.inc
[connection master]
-INSTALL PLUGIN rpl_semi_sync_master SONAME 'SEMISYNC_MASTER_PLUGIN';
-INSTALL PLUGIN rpl_semi_sync_slave SONAME 'SEMISYNC_SLAVE_PLUGIN';
+INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master';
+[connection slave]
+INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave';
UNINSTALL PLUGIN rpl_semi_sync_slave;
+[connection master]
UNINSTALL PLUGIN rpl_semi_sync_master;
CREATE TABLE t1(i int);
INSERT INTO t1 values (1);
DROP TABLE t1;
+[connection slave]
include/install_semisync.inc
-call mtr.add_suppression("Plugin 'rpl_semi_sync_slave' cannot be uninstalled now");
+[connection slave]
UNINSTALL PLUGIN rpl_semi_sync_slave;
-ERROR HY000: Unknown error
-call mtr.add_suppression("Plugin 'rpl_semi_sync_master' cannot be uninstalled now");
+Warnings:
+Warning 1620 Plugin is busy and will be uninstalled on shutdown
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
+plugin_name plugin_status
+rpl_semi_sync_slave DELETED
+[connection master]
UNINSTALL PLUGIN rpl_semi_sync_master;
-ERROR HY000: Unknown error
+Warnings:
+Warning 1620 Plugin is busy and will be uninstalled on shutdown
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
+plugin_name plugin_status
+rpl_semi_sync_master DELETED
CREATE TABLE t1(i int);
INSERT INTO t1 values (2);
DROP TABLE t1;
-include/assert.inc [semi sync slave status should be ON.]
-include/assert.inc [semi sync master status should be ON.]
-include/assert.inc [semi sync master clients should be 1.]
-SET GLOBAL rpl_semi_sync_master_enabled = OFF;
-include/assert.inc [semi sync master clients should be 1.]
-UNINSTALL PLUGIN rpl_semi_sync_master;
-ERROR HY000: Unknown error
+[connection slave]
+show status like "Rpl_semi_sync_slave_status";
+Variable_name Value
+Rpl_semi_sync_slave_status ON
+[connection master]
+show status like "Rpl_semi_sync_master_status";
+Variable_name Value
+Rpl_semi_sync_master_status ON
+show status like "Rpl_semi_sync_master_clients";
+Variable_name Value
+Rpl_semi_sync_master_clients 1
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
+plugin_name plugin_status
+rpl_semi_sync_master DELETED
+[connection slave]
include/stop_slave.inc
-SET GLOBAL rpl_semi_sync_slave_enabled = OFF;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
+plugin_name plugin_status
include/start_slave.inc
-UNINSTALL PLUGIN rpl_semi_sync_slave;
-include/assert.inc [semi sync master clients should be 0.]
-UNINSTALL PLUGIN rpl_semi_sync_master;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
+plugin_name plugin_status
+[connection master]
+show status like "Rpl_semi_sync_master_clients";
+Variable_name Value
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
+plugin_name plugin_status
CREATE TABLE t1(i int);
INSERT INTO t1 values (3);
DROP TABLE t1;
+[connection slave]
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
index 2badd4203cf..60636da35dd 100644
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
@@ -21,19 +21,19 @@
# not in use i.e., when asynchronous replication is active.
###############################################################################
# Step 1.1: Install semi sync master plugin on master
---replace_result $SEMISYNC_MASTER_PLUGIN SEMISYNC_MASTER_PLUGIN
-eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN';
+INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master';
# Step 1.2: Install semi sync slave plugin on slave
--connection slave
---replace_result $SEMISYNC_SLAVE_PLUGIN SEMISYNC_SLAVE_PLUGIN
-eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN';
+--echo [connection slave]
+INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave';
# Step 1.3: Uninstallation of semisync plugin on master and slave should be
# allowed at this state as there is no semi sync replication enabled between
# master and slave.
UNINSTALL PLUGIN rpl_semi_sync_slave;
--connection master
+--echo [connection master]
UNINSTALL PLUGIN rpl_semi_sync_master;
# Step 1.4: Check that replication is working fine at the end of the test case.
@@ -41,6 +41,7 @@ CREATE TABLE t1(i int);
INSERT INTO t1 values (1);
DROP TABLE t1;
--sync_slave_with_master
+--echo [connection slave]
###############################################################################
# Case 2: Uninstallation of semi sync plugins should be disallowed
@@ -52,40 +53,27 @@ DROP TABLE t1;
# Step 2.2: Check that rpl_semi_sync_slave uninstallation on Slave is not
# possible at this state
--connection slave
-call mtr.add_suppression("Plugin 'rpl_semi_sync_slave' cannot be uninstalled now");
---error ER_UNKNOWN_ERROR
+--echo [connection slave]
UNINSTALL PLUGIN rpl_semi_sync_slave;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
# Step 2.3: Check that rpl_semi_sync_master uninstallation on Master is not
# possible at this state
--connection master
-call mtr.add_suppression("Plugin 'rpl_semi_sync_master' cannot be uninstalled now");
---error ER_UNKNOWN_ERROR
+--echo [connection master]
UNINSTALL PLUGIN rpl_semi_sync_master;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
# Step 2.4: Check that replication is working fine at the end of the test case.
CREATE TABLE t1(i int);
INSERT INTO t1 values (2);
DROP TABLE t1;
--sync_slave_with_master
+--echo [connection slave]
# Step 2.5: Make sure rpl_semi_sync_master_status on Master and
# rpl_semi_sync_slave_staus on Slave are ON
---let $slave_status=[show status like "Rpl_semi_sync_slave_status", Value, 1]
---let assert_cond= "$slave_status" = "ON"
---let assert_text= semi sync slave status should be ON.
---source include/assert.inc
-
---connection master
---let $master_status=[show status like "Rpl_semi_sync_master_status", Value, 1]
---let assert_cond= "$master_status" = "ON"
---let assert_text= semi sync master status should be ON.
---source include/assert.inc
-
---let $master_clients=[show status like "Rpl_semi_sync_master_clients", Value, 1]
---let assert_cond= $master_clients = 1
---let assert_text= semi sync master clients should be 1.
---source include/assert.inc
+show status like "Rpl_semi_sync_slave_status";
###############################################################################
# Case 3: Uninstallation of semi sync plugin should be disallowed when there
@@ -93,18 +81,15 @@ DROP TABLE t1;
###############################################################################
# Step 3.1: Disable semi sync on master
--connection master
-SET GLOBAL rpl_semi_sync_master_enabled = OFF;
+--echo [connection master]
+show status like "Rpl_semi_sync_master_status";
# Step 3.2: Check that still Rpl_semi_sync_master_clients is 1
---let $master_clients=[show status like "Rpl_semi_sync_master_clients", Value, 1]
---let assert_cond= $master_clients = 1
---let assert_text= semi sync master clients should be 1.
---source include/assert.inc
+show status like "Rpl_semi_sync_master_clients";
# Step 3.3: Since Rpl_semi_sync_master_clients is 1, uninstallation of
# rpl_semi_sync_master should be disallowed.
---error ER_UNKNOWN_ERROR
-UNINSTALL PLUGIN rpl_semi_sync_master;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
###############################################################################
# Case 4: Uninstallation of semi sync plugin should be allowed when it is not
@@ -114,32 +99,32 @@ UNINSTALL PLUGIN rpl_semi_sync_master;
# Step 4.1: Stop IO thread on slave.
--connection slave
+--echo [connection slave]
--source include/stop_slave.inc
# Step 4.2: Disable semi sync on slave.
-SET GLOBAL rpl_semi_sync_slave_enabled = OFF;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
# Step 4.3: Start IO thread on slave.
--source include/start_slave.inc
# Step 4.4: Uninstall semi sync plugin, it should be successful now.
-UNINSTALL PLUGIN rpl_semi_sync_slave;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
# Step 4.5: On Master, check that semi sync slaves are now '0'.
--connection master
---let $master_clients=[show status like "Rpl_semi_sync_master_clients", Value, 1]
---let assert_cond= $master_clients = 0
---let assert_text= semi sync master clients should be 0.
---source include/assert.inc
+--echo [connection master]
+show status like "Rpl_semi_sync_master_clients";
# Step 4.6: So uninstalling semi sync plugin should be allowed
-UNINSTALL PLUGIN rpl_semi_sync_master;
+select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
# Step 4.7: Check that replication is working fine at the end of the test case
CREATE TABLE t1(i int);
INSERT INTO t1 values (3);
DROP TABLE t1;
--sync_slave_with_master
+--echo [connection slave]
# Cleanup
source include/rpl_end.inc;
diff --git a/sql/replication.h b/sql/replication.h
index 8027c4830ec..9492c54fabd 100644
--- a/sql/replication.h
+++ b/sql/replication.h
@@ -16,6 +16,20 @@
#ifndef REPLICATION_H
#define REPLICATION_H
+/***************************************************************************
+ NOTE: plugin locking.
+ This API was created specifically for the semisync plugin and its locking
+ logic is also matches semisync plugin usage pattern. In particular, a plugin
+ is locked on Binlog_transmit_observer::transmit_start and is unlocked after
+ Binlog_transmit_observer::transmit_stop. All other master observable events
+ happen between these two and don't lock the plugin at all. This works well
+ for the semisync_master plugin.
+
+ Also a plugin is locked on Binlog_relay_IO_observer::thread_start
+ and unlocked after Binlog_relay_IO_observer::thread_stop. This works well for
+ the semisync_slave plugin.
+***************************************************************************/
+
#include <mysql.h>
typedef struct st_mysql MYSQL;
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index 9267190605c..9480a9e0454 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -170,40 +170,16 @@ void delegates_destroy()
/*
This macro is used by almost all the Delegate methods to iterate
over all the observers running given callback function of the
- delegate .
-
- Add observer plugins to the thd->lex list, after each statement, all
- plugins add to thd->lex will be automatically unlocked.
+ delegate.
*/
-#define FOREACH_OBSERVER(r, f, thd, args) \
+#define FOREACH_OBSERVER(r, f, do_lock, 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(0, info->plugin); \
- if (!plugin) \
- { \
- /* plugin is not intialized or deleted, this is not an error */ \
- r= 0; \
- break; \
- } \
- insert_dynamic(plugins, (uchar *)&plugin); \
+ if (do_lock) plugin_lock(thd, plugin_int_to_ref(info->plugin_int)); \
if (((Observer *)info->observer)->f \
&& ((Observer *)info->observer)->f args) \
{ \
@@ -213,17 +189,7 @@ void delegates_destroy()
break; \
} \
} \
- 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)
+ unlock();
int Trans_delegate::after_commit(THD *thd, bool all)
@@ -240,7 +206,7 @@ int Trans_delegate::after_commit(THD *thd, bool all)
param.log_pos= log_info ? log_info->log_pos : 0;
int ret= 0;
- FOREACH_OBSERVER(ret, after_commit, thd, (&param));
+ FOREACH_OBSERVER(ret, after_commit, false, (&param));
/*
This is the end of a real transaction or autocommit statement, we
@@ -268,7 +234,7 @@ int Trans_delegate::after_rollback(THD *thd, bool all)
param.log_pos= log_info ? log_info->log_pos : 0;
int ret= 0;
- FOREACH_OBSERVER(ret, after_rollback, thd, (&param));
+ FOREACH_OBSERVER(ret, after_rollback, false, (&param));
/*
This is the end of a real transaction or autocommit statement, we
@@ -307,7 +273,7 @@ int Binlog_storage_delegate::after_flush(THD *thd,
log_info->log_pos = log_pos;
int ret= 0;
- FOREACH_OBSERVER(ret, after_flush, thd,
+ FOREACH_OBSERVER(ret, after_flush, false,
(&param, log_info->log_file, log_info->log_pos, flags));
return ret;
}
@@ -321,7 +287,7 @@ int Binlog_transmit_delegate::transmit_start(THD *thd, ushort flags,
param.flags= flags;
int ret= 0;
- FOREACH_OBSERVER(ret, transmit_start, thd, (&param, log_file, log_pos));
+ FOREACH_OBSERVER(ret, transmit_start, true, (&param, log_file, log_pos));
return ret;
}
@@ -331,7 +297,7 @@ int Binlog_transmit_delegate::transmit_stop(THD *thd, ushort flags)
param.flags= flags;
int ret= 0;
- FOREACH_OBSERVER(ret, transmit_stop, thd, (&param));
+ FOREACH_OBSERVER(ret, transmit_stop, false, (&param));
return ret;
}
@@ -356,13 +322,6 @@ int Binlog_transmit_delegate::reserve_header(THD *thd, ushort flags,
Observer_info *info= iter++;
for (; info; info= iter++)
{
- plugin_ref plugin=
- my_plugin_lock(thd, info->plugin);
- if (!plugin)
- {
- ret= 1;
- break;
- }
hlen= 0;
if (((Observer *)info->observer)->reserve_header
&& ((Observer *)info->observer)->reserve_header(&param,
@@ -371,10 +330,8 @@ int Binlog_transmit_delegate::reserve_header(THD *thd, ushort flags,
&hlen))
{
ret= 1;
- plugin_unlock(thd, plugin);
break;
}
- plugin_unlock(thd, plugin);
if (hlen == 0)
continue;
if (hlen > RESERVE_HEADER_SIZE || packet->append((char *)header, hlen))
@@ -396,7 +353,7 @@ int Binlog_transmit_delegate::before_send_event(THD *thd, ushort flags,
param.flags= flags;
int ret= 0;
- FOREACH_OBSERVER(ret, before_send_event, thd,
+ FOREACH_OBSERVER(ret, before_send_event, false,
(&param, (uchar *)packet->c_ptr(),
packet->length(),
log_file+dirname_length(log_file), log_pos));
@@ -410,7 +367,7 @@ int Binlog_transmit_delegate::after_send_event(THD *thd, ushort flags,
param.flags= flags;
int ret= 0;
- FOREACH_OBSERVER(ret, after_send_event, thd,
+ FOREACH_OBSERVER(ret, after_send_event, false,
(&param, packet->c_ptr(), packet->length()));
return ret;
}
@@ -422,7 +379,7 @@ int Binlog_transmit_delegate::after_reset_master(THD *thd, ushort flags)
param.flags= flags;
int ret= 0;
- FOREACH_OBSERVER(ret, after_reset_master, thd, (&param));
+ FOREACH_OBSERVER(ret, after_reset_master, false, (&param));
return ret;
}
@@ -443,7 +400,7 @@ int Binlog_relay_IO_delegate::thread_start(THD *thd, Master_info *mi)
init_param(&param, mi);
int ret= 0;
- FOREACH_OBSERVER(ret, thread_start, thd, (&param));
+ FOREACH_OBSERVER(ret, thread_start, true, (&param));
return ret;
}
@@ -455,7 +412,7 @@ int Binlog_relay_IO_delegate::thread_stop(THD *thd, Master_info *mi)
init_param(&param, mi);
int ret= 0;
- FOREACH_OBSERVER(ret, thread_stop, thd, (&param));
+ FOREACH_OBSERVER(ret, thread_stop, false, (&param));
return ret;
}
@@ -467,7 +424,7 @@ int Binlog_relay_IO_delegate::before_request_transmit(THD *thd,
init_param(&param, mi);
int ret= 0;
- FOREACH_OBSERVER(ret, before_request_transmit, thd, (&param, (uint32)flags));
+ FOREACH_OBSERVER(ret, before_request_transmit, false, (&param, (uint32)flags));
return ret;
}
@@ -480,7 +437,7 @@ int Binlog_relay_IO_delegate::after_read_event(THD *thd, Master_info *mi,
init_param(&param, mi);
int ret= 0;
- FOREACH_OBSERVER(ret, after_read_event, thd,
+ FOREACH_OBSERVER(ret, after_read_event, false,
(&param, packet, len, event_buf, event_len));
return ret;
}
@@ -498,7 +455,7 @@ int Binlog_relay_IO_delegate::after_queue_event(THD *thd, Master_info *mi,
flags |= BINLOG_STORAGE_IS_SYNCED;
int ret= 0;
- FOREACH_OBSERVER(ret, after_queue_event, thd,
+ FOREACH_OBSERVER(ret, after_queue_event, false,
(&param, event_buf, event_len, flags));
return ret;
}
@@ -510,7 +467,7 @@ int Binlog_relay_IO_delegate::after_reset_slave(THD *thd, Master_info *mi)
init_param(&param, mi);
int ret= 0;
- FOREACH_OBSERVER(ret, after_reset_slave, thd, (&param));
+ FOREACH_OBSERVER(ret, after_reset_slave, false, (&param));
return ret;
}
#endif /* HAVE_REPLICATION */
diff --git a/sql/rpl_handler.h b/sql/rpl_handler.h
index 4743fffb9a0..362f3c74a4b 100644
--- a/sql/rpl_handler.h
+++ b/sql/rpl_handler.h
@@ -26,13 +26,10 @@ class Observer_info {
public:
void *observer;
st_plugin_int *plugin_int;
- plugin_ref plugin;
Observer_info(void *ob, st_plugin_int *p)
:observer(ob), plugin_int(p)
- {
- plugin= plugin_int_to_ref(plugin_int);
- }
+ { }
};
class Delegate {
diff --git a/sql/slave.cc b/sql/slave.cc
index 78f152fd2fd..f224de2e1ff 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3388,9 +3388,10 @@ err_during_init:
DBUG_ASSERT(thd->net.buff != 0);
net_end(&thd->net); // destructor will not free it, because net.vio is 0
mysql_mutex_lock(&LOCK_thread_count);
+ thd->unlink();
+ mysql_mutex_unlock(&LOCK_thread_count);
THD_CHECK_SENTRY(thd);
delete thd;
- mysql_mutex_unlock(&LOCK_thread_count);
mi->abort_slave= 0;
mi->slave_running= 0;
mi->io_thd= 0;