1 /*
2 * Copyright (C) 2018-2019 Codership Oy <info@codership.com>
3 *
4 * This file is part of wsrep-lib.
5 *
6 * Wsrep-lib is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Wsrep-lib is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with wsrep-lib. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "client_state_fixture.hpp"
21
22 //
23 // Test a succesful 2PC transaction lifecycle
24 //
BOOST_FIXTURE_TEST_CASE(transaction_2pc,replicating_client_fixture_2pc)25 BOOST_FIXTURE_TEST_CASE(transaction_2pc,
26 replicating_client_fixture_2pc)
27 {
28 cc.start_transaction(wsrep::transaction_id(1));
29 BOOST_REQUIRE(tc.active());
30 BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
31 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing);
32 BOOST_REQUIRE(cc.before_prepare() == 0);
33 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_preparing);
34 BOOST_REQUIRE(tc.ordered());
35 BOOST_REQUIRE(tc.certified());
36 BOOST_REQUIRE(tc.ws_meta().gtid().is_undefined() == false);
37 BOOST_REQUIRE(cc.after_prepare() == 0);
38 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committing);
39 BOOST_REQUIRE(cc.before_commit() == 0);
40 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committing);
41 BOOST_REQUIRE(cc.ordered_commit() == 0);
42 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_ordered_commit);
43 BOOST_REQUIRE(cc.after_commit() == 0);
44 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committed);
45 BOOST_REQUIRE(cc.after_statement() == 0);
46 BOOST_REQUIRE(tc.active() == false);
47 BOOST_REQUIRE(tc.ordered() == false);
48 BOOST_REQUIRE(tc.certified() == false);
49 BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
50 }
51
52 //
53 // Test a 2PC transaction which gets BF aborted before before_prepare
54 //
BOOST_FIXTURE_TEST_CASE(transaction_2pc_bf_before_before_prepare,replicating_client_fixture_2pc)55 BOOST_FIXTURE_TEST_CASE(
56 transaction_2pc_bf_before_before_prepare,
57 replicating_client_fixture_2pc)
58 {
59 cc.start_transaction(wsrep::transaction_id(1));
60 BOOST_REQUIRE(tc.active());
61 BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
62 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing);
63 wsrep_test::bf_abort_unordered(cc);
64 BOOST_REQUIRE(cc.before_prepare());
65 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_abort);
66 BOOST_REQUIRE(tc.certified() == false);
67 BOOST_REQUIRE(tc.ordered() == false);
68 BOOST_REQUIRE(cc.before_rollback() == 0);
69 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_aborting);
70 BOOST_REQUIRE(cc.after_rollback() == 0);
71 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_aborted);
72 BOOST_REQUIRE(cc.after_statement() );
73 BOOST_REQUIRE(tc.active() == false);
74 BOOST_REQUIRE(tc.ordered() == false);
75 BOOST_REQUIRE(tc.certified() == false);
76 BOOST_REQUIRE(cc.current_error());
77 }
78
79 //
80 // Test a 2PC transaction which gets BF aborted before before_prepare
81 //
BOOST_FIXTURE_TEST_CASE(transaction_2pc_bf_before_after_prepare,replicating_client_fixture_2pc)82 BOOST_FIXTURE_TEST_CASE(
83 transaction_2pc_bf_before_after_prepare,
84 replicating_client_fixture_2pc)
85 {
86 cc.start_transaction(wsrep::transaction_id(1));
87 BOOST_REQUIRE(tc.active());
88 BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
89 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing);
90 BOOST_REQUIRE(cc.before_prepare() == 0);
91 BOOST_REQUIRE(tc.certified() == true);
92 BOOST_REQUIRE(tc.ordered() == true);
93 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_preparing);
94 wsrep_test::bf_abort_ordered(cc);
95 BOOST_REQUIRE(cc.after_prepare());
96 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
97 BOOST_REQUIRE(cc.will_replay_called() == true);
98 BOOST_REQUIRE(cc.before_rollback() == 0);
99 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
100 BOOST_REQUIRE(cc.after_rollback() == 0);
101 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
102 BOOST_REQUIRE(cc.after_statement() == 0);
103 BOOST_REQUIRE(tc.active() == false);
104 BOOST_REQUIRE(tc.ordered() == false);
105 BOOST_REQUIRE(tc.certified() == false);
106 BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
107 }
108
109 //
110 // Test a 2PC transaction which gets BF aborted after_prepare() and
111 // the rollback takes place before entering before_commit().
112 //
BOOST_FIXTURE_TEST_CASE(transaction_2pc_bf_after_after_prepare,replicating_client_fixture_2pc)113 BOOST_FIXTURE_TEST_CASE(
114 transaction_2pc_bf_after_after_prepare,
115 replicating_client_fixture_2pc)
116 {
117 cc.start_transaction(wsrep::transaction_id(1));
118 BOOST_REQUIRE(tc.active());
119 BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
120 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing);
121 BOOST_REQUIRE(cc.before_prepare() == 0);
122 BOOST_REQUIRE(cc.after_prepare() == 0);
123 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committing);
124 wsrep_test::bf_abort_ordered(cc);
125 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_abort);
126 BOOST_REQUIRE(cc.before_rollback() == 0);
127 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
128 BOOST_REQUIRE(cc.will_replay_called() == true);
129 BOOST_REQUIRE(cc.after_rollback() == 0);
130 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
131 BOOST_REQUIRE(cc.after_statement() == 0);
132 BOOST_REQUIRE(tc.active() == false);
133 BOOST_REQUIRE(tc.ordered() == false);
134 BOOST_REQUIRE(tc.certified() == false);
135 BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
136 }
137
138 //
139 // Test a 2PC transaction which gets BF aborted between after_prepare()
140 // and before_commit()
141 //
BOOST_FIXTURE_TEST_CASE(transaction_2pc_bf_before_before_commit,replicating_client_fixture_2pc)142 BOOST_FIXTURE_TEST_CASE(
143 transaction_2pc_bf_before_before_commit,
144 replicating_client_fixture_2pc)
145 {
146 cc.start_transaction(wsrep::transaction_id(1));
147 BOOST_REQUIRE(tc.active());
148 BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
149 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing);
150 BOOST_REQUIRE(cc.before_prepare() == 0);
151 BOOST_REQUIRE(cc.after_prepare() == 0);
152 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committing);
153 wsrep_test::bf_abort_ordered(cc);
154 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_abort);
155 BOOST_REQUIRE(cc.before_commit());
156 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
157 BOOST_REQUIRE(cc.will_replay_called() == true);
158 BOOST_REQUIRE(tc.certified() == true);
159 BOOST_REQUIRE(tc.ordered() == true);
160 BOOST_REQUIRE(cc.before_rollback() == 0);
161 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
162 BOOST_REQUIRE(cc.after_rollback() == 0);
163 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
164 BOOST_REQUIRE(cc.after_statement() == 0);
165 BOOST_REQUIRE(tc.active() == false);
166 BOOST_REQUIRE(tc.ordered() == false);
167 BOOST_REQUIRE(tc.certified() == false);
168 BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
169 }
170
171
172 //
173 // Test a 2PC transaction which gets BF aborted when trying to grab
174 // commit order.
175 //
BOOST_FIXTURE_TEST_CASE(transaction_2pc_bf_during_commit_order_enter,replicating_client_fixture_2pc)176 BOOST_FIXTURE_TEST_CASE(
177 transaction_2pc_bf_during_commit_order_enter,
178 replicating_client_fixture_2pc)
179 {
180 cc.start_transaction(wsrep::transaction_id(1));
181 BOOST_REQUIRE(tc.active());
182 BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
183 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing);
184 BOOST_REQUIRE(cc.before_prepare() == 0);
185 BOOST_REQUIRE(cc.after_prepare() == 0);
186 sc.provider().commit_order_enter_result_ = wsrep::provider::error_bf_abort;
187 BOOST_REQUIRE(cc.before_commit());
188 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
189 BOOST_REQUIRE(cc.will_replay_called() == true);
190 BOOST_REQUIRE(tc.certified() == true);
191 BOOST_REQUIRE(tc.ordered() == true);
192 sc.provider().commit_order_enter_result_ = wsrep::provider::success;
193 BOOST_REQUIRE(cc.before_rollback() == 0);
194 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
195 BOOST_REQUIRE(cc.after_rollback() == 0);
196 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_must_replay);
197 BOOST_REQUIRE(cc.after_statement() == 0);
198 BOOST_REQUIRE(tc.active() == false);
199 BOOST_REQUIRE(tc.ordered() == false);
200 BOOST_REQUIRE(tc.certified() == false);
201 BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
202 }
203
204 ///////////////////////////////////////////////////////////////////////////////
205 // STREAMING REPLICATION //
206 ///////////////////////////////////////////////////////////////////////////////
207
208
BOOST_FIXTURE_TEST_CASE(transaction_streaming_2pc_commit,streaming_client_fixture_row)209 BOOST_FIXTURE_TEST_CASE(transaction_streaming_2pc_commit,
210 streaming_client_fixture_row)
211 {
212 BOOST_REQUIRE(cc.start_transaction(wsrep::transaction_id(1)) == 0);
213 BOOST_REQUIRE(cc.after_row() == 0);
214 BOOST_REQUIRE(tc.streaming_context().fragments_certified() == 1);
215 BOOST_REQUIRE(cc.before_prepare() == 0);
216 BOOST_REQUIRE(cc.after_prepare() == 0);
217 BOOST_REQUIRE(cc.before_commit() == 0);
218 BOOST_REQUIRE(cc.ordered_commit() == 0);
219 BOOST_REQUIRE(cc.after_commit() == 0);
220 BOOST_REQUIRE(cc.after_statement() == 0);
221 BOOST_REQUIRE(sc.provider().fragments() == 2);
222 BOOST_REQUIRE(sc.provider().start_fragments() == 1);
223 BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
224 }
225
BOOST_FIXTURE_TEST_CASE(transaction_streaming_2pc_commit_two_statements,streaming_client_fixture_row)226 BOOST_FIXTURE_TEST_CASE(transaction_streaming_2pc_commit_two_statements,
227 streaming_client_fixture_row)
228 {
229 BOOST_REQUIRE(cc.start_transaction(wsrep::transaction_id(1)) == 0);
230 BOOST_REQUIRE(cc.after_row() == 0);
231 BOOST_REQUIRE(tc.streaming_context().fragments_certified() == 1);
232 BOOST_REQUIRE(cc.after_statement() == 0);
233 BOOST_REQUIRE(cc.before_statement() == 0);
234 BOOST_REQUIRE(cc.after_row() == 0);
235 BOOST_REQUIRE(tc.streaming_context().fragments_certified() == 2);
236 BOOST_REQUIRE(cc.before_prepare() == 0);
237 BOOST_REQUIRE(cc.after_prepare() == 0);
238 BOOST_REQUIRE(cc.before_commit() == 0);
239 BOOST_REQUIRE(cc.ordered_commit() == 0);
240 BOOST_REQUIRE(cc.after_commit() == 0);
241 BOOST_REQUIRE(cc.after_statement() == 0);
242 BOOST_REQUIRE(sc.provider().fragments() == 3);
243 BOOST_REQUIRE(sc.provider().start_fragments() == 1);
244 BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
245 }
246
247 //
248 // Fragments are removed in before_prepare in running transaction context.
249 // However, the BF abort may arrive during this removal and the
250 // client_service::remove_fragments() may roll back the transaction
251 // internally. This will cause the transaction to leave before_prepare()
252 // in aborted state.
253 //
BOOST_FIXTURE_TEST_CASE(transaction_streaming_2pc_bf_abort_during_fragment_removal,streaming_client_fixture_row)254 BOOST_FIXTURE_TEST_CASE(transaction_streaming_2pc_bf_abort_during_fragment_removal,
255 streaming_client_fixture_row)
256 {
257 BOOST_REQUIRE(cc.start_transaction(wsrep::transaction_id(1)) == 0);
258 BOOST_REQUIRE(cc.after_row() == 0);
259 BOOST_REQUIRE(tc.streaming_context().fragments_certified() == 1);
260 cc.bf_abort_during_fragment_removal_ = true;
261 BOOST_REQUIRE(cc.before_prepare());
262 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_aborted);
263 BOOST_REQUIRE(cc.after_statement());
264 BOOST_REQUIRE(tc.active() == false);
265 wsrep_test::terminate_streaming_applier(sc, sc.id(),
266 wsrep::transaction_id(1));
267 }
268
269 ///////////////////////////////////////////////////////////////////////////////
270 // APPLYING //
271 ///////////////////////////////////////////////////////////////////////////////
272
BOOST_FIXTURE_TEST_CASE(transaction_2pc_applying,applying_client_fixture_2pc)273 BOOST_FIXTURE_TEST_CASE(transaction_2pc_applying,
274 applying_client_fixture_2pc)
275 {
276 BOOST_REQUIRE(cc.before_prepare() == 0);
277 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_preparing);
278 BOOST_REQUIRE(cc.after_prepare() == 0);
279 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committing);
280 BOOST_REQUIRE(cc.before_commit() == 0);
281 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committing);
282 BOOST_REQUIRE(cc.ordered_commit() == 0);
283 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_ordered_commit);
284 BOOST_REQUIRE(cc.after_commit() == 0);
285 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committed);
286 cc.after_applying();
287 BOOST_REQUIRE(tc.state() == wsrep::transaction::s_committed);
288 BOOST_REQUIRE(tc.active() == false);
289 BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
290 }
291