~percona-toolkit-dev/percona-toolkit/release-2.2.2

« back to all changes in this revision

Viewing changes to bin/pt-online-schema-change

  • Committer: Brian Fraser
  • Date: 2013-04-19 23:26:48 UTC
  • Revision ID: brian.fraser@percona.com-20130419232648-mjnd4rt9k4xldmjc
BuildĀ percona-toolkit-2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
# ###########################################################################
54
54
{
55
55
package Percona::Toolkit;
56
 
our $VERSION = '2.2.1';
 
56
our $VERSION = '2.2.2';
57
57
 
58
58
1;
59
59
}
1137
1137
# ###########################################################################
1138
1138
{
1139
1139
package Lmo::Utils;
 
1140
 
1140
1141
use strict;
1141
1142
use warnings qw( FATAL all );
1142
1143
require Exporter;
1144
1145
 
1145
1146
BEGIN {
1146
1147
   @ISA = qw(Exporter);
1147
 
   @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for);
 
1148
   @EXPORT = @EXPORT_OK = qw(
 
1149
      _install_coderef
 
1150
      _unimport_coderefs
 
1151
      _glob_for
 
1152
      _stash_for
 
1153
   );
1148
1154
}
1149
1155
 
1150
1156
{
1328
1334
   return Lmo::Meta->new(class => $class);
1329
1335
}
1330
1336
 
1331
 
 
1332
1337
1;
1333
1338
}
1334
1339
# ###########################################################################
3786
3791
   return $self->{hostname} || $self->{dsn_name} || 'unknown host';
3787
3792
}
3788
3793
 
 
3794
sub remove_duplicate_cxns {
 
3795
   my ($self, %args) = @_;
 
3796
   my @cxns     = @{$args{cxns}};
 
3797
   my $seen_ids = $args{seen_ids} || {};
 
3798
   PTDEBUG && _d("Removing duplicates from ", join(" ", map { $_->name } @cxns));
 
3799
   my @trimmed_cxns;
 
3800
 
 
3801
   for my $cxn ( @cxns ) {
 
3802
      my $dbh  = $cxn->dbh();
 
3803
      my $sql  = q{SELECT @@server_id};
 
3804
      PTDEBUG && _d($sql);
 
3805
      my ($id) = $dbh->selectrow_array($sql);
 
3806
      PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
 
3807
 
 
3808
      if ( ! $seen_ids->{$id}++ ) {
 
3809
         push @trimmed_cxns, $cxn
 
3810
      }
 
3811
      else {
 
3812
         PTDEBUG && _d("Removing ", $cxn->name,
 
3813
                       ", ID ", $id, ", because we've already seen it");
 
3814
      }
 
3815
   }
 
3816
 
 
3817
   return \@trimmed_cxns;
 
3818
}
 
3819
 
