1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software Foundation, 21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 22 23 #ifndef RECOVERY_INCLUDE 24 #define RECOVERY_INCLUDE 25 26 #include <list> 27 #include <string> 28 29 #include "applier.h" 30 #include "channel_observation_manager.h" 31 #include "recovery_state_transfer.h" 32 #include <mysql/gcs/gcs_communication_interface.h> 33 #include <mysql/gcs/gcs_control_interface.h> 34 #include <mysql/group_replication_priv.h> 35 36 /* The possible policies used on recovery when applying cached transactions */ 37 enum enum_recovery_completion_policies 38 { 39 RECOVERY_POLICY_WAIT_CERTIFIED= 0, // Wait for the certification of transactions 40 RECOVERY_POLICY_WAIT_EXECUTED, // Wait for the execution of transactions 41 }; 42 43 class Recovery_module 44 { 45 46 public: 47 /** 48 Recovery_module constructor 49 50 @param applier 51 reference to the applier 52 @param channel_obsr_mngr 53 reference to the channel hooks observation manager 54 @param components_stop_timeout 55 timeout value for the recovery module during shutdown. 56 */ 57 Recovery_module(Applier_module_interface *applier, 58 Channel_observation_manager *channel_obsr_mngr, 59 ulong components_stop_timeout); 60 61 ~Recovery_module(); 62 set_applier_module(Applier_module_interface * applier)63 void set_applier_module(Applier_module_interface *applier) 64 { 65 applier_module= applier; 66 } 67 68 /** 69 Starts the recovery process, initializing the recovery thread. 70 This method is designed to be as light as possible, as if it involved any 71 major computation or wait process that would block the view change process 72 delaying the group. 73 74 @note this method only returns when the recovery thread is already running 75 76 @param group_name the joiner's group name 77 @param rec_view_id the new view id 78 79 @return the operation status 80 @retval 0 OK 81 @retval !=0 Error 82 */ 83 int start_recovery(const std::string& group_name, 84 const std::string& rec_view_id); 85 86 /** 87 Recovery thread main execution method. 88 89 Here, the donor is selected, the connection to the donor is established, 90 and several safe keeping assurances are guaranteed, such as the applier 91 being suspended. 92 */ 93 int recovery_thread_handle(); 94 95 /** 96 Set retrieved certification info from a group replication channel extracted 97 from a given View_change event. 98 99 @param info the given view_change_event 100 101 @return the operation status 102 @retval 0 OK 103 @retval !=0 Error 104 */ 105 int set_retrieved_cert_info(void* info); 106 107 /** 108 Stops the recovery process, shutting down the recovery thread. 109 If the thread does not stop in a user designated time interval, a timeout 110 is issued. 111 112 @note this method only returns when the thread is stopped or on timeout 113 114 @return the operation status 115 @retval 0 OK 116 @retval !=0 Timeout 117 */ 118 int stop_recovery(); 119 120 /** 121 This method decides what action to take when a member exits the group and 122 executes it. 123 It can for the joiner: 124 If it exited, then terminate the recovery process. 125 If the donor left, and the state transfer is still ongoing, then pick a 126 new one and restart the transfer. 127 128 @param did_members_left states if members left the view 129 @param is_leaving true if the member is leaving the group 130 131 @return the operation status 132 @retval 0 OK 133 @retval !=0 Error 134 */ 135 int update_recovery_process(bool did_members_left, bool is_leaving); 136 137 //Methods for variable updates 138 139 /** Sets the number of times recovery tries to connect to a given donor. */ set_recovery_donor_retry_count(ulong retry_count)140 void set_recovery_donor_retry_count(ulong retry_count) 141 { 142 recovery_state_transfer.set_recovery_donor_retry_count(retry_count); 143 } 144 145 /** Sets the sleep time between connection attempts to all possible donors */ set_recovery_donor_reconnect_interval(ulong reconnect_interval)146 void set_recovery_donor_reconnect_interval(ulong reconnect_interval) 147 { 148 recovery_state_transfer. 149 set_recovery_donor_reconnect_interval(reconnect_interval); 150 } 151 152 /** 153 Sets all the SSL option to use on recovery. 154 155 @param use_ssl force the use of SSL on recovery connections 156 @param ssl_ca SSL trusted certificate authorities file 157 @param ssl_capath a directory with trusted CA files 158 @param ssl_cert the certificate file for secure connections 159 @param ssl_cipher the list of ciphers to use 160 @param ssl_key the SSL key file 161 @param ssl_crl SSL revocation list file 162 @param ssl_crlpath path with revocation list files 163 @param ssl_verify_server_cert verify the hostname against the certificate 164 */ set_recovery_ssl_options(bool use_ssl,const char * ssl_ca,const char * ssl_capath,const char * ssl_cert,const char * ssl_cipher,const char * ssl_key,const char * ssl_crl,const char * ssl_crlpath,bool ssl_verify_server_cert)165 void set_recovery_ssl_options(bool use_ssl, 166 const char *ssl_ca, 167 const char *ssl_capath, 168 const char *ssl_cert, 169 const char *ssl_cipher, 170 const char *ssl_key, 171 const char *ssl_crl, 172 const char *ssl_crlpath, 173 bool ssl_verify_server_cert) 174 { 175 recovery_state_transfer.set_recovery_use_ssl(use_ssl); 176 if (ssl_ca != NULL) 177 recovery_state_transfer.set_recovery_ssl_ca(ssl_ca); 178 if (ssl_capath != NULL) 179 recovery_state_transfer.set_recovery_ssl_capath(ssl_capath); 180 if (ssl_cert != NULL) 181 recovery_state_transfer.set_recovery_ssl_cert(ssl_cert); 182 if (ssl_cipher != NULL) 183 recovery_state_transfer.set_recovery_ssl_cipher(ssl_cipher); 184 if (ssl_key != NULL) 185 recovery_state_transfer.set_recovery_ssl_key(ssl_key); 186 if (ssl_crl != NULL) 187 recovery_state_transfer.set_recovery_ssl_crl(ssl_crl); 188 if (ssl_crlpath != NULL) 189 recovery_state_transfer.set_recovery_ssl_crlpath(ssl_crlpath); 190 recovery_state_transfer. 191 set_recovery_ssl_verify_server_cert(ssl_verify_server_cert); 192 } 193 194 /** Set the option that forces the use of SSL on recovery connections */ set_recovery_use_ssl(char use_ssl)195 void set_recovery_use_ssl(char use_ssl) 196 { 197 recovery_state_transfer.set_recovery_use_ssl(use_ssl); 198 } 199 200 /** Set a SSL trusted certificate authorities file */ set_recovery_ssl_ca(const char * ssl_ca)201 void set_recovery_ssl_ca(const char* ssl_ca) 202 { 203 recovery_state_transfer.set_recovery_ssl_ca(ssl_ca); 204 } 205 206 /** Set a folder with SSL trusted CA files */ set_recovery_ssl_capath(const char * ssl_capath)207 void set_recovery_ssl_capath(const char* ssl_capath) 208 { 209 recovery_state_transfer.set_recovery_ssl_capath(ssl_capath); 210 } 211 212 /** Set a SSL certificate for connection */ set_recovery_ssl_cert(const char * ssl_cert)213 void set_recovery_ssl_cert(const char* ssl_cert) 214 { 215 recovery_state_transfer.set_recovery_ssl_cert(ssl_cert); 216 } 217 218 /** Set a SSL ciphers to be used */ set_recovery_ssl_cipher(const char * ssl_cipher)219 void set_recovery_ssl_cipher(const char* ssl_cipher) 220 { 221 recovery_state_transfer.set_recovery_ssl_cipher(ssl_cipher); 222 } 223 224 /** Set a SSL key for connections */ set_recovery_ssl_key(const char * ssl_key)225 void set_recovery_ssl_key(const char* ssl_key) 226 { 227 recovery_state_transfer.set_recovery_ssl_key(ssl_key); 228 } 229 230 /** Set a SSL revocation list file*/ set_recovery_ssl_crl(const char * ssl_crl)231 void set_recovery_ssl_crl(const char* ssl_crl) 232 { 233 recovery_state_transfer.set_recovery_ssl_crl(ssl_crl); 234 } 235 236 /** Set a folder with SSL revocation list files*/ set_recovery_ssl_crlpath(const char * ssl_crlpath)237 void set_recovery_ssl_crlpath(const char* ssl_crlpath) 238 { 239 recovery_state_transfer.set_recovery_ssl_crlpath(ssl_crlpath); 240 } 241 242 /** Set if recovery shall compare the used hostname against the certificate */ set_recovery_ssl_verify_server_cert(char ssl_verify_server_cert)243 void set_recovery_ssl_verify_server_cert(char ssl_verify_server_cert) 244 { 245 recovery_state_transfer.set_recovery_ssl_verify_server_cert(ssl_verify_server_cert); 246 } 247 248 /** 249 Sets the recovery shutdown timeout. 250 251 @param[in] timeout the timeout 252 */ set_stop_wait_timeout(ulong timeout)253 void set_stop_wait_timeout (ulong timeout){ 254 stop_wait_timeout= timeout; 255 recovery_state_transfer.set_stop_wait_timeout(timeout); 256 } 257 258 /** 259 Sets recovery threshold policy on what to wait when handling transactions 260 @param completion_policy if recovery shall wait for execution 261 or certification 262 */ 263 void set_recovery_completion_policy(enum_recovery_completion_policies completion_policy)264 set_recovery_completion_policy(enum_recovery_completion_policies completion_policy) 265 { 266 this->recovery_completion_policy= completion_policy; 267 } 268 269 /** 270 Checks if the given id matches the recovery applier thread 271 @param id the thread id 272 273 @return if it belongs to a thread 274 @retval true the id matches a SQL or worker thread 275 @retval false the id doesn't match any thread 276 */ 277 bool is_own_event_channel(my_thread_id id); 278 279 private: 280 281 /** Sets the thread context */ 282 void set_recovery_thread_context(); 283 284 /** 285 Handles code for removing the member in case of a failure during 286 recovery. 287 */ 288 void leave_group_on_recovery_failure(); 289 290 /** Cleans the recovery thread related options/structures. */ 291 void clean_recovery_thread_context(); 292 293 /** 294 Starts a wait process until the applier fulfills the necessary condition for 295 the member to be acknowledge as being online. 296 297 @return the operation status 298 @retval 0 OK 299 @retval !=0 Error 300 */ 301 int wait_for_applier_module_recovery(); 302 303 /** 304 Sends a message throughout the group stating the member as online. 305 */ 306 void notify_group_recovery_end(); 307 308 //recovery thread variables 309 my_thread_handle recovery_pthd; 310 THD *recovery_thd; 311 312 /* The plugin's applier module interface*/ 313 Applier_module_interface *applier_module; 314 315 /* The group to which the recovering member belongs */ 316 std::string group_name; 317 318 /* The recovery state transfer class */ 319 Recovery_state_transfer recovery_state_transfer; 320 321 /* Recovery running flag */ 322 bool recovery_running; 323 /* Recovery abort flag */ 324 bool recovery_aborted; 325 /* Recovery starting flag */ 326 bool recovery_starting; 327 328 //run conditions and locks 329 mysql_mutex_t run_lock; 330 mysql_cond_t run_cond; 331 332 /* Recovery strategy when waiting for the cache transaction handling*/ 333 enum_recovery_completion_policies recovery_completion_policy; 334 335 /* Recovery module's timeout on shutdown */ 336 ulong stop_wait_timeout; 337 }; 338 339 #endif /* RECOVERY_INCLUDE */ 340