diff --git a/bin/pt-archiver b/bin/pt-archiver index 75efc296..004b5bee 100755 --- a/bin/pt-archiver +++ b/bin/pt-archiver @@ -2725,6 +2725,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -3301,6 +3349,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/bin/pt-heartbeat b/bin/pt-heartbeat index 2908dc6c..24af7175 100755 --- a/bin/pt-heartbeat +++ b/bin/pt-heartbeat @@ -33,6 +33,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -609,6 +657,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/bin/pt-kill b/bin/pt-kill index a04fc502..571c3dc5 100755 --- a/bin/pt-kill +++ b/bin/pt-kill @@ -2437,6 +2437,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -3013,6 +3061,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/bin/pt-query-digest b/bin/pt-query-digest index a7cf6b77..750d1bf3 100755 --- a/bin/pt-query-digest +++ b/bin/pt-query-digest @@ -10441,6 +10441,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -11017,6 +11065,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/bin/pt-slave-find b/bin/pt-slave-find index 47e26f56..88c933c5 100755 --- a/bin/pt-slave-find +++ b/bin/pt-slave-find @@ -1414,6 +1414,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -1990,6 +2038,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/bin/pt-slave-restart b/bin/pt-slave-restart index b1758f28..676db6f9 100755 --- a/bin/pt-slave-restart +++ b/bin/pt-slave-restart @@ -1574,6 +1574,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -2150,6 +2198,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index 9f058f13..4702086f 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -2454,7 +2454,7 @@ sub get_slaves { my $slaves = []; my $method = $o->get('recursion-method'); PTDEBUG && _d('Slave recursion method:', $method); - if ( !$method || $method =~ m/proocesslist|hosts/i ) { + if ( !$method || $method =~ m/processlist|hosts/i ) { my @required_args = qw(dbh dsn); foreach my $arg ( @required_args ) { die "I need a $arg argument" unless $args{$arg}; @@ -2484,7 +2484,7 @@ sub get_slaves { ); } else { - die "Invalid --recusion-method: $method. Valid values are: " + die "Invalid --recursion-method: $method. Valid values are: " . "dsn=DSN, hosts, or processlist.\n"; } diff --git a/bin/pt-table-sync b/bin/pt-table-sync index 41e4bd9d..2a4172da 100755 --- a/bin/pt-table-sync +++ b/bin/pt-table-sync @@ -5856,6 +5856,54 @@ sub new { return bless $self, $class; } +sub get_slaves { + my ($self, %args) = @_; + my @required_args = qw(make_cxn OptionParser DSNParser Quoter); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my ($make_cxn, $o, $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 ) { + 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 { + 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 ( $method =~ m/^dsn=/i ) { + my ($dsn_table_dsn) = $method =~ m/^dsn=(.+)/i; + $slaves = $self->get_cxn_from_dsn_table( + %args, + dsn_table_dsn => $dsn_table_dsn, + ); + } + else { + die "Invalid --recursion-method: $method. Valid values are: " + . "dsn=DSN, hosts, or processlist.\n"; + } + + return $slaves; +} + sub recurse_to_slaves { my ( $self, $args, $level ) = @_; $level ||= 0; @@ -6432,6 +6480,43 @@ sub reset_known_replication_threads { return; } +sub get_cxn_from_dsn_table { + my ($self, %args) = @_; + my @required_args = qw(dsn_table_dsn make_cxn DSNParser Quoter); + 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}; + PTDEBUG && _d('DSN table DSN:', $dsn_table_dsn); + + my $dsn = $dp->parse($dsn_table_dsn); + my $dsn_table; + if ( $dsn->{D} && $dsn->{t} ) { + $dsn_table = $q->quote($dsn->{D}, $dsn->{t}); + } + elsif ( $dsn->{t} && $dsn->{t} =~ m/\./ ) { + $dsn_table = $q->quote($q->split_unquote($dsn->{t})); + } + else { + die "DSN table DSN does not specify a database (D) " + . "or a database-qualified table (t)"; + } + + my $dsn_tbl_cxn = $make_cxn->(dsn => $dsn); + my $dbh = $dsn_tbl_cxn->connect(); + my $sql = "SELECT dsn FROM $dsn_table ORDER BY id"; + PTDEBUG && _d($sql); + my $dsn_strings = $dbh->selectcol_arrayref($sql); + my @cxn; + if ( $dsn_strings ) { + foreach my $dsn_string ( @$dsn_strings ) { + PTDEBUG && _d('DSN from DSN table:', $dsn_string); + push @cxn, $make_cxn->(dsn_string => $dsn_string); + } + } + return \@cxn; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/lib/MasterSlave.pm b/lib/MasterSlave.pm index ca903fb0..89167592 100644 --- a/lib/MasterSlave.pm +++ b/lib/MasterSlave.pm @@ -47,7 +47,7 @@ sub get_slaves { my $slaves = []; my $method = $o->get('recursion-method'); PTDEBUG && _d('Slave recursion method:', $method); - if ( !$method || $method =~ m/proocesslist|hosts/i ) { + if ( !$method || $method =~ m/processlist|hosts/i ) { my @required_args = qw(dbh dsn); foreach my $arg ( @required_args ) { die "I need a $arg argument" unless $args{$arg}; @@ -77,7 +77,7 @@ sub get_slaves { ); } else { - die "Invalid --recusion-method: $method. Valid values are: " + die "Invalid --recursion-method: $method. Valid values are: " . "dsn=DSN, hosts, or processlist.\n"; } diff --git a/t/lib/MasterSlave.t b/t/lib/MasterSlave.t index 1654150f..470b3670 100644 --- a/t/lib/MasterSlave.t +++ b/t/lib/MasterSlave.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 46; +use Test::More tests => 47; use MasterSlave; use DSNParser; @@ -27,6 +27,13 @@ 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', + u => 'msandbox', + p => 'msandbox', +}; # ############################################################################ # get_slaves() wrapper around recurse_to_slaves() @@ -42,12 +49,7 @@ SKIP: { my $slaves = $ms->get_slaves( dbh => $master_dbh, - dsn => { - h => '127.1', - P => '12345', - u => 'msandbox', - p => 'msandbox', - }, + dsn => $master_dsn, OptionParser => $o, DSNParser => $dp, Quoter => $q, @@ -86,6 +88,37 @@ SKIP: { '12346', 'dbh created from get_slaves()' ); + + # This doesn't actually work because the master and slave are both + # localhost/127.1 so it will connect agian to the master, detect this, + # and ignore it. This tests nonetheless that "processlist" isn't + # misspelled, which would cause the sub to die. + # https://bugs.launchpad.net/percona-toolkit/+bug/921802 + @ARGV = ('--recursion-method', 'processlist'); + $o->get_opts(); + + $slaves = $ms->get_slaves( + OptionParser => $o, + DSNParser => $dp, + Quoter => $q, + dbh => $master_dbh, + dsn => $master_dsn, + make_cxn => sub { + my $cxn = new Cxn( + @_, + DSNParser => $dp, + OptionParser => $o, + ); + $cxn->connect(); + return $cxn; + }, + ); + + is_deeply( + $slaves, + [], + "get_slaves() by processlist" + ); } # #############################################################################