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