3789
3820
sub DESTROY {
3790
3821
   my ($self) = @_;
3791
3822
 
3880
3911
   my $dp      = $self->{DSNParser};
3881
3912
   my $methods = $self->_resolve_recursion_methods($args{dsn});
3882
3913
 
 
3914
   return $slaves unless @$methods;
 
3915
   
3883
3916
   if ( grep { m/processlist|hosts/i } @$methods ) {
3884
3917
      my @required_args = qw(dbh dsn);
3885
3918
      foreach my $arg ( @required_args ) {
7481
7514
use Lmo;
7482
7515
use Data::Dumper;
7483
7516
 
 
7517
{ local $EVAL_ERROR; eval { require Cxn } };
 
7518
 
7484
7519
sub get_cluster_name {
7485
7520
   my ($self, $cxn) = @_;
7486
7521
   my $sql = "SHOW VARIABLES LIKE 'wsrep\_cluster\_name'";
7505
7540
sub same_node {
7506
7541
   my ($self, $cxn1, $cxn2) = @_;
7507
7542
 
7508
 
   my $sql = "SHOW VARIABLES LIKE 'wsrep\_sst\_receive\_address'";
7509
 
   PTDEBUG && _d($cxn1->name, $sql);
7510
 
   my (undef, $val1) = $cxn1->dbh->selectrow_array($sql);
7511
 
   PTDEBUG && _d($cxn2->name, $sql);
7512
 
   my (undef, $val2) = $cxn2->dbh->selectrow_array($sql);
7513
 
 
7514
 
   return ($val1 || '') eq ($val2 || '');
 
7543
   foreach my $val ('wsrep\_sst\_receive\_address', 'wsrep\_node\_name', 'wsrep\_node\_address') {
 
7544
      my $sql = "SHOW VARIABLES LIKE '$val'";
 
7545
      PTDEBUG && _d($cxn1->name, $cxn2->name, $sql);
 
7546
      my (undef, $val1) = $cxn1->dbh->selectrow_array($sql);
 
7547
      my (undef, $val2) = $cxn2->dbh->selectrow_array($sql);
 
7548
 
 
7549
      return unless ($val1 || '') eq ($val2 || '');
 
7550
   }
 
7551
 
 
7552
   return 1;
 
7553
}
 
7554
 
 
7555
sub find_cluster_nodes {
 
7556
   my ($self, %args) = @_;
 
7557
 
 
7558
   my $dbh = $args{dbh};
 
7559
   my $dsn = $args{dsn};
 
7560
   my $dp  = $args{DSNParser};
 
7561
   my $make_cxn = $args{make_cxn};
 
7562
 
 
7563
   
 
7564
   my $sql = q{SHOW STATUS LIKE 'wsrep\_incoming\_addresses'};
 
7565
   PTDEBUG && _d($sql);
 
7566
   my (undef, $addresses) = $dbh->selectrow_array($sql);
 
7567
   PTDEBUG && _d("Cluster nodes found: ", $addresses);
 
7568
   return unless $addresses;
 
7569
 
 
7570
   my @addresses = grep { !/\Aunspecified\z/i }
 
7571
                   split /,\s*/, $addresses;
 
7572
 
 
7573
   my @nodes;
 
7574
   foreach my $address ( @addresses ) {
 
7575
      my ($host, $port) = split /:/, $address;
 
7576
      my $spec = "h=$host"
 
7577
               . ($port ? ",P=$port" : "");
 
7578
      my $node_dsn = $dp->parse($spec, $dsn);
 
7579
      my $node_dbh = eval { $dp->get_dbh(
 
7580
            $dp->get_cxn_params($node_dsn), { AutoCommit => 1 }) };
 
7581
      if ( $EVAL_ERROR ) {
 
7582
         print STDERR "Cannot connect to ", $dp->as_string($node_dsn),
 
7583
                      ", discovered through $sql: $EVAL_ERROR\n";
 
7584
         if ( !$port && $dsn->{P} != 3306 ) {
 
7585
            $address .= ":3306";
 
7586
            redo;
 
7587
         }
 
7588
         next;
 
7589
      }
 
7590
      PTDEBUG && _d('Connected to', $dp->as_string($node_dsn));
 
7591
      $node_dbh->disconnect();
 
7592
 
 
7593
      push @nodes, $make_cxn->(dsn => $node_dsn);
 
7594
   }
 
7595
 
 
7596
   return \@nodes;
 
7597
}
 
7598
 
 
7599
sub remove_duplicate_cxns {
 
7600
   my ($self, %args) = @_;
 
7601
   my @cxns     = @{$args{cxns}};
 
7602
   my $seen_ids = $args{seen_ids};
 
7603
   return Cxn->remove_duplicate_cxns(%args);
7515
7604
}
7516
7605
 
7517
7606
sub same_cluster {
7525
7614
   return ($cluster1 || '') eq ($cluster2 || '');
7526
7615
}
7527
7616
 
 
7617
sub autodetect_nodes {
 
7618
   my ($self, %args) = @_;
 
7619
   my $ms       = $args{MasterSlave};
 
7620
   my $dp       = $args{DSNParser};
 
7621
   my $make_cxn = $args{make_cxn};
 
7622
   my $nodes    = $args{nodes};
 
7623
   my $seen_ids = $args{seen_ids};
 
7624
 
 
7625
   my $new_nodes = [];
 
7626
 
 
7627
   return $new_nodes unless @$nodes;
 
7628
   
 
7629
   for my $node ( @$nodes ) {
 
7630
      my $nodes_found = $self->find_cluster_nodes(
 
7631
         dbh       => $node->dbh(),
 
7632
         dsn       => $node->dsn(),
 
7633
         make_cxn  => $make_cxn,
 
7634
         DSNParser => $dp,
 
7635
      );
 
7636
      push @$new_nodes, @$nodes_found;
 
7637
   }
 
7638
 
 
7639
   $new_nodes = $self->remove_duplicate_cxns(
 
7640
      cxns     => $new_nodes,
 
7641
      seen_ids => $seen_ids
 
7642
   );
 
7643
 
 
7644
   my $new_slaves = [];
 
7645
   foreach my $node (@$new_nodes) {
 
7646
      my $node_slaves = $ms->get_slaves(
 
7647
         dbh      => $node->dbh(),
 
7648
         dsn      => $node->dsn(),
 
7649
         make_cxn => $make_cxn,
 
7650
      );
 
7651
      push @$new_slaves, @$node_slaves;
 
7652
   }
 
7653
 
 
7654
   $new_slaves = $self->remove_duplicate_cxns(
 
7655
      cxns     => $new_slaves,
 
7656
      seen_ids => $seen_ids
 
7657
   );
 
7658
 
 
7659
   my @new_slave_nodes = grep { $self->is_cluster_node($_) } @$new_slaves;
 
7660
   
 
7661
   my $slaves_of_slaves = $self->autodetect_nodes(
 
7662
         %args,
 
7663
         nodes => \@new_slave_nodes,
 
7664
   );
 
7665
   
 
7666
   my @autodetected_nodes = ( @$new_nodes, @$new_slaves, @$slaves_of_slaves );
 
7667
   return \@autodetected_nodes;
 
7668
}
 
7669
 
7528
7670
sub _d {
7529
7671
   my ($package, undef, $line) = caller 0;
7530
7672
   @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
11255
11397
 
11256
11398
=head1 VERSION
11257
11399
 
11258
 
pt-online-schema-change 2.2.1
 
11400
pt-online-schema-change 2.2.2
11259
11401
 
11260
11402
=cut