358 lines
12 KiB
C++
358 lines
12 KiB
C++
/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#ifndef RECOVERY_INCLUDE
|
|
#define RECOVERY_INCLUDE
|
|
|
|
#include <mysql/group_replication_priv.h>
|
|
#include <stddef.h>
|
|
#include <list>
|
|
#include <string>
|
|
|
|
#include "plugin/group_replication/include/applier.h"
|
|
#include "plugin/group_replication/include/plugin_observers/channel_observation_manager.h"
|
|
#include "plugin/group_replication/include/recovery_state_transfer.h"
|
|
#include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/gcs_communication_interface.h"
|
|
#include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/gcs_control_interface.h"
|
|
|
|
/* The possible policies used on recovery when applying cached transactions */
|
|
enum enum_recovery_completion_policies {
|
|
RECOVERY_POLICY_WAIT_CERTIFIED =
|
|
0, // Wait for the certification of transactions
|
|
RECOVERY_POLICY_WAIT_EXECUTED, // Wait for the execution of transactions
|
|
};
|
|
|
|
class Recovery_module {
|
|
public:
|
|
/**
|
|
Recovery_module constructor
|
|
|
|
@param applier
|
|
reference to the applier
|
|
@param channel_obsr_mngr
|
|
reference to the channel hooks observation manager
|
|
@param components_stop_timeout
|
|
timeout value for the recovery module during shutdown.
|
|
*/
|
|
Recovery_module(Applier_module_interface *applier,
|
|
Channel_observation_manager *channel_obsr_mngr,
|
|
ulong components_stop_timeout);
|
|
|
|
~Recovery_module();
|
|
|
|
void set_applier_module(Applier_module_interface *applier) {
|
|
applier_module = applier;
|
|
}
|
|
|
|
/**
|
|
Starts the recovery process, initializing the recovery thread.
|
|
This method is designed to be as light as possible, as if it involved any
|
|
major computation or wait process that would block the view change process
|
|
delaying the group.
|
|
|
|
@note this method only returns when the recovery thread is already running
|
|
|
|
@param group_name the joiner's group name
|
|
@param rec_view_id the new view id
|
|
|
|
@return the operation status
|
|
@retval 0 OK
|
|
@retval !=0 Error
|
|
*/
|
|
int start_recovery(const std::string &group_name,
|
|
const std::string &rec_view_id);
|
|
|
|
/**
|
|
Recovery thread main execution method.
|
|
|
|
Here, the donor is selected, the connection to the donor is established,
|
|
and several safe keeping assurances are guaranteed, such as the applier
|
|
being suspended.
|
|
*/
|
|
int recovery_thread_handle();
|
|
|
|
/**
|
|
Set retrieved certification info from a group replication channel extracted
|
|
from a given View_change event.
|
|
|
|
@param info the given view_change_event
|
|
|
|
@return the operation status
|
|
@retval 0 OK
|
|
@retval !=0 Error
|
|
*/
|
|
int set_retrieved_cert_info(void *info);
|
|
|
|
/**
|
|
Stops the recovery process, shutting down the recovery thread.
|
|
If the thread does not stop in a user designated time interval, a timeout
|
|
is issued.
|
|
|
|
@param wait_for_termination wait for thread termination or not
|
|
|
|
@note this method only returns when the thread is stopped or on timeout
|
|
|
|
@return the operation status
|
|
@retval 0 OK
|
|
@retval !=0 Timeout
|
|
*/
|
|
int stop_recovery(bool wait_for_termination = true);
|
|
|
|
/**
|
|
This method decides what action to take when a member exits the group and
|
|
executes it.
|
|
It can for the joiner:
|
|
If it exited, then terminate the recovery process.
|
|
If the donor left, and the state transfer is still ongoing, then pick a
|
|
new one and restart the transfer.
|
|
|
|
@param did_members_left states if members left the view
|
|
@param is_leaving true if the member is leaving the group
|
|
|
|
@return the operation status
|
|
@retval 0 OK
|
|
@retval !=0 Error
|
|
*/
|
|
int update_recovery_process(bool did_members_left, bool is_leaving);
|
|
|
|
// Methods for variable updates
|
|
|
|
/** Sets the number of times recovery tries to connect to a given donor. */
|
|
void set_recovery_donor_retry_count(ulong retry_count) {
|
|
recovery_state_transfer.set_recovery_donor_retry_count(retry_count);
|
|
}
|
|
|
|
/** Sets the sleep time between connection attempts to all possible donors */
|
|
void set_recovery_donor_reconnect_interval(ulong reconnect_interval) {
|
|
recovery_state_transfer.set_recovery_donor_reconnect_interval(
|
|
reconnect_interval);
|
|
}
|
|
|
|
/**
|
|
Sets all the SSL option to use on recovery.
|
|
|
|
@param use_ssl force the use of SSL on recovery connections
|
|
@param ssl_ca SSL trusted certificate authorities file
|
|
@param ssl_capath a directory with trusted CA files
|
|
@param ssl_cert the certificate file for secure connections
|
|
@param ssl_cipher the list of ciphers to use
|
|
@param ssl_key the SSL key file
|
|
@param ssl_crl SSL revocation list file
|
|
@param ssl_crlpath path with revocation list files
|
|
@param ssl_verify_server_cert verify the hostname against the certificate
|
|
*/
|
|
void 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) {
|
|
recovery_state_transfer.set_recovery_use_ssl(use_ssl);
|
|
if (ssl_ca != NULL) recovery_state_transfer.set_recovery_ssl_ca(ssl_ca);
|
|
if (ssl_capath != NULL)
|
|
recovery_state_transfer.set_recovery_ssl_capath(ssl_capath);
|
|
if (ssl_cert != NULL)
|
|
recovery_state_transfer.set_recovery_ssl_cert(ssl_cert);
|
|
if (ssl_cipher != NULL)
|
|
recovery_state_transfer.set_recovery_ssl_cipher(ssl_cipher);
|
|
if (ssl_key != NULL) recovery_state_transfer.set_recovery_ssl_key(ssl_key);
|
|
if (ssl_crl != NULL) recovery_state_transfer.set_recovery_ssl_crl(ssl_crl);
|
|
if (ssl_crlpath != NULL)
|
|
recovery_state_transfer.set_recovery_ssl_crlpath(ssl_crlpath);
|
|
recovery_state_transfer.set_recovery_ssl_verify_server_cert(
|
|
ssl_verify_server_cert);
|
|
}
|
|
|
|
/** Set the option that forces the use of SSL on recovery connections */
|
|
void set_recovery_use_ssl(char use_ssl) {
|
|
recovery_state_transfer.set_recovery_use_ssl(use_ssl);
|
|
}
|
|
|
|
/** Set a SSL trusted certificate authorities file */
|
|
void set_recovery_ssl_ca(const char *ssl_ca) {
|
|
recovery_state_transfer.set_recovery_ssl_ca(ssl_ca);
|
|
}
|
|
|
|
/** Set a folder with SSL trusted CA files */
|
|
void set_recovery_ssl_capath(const char *ssl_capath) {
|
|
recovery_state_transfer.set_recovery_ssl_capath(ssl_capath);
|
|
}
|
|
|
|
/** Set a SSL certificate for connection */
|
|
void set_recovery_ssl_cert(const char *ssl_cert) {
|
|
recovery_state_transfer.set_recovery_ssl_cert(ssl_cert);
|
|
}
|
|
|
|
/** Set a SSL ciphers to be used */
|
|
void set_recovery_ssl_cipher(const char *ssl_cipher) {
|
|
recovery_state_transfer.set_recovery_ssl_cipher(ssl_cipher);
|
|
}
|
|
|
|
/** Set a SSL key for connections */
|
|
void set_recovery_ssl_key(const char *ssl_key) {
|
|
recovery_state_transfer.set_recovery_ssl_key(ssl_key);
|
|
}
|
|
|
|
/** Set a SSL revocation list file*/
|
|
void set_recovery_ssl_crl(const char *ssl_crl) {
|
|
recovery_state_transfer.set_recovery_ssl_crl(ssl_crl);
|
|
}
|
|
|
|
/** Set a folder with SSL revocation list files*/
|
|
void set_recovery_ssl_crlpath(const char *ssl_crlpath) {
|
|
recovery_state_transfer.set_recovery_ssl_crlpath(ssl_crlpath);
|
|
}
|
|
|
|
/** Set if recovery shall compare the used hostname against the certificate */
|
|
void set_recovery_ssl_verify_server_cert(char ssl_verify_server_cert) {
|
|
recovery_state_transfer.set_recovery_ssl_verify_server_cert(
|
|
ssl_verify_server_cert);
|
|
}
|
|
|
|
/**
|
|
@return Is recovery configured to use SSL
|
|
*/
|
|
bool get_recovery_use_ssl() {
|
|
return recovery_state_transfer.get_recovery_use_ssl();
|
|
}
|
|
|
|
/**
|
|
Get SSL options configured for recovery
|
|
|
|
@param[out] ssl_ca the ssl ca
|
|
@param[out] ssl_cert the ssl cert
|
|
@param[out] ssl_key the ssl key
|
|
*/
|
|
void get_recovery_base_ssl_options(std::string *ssl_ca, std::string *ssl_cert,
|
|
std::string *ssl_key) {
|
|
recovery_state_transfer.get_recovery_base_ssl_options(ssl_ca, ssl_cert,
|
|
ssl_key);
|
|
}
|
|
/**
|
|
Sets the recovery shutdown timeout.
|
|
|
|
@param[in] timeout the timeout
|
|
*/
|
|
void set_stop_wait_timeout(ulong timeout) {
|
|
stop_wait_timeout = timeout;
|
|
recovery_state_transfer.set_stop_wait_timeout(timeout);
|
|
}
|
|
|
|
/**
|
|
Sets recovery threshold policy on what to wait when handling transactions
|
|
@param completion_policy if recovery shall wait for execution
|
|
or certification
|
|
*/
|
|
void set_recovery_completion_policy(
|
|
enum_recovery_completion_policies completion_policy) {
|
|
this->recovery_completion_policy = completion_policy;
|
|
}
|
|
|
|
/** Set a public key file*/
|
|
void set_recovery_public_key_path(const char *public_key_path) {
|
|
if (public_key_path != NULL)
|
|
recovery_state_transfer.set_recovery_public_key_path(public_key_path);
|
|
}
|
|
|
|
/** Get public key automatically */
|
|
void set_recovery_get_public_key(bool set) {
|
|
recovery_state_transfer.set_recovery_get_public_key(set);
|
|
}
|
|
|
|
/** Set compression algorithm */
|
|
void set_recovery_compression_algorithm(const char *name) {
|
|
recovery_state_transfer.set_recovery_compression_algorithm(name);
|
|
}
|
|
|
|
/** Set compression level */
|
|
void set_recovery_zstd_compression_level(uint level) {
|
|
recovery_state_transfer.set_recovery_zstd_compression_level(level);
|
|
}
|
|
|
|
/**
|
|
Checks if the given id matches the recovery applier thread
|
|
@param id the thread id
|
|
|
|
@return if it belongs to a thread
|
|
@retval true the id matches a SQL or worker thread
|
|
@retval false the id doesn't match any thread
|
|
*/
|
|
bool is_own_event_channel(my_thread_id id);
|
|
|
|
private:
|
|
/** Sets the thread context */
|
|
void set_recovery_thread_context();
|
|
|
|
/**
|
|
Handles code for removing the member in case of a failure during
|
|
recovery.
|
|
*/
|
|
void leave_group_on_recovery_failure();
|
|
|
|
/** Cleans the recovery thread related options/structures. */
|
|
void clean_recovery_thread_context();
|
|
|
|
/**
|
|
Starts a wait process until the applier fulfills the necessary condition for
|
|
the member to be acknowledge as being online.
|
|
|
|
@return the operation status
|
|
@retval 0 OK
|
|
@retval !=0 Error
|
|
*/
|
|
int wait_for_applier_module_recovery();
|
|
|
|
/**
|
|
Sends a message throughout the group stating the member as online.
|
|
*/
|
|
void notify_group_recovery_end();
|
|
|
|
// recovery thread variables
|
|
my_thread_handle recovery_pthd;
|
|
THD *recovery_thd;
|
|
|
|
/* The plugin's applier module interface*/
|
|
Applier_module_interface *applier_module;
|
|
|
|
/* The group to which the recovering member belongs */
|
|
std::string group_name;
|
|
|
|
/* The recovery state transfer class */
|
|
Recovery_state_transfer recovery_state_transfer;
|
|
|
|
/* Recovery thread state */
|
|
thread_state recovery_thd_state;
|
|
/* Recovery abort flag */
|
|
bool recovery_aborted;
|
|
|
|
// run conditions and locks
|
|
mysql_mutex_t run_lock;
|
|
mysql_cond_t run_cond;
|
|
|
|
/* Recovery strategy when waiting for the cache transaction handling*/
|
|
enum_recovery_completion_policies recovery_completion_policy;
|
|
|
|
/* Recovery module's timeout on shutdown */
|
|
ulong stop_wait_timeout;
|
|
};
|
|
|
|
#endif /* RECOVERY_INCLUDE */
|