mirror of
https://github.com/percona/percona-toolkit.git
synced 2026-04-26 01:02:25 +08:00
Update all modules that use --recursion-method, additionally changing it to an array with default processlist,hosts and checking the array for validity
This commit is contained in:
+66
-36
@@ -35,27 +35,28 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
|
||||
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 => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
@@ -66,31 +67,49 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
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 ( $method =~ m/none/i ) {
|
||||
elsif ( !@$methods || $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 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 recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -141,19 +160,10 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
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);
|
||||
|
||||
@@ -170,6 +180,15 @@ 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 ) = @_;
|
||||
|
||||
@@ -1994,7 +2013,7 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error getting the current SQL_MODE: $EVAL_ERROR";
|
||||
}
|
||||
|
||||
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
|
||||
@@ -2004,15 +2023,17 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
|
||||
. ($sql_mode ? " and $sql_mode" : '')
|
||||
. ": $EVAL_ERROR";
|
||||
}
|
||||
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
|
||||
$sql = "/*!40101 SET NAMES $charset*/";
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
|
||||
$sql = qq{/*!40101 SET NAMES "$charset"*/};
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting NAMES to $charset: $EVAL_ERROR";
|
||||
}
|
||||
PTDEBUG && _d('Enabling charset for STDOUT');
|
||||
if ( $charset eq 'utf8' ) {
|
||||
@@ -2024,12 +2045,12 @@ sub get_dbh {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $self->prop('set-vars') ) {
|
||||
$sql = "SET " . $self->prop('set-vars');
|
||||
if ( my $var = $self->prop('set-vars') ) {
|
||||
$sql = "SET $var";
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting $var: $EVAL_ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3282,6 +3303,13 @@ sub main {
|
||||
}
|
||||
}
|
||||
|
||||
eval {
|
||||
MasterSlave::check_recursion_method($o->get('recursion-method'));
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
$o->save_error("Invalid --recursion-method: $EVAL_ERROR")
|
||||
}
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
# ########################################################################
|
||||
@@ -3742,7 +3770,9 @@ sub check_delay {
|
||||
PTDEBUG && _d("Found slave", $dp->as_string($dsn));
|
||||
push @sths, [ $dsn, $dbh->prepare($sql) ];
|
||||
},
|
||||
method => $o->get('recursion-method'),
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -4231,7 +4261,7 @@ This currently works only with MySQL. See L<"--recursion-method">.
|
||||
|
||||
=item --recursion-method
|
||||
|
||||
type: string
|
||||
type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method used to find slaves.
|
||||
|
||||
|
||||
+71
-36
@@ -1935,7 +1935,7 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error getting the current SQL_MODE: $EVAL_ERROR";
|
||||
}
|
||||
|
||||
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
|
||||
@@ -1945,15 +1945,17 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
|
||||
. ($sql_mode ? " and $sql_mode" : '')
|
||||
. ": $EVAL_ERROR";
|
||||
}
|
||||
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
|
||||
$sql = "/*!40101 SET NAMES $charset*/";
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
|
||||
$sql = qq{/*!40101 SET NAMES "$charset"*/};
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting NAMES to $charset: $EVAL_ERROR";
|
||||
}
|
||||
PTDEBUG && _d('Enabling charset for STDOUT');
|
||||
if ( $charset eq 'utf8' ) {
|
||||
@@ -1965,12 +1967,12 @@ sub get_dbh {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $self->prop('set-vars') ) {
|
||||
$sql = "SET " . $self->prop('set-vars');
|
||||
if ( my $var = $self->prop('set-vars') ) {
|
||||
$sql = "SET $var";
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting $var: $EVAL_ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3333,6 +3335,7 @@ sub new {
|
||||
dsn_name => $dp->as_string($dsn, [qw(h P S)]),
|
||||
hostname => '',
|
||||
set => $args{set},
|
||||
NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
|
||||
dbh_set => 0,
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
@@ -3370,7 +3373,10 @@ sub set_dbh {
|
||||
|
||||
PTDEBUG && _d($dbh, 'Setting dbh');
|
||||
|
||||
if ( !exists $self->{NAME_lc}
|
||||
|| (defined $self->{NAME_lc} && $self->{NAME_lc}) ) {
|
||||
$dbh->{FetchHashKeyName} = 'NAME_lc';
|
||||
}
|
||||
|
||||
my $sql = 'SELECT @@hostname, @@server_id';
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
@@ -3457,27 +3463,28 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
|
||||
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 => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
@@ -3488,31 +3495,49 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
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 ( $method =~ m/none/i ) {
|
||||
elsif ( !@$methods || $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 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 recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -3563,19 +3588,10 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
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);
|
||||
|
||||
@@ -3592,6 +3608,15 @@ 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 ) = @_;
|
||||
|
||||
@@ -5904,6 +5929,13 @@ sub main {
|
||||
}
|
||||
}
|
||||
|
||||
eval {
|
||||
MasterSlave::check_recursion_method($o->get('recursion-method'));
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
$o->save_error("Invalid --recursion-method: $EVAL_ERROR")
|
||||
}
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
if ( $o->get('quiet') ) {
|
||||
@@ -6005,7 +6037,10 @@ sub main {
|
||||
$slaves = $ms->get_slaves(
|
||||
dbh => $cxn->dbh(),
|
||||
dsn => $cxn->dsn(),
|
||||
OptionParser => $o,
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
make_cxn => sub {
|
||||
@@ -8361,7 +8396,7 @@ Default is infinite. See also L<"--recursion-method">.
|
||||
|
||||
=item --recursion-method
|
||||
|
||||
type: string
|
||||
type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method for discovering replicas. Possible methods are:
|
||||
|
||||
|
||||
+66
-36
@@ -1741,7 +1741,7 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error getting the current SQL_MODE: $EVAL_ERROR";
|
||||
}
|
||||
|
||||
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
|
||||
@@ -1751,15 +1751,17 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
|
||||
. ($sql_mode ? " and $sql_mode" : '')
|
||||
. ": $EVAL_ERROR";
|
||||
}
|
||||
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
|
||||
$sql = "/*!40101 SET NAMES $charset*/";
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
|
||||
$sql = qq{/*!40101 SET NAMES "$charset"*/};
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting NAMES to $charset: $EVAL_ERROR";
|
||||
}
|
||||
PTDEBUG && _d('Enabling charset for STDOUT');
|
||||
if ( $charset eq 'utf8' ) {
|
||||
@@ -1771,12 +1773,12 @@ sub get_dbh {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $self->prop('set-vars') ) {
|
||||
$sql = "SET " . $self->prop('set-vars');
|
||||
if ( my $var = $self->prop('set-vars') ) {
|
||||
$sql = "SET $var";
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting $var: $EVAL_ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1881,27 +1883,28 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
|
||||
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 => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
@@ -1912,31 +1915,49 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
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 ( $method =~ m/none/i ) {
|
||||
elsif ( !@$methods || $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 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 recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -1987,19 +2008,10 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
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);
|
||||
|
||||
@@ -2016,6 +2028,15 @@ 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 ) = @_;
|
||||
|
||||
@@ -3330,6 +3351,13 @@ sub main {
|
||||
$o->save_error("Missing or invalid master host");
|
||||
}
|
||||
|
||||
eval {
|
||||
MasterSlave::check_recursion_method($o->get('recursion-method'));
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
$o->save_error("Invalid --recursion-method: $EVAL_ERROR")
|
||||
}
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
# ########################################################################
|
||||
@@ -3361,7 +3389,9 @@ sub main {
|
||||
dsn => $master_dsn,
|
||||
dsn_parser => $dp,
|
||||
recurse => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
if ( !$parent ) {
|
||||
@@ -3710,7 +3740,7 @@ See L<"--recursion-method">.
|
||||
|
||||
=item --recursion-method
|
||||
|
||||
type: string
|
||||
type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method used to find slaves.
|
||||
|
||||
|
||||
+66
-36
@@ -2054,7 +2054,7 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error getting the current SQL_MODE: $EVAL_ERROR";
|
||||
}
|
||||
|
||||
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
|
||||
@@ -2064,15 +2064,17 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
|
||||
. ($sql_mode ? " and $sql_mode" : '')
|
||||
. ": $EVAL_ERROR";
|
||||
}
|
||||
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
|
||||
$sql = "/*!40101 SET NAMES $charset*/";
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
|
||||
$sql = qq{/*!40101 SET NAMES "$charset"*/};
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting NAMES to $charset: $EVAL_ERROR";
|
||||
}
|
||||
PTDEBUG && _d('Enabling charset for STDOUT');
|
||||
if ( $charset eq 'utf8' ) {
|
||||
@@ -2084,12 +2086,12 @@ sub get_dbh {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $self->prop('set-vars') ) {
|
||||
$sql = "SET " . $self->prop('set-vars');
|
||||
if ( my $var = $self->prop('set-vars') ) {
|
||||
$sql = "SET $var";
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting $var: $EVAL_ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2194,27 +2196,28 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
|
||||
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 => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
@@ -2225,31 +2228,49 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
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 ( $method =~ m/none/i ) {
|
||||
elsif ( !@$methods || $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 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 recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -2300,19 +2321,10 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
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);
|
||||
|
||||
@@ -2329,6 +2341,15 @@ 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 ) = @_;
|
||||
|
||||
@@ -3113,6 +3134,13 @@ sub main {
|
||||
}
|
||||
}
|
||||
|
||||
eval {
|
||||
MasterSlave::check_recursion_method($o->get('recursion-method'));
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
$o->save_error("Invalid --recursion-method: $EVAL_ERROR")
|
||||
}
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
# ########################################################################
|
||||
@@ -3206,7 +3234,9 @@ sub main {
|
||||
my ( $dsn, $dbh, $level ) = @_;
|
||||
print STDERR "Skipping ", $dp->as_string($dsn), "\n";
|
||||
},
|
||||
method => $o->get('recursion-method'),
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -3792,7 +3822,7 @@ password.
|
||||
|
||||
=item --recursion-method
|
||||
|
||||
type: string
|
||||
type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method used to find slaves.
|
||||
|
||||
|
||||
+71
-36
@@ -266,7 +266,7 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error getting the current SQL_MODE: $EVAL_ERROR";
|
||||
}
|
||||
|
||||
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
|
||||
@@ -276,15 +276,17 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
|
||||
. ($sql_mode ? " and $sql_mode" : '')
|
||||
. ": $EVAL_ERROR";
|
||||
}
|
||||
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
|
||||
$sql = "/*!40101 SET NAMES $charset*/";
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
|
||||
$sql = qq{/*!40101 SET NAMES "$charset"*/};
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting NAMES to $charset: $EVAL_ERROR";
|
||||
}
|
||||
PTDEBUG && _d('Enabling charset for STDOUT');
|
||||
if ( $charset eq 'utf8' ) {
|
||||
@@ -296,12 +298,12 @@ sub get_dbh {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $self->prop('set-vars') ) {
|
||||
$sql = "SET " . $self->prop('set-vars');
|
||||
if ( my $var = $self->prop('set-vars') ) {
|
||||
$sql = "SET $var";
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting $var: $EVAL_ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1901,6 +1903,7 @@ sub new {
|
||||
dsn_name => $dp->as_string($dsn, [qw(h P S)]),
|
||||
hostname => '',
|
||||
set => $args{set},
|
||||
NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
|
||||
dbh_set => 0,
|
||||
OptionParser => $o,
|
||||
DSNParser => $dp,
|
||||
@@ -1938,7 +1941,10 @@ sub set_dbh {
|
||||
|
||||
PTDEBUG && _d($dbh, 'Setting dbh');
|
||||
|
||||
if ( !exists $self->{NAME_lc}
|
||||
|| (defined $self->{NAME_lc} && $self->{NAME_lc}) ) {
|
||||
$dbh->{FetchHashKeyName} = 'NAME_lc';
|
||||
}
|
||||
|
||||
my $sql = 'SELECT @@hostname, @@server_id';
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
@@ -3041,27 +3047,28 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
|
||||
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 => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
@@ -3072,31 +3079,49 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
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 ( $method =~ m/none/i ) {
|
||||
elsif ( !@$methods || $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 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 recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -3147,19 +3172,10 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
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);
|
||||
|
||||
@@ -3176,6 +3192,15 @@ 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 ) = @_;
|
||||
|
||||
@@ -6856,6 +6881,13 @@ sub main {
|
||||
}
|
||||
}
|
||||
|
||||
eval {
|
||||
MasterSlave::check_recursion_method($o->get('recursion-method'));
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
$o->save_error("Invalid --recursion-method: $EVAL_ERROR")
|
||||
}
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
# ########################################################################
|
||||
@@ -7028,7 +7060,10 @@ sub main {
|
||||
$slaves = $ms->get_slaves(
|
||||
dbh => $master_dbh,
|
||||
dsn => $master_dsn,
|
||||
OptionParser => $o,
|
||||
recursion_method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
recurse => $o->get('recurse'),
|
||||
DSNParser => $dp,
|
||||
Quoter => $q,
|
||||
make_cxn => sub {
|
||||
@@ -9304,7 +9339,7 @@ Default is infinite. See also L<"--recursion-method">.
|
||||
|
||||
=item --recursion-method
|
||||
|
||||
type: string
|
||||
type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method for discovering replicas. Possible methods are:
|
||||
|
||||
|
||||
+66
-36
@@ -1860,7 +1860,7 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error getting the current SQL_MODE: $EVAL_ERROR";
|
||||
}
|
||||
|
||||
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
|
||||
@@ -1870,15 +1870,17 @@ sub get_dbh {
|
||||
PTDEBUG && _d($dbh, $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
|
||||
. ($sql_mode ? " and $sql_mode" : '')
|
||||
. ": $EVAL_ERROR";
|
||||
}
|
||||
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
|
||||
$sql = "/*!40101 SET NAMES $charset*/";
|
||||
if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
|
||||
$sql = qq{/*!40101 SET NAMES "$charset"*/};
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting NAMES to $charset: $EVAL_ERROR";
|
||||
}
|
||||
PTDEBUG && _d('Enabling charset for STDOUT');
|
||||
if ( $charset eq 'utf8' ) {
|
||||
@@ -1890,12 +1892,12 @@ sub get_dbh {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $self->prop('set-vars') ) {
|
||||
$sql = "SET " . $self->prop('set-vars');
|
||||
if ( my $var = $self->prop('set-vars') ) {
|
||||
$sql = "SET $var";
|
||||
PTDEBUG && _d($dbh, ':', $sql);
|
||||
eval { $dbh->do($sql) };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die $EVAL_ERROR;
|
||||
die "Error setting $var: $EVAL_ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6465,27 +6467,28 @@ sub new {
|
||||
|
||||
sub get_slaves {
|
||||
my ($self, %args) = @_;
|
||||
my @required_args = qw(make_cxn OptionParser DSNParser Quoter);
|
||||
my @required_args = qw(make_cxn recursion_method recurse DSNParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($make_cxn, $o, $dp) = @args{@required_args};
|
||||
my ($make_cxn, $methods, $recurse, $dp) = @args{@required_args};
|
||||
|
||||
my $slaves = [];
|
||||
my $method = $o->get('recursion-method');
|
||||
PTDEBUG && _d('Slave recursion method:', $method);
|
||||
if ( !$method || $method =~ m/processlist|hosts/i ) {
|
||||
|
||||
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 => $o->get('recurse'),
|
||||
method => $o->get('recursion-method'),
|
||||
recurse => $recurse,
|
||||
method => $methods,
|
||||
callback => sub {
|
||||
my ( $dsn, $dbh, $level, $parent ) = @_;
|
||||
return unless $level;
|
||||
@@ -6496,31 +6499,49 @@ sub get_slaves {
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ( $method =~ m/^dsn=/i ) {
|
||||
my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i;
|
||||
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 ( $method =~ m/none/i ) {
|
||||
elsif ( !@$methods || $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 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 recurse_to_slaves {
|
||||
my ( $self, $args, $level ) = @_;
|
||||
$level ||= 0;
|
||||
my $dp = $args->{dsn_parser};
|
||||
my $dsn = $args->{dsn};
|
||||
|
||||
if ( lc($args->{method} || '') eq 'none' ) {
|
||||
if ( $args->{method} && lc($args->{method}->[0] || '') eq 'none' ) {
|
||||
PTDEBUG && _d('Not recursing to slaves');
|
||||
return;
|
||||
}
|
||||
@@ -6571,19 +6592,10 @@ sub recurse_to_slaves {
|
||||
}
|
||||
|
||||
sub find_slave_hosts {
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $method ) = @_;
|
||||
my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_;
|
||||
|
||||
my @methods = $self->_resolve_recursion_methods($methods, $dsn);
|
||||
|
||||
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);
|
||||
|
||||
@@ -6600,6 +6612,15 @@ 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 ) = @_;
|
||||
|
||||
@@ -8320,6 +8341,13 @@ sub main {
|
||||
return 0;
|
||||
}
|
||||
|
||||
eval {
|
||||
MasterSlave::check_recursion_method($o->get('recursion-method'));
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
$o->save_error("Invalid --recursion-method: $EVAL_ERROR")
|
||||
}
|
||||
|
||||
$o->usage_or_errors();
|
||||
|
||||
# ########################################################################
|
||||
@@ -8809,7 +8837,9 @@ sub sync_via_replication {
|
||||
|
||||
return;
|
||||
}, # recurse_to_slaves() callback
|
||||
method => $o->get('recursion-method'),
|
||||
method => $o->got('recursion-method')
|
||||
? $o->get('recursion-method')
|
||||
: [],
|
||||
},
|
||||
);
|
||||
} # DSN is master
|
||||
@@ -10766,7 +10796,7 @@ yourself if you want to sync the tables manually.
|
||||
|
||||
=item --recursion-method
|
||||
|
||||
type: string
|
||||
type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method used to find slaves.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ BEGIN {
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More tests => 19;
|
||||
use Test::More;
|
||||
|
||||
use PerconaTest;
|
||||
shift @INC; # our unshift (above)
|
||||
@@ -95,6 +95,18 @@ like(
|
||||
"Default --replicate-check=TRUE"
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/^\s+--recursion-method=a/m,
|
||||
"--recursion-method is an array"
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/^\s+--recursion-method\s+processlist,hosts/m,
|
||||
"Default --recursion-method is processlist,hosts"
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# Check opts that disable other opts.
|
||||
# ############################################################################
|
||||
@@ -170,4 +182,4 @@ like(
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
exit;
|
||||
done_testing;
|
||||
|
||||
Reference in New Issue
Block a user