1
# Copyright (C) 2008-2009 Sun Microsystems, Inc. All rights reserved.
2
# Use is subject to license terms.
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, but
9
# WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
# 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
18
package GenTest::Reporter::DrizzleSlavePluginCrashRecover;
21
@ISA = qw(GenTest::Reporter);
26
use GenTest::Constants;
27
use GenTest::Reporter;
33
use constant SERVER1_FILE_NAME => 0;
34
use constant SERVER2_FILE_NAME => 1;
41
# In case of two servers, we will be called twice.
42
# Only kill the first server and ignore the second call.
44
$first_reporter = $reporter if not defined $first_reporter;
45
return STATUS_OK if $reporter ne $first_reporter;
47
my $dbh = DBI->connect($reporter->dsn(), undef, undef, {PrintError => 0});
50
my $pid = $ENV{'BOT0_S0_PID'};
52
my $testEnd = $reporter->testEnd();
54
say("testEnd: $testEnd");
55
if (time() > $reporter->testEnd() - 3500)
57
#my $ps_result = system("ps -al");
59
say("Sending kill -9 to server pid $pid in order to force a recovery.");
61
#my $ps_result = system("ps -al");
63
return STATUS_SERVER_KILLED;
76
$first_reporter = $reporter if not defined $first_reporter;
77
return STATUS_OK if $reporter ne $first_reporter;
79
# do some setup and whatnot
84
if (exists $ENV{'MASTER_MYPORT'})
86
$main_port = $ENV{'MASTER_MYPORT'};
92
if (exists $ENV{'BOT0_S1'})
94
$validator_port = $ENV{'BOT0_S1'};
98
$validator_port = '9307';
100
if (exists $ENV{'DRIZZLE_BASEDIR'})
102
$basedir = $ENV{'DRIZZLE_BASEDIR'};
106
$basedir= $reporter->serverVariable('basedir');
108
my $drizzledump = $basedir.'/client/drizzledump' ;
109
my $drizzle_client = $basedir.'/client/drizzle' ;
110
my $transaction_reader;
111
if (exists $ENV{'DRIZZLE_TRX_READER'})
113
$transaction_reader = $ENV{'DRIZZLE_TRX_READER'}
115
elsif (-e $basedir.'/drizzled/message/transaction_reader')
117
$transaction_reader = $basedir.'/drizzled/message/transaction_reader';
121
$transaction_reader = $basedir.'/plugin/transaction_log/utilities/drizzletrx' ;
124
# transaction log location can vary depending on how we start the server
125
# we really only account for test-run and drizzle-automation starts
126
my $transaction_log = '';
127
if (-e $basedir.'/var/local/transaction.log')
129
$transaction_log = $basedir.'/var/local/transaction.log' ;
131
elsif (-e $basedir.'/tests/workdir/bot0/s0/var/master-data/local/transaction.log')
133
$transaction_log = $basedir.'/tests/workdir/bot0/s0/var/master-data/local/transaction.log' ;
137
$transaction_log = $basedir.'/tests/var/master-data/local/transaction.log' ;
139
my $transaction_log_copy = tmpdir()."/translog_".$$."_.log" ;
140
copy($transaction_log, $transaction_log_copy);
142
# Server restart razzle-dazzle
143
my $binary = $basedir.'/drizzled/drizzled' ;
144
my $datadir = $reporter->serverVariable('datadir');
148
my $dbh_prev = DBI->connect($reporter->dsn());
150
if (defined $dbh_prev) {
151
# Server is still running, kill it.
152
$dbh_prev->disconnect();
154
say("Sending shutdown() call to server.");
155
$dbh_prev->selectrow_array('SELECT shutdown()');
159
say("Attempting database recovery using the server ...");
161
my @drizzled_options = (
164
'--datadir="'.$datadir.'"',
165
'--basedir="'.$basedir.'"',
166
'--plugin-add=shutdown_function',
167
'--innodb.replication-log',
168
'--mysql-protocol.port='.$main_port,
172
my $drizzled_command = $binary.' '.join(' ', @drizzled_options).' 2>&1';
173
say("Executing $drizzled_command .");
175
my $drizzled_pid = open2(\*RDRFH, \*WTRFH, $drizzled_command);
176
say("$drizzled_pid");
179
# Phase1 - the server is running single-threaded. We consume the error log and parse it for
180
# statements that indicate failed recovery
183
my $recovery_status = STATUS_OK;
186
my $dbh = DBI->connect($reporter->dsn());
187
$recovery_status = STATUS_DATABASE_CORRUPTION if not defined $dbh && $recovery_status == STATUS_OK;
189
if ($recovery_status > STATUS_OK) {
190
say("Recovery has failed.");
191
return $recovery_status;
194
say("Waiting for slave to catch up...");
196
say("$validator_port");
197
say("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
198
my $slave_dsn="dbi:drizzle:host=localhost:port=$validator_port:user=root:password='':database=sys_replication";
199
my $slave_dbh = DBI->connect($slave_dsn, undef, undef, {PrintError => 0});
200
my $master_dbh = DBI->connect($reporter->dsn(), undef, undef, {PrintError => 0});
204
my @max_slave_id_res = $slave_dbh->selectrow_array('SELECT last_applied_commit_id from applier_state');
205
my $max_slave_id = @max_slave_id_res->[0] ;
206
my @max_master_id_res = $master_dbh->selectrow_arrayref("SELECT MAX(commit_id) from DATA_DICTIONARY.SYS_REPLICATION_LOG");
207
my $max_master_id = @max_master_id_res->[0]->[0] ;
208
if ($max_slave_id == $max_master_id)
213
#say ("$max_slave_id");
214
#say ("$max_master_id");
217
say("Validating replication via dumpfile compare...");
219
my @ports = ($main_port, $validator_port);
221
foreach my $port_id (0..1)
223
$files[$port_id] = tmpdir()."/translog_rpl_dump_".$$."_".$ports[$port_id].".sql";
224
say("$files[$port_id]");
225
say("$drizzledump --compact --skip-extended-insert --host=127.0.0.1 --port=$ports[$port_id] --user=root test >$files[$port_id]");
226
my $drizzledump_result = system("$drizzledump --compact --skip-extended-insert --host=127.0.0.1 --port=$ports[$port_id] --user=root test >$files[$port_id]");
227
# disable pipe to 'sort' from drizzledump call above
228
#| sort > $files[$port_id]");
229
return STATUS_UNKNOWN_ERROR if $drizzledump_result > 0;
231
say ("Executing diff --unified $files[SERVER1_FILE_NAME] $files[SERVER2_FILE_NAME]");
232
my $diff_result = system("diff --unified $files[SERVER1_FILE_NAME] $files[SERVER2_FILE_NAME]");
233
$diff_result = $diff_result >> 8;
236
return STATUS_UNKNOWN_ERROR if $diff_result > 1;
238
if ($diff_result == 1)
240
say("Differences between the two servers were found after comparing dumpfiles");
241
say("diff command: diff --unified $files[SERVER1_FILE_NAME] $files[SERVER2_FILE_NAME]");
242
say("Master dumpfile: $files[SERVER1_FILE_NAME]");
243
say("Slave dumpfile: $files[SERVER2_FILE_NAME]");
244
#say ("$max_slave_id");
245
#say ("$max_master_id");
246
return STATUS_REPLICATION_FAILURE;
250
foreach my $file (@files)
262
return REPORTER_TYPE_ALWAYS | REPORTER_TYPE_PERIODIC;