~ubuntu-branches/ubuntu/vivid/drizzle/vivid

« back to all changes in this revision

Viewing changes to tests/kewpie/randgen/lib/GenTest/Reporter/CloneSlaveXtrabackup.pm

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-10-29 15:43:40 UTC
  • mfrom: (20.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20131029154340-j36v7gxq9tm1gi5f
Tags: 1:7.2.3-2ubuntu1
* Merge from debian, remaining changes:
  - Link against boost_system because of boost_thread.
  - Add required libs to message/include.am
  - Add upstart job and adjust init script to be upstart compatible.
  - Disable -floop-parallelize-all due to gcc-4.8/4.9 compiler ICE
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57732

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008-2009 Sun Microsystems, Inc. All rights reserved.
2
 
# Use is subject to license terms.
3
 
#
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.
7
 
#
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.
12
 
#
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
16
 
# USA
17
 
 
18
 
package GenTest::Reporter::CloneSlaveXtrabackup;
19
 
 
20
 
require Exporter;
21
 
@ISA = qw(GenTest::Reporter);
22
 
 
23
 
use strict;
24
 
use DBI;
25
 
use GenTest;
26
 
use GenTest::Constants;
27
 
use GenTest::Reporter;
28
 
use GenTest::Comparator;
29
 
use Data::Dumper;
30
 
use IPC::Open2;
31
 
use IPC::Open3;
32
 
 
33
 
my $first_reporter;
34
 
my $clone_done;
35
 
my $client_basedir;
36
 
 
37
 
#
38
 
# We abort the test in case not enough binlog events have been generated
39
 
# since the test can contain FLUSH , we check for either enough binlogs
40
 
# OR enough events in last binlog .
41
 
#
42
 
 
43
 
use constant MINIMUM_BINLOG_COUNT       => 10;
44
 
use constant MINIMUM_BINLOG_SIZE        => 1000000;
45
 
 
46
 
sub monitor {
47
 
        my $reporter = shift;
48
 
 
49
 
        # In case of two servers, we will be called twice.
50
 
        # Only clone a slave when called for the master
51
 
 
52
 
        $first_reporter = $reporter if not defined $first_reporter;
53
 
        return STATUS_OK if $reporter ne $first_reporter;
54
 
 
55
 
        return STATUS_OK if time() < ($reporter->testStart() + ($reporter->testDuration() / 2)) ;
56
 
        return STATUS_OK if $clone_done == 1;
57
 
 
58
 
        $clone_done = 1;
59
 
        
60
 
        my $basedir = $reporter->serverVariable('basedir');
61
 
 
62
 
        foreach my $path ("$basedir/../client", "$basedir/../bin", "$basedir/client/RelWithDebInfo", "$basedir/client/Debug", "$basedir/client", "$basedir/bin") {
63
 
                if (-e $path) {
64
 
                        $client_basedir = $path;
65
 
                        last;
66
 
                }
67
 
        }
68
 
 
69
 
        die "can't determine client_basedir; basedir = $basedir" if not defined $client_basedir;
70
 
 
71
 
        my $binary = $reporter->serverInfo('binary');
72
 
        my $language = $reporter->serverVariable('language');
73
 
        my $lc_messages_dir = $reporter->serverVariable('lc_messages_dir');
74
 
        my $datadir = $reporter->serverVariable('datadir');
75
 
        $datadir =~ s{[\\/]$}{}sgio;
76
 
        my $slave_datadir = $datadir.'_clonedslave_xtrabackup';
77
 
        mkdir($slave_datadir);
78
 
        my $master_port = $reporter->serverVariable('port');
79
 
        my $slave_port = $master_port + 4;
80
 
        my $plugin_dir = $reporter->serverVariable('plugin_dir');
81
 
        my $plugins = $reporter->serverPlugins();
82
 
 
83
 
        my $master_dbh = DBI->connect($reporter->dsn());
84
 
 
85
 
        my $xtrabackup_backup_command = "xtrabackup --backup --datadir=$datadir --target-dir=$slave_datadir";
86
 
        say("Executing backup: $xtrabackup_backup_command");
87
 
        system($xtrabackup_backup_command);
88
 
        return STATUS_ENVIRONMENT_FAILURE if $! != 0;
89
 
 
90
 
        my $xtrabackup_prepare_command = "xtrabackup --prepare --target-dir=$slave_datadir";
91
 
        say("Executing first prepare: $xtrabackup_prepare_command");
92
 
        system($xtrabackup_prepare_command);
93
 
        return STATUS_ENVIRONMENT_FAILURE if $! != 0;
94
 
 
95
 
        say("Executing second prepare: $xtrabackup_prepare_command");
96
 
        system($xtrabackup_prepare_command);
97
 
        return STATUS_ENVIRONMENT_FAILURE if $! != 0;
98
 
 
99
 
        my $binlog_pos_file = $slave_datadir.'/xtrabackup_binlog_pos_innodb';
100
 
        open(BINLOG_POS_FILE, $binlog_pos_file);
101
 
        read(BINLOG_POS_FILE, my $binlog_pos_text, -s $binlog_pos_file);
102
 
        chomp($binlog_pos_text);
103
 
        my ($binlog_file, $binlog_pos) = $binlog_pos_text =~ m{.*/(.*?)\t(.*?)$}sgio;
104
 
 
105
 
        if (($binlog_file eq '') || ($binlog_pos eq '')) {
106
 
                say("Xtrabackup did not provide master_log_file and master_log_pos.");
107
 
                return STATUS_ENVIRONMENT_FAILURE;
108
 
        } else {
109
 
                say("Xtrabackup reports: master_log_file: $binlog_file; master_log_pos: $binlog_pos.");
110
 
        }
111
 
 
112
 
        system("cp -r $datadir/mysql $slave_datadir/");
113
 
 
114
 
        my @all_databases = @{$master_dbh->selectcol_arrayref("SHOW DATABASES")};
115
 
        foreach my $database (grep { $_ !~ m{^(information_schema|performance_schema)$}sgio } @all_databases ) {
116
 
                system("Copying .frm files for database $database...");
117
 
                mkdir("$slave_datadir/$database");
118
 
                system("cp -r $datadir/$database/*.frm $slave_datadir/$database");
119
 
        }
120
 
 
121
 
        my @mysqld_options = (
122
 
                '--no-defaults',
123
 
                '--server-id=3',
124
 
                '--core-file',
125
 
                '--loose-console',
126
 
                '--language='.$language,
127
 
                '--loose-lc-messages-dir='.$lc_messages_dir,
128
 
                '--datadir="'.$slave_datadir.'"',
129
 
                '--log-output=file',
130
 
                '--skip-grant-tables',
131
 
                '--general-log',
132
 
                '--relay-log=clonedslave-relay',
133
 
                '--general_log_file="'.$slave_datadir.'/clonedslave.log"',
134
 
                '--log_error="'.$slave_datadir.'/clonedslave.err"',
135
 
                '--datadir="'.$slave_datadir.'"',
136
 
                '--port='.$slave_port,
137
 
                '--loose-plugin-dir='.$plugin_dir,
138
 
                '--max-allowed-packet=20M',
139
 
                '--innodb',
140
 
                '--sql_mode="NO_ENGINE_SUBSTITUTION"',
141
 
                '--skip-grant-tables'
142
 
        );
143
 
 
144
 
        foreach my $plugin (@$plugins) {
145
 
                push @mysqld_options, '--plugin-load='.$plugin->[0].'='.$plugin->[1];
146
 
        };
147
 
 
148
 
        my $mysqld_command = $binary.' '.join(' ', @mysqld_options).' 2>&1';
149
 
        say("Starting a new mysqld for the cloned slave.");
150
 
        say("$mysqld_command.");
151
 
        my $mysqld_pid = open2(\*RDRFH, \*WTRFH, $mysqld_command);
152
 
 
153
 
        my $slave_dbh;
154
 
 
155
 
        foreach my $try (1..120) {
156
 
                sleep(1);
157
 
                $slave_dbh = DBI->connect("dbi:mysql:user=root:host=127.0.0.1:port=".$slave_port, undef, undef, { RaiseError => 0 , PrintError => 0 } );
158
 
                next if not defined $slave_dbh;
159
 
                last if $slave_dbh->ping();
160
 
        }
161
 
 
162
 
        return STATUS_ENVIRONMENT_FAILURE if not defined $slave_dbh;
163
 
 
164
 
        say("Cloned slave has started.");
165
 
        
166
 
        say("Issuing START SLAVE on the cloned slave...");
167
 
 
168
 
        $slave_dbh->do("
169
 
                CHANGE MASTER TO
170
 
                MASTER_PORT = ".$master_port.",
171
 
                MASTER_HOST = '127.0.0.1',
172
 
                MASTER_LOG_FILE = '$binlog_file',
173
 
                MASTER_LOG_POS = $binlog_pos,
174
 
                MASTER_USER = 'root',
175
 
                MASTER_CONNECT_RETRY = 1
176
 
        ");
177
 
 
178
 
        $slave_dbh->do("START SLAVE");
179
 
 
180
 
        say("START SLAVE was issued. The main test/workload will now continue.");
181
 
 
182
 
        return STATUS_OK;
183
 
}
184
 
 
185
 
sub report {
186
 
        my $reporter = shift;
187
 
 
188
 
        my $basedir = $reporter->serverVariable('basedir');
189
 
 
190
 
        foreach my $path ("$basedir/../client", "$basedir/../bin", "$basedir/client/RelWithDebInfo", "$basedir/client/Debug", "$basedir/client", "$basedir/bin") {
191
 
                if (-e $path) {
192
 
                        $client_basedir = $path;
193
 
                        last;
194
 
                }
195
 
        }
196
 
 
197
 
        die "can't determine client_basedir; basedir = $basedir" if not defined $client_basedir;
198
 
 
199
 
        my $master_port = $reporter->serverVariable('port');
200
 
        my $slave_port = $master_port + 4;
201
 
        my $master_dbh = DBI->connect($reporter->dsn());
202
 
        my $slave_dbh = DBI->connect("dbi:mysql:user=root:host=127.0.0.1:port=".$slave_port, undef, undef, { RaiseError => 1 } );
203
 
 
204
 
        say("Issuing START SLAVE on the cloned slave.");
205
 
        $slave_dbh->do("START SLAVE");
206
 
 
207
 
        my ($final_binlog_file, $final_binlog_pos) = $master_dbh->selectrow_array("SHOW MASTER STATUS");
208
 
        exit_test(STATUS_UNKNOWN_ERROR) if !defined $final_binlog_file;
209
 
 
210
 
        say("The cloned slave must catch up to $final_binlog_file:$final_binlog_pos.");
211
 
 
212
 
        #
213
 
        # We call MASTER_POS_WAIT at 100K increments in order to avoid buildbot timeout in case
214
 
        # one big MASTER_POS_WAIT would take more than 20 minutes.
215
 
        #
216
 
 
217
 
        my $sth_binlogs = $master_dbh->prepare("SHOW BINARY LOGS");
218
 
        $sth_binlogs->execute();
219
 
        while (my ($intermediate_binlog_file, $intermediate_binlog_size) = $sth_binlogs->fetchrow_array()) {
220
 
                my $intermediate_binlog_pos = $intermediate_binlog_size < 10000000 ? $intermediate_binlog_size : 10000000;
221
 
                do {
222
 
                        say("Executing intermediate MASTER_POS_WAIT('$intermediate_binlog_file', $intermediate_binlog_pos) on cloned slave.");
223
 
                        my $intermediate_wait_result = $slave_dbh->selectrow_array("SELECT MASTER_POS_WAIT('$intermediate_binlog_file', $intermediate_binlog_pos)");
224
 
                        if (not defined $intermediate_wait_result) {
225
 
                                say("Intermediate MASTER_POS_WAIT('$intermediate_binlog_file', $intermediate_binlog_pos) failed on cloned slave on port $slave_port.");
226
 
                                return STATUS_REPLICATION_FAILURE;
227
 
                        }
228
 
                        $intermediate_binlog_pos += 10000000;
229
 
                } while (  $intermediate_binlog_pos <= $intermediate_binlog_size );
230
 
        }
231
 
 
232
 
        say("Waiting for cloned slave to catch up..., file $final_binlog_file, pos $final_binlog_pos .");
233
 
        my $final_wait_result = $slave_dbh->selectrow_array("SELECT MASTER_POS_WAIT('$final_binlog_file', $final_binlog_pos)");
234
 
 
235
 
        if (not defined $final_wait_result) {
236
 
                say("MASTER_POS_WAIT() failed. Cloned slave replication thread not running.");
237
 
                return STATUS_REPLICATION_FAILURE;        }
238
 
        
239
 
        say("Cloned slave caught up.");
240
 
 
241
 
        my @all_databases = @{$master_dbh->selectcol_arrayref("SHOW DATABASES")};
242
 
        my $databases_string = join(' ', grep { $_ !~ m{^(mysql|information_schema|performance_schema)$}sgio } @all_databases );
243
 
                
244
 
        my @dump_ports = ($master_port, $slave_port);
245
 
        my @dump_files;
246
 
 
247
 
        foreach my $i (0..$#dump_ports) {
248
 
                say("Dumping server on port $dump_ports[$i]...");
249
 
                $dump_files[$i] = tmpdir()."/server_".$$."_".$i.".dump";
250
 
 
251
 
                my $dump_result = system("\"$client_basedir/mysqldump\" --hex-blob --no-tablespaces --skip-triggers --compact --order-by-primary --skip-extended-insert --no-create-info --host=127.0.0.1 --port=$dump_ports[$i] --user=root --databases $databases_string | sort > $dump_files[$i]") >> 8;
252
 
                return STATUS_ENVIRONMENT_FAILURE if $dump_result > 0;
253
 
        }
254
 
 
255
 
        say("Comparing SQL dumps...");
256
 
        my $diff_result = system("diff -u $dump_files[0] $dump_files[1]") >> 8;
257
 
 
258
 
        if ($diff_result == 0) {
259
 
                say("No differences were found between master and cloned slave.");
260
 
        }
261
 
 
262
 
        foreach my $dump_file (@dump_files) {
263
 
                unlink($dump_file);
264
 
        }
265
 
 
266
 
        return $diff_result == 0 ? STATUS_OK : STATUS_REPLICATION_FAILURE;
267
 
}
268
 
 
269
 
sub type {
270
 
        return REPORTER_TYPE_PERIODIC | REPORTER_TYPE_SUCCESS;
271
 
}
272
 
 
273
 
1;