From 5a9cc13d6fffcfba9dab5ec8c96dc0d15d87802b Mon Sep 17 00:00:00 2001 From: Brian Fraser Date: Wed, 17 Oct 2012 15:39:06 -0300 Subject: [PATCH] Fixes for the previous commit --- bin/pt-table-checksum | 73 ++++++++++++++++++++++++++++++++++++++ lib/Cxn.pm | 27 +++++++++++--- t/lib/Cxn.t | 9 +++-- t/pt-table-checksum/bugs.t | 16 +++++---- 4 files changed, 112 insertions(+), 13 deletions(-) diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index 992023fd..8c257922 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -3206,11 +3206,21 @@ use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); use Scalar::Util qw(blessed); + use constant { PTDEBUG => $ENV{PTDEBUG} || 0, PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, }; +use Data::Dumper (); +sub Dumper { + local $Data::Dumper::Indent = 1; + local $Data::Dumper::Sortkeys = 1; + local $Data::Dumper::Quotekeys = 0; + + Data::Dumper::Dumper(@_); +} + sub new { my ( $class, %args ) = @_; my @required_args = qw(DSNParser OptionParser); @@ -3327,6 +3337,69 @@ sub is_cluster_node { return $self->{is_cluster_node}; } +sub same_cluster { + my ($self, $cxn) = @_; + return unless $self->is_cluster_node() && $cxn->is_cluster_node(); + return if $self->is_master_of($cxn) || $cxn->is_master_of($self); + + my $sql = q{SHOW VARIABLES LIKE 'wsrep_cluster_name'}; + PTDEBUG && _d($sql); + my (undef, $row) = $self->dbh->selectrow_array($sql); + my (undef, $cxn_row) = $cxn->dbh->selectrow_array($sql); + + return unless $row eq $cxn_row; + + $sql = q{SHOW VARIABLES LIKE 'wsrep_cluster_address'}; + PTDEBUG && _d($sql); + my (undef, $addr) = $self->dbh->selectrow_array($sql); + my (undef, $cxn_addr) = $cxn->dbh->selectrow_array($sql); + + return if $addr eq 'gcomm://' && $cxn_addr eq 'gcomm://'; + + if ( $addr eq 'gcomm://' ) { + $addr = $self->_find_full_gcomm_addr($self->dbh); + } + elsif ( $cxn_addr eq 'gcomm://' ) { + $cxn_addr = $self->_find_full_gcomm_addr($cxn->dbh); + } + + return 1 if $addr eq $cxn_addr; + + return 1; +} + +sub is_master_of { + my ($self, $cxn) = @_; + + my $cxn_dbh = $cxn->dbh; + local $cxn_dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = q{SHOW SLAVE STATUS}; + PTDEBUG && _d($sql); + my $slave_status = $cxn_dbh->selectrow_hashref($sql); + return unless ref($slave_status) eq 'HASH'; + + my $port = $self->dsn->{P}; + return unless $slave_status->{master_port} eq $port; + return 1 if $self->dsn->{h} eq $slave_status->{master_host}; + + my $host = scalar gethostbyname($self->dsn->{h}); + my $master_host = scalar gethostbyname($slave_status->{master_host}); + return 1 if $master_host eq $host; + return; +} + +sub _find_full_gcomm_addr { + my ($self, $dbh) = @_; + + my $sql = q{SHOW VARIABLES LIKE 'wsrep_provider_options'}; + PTDEBUG && _d($sql); + my (undef, $provider_opts) = $dbh->selectrow_array($sql); + my ($prov_addr) = $provider_opts =~ m{\Qgmcast.listen_addr\E\s*=\s*tcp://([^:]+:[0-9]+)\s*;}; + my $full_gcomm = "gcomm://$prov_addr"; + PTDEBUG && _d("gcomm address: ", $full_gcomm); + return $full_gcomm; +} + sub DESTROY { my ($self) = @_; if ( $self->{dbh} diff --git a/lib/Cxn.pm b/lib/Cxn.pm index eeef3006..0ab8b1d3 100644 --- a/lib/Cxn.pm +++ b/lib/Cxn.pm @@ -36,6 +36,7 @@ use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); use Scalar::Util qw(blessed); + use constant { PTDEBUG => $ENV{PTDEBUG} || 0, # Hostnames make testing less accurate. Tests need to see @@ -45,6 +46,15 @@ use constant { PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, }; +use Data::Dumper (); +sub Dumper { + local $Data::Dumper::Indent = 1; + local $Data::Dumper::Sortkeys = 1; + local $Data::Dumper::Quotekeys = 0; + + Data::Dumper::Dumper(@_); +} + # Sub: new # # Required Arguments: @@ -260,13 +270,20 @@ sub is_master_of { my $cxn_dbh = $cxn->dbh; local $cxn_dbh->{FetchHashKeyName} = 'NAME_lc'; - my $slave_status = $cxn_dbh->selectrow_hashref(q{SHOW SLAVE STATUS}); + my $sql = q{SHOW SLAVE STATUS}; + PTDEBUG && _d($sql); + my $slave_status = $cxn_dbh->selectrow_hashref($sql); return unless ref($slave_status) eq 'HASH'; - my $port = $self->dsn->{P}; - my $host = $self->dsn->{h}; - return 1 if $slave_status->{master_host} eq $host - && $slave_status->{master_port} eq $port; + my $port = $self->dsn->{P}; + return unless $slave_status->{master_port} eq $port; + return 1 if $self->dsn->{h} eq $slave_status->{master_host}; + + # They might be the same but in different format + my $host = scalar gethostbyname($self->dsn->{h}); + my $master_host = scalar gethostbyname($slave_status->{master_host}); + return 1 if $master_host eq $host; + return; } sub _find_full_gcomm_addr { diff --git a/t/lib/Cxn.t b/t/lib/Cxn.t index c644919e..eae15ac6 100644 --- a/t/lib/Cxn.t +++ b/t/lib/Cxn.t @@ -276,6 +276,11 @@ SKIP: { $cxn1->is_cluster_node(), "is_cluster_node works correctly for cluster nodes" ); + + ok( + !$cxn->is_master_of($cxn1), + "->is_master_of works correctly for a server unrelated to a cluster" + ); diag("Setting node as a slave of master1"); $sb->set_as_slave($node, "master1"); @@ -292,7 +297,7 @@ SKIP: { "->same_cluster works for master -> cluster" ); diag("Restarting the cluster"); - $sb->stop_sandbox($node); + diag($sb->stop_sandbox($node)); ($node) = $sb->start_cluster(cluster_size => 1); $cxn1 = make_cxn( dsn_string => $sb->dsn_for($node) ); $cxn1->connect(); @@ -391,5 +396,5 @@ diag($sb->stop_sandbox("master1")); # ############################################################################# $master_dbh->disconnect() if $master_dbh; ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); -done_testing +done_testing; exit; diff --git a/t/pt-table-checksum/bugs.t b/t/pt-table-checksum/bugs.t index 635c1365..0dcac017 100644 --- a/t/pt-table-checksum/bugs.t +++ b/t/pt-table-checksum/bugs.t @@ -214,18 +214,20 @@ SKIP: { diag("Creating a slave for $node2..."); { local $ENV{BINLOG_FORMAT} = 'ROW'; - $sb->start_sandbox("slave", $node2_slave, $node2); + diag($sb->start_sandbox("slave", $node2_slave, $node2)); } my $node_slave_dbh = $sb->get_dbh_for($node2_slave); make_dbh_differ($node2_dbh); # And make its slave differ as well + PerconaTest::wait_for_table($sb->get_dbh_for($nodes[-1]), "bug_1062563.ptc_pxc"); PerconaTest::wait_for_table($node_slave_dbh, "bug_1062563.ptc_pxc"); $node_slave_dbh->do("INSERT INTO bug_1062563.ptc_pxc (i) VALUES ($_)") for 3, 4; my $dsns_table_sql = catfile(qw(t lib samples MasterSlave dsn_table.sql)); $sb->load_file($node2, $dsns_table_sql, undef, no_wait => 1); + $node2_dbh->do("DELETE FROM dsn_t.dsns"); # Delete 12346 my $sth = $node2_dbh->prepare("INSERT INTO dsn_t.dsns VALUES (null, null, ?)"); for my $dsn ( map { $sb->dsn_for($_) } @nodes[0,2..$#nodes], $node2_slave ) { $sth->execute($dsn); @@ -245,16 +247,15 @@ SKIP: { PerconaTest::count_checksum_results($output, 'diffs'), 1, "Bug 1062563: Detects diffs between PXC nodes" - ); - + ) or diag($output); + my @cluster_nodes = $output =~ /(because it is a cluster node)/g; is( scalar(@cluster_nodes), 4, "Skips all the cluster nodes in the dsns table" ) or diag($output); - - + # Now try with just the slave $node2_dbh->do("DELETE FROM dsn_t.dsns"); @@ -295,11 +296,14 @@ SKIP: { make_dbh_differ($cluster1_dbh); # And make its slave differ as well + PerconaTest::wait_for_table($sb->get_dbh_for($cluster2[-1]), "bug_1062563.ptc_pxc"); + PerconaTest::wait_for_table($sb->get_dbh_for($cluster1[-1]), "bug_1062563.ptc_pxc"); PerconaTest::wait_for_table($cluster2_dbh, "bug_1062563.ptc_pxc"); $cluster2_dbh->do("INSERT INTO bug_1062563.ptc_pxc (i) VALUES ($_)") for 3, 4; $dsns_table_sql = catfile(qw(t lib samples MasterSlave dsn_table.sql)); $sb->load_file($cluster1[0], $dsns_table_sql, undef, no_wait => 1); + $cluster1_dbh->do("DELETE FROM dsn_t.dsns"); # Delete 12346 $sth = $cluster1_dbh->prepare("INSERT INTO dsn_t.dsns VALUES (null, null, ?)"); for my $dsn ( map { $sb->dsn_for($_) } @cluster1[1..$#cluster1], $cluster2[0] ) { $sth->execute($dsn); @@ -320,7 +324,7 @@ SKIP: { PerconaTest::count_checksum_results($output, 'diffs'), 1, "Bug 1062563: Detects diffs between PXC nodes when cluster -> cluster" - ); + ) or diag($output); like( $output,