~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to tests/randgen/lib/GenTest/Reporter/ReplicationSemiSync.pm

  • Committer: Mark Atwood
  • Date: 2011-10-14 15:59:08 UTC
  • mfrom: (2430.1.12 refactor3a)
  • Revision ID: me@mark.atwood.name-20111014155908-whqmrmaf2grpsg5c
mergeĀ lp:~olafvdspek/drizzle/refactor3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008-2009 Sun Microsystems, Inc. All rights reserved.
2
 
# Use is subject to license terms.
3
 
#
4
 
# This program is free software; you can redistribute it and/or modify
5
 
# it under the terms of the GNU General Public License as published by
6
 
# the Free Software Foundation; version 2 of the License.
7
 
#
8
 
# This program is distributed in the hope that it will be useful, but
9
 
# WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
 
# General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
16
 
# USA
17
 
 
18
 
package GenTest::Reporter::ReplicationSemiSync;
19
 
 
20
 
#
21
 
# The purpose of this Reporter is to test Semi-synchronous replication as follows:
22
 
#
23
 
#  At every monitoring cycle, we issue an adverse event against the slave or the master/slave connection and then:
24
 
#
25
 
# 1. Check that the slave IO thread is up to date with the master
26
 
#
27
 
# 2A. We wait for 1/2 of the timeout period, and then we check various counters to see that no transactions
28
 
#    have committed while the slave was not available OR 
29
 
#
30
 
# 2B. We wait for more than the timeout period and then we check that some transactions have moved forward
31
 
#
32
 
# 3. We restart replication in order to allow the slave to catch up, and check that the master is back to
33
 
#    semisync replication
34
 
#
35
 
 
36
 
require Exporter;
37
 
@ISA = qw(GenTest::Reporter);
38
 
 
39
 
use strict;
40
 
use GenTest;
41
 
use GenTest::Reporter;
42
 
use GenTest::Constants;
43
 
 
44
 
my $rpl_semi_sync_master_timeout = 10;
45
 
 
46
 
