summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/lib/mtr_process.pl17
-rwxr-xr-xmysql-test/mysql-test-run.pl54
-rw-r--r--mysql-test/r/im_daemon_life_cycle.result1
-rw-r--r--mysql-test/r/im_life_cycle.result76
-rw-r--r--mysql-test/r/im_utils.result3
-rw-r--r--mysql-test/r/insert.result26
-rw-r--r--mysql-test/r/trigger.result32
-rw-r--r--mysql-test/t/im_daemon_life_cycle-im.opt1
-rw-r--r--mysql-test/t/im_daemon_life_cycle.imtest18
-rw-r--r--mysql-test/t/im_life_cycle-im.opt1
-rw-r--r--mysql-test/t/im_life_cycle.imtest138
-rw-r--r--mysql-test/t/im_utils-im.opt1
-rw-r--r--mysql-test/t/im_utils.imtest16
-rw-r--r--mysql-test/t/insert.test23
-rwxr-xr-xmysql-test/t/kill_n_check.sh109
-rw-r--r--mysql-test/t/trigger.test40
-rwxr-xr-xmysql-test/t/wait_for_process.sh66
-rw-r--r--server-tools/instance-manager/guardian.cc3
-rw-r--r--server-tools/instance-manager/instance_map.cc2
-rw-r--r--server-tools/instance-manager/manager.cc43
-rw-r--r--sql/sql_insert.cc43
21 files changed, 508 insertions, 205 deletions
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 6fa6bc73bdb..0ca16b61fc2 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -890,19 +890,28 @@ sub mtr_kill_processes ($) {
sub mtr_kill_process ($$$$) {
my $pid= shift;
my $signal= shift;
- my $retries= shift;
+ my $total_retries= shift;
my $timeout= shift;
- while (1)
+ for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt)
{
+ mtr_debug("Sending $signal to $pid...");
+
kill($signal, $pid);
- last unless kill (0, $pid) and $retries--;
+ unless (kill (0, $pid))
+ {
+ mtr_debug("Process $pid died.");
+ return;
+ }
- mtr_debug("Sleep $timeout second waiting for processes to die");
+ mtr_debug("Sleeping $timeout second(s) waiting for processes to die...");
sleep($timeout);
}
+
+ mtr_debug("Process $pid is still alive after $total_retries " .
+ "of sending signal $signal.");
}
##############################################################################
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index bfd1f7de059..3293487a0ac 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -2860,22 +2860,58 @@ sub im_stop($) {
# Try graceful shutdown.
+ mtr_debug("IM-main pid: $instance_manager->{'pid'}");
+ mtr_debug("Stopping IM-main...");
+
mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1);
+ # If necessary, wait for angel process to die.
+
+ if (defined $instance_manager->{'angel_pid'})
+ {
+ mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}");
+ mtr_debug("Waiting for IM-angel to die...");
+
+ my $total_attempts= 10;
+
+ for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt)
+ {
+ unless (kill (0, $instance_manager->{'angel_pid'}))
+ {
+ mtr_debug("IM-angel died.");
+ last;
+ }
+
+ sleep(1);
+ }
+ }
+
# Check that all processes died.
my $clean_shutdown= 0;
while (1)
{
- last if kill (0, $instance_manager->{'pid'});
+ if (kill (0, $instance_manager->{'pid'}))
+ {
+ mtr_debug("IM-main is still alive.");
+ last;
+ }
- last if (defined $instance_manager->{'angel_pid'}) &&
- kill (0, $instance_manager->{'angel_pid'});
+ if (defined $instance_manager->{'angel_pid'} &&
+ kill (0, $instance_manager->{'angel_pid'}))
+ {
+ mtr_debug("IM-angel is still alive.");
+ last;
+ }
foreach my $pid (@mysqld_pids)
{
- last if kill (0, $pid);
+ if (kill (0, $pid))
+ {
+ mtr_debug("Guarded mysqld ($pid) is still alive.");
+ last;
+ }
}
$clean_shutdown= 1;
@@ -2886,15 +2922,21 @@ sub im_stop($) {
unless ($clean_shutdown)
{
- mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
- if defined $instance_manager->{'angel_pid'};
+
+ if (defined $instance_manager->{'angel_pid'})
+ {
+ mtr_debug("Killing IM-angel...");
+ mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
+ }
+ mtr_debug("Killing IM-main...");
mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1);
# Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM
# will not stop them on shutdown. So, we should firstly try to end them
# legally.
+ mtr_debug("Killing guarded mysqld(s)...");
mtr_kill_processes(\@mysqld_pids);
# Complain in error log so that a warning will be shown.
diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result
index d0a76b450fe..ea27fcb6db1 100644
--- a/mysql-test/r/im_daemon_life_cycle.result
+++ b/mysql-test/r/im_daemon_life_cycle.result
@@ -1,3 +1,4 @@
+Success: the process has been started.
SHOW INSTANCES;
instance_name status
mysqld1 online
diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result
index 36277f6aa28..a9f78aea7d3 100644
--- a/mysql-test/r/im_life_cycle.result
+++ b/mysql-test/r/im_life_cycle.result
@@ -1,44 +1,45 @@
+
+--------------------------------------------------------------------
+-- 1.1.1.
+--------------------------------------------------------------------
+Success: the process has been started.
SHOW INSTANCES;
instance_name status
mysqld1 online
mysqld2 offline
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version
-mysqld1 online VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version
-mysqld2 offline VERSION
+
+--------------------------------------------------------------------
+-- 1.1.2.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 online
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version
-mysqld1 online VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version
-mysqld2 online VERSION
+Success: the process has been started.
SHOW VARIABLES LIKE 'port';
Variable_name Value
-port IM_MYSQLD1_PORT
+port IM_MYSQLD2_PORT
+
+--------------------------------------------------------------------
+-- 1.1.3.
+--------------------------------------------------------------------
STOP INSTANCE mysqld2;
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version
-mysqld1 online VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version
-mysqld2 offline VERSION
+Success: the process has been stopped.
+
+--------------------------------------------------------------------
+-- 1.1.4.
+--------------------------------------------------------------------
START INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
START INSTANCE mysqld1;
ERROR HY000: The instance is already started
+
+--------------------------------------------------------------------
+-- 1.1.5.
+--------------------------------------------------------------------
STOP INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
+
+--------------------------------------------------------------------
+-- 1.1.6.
+--------------------------------------------------------------------
SHOW INSTANCES;
instance_name status
mysqld1 online
@@ -50,20 +51,25 @@ SHOW INSTANCES;
instance_name status
mysqld1 online
mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.7.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 online
+Success: the process has been started.
Killing the process...
Sleeping...
Success: the process was killed.
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.8.
+--------------------------------------------------------------------
SHOW INSTANCE STATUS;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
+
+--------------------------------------------------------------------
+-- BUG#12813
+--------------------------------------------------------------------
START INSTANCE mysqld1,mysqld2,mysqld3;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
STOP INSTANCE mysqld1,mysqld2,mysqld3;
diff --git a/mysql-test/r/im_utils.result b/mysql-test/r/im_utils.result
index fbfaeaebcac..e6a5e007ed4 100644
--- a/mysql-test/r/im_utils.result
+++ b/mysql-test/r/im_utils.result
@@ -1,3 +1,4 @@
+Success: the process has been started.
SHOW INSTANCES;
instance_name status
mysqld1 online
@@ -42,7 +43,9 @@ skip-innodb VALUE
skip-bdb VALUE
skip-ndbcluster VALUE
START INSTANCE mysqld2;
+Success: the process has been started.
STOP INSTANCE mysqld2;
+Success: the process has been stopped.
SHOW mysqld1 LOG FILES;
Logfile Path File size
ERROR LOG PATH FILE_SIZE
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 00a987c9254..82fad8e912c 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -305,3 +305,29 @@ insert delayed into v1 values (1);
ERROR HY000: 'test.v1' is not BASE TABLE
drop table t1;
drop view v1;
+create table t1 (id int primary key, data int);
+insert into t1 values (1, 1), (2, 2), (3, 3);
+select row_count();
+row_count()
+3
+insert ignore into t1 values (1, 1);
+select row_count();
+row_count()
+0
+replace into t1 values (1, 11);
+select row_count();
+row_count()
+2
+replace into t1 values (4, 4);
+select row_count();
+row_count()
+1
+insert into t1 values (2, 2) on duplicate key update data= data + 10;
+select row_count();
+row_count()
+2
+insert into t1 values (5, 5) on duplicate key update data= data + 10;
+select row_count();
+row_count()
+1
+drop table t1;
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 8b4aba367fb..d4791c6b117 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -169,21 +169,22 @@ select @log;
@log
(BEFORE_INSERT: new=(id=1, data=2))
set @log:= "";
-replace t1 values (1, 3), (2, 2);
+insert into t1 (id, data) values (1, 3), (2, 2) on duplicate key update data= data + 1;
select @log;
@log
-(BEFORE_INSERT: new=(id=1, data=3))(BEFORE_UPDATE: old=(id=1, data=1) new=(id=1, data=3))(AFTER_UPDATE: old=(id=1, data=1) new=(id=1, data=3))(BEFORE_INSERT: new=(id=2, data=2))(AFTER_INSERT: new=(id=2, data=2))
-alter table t1 add ts timestamp default now();
+(BEFORE_INSERT: new=(id=1, data=3))(BEFORE_UPDATE: old=(id=1, data=1) new=(id=1, data=2))(AFTER_UPDATE: old=(id=1, data=1) new=(id=1, data=2))(BEFORE_INSERT: new=(id=2, data=2))(AFTER_INSERT: new=(id=2, data=2))
set @log:= "";
-replace t1 (id, data) values (1, 4);
+replace t1 values (1, 4), (3, 3);
select @log;
@log
-(BEFORE_INSERT: new=(id=1, data=4))(BEFORE_DELETE: old=(id=1, data=3))(AFTER_DELETE: old=(id=1, data=3))(AFTER_INSERT: new=(id=1, data=4))
+(BEFORE_INSERT: new=(id=1, data=4))(BEFORE_DELETE: old=(id=1, data=2))(AFTER_DELETE: old=(id=1, data=2))(AFTER_INSERT: new=(id=1, data=4))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3))
+drop trigger t1_bd;
+drop trigger t1_ad;
set @log:= "";
-insert into t1 (id, data) values (1, 5), (3, 3) on duplicate key update data= data + 2;
+replace t1 values (1, 5);
select @log;
@log
-(BEFORE_INSERT: new=(id=1, data=5))(BEFORE_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(AFTER_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3))
+(BEFORE_INSERT: new=(id=1, data=5))(AFTER_INSERT: new=(id=1, data=5))
drop table t1;
create table t1 (id int primary key, data varchar(10), fk int);
create table t2 (event varchar(100));
@@ -493,15 +494,9 @@ select * from t1;
i k
3 13
replace into t1 values (3, 3);
-ERROR 42S22: Unknown column 'at' in 'NEW'
-select * from t1;
-i k
-3 3
-alter table t1 add ts timestamp default now();
-replace into t1 (i, k) values (3, 13);
ERROR 42S22: Unknown column 'at' in 'OLD'
select * from t1;
-i k ts
+i k
drop table t1, t2;
create table t1 (i int, bt int, k int, key(k)) engine=myisam;
create table t2 (i int);
@@ -574,18 +569,11 @@ i k
1 1
2 2
replace into t1 values (2, 4);
-ERROR 42S22: Unknown column 'bt' in 'NEW'
+ERROR 42S22: Unknown column 'bt' in 'OLD'
select * from t1;
i k
1 1
2 2
-alter table t1 add ts timestamp default now();
-replace into t1 (i, k) values (2, 11);
-ERROR 42S22: Unknown column 'bt' in 'OLD'
-select * from t1;
-i k ts
-1 1 0000-00-00 00:00:00
-2 2 0000-00-00 00:00:00
drop table t1, t2;
drop function if exists bug5893;
create table t1 (col1 int, col2 int);
diff --git a/mysql-test/t/im_daemon_life_cycle-im.opt b/mysql-test/t/im_daemon_life_cycle-im.opt
index 21c01191e4c..3a45c7a41f7 100644
--- a/mysql-test/t/im_daemon_life_cycle-im.opt
+++ b/mysql-test/t/im_daemon_life_cycle-im.opt
@@ -1,2 +1,3 @@
--run-as-service
--log=$MYSQLTEST_VARDIR/log/im.log
+--monitoring-interval=1
diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest
index 87388d7c1e6..3afc36935f8 100644
--- a/mysql-test/t/im_daemon_life_cycle.imtest
+++ b/mysql-test/t/im_daemon_life_cycle.imtest
@@ -10,6 +10,22 @@
###########################################################################
+# Wait for mysqld1 (guarded instance) to start.
+
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started
+
+# Let IM detect that mysqld1 is online. This delay should be longer than
+# monitoring interval.
+
+--sleep 3
+
+# Check that start conditions are as expected.
+
SHOW INSTANCES;
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted
+###########################################################################
+
+# Kill the IM main process and check that the IM Angel will restart the main
+# process.
+
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30
diff --git a/mysql-test/t/im_life_cycle-im.opt b/mysql-test/t/im_life_cycle-im.opt
new file mode 100644
index 00000000000..34b74ce0c95
--- /dev/null
+++ b/mysql-test/t/im_life_cycle-im.opt
@@ -0,0 +1 @@
+--monitoring-interval=1
diff --git a/mysql-test/t/im_life_cycle.imtest b/mysql-test/t/im_life_cycle.imtest
index 445ae7f72fa..2cbe53a7b28 100644
--- a/mysql-test/t/im_life_cycle.imtest
+++ b/mysql-test/t/im_life_cycle.imtest
@@ -17,11 +17,23 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.1.
+--echo --------------------------------------------------------------------
+
+# Wait for mysqld1 (guarded instance) to start.
+
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started
+
+# Let IM detect that mysqld1 is online. This delay should be longer than
+# monitoring interval.
+
+--sleep 3
+
+# Check that start conditions are as expected.
+
SHOW INSTANCES;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld2;
###########################################################################
#
@@ -33,20 +45,24 @@ SHOW INSTANCE STATUS mysqld2;
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.2.
+--echo --------------------------------------------------------------------
+
START INSTANCE mysqld2;
-# FIXME
---sleep 3
+# FIXME: START INSTANCE should be synchronous.
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
-SHOW INSTANCES;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld2;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
---connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
+--connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD2_PORT,$IM_MYSQLD2_SOCK)
--connection mysql_con
---replace_result $IM_MYSQLD1_PORT IM_MYSQLD1_PORT
+--replace_result $IM_MYSQLD2_PORT IM_MYSQLD2_PORT
SHOW VARIABLES LIKE 'port';
--connection default
@@ -61,15 +77,19 @@ SHOW VARIABLES LIKE 'port';
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.3.
+--echo --------------------------------------------------------------------
+
STOP INSTANCE mysqld2;
-# FIXME
---sleep 3
+# FIXME: STOP INSTANCE should be synchronous.
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
-SHOW INSTANCES;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld2;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
###########################################################################
#
@@ -81,16 +101,17 @@ SHOW INSTANCE STATUS mysqld2;
#
###########################################################################
---error 3000
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.4.
+--echo --------------------------------------------------------------------
+
+--error 3000 # ER_BAD_INSTANCE_NAME
START INSTANCE mysqld3;
---error 3002
+--error 3002 # ER_INSTANCE_ALREADY_STARTED
START INSTANCE mysqld1;
-# FIXME TODO
-# BUG#12813: START/STOP INSTANCE commands accept a list as argument
-# START INSTANCE mysqld1, mysqld2;
-
###########################################################################
#
# 1.1.5. Check that Instance Manager reports correct errors for 'STOP INSTANCE'
@@ -101,27 +122,40 @@ START INSTANCE mysqld1;
#
###########################################################################
---error 3000
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.5.
+--echo --------------------------------------------------------------------
+
+--error 3000 # ER_BAD_INSTANCE_NAME
STOP INSTANCE mysqld3;
# TODO: IM should be fixed.
# BUG#12673: Instance Manager allows to stop the instance many times
-# --error 3002
+# --error 3002 # ER_INSTANCE_ALREADY_STARTED
# STOP INSTANCE mysqld2;
-# FIXME TODO
-# BUG#12813: START/STOP INSTANCE commands accept a list as argument
-# STOP INSTANCE mysqld1, mysqld2;
-
###########################################################################
#
# 1.1.6. Check that Instance Manager is able to restart guarded instances.
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.6.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted 30
+
+# Give some time to IM to detect that mysqld was restarted. It should be longer
+# than monitoring interval.
+
+--sleep 3
+
+SHOW INSTANCES;
###########################################################################
#
@@ -129,17 +163,26 @@ SHOW INSTANCES;
#
###########################################################################
-SHOW INSTANCES;
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.7.
+--echo --------------------------------------------------------------------
START INSTANCE mysqld2;
-# FIXME
---sleep 3
+# FIXME: START INSTANCE should be synchronous.
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
-SHOW INSTANCES;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed 10
-SHOW INSTANCES;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
###########################################################################
#
@@ -147,7 +190,13 @@ SHOW INSTANCES;
# incomplete SHOW INSTANCE STATUS command.
#
###########################################################################
---error 1149
+
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.8.
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
SHOW INSTANCE STATUS;
#
@@ -159,8 +208,13 @@ SHOW INSTANCE STATUS;
# a list as argument.
#
---error 1149
+--echo
+--echo --------------------------------------------------------------------
+--echo -- BUG#12813
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
START INSTANCE mysqld1,mysqld2,mysqld3;
---error 1149
+--error ER_SYNTAX_ERROR
STOP INSTANCE mysqld1,mysqld2,mysqld3;
diff --git a/mysql-test/t/im_utils-im.opt b/mysql-test/t/im_utils-im.opt
new file mode 100644
index 00000000000..34b74ce0c95
--- /dev/null
+++ b/mysql-test/t/im_utils-im.opt
@@ -0,0 +1 @@
+--monitoring-interval=1
diff --git a/mysql-test/t/im_utils.imtest b/mysql-test/t/im_utils.imtest
index dc6fb93c4ff..47902eeba52 100644
--- a/mysql-test/t/im_utils.imtest
+++ b/mysql-test/t/im_utils.imtest
@@ -17,6 +17,17 @@
# - the second instance is offline;
#
+# Wait for mysqld1 (guarded instance) to start.
+
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started
+
+# Let IM detect that mysqld1 is online. This delay should be longer than
+# monitoring interval.
+
+--sleep 3
+
+# Check that start conditions are as expected.
+
SHOW INSTANCES;
#
@@ -40,11 +51,10 @@ SHOW INSTANCE OPTIONS mysqld2;
#
START INSTANCE mysqld2;
-
-# FIXME
--- sleep 3
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
STOP INSTANCE mysqld2;
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
#
# Check 'SHOW LOG FILES' command:
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 0c64dd80bec..ac43d0bc818 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -187,3 +187,26 @@ create view v1 as select * from t1;
insert delayed into v1 values (1);
drop table t1;
drop view v1;
+
+#
+# Test for values returned by ROW_COUNT() function
+# (and thus for values returned by mysql_affected_rows())
+# for various forms of INSERT
+#
+create table t1 (id int primary key, data int);
+insert into t1 values (1, 1), (2, 2), (3, 3);
+select row_count();
+insert ignore into t1 values (1, 1);
+select row_count();
+# Reports that 2 rows are affected (1 deleted + 1 inserted)
+replace into t1 values (1, 11);
+select row_count();
+replace into t1 values (4, 4);
+select row_count();
+# Reports that 2 rows are affected. This conforms to documentation.
+# (Useful for differentiating inserts from updates).
+insert into t1 values (2, 2) on duplicate key update data= data + 10;
+select row_count();
+insert into t1 values (5, 5) on duplicate key update data= data + 10;
+select row_count();
+drop table t1;
diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh
index e722b3a180d..64cc869d1ec 100755
--- a/mysql-test/t/kill_n_check.sh
+++ b/mysql-test/t/kill_n_check.sh
@@ -1,66 +1,115 @@
#!/bin/sh
-if [ $# -ne 2 ]; then
- echo "Usage: kill_n_check.sh <pid file path> killed|restarted"
+###########################################################################
+
+# NOTE: this script returns 0 (success) even in case of failure. This is
+# because this script is executed under mysql-test-run[.pl] and it's better to
+# examine particular problem in log file, than just having said that the test
+# case has failed.
+
+###########################################################################
+
+check_restart()
+{
+ if [ ! -r "$pid_path" ]; then
+ user_msg='the process was killed'
+ return 1
+ fi
+
+ new_pid=`cat "$pid_path" 2>/dev/null`
+
+ if [ $? -eq 0 -a "$original_pid" = "$new_pid" ]; then
+ user_msg='the process was not restarted'
+ return 1
+ fi
+
+ user_msg='the process was restarted'
+ return 0
+}
+
+###########################################################################
+
+if [ $# -ne 3 ]; then
+ echo "Usage: kill_n_check.sh <pid file path> killed|restarted <timeout>"
exit 0
fi
pid_path="$1"
expected_result="$2"
+total_timeout="$3"
-if [ -z "$pid_path" -o ! -r "$pid_path" ]; then
- echo "Error: invalid PID path ($pid_path) or PID file does not exist."
+if [ "$expected_result" != 'killed' -a \
+ "$expected_result" != 'restarted' ]; then
+ echo "Error: invalid second argument ('killed' or 'restarted' expected)."
exit 0
fi
-if [ "$expected_result" != "killed" -a \
- "$expected_result" != "restarted" ]; then
- echo "Error: expected result must be either 'killed' or 'restarted'."
+if [ -z "$pid_path" ]; then
+ echo "Error: invalid PID path ($pid_path)."
exit 0
fi
-# echo "PID path: '$pid_path'"
+if [ $expected_result = 'killed' -a ! -r "$pid_path" ]; then
+ echo "Error: PID file ($pid_path) does not exist."
+ exit 0
+fi
-original_pid=`cat "$pid_path"`
+if [ -z "$total_timeout" ]; then
+ echo "Error: timeout is not specified."
+ exit 0
+fi
-# echo "Original PID: $original_pid"
+###########################################################################
+
+original_pid=`cat "$pid_path"`
echo "Killing the process..."
kill -9 $original_pid
+###########################################################################
+
echo "Sleeping..."
-sleep 3
+if [ "$expected_result" = "restarted" ]; then
-new_pid=""
+ # Wait for the process to restart.
-[ -r "$pid_path" ] && new_pid=`cat "$pid_path"`
+ cur_attempt=1
-# echo "New PID: $new_pid"
+ while true; do
-if [ "$expected_result" = "restarted" ]; then
+ if check_restart; then
+ echo "Success: $user_msg."
+ exit 0
+ fi
- if [ -z "$new_pid" ]; then
- echo "Error: the process was killed."
- exit 0
- fi
+ [ $cur_attempt -ge $total_timeout ] && break
- if [ "$original_pid" -eq "$new_pid" ]; then
- echo "Error: the process was not restarted."
- exit 0
- fi
-
- echo "Success: the process was restarted."
+ sleep 1
+
+ cur_attempt=`expr $cur_attempt + 1`
+
+ done
+
+ echo "Error: $user_msg."
exit 0
-
-else # $expected_result = killed
-
+
+else # $expected_result == killed
+
+ # Here we have to sleep for some long time to ensure that the process will
+ # not be restarted.
+
+ sleep $total_timeout
+
+ new_pid=`cat "$pid_path" 2>/dev/null`
+
if [ "$new_pid" -a "$new_pid" -ne "$original_pid" ]; then
echo "Error: the process was restarted."
- exit 0
+ else
+ echo "Success: the process was killed."
fi
- echo "Success: the process was killed."
exit 0
+
fi
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index a5bd2ba0b38..3743d8f5c76 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -185,24 +185,26 @@ select @log;
set @log:= "";
insert ignore t1 values (1, 2);
select @log;
-# REPLACE: before insert trigger should be called for both records,
-# but then for first one update will be executed (and both update
-# triggers should fire). For second after insert trigger will be
-# called as for usual insert
+# INSERT ... ON DUPLICATE KEY UPDATE ...
set @log:= "";
-replace t1 values (1, 3), (2, 2);
+insert into t1 (id, data) values (1, 3), (2, 2) on duplicate key update data= data + 1;
select @log;
-# Now let us change table in such way that REPLACE on won't be executed
-# using update.
-alter table t1 add ts timestamp default now();
+# REPLACE (also test for bug#13479 "REPLACE activates UPDATE trigger,
+# not the DELETE and INSERT triggers")
+# We define REPLACE as INSERT which DELETEs old rows which conflict with
+# row being inserted. So for the first record in statement below we will
+# call before insert trigger, then delete will be executed (and both delete
+# triggers should fire). Finally after insert trigger will be called.
+# For the second record we will just call both on insert triggers.
set @log:= "";
-# This REPLACE should be executed via DELETE and INSERT so proper
-# triggers should be invoked.
-replace t1 (id, data) values (1, 4);
+replace t1 values (1, 4), (3, 3);
select @log;
-# Finally let us test INSERT ... ON DUPLICATE KEY UPDATE ...
+# Now we will drop ON DELETE triggers to test REPLACE which is internally
+# executed via update
+drop trigger t1_bd;
+drop trigger t1_ad;
set @log:= "";
-insert into t1 (id, data) values (1, 5), (3, 3) on duplicate key update data= data + 2;
+replace t1 values (1, 5);
select @log;
# This also drops associated triggers
@@ -531,14 +533,11 @@ alter table t1 add primary key (i);
--error 1054
insert into t1 values (3, 4) on duplicate key update k= k + 10;
select * from t1;
+# The following statement will delete old row and won't
+# insert new one since after delete trigger will fail.
--error 1054
replace into t1 values (3, 3);
select * from t1;
-# Change table in such way that REPLACE will delete row
-alter table t1 add ts timestamp default now();
---error 1054
-replace into t1 (i, k) values (3, 13);
-select * from t1;
# Also drops all triggers
drop table t1, t2;
@@ -594,11 +593,6 @@ select * from t1;
--error 1054
replace into t1 values (2, 4);
select * from t1;
-# Change table in such way that REPLACE will delete row
-alter table t1 add ts timestamp default now();
---error 1054
-replace into t1 (i, k) values (2, 11);
-select * from t1;
# Also drops all triggers
drop table t1, t2;
diff --git a/mysql-test/t/wait_for_process.sh b/mysql-test/t/wait_for_process.sh
new file mode 100755
index 00000000000..df0f4a17e3a
--- /dev/null
+++ b/mysql-test/t/wait_for_process.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+###########################################################################
+
+pid_path="$1"
+total_attempts="$2"
+event="$3"
+
+case "$3" in
+ started)
+ check_fn='check_started';
+ ;;
+
+ stopped)
+ check_fn='check_stopped';
+ ;;
+
+ *)
+ echo "Error: invalid third argument ('started' or 'stopped' expected)."
+ exit 0
+esac
+
+###########################################################################
+
+check_started()
+{
+ [ ! -r "$pid_path" ] && return 1
+
+ new_pid=`cat "$pid_path" 2>/dev/null`
+
+ [ $? -eq 0 -a "$original_pid" = "$new_pid" ] && return 1
+
+ return 0
+}
+
+###########################################################################
+
+check_stopped()
+{
+ [ -r "$pid_path" ] && return 1
+
+ return 0
+}
+
+###########################################################################
+
+cur_attempt=1
+
+while true; do
+
+ if ( eval $check_fn ); then
+ echo "Success: the process has been $event."
+ exit 0
+ fi
+
+ [ $cur_attempt -ge $total_attempts ] && break
+
+ sleep 1
+
+ cur_attempt=`expr $cur_attempt + 1`
+
+done
+
+echo "Error: the process has not been $event in $total_attempts secs."
+exit 0
+
diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc
index fa9d877fde6..24844e05776 100644
--- a/server-tools/instance-manager/guardian.cc
+++ b/server-tools/instance-manager/guardian.cc
@@ -271,10 +271,7 @@ int Guardian_thread::init()
{
if (!(instance->options.nonguarded))
if (guard(instance, TRUE)) /* do not lock guardian */
- {
- instance_map->unlock();
return 1;
- }
}
return 0;
diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc
index 543c9c31bfa..3b7f58d8a09 100644
--- a/server-tools/instance-manager/instance_map.cc
+++ b/server-tools/instance-manager/instance_map.cc
@@ -215,7 +215,7 @@ int Instance_map::flush_instances()
hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
get_instance_key, delete_instance, 0);
rc= load();
- guardian->init();
+ guardian->init(); // TODO: check error status.
pthread_mutex_unlock(&LOCK_instance_map);
guardian->unlock();
return rc;
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
index 00ef50a84e1..353dfcf64dc 100644
--- a/server-tools/instance-manager/manager.cc
+++ b/server-tools/instance-manager/manager.cc
@@ -147,6 +147,25 @@ void manager(const Options &options)
if (create_pid_file(options.pid_file_name, manager_pid))
return;
+ /*
+ Initialize signals and alarm-infrastructure.
+
+ NOTE: To work nicely with LinuxThreads, the signal thread is the first
+ thread in the process.
+
+ NOTE:
+ After init_thr_alarm() call it's possible to call thr_alarm() (from
+ different threads), that results in sending ALARM signal to the alarm
+ thread (which can be the main thread). That signal can interrupt
+ blocking calls.
+
+ In other words, a blocking call can be interrupted in the main thread
+ after init_thr_alarm().
+ */
+
+ sigset_t mask;
+ set_signals(&mask);
+
/* create guardian thread */
{
pthread_t guardian_thd_id;
@@ -154,9 +173,16 @@ void manager(const Options &options)
int rc;
/*
- NOTE: Guardian should be shutdown first. Only then all other threads
- need to be stopped. This should be done, as guardian is responsible for
- shutting down the instances, and this is a long operation.
+ NOTE: Guardian should be shutdown first. Only then all other threads
+ need to be stopped. This should be done, as guardian is responsible
+ for shutting down the instances, and this is a long operation.
+
+ NOTE: Guardian uses thr_alarm() when detects current state of
+ instances (is_running()), but it is not interfere with
+ flush_instances() later in the code, because until flush_instances()
+ complete in the main thread, Guardian thread is not permitted to
+ process instances. And before flush_instances() there is no instances
+ to proceed.
*/
pthread_attr_init(&guardian_thd_attr);
@@ -172,10 +198,8 @@ void manager(const Options &options)
}
- /*
- To work nicely with LinuxThreads, the signal thread is the first thread
- in the process.
- */
+ /* Load instances. */
+
int signo;
bool shutdown_complete;
@@ -189,11 +213,6 @@ void manager(const Options &options)
return;
}
- /* Initialize signals and alarm-infrastructure. */
-
- sigset_t mask;
- set_signals(&mask);
-
/* create the listener */
{
pthread_t listener_thd_id;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5630702fe52..8ffc6f53a43 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1057,16 +1057,19 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
to convert the latter operation internally to an UPDATE.
We also should not perform this conversion if we have
timestamp field with ON UPDATE which is different from DEFAULT.
+ Another case when conversion should not be performed is when
+ we have ON DELETE trigger on table so user may notice that
+ we cheat here. Note that it is ok to do such conversion for
+ tables which have ON UPDATE but have no ON DELETE triggers,
+ we just should not expose this fact to users by invoking
+ ON UPDATE triggers.
*/
if (last_uniq_key(table,key_nr) &&
!table->file->referenced_by_foreign_key() &&
(table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
- table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
+ table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
{
- if (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
- TRG_ACTION_BEFORE, TRUE))
- goto before_trg_err;
if (thd->clear_next_insert_id)
{
/* Reset auto-increment cacheing if we do an update */
@@ -1077,13 +1080,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->record[0])))
goto err;
info->deleted++;
- trg_error= (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
- TRG_ACTION_AFTER,
- TRUE));
- /* Update logfile and count */
- info->copied++;
- goto ok_or_after_trg_err;
+ /*
+ Since we pretend that we have done insert we should call
+ its after triggers.
+ */
+ goto after_trg_n_copied_inc;
}
else
{
@@ -1107,10 +1108,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
}
}
- info->copied++;
- trg_error= (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
- TRG_ACTION_AFTER, TRUE));
}
else if ((error=table->file->write_row(table->record[0])))
{
@@ -1118,14 +1115,14 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
(error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE))
goto err;
table->file->restore_auto_increment();
+ goto ok_or_after_trg_err;
}
- else
- {
- info->copied++;
- trg_error= (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
- TRG_ACTION_AFTER, TRUE));
- }
+
+after_trg_n_copied_inc:
+ info->copied++;
+ trg_error= (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
+ TRG_ACTION_AFTER, TRUE));
ok_or_after_trg_err:
if (key)