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 #ifndef WSREP_MOCK_SERVER_STATE_HPP
21 #define WSREP_MOCK_SERVER_STATE_HPP
22 
23 #include "wsrep/server_state.hpp"
24 #include "wsrep/server_service.hpp"
25 #include "mock_client_state.hpp"
26 #include "mock_high_priority_service.hpp"
27 #include "mock_storage_service.hpp"
28 #include "mock_provider.hpp"
29 
30 #include "wsrep/compiler.hpp"
31 
32 namespace wsrep
33 {
34     class mock_server_service : public wsrep::server_service
35     {
36     public:
mock_server_service(wsrep::server_state & server_state)37         mock_server_service(wsrep::server_state& server_state)
38             : sync_point_enabled_()
39             , sync_point_action_()
40             , sst_before_init_()
41             , server_state_(server_state)
42             , last_client_id_(0)
43             , last_transaction_id_(0)
44             , logged_view_()
45             , position_()
46         { }
47 
storage_service(wsrep::client_service &)48         wsrep::storage_service* storage_service(wsrep::client_service&)
49             WSREP_OVERRIDE
50         {
51             return new wsrep::mock_storage_service(server_state_,
52                                                    wsrep::client_id(++last_client_id_));
53         }
54 
storage_service(wsrep::high_priority_service &)55         wsrep::storage_service* storage_service(wsrep::high_priority_service&)
56             WSREP_OVERRIDE
57         {
58             return new wsrep::mock_storage_service(server_state_,
59                                                    wsrep::client_id(++last_client_id_));
60         }
61 
release_storage_service(wsrep::storage_service * storage_service)62         void release_storage_service(wsrep::storage_service* storage_service)
63             WSREP_OVERRIDE
64         {
65             delete storage_service;
66         }
67 
streaming_applier_service(wsrep::client_service &)68         wsrep::high_priority_service* streaming_applier_service(
69             wsrep::client_service&)
70             WSREP_OVERRIDE
71         {
72             wsrep::mock_client* cs(new wsrep::mock_client(
73                                        server_state_,
74                                        wsrep::client_id(++last_client_id_),
75                                        wsrep::client_state::m_high_priority));
76             wsrep::mock_high_priority_service* ret(
77                 new wsrep::mock_high_priority_service(server_state_,
78                                                       cs, false));
79             cs->open(cs->id());
80             cs->before_command();
81             return ret;
82         }
83 
streaming_applier_service(wsrep::high_priority_service &)84         wsrep::high_priority_service* streaming_applier_service(
85             wsrep::high_priority_service&) WSREP_OVERRIDE
86         {
87             wsrep::mock_client* cs(new wsrep::mock_client(
88                                        server_state_,
89                                        wsrep::client_id(++last_client_id_),
90                                        wsrep::client_state::m_high_priority));
91             wsrep::mock_high_priority_service* ret(
92                 new wsrep::mock_high_priority_service(server_state_,
93                                                       cs, false));
94             cs->open(cs->id());
95             cs->before_command();
96             return ret;
97         }
98 
release_high_priority_service(wsrep::high_priority_service * high_priority_service)99         void release_high_priority_service(
100             wsrep::high_priority_service *high_priority_service)
101             WSREP_OVERRIDE
102         {
103             mock_high_priority_service* mhps(
104                 static_cast<mock_high_priority_service*>(high_priority_service));
105             wsrep::mock_client* cs(&static_cast<wsrep::mock_client&>(
106                                        mhps->client_state()));
107             cs->after_command_before_result();
108             cs->after_command_after_result();
109             cs->close();
110             cs->cleanup();
111             delete cs;
112             delete mhps;
113         }
bootstrap()114         void bootstrap() WSREP_OVERRIDE { }
log_message(enum wsrep::log::level level,const char * message)115         void log_message(enum wsrep::log::level level, const char* message)
116             WSREP_OVERRIDE
117         {
118             wsrep::log(level, server_state_.name().c_str()) << message;
119         }
log_dummy_write_set(wsrep::client_state &,const wsrep::ws_meta &)120         void log_dummy_write_set(wsrep::client_state&,
121                                  const wsrep::ws_meta&)
122             WSREP_OVERRIDE
123         {
124         }
log_view(wsrep::high_priority_service *,const wsrep::view & view)125         void log_view(wsrep::high_priority_service*, const wsrep::view& view)
126             WSREP_OVERRIDE
127         {
128             logged_view_ = view;
129         }
130 
recover_streaming_appliers(wsrep::client_service &)131         void recover_streaming_appliers(wsrep::client_service&)
132             WSREP_OVERRIDE
133         { }
134 
recover_streaming_appliers(wsrep::high_priority_service &)135         void recover_streaming_appliers(wsrep::high_priority_service&)
136             WSREP_OVERRIDE
137         { }
138 
get_view(wsrep::client_service &,const wsrep::id & own_id)139         wsrep::view get_view(wsrep::client_service&, const wsrep::id& own_id)
140             WSREP_OVERRIDE
141         {
142             int const my_idx(logged_view_.member_index(own_id));
143             wsrep::view my_view(
144                 logged_view_.state_id(),
145                 logged_view_.view_seqno(),
146                 logged_view_.status(),
147                 logged_view_.capabilities(),
148                 my_idx,
149                 logged_view_.protocol_version(),
150                 logged_view_.members()
151             );
152             return my_view;
153         }
154 
get_position(wsrep::client_service &)155         wsrep::gtid get_position(wsrep::client_service&) WSREP_OVERRIDE
156         {
157             return position_;
158         }
159 
set_position(wsrep::client_service &,const wsrep::gtid & gtid)160         void set_position(wsrep::client_service&,
161                           const wsrep::gtid& gtid) WSREP_OVERRIDE
162         {
163             position_ = gtid;
164         }
165 
log_state_change(enum wsrep::server_state::state,enum wsrep::server_state::state)166         void log_state_change(enum wsrep::server_state::state,
167                               enum wsrep::server_state::state)
168             WSREP_OVERRIDE
169         { }
sst_before_init() const170         bool sst_before_init() const WSREP_OVERRIDE
171         { return sst_before_init_; }
sst_request()172         std::string sst_request() WSREP_OVERRIDE { return ""; }
start_sst(const std::string &,const wsrep::gtid &,bool)173         int start_sst(const std::string&,
174                       const wsrep::gtid&,
175                       bool) WSREP_OVERRIDE { return 0; }
background_rollback(wsrep::client_state & client_state)176         void background_rollback(wsrep::client_state& client_state)
177             WSREP_OVERRIDE
178         {
179             client_state.before_rollback();
180             client_state.after_rollback();
181         }
182 
wait_committing_transactions(int)183         int wait_committing_transactions(int) WSREP_OVERRIDE { return 0; }
184 
next_transaction_id()185         wsrep::transaction_id next_transaction_id()
186         {
187             return wsrep::transaction_id(++last_transaction_id_);
188         }
189 
debug_sync(const char * sync_point)190         void debug_sync(const char* sync_point) WSREP_OVERRIDE
191         {
192             if (sync_point_enabled_ == sync_point)
193             {
194                 switch (sync_point_action_)
195                 {
196                 case spa_none:
197                     break;
198                 case spa_initialize:
199                     server_state_.initialized();
200                     break;
201                 case spa_initialize_error:
202                     throw wsrep::runtime_error("Inject initialization error");
203                     break;
204                 }
205             }
206         }
207 
208         std::string sync_point_enabled_;
209         enum sync_point_action
210         {
211             spa_none,
212             spa_initialize,
213             spa_initialize_error
214 
215         } sync_point_action_;
216         bool sst_before_init_;
217 
logged_view(const wsrep::view & view)218         void logged_view(const wsrep::view& view)
219         {
220             logged_view_ = view;
221         }
position(const wsrep::gtid & position)222         void position(const wsrep::gtid& position)
223         {
224             position_ = position;
225         }
226     private:
227         wsrep::server_state& server_state_;
228         unsigned long long last_client_id_;
229         unsigned long long last_transaction_id_;
230         wsrep::view logged_view_;
231         wsrep::gtid position_;
232     };
233 
234 
235     class mock_server_state : public wsrep::server_state
236     {
237     public:
mock_server_state(const std::string & name,enum wsrep::server_state::rollback_mode rollback_mode,wsrep::server_service & server_service)238         mock_server_state(const std::string& name,
239                           enum wsrep::server_state::rollback_mode rollback_mode,
240                           wsrep::server_service& server_service)
241             : wsrep::server_state(mutex_, cond_, server_service, NULL,
242                                   name, "", "", "./",
243                                   wsrep::gtid::undefined(),
244                                   1,
245                                   rollback_mode)
246             , mutex_()
247             , cond_()
248             , provider_(*this)
249         { }
250 
provider() const251         wsrep::mock_provider& provider() const WSREP_OVERRIDE
252         { return provider_; }
253 
254         // mock connected state for tests without overriding the connect()
255         // method.
mock_connect(const std::string & own_id,const std::string & cluster_name,const std::string & cluster_address,const std::string & state_donor,bool bootstrap)256         int mock_connect(const std::string& own_id,
257                          const std::string& cluster_name,
258                          const std::string& cluster_address,
259                          const std::string& state_donor,
260                          bool bootstrap)
261         {
262             int const ret(server_state::connect(cluster_name,
263                                                 cluster_address,
264                                                 state_donor,
265                                                 bootstrap));
266             if (0 == ret)
267             {
268                 wsrep::id cluster_id("1");
269                 wsrep::gtid state_id(cluster_id, wsrep::seqno(0));
270                 std::vector<wsrep::view::member> members;
271                 members.push_back(wsrep::view::member(wsrep::id(own_id),
272                                                       "name", ""));
273                 wsrep::view bootstrap_view(state_id,
274                                            wsrep::seqno(1),
275                                            wsrep::view::primary,
276                                            0,
277                                            0,
278                                            1,
279                                            members);
280                 server_state::on_connect(bootstrap_view);
281             }
282             else
283             {
284                 assert(0);
285             }
286 
287             return ret;
288         }
289 
mock_connect()290         int mock_connect()
291         {
292              return mock_connect(name(), "cluster", "local", "0", false);
293         }
294 
295     private:
296         wsrep::default_mutex mutex_;
297         wsrep::default_condition_variable cond_;
298         mutable wsrep::mock_provider provider_;
299     };
300 }
301 
302 #endif // WSREP_MOCK_SERVER_STATE_HPP
303