409 lines
12 KiB
C++
409 lines
12 KiB
C++
/* Copyright (c) 2013, 2018, 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 as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
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 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,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
|
|
|
#include "rpl_group_replication.h"
|
|
#include "rpl_channel_service_interface.h"
|
|
#include "rpl_info_factory.h"
|
|
#include "rpl_slave.h"
|
|
#include "tc_log.h"
|
|
#include "mysqld_thd_manager.h"
|
|
#include "log.h"
|
|
|
|
|
|
|
|
/**
|
|
Static name of Group Replication plugin.
|
|
*/
|
|
LEX_CSTRING group_replication_plugin_name_str= {
|
|
C_STRING_WITH_LEN("group_replication")
|
|
};
|
|
|
|
|
|
/*
|
|
Group Replication plugin handler function accessors.
|
|
*/
|
|
#ifdef HAVE_REPLICATION
|
|
int group_replication_init()
|
|
{
|
|
return initialize_channel_service_interface();
|
|
}
|
|
#endif
|
|
|
|
|
|
bool is_group_replication_plugin_loaded()
|
|
{
|
|
bool result= false;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
plugin_unlock(0, plugin);
|
|
result= true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int group_replication_start()
|
|
{
|
|
int result= 1;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
/*
|
|
We need to take global_sid_lock because
|
|
group_replication_handler->start function will (among other
|
|
things) do the following:
|
|
|
|
1. Call get_server_startup_prerequirements, which calls get_gtid_mode.
|
|
2. Set plugin-internal state that ensures that
|
|
is_group_replication_running() returns true.
|
|
|
|
In order to prevent a concurrent client from executing SET
|
|
GTID_MODE=ON_PERMISSIVE between 1 and 2, we must hold
|
|
gtid_mode_lock.
|
|
*/
|
|
gtid_mode_lock->rdlock();
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->start();
|
|
gtid_mode_lock->unlock();
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
else
|
|
{
|
|
sql_print_error("Group Replication plugin is not installed.");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int group_replication_stop()
|
|
{
|
|
int result= 1;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->stop();
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
else
|
|
{
|
|
sql_print_error("Group Replication plugin is not installed.");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool is_group_replication_running()
|
|
{
|
|
bool result= false;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->is_running();
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int set_group_replication_retrieved_certification_info(View_change_log_event *view_change_event)
|
|
{
|
|
int result= 1;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->set_retrieved_certification_info(view_change_event);
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool get_group_replication_connection_status_info(
|
|
const GROUP_REPLICATION_CONNECTION_STATUS_CALLBACKS& callbacks)
|
|
{
|
|
bool result= true;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->get_connection_status_info(callbacks);
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool get_group_replication_group_members_info(
|
|
unsigned int index,
|
|
const GROUP_REPLICATION_GROUP_MEMBERS_CALLBACKS& callbacks)
|
|
{
|
|
bool result= true;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->get_group_members_info(index, callbacks);
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool get_group_replication_group_member_stats_info(
|
|
const GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS& callbacks)
|
|
{
|
|
bool result= true;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->get_group_member_stats_info(callbacks);
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
unsigned int get_group_replication_members_number_info()
|
|
{
|
|
unsigned int result= 0;
|
|
|
|
plugin_ref plugin= my_plugin_lock_by_name(0,
|
|
group_replication_plugin_name_str,
|
|
MYSQL_GROUP_REPLICATION_PLUGIN);
|
|
if (plugin != NULL)
|
|
{
|
|
st_mysql_group_replication *plugin_handle=
|
|
(st_mysql_group_replication*) plugin_decl(plugin)->info;
|
|
result= plugin_handle->get_members_number_info();
|
|
|
|
plugin_unlock(0, plugin);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Server methods exported to plugin through
|
|
include/mysql/group_replication_priv.h
|
|
*/
|
|
#ifdef HAVE_REPLICATION
|
|
void get_server_parameters(char **hostname, uint *port, char** uuid,
|
|
unsigned int *out_server_version,
|
|
st_server_ssl_variables* server_ssl_variables)
|
|
{
|
|
/*
|
|
use startup option report-host and report-port when provided,
|
|
as value provided by glob_hostname, which used gethostname() function
|
|
internally to determine hostname, will not always provide correct
|
|
network interface, especially in case of multiple network interfaces.
|
|
*/
|
|
if (report_host)
|
|
*hostname= report_host;
|
|
else
|
|
*hostname= glob_hostname;
|
|
|
|
if (report_port)
|
|
*port= report_port;
|
|
else
|
|
*port= mysqld_port;
|
|
|
|
*uuid= server_uuid;
|
|
|
|
//Convert server version to hex
|
|
|
|
ulong major= 0, minor= 0, patch= 0;
|
|
char *pos= server_version, *end_pos;
|
|
//extract each server decimal number, e.g., for 5.9.30 -> 5, 9 and 30
|
|
major= strtoul(pos, &end_pos, 10); pos=end_pos+1;
|
|
minor= strtoul(pos, &end_pos, 10); pos=end_pos+1;
|
|
patch= strtoul(pos, &end_pos, 10);
|
|
|
|
/*
|
|
Convert to a equivalent hex representation.
|
|
5.9.30 -> 0x050930
|
|
version= 0 x 16^5 + 5 x 16^4 + 0 x 16^3 + 9 x 16^2 + 3 x 16^1 + 0 x 16^0
|
|
*/
|
|
int v1= patch / 10;
|
|
int v0= patch - v1 * 10;
|
|
int v3= minor / 10;
|
|
int v2= minor - v3 * 10;
|
|
int v5= major / 10;
|
|
int v4= major - v5 * 10;
|
|
|
|
*out_server_version= v0 + v1 * 16 + v2 * 256 + v3 * 4096 + v4 * 65536 + v5 * 1048576;
|
|
|
|
server_ssl_variables->have_ssl_opt= (have_ssl == SHOW_OPTION_YES);
|
|
server_ssl_variables->ssl_ca= opt_ssl_ca;
|
|
server_ssl_variables->ssl_capath= opt_ssl_capath;
|
|
server_ssl_variables->tls_version= opt_tls_version;
|
|
server_ssl_variables->ssl_cert= opt_ssl_cert;
|
|
server_ssl_variables->ssl_cipher= opt_ssl_cipher;
|
|
server_ssl_variables->ssl_key= opt_ssl_key;
|
|
server_ssl_variables->ssl_crl= opt_ssl_crl;
|
|
server_ssl_variables->ssl_crlpath= opt_ssl_crlpath;
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ulong get_server_id()
|
|
{
|
|
return server_id;
|
|
}
|
|
|
|
ulong get_auto_increment_increment()
|
|
{
|
|
return global_system_variables.auto_increment_increment;
|
|
}
|
|
|
|
ulong get_auto_increment_offset()
|
|
{
|
|
return global_system_variables.auto_increment_offset;
|
|
}
|
|
|
|
void set_auto_increment_increment(ulong auto_increment_increment)
|
|
{
|
|
global_system_variables.auto_increment_increment= auto_increment_increment;
|
|
}
|
|
|
|
void set_auto_increment_offset(ulong auto_increment_offset)
|
|
{
|
|
global_system_variables.auto_increment_offset= auto_increment_offset;
|
|
}
|
|
|
|
#ifdef HAVE_REPLICATION
|
|
void
|
|
get_server_startup_prerequirements(Trans_context_info& requirements,
|
|
bool has_lock)
|
|
{
|
|
requirements.binlog_enabled= opt_bin_log;
|
|
requirements.binlog_format= global_system_variables.binlog_format;
|
|
requirements.binlog_checksum_options= binlog_checksum_options;
|
|
requirements.gtid_mode=
|
|
get_gtid_mode(has_lock ? GTID_MODE_LOCK_GTID_MODE :
|
|
GTID_MODE_LOCK_NONE);
|
|
requirements.log_slave_updates= opt_log_slave_updates;
|
|
requirements.transaction_write_set_extraction=
|
|
global_system_variables.transaction_write_set_extraction;
|
|
requirements.mi_repository_type= opt_mi_repository_id;
|
|
requirements.rli_repository_type= opt_rli_repository_id;
|
|
requirements.parallel_applier_type= mts_parallel_option;
|
|
requirements.parallel_applier_workers= opt_mts_slave_parallel_workers;
|
|
requirements.parallel_applier_preserve_commit_order= opt_slave_preserve_commit_order;
|
|
requirements.lower_case_table_names = lower_case_table_names;
|
|
}
|
|
#endif //HAVE_REPLICATION
|
|
|
|
bool get_server_encoded_gtid_executed(uchar **encoded_gtid_executed,
|
|
size_t *length)
|
|
{
|
|
global_sid_lock->wrlock();
|
|
|
|
DBUG_ASSERT(get_gtid_mode(GTID_MODE_LOCK_SID) > 0);
|
|
|
|
const Gtid_set *executed_gtids= gtid_state->get_executed_gtids();
|
|
*length= executed_gtids->get_encoded_length();
|
|
*encoded_gtid_executed= (uchar*) my_malloc(key_memory_Gtid_set_to_string,
|
|
*length, MYF(MY_WME));
|
|
if (*encoded_gtid_executed == NULL)
|
|
{
|
|
global_sid_lock->unlock();
|
|
return true;
|
|
}
|
|
|
|
executed_gtids->encode(*encoded_gtid_executed);
|
|
global_sid_lock->unlock();
|
|
return false;
|
|
}
|
|
|
|
#if !defined(DBUG_OFF)
|
|
char* encoded_gtid_set_to_string(uchar *encoded_gtid_set,
|
|
size_t length)
|
|
{
|
|
/* No sid_lock because this is a completely local object. */
|
|
Sid_map sid_map(NULL);
|
|
Gtid_set set(&sid_map);
|
|
|
|
if (set.add_gtid_encoding(encoded_gtid_set, length) !=
|
|
RETURN_STATUS_OK)
|
|
return NULL;
|
|
|
|
char *buf;
|
|
set.to_string(&buf);
|
|
return buf;
|
|
}
|
|
#endif
|
|
|
|
|
|
void global_thd_manager_add_thd(THD *thd)
|
|
{
|
|
Global_THD_manager::get_instance()->add_thd(thd);
|
|
}
|
|
|
|
|
|
void global_thd_manager_remove_thd(THD *thd)
|
|
{
|
|
Global_THD_manager::get_instance()->remove_thd(thd);
|
|
}
|
|
|
|
unsigned long get_slave_max_allowed_packet() {
|
|
return slave_max_allowed_packet;
|
|
}
|