Merge lp:~percona-toolkit-dev/percona-toolkit/fix-1062563-1063912-ptc-pxc-bugs into lp:percona-toolkit/2.1
- fix-1062563-1063912-ptc-pxc-bugs
- Merge into 2.1
Status: | Superseded |
---|---|
Proposed branch: | lp:~percona-toolkit-dev/percona-toolkit/fix-1062563-1063912-ptc-pxc-bugs |
Merge into: | lp:percona-toolkit/2.1 |
Diff against target: |
1196 lines (+834/-103) 10 files modified
bin/pt-config-diff (+1/-15) bin/pt-kill (+9/-19) bin/pt-online-schema-change (+9/-19) bin/pt-table-checksum (+144/-25) lib/Cxn.pm (+1/-15) lib/Percona/XtraDB/Cluster.pm (+123/-0) lib/Sandbox.pm (+85/-4) t/lib/Cxn.t (+4/-6) t/lib/Percona/XtraDB/Cluster.t (+216/-0) t/pt-table-checksum/pxc.t (+242/-0) |
To merge this branch: | bzr merge lp:~percona-toolkit-dev/percona-toolkit/fix-1062563-1063912-ptc-pxc-bugs |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Nichter | Needs Fixing | ||
Review via email: mp+130191@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-11-08.
Commit message
Description of the change
- 417. By Daniel Nichter
-
Merge fix-pt-
upgrade- select-bug-1060774 - 418. By Daniel Nichter
-
Merge fix-938068-
ptc-slave- binlog- formats - 419. By Daniel Nichter
-
Merge fix-978133-
remove- pqd-priv- checks - 420. By Daniel Nichter
-
Redirect sys cmd 2>/dev/null in pt-kill tests to avoid false-positive errors.
- 421. By Daniel Nichter
-
Fix RawLogParser.t. Use diag in PerconaTest.pm.
- 422. By Daniel Nichter
-
Remove all_privs tests. Update Percona:
:Toolkit: :VERSION. - 423. By Daniel Nichter
-
Make CompareResults.t stable--yet another case of not waiting for replication.
- 424. By Daniel Nichter
-
Merge fix-pt-osc-del-trg-bug-1062324.
- 425. By Daniel Nichter
-
Merge opt-parsing-
exit-status-bug-1039074. - 426. By Daniel Nichter
-
Merge quiet-progress-bug-1039541.
- 427. By Daniel Nichter
-
Merge pdl-partitions-bug-1043528.
- 428. By Daniel Nichter
-
Merge pt-stalk-iter-1-bug-1070434.
- 429. By Daniel Nichter
-
Merge find_my_cnf_file-bug-1070916.
- 430. By Daniel Nichter
-
Remove $Sandbox:
:Percona: :Toolkit: :VERSION and use $Percona: :Toolkit: :VERSION instead since it's the authoritative version. - 431. By Daniel Nichter
-
Add deprecation notice to pt-log-player for PT 2.2.
- 432. By Daniel Nichter
-
Fix t/pt-slave-
delay/auto_ restart. t and use direct call, no backticks. - 433. By Daniel Nichter
-
Don't use literal values for t/pt-heartbeat/
basics. t 'It is being updated' test. Use direct call rather than backticks. - 434. By Daniel Nichter
-
Make pt-archiver --sleep tests more precise and reliable.
- 435. By Daniel Nichter
-
Merge fix-ptc-
slave-binglog- formats- on-5.0. - 436. By Daniel Nichter
-
Merge pt-find-docu-bug-1013407
- 437. By Daniel Nichter
-
Merge fix-995896-
cat-in- daemon - 438. By Brian Fraser
-
Merged fix-821715-
enable- local-infile- in-dsn - 439. By Brian Fraser
-
Merged fix-1052722-
pt-fifo- split-n- minus-1- rows-initially - 440. By Brian Fraser
-
Updated modules in all tools
Daniel Nichter (daniel-nichter) wrote : | # |
Brian Fraser (fraserbn) wrote : | # |
->start_sandbox, ->stop_sandbox and ->port_for are pseudo-vestigial (they are wrappers that aren't needed, but I find ->start_
set_as_slave and start_cluster are there mostly for convenience and brevity.
But since they are all ultimately wrappers around the sandbox/ scripts, sure, it could be done.
- 441. By Daniel Nichter
-
Merge fix-938660-
ptc-chunk- size-limit- 0 - 442. By Daniel Nichter
-
Merge pt-show-
grant-col- privs-bug-866075 - 443. By Brian Fraser
-
Merged fix-1059732-
ptc-hash- functions - 444. By Brian Fraser
-
bin/pt-
table-checksum: Missing word in an error message - 445. By Daniel Nichter
-
Merge fix-1009510-
1039569- ptc-check- table-on- replicas - 446. By Daniel Nichter
-
Merged fix-i26211-
1058285- 821722- implicit- ansi_quotes
Daniel Nichter (daniel-nichter) wrote : | # |
The PXC code in Cxn.pm doesn't seem to belong there. Let's move it and its tests to separate files, i.e. Percona/
- 447. By Brian Fraser
-
Merged fix-1073532-
Mo-Scalar- Util-PP - 448. By Brian Fraser
-
Merged sandbox-
get_dbh_ for-fix - 449. By Brian Fraser
-
Removed the L option from the dsn_opts exported by PerconaTest, as it was useless and breaking tests, and added an L=1 to a leftover pt-archiver --bulk-insert call
- 450. By Daniel Nichter
-
Merge fix-pt-fel-bug-1075773
- 451. By Brian Fraser
-
Merged fix-1062563-
1063912- ptc-pxc- bugs and resolved conflicts, added the missing Percona: :XtraDB: :Cluster file - 452. By Brian Fraser
-
Reverted a few unnecessary changes
- 453. By Brian Fraser
-
Split the Percona:
:XtraDB: :Cluster tests in two files: One that requires a PXC sandbox, and a general tests file
Unmerged revisions
Preview Diff
1 | === modified file 'bin/pt-config-diff' | |||
2 | --- bin/pt-config-diff 2012-10-31 09:18:34 +0000 | |||
3 | +++ bin/pt-config-diff 2012-11-08 20:42:20 +0000 | |||
4 | @@ -1466,6 +1466,7 @@ | |||
5 | 1466 | use warnings FATAL => 'all'; | 1466 | use warnings FATAL => 'all'; |
6 | 1467 | use English qw(-no_match_vars); | 1467 | use English qw(-no_match_vars); |
7 | 1468 | use Scalar::Util qw(blessed); | 1468 | use Scalar::Util qw(blessed); |
8 | 1469 | |||
9 | 1469 | use constant { | 1470 | use constant { |
10 | 1470 | PTDEBUG => $ENV{PTDEBUG} || 0, | 1471 | PTDEBUG => $ENV{PTDEBUG} || 0, |
11 | 1471 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, | 1472 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, |
12 | @@ -1572,21 +1573,6 @@ | |||
13 | 1572 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; | 1573 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; |
14 | 1573 | } | 1574 | } |
15 | 1574 | 1575 | ||
16 | 1575 | sub is_cluster_node { | ||
17 | 1576 | my ($self) = @_; | ||
18 | 1577 | return $self->{is_cluster_node} if defined $self->{is_cluster_node}; | ||
19 | 1578 | |||
20 | 1579 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
21 | 1580 | PTDEBUG && _d($sql); | ||
22 | 1581 | my $row = $self->{dbh}->selectrow_arrayref($sql); | ||
23 | 1582 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
24 | 1583 | $self->{is_cluster_node} = $row && $row->[1] | ||
25 | 1584 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
26 | 1585 | : 0; | ||
27 | 1586 | |||
28 | 1587 | return $self->{is_cluster_node}; | ||
29 | 1588 | } | ||
30 | 1589 | |||
31 | 1590 | sub DESTROY { | 1576 | sub DESTROY { |
32 | 1591 | my ($self) = @_; | 1577 | my ($self) = @_; |
33 | 1592 | if ( $self->{dbh} | 1578 | if ( $self->{dbh} |
34 | 1593 | 1579 | ||
35 | === modified file 'bin/pt-kill' | |||
36 | --- bin/pt-kill 2012-11-07 07:12:37 +0000 | |||
37 | +++ bin/pt-kill 2012-11-08 20:42:20 +0000 | |||
38 | @@ -2478,16 +2478,20 @@ | |||
39 | 2478 | $Data::Dumper::Sortkeys = 1; | 2478 | $Data::Dumper::Sortkeys = 1; |
40 | 2479 | $Data::Dumper::Quotekeys = 0; | 2479 | $Data::Dumper::Quotekeys = 0; |
41 | 2480 | 2480 | ||
42 | 2481 | local $EVAL_ERROR; | ||
43 | 2482 | eval { | ||
44 | 2483 | require Quoter; | ||
45 | 2484 | }; | ||
46 | 2485 | |||
47 | 2481 | sub new { | 2486 | sub new { |
48 | 2482 | my ( $class, %args ) = @_; | 2487 | my ( $class, %args ) = @_; |
49 | 2483 | my @required_args = qw(Quoter); | ||
50 | 2484 | foreach my $arg ( @required_args ) { | ||
51 | 2485 | die "I need a $arg argument" unless $args{$arg}; | ||
52 | 2486 | } | ||
53 | 2487 | my $self = { %args }; | 2488 | my $self = { %args }; |
54 | 2489 | $self->{Quoter} ||= Quoter->new(); | ||
55 | 2488 | return bless $self, $class; | 2490 | return bless $self, $class; |
56 | 2489 | } | 2491 | } |
57 | 2490 | 2492 | ||
58 | 2493 | sub Quoter { shift->{Quoter} } | ||
59 | 2494 | |||
60 | 2491 | sub get_create_table { | 2495 | sub get_create_table { |
61 | 2492 | my ( $self, $dbh, $db, $tbl ) = @_; | 2496 | my ( $self, $dbh, $db, $tbl ) = @_; |
62 | 2493 | die "I need a dbh parameter" unless $dbh; | 2497 | die "I need a dbh parameter" unless $dbh; |
63 | @@ -4711,6 +4715,7 @@ | |||
64 | 4711 | use warnings FATAL => 'all'; | 4715 | use warnings FATAL => 'all'; |
65 | 4712 | use English qw(-no_match_vars); | 4716 | use English qw(-no_match_vars); |
66 | 4713 | use Scalar::Util qw(blessed); | 4717 | use Scalar::Util qw(blessed); |
67 | 4718 | |||
68 | 4714 | use constant { | 4719 | use constant { |
69 | 4715 | PTDEBUG => $ENV{PTDEBUG} || 0, | 4720 | PTDEBUG => $ENV{PTDEBUG} || 0, |
70 | 4716 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, | 4721 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, |
71 | @@ -4817,21 +4822,6 @@ | |||
72 | 4817 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; | 4822 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; |
73 | 4818 | } | 4823 | } |
74 | 4819 | 4824 | ||
75 | 4820 | sub is_cluster_node { | ||
76 | 4821 | my ($self) = @_; | ||
77 | 4822 | return $self->{is_cluster_node} if defined $self->{is_cluster_node}; | ||
78 | 4823 | |||
79 | 4824 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
80 | 4825 | PTDEBUG && _d($sql); | ||
81 | 4826 | my $row = $self->{dbh}->selectrow_arrayref($sql); | ||
82 | 4827 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
83 | 4828 | $self->{is_cluster_node} = $row && $row->[1] | ||
84 | 4829 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
85 | 4830 | : 0; | ||
86 | 4831 | |||
87 | 4832 | return $self->{is_cluster_node}; | ||
88 | 4833 | } | ||
89 | 4834 | |||
90 | 4835 | sub DESTROY { | 4825 | sub DESTROY { |
91 | 4836 | my ($self) = @_; | 4826 | my ($self) = @_; |
92 | 4837 | if ( $self->{dbh} | 4827 | if ( $self->{dbh} |
93 | 4838 | 4828 | ||
94 | === modified file 'bin/pt-online-schema-change' | |||
95 | --- bin/pt-online-schema-change 2012-11-07 07:12:37 +0000 | |||
96 | +++ bin/pt-online-schema-change 2012-11-08 20:42:20 +0000 | |||
97 | @@ -2712,16 +2712,20 @@ | |||
98 | 2712 | $Data::Dumper::Sortkeys = 1; | 2712 | $Data::Dumper::Sortkeys = 1; |
99 | 2713 | $Data::Dumper::Quotekeys = 0; | 2713 | $Data::Dumper::Quotekeys = 0; |
100 | 2714 | 2714 | ||
101 | 2715 | local $EVAL_ERROR; | ||
102 | 2716 | eval { | ||
103 | 2717 | require Quoter; | ||
104 | 2718 | }; | ||
105 | 2719 | |||
106 | 2715 | sub new { | 2720 | sub new { |
107 | 2716 | my ( $class, %args ) = @_; | 2721 | my ( $class, %args ) = @_; |
108 | 2717 | my @required_args = qw(Quoter); | ||
109 | 2718 | foreach my $arg ( @required_args ) { | ||
110 | 2719 | die "I need a $arg argument" unless $args{$arg}; | ||
111 | 2720 | } | ||
112 | 2721 | my $self = { %args }; | 2722 | my $self = { %args }; |
113 | 2723 | $self->{Quoter} ||= Quoter->new(); | ||
114 | 2722 | return bless $self, $class; | 2724 | return bless $self, $class; |
115 | 2723 | } | 2725 | } |
116 | 2724 | 2726 | ||
117 | 2727 | sub Quoter { shift->{Quoter} } | ||
118 | 2728 | |||
119 | 2725 | sub get_create_table { | 2729 | sub get_create_table { |
120 | 2726 | my ( $self, $dbh, $db, $tbl ) = @_; | 2730 | my ( $self, $dbh, $db, $tbl ) = @_; |
121 | 2727 | die "I need a dbh parameter" unless $dbh; | 2731 | die "I need a dbh parameter" unless $dbh; |
122 | @@ -3341,6 +3345,7 @@ | |||
123 | 3341 | use warnings FATAL => 'all'; | 3345 | use warnings FATAL => 'all'; |
124 | 3342 | use English qw(-no_match_vars); | 3346 | use English qw(-no_match_vars); |
125 | 3343 | use Scalar::Util qw(blessed); | 3347 | use Scalar::Util qw(blessed); |
126 | 3348 | |||
127 | 3344 | use constant { | 3349 | use constant { |
128 | 3345 | PTDEBUG => $ENV{PTDEBUG} || 0, | 3350 | PTDEBUG => $ENV{PTDEBUG} || 0, |
129 | 3346 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, | 3351 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, |
130 | @@ -3447,21 +3452,6 @@ | |||
131 | 3447 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; | 3452 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; |
132 | 3448 | } | 3453 | } |
133 | 3449 | 3454 | ||
134 | 3450 | sub is_cluster_node { | ||
135 | 3451 | my ($self) = @_; | ||
136 | 3452 | return $self->{is_cluster_node} if defined $self->{is_cluster_node}; | ||
137 | 3453 | |||
138 | 3454 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
139 | 3455 | PTDEBUG && _d($sql); | ||
140 | 3456 | my $row = $self->{dbh}->selectrow_arrayref($sql); | ||
141 | 3457 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
142 | 3458 | $self->{is_cluster_node} = $row && $row->[1] | ||
143 | 3459 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
144 | 3460 | : 0; | ||
145 | 3461 | |||
146 | 3462 | return $self->{is_cluster_node}; | ||
147 | 3463 | } | ||
148 | 3464 | |||
149 | 3465 | sub DESTROY { | 3455 | sub DESTROY { |
150 | 3466 | my ($self) = @_; | 3456 | my ($self) = @_; |
151 | 3467 | if ( $self->{dbh} | 3457 | if ( $self->{dbh} |
152 | 3468 | 3458 | ||
153 | === modified file 'bin/pt-table-checksum' | |||
154 | --- bin/pt-table-checksum 2012-11-07 07:12:37 +0000 | |||
155 | +++ bin/pt-table-checksum 2012-11-08 20:42:20 +0000 | |||
156 | @@ -21,6 +21,7 @@ | |||
157 | 21 | OptionParser | 21 | OptionParser |
158 | 22 | Mo | 22 | Mo |
159 | 23 | Cxn | 23 | Cxn |
160 | 24 | Percona::XtraDB::Cluster | ||
161 | 24 | Quoter | 25 | Quoter |
162 | 25 | VersionParser | 26 | VersionParser |
163 | 26 | TableParser | 27 | TableParser |
164 | @@ -3211,6 +3212,7 @@ | |||
165 | 3211 | use warnings FATAL => 'all'; | 3212 | use warnings FATAL => 'all'; |
166 | 3212 | use English qw(-no_match_vars); | 3213 | use English qw(-no_match_vars); |
167 | 3213 | use Scalar::Util qw(blessed); | 3214 | use Scalar::Util qw(blessed); |
168 | 3215 | |||
169 | 3214 | use constant { | 3216 | use constant { |
170 | 3215 | PTDEBUG => $ENV{PTDEBUG} || 0, | 3217 | PTDEBUG => $ENV{PTDEBUG} || 0, |
171 | 3216 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, | 3218 | PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, |
172 | @@ -3317,21 +3319,6 @@ | |||
173 | 3317 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; | 3319 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; |
174 | 3318 | } | 3320 | } |
175 | 3319 | 3321 | ||
176 | 3320 | sub is_cluster_node { | ||
177 | 3321 | my ($self) = @_; | ||
178 | 3322 | return $self->{is_cluster_node} if defined $self->{is_cluster_node}; | ||
179 | 3323 | |||
180 | 3324 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
181 | 3325 | PTDEBUG && _d($sql); | ||
182 | 3326 | my $row = $self->{dbh}->selectrow_arrayref($sql); | ||
183 | 3327 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
184 | 3328 | $self->{is_cluster_node} = $row && $row->[1] | ||
185 | 3329 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
186 | 3330 | : 0; | ||
187 | 3331 | |||
188 | 3332 | return $self->{is_cluster_node}; | ||
189 | 3333 | } | ||
190 | 3334 | |||
191 | 3335 | sub DESTROY { | 3322 | sub DESTROY { |
192 | 3336 | my ($self) = @_; | 3323 | my ($self) = @_; |
193 | 3337 | if ( $self->{dbh} | 3324 | if ( $self->{dbh} |
194 | @@ -3358,6 +3345,104 @@ | |||
195 | 3358 | # ########################################################################### | 3345 | # ########################################################################### |
196 | 3359 | 3346 | ||
197 | 3360 | # ########################################################################### | 3347 | # ########################################################################### |
198 | 3348 | # Percona::XtraDB::Cluster package | ||
199 | 3349 | # This package is a copy without comments from the original. The original | ||
200 | 3350 | # with comments and its test file can be found in the Bazaar repository at, | ||
201 | 3351 | # lib/Percona/XtraDB/Cluster.pm | ||
202 | 3352 | # t/lib/Percona/XtraDB/Cluster.t | ||
203 | 3353 | # See https://launchpad.net/percona-toolkit for more information. | ||
204 | 3354 | # ########################################################################### | ||
205 | 3355 | { | ||
206 | 3356 | |||
207 | 3357 | package Percona::XtraDB::Cluster; | ||
208 | 3358 | use Mo; | ||
209 | 3359 | use constant PTDEBUG => $ENV{PTDEBUG} || 0; | ||
210 | 3360 | |||
211 | 3361 | sub is_cluster_node { | ||
212 | 3362 | my ($self, $cxn) = @_; | ||
213 | 3363 | return $self->{is_cluster_node}->{$cxn} if defined $self->{is_cluster_node}->{$cxn}; | ||
214 | 3364 | |||
215 | 3365 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
216 | 3366 | PTDEBUG && _d($sql); | ||
217 | 3367 | my $row = $cxn->dbh->selectrow_arrayref($sql); | ||
218 | 3368 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
219 | 3369 | $self->{is_cluster_node}->{$cxn} = $row && $row->[1] | ||
220 | 3370 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
221 | 3371 | : 0; | ||
222 | 3372 | |||
223 | 3373 | return $self->{is_cluster_node}->{$cxn}; | ||
224 | 3374 | } | ||
225 | 3375 | |||
226 | 3376 | sub same_cluster { | ||
227 | 3377 | my ($self, $cxn1, $cxn2) = @_; | ||
228 | 3378 | return unless $self->is_cluster_node($cxn1) && $self->is_cluster_node($cxn2); | ||
229 | 3379 | return if $self->is_master_of($cxn1, $cxn2) || $self->is_master_of($cxn2, $cxn1); | ||
230 | 3380 | |||
231 | 3381 | my $sql = q{SHOW VARIABLES LIKE 'wsrep_cluster_name'}; | ||
232 | 3382 | PTDEBUG && _d($sql); | ||
233 | 3383 | my (undef, $row) = $cxn1->dbh->selectrow_array($sql); | ||
234 | 3384 | my (undef, $cxn2_row) = $cxn2->dbh->selectrow_array($sql); | ||
235 | 3385 | |||
236 | 3386 | return unless $row eq $cxn2_row; | ||
237 | 3387 | |||
238 | 3388 | $sql = q{SHOW VARIABLES LIKE 'wsrep_cluster_address'}; | ||
239 | 3389 | PTDEBUG && _d($sql); | ||
240 | 3390 | my (undef, $addr) = $cxn1->dbh->selectrow_array($sql); | ||
241 | 3391 | my (undef, $cxn2_addr) = $cxn2->dbh->selectrow_array($sql); | ||
242 | 3392 | |||
243 | 3393 | return if $addr eq 'gcomm://' && $cxn2_addr eq 'gcomm://'; | ||
244 | 3394 | |||
245 | 3395 | if ( $addr eq 'gcomm://' ) { | ||
246 | 3396 | $addr = $self->_find_full_gcomm_addr($cxn1->dbh); | ||
247 | 3397 | } | ||
248 | 3398 | elsif ( $cxn2_addr eq 'gcomm://' ) { | ||
249 | 3399 | $cxn2_addr = $self->_find_full_gcomm_addr($cxn2->dbh); | ||
250 | 3400 | } | ||
251 | 3401 | |||
252 | 3402 | return 1 if lc($addr) eq lc($cxn2_addr); | ||
253 | 3403 | |||
254 | 3404 | return 1; | ||
255 | 3405 | } | ||
256 | 3406 | |||
257 | 3407 | sub is_master_of { | ||
258 | 3408 | my ($self, $cxn1, $cxn2) = @_; | ||
259 | 3409 | |||
260 | 3410 | my $cxn2_dbh = $cxn2->dbh; | ||
261 | 3411 | my $sql = q{SHOW SLAVE STATUS}; | ||
262 | 3412 | PTDEBUG && _d($sql); | ||
263 | 3413 | local $cxn2_dbh->{FetchHashKeyName} = 'NAME_lc'; | ||
264 | 3414 | my $slave_status = $cxn2_dbh->selectrow_hashref($sql); | ||
265 | 3415 | return unless ref($slave_status) eq 'HASH'; | ||
266 | 3416 | |||
267 | 3417 | my $port = $cxn1->dsn->{P}; | ||
268 | 3418 | return unless $slave_status->{master_port} eq $port; | ||
269 | 3419 | return 1 if $cxn1->dsn->{h} eq $slave_status->{master_host}; | ||
270 | 3420 | |||
271 | 3421 | my $host = scalar gethostbyname($cxn1->dsn->{h}); | ||
272 | 3422 | my $master_host = scalar gethostbyname($slave_status->{master_host}); | ||
273 | 3423 | return 1 if $master_host eq $host; | ||
274 | 3424 | return; | ||
275 | 3425 | } | ||
276 | 3426 | |||
277 | 3427 | sub _find_full_gcomm_addr { | ||
278 | 3428 | my ($self, $dbh) = @_; | ||
279 | 3429 | |||
280 | 3430 | my $sql = q{SHOW VARIABLES LIKE 'wsrep_provider_options'}; | ||
281 | 3431 | PTDEBUG && _d($sql); | ||
282 | 3432 | my (undef, $provider_opts) = $dbh->selectrow_array($sql); | ||
283 | 3433 | my ($prov_addr) = $provider_opts =~ m{\Qgmcast.listen_addr\E\s*=\s*tcp://([^:]+:[0-9]+)\s*;}i; | ||
284 | 3434 | my $full_gcomm = "gcomm://$prov_addr"; | ||
285 | 3435 | PTDEBUG && _d("gcomm address: ", $full_gcomm); | ||
286 | 3436 | return $full_gcomm; | ||
287 | 3437 | } | ||
288 | 3438 | |||
289 | 3439 | 1; | ||
290 | 3440 | } | ||
291 | 3441 | # ########################################################################### | ||
292 | 3442 | # End Percona::XtraDB::Cluster package | ||
293 | 3443 | # ########################################################################### | ||
294 | 3444 | |||
295 | 3445 | # ########################################################################### | ||
296 | 3361 | # Quoter package | 3446 | # Quoter package |
297 | 3362 | # This package is a copy without comments from the original. The original | 3447 | # This package is a copy without comments from the original. The original |
298 | 3363 | # with comments and its test file can be found in the Bazaar repository at, | 3448 | # with comments and its test file can be found in the Bazaar repository at, |
299 | @@ -5281,7 +5366,7 @@ | |||
300 | 5281 | } | 5366 | } |
301 | 5282 | my ($dbh) = @args{@required_args}; | 5367 | my ($dbh) = @args{@required_args}; |
302 | 5283 | my $o = $self->{OptionParser}; | 5368 | my $o = $self->{OptionParser}; |
304 | 5284 | my @funcs = qw(CRC32 FNV1A_64 FNV_64 MD5 SHA1); | 5369 | my @funcs = qw(CRC32 FNV1A_64 FNV_64 MURMUR_HASH MD5 SHA1); |
305 | 5285 | 5370 | ||
306 | 5286 | if ( my $func = $o->get('function') ) { | 5371 | if ( my $func = $o->get('function') ) { |
307 | 5287 | unshift @funcs, $func; | 5372 | unshift @funcs, $func; |
308 | @@ -5302,7 +5387,7 @@ | |||
309 | 5302 | PTDEBUG && _d('Chosen hash func:', $result); | 5387 | PTDEBUG && _d('Chosen hash func:', $result); |
310 | 5303 | return $func; | 5388 | return $func; |
311 | 5304 | } | 5389 | } |
313 | 5305 | die $error || 'No hash functions (CRC32, MD5, etc.) are available'; | 5390 | die($error || 'No hash functions (CRC32, MD5, etc.) are available'); |
314 | 5306 | } | 5391 | } |
315 | 5307 | 5392 | ||
316 | 5308 | sub _get_crc_width { | 5393 | sub _get_crc_width { |
317 | @@ -8535,6 +8620,9 @@ | |||
318 | 8535 | $have_time = sub { return 1; }; | 8620 | $have_time = sub { return 1; }; |
319 | 8536 | } | 8621 | } |
320 | 8537 | 8622 | ||
321 | 8623 | # PXC helper class | ||
322 | 8624 | my $cluster = Percona::XtraDB::Cluster->new(); | ||
323 | 8625 | |||
324 | 8538 | # ######################################################################## | 8626 | # ######################################################################## |
325 | 8539 | # If this is not a dry run (--explain was not specified), then we're | 8627 | # If this is not a dry run (--explain was not specified), then we're |
326 | 8540 | # going to checksum the tables, so do the necessary preparations and | 8628 | # going to checksum the tables, so do the necessary preparations and |
327 | @@ -8604,12 +8692,42 @@ | |||
328 | 8604 | die $err if $err; | 8692 | die $err if $err; |
329 | 8605 | } | 8693 | } |
330 | 8606 | 8694 | ||
337 | 8607 | if ( $master_cxn->is_cluster_node() && !@$slaves ) { | 8695 | if ( $cluster->is_cluster_node($master_cxn) ) { |
338 | 8608 | die $master_cxn->name() . " is a cluster node but no other nodes " | 8696 | if ( !@$slaves ) { |
339 | 8609 | . "or regular replicas were found. Use --recursion-method=dsn " | 8697 | die $master_cxn->name() . " is a cluster node but no other nodes " |
340 | 8610 | . "to specify the other nodes in the cluster.\n"; | 8698 | . "or regular replicas were found. Use --recursion-method=dsn " |
341 | 8611 | } | 8699 | . "to specify the other nodes in the cluster.\n"; |
342 | 8612 | 8700 | } | |
343 | 8701 | else { | ||
344 | 8702 | my $err = ''; | ||
345 | 8703 | for my $slave (@$slaves) { | ||
346 | 8704 | if ( $cluster->is_cluster_node($slave) | ||
347 | 8705 | && !$cluster->same_cluster($slave, $master_cxn) ) { | ||
348 | 8706 | $err .= $slave->name() . " is a cluster node, but doesn't " | ||
349 | 8707 | . "belong to the same cluster as " . $master_cxn->name() | ||
350 | 8708 | . ". This is not currently supported; You can try " | ||
351 | 8709 | . "using --recursion-method=dsn to specify all nodes " | ||
352 | 8710 | . "in the slave cluster.\n" | ||
353 | 8711 | } | ||
354 | 8712 | } | ||
355 | 8713 | warn $err if $err; | ||
356 | 8714 | } | ||
357 | 8715 | } | ||
358 | 8716 | elsif ( @$slaves ) { | ||
359 | 8717 | my $err = ''; | ||
360 | 8718 | for my $slave (@$slaves) { | ||
361 | 8719 | if ( $cluster->is_cluster_node($slave) ) { | ||
362 | 8720 | $err .= $slave->name() . " is a cluster node, but " | ||
363 | 8721 | . $master_cxn->name() . " is not. This is not currently " | ||
364 | 8722 | . "supported; You can try to specify " | ||
365 | 8723 | . "all nodes in the cluster with " | ||
366 | 8724 | . "--recursion-method=dsn if you want them checksummed.\n" | ||
367 | 8725 | } | ||
368 | 8726 | } | ||
369 | 8727 | warn $err if $err; | ||
370 | 8728 | } | ||
371 | 8729 | |||
372 | 8730 | |||
373 | 8613 | if ( $o->get('check-slave-lag') ) { | 8731 | if ( $o->get('check-slave-lag') ) { |
374 | 8614 | PTDEBUG && _d('Will use --check-slave-lag to check for slave lag'); | 8732 | PTDEBUG && _d('Will use --check-slave-lag to check for slave lag'); |
375 | 8615 | my $cxn = $make_cxn->( | 8733 | my $cxn = $make_cxn->( |
376 | @@ -8629,7 +8747,8 @@ | |||
377 | 8629 | # to appear should be sufficient. | 8747 | # to appear should be sufficient. |
378 | 8630 | @$slave_lag_cxns = grep { | 8748 | @$slave_lag_cxns = grep { |
379 | 8631 | my $slave_cxn = $_; | 8749 | my $slave_cxn = $_; |
381 | 8632 | if ( $slave_cxn->is_cluster_node() ) { | 8750 | if ( $cluster->is_cluster_node($slave_cxn) |
382 | 8751 | && $cluster->same_cluster($master_cxn, $slave_cxn) ) { | ||
383 | 8633 | warn "Not checking replica lag on " . $slave_cxn->name() | 8752 | warn "Not checking replica lag on " . $slave_cxn->name() |
384 | 8634 | . " because it is a cluster node.\n"; | 8753 | . " because it is a cluster node.\n"; |
385 | 8635 | 0; | 8754 | 0; |
386 | @@ -8844,7 +8963,7 @@ | |||
387 | 8844 | . "(db, tbl, chunk, chunk_index," | 8963 | . "(db, tbl, chunk, chunk_index," |
388 | 8845 | . " lower_boundary, upper_boundary, this_cnt, this_crc) " | 8964 | . " lower_boundary, upper_boundary, this_cnt, this_crc) " |
389 | 8846 | . "SELECT" | 8965 | . "SELECT" |
391 | 8847 | . ($master_cxn->is_cluster_node() ? ' /*!99997*/' : '') | 8966 | . ($cluster->is_cluster_node($master_cxn) ? ' /*!99997*/' : '') |
392 | 8848 | . " ?, ?, ?, ?, ?, ?,"; | 8967 | . " ?, ?, ?, ?, ?, ?,"; |
393 | 8849 | my $past_cols = " COUNT(*), '0'"; | 8968 | my $past_cols = " COUNT(*), '0'"; |
394 | 8850 | 8969 | ||
395 | 8851 | 8970 | ||
396 | === modified file 'lib/Cxn.pm' | |||
397 | --- lib/Cxn.pm 2012-10-08 18:53:54 +0000 | |||
398 | +++ lib/Cxn.pm 2012-11-08 20:42:20 +0000 | |||
399 | @@ -36,6 +36,7 @@ | |||
400 | 36 | use warnings FATAL => 'all'; | 36 | use warnings FATAL => 'all'; |
401 | 37 | use English qw(-no_match_vars); | 37 | use English qw(-no_match_vars); |
402 | 38 | use Scalar::Util qw(blessed); | 38 | use Scalar::Util qw(blessed); |
403 | 39 | |||
404 | 39 | use constant { | 40 | use constant { |
405 | 40 | PTDEBUG => $ENV{PTDEBUG} || 0, | 41 | PTDEBUG => $ENV{PTDEBUG} || 0, |
406 | 41 | # Hostnames make testing less accurate. Tests need to see | 42 | # Hostnames make testing less accurate. Tests need to see |
407 | @@ -195,21 +196,6 @@ | |||
408 | 195 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; | 196 | return $self->{hostname} || $self->{dsn_name} || 'unknown host'; |
409 | 196 | } | 197 | } |
410 | 197 | 198 | ||
411 | 198 | sub is_cluster_node { | ||
412 | 199 | my ($self) = @_; | ||
413 | 200 | return $self->{is_cluster_node} if defined $self->{is_cluster_node}; | ||
414 | 201 | |||
415 | 202 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
416 | 203 | PTDEBUG && _d($sql); | ||
417 | 204 | my $row = $self->{dbh}->selectrow_arrayref($sql); | ||
418 | 205 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
419 | 206 | $self->{is_cluster_node} = $row && $row->[1] | ||
420 | 207 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
421 | 208 | : 0; | ||
422 | 209 | |||
423 | 210 | return $self->{is_cluster_node}; | ||
424 | 211 | } | ||
425 | 212 | |||
426 | 213 | sub DESTROY { | 199 | sub DESTROY { |
427 | 214 | my ($self) = @_; | 200 | my ($self) = @_; |
428 | 215 | if ( $self->{dbh} | 201 | if ( $self->{dbh} |
429 | 216 | 202 | ||
430 | === added directory 'lib/Percona/XtraDB' | |||
431 | === added file 'lib/Percona/XtraDB/Cluster.pm' | |||
432 | --- lib/Percona/XtraDB/Cluster.pm 1970-01-01 00:00:00 +0000 | |||
433 | +++ lib/Percona/XtraDB/Cluster.pm 2012-11-08 20:42:20 +0000 | |||
434 | @@ -0,0 +1,123 @@ | |||
435 | 1 | # This program is copyright 2011 Percona Inc. | ||
436 | 2 | # Feedback and improvements are welcome. | ||
437 | 3 | # | ||
438 | 4 | # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED | ||
439 | 5 | # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | ||
440 | 6 | # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
441 | 7 | # | ||
442 | 8 | # This program is free software; you can redistribute it and/or modify it under | ||
443 | 9 | # the terms of the GNU General Public License as published by the Free Software | ||
444 | 10 | # Foundation, version 2; OR the Perl Artistic License. On UNIX and similar | ||
445 | 11 | # systems, you can issue `man perlgpl' or `man perlartistic' to read these | ||
446 | 12 | # licenses. | ||
447 | 13 | # | ||
448 | 14 | # You should have received a copy of the GNU General Public License along with | ||
449 | 15 | # this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
450 | 16 | # Place, Suite 330, Boston, MA 02111-1307 USA. | ||
451 | 17 | # ########################################################################### | ||
452 | 18 | # Percona::XtraDB::Cluster package | ||
453 | 19 | # ########################################################################### | ||
454 | 20 | { | ||
455 | 21 | # Package: Percona::XtraDB::Cluster | ||
456 | 22 | # Percona::XtraDB::Cluster has helper methods to deal with Percona XtraDB Cluster | ||
457 | 23 | # based servers | ||
458 | 24 | |||
459 | 25 | package Percona::XtraDB::Cluster; | ||
460 | 26 | use Mo; | ||
461 | 27 | use constant PTDEBUG => $ENV{PTDEBUG} || 0; | ||
462 | 28 | |||
463 | 29 | sub is_cluster_node { | ||
464 | 30 | my ($self, $cxn) = @_; | ||
465 | 31 | return $self->{is_cluster_node}->{$cxn} if defined $self->{is_cluster_node}->{$cxn}; | ||
466 | 32 | |||
467 | 33 | my $sql = "SHOW VARIABLES LIKE 'wsrep_on'"; | ||
468 | 34 | PTDEBUG && _d($sql); | ||
469 | 35 | my $row = $cxn->dbh->selectrow_arrayref($sql); | ||
470 | 36 | PTDEBUG && _d(defined $row ? @$row : 'undef'); | ||
471 | 37 | $self->{is_cluster_node}->{$cxn} = $row && $row->[1] | ||
472 | 38 | ? ($row->[1] eq 'ON' || $row->[1] eq '1') | ||
473 | 39 | : 0; | ||
474 | 40 | |||
475 | 41 | return $self->{is_cluster_node}->{$cxn}; | ||
476 | 42 | } | ||
477 | 43 | |||
478 | 44 | sub same_cluster { | ||
479 | 45 | my ($self, $cxn1, $cxn2) = @_; | ||
480 | 46 | return unless $self->is_cluster_node($cxn1) && $self->is_cluster_node($cxn2); | ||
481 | 47 | return if $self->is_master_of($cxn1, $cxn2) || $self->is_master_of($cxn2, $cxn1); | ||
482 | 48 | |||
483 | 49 | my $sql = q{SHOW VARIABLES LIKE 'wsrep_cluster_name'}; | ||
484 | 50 | PTDEBUG && _d($sql); | ||
485 | 51 | my (undef, $row) = $cxn1->dbh->selectrow_array($sql); | ||
486 | 52 | my (undef, $cxn2_row) = $cxn2->dbh->selectrow_array($sql); | ||
487 | 53 | |||
488 | 54 | return unless $row eq $cxn2_row; | ||
489 | 55 | |||
490 | 56 | # Now it becomes tricky. Ostensibly clusters shouldn't have the | ||
491 | 57 | # same name, but tell that to the world. | ||
492 | 58 | $sql = q{SHOW VARIABLES LIKE 'wsrep_cluster_address'}; | ||
493 | 59 | PTDEBUG && _d($sql); | ||
494 | 60 | my (undef, $addr) = $cxn1->dbh->selectrow_array($sql); | ||
495 | 61 | my (undef, $cxn2_addr) = $cxn2->dbh->selectrow_array($sql); | ||
496 | 62 | |||
497 | 63 | # If they both have gcomm://, then they are both the first | ||
498 | 64 | # node of a cluster, so they can't be in the same one. | ||
499 | 65 | return if $addr eq 'gcomm://' && $cxn2_addr eq 'gcomm://'; | ||
500 | 66 | |||
501 | 67 | if ( $addr eq 'gcomm://' ) { | ||
502 | 68 | $addr = $self->_find_full_gcomm_addr($cxn1->dbh); | ||
503 | 69 | } | ||
504 | 70 | elsif ( $cxn2_addr eq 'gcomm://' ) { | ||
505 | 71 | $cxn2_addr = $self->_find_full_gcomm_addr($cxn2->dbh); | ||
506 | 72 | } | ||
507 | 73 | |||
508 | 74 | # Meanwhile, if they have the same address, then | ||
509 | 75 | # they are definitely part of the same cluster | ||
510 | 76 | return 1 if lc($addr) eq lc($cxn2_addr); | ||
511 | 77 | |||
512 | 78 | # However, this still leaves us with the issue that | ||
513 | 79 | # the cluster addresses could look like this: | ||
514 | 80 | # node1 -> node2, node2 -> node1, | ||
515 | 81 | # or | ||
516 | 82 | # node1 -> node2 addr, | ||
517 | 83 | # node2 -> node3 addr, | ||
518 | 84 | # node3 -> node1 addr, | ||
519 | 85 | # TODO No clue what to do here | ||
520 | 86 | return 1; | ||
521 | 87 | } | ||
522 | 88 | |||
523 | 89 | sub is_master_of { | ||
524 | 90 | my ($self, $cxn1, $cxn2) = @_; | ||
525 | 91 | |||
526 | 92 | my $cxn2_dbh = $cxn2->dbh; | ||
527 | 93 | my $sql = q{SHOW SLAVE STATUS}; | ||
528 | 94 | PTDEBUG && _d($sql); | ||
529 | 95 | local $cxn2_dbh->{FetchHashKeyName} = 'NAME_lc'; | ||
530 | 96 | my $slave_status = $cxn2_dbh->selectrow_hashref($sql); | ||
531 | 97 | return unless ref($slave_status) eq 'HASH'; | ||
532 | 98 | |||
533 | 99 | my $port = $cxn1->dsn->{P}; | ||
534 | 100 | return unless $slave_status->{master_port} eq $port; | ||
535 | 101 | return 1 if $cxn1->dsn->{h} eq $slave_status->{master_host}; | ||
536 | 102 | |||
537 | 103 | # They might be the same but in different format | ||
538 | 104 | my $host = scalar gethostbyname($cxn1->dsn->{h}); | ||
539 | 105 | my $master_host = scalar gethostbyname($slave_status->{master_host}); | ||
540 | 106 | return 1 if $master_host eq $host; | ||
541 | 107 | return; | ||
542 | 108 | } | ||
543 | 109 | |||
544 | 110 | sub _find_full_gcomm_addr { | ||
545 | 111 | my ($self, $dbh) = @_; | ||
546 | 112 | |||
547 | 113 | my $sql = q{SHOW VARIABLES LIKE 'wsrep_provider_options'}; | ||
548 | 114 | PTDEBUG && _d($sql); | ||
549 | 115 | my (undef, $provider_opts) = $dbh->selectrow_array($sql); | ||
550 | 116 | my ($prov_addr) = $provider_opts =~ m{\Qgmcast.listen_addr\E\s*=\s*tcp://([^:]+:[0-9]+)\s*;}i; | ||
551 | 117 | my $full_gcomm = "gcomm://$prov_addr"; | ||
552 | 118 | PTDEBUG && _d("gcomm address: ", $full_gcomm); | ||
553 | 119 | return $full_gcomm; | ||
554 | 120 | } | ||
555 | 121 | |||
556 | 122 | 1; | ||
557 | 123 | } | ||
558 | 0 | 124 | ||
559 | === modified file 'lib/Sandbox.pm' | |||
560 | --- lib/Sandbox.pm 2012-11-07 07:13:50 +0000 | |||
561 | +++ lib/Sandbox.pm 2012-11-08 20:42:20 +0000 | |||
562 | @@ -39,6 +39,8 @@ | |||
563 | 39 | use constant PTDEBUG => $ENV{PTDEBUG} || 0; | 39 | use constant PTDEBUG => $ENV{PTDEBUG} || 0; |
564 | 40 | use constant PTDEVDEBUG => $ENV{PTDEVDEBUG} || 0; | 40 | use constant PTDEVDEBUG => $ENV{PTDEVDEBUG} || 0; |
565 | 41 | 41 | ||
566 | 42 | use IO::Socket::INET; | ||
567 | 43 | |||
568 | 42 | my $trunk = $ENV{PERCONA_TOOLKIT_BRANCH}; | 44 | my $trunk = $ENV{PERCONA_TOOLKIT_BRANCH}; |
569 | 43 | 45 | ||
570 | 44 | my %port_for = ( | 46 | my %port_for = ( |
571 | @@ -74,7 +76,7 @@ | |||
572 | 74 | return if !defined $cmd || !$cmd; | 76 | return if !defined $cmd || !$cmd; |
573 | 75 | my $use = $self->_use_for($server) . " $cmd"; | 77 | my $use = $self->_use_for($server) . " $cmd"; |
574 | 76 | PTDEBUG && _d('"Executing', $use, 'on', $server); | 78 | PTDEBUG && _d('"Executing', $use, 'on', $server); |
576 | 77 | my $out = `$use 2>&1`; | 79 | my $out = `$use`; |
577 | 78 | if ( $? >> 8 ) { | 80 | if ( $? >> 8 ) { |
578 | 79 | die "Failed to execute $cmd on $server: $out"; | 81 | die "Failed to execute $cmd on $server: $out"; |
579 | 80 | } | 82 | } |
580 | @@ -130,7 +132,7 @@ | |||
581 | 130 | } | 132 | } |
582 | 131 | 133 | ||
583 | 132 | sub load_file { | 134 | sub load_file { |
585 | 133 | my ( $self, $server, $file, $use_db ) = @_; | 135 | my ( $self, $server, $file, $use_db, %args ) = @_; |
586 | 134 | _check_server($server); | 136 | _check_server($server); |
587 | 135 | $file = "$trunk/$file"; | 137 | $file = "$trunk/$file"; |
588 | 136 | if ( !-f $file ) { | 138 | if ( !-f $file ) { |
589 | @@ -141,11 +143,11 @@ | |||
590 | 141 | 143 | ||
591 | 142 | my $use = $self->_use_for($server) . " $d < $file"; | 144 | my $use = $self->_use_for($server) . " $d < $file"; |
592 | 143 | PTDEBUG && _d('Loading', $file, 'on', $server, ':', $use); | 145 | PTDEBUG && _d('Loading', $file, 'on', $server, ':', $use); |
594 | 144 | my $out = `$use 2>&1`; | 146 | my $out = `$use`; |
595 | 145 | if ( $? >> 8 ) { | 147 | if ( $? >> 8 ) { |
596 | 146 | die "Failed to execute $file on $server: $out"; | 148 | die "Failed to execute $file on $server: $out"; |
597 | 147 | } | 149 | } |
599 | 148 | $self->wait_for_slaves(); | 150 | $self->wait_for_slaves() unless $args{no_wait}; |
600 | 149 | } | 151 | } |
601 | 150 | 152 | ||
602 | 151 | sub _use_for { | 153 | sub _use_for { |
603 | @@ -420,6 +422,85 @@ | |||
604 | 420 | return ($output || '') =~ /1/; | 422 | return ($output || '') =~ /1/; |
605 | 421 | } | 423 | } |
606 | 422 | 424 | ||
607 | 425 | sub set_as_slave { | ||
608 | 426 | my ($self, $server, $master_server, @extras) = @_; | ||
609 | 427 | PTDEBUG && _d("Setting $server as slave of $master_server"); | ||
610 | 428 | my $master_port = $port_for{$master_server}; | ||
611 | 429 | my $sql = join ", ", qq{change master to master_host='127.0.0.1'}, | ||
612 | 430 | qq{master_user='msandbox'}, | ||
613 | 431 | qq{master_password='msandbox'}, | ||
614 | 432 | qq{master_port=$master_port}, | ||
615 | 433 | @extras; | ||
616 | 434 | for my $sql_to_run ($sql, "start slave") { | ||
617 | 435 | my $out = $self->use($server, qq{-e "$sql_to_run"}); | ||
618 | 436 | PTDEBUG && _d($out); | ||
619 | 437 | } | ||
620 | 438 | } | ||
621 | 439 | |||
622 | 440 | sub start_sandbox { | ||
623 | 441 | my ($self, $mode, $server, $master_server) = @_; | ||
624 | 442 | my $port = $port_for{$server}; | ||
625 | 443 | my $master_port = $master_server ? $port_for{$master_server} : ''; | ||
626 | 444 | my $out = `$trunk/sandbox/start-sandbox $mode $port $master_port`; | ||
627 | 445 | die $out if $CHILD_ERROR; | ||
628 | 446 | return $out; | ||
629 | 447 | } | ||
630 | 448 | |||
631 | 449 | sub stop_sandbox { | ||
632 | 450 | my ($self, @sandboxes) = @_; | ||
633 | 451 | my @ports = @port_for{@sandboxes}; | ||
634 | 452 | my $out = `$trunk/sandbox/stop-sandbox @ports`; | ||
635 | 453 | die $out if $CHILD_ERROR; | ||
636 | 454 | return $out; | ||
637 | 455 | } | ||
638 | 456 | |||
639 | 457 | sub start_cluster { | ||
640 | 458 | my ($self, %args) = @_; | ||
641 | 459 | my $cluster_size = $args{cluster_size} || 3; | ||
642 | 460 | |||
643 | 461 | my $out = ''; | ||
644 | 462 | |||
645 | 463 | my ($node1, @nodes) = map { | ||
646 | 464 | my $node_name = "node$_"; | ||
647 | 465 | $node_name = "_$node_name" while exists $port_for{$node_name}; | ||
648 | 466 | $port_for{$node_name} = $self->_get_unused_port(); | ||
649 | 467 | $node_name | ||
650 | 468 | } 1..$cluster_size; | ||
651 | 469 | |||
652 | 470 | local $ENV{CLUSTER_NAME} = $args{cluster_name} if $args{cluster_name}; | ||
653 | 471 | $self->start_sandbox("cluster", $node1); | ||
654 | 472 | for my $node ( @nodes ) { | ||
655 | 473 | $self->start_sandbox("cluster", $node, $node1); | ||
656 | 474 | } | ||
657 | 475 | |||
658 | 476 | return ($node1, @nodes); | ||
659 | 477 | } | ||
660 | 478 | |||
661 | 479 | # Lifted from Nginx::Test on CPAN | ||
662 | 480 | sub _get_unused_port { | ||
663 | 481 | my $port = 50000 + int (rand() * 5000); | ||
664 | 482 | |||
665 | 483 | while ($port++ < 64000) { | ||
666 | 484 | my $sock = IO::Socket::INET->new ( | ||
667 | 485 | Listen => 5, | ||
668 | 486 | LocalAddr => '127.0.0.1', | ||
669 | 487 | LocalPort => $port, | ||
670 | 488 | Proto => 'tcp', | ||
671 | 489 | ReuseAddr => 1 | ||
672 | 490 | ) or next; | ||
673 | 491 | |||
674 | 492 | $sock->close; | ||
675 | 493 | return $port; | ||
676 | 494 | } | ||
677 | 495 | |||
678 | 496 | die "Cannot find an open port"; | ||
679 | 497 | } | ||
680 | 498 | |||
681 | 499 | sub port_for { | ||
682 | 500 | my ($self, $server) = @_; | ||
683 | 501 | return $port_for{$server}; | ||
684 | 502 | } | ||
685 | 503 | |||
686 | 423 | 1; | 504 | 1; |
687 | 424 | } | 505 | } |
688 | 425 | # ########################################################################### | 506 | # ########################################################################### |
689 | 426 | 507 | ||
690 | === modified file 't/lib/Cxn.t' | |||
691 | --- t/lib/Cxn.t 2012-07-23 02:37:39 +0000 | |||
692 | +++ t/lib/Cxn.t 2012-11-08 20:42:20 +0000 | |||
693 | @@ -9,7 +9,8 @@ | |||
694 | 9 | use strict; | 9 | use strict; |
695 | 10 | use warnings FATAL => 'all'; | 10 | use warnings FATAL => 'all'; |
696 | 11 | use English qw(-no_match_vars); | 11 | use English qw(-no_match_vars); |
698 | 12 | use Test::More tests => 19; | 12 | use Test::More; |
699 | 13 | use Data::Dumper; | ||
700 | 13 | 14 | ||
701 | 14 | use Sandbox; | 15 | use Sandbox; |
702 | 15 | use OptionParser; | 16 | use OptionParser; |
703 | @@ -17,8 +18,7 @@ | |||
704 | 17 | use Quoter; | 18 | use Quoter; |
705 | 18 | use PerconaTest; | 19 | use PerconaTest; |
706 | 19 | use Cxn; | 20 | use Cxn; |
709 | 20 | 21 | use VersionParser; | |
708 | 21 | use Data::Dumper; | ||
710 | 22 | 22 | ||
711 | 23 | my $q = new Quoter(); | 23 | my $q = new Quoter(); |
712 | 24 | my $dp = new DSNParser(opts=>$dsn_opts); | 24 | my $dp = new DSNParser(opts=>$dsn_opts); |
713 | @@ -248,12 +248,10 @@ | |||
714 | 248 | "Default cxn inherits default connection options" | 248 | "Default cxn inherits default connection options" |
715 | 249 | ); | 249 | ); |
716 | 250 | 250 | ||
717 | 251 | @ARGV = (); | ||
718 | 252 | $o->get_opts(); | ||
719 | 253 | |||
720 | 254 | # ############################################################################# | 251 | # ############################################################################# |
721 | 255 | # Done. | 252 | # Done. |
722 | 256 | # ############################################################################# | 253 | # ############################################################################# |
723 | 257 | $master_dbh->disconnect() if $master_dbh; | 254 | $master_dbh->disconnect() if $master_dbh; |
724 | 258 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); | 255 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); |
725 | 256 | done_testing; | ||
726 | 259 | exit; | 257 | exit; |
727 | 260 | 258 | ||
728 | === added directory 't/lib/Percona' | |||
729 | === added directory 't/lib/Percona/XtraDB' | |||
730 | === added file 't/lib/Percona/XtraDB/Cluster.t' | |||
731 | --- t/lib/Percona/XtraDB/Cluster.t 1970-01-01 00:00:00 +0000 | |||
732 | +++ t/lib/Percona/XtraDB/Cluster.t 2012-11-08 20:42:20 +0000 | |||
733 | @@ -0,0 +1,216 @@ | |||
734 | 1 | #!/usr/bin/perl | ||
735 | 2 | |||
736 | 3 | BEGIN { | ||
737 | 4 | die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" | ||
738 | 5 | unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; | ||
739 | 6 | unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; | ||
740 | 7 | }; | ||
741 | 8 | |||
742 | 9 | use strict; | ||
743 | 10 | use warnings FATAL => 'all'; | ||
744 | 11 | use English qw(-no_match_vars); | ||
745 | 12 | use Test::More; | ||
746 | 13 | use Data::Dumper; | ||
747 | 14 | |||
748 | 15 | # Hostnames make testing less accurate. Tests need to see | ||
749 | 16 | # that such-and-such happened on specific slave hosts, but | ||
750 | 17 | # the sandbox servers are all on one host so all slaves have | ||
751 | 18 | # the same hostname. | ||
752 | 19 | $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1; | ||
753 | 20 | |||
754 | 21 | use Sandbox; | ||
755 | 22 | use OptionParser; | ||
756 | 23 | use DSNParser; | ||
757 | 24 | use Quoter; | ||
758 | 25 | use PerconaTest; | ||
759 | 26 | use Cxn; | ||
760 | 27 | use VersionParser; | ||
761 | 28 | |||
762 | 29 | use Percona::XtraDB::Cluster; | ||
763 | 30 | |||
764 | 31 | my $q = new Quoter(); | ||
765 | 32 | my $dp = new DSNParser(opts=>$dsn_opts); | ||
766 | 33 | my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); | ||
767 | 34 | my $master_dbh = $sb->get_dbh_for('master'); | ||
768 | 35 | |||
769 | 36 | my $cluster = Percona::XtraDB::Cluster->new(); | ||
770 | 37 | |||
771 | 38 | if ( !$master_dbh ) { | ||
772 | 39 | plan skip_all => 'Cannot connect to sandbox master'; | ||
773 | 40 | } | ||
774 | 41 | |||
775 | 42 | my $o = new OptionParser(description => 'Cxn'); | ||
776 | 43 | $o->get_specs("$trunk/bin/pt-table-checksum"); | ||
777 | 44 | $o->get_opts(); | ||
778 | 45 | $dp->prop('set-vars', $o->get('set-vars')); | ||
779 | 46 | |||
780 | 47 | sub make_cxn { | ||
781 | 48 | my (%args) = @_; | ||
782 | 49 | $o->get_opts(); | ||
783 | 50 | return new Cxn( | ||
784 | 51 | OptionParser => $o, | ||
785 | 52 | DSNParser => $dp, | ||
786 | 53 | %args, | ||
787 | 54 | ); | ||
788 | 55 | } | ||
789 | 56 | |||
790 | 57 | local @ARGV = (); | ||
791 | 58 | $o->get_opts(); | ||
792 | 59 | |||
793 | 60 | diag("Starting master1"); | ||
794 | 61 | $sb->start_sandbox("master", "master1"); | ||
795 | 62 | |||
796 | 63 | my ($master_cxn, $slave1_cxn, $master1_cxn) | ||
797 | 64 | = map { | ||
798 | 65 | my $cxn = make_cxn( dsn_string => $sb->dsn_for($_) ); | ||
799 | 66 | $cxn->connect(); | ||
800 | 67 | $cxn; | ||
801 | 68 | } qw( master slave1 master1 ); | ||
802 | 69 | |||
803 | 70 | for my $cxn ( $master_cxn, $slave1_cxn, $master1_cxn ) { | ||
804 | 71 | ok( | ||
805 | 72 | !$cluster->is_cluster_node($cxn), | ||
806 | 73 | "is_cluster_node works correctly for non-nodes " . $cxn->name | ||
807 | 74 | ); | ||
808 | 75 | } | ||
809 | 76 | |||
810 | 77 | ok($cluster->is_master_of($master_cxn, $slave1_cxn), "is_master_of(master, slave1) is true"); | ||
811 | 78 | ok(!$cluster->is_master_of($slave1_cxn, $master_cxn), "is_master_of(slave1, master) is false"); | ||
812 | 79 | |||
813 | 80 | my $db_flavor = VersionParser->new($master_dbh)->flavor(); | ||
814 | 81 | SKIP: { | ||
815 | 82 | skip "PXC-only test", 17 | ||
816 | 83 | unless $db_flavor =~ /XtraDB Cluster/; | ||
817 | 84 | |||
818 | 85 | diag("Starting a 1-node PXC"); | ||
819 | 86 | my ($node) = $sb->start_cluster(cluster_size => 1); | ||
820 | 87 | |||
821 | 88 | my $cxn1 = make_cxn( dsn_string => $sb->dsn_for($node) ); | ||
822 | 89 | $cxn1->connect(); | ||
823 | 90 | ok( | ||
824 | 91 | $cluster->is_cluster_node($cxn1), | ||
825 | 92 | "is_cluster_node works correctly for cluster nodes" | ||
826 | 93 | ); | ||
827 | 94 | |||
828 | 95 | ok( | ||
829 | 96 | !$cluster->is_master_of($master1_cxn, $cxn1), | ||
830 | 97 | "->is_master_of works correctly for a server unrelated to a cluster" | ||
831 | 98 | ); | ||
832 | 99 | |||
833 | 100 | diag("Setting node as a slave of master1"); | ||
834 | 101 | $sb->set_as_slave($node, "master1"); | ||
835 | 102 | ok( | ||
836 | 103 | $cluster->is_master_of($master1_cxn, $cxn1), | ||
837 | 104 | "->is_master_of works correctly for master -> cluster" | ||
838 | 105 | ); | ||
839 | 106 | ok( | ||
840 | 107 | !$cluster->is_master_of($cxn1, $master1_cxn), | ||
841 | 108 | "...and the inverse returns the expected result" | ||
842 | 109 | ); | ||
843 | 110 | ok( | ||
844 | 111 | !$cluster->same_cluster($master1_cxn, $cxn1), | ||
845 | 112 | "->same_cluster works for master -> cluster" | ||
846 | 113 | ); | ||
847 | 114 | diag("Restarting the cluster"); | ||
848 | 115 | diag($sb->stop_sandbox($node)); | ||
849 | 116 | ($node) = $sb->start_cluster(cluster_size => 1); | ||
850 | 117 | $cxn1 = make_cxn( dsn_string => $sb->dsn_for($node) ); | ||
851 | 118 | $cxn1->connect(); | ||
852 | 119 | |||
853 | 120 | diag("Setting master1 as a slave of the node"); | ||
854 | 121 | $sb->set_as_slave("master1", $node); | ||
855 | 122 | ok( | ||
856 | 123 | $cluster->is_master_of($cxn1, $master1_cxn), | ||
857 | 124 | "->is_master_of works correctly for cluster -> master" | ||
858 | 125 | ); | ||
859 | 126 | ok( | ||
860 | 127 | !$cluster->is_master_of($master1_cxn, $cxn1), | ||
861 | 128 | "...and the inverse returns the expected result" | ||
862 | 129 | ); | ||
863 | 130 | |||
864 | 131 | ok( | ||
865 | 132 | !$cluster->same_cluster($cxn1, $master1_cxn), | ||
866 | 133 | "->same_cluster works for cluster -> master" | ||
867 | 134 | ); | ||
868 | 135 | |||
869 | 136 | diag("Starting a 2-node PXC"); | ||
870 | 137 | my ($node2, $node3) = $sb->start_cluster(cluster_size => 2); | ||
871 | 138 | |||
872 | 139 | my $cxn2 = make_cxn( dsn_string => $sb->dsn_for($node2) ); | ||
873 | 140 | $cxn2->connect(); | ||
874 | 141 | my $cxn3 = make_cxn( dsn_string => $sb->dsn_for($node3) ); | ||
875 | 142 | $cxn3->connect(); | ||
876 | 143 | ok( | ||
877 | 144 | $cluster->is_cluster_node($cxn2), | ||
878 | 145 | "is_cluster_node correctly finds that this node is part of a cluster" | ||
879 | 146 | ); | ||
880 | 147 | |||
881 | 148 | ok( | ||
882 | 149 | !$cluster->same_cluster($cxn1, $cxn2), | ||
883 | 150 | "and same_cluster correctly finds that they don't belong to the same cluster, even when they have the same cluster name" | ||
884 | 151 | ); | ||
885 | 152 | |||
886 | 153 | ok( | ||
887 | 154 | $cluster->same_cluster($cxn2, $cxn3), | ||
888 | 155 | "...but does find that they are in the same cluster, even if one is node1" | ||
889 | 156 | ); | ||
890 | 157 | |||
891 | 158 | TODO: { | ||
892 | 159 | local $::TODO = "Should detected that (cluster1.node1) (cluster2.node2) come from different clusters, but doesn't"; | ||
893 | 160 | ok( | ||
894 | 161 | !$cluster->same_cluster($cxn1, $cxn3), | ||
895 | 162 | "...same_cluster works correctly when they have the same cluster names" | ||
896 | 163 | ); | ||
897 | 164 | } | ||
898 | 165 | |||
899 | 166 | diag("Making the second cluster a slave of the first"); | ||
900 | 167 | $sb->set_as_slave($node2, $node); | ||
901 | 168 | ok($cluster->is_master_of($cxn1, $cxn2), "is_master_of(cluster1, cluster2) works"); | ||
902 | 169 | |||
903 | 170 | ok( | ||
904 | 171 | !$cluster->same_cluster($cxn1, $cxn2), | ||
905 | 172 | "...same_cluster works correctly when they are cluster1.node1.master -> cluster2.node1.slave" | ||
906 | 173 | ); | ||
907 | 174 | |||
908 | 175 | diag($sb->stop_sandbox($node2, $node3)); | ||
909 | 176 | diag("Starting a 3-node cluster"); | ||
910 | 177 | my $node4; | ||
911 | 178 | ($node2, $node3, $node4) | ||
912 | 179 | = $sb->start_cluster( | ||
913 | 180 | cluster_size => 3, | ||
914 | 181 | cluster_name => "pt_cxn_test", | ||
915 | 182 | ); | ||
916 | 183 | $cxn2 = make_cxn( dsn_string => $sb->dsn_for($node2) ); | ||
917 | 184 | $cxn2->connect(); | ||
918 | 185 | $cxn3 = make_cxn( dsn_string => $sb->dsn_for($node3) ); | ||
919 | 186 | $cxn3->connect(); | ||
920 | 187 | my $cxn4 = make_cxn( dsn_string => $sb->dsn_for($node4) ); | ||
921 | 188 | $cxn4->connect(); | ||
922 | 189 | |||
923 | 190 | ok( | ||
924 | 191 | !$cluster->same_cluster($cxn1, $cxn2), | ||
925 | 192 | "...same_cluster works correctly when they have different cluster names & the are both gcomm" | ||
926 | 193 | ); | ||
927 | 194 | |||
928 | 195 | ok( | ||
929 | 196 | !$cluster->same_cluster($cxn1, $cxn3), | ||
930 | 197 | "same_cluster detects that (cluster1.node1) (cluster2.node2) come from different clusters if they have different cluster_names" | ||
931 | 198 | ); | ||
932 | 199 | |||
933 | 200 | ok( | ||
934 | 201 | $cluster->same_cluster($cxn2, $cxn3), | ||
935 | 202 | "sanity check: but still finds that nodes in the same cluster belong together" | ||
936 | 203 | ); | ||
937 | 204 | |||
938 | 205 | diag($sb->stop_sandbox($node, $node2, $node3, $node4)); | ||
939 | 206 | } | ||
940 | 207 | |||
941 | 208 | diag($sb->stop_sandbox("master1")); | ||
942 | 209 | |||
943 | 210 | # ############################################################################# | ||
944 | 211 | # Done. | ||
945 | 212 | # ############################################################################# | ||
946 | 213 | $master_dbh->disconnect() if $master_dbh; | ||
947 | 214 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); | ||
948 | 215 | done_testing; | ||
949 | 216 | exit; | ||
950 | 0 | 217 | ||
951 | === added file 't/pt-table-checksum/pxc.t' | |||
952 | --- t/pt-table-checksum/pxc.t 1970-01-01 00:00:00 +0000 | |||
953 | +++ t/pt-table-checksum/pxc.t 2012-11-08 20:42:20 +0000 | |||
954 | @@ -0,0 +1,242 @@ | |||
955 | 1 | #!/usr/bin/env perl | ||
956 | 2 | |||
957 | 3 | BEGIN { | ||
958 | 4 | die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" | ||
959 | 5 | unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; | ||
960 | 6 | unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; | ||
961 | 7 | }; | ||
962 | 8 | |||
963 | 9 | use strict; | ||
964 | 10 | use warnings FATAL => 'all'; | ||
965 | 11 | use English qw(-no_match_vars); | ||
966 | 12 | use Test::More; | ||
967 | 13 | use Data::Dumper; | ||
968 | 14 | use File::Spec::Functions; | ||
969 | 15 | |||
970 | 16 | # Hostnames make testing less accurate. Tests need to see | ||
971 | 17 | # that such-and-such happened on specific slave hosts, but | ||
972 | 18 | # the sandbox servers are all on one host so all slaves have | ||
973 | 19 | # the same hostname. | ||
974 | 20 | $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1; | ||
975 | 21 | |||
976 | 22 | use PerconaTest; | ||
977 | 23 | use Sandbox; | ||
978 | 24 | |||
979 | 25 | require "$trunk/bin/pt-table-checksum"; | ||
980 | 26 | # Do this after requiring ptc, since it uses Mo | ||
981 | 27 | require VersionParser; | ||
982 | 28 | |||
983 | 29 | my $dp = new DSNParser(opts=>$dsn_opts); | ||
984 | 30 | my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); | ||
985 | 31 | my $master_dbh = $sb->get_dbh_for('master'); | ||
986 | 32 | |||
987 | 33 | my $db_flavor = VersionParser->new($master_dbh)->flavor(); | ||
988 | 34 | |||
989 | 35 | if ( !$master_dbh ) { | ||
990 | 36 | plan skip_all => 'Cannot connect to sandbox master'; | ||
991 | 37 | } | ||
992 | 38 | elsif ( $db_flavor !~ /XtraDB Cluster/ ) { | ||
993 | 39 | plan skip_all => "PXC tests"; | ||
994 | 40 | } | ||
995 | 41 | |||
996 | 42 | # The sandbox servers run with lock_wait_timeout=3 and it's not dynamic | ||
997 | 43 | # so we need to specify --lock-wait-timeout=3 else the tool will die. | ||
998 | 44 | my $master_dsn = 'h=127.1,P=12345,u=msandbox,p=msandbox'; | ||
999 | 45 | my @args = ($master_dsn, qw(--lock-wait-timeout 3)); | ||
1000 | 46 | my $output; | ||
1001 | 47 | my $exit_status; | ||
1002 | 48 | my $sample = "t/pt-table-checksum/samples/"; | ||
1003 | 49 | |||
1004 | 50 | # ############################################################################# | ||
1005 | 51 | # pt-table-checksum v2.1.4 doesn't detect diffs on Percona XtraDB Cluster nodes | ||
1006 | 52 | # https://bugs.launchpad.net/percona-toolkit/+bug/1062563 | ||
1007 | 53 | # ############################################################################# | ||
1008 | 54 | |||
1009 | 55 | sub make_dbh_differ { | ||
1010 | 56 | my ($dbh, @vals) = @_; | ||
1011 | 57 | @vals = (@vals ? @vals : 1); | ||
1012 | 58 | # Make them differ... | ||
1013 | 59 | $dbh->do("DROP DATABASE IF EXISTS bug_1062563"); | ||
1014 | 60 | $dbh->do("CREATE DATABASE bug_1062563"); | ||
1015 | 61 | $dbh->do("CREATE TABLE bug_1062563.ptc_pxc (i int)"); | ||
1016 | 62 | |||
1017 | 63 | # Now make this node different from the rest | ||
1018 | 64 | $dbh->do("set sql_log_bin=0"); | ||
1019 | 65 | $dbh->do("INSERT INTO bug_1062563.ptc_pxc (i) VALUES ($_)") for @vals; | ||
1020 | 66 | $dbh->do("set sql_log_bin=1"); | ||
1021 | 67 | } | ||
1022 | 68 | |||
1023 | 69 | diag("Creating a 5-node PXC cluster..."); | ||
1024 | 70 | my @nodes = $sb->start_cluster(cluster_size => 5); | ||
1025 | 71 | diag("Nodes: ", Dumper( { map { $_ => $sb->port_for($_) } @nodes } )); | ||
1026 | 72 | |||
1027 | 73 | my $node2 = $nodes[1]; | ||
1028 | 74 | my $node2_dbh = $sb->get_dbh_for($node2); | ||
1029 | 75 | |||
1030 | 76 | my $node2_slave = "master3"; | ||
1031 | 77 | |||
1032 | 78 | diag("Creating a slave for $node2..."); | ||
1033 | 79 | { | ||
1034 | 80 | local $ENV{BINLOG_FORMAT} = 'ROW'; | ||
1035 | 81 | diag($sb->start_sandbox("slave", $node2_slave, $node2)); | ||
1036 | 82 | } | ||
1037 | 83 | my $node_slave_dbh = $sb->get_dbh_for($node2_slave); | ||
1038 | 84 | |||
1039 | 85 | make_dbh_differ($node2_dbh); | ||
1040 | 86 | |||
1041 | 87 | # And make its slave differ as well | ||
1042 | 88 | PerconaTest::wait_for_table($sb->get_dbh_for($nodes[-1]), "bug_1062563.ptc_pxc"); | ||
1043 | 89 | PerconaTest::wait_for_table($node_slave_dbh, "bug_1062563.ptc_pxc"); | ||
1044 | 90 | $node_slave_dbh->do("INSERT INTO bug_1062563.ptc_pxc (i) VALUES ($_)") for 3, 4; | ||
1045 | 91 | |||
1046 | 92 | my $dsns_table_sql = catfile(qw(t lib samples MasterSlave dsn_table.sql)); | ||
1047 | 93 | $sb->load_file($node2, $dsns_table_sql, undef, no_wait => 1); | ||
1048 | 94 | $node2_dbh->do("DELETE FROM dsn_t.dsns"); # Delete 12346 | ||
1049 | 95 | my $sth = $node2_dbh->prepare("INSERT INTO dsn_t.dsns VALUES (null, null, ?)"); | ||
1050 | 96 | for my $dsn ( map { $sb->dsn_for($_) } @nodes[0,2..$#nodes], $node2_slave ) { | ||
1051 | 97 | $sth->execute($dsn); | ||
1052 | 98 | } | ||
1053 | 99 | |||
1054 | 100 | my $node2_dsn = $sb->dsn_for($node2); | ||
1055 | 101 | $output = output( | ||
1056 | 102 | sub { pt_table_checksum::main( | ||
1057 | 103 | $node2_dsn, qw(--lock-wait-timeout 3), | ||
1058 | 104 | qw(-d bug_1062563), | ||
1059 | 105 | '--recursion-method', "dsn=D=dsn_t,t=dsns" | ||
1060 | 106 | ) }, | ||
1061 | 107 | stderr => 1, | ||
1062 | 108 | ); | ||
1063 | 109 | |||
1064 | 110 | is( | ||
1065 | 111 | PerconaTest::count_checksum_results($output, 'diffs'), | ||
1066 | 112 | 1, | ||
1067 | 113 | "Bug 1062563: Detects diffs between PXC nodes" | ||
1068 | 114 | ) or diag($output); | ||
1069 | 115 | |||
1070 | 116 | my @cluster_nodes = $output =~ /(because it is a cluster node)/g; | ||
1071 | 117 | is( | ||
1072 | 118 | scalar(@cluster_nodes), | ||
1073 | 119 | 4, | ||
1074 | 120 | "Skips all the cluster nodes in the dsns table" | ||
1075 | 121 | ) or diag($output); | ||
1076 | 122 | |||
1077 | 123 | # Now try with just the slave | ||
1078 | 124 | |||
1079 | 125 | $node2_dbh->do("DELETE FROM dsn_t.dsns"); | ||
1080 | 126 | $sth->execute($sb->dsn_for($node2_slave)); | ||
1081 | 127 | |||
1082 | 128 | $output = output( | ||
1083 | 129 | sub { pt_table_checksum::main( | ||
1084 | 130 | $node2_dsn, qw(--lock-wait-timeout 3), | ||
1085 | 131 | qw(--chunk-size 1), | ||
1086 | 132 | qw(-d bug_1062563), | ||
1087 | 133 | '--recursion-method', "dsn=D=dsn_t,t=dsns" | ||
1088 | 134 | ) }, | ||
1089 | 135 | stderr => 1, | ||
1090 | 136 | ); | ||
1091 | 137 | |||
1092 | 138 | is( | ||
1093 | 139 | PerconaTest::count_checksum_results($output, 'diffs'), | ||
1094 | 140 | 1, | ||
1095 | 141 | "Bug 1062563: Detects diffs on slaves where the master is a PXC node" | ||
1096 | 142 | ) or diag($output); | ||
1097 | 143 | |||
1098 | 144 | $sth->finish(); | ||
1099 | 145 | diag("Stopping the PXC cluster and the slave..."); | ||
1100 | 146 | $sb->stop_sandbox($node2_slave, @nodes); | ||
1101 | 147 | |||
1102 | 148 | # Now checking that cluster -> cluster works | ||
1103 | 149 | |||
1104 | 150 | diag("Creating two 3-node clusters..."); | ||
1105 | 151 | my @cluster1 = $sb->start_cluster(cluster_size => 3, cluster_name => "pt_test_cluster_1"); | ||
1106 | 152 | my @cluster2 = $sb->start_cluster(cluster_size => 3, cluster_name => "pt_test_cluster_2"); | ||
1107 | 153 | diag("Cluster 1: ", Dumper( { map { $_ => $sb->port_for($_) } @cluster1 } )); | ||
1108 | 154 | diag("Cluster 2: ", Dumper( { map { $_ => $sb->port_for($_) } @cluster2 } )); | ||
1109 | 155 | |||
1110 | 156 | $sb->set_as_slave($cluster2[0], $cluster1[0]); | ||
1111 | 157 | |||
1112 | 158 | my $cluster1_dbh = $sb->get_dbh_for($cluster1[0]); | ||
1113 | 159 | my $cluster2_dbh = $sb->get_dbh_for($cluster2[0]); | ||
1114 | 160 | make_dbh_differ($cluster1_dbh); | ||
1115 | 161 | |||
1116 | 162 | # And make its slave differ as well | ||
1117 | 163 | PerconaTest::wait_for_table($sb->get_dbh_for($cluster2[-1]), "bug_1062563.ptc_pxc"); | ||
1118 | 164 | PerconaTest::wait_for_table($sb->get_dbh_for($cluster1[-1]), "bug_1062563.ptc_pxc"); | ||
1119 | 165 | PerconaTest::wait_for_table($cluster2_dbh, "bug_1062563.ptc_pxc"); | ||
1120 | 166 | $cluster2_dbh->do("INSERT INTO bug_1062563.ptc_pxc (i) VALUES ($_)") for 3, 4; | ||
1121 | 167 | |||
1122 | 168 | $dsns_table_sql = catfile(qw(t lib samples MasterSlave dsn_table.sql)); | ||
1123 | 169 | $sb->load_file($cluster1[0], $dsns_table_sql, undef, no_wait => 1); | ||
1124 | 170 | $cluster1_dbh->do("DELETE FROM dsn_t.dsns"); # Delete 12346 | ||
1125 | 171 | $sth = $cluster1_dbh->prepare("INSERT INTO dsn_t.dsns VALUES (null, null, ?)"); | ||
1126 | 172 | for my $dsn ( map { $sb->dsn_for($_) } @cluster1[1..$#cluster1], $cluster2[0] ) { | ||
1127 | 173 | $sth->execute($dsn); | ||
1128 | 174 | } | ||
1129 | 175 | $sth->finish(); | ||
1130 | 176 | |||
1131 | 177 | my $cluster1_dsn = $sb->dsn_for($cluster1[0]); | ||
1132 | 178 | $output = output( | ||
1133 | 179 | sub { pt_table_checksum::main( | ||
1134 | 180 | $cluster1_dsn, qw(--lock-wait-timeout 3), | ||
1135 | 181 | qw(-d bug_1062563), | ||
1136 | 182 | '--recursion-method', "dsn=D=dsn_t,t=dsns" | ||
1137 | 183 | ) }, | ||
1138 | 184 | stderr => 1, | ||
1139 | 185 | ); | ||
1140 | 186 | |||
1141 | 187 | is( | ||
1142 | 188 | PerconaTest::count_checksum_results($output, 'diffs'), | ||
1143 | 189 | 1, | ||
1144 | 190 | "Bug 1062563: Detects diffs between PXC nodes when cluster -> cluster" | ||
1145 | 191 | ) or diag($output); | ||
1146 | 192 | |||
1147 | 193 | like( | ||
1148 | 194 | $output, | ||
1149 | 195 | qr/is a cluster node, but doesn't belong to the same cluster as/, #' | ||
1150 | 196 | "Shows a warning when cluster -> cluster" | ||
1151 | 197 | ) or diag($output); | ||
1152 | 198 | |||
1153 | 199 | diag("Starting master1..."); | ||
1154 | 200 | $sb->start_sandbox("master", "master1"); | ||
1155 | 201 | diag("Setting it as master of a node in the first cluster"); | ||
1156 | 202 | $sb->set_as_slave($cluster1[0], "master1"); | ||
1157 | 203 | |||
1158 | 204 | my $master1_dbh = $sb->get_dbh_for("master1"); | ||
1159 | 205 | make_dbh_differ($master1_dbh, 10..50); | ||
1160 | 206 | |||
1161 | 207 | my $master1_dsn = $sb->dsn_for("master1"); | ||
1162 | 208 | $output = output( | ||
1163 | 209 | sub { pt_table_checksum::main( | ||
1164 | 210 | $master1_dsn, qw(--lock-wait-timeout 3), | ||
1165 | 211 | qw(-d bug_1062563), | ||
1166 | 212 | ) }, | ||
1167 | 213 | stderr => 1, | ||
1168 | 214 | ); | ||
1169 | 215 | |||
1170 | 216 | is( | ||
1171 | 217 | PerconaTest::count_checksum_results($output, 'diffs'), | ||
1172 | 218 | 1, | ||
1173 | 219 | "Bug 1062563: Detects diffs when master -> cluster" | ||
1174 | 220 | ) or diag($output); | ||
1175 | 221 | |||
1176 | 222 | is( | ||
1177 | 223 | PerconaTest::count_checksum_results($output, 'rows'), | ||
1178 | 224 | 41, | ||
1179 | 225 | "Bug 1062563: Correct number of rows for master -> cluster" | ||
1180 | 226 | ) or diag($output); | ||
1181 | 227 | |||
1182 | 228 | like( | ||
1183 | 229 | $output, | ||
1184 | 230 | qr/is a cluster node, but .*? is not. This is not currently supported/, | ||
1185 | 231 | "Shows a warning when master -> cluster" | ||
1186 | 232 | ) or diag($output); | ||
1187 | 233 | |||
1188 | 234 | diag("Stopping both clusters and master1..."); | ||
1189 | 235 | $sb->stop_sandbox(@cluster1, @cluster2, "master1"); | ||
1190 | 236 | |||
1191 | 237 | # ############################################################################# | ||
1192 | 238 | # Done. | ||
1193 | 239 | # ############################################################################# | ||
1194 | 240 | $sb->wipe_clean($master_dbh); | ||
1195 | 241 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); | ||
1196 | 242 | done_testing; |
Are the new subs in Sandbox.pm and how Cxn.t works with a cluster vestiges of portable- test-suite, or can we do this stuff now with the sandbox/ scripts?