mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-10-21 01:54:44 +00:00
Test and fix very small --chunk-time. Report immediately when a slave is stopped. Add short form -q for --quiet. Report very slow checksums once for each table. Use Cxn::name() instead of Cxn::dsn()->{n}; remove n from DSNParser; make cxn's name @@hostname by default, else stringified DSN parts.
This commit is contained in:
@@ -122,10 +122,6 @@ sub parse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$final_props{n} ) { # name
|
|
||||||
$final_props{n} = $self->as_string(\%final_props, [qw(h P S F)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return \%final_props;
|
return \%final_props;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1411,6 +1407,8 @@ use warnings FATAL => 'all';
|
|||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||||
|
|
||||||
|
use constant PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ( $class, %args ) = @_;
|
my ( $class, %args ) = @_;
|
||||||
my @required_args = qw(DSNParser OptionParser);
|
my @required_args = qw(DSNParser OptionParser);
|
||||||
@@ -1430,18 +1428,19 @@ sub new {
|
|||||||
}
|
}
|
||||||
elsif ( $prev_dsn ) {
|
elsif ( $prev_dsn ) {
|
||||||
$dsn = $dp->copy($prev_dsn, $dsn);
|
$dsn = $dp->copy($prev_dsn, $dsn);
|
||||||
$dsn->{n} = $dp->as_string($dsn, [qw(h P S F)]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $self = {
|
my $self = {
|
||||||
dsn => $dsn,
|
dsn => $dsn,
|
||||||
dbh => $args{dbh},
|
dbh => $args{dbh},
|
||||||
|
dsn_name => $dp->as_string($dsn, [qw(h P S)]),
|
||||||
|
hostname => '',
|
||||||
set => $args{set},
|
set => $args{set},
|
||||||
|
dbh_set => 0,
|
||||||
OptionParser => $o,
|
OptionParser => $o,
|
||||||
DSNParser => $dp,
|
DSNParser => $dp,
|
||||||
};
|
};
|
||||||
|
|
||||||
MKDEBUG && _d('New connection to', $dsn->{n});
|
|
||||||
return bless $self, $class;
|
return bless $self, $class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1457,10 +1456,9 @@ sub connect {
|
|||||||
$dsn->{p} = OptionParser::prompt_noecho("Enter MySQL password: ");
|
$dsn->{p} = OptionParser::prompt_noecho("Enter MySQL password: ");
|
||||||
$self->{asked_for_pass} = 1;
|
$self->{asked_for_pass} = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbh = $dp->get_dbh($dp->get_cxn_params($dsn), { AutoCommit => 1 });
|
$dbh = $dp->get_dbh($dp->get_cxn_params($dsn), { AutoCommit => 1 });
|
||||||
MKDEBUG && _d('Connected dbh', $dbh, $dsn->{n});
|
|
||||||
}
|
}
|
||||||
|
MKDEBUG && _d($dbh, 'Connected dbh to', $self->{name});
|
||||||
|
|
||||||
return $self->set_dbh($dbh);
|
return $self->set_dbh($dbh);
|
||||||
}
|
}
|
||||||
@@ -1468,15 +1466,29 @@ sub connect {
|
|||||||
sub set_dbh {
|
sub set_dbh {
|
||||||
my ($self, $dbh) = @_;
|
my ($self, $dbh) = @_;
|
||||||
|
|
||||||
return $dbh if $self->{dbh} && $self->{dbh} == $dbh;
|
if ( $self->{dbh} && $self->{dbh} == $dbh && $self->{dbh_set} ) {
|
||||||
|
MKDEBUG && _d($dbh, 'Already set dbh');
|
||||||
|
return $dbh;
|
||||||
|
}
|
||||||
|
|
||||||
|
MKDEBUG && _d($dbh, 'Setting dbh');
|
||||||
|
|
||||||
$dbh->{FetchHashKeyName} = 'NAME_lc';
|
$dbh->{FetchHashKeyName} = 'NAME_lc';
|
||||||
|
|
||||||
|
my $sql = 'SELECT @@hostname, @@server_id';
|
||||||
|
MKDEBUG && _d($dbh, $sql);
|
||||||
|
my ($hostname, $server_id) = $dbh->selectrow_array($sql);
|
||||||
|
MKDEBUG && _d($dbh, 'hostname:', $hostname, $server_id);
|
||||||
|
if ( $hostname ) {
|
||||||
|
$self->{hostname} = $hostname;
|
||||||
|
}
|
||||||
|
|
||||||
if ( my $set = $self->{set}) {
|
if ( my $set = $self->{set}) {
|
||||||
$set->($dbh);
|
$set->($dbh);
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{dbh} = $dbh;
|
$self->{dbh} = $dbh;
|
||||||
|
$self->{dbh_set} = 1;
|
||||||
return $dbh;
|
return $dbh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1490,10 +1502,16 @@ sub dsn {
|
|||||||
return $self->{dsn};
|
return $self->{dsn};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub name {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->{dsn_name} if PERCONA_TOOLKIT_TEST_USE_DSN_NAMES;
|
||||||
|
return $self->{hostname} || $self->{dsn_name} || 'unknown host';
|
||||||
|
}
|
||||||
|
|
||||||
sub DESTROY {
|
sub DESTROY {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
if ( $self->{dbh} ) {
|
if ( $self->{dbh} ) {
|
||||||
MKDEBUG && _d('Disconnecting dbh', $self->{dbh}, $self->{dsn}->{n});
|
MKDEBUG && _d('Disconnecting dbh', $self->{dbh}, $self->{name});
|
||||||
$self->{dbh}->disconnect();
|
$self->{dbh}->disconnect();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -5049,11 +5067,17 @@ sub start {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub update {
|
sub update {
|
||||||
my ( $self, $callback, $now ) = @_;
|
my ( $self, $callback, %args ) = @_;
|
||||||
my $jobsize = $self->{jobsize};
|
my $jobsize = $self->{jobsize};
|
||||||
$now ||= time();
|
my $now ||= $args{now} || time;
|
||||||
|
|
||||||
$self->{iterations}++; # How many updates have happened;
|
$self->{iterations}++; # How many updates have happened;
|
||||||
|
|
||||||
|
if ( !$self->{first_report} && $args{first_report} ) {
|
||||||
|
$args{first_report}->();
|
||||||
|
$self->{first_report} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ( $self->{report} eq 'time'
|
if ( $self->{report} eq 'time'
|
||||||
&& $self->{interval} > $now - $self->{last_reported}
|
&& $self->{interval} > $now - $self->{last_reported}
|
||||||
) {
|
) {
|
||||||
@@ -5165,10 +5189,11 @@ sub wait {
|
|||||||
|
|
||||||
my $worst; # most lagging slave
|
my $worst; # most lagging slave
|
||||||
my $pr_callback;
|
my $pr_callback;
|
||||||
|
my $pr_first_report;
|
||||||
if ( $pr ) {
|
if ( $pr ) {
|
||||||
$pr_callback = sub {
|
$pr_callback = sub {
|
||||||
my ($fraction, $elapsed, $remaining, $eta, $completed) = @_;
|
my ($fraction, $elapsed, $remaining, $eta, $completed) = @_;
|
||||||
my $dsn_name = $worst->{cxn}->dsn()->{n} || '?';
|
my $dsn_name = $worst->{cxn}->name();
|
||||||
if ( defined $worst->{lag} ) {
|
if ( defined $worst->{lag} ) {
|
||||||
print STDERR "Replica lag is " . ($worst->{lag} || '?')
|
print STDERR "Replica lag is " . ($worst->{lag} || '?')
|
||||||
. " seconds on $dsn_name. Waiting.\n";
|
. " seconds on $dsn_name. Waiting.\n";
|
||||||
@@ -5179,6 +5204,14 @@ sub wait {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
$pr->set_callback($pr_callback);
|
$pr->set_callback($pr_callback);
|
||||||
|
|
||||||
|
$pr_first_report = sub {
|
||||||
|
my $dsn_name = $worst->{cxn}->name();
|
||||||
|
if ( !defined $worst->{lag} ) {
|
||||||
|
print STDERR "Replica $dsn_name is stopped. Waiting.\n";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
my @lagged_slaves = map { {cxn=>$_, lag=>undef} } @$slaves;
|
my @lagged_slaves = map { {cxn=>$_, lag=>undef} } @$slaves;
|
||||||
@@ -5186,7 +5219,7 @@ sub wait {
|
|||||||
MKDEBUG && _d('Checking slave lag');
|
MKDEBUG && _d('Checking slave lag');
|
||||||
for my $i ( 0..$#lagged_slaves ) {
|
for my $i ( 0..$#lagged_slaves ) {
|
||||||
my $lag = $get_lag->($lagged_slaves[$i]->{cxn});
|
my $lag = $get_lag->($lagged_slaves[$i]->{cxn});
|
||||||
MKDEBUG && _d($lagged_slaves[$i]->{cxn}->dsn()->{n},
|
MKDEBUG && _d($lagged_slaves[$i]->{cxn}->name(),
|
||||||
'slave lag:', $lag);
|
'slave lag:', $lag);
|
||||||
if ( !defined $lag || $lag > $max_lag ) {
|
if ( !defined $lag || $lag > $max_lag ) {
|
||||||
$lagged_slaves[$i]->{lag} = $lag;
|
$lagged_slaves[$i]->{lag} = $lag;
|
||||||
@@ -5208,7 +5241,10 @@ sub wait {
|
|||||||
$worst->{lag}, 'on', Dumper($worst->{cxn}->dsn()));
|
$worst->{lag}, 'on', Dumper($worst->{cxn}->dsn()));
|
||||||
|
|
||||||
if ( $pr ) {
|
if ( $pr ) {
|
||||||
$pr->update(sub { return 0; });
|
$pr->update(
|
||||||
|
sub { return 0; },
|
||||||
|
first_report => $pr_first_report,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MKDEBUG && _d('Calling sleep callback');
|
MKDEBUG && _d('Calling sleep callback');
|
||||||
@@ -5462,11 +5498,12 @@ sub main {
|
|||||||
# is applied to every cxn.
|
# is applied to every cxn.
|
||||||
# TODO: maybe this stuff only needs to be set on master cxn?
|
# TODO: maybe this stuff only needs to be set on master cxn?
|
||||||
my $make_cxn = sub {
|
my $make_cxn = sub {
|
||||||
|
my (%args) = @_;
|
||||||
my $cxn = new Cxn(
|
my $cxn = new Cxn(
|
||||||
@_,
|
%args,
|
||||||
DSNParser => $dp,
|
DSNParser => $dp,
|
||||||
OptionParser => $o,
|
OptionParser => $o,
|
||||||
set => $set_on_connect,
|
set => $args{set_vars} ? $set_on_connect : undef,
|
||||||
);
|
);
|
||||||
eval { $cxn->connect() }; # connect or die trying
|
eval { $cxn->connect() }; # connect or die trying
|
||||||
if ( $EVAL_ERROR ) {
|
if ( $EVAL_ERROR ) {
|
||||||
@@ -5478,7 +5515,7 @@ sub main {
|
|||||||
# The dbh and dsn can be used before checksumming starts, but once
|
# The dbh and dsn can be used before checksumming starts, but once
|
||||||
# inside the main TABLE loop, only use the master cxn because its
|
# inside the main TABLE loop, only use the master cxn because its
|
||||||
# dbh may be recreated.
|
# dbh may be recreated.
|
||||||
my $master_cxn = $make_cxn->(dsn_string => shift @ARGV);
|
my $master_cxn = $make_cxn->(set_vars => 1, dsn_string => shift @ARGV);
|
||||||
my $master_dbh = $master_cxn->dbh(); # just for brevity
|
my $master_dbh = $master_cxn->dbh(); # just for brevity
|
||||||
my $master_dsn = $master_cxn->dsn(); # just for brevity
|
my $master_dsn = $master_cxn->dsn(); # just for brevity
|
||||||
|
|
||||||
@@ -5544,7 +5581,7 @@ sub main {
|
|||||||
repl_table => $repl_table,
|
repl_table => $repl_table,
|
||||||
);
|
);
|
||||||
MKDEBUG && _d(scalar @$diffs, 'checksum diffs on',
|
MKDEBUG && _d(scalar @$diffs, 'checksum diffs on',
|
||||||
$slave->dsn()->{n});
|
$slave->name());
|
||||||
if ( @$diffs ) {
|
if ( @$diffs ) {
|
||||||
$exit_status |= 1;
|
$exit_status |= 1;
|
||||||
if ( $o->get('quiet') < 2 ) {
|
if ( $o->get('quiet') < 2 ) {
|
||||||
@@ -5572,7 +5609,7 @@ sub main {
|
|||||||
);
|
);
|
||||||
if ( keys %$repl_filters ) {
|
if ( keys %$repl_filters ) {
|
||||||
push @all_repl_filters,
|
push @all_repl_filters,
|
||||||
{ name => $slave->dsn()->{n},
|
{ name => $slave->name(),
|
||||||
filters => $repl_filters,
|
filters => $repl_filters,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -5637,13 +5674,13 @@ sub main {
|
|||||||
my ($cxn) = @_;
|
my ($cxn) = @_;
|
||||||
my $dbh = $cxn->dbh();
|
my $dbh = $cxn->dbh();
|
||||||
if ( !$dbh || !$dbh->ping() ) {
|
if ( !$dbh || !$dbh->ping() ) {
|
||||||
MKDEBUG && _d('Lost connection to slave', $cxn->dsn()->{n},
|
MKDEBUG && _d('Lost connection to slave', $cxn->name(),
|
||||||
'while waiting for slave lag');
|
'while waiting for slave lag');
|
||||||
eval { $dbh = $cxn->connect() }; # connect or die trying
|
eval { $dbh = $cxn->connect() }; # connect or die trying
|
||||||
if ( $EVAL_ERROR ) {
|
if ( $EVAL_ERROR ) {
|
||||||
$oktorun = 0; # Fatal error
|
$oktorun = 0; # Fatal error
|
||||||
chomp $EVAL_ERROR;
|
chomp $EVAL_ERROR;
|
||||||
die "Lost connection to replica " . $cxn->dsn()->{n}
|
die "Lost connection to replica " . $cxn->name()
|
||||||
. " while attempting to get its lag ($EVAL_ERROR)";
|
. " while attempting to get its lag ($EVAL_ERROR)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5934,11 +5971,16 @@ sub main {
|
|||||||
if ( $o->get('chunk-time') ) {
|
if ( $o->get('chunk-time') ) {
|
||||||
$tbl->{chunk_size}
|
$tbl->{chunk_size}
|
||||||
= $tbl->{rate}->update($cnt, $tbl->{nibble_time});
|
= $tbl->{rate}->update($cnt, $tbl->{nibble_time});
|
||||||
|
|
||||||
if ( $tbl->{chunk_size} < 1 ) {
|
if ( $tbl->{chunk_size} < 1 ) {
|
||||||
# This shouldn't happen. WeightedAvgRate::update() may return
|
# This shouldn't happen. WeightedAvgRate::update() may return
|
||||||
# a value < 1, but minimum chunk size is 1.
|
# a value < 1, but minimum chunk size is 1.
|
||||||
if ( $o->get('quiet') < 2 ) {
|
$tbl->{chunk_size} = 1;
|
||||||
warn ts("Checksums are executing very slowly. "
|
|
||||||
|
# This warning is printed once per table.
|
||||||
|
if ( !$tbl->{warned_slow} && $o->get('quiet') < 2 ) {
|
||||||
|
warn ts("Checksum queries for table "
|
||||||
|
. "$tbl->{db}.$tbl->{tbl} are executing very slowly. "
|
||||||
. "--chunk-size has been automatically reduced to 1. "
|
. "--chunk-size has been automatically reduced to 1. "
|
||||||
. "Check that the server is not being overloaded, "
|
. "Check that the server is not being overloaded, "
|
||||||
. "or increase --chunk-time. The last chunk, number "
|
. "or increase --chunk-time. The last chunk, number "
|
||||||
@@ -5946,10 +5988,12 @@ sub main {
|
|||||||
. "selected $cnt rows and took "
|
. "selected $cnt rows and took "
|
||||||
. sprintf('%.3f', $tbl->{nibble_time})
|
. sprintf('%.3f', $tbl->{nibble_time})
|
||||||
. " seconds to execute.\n");
|
. " seconds to execute.\n");
|
||||||
|
$tbl->{warned_slow} = 1;
|
||||||
}
|
}
|
||||||
$tbl->{chunk_size} = 1;
|
|
||||||
}
|
}
|
||||||
$args{NibbleIterator}->set_chunk_size($tbl->{chunk_size});
|
|
||||||
|
# Update chunk-size based on rows/s checksum rate.
|
||||||
|
$nibble_iter->set_chunk_size($tbl->{chunk_size});
|
||||||
}
|
}
|
||||||
|
|
||||||
# Every table should have a Progress obj; update it.
|
# Every table should have a Progress obj; update it.
|
||||||
@@ -6010,7 +6054,7 @@ sub main {
|
|||||||
for my $i ( 0..$n_slaves ) {
|
for my $i ( 0..$n_slaves ) {
|
||||||
my $slave = $slaves->[$i];
|
my $slave = $slaves->[$i];
|
||||||
my ($chunk) = $slave->dbh()->selectrow_array($sql);
|
my ($chunk) = $slave->dbh()->selectrow_array($sql);
|
||||||
MKDEBUG && _d($slave->dsn()->{n}, 'max chunk:', $chunk);
|
MKDEBUG && _d($slave->name(), 'max chunk:', $chunk);
|
||||||
$chunks[$i] = $chunk || 0;
|
$chunks[$i] = $chunk || 0;
|
||||||
}
|
}
|
||||||
@chunks = sort { $a <=> $b } @chunks;
|
@chunks = sort { $a <=> $b } @chunks;
|
||||||
@@ -6034,7 +6078,7 @@ sub main {
|
|||||||
where => "db='$tbl->{db}' AND tbl='$tbl->{tbl}'",
|
where => "db='$tbl->{db}' AND tbl='$tbl->{tbl}'",
|
||||||
);
|
);
|
||||||
MKDEBUG && _d(scalar @$diffs, 'checksum diffs on',
|
MKDEBUG && _d(scalar @$diffs, 'checksum diffs on',
|
||||||
$slave->dsn()->{n});
|
$slave->name());
|
||||||
if ( @$diffs ) {
|
if ( @$diffs ) {
|
||||||
$tbl->{checksum_results}->{diffs} = scalar @$diffs;
|
$tbl->{checksum_results}->{diffs} = scalar @$diffs;
|
||||||
}
|
}
|
||||||
@@ -6087,10 +6131,12 @@ sub main {
|
|||||||
# then total rate will be zero, so use --chunk-size. Or, if
|
# then total rate will be zero, so use --chunk-size. Or, if
|
||||||
# --chunk-time=0, then only use --chunk-size for every table.
|
# --chunk-time=0, then only use --chunk-size for every table.
|
||||||
# Else, the initial chunk size is based on the total rates of
|
# Else, the initial chunk size is based on the total rates of
|
||||||
# rows/s from all previous tables.
|
# rows/s from all previous tables. If --chunk-time is really
|
||||||
|
# small, like 0.001, then Perl int() will probably round the
|
||||||
|
# chunk size to zero, which is invalid, so we default to 1.
|
||||||
my $chunk_time = $o->get('chunk-time');
|
my $chunk_time = $o->get('chunk-time');
|
||||||
my $chunk_size = $chunk_time && $total_rate
|
my $chunk_size = $chunk_time && $total_rate
|
||||||
? int($total_rate * $chunk_time)
|
? int($total_rate * $chunk_time) || 1
|
||||||
: $o->get('chunk-size');
|
: $o->get('chunk-size');
|
||||||
$tbl->{chunk_size} = $chunk_size;
|
$tbl->{chunk_size} = $chunk_size;
|
||||||
|
|
||||||
@@ -6400,7 +6446,7 @@ sub print_checksum_diffs {
|
|||||||
}
|
}
|
||||||
my ($cxn, $diffs) = @args{@required_args};
|
my ($cxn, $diffs) = @args{@required_args};
|
||||||
|
|
||||||
print "Differences on ", $cxn->dsn()->{n}, "\n";
|
print "Differences on ", $cxn->name(), "\n";
|
||||||
print join(' ', map { uc $_ } @headers), "\n";
|
print join(' ', map { uc $_ } @headers), "\n";
|
||||||
foreach my $diff ( @$diffs ) {
|
foreach my $diff ( @$diffs ) {
|
||||||
print join(' ', map { defined $_ ? $_ : '' } @{$diff}{@headers}), "\n";
|
print join(' ', map { defined $_ ? $_ : '' } @{$diff}{@headers}), "\n";
|
||||||
@@ -7189,7 +7235,7 @@ should be printed, in percentage, seconds, or number of iterations.
|
|||||||
|
|
||||||
=item --quiet
|
=item --quiet
|
||||||
|
|
||||||
cumulative: yes; default: 0
|
short form: -q; cumulative: yes; default: 0
|
||||||
|
|
||||||
Print only the most important information (disables L<"--progress">).
|
Print only the most important information (disables L<"--progress">).
|
||||||
|
|
||||||
|
57
lib/Cxn.pm
57
lib/Cxn.pm
@@ -37,6 +37,12 @@ use warnings FATAL => 'all';
|
|||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||||
|
|
||||||
|
# Hostnames make testing less accurate. Tests need to see
|
||||||
|
# that such-and-such happened on specific slave hosts, but
|
||||||
|
# the sandbox servers are all on one host so all slaves have
|
||||||
|
# the same hostname.
|
||||||
|
use constant PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0;
|
||||||
|
|
||||||
# Sub: new
|
# Sub: new
|
||||||
#
|
#
|
||||||
# Required Arguments:
|
# Required Arguments:
|
||||||
@@ -87,18 +93,19 @@ sub new {
|
|||||||
# copy values from it into this new DSN, resulting in a new DSN
|
# copy values from it into this new DSN, resulting in a new DSN
|
||||||
# with values from both sources.
|
# with values from both sources.
|
||||||
$dsn = $dp->copy($prev_dsn, $dsn);
|
$dsn = $dp->copy($prev_dsn, $dsn);
|
||||||
$dsn->{n} = $dp->as_string($dsn, [qw(h P S F)]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $self = {
|
my $self = {
|
||||||
dsn => $dsn,
|
dsn => $dsn,
|
||||||
dbh => $args{dbh},
|
dbh => $args{dbh},
|
||||||
|
dsn_name => $dp->as_string($dsn, [qw(h P S)]),
|
||||||
|
hostname => '',
|
||||||
set => $args{set},
|
set => $args{set},
|
||||||
|
dbh_set => 0,
|
||||||
OptionParser => $o,
|
OptionParser => $o,
|
||||||
DSNParser => $dp,
|
DSNParser => $dp,
|
||||||
};
|
};
|
||||||
|
|
||||||
MKDEBUG && _d('New connection to', $dsn->{n});
|
|
||||||
return bless $self, $class;
|
return bless $self, $class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +122,9 @@ sub connect {
|
|||||||
$dsn->{p} = OptionParser::prompt_noecho("Enter MySQL password: ");
|
$dsn->{p} = OptionParser::prompt_noecho("Enter MySQL password: ");
|
||||||
$self->{asked_for_pass} = 1;
|
$self->{asked_for_pass} = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbh = $dp->get_dbh($dp->get_cxn_params($dsn), { AutoCommit => 1 });
|
$dbh = $dp->get_dbh($dp->get_cxn_params($dsn), { AutoCommit => 1 });
|
||||||
MKDEBUG && _d('Connected dbh', $dbh, $dsn->{n});
|
|
||||||
}
|
}
|
||||||
|
MKDEBUG && _d($dbh, 'Connected dbh to', $self->{name});
|
||||||
|
|
||||||
return $self->set_dbh($dbh);
|
return $self->set_dbh($dbh);
|
||||||
}
|
}
|
||||||
@@ -126,34 +132,69 @@ sub connect {
|
|||||||
sub set_dbh {
|
sub set_dbh {
|
||||||
my ($self, $dbh) = @_;
|
my ($self, $dbh) = @_;
|
||||||
|
|
||||||
# Don't set stuff twice on the same dbh.
|
# If we already have a dbh, and that dbh is the same as this dbh,
|
||||||
return $dbh if $self->{dbh} && $self->{dbh} == $dbh;
|
# and the dbh has already been set, then do not re-set the same
|
||||||
|
# dbh. dbh_set is required so that if this obj was created with
|
||||||
|
# a dbh, we set that dbh when connect() is called because whoever
|
||||||
|
# created the dbh probably didn't set what we set here. For example,
|
||||||
|
# MasterSlave makes dbhs when finding slaves, but it doesn't set
|
||||||
|
# anything.
|
||||||
|
if ( $self->{dbh} && $self->{dbh} == $dbh && $self->{dbh_set} ) {
|
||||||
|
MKDEBUG && _d($dbh, 'Already set dbh');
|
||||||
|
return $dbh;
|
||||||
|
}
|
||||||
|
|
||||||
|
MKDEBUG && _d($dbh, 'Setting dbh');
|
||||||
|
|
||||||
# Set stuff for this dbh (i.e. initialize it).
|
# Set stuff for this dbh (i.e. initialize it).
|
||||||
$dbh->{FetchHashKeyName} = 'NAME_lc';
|
$dbh->{FetchHashKeyName} = 'NAME_lc';
|
||||||
|
|
||||||
|
# Update the cxn's name. Until we connect, the DSN parts
|
||||||
|
# h and P are used. Once connected, use @@hostname.
|
||||||
|
my $sql = 'SELECT @@hostname, @@server_id';
|
||||||
|
MKDEBUG && _d($dbh, $sql);
|
||||||
|
my ($hostname, $server_id) = $dbh->selectrow_array($sql);
|
||||||
|
MKDEBUG && _d($dbh, 'hostname:', $hostname, $server_id);
|
||||||
|
if ( $hostname ) {
|
||||||
|
$self->{hostname} = $hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the set callback to let the caller SET any MySQL variables.
|
||||||
if ( my $set = $self->{set}) {
|
if ( my $set = $self->{set}) {
|
||||||
$set->($dbh);
|
$set->($dbh);
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{dbh} = $dbh;
|
$self->{dbh} = $dbh;
|
||||||
|
$self->{dbh_set} = 1;
|
||||||
return $dbh;
|
return $dbh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Sub: dbh
|
||||||
|
# Return the cxn's dbh.
|
||||||
sub dbh {
|
sub dbh {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
return $self->{dbh};
|
return $self->{dbh};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Sub: dsn
|
||||||
|
# Return the cxn's dsn.
|
||||||
sub dsn {
|
sub dsn {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
return $self->{dsn};
|
return $self->{dsn};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Sub: name
|
||||||
|
# Return the cxn's name.
|
||||||
|
sub name {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->{dsn_name} if PERCONA_TOOLKIT_TEST_USE_DSN_NAMES;
|
||||||
|
return $self->{hostname} || $self->{dsn_name} || 'unknown host';
|
||||||
|
}
|
||||||
|
|
||||||
sub DESTROY {
|
sub DESTROY {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
if ( $self->{dbh} ) {
|
if ( $self->{dbh} ) {
|
||||||
MKDEBUG && _d('Disconnecting dbh', $self->{dbh}, $self->{dsn}->{n});
|
MKDEBUG && _d('Disconnecting dbh', $self->{dbh}, $self->{name});
|
||||||
$self->{dbh}->disconnect();
|
$self->{dbh}->disconnect();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@@ -170,10 +170,6 @@ sub parse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$final_props{n} ) { # name
|
|
||||||
$final_props{n} = $self->as_string(\%final_props, [qw(h P S F)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return \%final_props;
|
return \%final_props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -467,12 +467,17 @@ sub no_diff {
|
|||||||
die "I need a cmd argument" unless $cmd;
|
die "I need a cmd argument" unless $cmd;
|
||||||
die "I need an expected_output argument" unless $expected_output;
|
die "I need an expected_output argument" unless $expected_output;
|
||||||
|
|
||||||
|
die "$expected_output does not exist" unless -f "$trunk/$expected_output";
|
||||||
$expected_output = "$trunk/$expected_output";
|
$expected_output = "$trunk/$expected_output";
|
||||||
die "$expected_output does not exist" unless -f $expected_output;
|
|
||||||
|
|
||||||
my $tmp_file = '/tmp/percona-toolkit-test-output.txt';
|
my $tmp_file = '/tmp/percona-toolkit-test-output.txt';
|
||||||
my $tmp_file_orig = '/tmp/percona-toolkit-test-output-original.txt';
|
my $tmp_file_orig = '/tmp/percona-toolkit-test-output-original.txt';
|
||||||
|
|
||||||
|
if ( my $sed_args = $args{sed_out} ) {
|
||||||
|
`cat $expected_output | sed $sed_args > /tmp/pt-test-outfile-trf`;
|
||||||
|
$expected_output = "/tmp/pt-test-outfile-trf";
|
||||||
|
}
|
||||||
|
|
||||||
# Determine cmd type and run it.
|
# Determine cmd type and run it.
|
||||||
if ( ref $cmd eq 'CODE' ) {
|
if ( ref $cmd eq 'CODE' ) {
|
||||||
output($cmd, file => $tmp_file);
|
output($cmd, file => $tmp_file);
|
||||||
@@ -522,7 +527,7 @@ sub no_diff {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Remove our tmp files.
|
# Remove our tmp files.
|
||||||
`rm -f $tmp_file $tmp_file_orig`
|
`rm -f $tmp_file $tmp_file_orig /tmp/pt-test-outfile-trf >/dev/null 2>&1`
|
||||||
unless $ENV{KEEP_OUTPUT} || $args{keep_output};
|
unless $ENV{KEEP_OUTPUT} || $args{keep_output};
|
||||||
|
|
||||||
return !$retval;
|
return !$retval;
|
||||||
|
@@ -125,11 +125,21 @@ sub start {
|
|||||||
# many lines we're done processing -- a number between 0 and 800. You can also
|
# many lines we're done processing -- a number between 0 and 800. You can also
|
||||||
# optionally pass in the current time, but this is only for testing.
|
# optionally pass in the current time, but this is only for testing.
|
||||||
sub update {
|
sub update {
|
||||||
my ( $self, $callback, $now ) = @_;
|
my ( $self, $callback, %args ) = @_;
|
||||||
my $jobsize = $self->{jobsize};
|
my $jobsize = $self->{jobsize};
|
||||||
$now ||= time();
|
my $now ||= $args{now} || time;
|
||||||
|
|
||||||
$self->{iterations}++; # How many updates have happened;
|
$self->{iterations}++; # How many updates have happened;
|
||||||
|
|
||||||
|
# The caller may want to report something special before the actual
|
||||||
|
# first report ($callback) if, for example, they know that the wait
|
||||||
|
# could be long. This is called only once; subsequent reports will
|
||||||
|
# come from $callback after 30s, or whatever the interval is.
|
||||||
|
if ( !$self->{first_report} && $args{first_report} ) {
|
||||||
|
$args{first_report}->();
|
||||||
|
$self->{first_report} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
# Determine whether to just quit and return...
|
# Determine whether to just quit and return...
|
||||||
if ( $self->{report} eq 'time'
|
if ( $self->{report} eq 'time'
|
||||||
&& $self->{interval} > $now - $self->{last_reported}
|
&& $self->{interval} > $now - $self->{last_reported}
|
||||||
|
@@ -79,12 +79,13 @@ sub wait {
|
|||||||
|
|
||||||
my $worst; # most lagging slave
|
my $worst; # most lagging slave
|
||||||
my $pr_callback;
|
my $pr_callback;
|
||||||
|
my $pr_first_report;
|
||||||
if ( $pr ) {
|
if ( $pr ) {
|
||||||
# If you use the default Progress report callback, you'll need to
|
# If you use the default Progress report callback, you'll need to
|
||||||
# to add Transformers.pm to this tool.
|
# to add Transformers.pm to this tool.
|
||||||
$pr_callback = sub {
|
$pr_callback = sub {
|
||||||
my ($fraction, $elapsed, $remaining, $eta, $completed) = @_;
|
my ($fraction, $elapsed, $remaining, $eta, $completed) = @_;
|
||||||
my $dsn_name = $worst->{cxn}->dsn()->{n} || '?';
|
my $dsn_name = $worst->{cxn}->name();
|
||||||
if ( defined $worst->{lag} ) {
|
if ( defined $worst->{lag} ) {
|
||||||
print STDERR "Replica lag is " . ($worst->{lag} || '?')
|
print STDERR "Replica lag is " . ($worst->{lag} || '?')
|
||||||
. " seconds on $dsn_name. Waiting.\n";
|
. " seconds on $dsn_name. Waiting.\n";
|
||||||
@@ -95,6 +96,17 @@ sub wait {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
$pr->set_callback($pr_callback);
|
$pr->set_callback($pr_callback);
|
||||||
|
|
||||||
|
# If a replic is stopped, don't wait 30s (or whatever interval)
|
||||||
|
# to report this. Instead, report it once, immediately, then
|
||||||
|
# keep reporting it every interval.
|
||||||
|
$pr_first_report = sub {
|
||||||
|
my $dsn_name = $worst->{cxn}->name();
|
||||||
|
if ( !defined $worst->{lag} ) {
|
||||||
|
print STDERR "Replica $dsn_name is stopped. Waiting.\n";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
# First check all slaves.
|
# First check all slaves.
|
||||||
@@ -103,7 +115,7 @@ sub wait {
|
|||||||
MKDEBUG && _d('Checking slave lag');
|
MKDEBUG && _d('Checking slave lag');
|
||||||
for my $i ( 0..$#lagged_slaves ) {
|
for my $i ( 0..$#lagged_slaves ) {
|
||||||
my $lag = $get_lag->($lagged_slaves[$i]->{cxn});
|
my $lag = $get_lag->($lagged_slaves[$i]->{cxn});
|
||||||
MKDEBUG && _d($lagged_slaves[$i]->{cxn}->dsn()->{n},
|
MKDEBUG && _d($lagged_slaves[$i]->{cxn}->name(),
|
||||||
'slave lag:', $lag);
|
'slave lag:', $lag);
|
||||||
if ( !defined $lag || $lag > $max_lag ) {
|
if ( !defined $lag || $lag > $max_lag ) {
|
||||||
$lagged_slaves[$i]->{lag} = $lag;
|
$lagged_slaves[$i]->{lag} = $lag;
|
||||||
@@ -131,7 +143,10 @@ sub wait {
|
|||||||
# it will take all slaves to catch up. The progress reports
|
# it will take all slaves to catch up. The progress reports
|
||||||
# are just to inform the user every 30s which slave is still
|
# are just to inform the user every 30s which slave is still
|
||||||
# lagging this most.
|
# lagging this most.
|
||||||
$pr->update(sub { return 0; });
|
$pr->update(
|
||||||
|
sub { return 0; },
|
||||||
|
first_report => $pr_first_report,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MKDEBUG && _d('Calling sleep callback');
|
MKDEBUG && _d('Calling sleep callback');
|
||||||
|
16
t/lib/Cxn.t
16
t/lib/Cxn.t
@@ -97,6 +97,12 @@ ok(
|
|||||||
"New Cxn, dbh not connected yet"
|
"New Cxn, dbh not connected yet"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
$cxn->name(),
|
||||||
|
'h=127.1,P=12345',
|
||||||
|
'name() uses DSN if not connected'
|
||||||
|
);
|
||||||
|
|
||||||
$cxn->connect();
|
$cxn->connect();
|
||||||
ok(
|
ok(
|
||||||
$cxn->dbh()->ping(),
|
$cxn->dbh()->ping(),
|
||||||
@@ -193,11 +199,17 @@ is_deeply(
|
|||||||
S => undef,
|
S => undef,
|
||||||
D => undef,
|
D => undef,
|
||||||
t => undef,
|
t => undef,
|
||||||
n => 'h=127.1,P=12345',
|
|
||||||
},
|
},
|
||||||
"cxn->dsn()"
|
"cxn->dsn()"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
my ($hostname) = $master_dbh->selectrow_array('select @@hostname');
|
||||||
|
is(
|
||||||
|
$cxn->name(),
|
||||||
|
$hostname,
|
||||||
|
'name() uses @@hostname'
|
||||||
|
);
|
||||||
|
exit;
|
||||||
# ############################################################################
|
# ############################################################################
|
||||||
# Default cxn, should be equivalent to 'h=localhost'.
|
# Default cxn, should be equivalent to 'h=localhost'.
|
||||||
# ############################################################################
|
# ############################################################################
|
||||||
@@ -214,7 +226,6 @@ is_deeply(
|
|||||||
S => undef,
|
S => undef,
|
||||||
D => undef,
|
D => undef,
|
||||||
t => undef,
|
t => undef,
|
||||||
n => 'h=localhost',
|
|
||||||
},
|
},
|
||||||
"Defaults to h=localhost"
|
"Defaults to h=localhost"
|
||||||
);
|
);
|
||||||
@@ -234,7 +245,6 @@ is_deeply(
|
|||||||
S => undef,
|
S => undef,
|
||||||
D => undef,
|
D => undef,
|
||||||
t => undef,
|
t => undef,
|
||||||
n => 'h=localhost,P=12345',
|
|
||||||
},
|
},
|
||||||
"Default cxn inherits default connection options"
|
"Default cxn inherits default connection options"
|
||||||
);
|
);
|
||||||
|
@@ -137,7 +137,7 @@ is (
|
|||||||
|
|
||||||
is (
|
is (
|
||||||
$dp->as_string({ h=>'localhost', P=>'3306',p=>'omg'}, [qw(h P)]),
|
$dp->as_string({ h=>'localhost', P=>'3306',p=>'omg'}, [qw(h P)]),
|
||||||
'P=3306,h=localhost',
|
'h=localhost,P=3306',
|
||||||
'DSN stringifies only requested parts'
|
'DSN stringifies only requested parts'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ BEGIN {
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings FATAL => 'all';
|
use warnings FATAL => 'all';
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use Test::More tests => 29;
|
use Test::More tests => 31;
|
||||||
|
|
||||||
use Transformers;
|
use Transformers;
|
||||||
use Progress;
|
use Progress;
|
||||||
@@ -153,7 +153,7 @@ $pr->set_callback(
|
|||||||
$callbacks_called++;
|
$callbacks_called++;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$pr->update(sub{return 60}, 35);
|
$pr->update(sub{return 60}, now => 35);
|
||||||
is_deeply(
|
is_deeply(
|
||||||
$completion_arr,
|
$completion_arr,
|
||||||
[.1, 25, 225, 260, 60 ],
|
[.1, 25, 225, 260, 60 ],
|
||||||
@@ -175,7 +175,7 @@ eval {
|
|||||||
interval => 10, # Every ten seconds
|
interval => 10, # Every ten seconds
|
||||||
);
|
);
|
||||||
$pr->start(10); # Current time is 10 seconds.
|
$pr->start(10); # Current time is 10 seconds.
|
||||||
$pr->update(sub{return 60}, 35);
|
$pr->update(sub{return 60}, now => 35);
|
||||||
is($buffer, "Progress: 10% 03:45 remain\n",
|
is($buffer, "Progress: 10% 03:45 remain\n",
|
||||||
'Tested the default callback');
|
'Tested the default callback');
|
||||||
};
|
};
|
||||||
@@ -193,12 +193,57 @@ eval {
|
|||||||
start => 10, # Current time is 10 seconds, alternate interface
|
start => 10, # Current time is 10 seconds, alternate interface
|
||||||
);
|
);
|
||||||
is($pr->{start}, 10, 'Custom start time param works');
|
is($pr->{start}, 10, 'Custom start time param works');
|
||||||
$pr->update(sub{return 60}, 35);
|
$pr->update(sub{return 60}, now => 35);
|
||||||
is($buffer, "custom name: 10% 03:45 remain\n",
|
is($buffer, "custom name: 10% 03:45 remain\n",
|
||||||
'Tested the default callback with custom name');
|
'Tested the default callback with custom name');
|
||||||
};
|
};
|
||||||
is ($EVAL_ERROR, '', "No error in default callback with custom name");
|
is ($EVAL_ERROR, '', "No error in default callback with custom name");
|
||||||
|
|
||||||
|
# ############################################################################
|
||||||
|
# Do a "first report" before the normal interval reports.
|
||||||
|
# ############################################################################
|
||||||
|
$pr = new Progress(
|
||||||
|
jobsize => 600,
|
||||||
|
report => 'time',
|
||||||
|
interval => 10, # Every ten seconds
|
||||||
|
);
|
||||||
|
$pr->start(2); # Current time is 2 seconds.
|
||||||
|
$callbacks_called = 0;
|
||||||
|
my $first_report_called = 0;
|
||||||
|
$pr->set_callback(
|
||||||
|
sub {
|
||||||
|
$completion_arr = [ @_ ];
|
||||||
|
$callbacks_called++;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$pr->update(
|
||||||
|
sub { return 60 },
|
||||||
|
now => 5,
|
||||||
|
first_report => sub { $first_report_called++ }
|
||||||
|
);
|
||||||
|
$pr->update(
|
||||||
|
sub { return 70 },
|
||||||
|
now => 16,
|
||||||
|
first_report => sub { $first_report_called++ }
|
||||||
|
);
|
||||||
|
$pr->update(
|
||||||
|
sub { return 100 },
|
||||||
|
now => 27,
|
||||||
|
first_report => sub { $first_report_called++ }
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
$first_report_called,
|
||||||
|
1,
|
||||||
|
"Called first_report ocne"
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
$callbacks_called,
|
||||||
|
2,
|
||||||
|
"Called interval report twice"
|
||||||
|
);
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Done.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
@@ -12,6 +12,8 @@ use English qw(-no_match_vars);
|
|||||||
use Test::More tests => 7;
|
use Test::More tests => 7;
|
||||||
|
|
||||||
use ReplicaLagWaiter;
|
use ReplicaLagWaiter;
|
||||||
|
use OptionParser;
|
||||||
|
use DSNParser;
|
||||||
use Cxn;
|
use Cxn;
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
|
|
||||||
@@ -38,8 +40,14 @@ sub sleep {
|
|||||||
sleep $t;
|
sleep $t;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $r1 = new Cxn(dsn=>{n=>'slave1'}, dbh=>1, DSNParser=>1, OptionParser=>1);
|
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||||
my $r2 = new Cxn(dsn=>{n=>'slave2'}, dbh=>2, DSNParser=>1, OptionParser=>1);
|
my $o = new OptionParser(description => 'Cxn');
|
||||||
|
$o->get_specs("$trunk/bin/pt-table-checksum");
|
||||||
|
$o->get_opts();
|
||||||
|
$dp->prop('set-vars', $o->get('set-vars'));
|
||||||
|
|
||||||
|
my $r1 = new Cxn(dsn=>{n=>'slave1'}, dbh=>1, DSNParser=>$dp, OptionParser=>$o);
|
||||||
|
my $r2 = new Cxn(dsn=>{n=>'slave2'}, dbh=>2, DSNParser=>$dp, OptionParser=>$o);
|
||||||
|
|
||||||
my $rll = new ReplicaLagWaiter(
|
my $rll = new ReplicaLagWaiter(
|
||||||
oktorun => \&oktorun,
|
oktorun => \&oktorun,
|
||||||
|
@@ -11,6 +11,12 @@ use warnings FATAL => 'all';
|
|||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use Test::More;
|
use Test::More;
|
||||||
|
|
||||||
|
# Hostnames make testing less accurate. Tests need to see
|
||||||
|
# that such-and-such happened on specific slave hosts, but
|
||||||
|
# the sandbox servers are all on one host so all slaves have
|
||||||
|
# the same hostname.
|
||||||
|
$ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1;
|
||||||
|
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
use Sandbox;
|
use Sandbox;
|
||||||
@@ -194,5 +200,5 @@ ok(
|
|||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Done.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
#$sb->wipe_clean($master_dbh);
|
$sb->wipe_clean($master_dbh);
|
||||||
exit;
|
exit;
|
||||||
|
@@ -23,7 +23,7 @@ if ( !$master_dbh ) {
|
|||||||
plan skip_all => 'Cannot connect to sandbox master';
|
plan skip_all => 'Cannot connect to sandbox master';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
plan tests => 4;
|
plan tests => 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
|
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
|
||||||
@@ -84,6 +84,23 @@ is_deeply(
|
|||||||
"--chunk-time=0 disables auto-adjusting --chunk-size"
|
"--chunk-time=0 disables auto-adjusting --chunk-size"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
# ############################################################################
|
||||||
|
# Sub-second chunk-time.
|
||||||
|
# ############################################################################
|
||||||
|
|
||||||
|
$output = output(
|
||||||
|
sub { pt_table_checksum::main(@args,
|
||||||
|
qw(--quiet --chunk-time .001 -d mysql)) },
|
||||||
|
stderr => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
unlike(
|
||||||
|
$output,
|
||||||
|
qr/Cannot checksum table/,
|
||||||
|
"Very small --chunk-time doesn't cause zero --chunk-size"
|
||||||
|
);
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Done.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
@@ -11,6 +11,12 @@ use warnings FATAL => 'all';
|
|||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use Test::More;
|
use Test::More;
|
||||||
|
|
||||||
|
# Hostnames make testing less accurate. Tests need to see
|
||||||
|
# that such-and-such happened on specific slave hosts, but
|
||||||
|
# the sandbox servers are all on one host so all slaves have
|
||||||
|
# the same hostname.
|
||||||
|
$ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1;
|
||||||
|
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
use Sandbox;
|
use Sandbox;
|
||||||
require "$trunk/bin/pt-table-checksum";
|
require "$trunk/bin/pt-table-checksum";
|
||||||
|
@@ -11,6 +11,12 @@ use warnings FATAL => 'all';
|
|||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use Test::More;
|
use Test::More;
|
||||||
|
|
||||||
|
# Hostnames make testing less accurate. Tests need to see
|
||||||
|
# that such-and-such happened on specific slave hosts, but
|
||||||
|
# the sandbox servers are all on one host so all slaves have
|
||||||
|
# the same hostname.
|
||||||
|
$ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1;
|
||||||
|
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
use Sandbox;
|
use Sandbox;
|
||||||
require "$trunk/bin/pt-table-checksum";
|
require "$trunk/bin/pt-table-checksum";
|
||||||
|
Reference in New Issue
Block a user