sub monitor {
47
 
        my $reporter = shift;
48
 
 
49
 
        say("GenTest::Reporter::ReplicationSemiSync: Test cycle starting.");
50
 
 
51
 
        my $prng = $reporter->prng();
52
 
 
53
 
        my $slave_host = $reporter->serverInfo('slave_host');
54
 
        my $slave_port = $reporter->serverInfo('slave_port');
55
 
 
56
 
        my $master_dsn = $reporter->dsn();
57
 
        my $slave_dsn = 'dbi:mysql:host='.$slave_host.':port='.$slave_port.':user=root';
58
 
 
59
 
        my $slave_dbh = DBI->connect($slave_dsn);
60
 
        my $master_dbh = DBI->connect($master_dsn);
61
 
 
62
 
        $master_dbh->do("SET GLOBAL rpl_semi_sync_master_enabled = 1");
63
 
        $master_dbh->do("SET GLOBAL rpl_semi_sync_master_trace_level = 80");
64
 
        $slave_dbh->do("SET GLOBAL rpl_semi_sync_slave_enabled = 1");
65
 
        $slave_dbh->do("SET GLOBAL rpl_semi_sync_slave_trace_level = 80");
66
 
 
67
 
        return STATUS_REPLICATION_FAILURE if waitForSlave($master_dbh, $slave_dbh, 1);
68
 
#       sleep(1);
69
 
 
70
 
#       my ($unused2, $rpl_semi_sync_master_status_first) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
71
 
 
72
 
#       if (
73
 
#               ($rpl_semi_sync_master_status_first eq '') ||
74
 
#               ($rpl_semi_sync_master_status_first eq 'OFF')
75
 
#       ) {
76
 
#               say("GenTest::Reporter::ReplicationSemiSync: Semisync replication is not enabled: rpl_semi_sync_master_status = $rpl_semi_sync_master_status_first.");
77
 
#               return STATUS_REPLICATION_FAILURE;
78
 
#       }
79
 
 
80
 
#       $master_dbh->do("SET GLOBAL rpl_semi_sync_master_timeout = ".($rpl_semi_sync_master_timeout * 1000));
81
 
#       say("GenTest::Reporter::ReplicationSemiSync: Acquiring the global read lock.");
82
 
#       $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG TABLES WITH READ LOCK");
83
 
#       say("GenTest::Reporter::ReplicationSemiSync: stopping slave IO thread.");
84
 
#       $slave_dbh->do("STOP SLAVE IO_THREAD");
85
 
#       say("GenTest::Reporter::ReplicationSemiSync: stopped slave IO thread.");
86
 
 
87
 
#       return STATUS_REPLICATION_FAILURE if isSlaveBehind($master_dbh, $slave_dbh);
88
 
 
89
 
#       $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG STATUS");
90
 
#       say("GenTest::Reporter::ReplicationSemiSync: Flushed status.");
91
 
#       $master_dbh->do("UNLOCK TABLES");
92
 
#       say("GenTest::Reporter::ReplicationSemiSync: Released the global read lock.");
93
 
#       my ($unusedA, $rpl_semi_sync_master_yes_tx_atflush) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'");
94
 
#       my ($unusedB, $rpl_semi_sync_master_no_tx_atflush) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'");
95
 
 
96
 
        # Pick a sleep interval that is either more or less than the semisync timeout
97
 
 
98
 
        my $sleep_interval = $prng->int(0, 1) == 1 ? ($rpl_semi_sync_master_timeout * 2) : 5;
99
 
        say("GenTest::Reporter::ReplicationSemiSync: Sleeping for $sleep_interval seconds.");
100
 
        sleep($sleep_interval);
101
 
 
102
 
        my ($unused4, $rpl_semi_sync_master_yes_tx) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'");
103
 
        my ($unused5, $rpl_semi_sync_master_no_tx) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'");
104
 
        my ($unused6, $rpl_semi_sync_master_status_after) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
105
 
 
106
 
        #
107
 
        # If we slept more than the semisync timeout, then we can expect that transactions have been committed
108
 
        # If we slept less, then no transactions should have committed
109
 
        #
110
 
 
111
 
        if ($sleep_interval > $rpl_semi_sync_master_timeout) {
112
 
                if ($rpl_semi_sync_master_status_after eq 'ON') {
113
 
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_status = ON even after stopping for longer than the timeout.");
114
 
                        return STATUS_REPLICATION_FAILURE;
115
 
                } elsif ($rpl_semi_sync_master_no_tx == 0) {
116
 
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were not committed asynchronously while slave was stopped for longer than the timeout.");
117
 
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_no_tx = $rpl_semi_sync_master_no_tx;");
118
 
                } elsif ($rpl_semi_sync_master_yes_tx > 0) {
119
 
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were committed semisynchronously while slave was stopped longer than the timeout.");
120
 
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_yes_tx = $rpl_semi_sync_master_yes_tx;");
121
 
                        return STATUS_REPLICATION_FAILURE;
122
 
                }
123
 
        } else {
124
 
 
125
 
#               jasonh says that this condition is not guaranteed - if we detect a slave problem, we abort immediately and do not bother
126
 
#               to wait for the full timeout
127
 
#
128
 
                if ($rpl_semi_sync_master_status_after eq 'OFF') {
129
 
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_status = OFF even after stopping for less than the timeout.");
130
 
                        return STATUS_REPLICATION_FAILURE;
131
 
                } elsif ($rpl_semi_sync_master_no_tx > 0) {
132
 
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were committed asynchronously while slave was stopped for less than the timeout.");
133
 
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_no_tx = $rpl_semi_sync_master_no_tx;");
134
 
                        return STATUS_REPLICATION_FAILURE;
135
 
                } elsif ($rpl_semi_sync_master_yes_tx > 0) {
136
 
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were committed semisynchronously while slave was stopped for less than the timeout.");
137
 
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_yes_tx = $rpl_semi_sync_master_yes_tx;");
138
 
                        return STATUS_REPLICATION_FAILURE;
139
 
                } else {
140
 
#                       return STATUS_REPLICATION_FAILURE if isSlaveBehind($master_dbh, $slave_dbh);
141
 
                }
142
 
        }
143
 
        
144
 
        say("GenTest::Reporter::ReplicationSemiSync: Starting slave IO thread.");
145
 
        $slave_dbh->do("START SLAVE IO_THREAD");
146
 
 
147
 
        #
148
 
        # Make sure master and slave can reconcile and semisync will be turned on again
149
 
        #
150
 
 
151
 
        return STATUS_REPLICATION_FAILURE if waitForSlave($master_dbh, $slave_dbh, 0);
152
 
#       sleep(1);
153
 
 
154
 
#       my ($unused7, $rpl_semi_sync_master_status_last) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
155
 
#       if ($rpl_semi_sync_master_status_last eq 'OFF') {
156
 
#               say("GenTest::Reporter::ReplicationSemiSync: Master has failed to return to semisync replication even after the slave has reconnected.");
157
 
#               return STATUS_REPLICATION_FAILURE;
158
 
#       }
159
 
 
160
 
#       say("GenTest::Reporter::ReplicationSemiSync: test cycle ending with Rpl_semi_sync_master_status = $rpl_semi_sync_master_status_last.");
161
 
 
162
 
        return STATUS_OK;
163
 
}
164
 
 
165
 
