2
# Copyright (C) 2006 MySQL AB
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; version 2 of the License.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
# This is a library file used by the Perl version of mysql-test-run,
18
# and is part of the translation of the Bourne shell script with the
23
# Private IM-related operations.
25
sub mtr_im_kill_process ($$$$);
26
sub mtr_im_load_pids ($);
27
sub mtr_im_terminate ($);
28
sub mtr_im_check_alive ($);
29
sub mtr_im_check_main_alive ($);
30
sub mtr_im_check_angel_alive ($);
31
sub mtr_im_check_mysqlds_alive ($);
32
sub mtr_im_check_mysqld_alive ($);
33
sub mtr_im_cleanup ($);
34
sub mtr_im_rm_file ($);
35
sub mtr_im_errlog ($);
37
sub mtr_im_wait_for_connection ($$$);
38
sub mtr_im_wait_for_mysqld($$$);
40
# Public IM-related operations.
42
sub mtr_im_start ($$);
45
##############################################################################
49
##############################################################################
51
sub mtr_im_kill_process ($$$$) {
54
my $total_retries= shift;
59
foreach my $pid ( @{$pid_lst} )
64
for ( my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt )
66
foreach my $pid ( keys %pids )
68
mtr_debug("Sending $signal to $pid...");
72
unless ( kill (0, $pid) )
74
mtr_debug("Process $pid died.");
79
return if scalar keys %pids == 0;
81
mtr_debug("Sleeping $timeout second(s) waiting for processes to die...");
86
mtr_debug("Process(es) " .
87
join(' ', keys %pids) .
88
" is still alive after $total_retries " .
89
"of sending signal $signal.");
92
###########################################################################
94
sub mtr_im_load_pids($) {
97
mtr_debug("Loading PID files...");
99
# Obtain mysqld-process pids.
101
my $instances = $im->{'instances'};
103
for ( my $idx= 0; $idx < 2; ++$idx )
105
mtr_debug("IM-guarded mysqld[$idx] PID file: '" .
106
$instances->[$idx]->{'path_pid'} . "'.");
110
if ( -r $instances->[$idx]->{'path_pid'} )
112
$mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'});
113
mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid.");
118
mtr_debug("IM-guarded mysqld[$idx]: no PID file.");
121
$instances->[$idx]->{'pid'}= $mysqld_pid;
124
# Re-read Instance Manager PIDs from the file, since during tests Instance
125
# Manager could have been restarted, so its PIDs could have been changed.
129
mtr_debug("IM-main PID file: '$im->{path_pid}'.");
131
if ( -f $im->{'path_pid'} )
134
mtr_get_pid_from_file($im->{'path_pid'});
136
mtr_debug("IM-main PID: $im->{pid}.");
140
mtr_debug("IM-main: no PID file.");
146
mtr_debug("IM-angel PID file: '$im->{path_angel_pid}'.");
148
if ( -f $im->{'path_angel_pid'} )
151
mtr_get_pid_from_file($im->{'path_angel_pid'});
153
mtr_debug("IM-angel PID: $im->{'angel_pid'}.");
157
mtr_debug("IM-angel: no PID file.");
158
$im->{'angel_pid'} = undef;
162
###########################################################################
164
sub mtr_im_terminate($) {
167
# Load pids from pid-files. We should do it first of all, because IM deletes
170
mtr_im_load_pids($im);
172
mtr_debug("Shutting Instance Manager down...");
174
# Ignoring SIGCHLD so that all children could rest in peace.
178
# Send SIGTERM to IM-main.
180
if ( defined $im->{'pid'} )
182
mtr_debug("IM-main pid: $im->{pid}.");
183
mtr_debug("Stopping IM-main...");
185
mtr_im_kill_process([ $im->{'pid'} ], 'TERM', 10, 1);
189
mtr_debug("IM-main pid: n/a.");
192
# If IM-angel was alive, wait for it to die.
194
if ( defined $im->{'angel_pid'} )
196
mtr_debug("IM-angel pid: $im->{'angel_pid'}.");
197
mtr_debug("Waiting for IM-angel to die...");
199
my $total_attempts= 10;
201
for ( my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt )
203
unless ( kill (0, $im->{'angel_pid'}) )
205
mtr_debug("IM-angel died.");
214
mtr_debug("IM-angel pid: n/a.");
221
mtr_im_load_pids($im);
224
###########################################################################
226
sub mtr_im_check_alive($) {
229
mtr_debug("Checking whether IM-components are alive...");
231
return 1 if mtr_im_check_main_alive($im);
233
return 1 if mtr_im_check_angel_alive($im);
235
return 1 if mtr_im_check_mysqlds_alive($im);
240
###########################################################################
242
sub mtr_im_check_main_alive($) {
245
# Check that the process, that we know to be IM's, is dead.
247
if ( defined $im->{'pid'} )
249
if ( kill (0, $im->{'pid'}) )
251
mtr_debug("IM-main (PID: $im->{pid}) is alive.");
256
mtr_debug("IM-main (PID: $im->{pid}) is dead.");
261
mtr_debug("No PID file for IM-main.");
264
# Check that IM does not accept client connections.
266
if ( mtr_ping_port($im->{'port'}) )
268
mtr_debug("IM-main (port: $im->{port}) " .
269
"is accepting connections.");
271
mtr_im_errlog("IM-main is accepting connections on port " .
272
"$im->{port}, but there is no " .
273
"process information.");
278
mtr_debug("IM-main (port: $im->{port}) " .
279
"does not accept connections.");
284
###########################################################################
286
sub mtr_im_check_angel_alive($) {
289
# Check that the process, that we know to be the Angel, is dead.
291
if ( defined $im->{'angel_pid'} )
293
if ( kill (0, $im->{'angel_pid'}) )
295
mtr_debug("IM-angel (PID: $im->{angel_pid}) is alive.");
300
mtr_debug("IM-angel (PID: $im->{angel_pid}) is dead.");
306
mtr_debug("No PID file for IM-angel.");
311
###########################################################################
313
sub mtr_im_check_mysqlds_alive($) {
316
mtr_debug("Checking for IM-guarded mysqld instances...");
318
my $instances = $im->{'instances'};
320
for ( my $idx= 0; $idx < 2; ++$idx )
322
mtr_debug("Checking mysqld[$idx]...");
325
if mtr_im_check_mysqld_alive($instances->[$idx]);
329
###########################################################################
331
sub mtr_im_check_mysqld_alive($) {
332
my $mysqld_instance= shift;
334
# Check that the process is dead.
336
if ( defined $mysqld_instance->{'pid'} )
338
if ( kill (0, $mysqld_instance->{'pid'}) )
340
mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive.");
345
mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead.");
350
mtr_debug("No PID file for mysqld instance.");
353
# Check that mysqld does not accept client connections.
355
if ( mtr_ping_port($mysqld_instance->{'port'}) )
357
mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
358
"is accepting connections.");
360
mtr_im_errlog("Mysqld is accepting connections on port " .
361
"$mysqld_instance->{port}, but there is no " .
362
"process information.");
367
mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
368
"does not accept connections.");
373
###########################################################################
375
sub mtr_im_cleanup($) {
378
mtr_im_rm_file($im->{'path_pid'});
379
mtr_im_rm_file($im->{'path_sock'});
381
mtr_im_rm_file($im->{'path_angel_pid'});
383
for ( my $idx= 0; $idx < 2; ++$idx )
385
mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_pid'});
386
mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_sock'});
390
###########################################################################
392
sub mtr_im_rm_file($)
394
my $file_path= shift;
398
mtr_debug("Removing '$file_path'...");
400
unless ( unlink($file_path) )
402
mtr_warning("Can not remove '$file_path'.")
407
mtr_debug("File '$file_path' does not exist already.");
411
###########################################################################
413
sub mtr_im_errlog($) {
416
# Complain in error log so that a warning will be shown.
418
# TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so
419
# that it can be seen on console and does not produce pushbuild error.
421
# my $errlog= "$opt_vardir/log/mysql-test-run.pl.err";
423
# open (ERRLOG, ">>$errlog") ||
424
# mtr_error("Can not open error log ($errlog)");
426
# my $ts= localtime();
428
# "Warning: [$ts] $msg\n";
433
print "Warning: [$ts] $msg\n";
436
###########################################################################
441
# Re-load PIDs. That can be useful because some processes could have been
444
mtr_im_load_pids($im);
446
# Ignoring SIGCHLD so that all children could rest in peace.
450
# Kill IM-angel first of all.
452
if ( defined $im->{'angel_pid'} )
454
mtr_debug("Killing IM-angel (PID: $im->{angel_pid})...");
455
mtr_im_kill_process([ $im->{'angel_pid'} ], 'KILL', 10, 1)
459
mtr_debug("IM-angel is dead.");
462
# Re-load PIDs again.
464
mtr_im_load_pids($im);
468
if ( defined $im->{'pid'} )
470
mtr_debug("Killing IM-main (PID: $im->pid})...");
471
mtr_im_kill_process([ $im->{'pid'} ], 'KILL', 10, 1);
475
mtr_debug("IM-main is dead.");
478
# Re-load PIDs again.
480
mtr_im_load_pids($im);
482
# Kill guarded mysqld instances.
486
mtr_debug("Collecting PIDs of mysqld instances to kill...");
488
for ( my $idx= 0; $idx < 2; ++$idx )
490
my $pid= $im->{'instances'}->[$idx]->{'pid'};
492
unless ( defined $pid )
497
mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid.");
499
push (@mysqld_pids, $pid);
502
if ( scalar @mysqld_pids > 0 )
504
mtr_debug("Killing IM-guarded mysqld instances...");
505
mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1);
513
##############################################################################
515
sub mtr_im_wait_for_connection($$$) {
517
my $total_attempts= shift;
518
my $connect_timeout= shift;
520
mtr_debug("Waiting for IM on port $im->{port} " .
521
"to start accepting connections...");
523
for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt )
525
mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)...");
527
if ( mtr_ping_port($im->{'port'}) )
529
mtr_debug("IM is accepting connections " .
530
"on port $im->{port}.");
534
mtr_debug("Sleeping $connect_timeout...");
535
sleep($connect_timeout);
538
mtr_debug("IM does not accept connections " .
539
"on port $im->{port} after " .
540
($total_attempts * $connect_timeout) . " seconds.");
545
##############################################################################
547
sub mtr_im_wait_for_mysqld($$$) {
549
my $total_attempts= shift;
550
my $connect_timeout= shift;
552
mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " .
553
"to start accepting connections...");
555
for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt )
557
mtr_debug("Trying to connect to mysqld " .
558
"($cur_attempt of $total_attempts)...");
560
if ( mtr_ping_port($mysqld->{'port'}) )
562
mtr_debug("Mysqld is accepting connections " .
563
"on port $mysqld->{port}.");
567
mtr_debug("Sleeping $connect_timeout...");
568
sleep($connect_timeout);
571
mtr_debug("Mysqld does not accept connections " .
572
"on port $mysqld->{port} after " .
573
($total_attempts * $connect_timeout) . " seconds.");
578
##############################################################################
582
##############################################################################
584
sub mtr_im_start($$) {
588
mtr_debug("Starting Instance Manager...");
591
mtr_init_args(\$args);
592
mtr_add_arg($args, "--defaults-file=%s", $im->{'defaults_file'});
594
foreach my $opt ( @{$opts} )
596
mtr_add_arg($args, $opt);
599
$im->{'spawner_pid'} =
601
$::exe_im, # path to the executable
602
$args, # cmd-line args
604
$im->{'path_log'}, # stdout
605
$im->{'path_err'}, # stderr
606
'', # pid file path (not used)
607
{ append_log_file => 1 } # append log files
610
unless ( $im->{'spawner_pid'} )
612
mtr_error('Could not start Instance Manager.')
615
# Instance Manager can be run in daemon mode. In this case, it creates
616
# several processes and the parent process, created by mtr_spawn(), exits just
617
# after start. So, we have to obtain Instance Manager PID from the PID file.
619
mtr_debug("Waiting for IM to create PID file (" .
620
"path: '$im->{path_pid}'; " .
621
"timeout: $im->{start_timeout})...");
623
unless ( sleep_until_file_created($im->{'path_pid'},
624
$im->{'start_timeout'},
625
-1) ) # real PID is still unknown
627
mtr_debug("IM has not created PID file in $im->{start_timeout} secs.");
628
mtr_debug("Aborting test suite...");
630
mtr_kill_leftovers();
632
mtr_report("IM has not created PID file in $im->{start_timeout} secs.");
636
$im->{'pid'}= mtr_get_pid_from_file($im->{'path_pid'});
638
mtr_debug("Instance Manager started. PID: $im->{pid}.");
640
# Wait until we can connect to IM.
642
my $IM_CONNECT_TIMEOUT= 30;
644
unless ( mtr_im_wait_for_connection($im,
645
$IM_CONNECT_TIMEOUT, 1) )
647
mtr_debug("Can not connect to Instance Manager " .
648
"in $IM_CONNECT_TIMEOUT seconds after start.");
649
mtr_debug("Aborting test suite...");
651
mtr_kill_leftovers();
653
mtr_report("Can not connect to Instance Manager " .
654
"in $IM_CONNECT_TIMEOUT seconds after start.");
658
# Wait for IM to start guarded instances:
659
# - wait for PID files;
661
mtr_debug("Waiting for guarded mysqlds instances to create PID files...");
663
for ( my $idx= 0; $idx < 2; ++$idx )
665
my $mysqld= $im->{'instances'}->[$idx];
667
if ( exists $mysqld->{'nonguarded'} )
672
mtr_debug("Waiting for mysqld[$idx] to create PID file (" .
673
"path: '$mysqld->{path_pid}'; " .
674
"timeout: $mysqld->{start_timeout})...");
676
unless ( sleep_until_file_created($mysqld->{'path_pid'},
677
$mysqld->{'start_timeout'},
678
-1) ) # real PID is still unknown
680
mtr_debug("mysqld[$idx] has not created PID file in " .
681
"$mysqld->{start_timeout} secs.");
682
mtr_debug("Aborting test suite...");
684
mtr_kill_leftovers();
686
mtr_report("mysqld[$idx] has not created PID file in " .
687
"$mysqld->{start_timeout} secs.");
691
mtr_debug("PID file for mysqld[$idx] ($mysqld->{path_pid} created.");
694
# Wait until we can connect to guarded mysqld-instances
695
# (in other words -- wait for IM to start guarded instances).
697
mtr_debug("Waiting for guarded mysqlds to start accepting connections...");
699
for ( my $idx= 0; $idx < 2; ++$idx )
701
my $mysqld= $im->{'instances'}->[$idx];
703
if ( exists $mysqld->{'nonguarded'} )
708
mtr_debug("Waiting for mysqld[$idx] to accept connection...");
710
unless ( mtr_im_wait_for_mysqld($mysqld, 30, 1) )
712
mtr_debug("Can not connect to mysqld[$idx] " .
713
"in $IM_CONNECT_TIMEOUT seconds after start.");
714
mtr_debug("Aborting test suite...");
716
mtr_kill_leftovers();
718
mtr_report("Can not connect to mysqld[$idx] " .
719
"in $IM_CONNECT_TIMEOUT seconds after start.");
723
mtr_debug("mysqld[$idx] started.");
726
mtr_debug("Instance Manager and its components are up and running.");
731
##############################################################################
736
mtr_debug("Stopping Instance Manager...");
738
# Try graceful shutdown.
740
mtr_im_terminate($im);
742
# Check that all processes died.
744
unless ( mtr_im_check_alive($im) )
746
mtr_debug("Instance Manager has been stopped successfully.");
751
# Instance Manager don't want to die. We should kill it.
753
mtr_im_errlog("Instance Manager did not shutdown gracefully.");
757
# Check again that all IM-related processes have been killed.
759
my $im_is_alive= mtr_im_check_alive($im);
765
mtr_debug("Can not kill Instance Manager or its children.");
769
mtr_debug("Instance Manager has been killed successfully.");
773
###########################################################################