Merge pt-osc-2.1. Fix NibbleItertor.pm to work with OobNibbleIterator when resuming at oob boundaries (t/pt-table-checksum/resume.t was failing).

This commit is contained in:
Daniel Nichter
2012-04-03 09:33:10 -06:00
23 changed files with 6209 additions and 3459 deletions

View File

@@ -9,7 +9,7 @@ BEGIN {
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More tests => 2;
use Test::More tests => 4;
use PerconaTest;
use CleanupTask;
@@ -30,6 +30,23 @@ is(
"Cleanup task called after obj destroyed"
);
$foo = 0;
my $set_foo = new CleanupTask(sub { $foo = 42; });
is(
$foo,
0,
"Cleanup task not called yet"
);
$set_foo = undef;
is(
$foo,
42,
"Cleanup task called after obj=undef"
);
# #############################################################################
# Done.
# #############################################################################

View File

@@ -9,7 +9,7 @@ BEGIN {
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More tests => 12;
use Test::More tests => 14;
use MySQLStatusWaiter;
use PerconaTest;
@@ -72,7 +72,7 @@ my $sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
spec => [qw(Threads_connected Threads_running)],
max_spec => [qw(Threads_connected Threads_running)],
);
is_deeply(
@@ -136,7 +136,7 @@ $sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
spec => [qw(Threads_connected=5 Threads_running=5)],
max_spec => [qw(Threads_connected=5 Threads_running=5)],
);
is_deeply(
@@ -178,7 +178,7 @@ $sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
spec => [],
max_spec => [],
);
is(
@@ -204,6 +204,40 @@ is(
"No spec, no sleep"
);
# ############################################################################
# Critical thresholds (with static vals).
# ############################################################################
@vals = (
# first check, no wait
{ Threads_running => 1, },
{ Threads_running => 9, },
);
$sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
max_spec => [qw(Threads_running=4)],
critical_spec => [qw(Threads_running=8)],
);
@checked = ();
$slept = 0;
$sw->wait();
is(
$slept,
0,
"Vals not critical, did not sleep"
);
throws_ok(
sub { $sw->wait(); },
qr/Threads_running=9 exceeds its critical threshold 8/,
"Die on critical threshold"
);
# #############################################################################
# Done.
# #############################################################################

View File

@@ -39,7 +39,7 @@ if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
else {
plan tests => 46;
plan tests => 48;
}
my $q = new Quoter();
@@ -94,6 +94,7 @@ sub make_nibble_iter {
one_nibble => $args{one_nibble},
resume => $args{resume},
order_by => $args{order_by},
comments => $args{comments},
%common_modules,
);
@@ -527,7 +528,7 @@ $ni = make_nibble_iter(
$ni->next();
is(
$ni->statements()->{nibble}->{Statement},
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code` FROM `sakila`.`address` FORCE INDEX(`PRIMARY`) WHERE ((`address_id` >= ?)) AND ((`address_id` <= ?)) /*checksum chunk*/",
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code` FROM `sakila`.`address` FORCE INDEX(`PRIMARY`) WHERE ((`address_id` >= ?)) AND ((`address_id` <= ?)) /*nibble table*/",
"--ignore-columns"
);
@@ -545,7 +546,7 @@ $ni->next();
is(
$ni->statements()->{nibble}->{Statement},
"SELECT `actor_id`, `film_id`, `last_update` FROM `sakila`.`film_actor` FORCE INDEX(`PRIMARY`) WHERE ((`actor_id` > ?) OR (`actor_id` = ? AND `film_id` >= ?)) AND ((`actor_id` < ?) OR (`actor_id` = ? AND `film_id` <= ?)) ORDER BY `actor_id`, `film_id` /*checksum chunk*/",
"SELECT `actor_id`, `film_id`, `last_update` FROM `sakila`.`film_actor` FORCE INDEX(`PRIMARY`) WHERE ((`actor_id` > ?) OR (`actor_id` = ? AND `film_id` >= ?)) AND ((`actor_id` < ?) OR (`actor_id` = ? AND `film_id` <= ?)) ORDER BY `actor_id`, `film_id` /*nibble table*/",
"Add ORDER BY to nibble SQL"
);
@@ -722,7 +723,7 @@ $ni = make_nibble_iter(
my $sql = $ni->statements()->{nibble}->{Statement};
is(
$sql,
"SELECT `c` FROM `test`.`t` WHERE c>'m' /*checksum table*/",
"SELECT `c` FROM `test`.`t` WHERE c>'m' /*bite table*/",
"One nibble SQL with where"
);
@@ -795,6 +796,43 @@ is_deeply(
"Resume from end"
);
# #############################################################################
# Customize bite and nibble statement comments.
# #############################################################################
$ni = make_nibble_iter(
db => 'sakila',
tbl => 'address',
argv => [qw(--tables sakila.address --chunk-size 10)],
comments => {
bite => "my bite",
nibble => "my nibble",
}
);
$ni->next();
is(
$ni->statements()->{nibble}->{Statement},
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code`, `phone`, `last_update` FROM `sakila`.`address` FORCE INDEX(`PRIMARY`) WHERE ((`address_id` >= ?)) AND ((`address_id` <= ?)) /*my nibble*/",
"Custom nibble comment"
);
$ni = make_nibble_iter(
db => 'sakila',
tbl => 'address',
argv => [qw(--tables sakila.address --chunk-size 1000)],
comments => {
bite => "my bite",
nibble => "my nibble",
}
);
$ni->next();
is(
$ni->statements()->{nibble}->{Statement},
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code`, `phone`, `last_update` FROM `sakila`.`address` /*my bite*/",
"Custom bite comment"
);
# #############################################################################
# Done.
# #############################################################################

View File

@@ -1,131 +0,0 @@
#!/usr/bin/perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use DSNParser;
use Sandbox;
use PerconaTest;
use Quoter;
use OSCCaptureSync;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Quotekeys = 0;
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) {
plan skip_all => 'Cannot connect to MySQL';
}
else {
plan tests => 10;
}
my $q = new Quoter();
my $osc = new OSCCaptureSync(Quoter => $q);
my $msg = sub { print "$_[0]\n"; };
my $output;
sub test_table {
my (%args) = @_;
my ($tbl, $col, $expect) = @args{qw(tbl col expect)};
$sb->load_file("master", "t/lib/samples/osc/$tbl");
PerconaTest::wait_for_table($dbh, "osc.t", "id=5");
$dbh->do("USE osc");
ok(
no_diff(
sub {
$osc->capture(
dbh => $dbh,
db => 'osc',
tbl => 't',
tmp_tbl => '__new_t',
columns => ['id', $col],
chunk_column => 'id',
msg => $msg,
)
},
"t/lib/samples/osc/$expect",
stderr => 1,
),
"$tbl: SQL statments to create triggers"
);
$dbh->do("insert into t values (6, 'f')");
$dbh->do("update t set `$col`='z' where id=1");
$dbh->do("delete from t where id=3");
my $rows = $dbh->selectall_arrayref("select id, `$col` from __new_t order by id");
is_deeply(
$rows,
[
[1, 'z'], # update t set c="z" where id=1
[6, 'f'], # insert into t values (6, "f")
],
"$tbl: Triggers work"
) or print Dumper($rows);
output(sub {
$osc->cleanup(
dbh => $dbh,
db => 'osc',
msg => $msg,
);
});
$rows = $dbh->selectall_arrayref("show triggers from `osc` like 't'");
is_deeply(
$rows,
[],
"$tbl: Cleanup removes the triggers"
);
}
test_table(
tbl => "tbl001.sql",
col => "c",
expect => "capsync001.txt",
);
test_table(
tbl => "tbl002.sql",
col => "default",
expect => "capsync002.txt",
);
test_table(
tbl => "tbl003.sql",
col => "space col",
expect => "capsync003.txt",
);
# #############################################################################
# Done.
# #############################################################################
{
local *STDERR;
open STDERR, '>', \$output;
$osc->_d('Complete test coverage');
}
like(
$output,
qr/Complete test coverage/,
'_d() works'
);
$sb->wipe_clean($dbh);
exit;

View File

@@ -191,7 +191,6 @@ $ni = make_nibble_iter(
argv => [qw(--databases test --chunk-size 8)],
);
$dbh->do("delete from test.t where c='a' or c='z'");
@rows = ();
@@ -204,8 +203,6 @@ is_deeply(
'a-z nibble 1 with oob'
) or print Dumper(\@rows);
$dbh->do("insert into test.t values ('a'), ('z')");
@rows = ();
for (1..8) {
push @rows, $ni->next();
@@ -226,6 +223,13 @@ is_deeply(
'a-z nibble 3 with oob'
) or print Dumper(\@rows);
# NibbleIterator is done (b-y), now insert a row on the low end (a),
# and one on the high end (z), past what NibbleIterator originally
# saw as the first and last boundaries. OobNibbleIterator should kick
# in and see a and z.
$dbh->do("insert into test.t values ('a'), ('z')");
# OobNibbleIterator checks the low end first.
@rows = ();
push @rows, $ni->next();
is_deeply(
@@ -234,6 +238,7 @@ is_deeply(
'a-z nibble 4 lower oob'
) or print Dumper(\@rows);
# Then it checks the high end.
@rows = ();
push @rows, $ni->next();
is_deeply(