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