sub type {
166
 
        return REPORTER_TYPE_PERIODIC;
167
 
}
168
 
 
169
 
sub isSlaveBehind {
170
 
        my ($master_dbh, $slave_dbh) = @_;
171
 
 
172
 
        my $binlogs = $master_dbh->selectall_arrayref("SHOW BINARY LOGS");
173
 
        my ($last_log_name, $last_log_pos) = ($binlogs->[$#$binlogs]->[0], $binlogs->[$#$binlogs]->[1]);
174
 
        my ($last_log_id) = $last_log_name =~ m{(\d+)}sgio;
175
 
        say("Master: last_log_name = $last_log_name; last_log_pos = $last_log_pos; $last_log_id = $last_log_id.");
176
 
                        
177
 
        my $slave_status = $slave_dbh->selectrow_arrayref("SHOW SLAVE STATUS");
178
 
        my ($master_log_file, $read_master_log_pos) = ($slave_status->[5], $slave_status->[6]);
179
 
        my ($master_log_id) = $master_log_file =~ m{(\d+)}sgio;
180
 
        say("GenTest::Reporter::ReplicationSemiSync: slave: master_log_file = $master_log_file; read_master_log_pos = $read_master_log_pos; master_log_id = $master_log_id.");
181
 
        if ( 
182
 
                ($last_log_id < $master_log_id) ||
183
 
                ($last_log_id == $master_log_id) && ($last_log_pos > $read_master_log_pos)
184
 
        ) {
185
 
                my ($unused, $rpl_semi_sync_master_status) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
186
 
                say("GenTest::Reporter::ReplicationSemiSync: Slave has lagged behind while Rpl_semi_sync_master_status = $rpl_semi_sync_master_status.");
187
 
                return STATUS_REPLICATION_FAILURE;
188
 
        }
189
 
}
190
 
 
191
 
sub waitForSlave {
192
 
        my ($master_dbh, $slave_dbh, $stop_slave) = @_;
193
 
 
194
 
        say("GenTest::Reporter::ReplicationSemiSync: Flushing tables with read lock on master...");
195
 
        $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG TABLES WITH READ LOCK");
196
 
        say("GenTest::Reporter::ReplicationSemiSync: ... flushed.");
197
 
 
198
 
        my ($file, $pos) = $master_dbh->selectrow_array("SHOW MASTER STATUS");
199
 
 
200
 
        if (($file eq '') || ($pos eq '')) {
201
 
                 say("GenTest::Reporter::ReplicationSemiSync: SHOW MASTER STATUS failed.");
202
 
                 return STATUS_REPLICATION_FAILURE;
203
 
        }
204
 
 
205
 
        say("GenTest::Reporter::ReplicationSemiSync: Waiting for slave...");
206
 
        #say("SHOW MASTER STATUS: " . $file . ", " . $pos);
207
 
        my $wait_status = $slave_dbh->selectrow_array("SELECT MASTER_POS_WAIT(?, ?)", undef, $file, $pos);
208
 
        say("GenTest::Reporter::ReplicationSemiSync: ... slave caught up with master.");
209
 
 
210
 
        #my ($new_file, $new_pos) = $master_dbh->selectrow_array("SHOW MASTER STATUS");
211
 
        #say("SHOW MASTER STATUS: " . $new_file . ", " . $new_pos);
212
 
 
213
 
        my ($unused2, $rpl_semi_sync_master_status) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
214
 
        if (not $rpl_semi_sync_master_status eq 'ON') {
215
 
            say("GenTest::Reporter::ReplicationSemiSync: Master has failed to return to semisync replication even after the slave has caught up.");
216
 
            return STATUS_REPLICATION_FAILURE;
217
 
        }
218
 
 
219
 
        if ($stop_slave) {
220
 
            $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG STATUS");
221
 
            say("GenTest::Reporter::ReplicationSemiSync: Flushed status.");
222
 
            $master_dbh->do("SET GLOBAL rpl_semi_sync_master_timeout = ".($rpl_semi_sync_master_timeout * 1000));
223
 
            say("GenTest::Reporter::ReplicationSemiSync: stopping slave IO thread.");
224
 
            $slave_dbh->do("STOP SLAVE IO_THREAD");
225
 
            say("GenTest::Reporter::ReplicationSemiSync: stopped slave IO thread.");
226
 
        }
227
 
 
228
 
        $master_dbh->do("UNLOCK TABLES");
229
 
 
230
 
        if (not defined $wait_status) {
231
 
                say("GenTest::Reporter::ReplicationSemiSync: MASTER_POS_WAIT() has failed. Slave SQL thread has likely stopped.");
232
 
                return STATUS_REPLICATION_FAILURE;
233
 
        }
234
 
        return 0;
235
 
}
236
 
 
237
 
1;
 
1
# Copyright (C) 2008-2009 Sun Microsystems, Inc. All rights reserved.
 
2
# Use is subject to license terms.
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; version 2 of the License.
 
7
#
 
8
# This program is distributed in the hope that it will be useful, but
 
9
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
11
# General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 
16
# USA
 
17
 
 
18
package GenTest::Reporter::ReplicationSemiSync;
 
19
 
 
20
#
 
21
# The purpose of this Reporter is to test Semi-synchronous replication as follows:
 
22
#
 
23
#  At every monitoring cycle, we issue an adverse event against the slave or the master/slave connection and then:
 
24
#
 
25
# 1. Check that the slave IO thread is up to date with the master
 
26
#
 
27
# 2A. We wait for 1/2 of the timeout period, and then we check various counters to see that no transactions
 
28
#    have committed while the slave was not available OR 
 
29
#
 
30
# 2B. We wait for more than the timeout period and then we check that some transactions have moved forward
 
31
#
 
32
# 3. We restart replication in order to allow the slave to catch up, and check that the master is back to
 
33
#    semisync replication
 
34
#
 
35
 
 
36
require Exporter;
 
37
@ISA = qw(GenTest::Reporter);
 
38
 
 
39
use strict;
 
40
use GenTest;
 
41
use GenTest::Reporter;
 
42
use GenTest::Constants;
 
43
 
 
44
my $rpl_semi_sync_master_timeout = 10;
 
45
 
 
46
sub monitor {
 
47
        my $reporter = shift;
 
48
 
 
49
        say("GenTest::Reporter::ReplicationSemiSync: Test cycle starting.");
 
50
 
 
51
        my $prng = $reporter->prng();
 
52
 
 
53
        my $slave_host = $reporter->serverInfo('slave_host');
 
54
        my $slave_port = $reporter->serverInfo('slave_port');
 
55
 
 
56
        my $master_dsn = $reporter->dsn();
 
57
        my $slave_dsn = 'dbi:mysql:host='.$slave_host.':port='.$slave_port.':user=root';
 
58
 
 
59
        my $slave_dbh = DBI->connect($slave_dsn);
 
60
        my $master_dbh = DBI->connect($master_dsn);
 
61
 
 
62
        $master_dbh->do("SET GLOBAL rpl_semi_sync_master_enabled = 1");
 
63
        $master_dbh->do("SET GLOBAL rpl_semi_sync_master_trace_level = 80");
 
64
        $slave_dbh->do("SET GLOBAL rpl_semi_sync_slave_enabled = 1");
 
65
        $slave_dbh->do("SET GLOBAL rpl_semi_sync_slave_trace_level = 80");
 
66
 
 
67
        return STATUS_REPLICATION_FAILURE if waitForSlave($master_dbh, $slave_dbh, 1);
 
68
#       sleep(1);
 
69
 
 
70
#       my ($unused2, $rpl_semi_sync_master_status_first) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
 
71
 
 
72
#       if (
 
73
#               ($rpl_semi_sync_master_status_first eq '') ||
 
74
#               ($rpl_semi_sync_master_status_first eq 'OFF')
 
75
#       ) {
 
76
#               say("GenTest::Reporter::ReplicationSemiSync: Semisync replication is not enabled: rpl_semi_sync_master_status = $rpl_semi_sync_master_status_first.");
 
77
#               return STATUS_REPLICATION_FAILURE;
 
78
#       }
 
79
 
 
80
#       $master_dbh->do("SET GLOBAL rpl_semi_sync_master_timeout = ".($rpl_semi_sync_master_timeout * 1000));
 
81
#       say("GenTest::Reporter::ReplicationSemiSync: Acquiring the global read lock.");
 
82
#       $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG TABLES WITH READ LOCK");
 
83
#       say("GenTest::Reporter::ReplicationSemiSync: stopping slave IO thread.");
 
84
#       $slave_dbh->do("STOP SLAVE IO_THREAD");
 
85
#       say("GenTest::Reporter::ReplicationSemiSync: stopped slave IO thread.");
 
86
 
 
87
#       return STATUS_REPLICATION_FAILURE if isSlaveBehind($master_dbh, $slave_dbh);
 
88
 
 
89
#       $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG STATUS");
 
90
#       say("GenTest::Reporter::ReplicationSemiSync: Flushed status.");
 
91
#       $master_dbh->do("UNLOCK TABLES");
 
92
#       say("GenTest::Reporter::ReplicationSemiSync: Released the global read lock.");
 
93
#       my ($unusedA, $rpl_semi_sync_master_yes_tx_atflush) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'");
 
94
#       my ($unusedB, $rpl_semi_sync_master_no_tx_atflush) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'");
 
95
 
 
96
        # Pick a sleep interval that is either more or less than the semisync timeout
 
97
 
 
98
        my $sleep_interval = $prng->int(0, 1) == 1 ? ($rpl_semi_sync_master_timeout * 2) : 5;
 
99
        say("GenTest::Reporter::ReplicationSemiSync: Sleeping for $sleep_interval seconds.");
 
100
        sleep($sleep_interval);
 
101
 
 
102
        my ($unused4, $rpl_semi_sync_master_yes_tx) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'");
 
103
        my ($unused5, $rpl_semi_sync_master_no_tx) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'");
 
104
        my ($unused6, $rpl_semi_sync_master_status_after) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
 
105
 
 
106
        #
 
107
        # If we slept more than the semisync timeout, then we can expect that transactions have been committed
 
108
        # If we slept less, then no transactions should have committed
 
109
        #
 
110
 
 
111
        if ($sleep_interval > $rpl_semi_sync_master_timeout) {
 
112
                if ($rpl_semi_sync_master_status_after eq 'ON') {
 
113
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_status = ON even after stopping for longer than the timeout.");
 
114
                        return STATUS_REPLICATION_FAILURE;
 
115
                } elsif ($rpl_semi_sync_master_no_tx == 0) {
 
116
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were not committed asynchronously while slave was stopped for longer than the timeout.");
 
117
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_no_tx = $rpl_semi_sync_master_no_tx;");
 
118
                } elsif ($rpl_semi_sync_master_yes_tx > 0) {
 
119
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were committed semisynchronously while slave was stopped longer than the timeout.");
 
120
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_yes_tx = $rpl_semi_sync_master_yes_tx;");
 
121
                        return STATUS_REPLICATION_FAILURE;
 
122
                }
 
123
        } else {
 
124
 
 
125
#               jasonh says that this condition is not guaranteed - if we detect a slave problem, we abort immediately and do not bother
 
126
#               to wait for the full timeout
 
127
#
 
128
                if ($rpl_semi_sync_master_status_after eq 'OFF') {
 
129
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_status = OFF even after stopping for less than the timeout.");
 
130
                        return STATUS_REPLICATION_FAILURE;
 
131
                } elsif ($rpl_semi_sync_master_no_tx > 0) {
 
132
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were committed asynchronously while slave was stopped for less than the timeout.");
 
133
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_no_tx = $rpl_semi_sync_master_no_tx;");
 
134
                        return STATUS_REPLICATION_FAILURE;
 
135
                } elsif ($rpl_semi_sync_master_yes_tx > 0) {
 
136
                        say("GenTest::Reporter::ReplicationSemiSync: Transactions were committed semisynchronously while slave was stopped for less than the timeout.");
 
137
                        say("GenTest::Reporter::ReplicationSemiSync: rpl_semi_sync_master_yes_tx = $rpl_semi_sync_master_yes_tx;");
 
138
                        return STATUS_REPLICATION_FAILURE;
 
139
                } else {
 
140
#                       return STATUS_REPLICATION_FAILURE if isSlaveBehind($master_dbh, $slave_dbh);
 
141
                }
 
142
        }
 
143
        
 
144
        say("GenTest::Reporter::ReplicationSemiSync: Starting slave IO thread.");
 
145
        $slave_dbh->do("START SLAVE IO_THREAD");
 
146
 
 
147
        #
 
148
        # Make sure master and slave can reconcile and semisync will be turned on again
 
149
        #
 
150
 
 
151
        return STATUS_REPLICATION_FAILURE if waitForSlave($master_dbh, $slave_dbh, 0);
 
152
#       sleep(1);
 
153
 
 
154
#       my ($unused7, $rpl_semi_sync_master_status_last) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
 
155
#       if ($rpl_semi_sync_master_status_last eq 'OFF') {
 
156
#               say("GenTest::Reporter::ReplicationSemiSync: Master has failed to return to semisync replication even after the slave has reconnected.");
 
157
#               return STATUS_REPLICATION_FAILURE;
 
158
#       }
 
159
 
 
160
#       say("GenTest::Reporter::ReplicationSemiSync: test cycle ending with Rpl_semi_sync_master_status = $rpl_semi_sync_master_status_last.");
 
161
 
 
162
        return STATUS_OK;
 
163
}
 
164
 
 
165
sub type {
 
166
        return REPORTER_TYPE_PERIODIC;
 
167
}
 
168
 
 
169
sub isSlaveBehind {
 
170
        my ($master_dbh, $slave_dbh) = @_;
 
171
 
 
172
        my $binlogs = $master_dbh->selectall_arrayref("SHOW BINARY LOGS");
 
173
        my ($last_log_name, $last_log_pos) = ($binlogs->[$#$binlogs]->[0], $binlogs->[$#$binlogs]->[1]);
 
174
        my ($last_log_id) = $last_log_name =~ m{(\d+)}sgio;
 
175
        say("Master: last_log_name = $last_log_name; last_log_pos = $last_log_pos; $last_log_id = $last_log_id.");
 
176
                        
 
177
        my $slave_status = $slave_dbh->selectrow_arrayref("SHOW SLAVE STATUS");
 
178
        my ($master_log_file, $read_master_log_pos) = ($slave_status->[5], $slave_status->[6]);
 
179
        my ($master_log_id) = $master_log_file =~ m{(\d+)}sgio;
 
180
        say("GenTest::Reporter::ReplicationSemiSync: slave: master_log_file = $master_log_file; read_master_log_pos = $read_master_log_pos; master_log_id = $master_log_id.");
 
181
        if ( 
 
182
                ($last_log_id < $master_log_id) ||
 
183
                ($last_log_id == $master_log_id) && ($last_log_pos > $read_master_log_pos)
 
184
        ) {
 
185
                my ($unused, $rpl_semi_sync_master_status) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
 
186
                say("GenTest::Reporter::ReplicationSemiSync: Slave has lagged behind while Rpl_semi_sync_master_status = $rpl_semi_sync_master_status.");
 
187
                return STATUS_REPLICATION_FAILURE;
 
188
        }
 
189
}
 
190
 
 
191
sub waitForSlave {
 
192
        my ($master_dbh, $slave_dbh, $stop_slave) = @_;
 
193
 
 
194
        say("GenTest::Reporter::ReplicationSemiSync: Flushing tables with read lock on master...");
 
195
        $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG TABLES WITH READ LOCK");
 
196
        say("GenTest::Reporter::ReplicationSemiSync: ... flushed.");
 
197
 
 
198
        my ($file, $pos) = $master_dbh->selectrow_array("SHOW MASTER STATUS");
 
199
 
 
200
        if (($file eq '') || ($pos eq '')) {
 
201
                 say("GenTest::Reporter::ReplicationSemiSync: SHOW MASTER STATUS failed.");
 
202
                 return STATUS_REPLICATION_FAILURE;
 
203
        }
 
204
 
 
205
        say("GenTest::Reporter::ReplicationSemiSync: Waiting for slave...");
 
206
        #say("SHOW MASTER STATUS: " . $file . ", " . $pos);
 
207
        my $wait_status = $slave_dbh->selectrow_array("SELECT MASTER_POS_WAIT(?, ?)", undef, $file, $pos);
 
208
        say("GenTest::Reporter::ReplicationSemiSync: ... slave caught up with master.");
 
209
 
 
210
        #my ($new_file, $new_pos) = $master_dbh->selectrow_array("SHOW MASTER STATUS");
 
211
        #say("SHOW MASTER STATUS: " . $new_file . ", " . $new_pos);
 
212
 
 
213
        my ($unused2, $rpl_semi_sync_master_status) = $master_dbh->selectrow_array("SHOW STATUS LIKE 'Rpl_semi_sync_master_status'");
 
214
        if (not $rpl_semi_sync_master_status eq 'ON') {
 
215
            say("GenTest::Reporter::ReplicationSemiSync: Master has failed to return to semisync replication even after the slave has caught up.");
 
216
            return STATUS_REPLICATION_FAILURE;
 
217
        }
 
218
 
 
219
        if ($stop_slave) {
 
220
            $master_dbh->do("FLUSH NO_WRITE_TO_BINLOG STATUS");
 
221
            say("GenTest::Reporter::ReplicationSemiSync: Flushed status.");
 
222
            $master_dbh->do("SET GLOBAL rpl_semi_sync_master_timeout = ".($rpl_semi_sync_master_timeout * 1000));
 
223
            say("GenTest::Reporter::ReplicationSemiSync: stopping slave IO thread.");
 
224
            $slave_dbh->do("STOP SLAVE IO_THREAD");
 
225
            say("GenTest::Reporter::ReplicationSemiSync: stopped slave IO thread.");
 
226
        }
 
227
 
 
228
        $master_dbh->do("UNLOCK TABLES");
 
229
 
 
230
        if (not defined $wait_status) {
 
231
                say("GenTest::Reporter::ReplicationSemiSync: MASTER_POS_WAIT() has failed. Slave SQL thread has likely stopped.");
 
232
                return STATUS_REPLICATION_FAILURE;
 
233
        }
 
234
        return 0;
 
235
}
 
236
 
 
237
1;