mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-03 19:15:54 +00:00
Rewrite how MasterSlave handles --recursion-methods.
This commit is contained in:
115
bin/pt-archiver
115
bin/pt-archiver
@@ -3078,8 +3078,31 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
if ( @$methods != 1 ) {
|
||||
if ( grep({ !m/processlist|hosts/i } @$methods)
|
||||
&& $methods->[0] !~ /^dsn=/i )
|
||||
{
|
||||
die "Invalid combination of recursion methods: "
|
||||
. join(", ", map { defined($_) ? $_ : 'undef' } @$methods) . ". "
|
||||
. "Only hosts and processlist may be combined.\n"
|
||||
}
|
||||
}
|
||||
else {
|
||||
my ($method) = @$methods;
|
||||
die "Invalid recursion method: " . ( $method || 'undef' )
|
||||
unless $method && $method =~ m/^(?:processlist$|hosts$|none$|dsn=)/i;
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
@@ -3089,28 +3112,27 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
callback => sub {
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
@@ -3120,31 +3142,48 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/none/i ) {
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Invalid --recursion-method: $method. Valid values are: "
|
||||
. "dsn=DSN, hosts, or processlist.\n";
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -3179,11 +3218,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -3195,25 +3234,14 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = qw(processlist hosts);
|
||||
if ( $method ) {
|
||||
@methods = grep { $_ ne $method } @methods;
|
||||
unshift @methods, $method;
|
||||
}
|
||||
else {
|
||||
if ( ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
@methods = qw(hosts);
|
||||
}
|
||||
}
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -3716,13 +3744,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -4070,7 +4101,11 @@ sub main {
|
||||
my $dsn_defaults = $dp->parse_options($o);
|
||||
my $dsn = $dp->parse($o->get('check-slave-lag'), $dsn_defaults);
|
||||
$lag_dbh = $dp->get_dbh($dp->get_cxn_params($dsn), { AutoCommit => 1 });
|
||||
$ms = new MasterSlave();
|
||||
$ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
}
|
||||
|
||||
# ########################################################################
|
||||
|
183
bin/pt-heartbeat
183
bin/pt-heartbeat
@@ -24,66 +24,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
@@ -103,13 +43,93 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -144,11 +164,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -162,14 +182,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -180,15 +198,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
return @$methods if $methods && @$methods;
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -681,13 +690,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -3431,7 +3443,11 @@ sub main {
|
||||
my $master_server_id = $o->get('master-server-id');
|
||||
if ( !$master_server_id ) {
|
||||
eval {
|
||||
my $ms = new MasterSlave();
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
my $master_dsn = $ms->get_master_dsn($dbh, $dsn, $dp)
|
||||
or die "This server is not a slave";
|
||||
my $master_dbh = $dp->get_dbh($dp->get_cxn_params($master_dsn),
|
||||
@@ -3762,17 +3778,12 @@ sub check_delay {
|
||||
$ms->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse'),
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level ) = @_;
|
||||
push @dbhs, $dbh;
|
||||
PTDEBUG && _d("Found slave", $dp->as_string($dsn));
|
||||
push @sths, [ $dsn, $dbh->prepare($sql) ];
|
||||
},
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
121
bin/pt-kill
121
bin/pt-kill
@@ -3345,8 +3345,31 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
if ( @$methods != 1 ) {
|
||||
if ( grep({ !m/processlist|hosts/i } @$methods)
|
||||
&& $methods->[0] !~ /^dsn=/i )
|
||||
{
|
||||
die "Invalid combination of recursion methods: "
|
||||
. join(", ", map { defined($_) ? $_ : 'undef' } @$methods) . ". "
|
||||
. "Only hosts and processlist may be combined.\n"
|
||||
}
|
||||
}
|
||||
else {
|
||||
my ($method) = @$methods;
|
||||
die "Invalid recursion method: " . ( $method || 'undef' )
|
||||
unless $method && $method =~ m/^(?:processlist$|hosts$|none$|dsn=)/i;
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
@@ -3356,28 +3379,27 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
callback => sub {
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
@@ -3387,31 +3409,48 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/none/i ) {
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Invalid --recursion-method: $method. Valid values are: "
|
||||
. "dsn=DSN, hosts, or processlist.\n";
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -3446,11 +3485,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -3462,25 +3501,14 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = qw(processlist hosts);
|
||||
if ( $method ) {
|
||||
@methods = grep { $_ ne $method } @methods;
|
||||
unshift @methods, $method;
|
||||
}
|
||||
else {
|
||||
if ( ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
@methods = qw(hosts);
|
||||
}
|
||||
}
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -3983,13 +4011,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -4802,10 +4833,6 @@ my $o;
|
||||
sub main {
|
||||
@ARGV = @_; # set global ARGV for this package
|
||||
|
||||
my $ms = new MasterSlave();
|
||||
my $pl = new Processlist(MasterSlave => $ms);
|
||||
my $qr = new QueryRewriter();
|
||||
|
||||
# ########################################################################
|
||||
# Get configuration information.
|
||||
# ########################################################################
|
||||
@@ -4880,6 +4907,14 @@ sub main {
|
||||
# ########################################################################
|
||||
# Make input sub that will either get processlist from MySQL or a file.
|
||||
# ########################################################################
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => "Quoter",
|
||||
);
|
||||
my $pl = new Processlist(MasterSlave => $ms);
|
||||
my $qr = new QueryRewriter();
|
||||
|
||||
my $cxn;
|
||||
my $dbh; # $cxn->dbh
|
||||
my $get_proclist; # callback to SHOW PROCESSLIST
|
||||
|
@@ -3452,66 +3452,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
@@ -3531,13 +3471,93 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -3572,11 +3592,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -3590,14 +3610,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -3608,15 +3626,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
return @$methods if $methods && @$methods;
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -4109,13 +4118,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -6033,16 +6045,15 @@ sub main {
|
||||
# #####################################################################
|
||||
# Find and connect to slaves.
|
||||
# #####################################################################
|
||||
my $ms = new MasterSlave();
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
|
||||
$slaves = $ms->get_slaves(
|
||||
dbh => $cxn->dbh(),
|
||||
dsn => $cxn->dsn(),
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
make_cxn => sub {
|
||||
return $make_cxn->(@_, prev_dsn => $cxn->dsn());
|
||||
},
|
||||
|
@@ -10339,8 +10339,31 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
if ( @$methods != 1 ) {
|
||||
if ( grep({ !m/processlist|hosts/i } @$methods)
|
||||
&& $methods->[0] !~ /^dsn=/i )
|
||||
{
|
||||
die "Invalid combination of recursion methods: "
|
||||
. join(", ", map { defined($_) ? $_ : 'undef' } @$methods) . ". "
|
||||
. "Only hosts and processlist may be combined.\n"
|
||||
}
|
||||
}
|
||||
else {
|
||||
my ($method) = @$methods;
|
||||
die "Invalid recursion method: " . ( $method || 'undef' )
|
||||
unless $method && $method =~ m/^(?:processlist$|hosts$|none$|dsn=)/i;
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
@@ -10350,28 +10373,27 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
callback => sub {
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
@@ -10381,31 +10403,48 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/none/i ) {
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Invalid --recursion-method: $method. Valid values are: "
|
||||
. "dsn=DSN, hosts, or processlist.\n";
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -10440,11 +10479,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -10456,25 +10495,14 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = qw(processlist hosts);
|
||||
if ( $method ) {
|
||||
@methods = grep { $_ ne $method } @methods;
|
||||
unshift @methods, $method;
|
||||
}
|
||||
else {
|
||||
if ( ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
@methods = qw(hosts);
|
||||
}
|
||||
}
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -10977,13 +11005,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -12195,7 +12226,11 @@ sub main {
|
||||
{ # event
|
||||
my $misc;
|
||||
if ( my $ps_dsn = $o->get('processlist') ) {
|
||||
my $ms = new MasterSlave();
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
my $pl = new Processlist(
|
||||
interval => $o->get('interval') * 1_000_000,
|
||||
MasterSlave => $ms
|
||||
|
@@ -1872,66 +1872,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
@@ -1951,13 +1891,93 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -1992,11 +2012,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -2010,14 +2030,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -2028,15 +2046,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
return @$methods if $methods && @$methods;
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -2529,13 +2538,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -3383,16 +3395,15 @@ sub main {
|
||||
|
||||
# Despite the name, recursing to slaves actually begins at the specified
|
||||
# server, so the named server may also be included.
|
||||
my $ms = new MasterSlave();
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
$ms->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $master_dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse'),
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
callback => sub {
|
||||
{ dbh => $dbh,
|
||||
dsn => $master_dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
if ( !$parent ) {
|
||||
$root = $dsn;
|
||||
|
@@ -2185,66 +2185,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
@@ -2264,13 +2204,93 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -2305,11 +2325,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -2323,14 +2343,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -2341,15 +2359,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
return @$methods if $methods && @$methods;
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -2842,13 +2851,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -3206,13 +3218,15 @@ sub main {
|
||||
|
||||
# Despite the name, recursing to slaves actually begins at the specified
|
||||
# server, so the named server may also be watched, if it's a slave.
|
||||
my $ms = new MasterSlave();
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
$ms->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse') || 0,
|
||||
callback => sub {
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level ) = @_;
|
||||
# Test whether we want to watch this server.
|
||||
eval {
|
||||
@@ -3234,9 +3248,6 @@ sub main {
|
||||
my ( $dsn, $dbh, $level ) = @_;
|
||||
print STDERR "Skipping ", $dp->as_string($dsn), "\n";
|
||||
},
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
}
|
||||
);
|
||||
|
||||
|
@@ -3036,66 +3036,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
@@ -3115,13 +3055,93 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -3156,11 +3176,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -3174,14 +3194,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -3192,15 +3210,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
return @$methods if $methods && @$methods;
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -3693,13 +3702,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -7038,7 +7050,11 @@ sub main {
|
||||
my $q = new Quoter();
|
||||
my $tp = new TableParser(Quoter => $q);
|
||||
my $rc = new RowChecksum(Quoter=> $q, OptionParser => $o);
|
||||
my $ms = new MasterSlave();
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
|
||||
my $slaves; # all slaves (that we can find)
|
||||
my $slave_lag_cxns; # slaves whose lag we'll check
|
||||
@@ -7058,15 +7074,9 @@ sub main {
|
||||
# Find and connect to slaves.
|
||||
# #####################################################################
|
||||
$slaves = $ms->get_slaves(
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
make_cxn => sub {
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
make_cxn => sub {
|
||||
return $make_cxn->(@_, prev_dsn => $master_cxn->dsn());
|
||||
},
|
||||
);
|
||||
|
@@ -6456,66 +6456,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub check_recursion_method {
|
||||
my ($methods) = @_;
|
||||
|
||||
@@ -6535,13 +6475,93 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -6576,11 +6596,11 @@ sub recurse_to_slaves {
|
||||
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -6594,14 +6614,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -6612,15 +6630,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
return @$methods if $methods && @$methods;
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -7113,13 +7122,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
@@ -8764,11 +8776,10 @@ sub sync_via_replication {
|
||||
# then sync them.
|
||||
else {
|
||||
$ms->recurse_to_slaves(
|
||||
{ dbh => $src->{dbh},
|
||||
dsn => $src->{dsn},
|
||||
dsn_parser => $dp,
|
||||
recurse => 1,
|
||||
callback => sub {
|
||||
{ dbh => $src->{dbh},
|
||||
dsn => $src->{dsn},
|
||||
recurse => 1,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
my $all_diffs = $checksum->find_replication_differences(
|
||||
$dbh, $o->get('replicate'));
|
||||
@@ -8837,9 +8848,6 @@ sub sync_via_replication {
|
||||
|
||||
return;
|
||||
}, # recurse_to_slaves() callback
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
},
|
||||
);
|
||||
} # DSN is master
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
@@ -27,67 +27,6 @@ use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
# exists because recurse can be undef
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
|
||||
PTDEBUG && _d('Slave recursion method:', $methods);
|
||||
if ( !@$methods || grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( @$methods && $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( !@$methods || $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
# Sub: check_recursion_method
|
||||
# Check that the arrayref of recursion methods passed in is valid
|
||||
sub check_recursion_method {
|
||||
@@ -109,6 +48,86 @@ sub check_recursion_method {
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
%args,
|
||||
replication_thread => {},
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($make_cxn) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $dp = $self->{DSNParser};
|
||||
my $methods = $self->_resolve_recursion_methods($args{dsn});
|
||||
|
||||
if ( grep { m/processlist|hosts/i } @$methods ) {
|
||||
my @required_args = qw(dbh dsn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $dsn) = @args{@required_args};
|
||||
|
||||
$self->recurse_to_slaves(
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
PTDEBUG && _d('Found slave:', $dp->as_string($dsn));
|
||||
push @$slaves, $make_cxn->(dsn => $dsn, dbh => $dbh);
|
||||
return;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/^dsn=/i ) {
|
||||
(my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i;
|
||||
$slaves = $self->get_cxn_from_dsn_table(
|
||||
%args,
|
||||
dsn_table_dsn => $dsn_table_dsn,
|
||||
);
|
||||
}
|
||||
elsif ( $methods->[0] =~ m/none/i ) {
|
||||
PTDEBUG && _d('Not getting to slaves');
|
||||
}
|
||||
else {
|
||||
die "Unexpected recursion methods: @$methods";
|
||||
}
|
||||
|
||||
return $slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $dsn) = @_;
|
||||
my $o = $self->{OptionParser};
|
||||
if ( $o->got('recursion-method') ) {
|
||||
# Use whatever the user explicitly gave on the command line.
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
elsif ( $dsn && ($dsn->{P} || 3306) != 3306 ) {
|
||||
# Special case: hosts is best when port is non-standard.
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return [qw(hosts)];
|
||||
}
|
||||
else {
|
||||
# Use the option's default.
|
||||
return $o->get('recursion-method');
|
||||
}
|
||||
}
|
||||
|
||||
# Sub: recurse_to_slaves
|
||||
# Descend to slaves by examining SHOW SLAVE HOSTS.
|
||||
# The callback gets the slave's DSN, dbh, parent, and the recursion level
|
||||
@@ -132,10 +151,16 @@ sub check_recursion_method {
|
||||
sub recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
my $dp = $self->{DSNParser};
|
||||
my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse');
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
# Re-resolve the recursion methods for each slave. In most cases
|
||||
# it won't change, but it could if one slave uses standard port (3306)
|
||||
# and another does not.
|
||||
my $methods = $self->_resolve_recursion_methods($dsn);
|
||||
PTDEBUG && _d('Recursion methods:', @$methods);
|
||||
if ( lc($methods->[0]) eq 'none' ) {
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/987694
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
@@ -175,13 +200,13 @@ sub recurse_to_slaves {
|
||||
# Call the callback!
|
||||
$args->{callback}->($dsn, $dbh, $level, $args->{parent});
|
||||
|
||||
if ( !defined $args->{recurse} || $level < $args->{recurse} ) {
|
||||
if ( !defined $recurse || $level < $recurse ) {
|
||||
|
||||
# Find the slave hosts. Eliminate hosts that aren't slaves of me (as
|
||||
# revealed by server_id and master_id).
|
||||
my @slaves =
|
||||
grep { !$_->{master_id} || $_->{master_id} == $id } # Only my slaves.
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $args->{method});
|
||||
$self->find_slave_hosts($dp, $dbh, $dsn, $methods);
|
||||
|
||||
foreach my $slave ( @slaves ) {
|
||||
PTDEBUG && _d('Recursing from',
|
||||
@@ -207,14 +232,12 @@ sub recurse_to_slaves {
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn),
|
||||
'using methods', @methods);
|
||||
'using methods', @$methods);
|
||||
|
||||
my @slaves;
|
||||
METHOD:
|
||||
foreach my $method ( @methods ) {
|
||||
foreach my $method ( @$methods ) {
|
||||
my $find_slaves = "_find_slaves_by_$method";
|
||||
PTDEBUG && _d('Finding slaves with', $find_slaves);
|
||||
@slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn);
|
||||
@@ -225,18 +248,6 @@ sub find_slave_hosts {
|
||||
return @slaves;
|
||||
}
|
||||
|
||||
sub _resolve_recursion_methods {
|
||||
my ($self, $methods, $dsn) = @_;
|
||||
|
||||
# If an explicit recursion method was specified, use that
|
||||
return @$methods if $methods && @$methods;
|
||||
# Otherwise, if we're on the standard port, default to processlist and hosts
|
||||
return qw( processlist hosts ) if (($dsn->{P} || 3306) == 3306);
|
||||
# Or if on a non-standard port, default to hosts.
|
||||
PTDEBUG && _d('Port number is non-standard; using only hosts method');
|
||||
return qw( hosts );
|
||||
}
|
||||
|
||||
sub _find_slaves_by_processlist {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn ) = @_;
|
||||
|
||||
@@ -871,13 +882,16 @@ sub reset_known_replication_threads {
|
||||
|
||||
sub get_cxn_from_dsn_table {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter);
|
||||
my @required_args = qw(dsn_table_dsn make_cxn);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dsn_table_dsn, $make_cxn, $dp, $q) = @args{@required_args};
|
||||
my ($dsn_table_dsn, $make_cxn) = @args{@required_args};
|
||||
PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn);
|
||||
|
||||
my $dp = $self->{DSNParser};
|
||||
my $q = $self->{Quoter};
|
||||
|
||||
my $dsn = $dp->parse($dsn_table_dsn);
|
||||
my $dsn_table;
|
||||
if ( $dsn->{D} && $dsn->{t} ) {
|
||||
|
@@ -22,13 +22,11 @@ use PerconaTest;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
my $ms = new MasterSlave();
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
|
||||
my $master_dbh = $sb->get_dbh_for('master');
|
||||
my $slave_dbh = $sb->get_dbh_for('slave1');
|
||||
|
||||
my $master_dsn = {
|
||||
h => '127.1',
|
||||
P => '12345',
|
||||
@@ -36,28 +34,29 @@ my $master_dsn = {
|
||||
p => 'msandbox',
|
||||
};
|
||||
|
||||
# ############################################################################
|
||||
# get_slaves() wrapper around recurse_to_slaves()
|
||||
# ############################################################################
|
||||
my $q = new Quoter;
|
||||
my $o = new OptionParser(description => 'MasterSlave');
|
||||
$o->get_specs("$trunk/bin/pt-table-checksum");
|
||||
|
||||
my $ms = new MasterSlave(
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# get_slaves() wrapper around recurse_to_slaves()
|
||||
# ############################################################################
|
||||
|
||||
SKIP: {
|
||||
skip "Cannot connect to sandbox master", 2 unless $master_dbh;
|
||||
local @ARGV = ();
|
||||
$o->get_opts();
|
||||
|
||||
my $slaves = $ms->get_slaves(
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
make_cxn => sub {
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
make_cxn => sub {
|
||||
my $cxn = new Cxn(
|
||||
@_,
|
||||
DSNParser => $dp,
|
||||
@@ -83,7 +82,7 @@ SKIP: {
|
||||
master_id => 12345,
|
||||
source => 'hosts',
|
||||
},
|
||||
'get_slaves() from recurse_to_slaves() with a default --recursion-method works'
|
||||
'get_slaves() from recurse_to_slaves() with a default --recursion-method'
|
||||
);
|
||||
|
||||
my ($id) = $slaves->[0]->dbh()->selectrow_array('SELECT @@SERVER_ID');
|
||||
@@ -102,15 +101,9 @@ SKIP: {
|
||||
$o->get_opts();
|
||||
|
||||
$slaves = $ms->get_slaves(
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
make_cxn => sub {
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
make_cxn => sub {
|
||||
my $cxn = new Cxn(
|
||||
@_,
|
||||
DSNParser => $dp,
|
||||
@@ -154,15 +147,9 @@ SKIP: {
|
||||
throws_ok(
|
||||
sub {
|
||||
$slaves = $ms->get_slaves(
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
dbh => $ro_dbh,
|
||||
dsn => $ro_dsn,
|
||||
make_cxn => sub {
|
||||
dbh => $ro_dbh,
|
||||
dsn => $ro_dsn,
|
||||
make_cxn => sub {
|
||||
my $cxn = new Cxn(
|
||||
@_,
|
||||
DSNParser => $dp,
|
||||
@@ -180,15 +167,9 @@ SKIP: {
|
||||
@ARGV = ('--recursion-method', 'none');
|
||||
$o->get_opts();
|
||||
$slaves = $ms->get_slaves(
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
dbh => $ro_dbh,
|
||||
dsn => $ro_dsn,
|
||||
make_cxn => sub {
|
||||
dbh => $ro_dbh,
|
||||
dsn => $ro_dsn,
|
||||
make_cxn => sub {
|
||||
my $cxn = new Cxn(
|
||||
@_,
|
||||
DSNParser => $dp,
|
||||
@@ -204,14 +185,13 @@ SKIP: {
|
||||
"No privs needed for --recursion-method=none (bug 987694)"
|
||||
);
|
||||
|
||||
@ARGV = ('--recursion-method', 'none', '--recurse', '2');
|
||||
$o->get_opts();
|
||||
my $recursed = 0;
|
||||
$ms->recurse_to_slaves(
|
||||
{ dsn_parser => $dp,
|
||||
dbh => $ro_dbh,
|
||||
dsn => $ro_dsn,
|
||||
recurse => 2,
|
||||
callback => sub { $recursed++ },
|
||||
method => [ 'none' ],
|
||||
{ dbh => $ro_dbh,
|
||||
dsn => $ro_dsn,
|
||||
callback => sub { $recursed++ },
|
||||
});
|
||||
is(
|
||||
$recursed,
|
||||
@@ -245,10 +225,10 @@ foreach my $port ( values %port_for ) {
|
||||
diag(`$trunk/sandbox/stop-sandbox $port >/dev/null 2>&1`);
|
||||
}
|
||||
}
|
||||
diag(`$trunk/sandbox/start-sandbox master 2900 >/dev/null 2>&1`);
|
||||
diag(`$trunk/sandbox/start-sandbox slave 2903 2900 >/dev/null 2>&1`);
|
||||
diag(`$trunk/sandbox/start-sandbox slave 2901 2900 >/dev/null 2>&1`);
|
||||
diag(`$trunk/sandbox/start-sandbox slave 2902 2901 >/dev/null 2>&1`);
|
||||
diag(`$trunk/sandbox/start-sandbox master 2900`);
|
||||
diag(`$trunk/sandbox/start-sandbox slave 2903 2900`);
|
||||
diag(`$trunk/sandbox/start-sandbox slave 2901 2900`);
|
||||
diag(`$trunk/sandbox/start-sandbox slave 2902 2901`);
|
||||
|
||||
# I discovered something weird while updating this test. Above, you see that
|
||||
# slave2 is started first, then the others. Before, slave2 was started last,
|
||||
@@ -293,11 +273,12 @@ my $skip_callback = sub {
|
||||
. " from $dsn->{source}");
|
||||
};
|
||||
|
||||
@ARGV = ('--recurse', '2');
|
||||
$o->get_opts();
|
||||
|
||||
$ms->recurse_to_slaves(
|
||||
{ dsn_parser => $dp,
|
||||
dbh => $dbh,
|
||||
{ dbh => $dbh,
|
||||
dsn => $dsn,
|
||||
recurse => 2,
|
||||
callback => $callback,
|
||||
skip_callback => $skip_callback,
|
||||
});
|
||||
@@ -685,10 +666,7 @@ $sb->load_file('master', "t/lib/samples/MasterSlave/dsn_table.sql");
|
||||
$o->get_opts();
|
||||
|
||||
my $slaves = $ms->get_slaves(
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
make_cxn => sub {
|
||||
@@ -735,7 +713,7 @@ eval {
|
||||
like(
|
||||
$EVAL_ERROR,
|
||||
qr/Invalid recursion method: stuff/,
|
||||
"Invalid recursion methods are caught",
|
||||
"--recursion-method stuff causes error"
|
||||
);
|
||||
|
||||
local $EVAL_ERROR;
|
||||
@@ -746,17 +724,18 @@ eval {
|
||||
like(
|
||||
$EVAL_ERROR,
|
||||
qr/Invalid combination of recursion methods: processlist, stuff/,
|
||||
"Invalid recursion methods are caught",
|
||||
"--recursion-method processlist,stuff causes error",
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
$sb->wipe_clean($master_dbh);
|
||||
diag(`$trunk/sandbox/stop-sandbox 2903 2902 2901 2900 >/dev/null 2>&1`);
|
||||
diag(`$trunk/sandbox/stop-sandbox 2903 2902 2901 2900`);
|
||||
diag(`/tmp/12346/use -e "set global read_only=1"`);
|
||||
diag(`/tmp/12347/use -e "set global read_only=1"`);
|
||||
diag(`$trunk/sandbox/test-env reset >/dev/null 2>&1`);
|
||||
$sb->wait_for_slaves();
|
||||
diag(`$trunk/sandbox/test-env reset`);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
|
||||
done_testing;
|
||||
exit;
|
||||
|
Reference in New Issue
Block a user