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 "mock_high_priority_service.hpp"
21 #include "mock_server_state.hpp"
22 #include <sstream>
23 
start_transaction(const wsrep::ws_handle & ws_handle,const wsrep::ws_meta & ws_meta)24 int wsrep::mock_high_priority_service::start_transaction(
25     const wsrep::ws_handle& ws_handle, const wsrep::ws_meta& ws_meta)
26 {
27     return client_state_->start_transaction(ws_handle, ws_meta);
28 }
29 
next_fragment(const wsrep::ws_meta & ws_meta)30 int wsrep::mock_high_priority_service::next_fragment(
31     const wsrep::ws_meta& ws_meta)
32 {
33     return client_state_->next_fragment(ws_meta);
34 }
35 
adopt_transaction(const wsrep::transaction & transaction)36 int wsrep::mock_high_priority_service::adopt_transaction(
37     const wsrep::transaction& transaction)
38 {
39     client_state_->adopt_transaction(transaction);
40     if (transaction.state() == wsrep::transaction::s_prepared)
41     {
42         client_state_->restore_xid(transaction.xid());
43     }
44     return 0;
45 }
46 
apply_write_set(const wsrep::ws_meta & meta,const wsrep::const_buffer &,wsrep::mutable_buffer & err)47 int wsrep::mock_high_priority_service::apply_write_set(
48     const wsrep::ws_meta& meta,
49     const wsrep::const_buffer&,
50     wsrep::mutable_buffer& err)
51 {
52     assert(client_state_->toi_meta().seqno().is_undefined());
53     assert(client_state_->transaction().state() == wsrep::transaction::s_executing ||
54            client_state_->transaction().state() == wsrep::transaction::s_prepared ||
55            client_state_->transaction().state() == wsrep::transaction::s_replaying);
56     if (fail_next_applying_)
57     {
58         std::ostringstream os;
59         os << "failed " << meta;
60         err.push_back(os.str());
61         assert(err.size() > 0);
62         return 1;
63     }
64     else
65     {
66         int ret(0);
67         if (!(meta.flags() & wsrep::provider::flag::commit))
68         {
69             client_state_->fragment_applied(meta.seqno());
70         }
71         if ((meta.flags() & wsrep::provider::flag::prepare))
72         {
73             client_state_->assign_xid(wsrep::xid(1, 3, 1, "xid"));
74             ret = client_state_->before_prepare() ||
75             client_state_->after_prepare();
76         }
77         return ret;
78     };
79 }
80 
commit(const wsrep::ws_handle & ws_handle,const wsrep::ws_meta & ws_meta)81 int wsrep::mock_high_priority_service::commit(
82     const wsrep::ws_handle& ws_handle,
83     const wsrep::ws_meta& ws_meta)
84 {
85     int ret(0);
86     client_state_->prepare_for_ordering(ws_handle, ws_meta, true);
87     if (do_2pc_)
88     {
89         ret = client_state_->before_prepare() ||
90             client_state_->after_prepare();
91     }
92     const bool is_ordered= !ws_meta.seqno().is_undefined();
93     if (!is_ordered)
94     {
95         client_state_->before_rollback();
96         client_state_->after_rollback();
97         return 0;
98     }
99     else
100     {
101         return (ret || client_state_->before_commit() ||
102                 client_state_->ordered_commit() ||
103                 client_state_->after_commit());
104     }
105 }
106 
rollback(const wsrep::ws_handle & ws_handle,const wsrep::ws_meta & ws_meta)107 int wsrep::mock_high_priority_service::rollback(
108     const wsrep::ws_handle& ws_handle,
109     const wsrep::ws_meta& ws_meta)
110 {
111     client_state_->prepare_for_ordering(ws_handle, ws_meta, false);
112     return (client_state_->before_rollback() ||
113             client_state_->after_rollback());
114 }
115 
apply_toi(const wsrep::ws_meta &,const wsrep::const_buffer &,wsrep::mutable_buffer &)116 int wsrep::mock_high_priority_service::apply_toi(const wsrep::ws_meta&,
117                                                  const wsrep::const_buffer&,
118                                                  wsrep::mutable_buffer&)
119 {
120     assert(client_state_->transaction().active() == false);
121     assert(client_state_->toi_meta().seqno().is_undefined() == false);
122     return (fail_next_toi_ ? 1 : 0);
123 }
124 
apply_nbo_begin(const wsrep::ws_meta & ws_meta,const wsrep::const_buffer &,wsrep::mutable_buffer &)125 int wsrep::mock_high_priority_service::apply_nbo_begin(
126     const wsrep::ws_meta& ws_meta,
127     const wsrep::const_buffer&,
128     wsrep::mutable_buffer&)
129 {
130     const int nbo_begin_flags __attribute__((unused))
131         (wsrep::provider::flag::isolation |
132          wsrep::provider::flag::start_transaction);
133     assert(ws_meta.flags() & nbo_begin_flags);
134     assert((ws_meta.flags() & ~nbo_begin_flags) == 0);
135 
136     if (fail_next_toi_)
137     {
138         return 1;
139     }
140     else
141     {
142         nbo_cs_ = std::unique_ptr<wsrep::mock_client>(
143             new wsrep::mock_client(client_state_->server_state(),
144                                    wsrep::client_id(1),
145                                    wsrep::client_state::m_local));
146         nbo_cs_->open(wsrep::client_id(1));
147         nbo_cs_->before_command();
148         nbo_cs_->before_statement();
149         return nbo_cs_->enter_nbo_mode(ws_meta);
150     }
151 }
152 
adopt_apply_error(wsrep::mutable_buffer & err)153 void wsrep::mock_high_priority_service::adopt_apply_error(
154     wsrep::mutable_buffer& err)
155 {
156     client_state_->adopt_apply_error(err);
157 }
158 
after_apply()159 void wsrep::mock_high_priority_service::after_apply()
160 {
161     client_state_->after_applying();
162 }
163 
log_dummy_write_set(const wsrep::ws_handle &,const wsrep::ws_meta &,wsrep::mutable_buffer & err)164 int wsrep::mock_high_priority_service::log_dummy_write_set(
165     const wsrep::ws_handle&,
166     const wsrep::ws_meta&,
167     wsrep::mutable_buffer& err)
168 {
169     return err.size() > 0;
170 }
171