mariadb/sql/wsrep_var.cc

1047 lines
30 KiB
C++
Raw Normal View History

/* Copyright 2008-2021 Codership Oy <http://www.codership.com>
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
2019-05-11 21:19:05 +02:00
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "wsrep_var.h"
#include <mysqld.h>
#include <sql_class.h>
#include <set_var.h>
#include <sql_acl.h>
#include "wsrep_priv.h"
#include "wsrep_thd.h"
2015-07-14 22:05:29 +02:00
#include "wsrep_xid.h"
#include <my_dir.h>
#include <cstdio>
#include <cstdlib>
#include "wsrep_trans_observer.h"
ulong wsrep_reject_queries;
int wsrep_init_vars()
{
wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME));
wsrep_provider_options= my_strdup("", MYF(MY_WME));
wsrep_cluster_address = my_strdup("", MYF(MY_WME));
wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME));
wsrep_node_name = my_strdup("", MYF(MY_WME));
wsrep_node_address = my_strdup("", MYF(MY_WME));
wsrep_node_incoming_address= my_strdup(WSREP_NODE_INCOMING_AUTO, MYF(MY_WME));
wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME));
return 0;
}
static int get_provider_option_value(const char* opts,
const char* opt_name,
ulong* opt_value)
{
int ret= 1;
ulong opt_value_tmp;
char *opt_value_str, *s, *opts_copy= my_strdup(opts, MYF(MY_WME));
if ((opt_value_str= strstr(opts_copy, opt_name)) == NULL)
goto end;
opt_value_str= strtok_r(opt_value_str, "=", &s);
if (opt_value_str == NULL) goto end;
opt_value_str= strtok_r(NULL, ";", &s);
if (opt_value_str == NULL) goto end;
opt_value_tmp= strtoul(opt_value_str, NULL, 10);
if (errno == ERANGE) goto end;
*opt_value= opt_value_tmp;
ret= 0;
end:
my_free(opts_copy);
return ret;
}
static bool refresh_provider_options()
{
WSREP_DEBUG("refresh_provider_options: %s",
(wsrep_provider_options) ? wsrep_provider_options : "null");
try
{
std::string opts= Wsrep_server_state::instance().provider().options();
wsrep_provider_options_init(opts.c_str());
get_provider_option_value(wsrep_provider_options,
(char*)"repl.max_ws_size",
&wsrep_max_ws_size);
return false;
}
catch (...)
{
WSREP_ERROR("Failed to get provider options");
return true;
}
}
void wsrep_set_wsrep_on()
{
WSREP_PROVIDER_EXISTS_= wsrep_provider &&
strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN);
WSREP_ON_= global_system_variables.wsrep_on && WSREP_PROVIDER_EXISTS_;
}
MDEV-14648 Restore fix for MySQL BUG#39053 - UNINSTALL PLUGIN does not allow the storage engine to cleanup open connections Also, allow the MariaDB 10.2 server to link InnoDB dynamically against ha_innodb.so (which is what mysql-test-run.pl expects to exist, instead of the default name ha_innobase.so). wsrep_load_data_split(): Instead of referring to innodb_hton_ptr, check the handlerton::db_type. This was recently broken by me in MDEV-11415. innodb_lock_schedule_algorithm: Define as a weak global symbol, so that WITH_WSREP will not depend on InnoDB being linked statically. I tested this manually. Notably, running a test that only does SET GLOBAL wsrep_on=1; with a static or dynamic InnoDB and ./mtr --mysqld=--loose-innodb-lock-schedule-algorithm=fcfs will crash with SIGSEGV at shutdown. With the default VATS combination the wsrep_on is properly refused for both the static and dynamic InnoDB. ha_close_connection(): Do invoke the method also for plugins for which UNINSTALL PLUGIN was deferred due to open connections. Thanks to @svoj for pointing this out. thd_to_trx(): Return a pointer, not a reference to a pointer. check_trx_exists(): Invoke thd_set_ha_data() for assigning a transaction. log_write_checkpoint_info(): Remove an unused DEBUG_SYNC point that would cause an assertion failure on shutdown after deferred UNINSTALL PLUGIN. This was tested as follows: cmake -DWITH_WSREP=1 -DPLUGIN_INNOBASE:STRING=DYNAMIC \ -DWITH_MARIABACKUP:BOOL=OFF ... make cd mysql-test ./mtr innodb.innodb_uninstall
2018-02-14 14:18:55 +01:00
/* This is intentionally declared as a weak global symbol, so that
linking will succeed even if the server is built with a dynamically
linked InnoDB. */
ulong innodb_lock_schedule_algorithm __attribute__((weak));
struct handlerton* innodb_hton_ptr __attribute__((weak));
bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
{
if (var_type == OPT_GLOBAL)
{
my_bool saved_wsrep_on= global_system_variables.wsrep_on;
2019-01-23 12:30:00 +01:00
thd->variables.wsrep_on= global_system_variables.wsrep_on;
// If wsrep has not been inited we need to do it now
if (global_system_variables.wsrep_on && wsrep_provider && !wsrep_inited)
{
// wsrep_init() rewrites provide if it fails
char* tmp= strdup(wsrep_provider);
mysql_mutex_unlock(&LOCK_global_system_variables);
if (wsrep_init())
{
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp, my_error, "wsrep_init failed");
//rcode= true;
saved_wsrep_on= false;
}
free(tmp);
mysql_mutex_lock(&LOCK_global_system_variables);
}
thd->variables.wsrep_on= global_system_variables.wsrep_on= saved_wsrep_on;
}
wsrep_set_wsrep_on();
if (var_type == OPT_GLOBAL)
{
if (thd->variables.wsrep_on &&
thd->wsrep_cs().state() == wsrep::client_state::s_none)
{
wsrep_open(thd);
wsrep_before_command(thd);
}
}
return false;
}
bool wsrep_on_check(sys_var *self, THD* thd, set_var* var)
{
bool new_wsrep_on= (bool)var->save_result.ulonglong_value;
if (check_has_super(self, thd, var))
return true;
if (new_wsrep_on)
{
if (innodb_hton_ptr && innodb_lock_schedule_algorithm != 0)
{
my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled "
"if innodb_lock_schedule_algorithm=VATS. Please configure"
" innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0));
return true;
}
if (!WSREP_PROVIDER_EXISTS)
{
my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) can't be enabled "
"if the wsrep_provider is unset or set to 'none'", MYF(0));
return true;
}
if (var->type == OPT_SESSION &&
!global_system_variables.wsrep_on)
{
my_message(ER_WRONG_ARGUMENTS,
"Can't enable @@session.wsrep_on, "
"while @@global.wsrep_on is disabled", MYF(0));
return true;
}
}
if (thd->in_active_multi_stmt_transaction())
{
my_error(ER_CANT_DO_THIS_DURING_AN_TRANSACTION, MYF(0));
return true;
}
if (var->type == OPT_GLOBAL)
{
/*
The global value is about to change. Cleanup
the transaction state and close the client
state. wsrep_on_update() will take care of
reopening it should wsrep_on be re-enabled.
*/
if (global_system_variables.wsrep_on && !new_wsrep_on)
{
wsrep_commit_empty(thd, true);
wsrep_after_statement(thd);
wsrep_after_command_ignore_result(thd);
wsrep_close(thd);
wsrep_cleanup(thd);
}
}
return false;
}
bool wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type)
2014-09-25 23:00:45 +02:00
{
Fix test failure on test MW-86 and remove MW-360 test. Merged from mysql-wsrep-bugs following: GCF-1058 MTR test galera.MW-86 fails on repeated runs Wait for the sync point sync.wsrep_apply_cb to be reached before executing the test and clearing the debug flag sync.wsrep_apply_cb. The race scenario: Intended behavior: node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed node2 (background): consume the signal node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - ok What happens occasionally (unexpected): node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end // The background INSERT still has _not_ reached the place where it starts // waiting for the signal: // DBUG_EXECUTE_IF("sync.wsrep_apply_cb", "now wait_for..."); node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed // The background INSERT reaches DBUG_EXECUTE_IF("sync.wsrep_apply_cb", ...) // but sync.wsrep_apply_cb has already been cleared and the "wait" code is not // executed. The signal remains unconsumed. node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - failure, signal.wsrep_apply_cb is pending (not consumed) Remove MW-360 test case as it is not intended for MariaDB (uses MySQL GTID).
2017-08-15 12:57:15 +02:00
if (thd->variables.wsrep_causal_reads) {
thd->variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ;
} else {
Fix test failure on test MW-86 and remove MW-360 test. Merged from mysql-wsrep-bugs following: GCF-1058 MTR test galera.MW-86 fails on repeated runs Wait for the sync point sync.wsrep_apply_cb to be reached before executing the test and clearing the debug flag sync.wsrep_apply_cb. The race scenario: Intended behavior: node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed node2 (background): consume the signal node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - ok What happens occasionally (unexpected): node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end // The background INSERT still has _not_ reached the place where it starts // waiting for the signal: // DBUG_EXECUTE_IF("sync.wsrep_apply_cb", "now wait_for..."); node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed // The background INSERT reaches DBUG_EXECUTE_IF("sync.wsrep_apply_cb", ...) // but sync.wsrep_apply_cb has already been cleared and the "wait" code is not // executed. The signal remains unconsumed. node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - failure, signal.wsrep_apply_cb is pending (not consumed) Remove MW-360 test case as it is not intended for MariaDB (uses MySQL GTID).
2017-08-15 12:57:15 +02:00
thd->variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ;
}
// update global settings too.
if (global_system_variables.wsrep_causal_reads) {
global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ;
} else {
Fix test failure on test MW-86 and remove MW-360 test. Merged from mysql-wsrep-bugs following: GCF-1058 MTR test galera.MW-86 fails on repeated runs Wait for the sync point sync.wsrep_apply_cb to be reached before executing the test and clearing the debug flag sync.wsrep_apply_cb. The race scenario: Intended behavior: node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed node2 (background): consume the signal node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - ok What happens occasionally (unexpected): node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end // The background INSERT still has _not_ reached the place where it starts // waiting for the signal: // DBUG_EXECUTE_IF("sync.wsrep_apply_cb", "now wait_for..."); node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed // The background INSERT reaches DBUG_EXECUTE_IF("sync.wsrep_apply_cb", ...) // but sync.wsrep_apply_cb has already been cleared and the "wait" code is not // executed. The signal remains unconsumed. node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - failure, signal.wsrep_apply_cb is pending (not consumed) Remove MW-360 test case as it is not intended for MariaDB (uses MySQL GTID).
2017-08-15 12:57:15 +02:00
global_system_variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ;
}
2014-10-01 00:06:15 +02:00
return false;
}
bool wsrep_sync_wait_update (sys_var* self, THD* thd, enum_var_type var_type)
{
2019-01-23 12:30:00 +01:00
thd->variables.wsrep_causal_reads= thd->variables.wsrep_sync_wait &
Fix test failure on test MW-86 and remove MW-360 test. Merged from mysql-wsrep-bugs following: GCF-1058 MTR test galera.MW-86 fails on repeated runs Wait for the sync point sync.wsrep_apply_cb to be reached before executing the test and clearing the debug flag sync.wsrep_apply_cb. The race scenario: Intended behavior: node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed node2 (background): consume the signal node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - ok What happens occasionally (unexpected): node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end // The background INSERT still has _not_ reached the place where it starts // waiting for the signal: // DBUG_EXECUTE_IF("sync.wsrep_apply_cb", "now wait_for..."); node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed // The background INSERT reaches DBUG_EXECUTE_IF("sync.wsrep_apply_cb", ...) // but sync.wsrep_apply_cb has already been cleared and the "wait" code is not // executed. The signal remains unconsumed. node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - failure, signal.wsrep_apply_cb is pending (not consumed) Remove MW-360 test case as it is not intended for MariaDB (uses MySQL GTID).
2017-08-15 12:57:15 +02:00
WSREP_SYNC_WAIT_BEFORE_READ;
// update global settings too
2019-01-23 12:30:00 +01:00
global_system_variables.wsrep_causal_reads= global_system_variables.wsrep_sync_wait &
Fix test failure on test MW-86 and remove MW-360 test. Merged from mysql-wsrep-bugs following: GCF-1058 MTR test galera.MW-86 fails on repeated runs Wait for the sync point sync.wsrep_apply_cb to be reached before executing the test and clearing the debug flag sync.wsrep_apply_cb. The race scenario: Intended behavior: node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed node2 (background): consume the signal node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - ok What happens occasionally (unexpected): node2: set sync.wsrep_apply_cb in order to start waiting in the background INSERT node1: INSERT start node2 (background): INSERT start node1: INSERT end // The background INSERT still has _not_ reached the place where it starts // waiting for the signal: // DBUG_EXECUTE_IF("sync.wsrep_apply_cb", "now wait_for..."); node2: send signal to background INSERT: "stop waiting and continue executing" node2: clear sync.wsrep_apply_cb as no longer needed // The background INSERT reaches DBUG_EXECUTE_IF("sync.wsrep_apply_cb", ...) // but sync.wsrep_apply_cb has already been cleared and the "wait" code is not // executed. The signal remains unconsumed. node2 (background): INSERT end node2: DROP TABLE node2: check no pending signals are left - failure, signal.wsrep_apply_cb is pending (not consumed) Remove MW-360 test case as it is not intended for MariaDB (uses MySQL GTID).
2017-08-15 12:57:15 +02:00
WSREP_SYNC_WAIT_BEFORE_READ;
return false;
}
/*
Verify the format of the given UUID:seqno.
@return
true Fail
false Pass
*/
static
bool wsrep_start_position_verify (const char* start_str)
{
size_t start_len;
wsrep_uuid_t uuid;
ssize_t uuid_len;
// Check whether it has minimum acceptable length.
2019-01-23 12:30:00 +01:00
start_len= strlen (start_str);
if (start_len < 34)
return true;
/*
Parse the input to check whether UUID length is acceptable
and seqno has been provided.
*/
2019-01-23 12:30:00 +01:00
uuid_len= wsrep_uuid_scan (start_str, start_len, &uuid);
if (uuid_len < 0 || (start_len - uuid_len) < 2)
return true;
// Separator must follow the UUID.
if (start_str[uuid_len] != ':')
return true;
char* endptr;
wsrep_seqno_t const seqno(strtoll(&start_str[uuid_len + 1], &endptr, 10));
// Do not allow seqno < -1
if (*endptr == '\0' && seqno < -1)
return true;
// Remaining string was seqno.
if (*endptr == '\0') return false;
return true;
}
static
2019-01-23 12:30:00 +01:00
bool wsrep_set_local_position(THD* thd, const char* const value,
size_t length, bool const sst)
{
wsrep_uuid_t uuid;
2019-01-23 12:30:00 +01:00
size_t const uuid_len= wsrep_uuid_scan(value, length, &uuid);
wsrep_seqno_t const seqno= strtoll(value + uuid_len + 1, NULL, 10);
char start_pos_buf[FN_REFLEN];
memcpy(start_pos_buf, value, length);
start_pos_buf[length]='\0';
// If both are same as WSREP_START_POSITION_ZERO just set local
if (!strcmp(start_pos_buf, WSREP_START_POSITION_ZERO) &&
!strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO))
goto set;
else
WSREP_INFO("SST setting local position to %s current %s", start_pos_buf, wsrep_start_position);
if (sst)
return (wsrep_sst_received (thd, uuid, seqno, NULL, 0));
set:
local_uuid= uuid;
local_seqno= seqno;
return false;
}
bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var)
{
char start_pos_buf[FN_REFLEN];
if ((! var->save_result.string_value.str) ||
(var->save_result.string_value.length > (FN_REFLEN - 1))) // safety
goto err;
memcpy(start_pos_buf, var->save_result.string_value.str,
var->save_result.string_value.length);
start_pos_buf[var->save_result.string_value.length]= 0;
WSREP_DEBUG("SST wsrep_start_position check for new position %s old %s",
start_pos_buf, wsrep_start_position);
// Verify the format.
if (wsrep_start_position_verify(start_pos_buf)) return true;
// Give error if position is updated when wsrep is not enabled or
// provider is not loaded.
if ((!WSREP_ON || !Wsrep_server_state::instance().is_provider_loaded())
&& strcmp(start_pos_buf, WSREP_START_POSITION_ZERO))
{
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Cannot set 'wsrep_start_position' because "
"wsrep is switched off or provider is not loaded");
goto err;
}
/*
As part of further verification, we try to update the value and catch
errors (if any) only when value actually has been changed.
*/
if (wsrep_set_local_position(thd, var->save_result.string_value.str,
var->save_result.string_value.length,
true))
goto err;
return false;
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL");
return true;
}
bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type)
{
// Print a confirmation that wsrep_start_position has been updated.
WSREP_INFO ("wsrep_start_position set to '%s'", wsrep_start_position);
return false;
}
bool wsrep_start_position_init (const char* val)
{
if (NULL == val || wsrep_start_position_verify (val))
{
WSREP_ERROR("Bad initial value for wsrep_start_position: %s",
(val ? val : ""));
return true;
}
2019-01-23 12:30:00 +01:00
if (wsrep_set_local_position (NULL, val, strlen(val), false))
{
WSREP_ERROR("Failed to set initial wsep_start_position: %s", val);
return true;
}
return false;
}
static int wsrep_provider_verify (const char* provider_str)
{
MY_STAT f_stat;
char path[FN_REFLEN];
if (!provider_str || strlen(provider_str)== 0)
return 1;
if (!strcmp(provider_str, WSREP_NONE))
return 0;
if (!unpack_filename(path, provider_str))
return 1;
/* check that provider file exists */
2015-07-14 22:05:29 +02:00
memset(&f_stat, 0, sizeof(MY_STAT));
if (!my_stat(path, &f_stat, MYF(0)))
{
return 1;
}
if (MY_S_ISDIR(f_stat.st_mode))
{
return 1;
}
return 0;
}
bool wsrep_provider_check (sys_var *self, THD* thd, set_var* var)
{
char wsrep_provider_buf[FN_REFLEN];
if ((! var->save_result.string_value.str) ||
(var->save_result.string_value.length > (FN_REFLEN - 1))) // safety
goto err;
memcpy(wsrep_provider_buf, var->save_result.string_value.str,
var->save_result.string_value.length);
wsrep_provider_buf[var->save_result.string_value.length]= 0;
if (!wsrep_provider_verify(wsrep_provider_buf)) return 0;
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL");
return 1;
}
bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
{
bool rcode= false;
WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider);
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd);
2019-01-23 12:30:00 +01:00
/* provider status variables are allocated in provider library
and need to freed here, otherwise a dangling reference to
wsrep_status_vars would remain in THD
*/
wsrep_free_status(thd);
if (wsrep_inited == 1)
wsrep_deinit(false);
char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider
//when fails
if (wsrep_init())
{
Changing field::field_name and Item::name to LEX_CSTRING Benefits of this patch: - Removed a lot of calls to strlen(), especially for field_string - Strings generated by parser are now const strings, less chance of accidently changing a string - Removed a lot of calls with LEX_STRING as parameter (changed to pointer) - More uniform code - Item::name_length was not kept up to date. Now fixed - Several bugs found and fixed (Access to null pointers, access of freed memory, wrong arguments to printf like functions) - Removed a lot of casts from (const char*) to (char*) Changes: - This caused some ABI changes - lex_string_set now uses LEX_CSTRING - Some fucntions are now taking const char* instead of char* - Create_field::change and after changed to LEX_CSTRING - handler::connect_string, comment and engine_name() changed to LEX_CSTRING - Checked printf() related calls to find bugs. Found and fixed several errors in old code. - A lot of changes from LEX_STRING to LEX_CSTRING, especially related to parsing and events. - Some changes from LEX_STRING and LEX_STRING & to LEX_CSTRING* - Some changes for char* to const char* - Added printf argument checking for my_snprintf() - Introduced null_clex_str, star_clex_string, temp_lex_str to simplify code - Added item_empty_name and item_used_name to be able to distingush between items that was given an empty name and items that was not given a name This is used in sql_yacc.yy to know when to give an item a name. - select table_name."*' is not anymore same as table_name.* - removed not used function Item::rename() - Added comparision of item->name_length before some calls to my_strcasecmp() to speed up comparison - Moved Item_sp_variable::make_field() from item.h to item.cc - Some minimal code changes to avoid copying to const char * - Fixed wrong error message in wsrep_mysql_parse() - Fixed wrong code in find_field_in_natural_join() where real_item() was set when it shouldn't - ER_ERROR_ON_RENAME was used with extra arguments. - Removed some (wrong) ER_OUTOFMEMORY, as alloc_root will already give the error. TODO: - Check possible unsafe casts in plugin/auth_examples/qa_auth_interface.c - Change code to not modify LEX_CSTRING for database name (as part of lower_case_table_names)
2017-04-23 18:39:57 +02:00
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp, my_error, "wsrep_init failed");
2019-01-23 12:30:00 +01:00
rcode= true;
}
free(tmp);
// we sure don't want to use old address with new provider
wsrep_cluster_address_init(NULL);
wsrep_provider_options_init(NULL);
2019-01-23 12:30:00 +01:00
if (!rcode)
refresh_provider_options();
wsrep_set_wsrep_on();
2019-01-23 12:30:00 +01:00
mysql_mutex_lock(&LOCK_global_system_variables);
return rcode;
}
void wsrep_provider_init (const char* value)
{
WSREP_DEBUG("wsrep_provider_init: %s -> %s",
(wsrep_provider) ? wsrep_provider : "null",
(value) ? value : "null");
if (NULL == value || wsrep_provider_verify (value))
{
WSREP_ERROR("Bad initial value for wsrep_provider: %s",
(value ? value : ""));
return;
}
if (wsrep_provider) my_free((void *)wsrep_provider);
2019-01-23 12:30:00 +01:00
wsrep_provider= my_strdup(value, MYF(0));
wsrep_set_wsrep_on();
}
bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var)
{
2019-01-23 12:30:00 +01:00
if (!WSREP_ON)
{
my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0));
return true;
}
2016-08-26 03:28:26 +02:00
return false;
}
2016-08-26 03:28:26 +02:00
bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type)
{
if (wsrep_provider_options)
{
enum wsrep::provider::status ret=
Wsrep_server_state::instance().provider().options(wsrep_provider_options);
if (ret)
{
WSREP_ERROR("Set options returned %d", ret);
goto err;
}
return refresh_provider_options();
}
err:
refresh_provider_options();
return true;
}
void wsrep_provider_options_init(const char* value)
{
if (wsrep_provider_options && wsrep_provider_options != value)
my_free((void *)wsrep_provider_options);
2019-01-23 12:30:00 +01:00
wsrep_provider_options= (value) ? my_strdup(value, MYF(0)) : NULL;
}
bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type)
{
switch (wsrep_reject_queries) {
case WSREP_REJECT_NONE:
WSREP_INFO("Allowing client queries due to manual setting");
break;
case WSREP_REJECT_ALL:
WSREP_INFO("Rejecting client queries due to manual setting");
break;
case WSREP_REJECT_ALL_KILL:
/* close all client connections, but this one */
wsrep_close_client_connections(FALSE, thd);
WSREP_INFO("Rejecting client queries and killing connections due to manual setting");
break;
default:
WSREP_INFO("Unknown value for wsrep_reject_queries: %lu",
wsrep_reject_queries);
return true;
}
return false;
}
bool wsrep_debug_update(sys_var *self, THD* thd, enum_var_type type)
{
// Give warnings if wsrep_debug is set and wsrep is disabled or
// provider is not loaded, it will not have any effect
if ((!WSREP_ON || !Wsrep_server_state::instance().is_provider_loaded())
&& wsrep_debug)
{
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Setting 'wsrep_debug' has no effect because "
"wsrep is switched off");
wsrep_debug= 0;
}
else
Wsrep_server_state::instance().debug_log_level(wsrep_debug);
return false;
}
static int wsrep_cluster_address_verify (const char* cluster_address_str)
{
/* There is no predefined address format, it depends on provider. */
return 0;
}
bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var)
{
char addr_buf[FN_REFLEN];
if ((! var->save_result.string_value.str) ||
2016-08-30 08:16:50 +02:00
(var->save_result.string_value.length >= sizeof(addr_buf))) // safety
goto err;
strmake(addr_buf, var->save_result.string_value.str,
2016-08-30 08:16:50 +02:00
MY_MIN(sizeof(addr_buf)-1, var->save_result.string_value.length));
if (!wsrep_cluster_address_verify(addr_buf))
return 0;
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL");
return 1;
}
bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
{
2019-01-23 12:30:00 +01:00
if (!Wsrep_server_state::instance().is_provider_loaded())
{
2019-01-23 12:30:00 +01:00
WSREP_INFO("WSREP (galera) provider is not loaded, can't re(start) replication.");
return false;
}
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
*/
char *tmp= my_strdup(wsrep_cluster_address, MYF(MY_WME));
WSREP_DEBUG("wsrep_cluster_address_update: %s", wsrep_cluster_address);
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_wsrep_cluster_config);
wsrep_stop_replication(thd);
if (*tmp && wsrep_start_replication(tmp))
{
wsrep_create_rollbacker();
MDEV-19746: Galera test failures because of wsrep_slave_threads identification Problem was that tests select INFORMATION_SCHEMA.PROCESSLIST processes from user system user and empty state. Thus, there is not clear state for slave threads. Changes: - Added new status variables that store current amount of applier threads (wsrep_applier_thread_count) and rollbacker threads (wsrep_rollbacker_thread_count). This will make clear how many slave threads of certain type there is. - Added THD state "wsrep applier idle" when applier slave thread is waiting for work. This makes finding slave/applier threads easier. - Added force-restart option for mtr to always restart servers between tests to avoid race on start of the test - Added wait_condition_with_debug to wait until the passed statement returns true, or the operation times out. If operation times out, the additional error statement will be executed Changes to be committed: new file: mysql-test/include/force_restart.inc new file: mysql-test/include/wait_condition_with_debug.inc modified: mysql-test/mysql-test-run.pl modified: mysql-test/suite/galera/disabled.def modified: mysql-test/suite/galera/r/MW-336.result modified: mysql-test/suite/galera/r/galera_kill_applier.result modified: mysql-test/suite/galera/r/galera_var_slave_threads.result new file: mysql-test/suite/galera/t/MW-336.cnf modified: mysql-test/suite/galera/t/MW-336.test modified: mysql-test/suite/galera/t/galera_kill_applier.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test modified: mysql-test/suite/galera/t/galera_var_slave_threads.test modified: mysql-test/suite/wsrep/disabled.def modified: mysql-test/suite/wsrep/r/variables.result modified: mysql-test/suite/wsrep/t/variables.test modified: sql/mysqld.cc modified: sql/wsrep_mysqld.cc modified: sql/wsrep_mysqld.h modified: sql/wsrep_thd.cc modified: sql/wsrep_var.cc
2019-07-11 06:13:58 +02:00
WSREP_DEBUG("Cluster address update creating %ld applier threads running %lu",
wsrep_slave_threads, wsrep_running_applier_threads);
wsrep_create_appliers(wsrep_slave_threads);
}
mysql_mutex_unlock(&LOCK_wsrep_cluster_config);
2019-01-23 12:30:00 +01:00
mysql_mutex_lock(&LOCK_global_system_variables);
if (strcmp(tmp, wsrep_cluster_address))
{
my_free((void*)wsrep_cluster_address);
wsrep_cluster_address= tmp;
}
else
my_free(tmp);
return false;
}
void wsrep_cluster_address_init (const char* value)
{
WSREP_DEBUG("wsrep_cluster_address_init: %s -> %s",
(wsrep_cluster_address) ? wsrep_cluster_address : "null",
(value) ? value : "null");
my_free((void*) wsrep_cluster_address);
wsrep_cluster_address= my_strdup(value ? value : "", MYF(0));
}
/* wsrep_cluster_name cannot be NULL or an empty string. */
bool wsrep_cluster_name_check (sys_var *self, THD* thd, set_var* var)
{
if (!var->save_result.string_value.str ||
(var->save_result.string_value.length == 0))
{
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
(var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL"));
return 1;
}
return 0;
}
bool wsrep_cluster_name_update (sys_var *self, THD* thd, enum_var_type type)
{
return 0;
}
bool wsrep_node_name_check (sys_var *self, THD* thd, set_var* var)
{
// TODO: for now 'allow' 0-length string to be valid (default)
if (!var->save_result.string_value.str)
{
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
(var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL"));
return 1;
}
return 0;
}
bool wsrep_node_name_update (sys_var *self, THD* thd, enum_var_type type)
{
return 0;
}
// TODO: do something more elaborate, like checking connectivity
bool wsrep_node_address_check (sys_var *self, THD* thd, set_var* var)
{
char addr_buf[FN_REFLEN];
if ((! var->save_result.string_value.str) ||
(var->save_result.string_value.length > (FN_REFLEN - 1))) // safety
goto err;
memcpy(addr_buf, var->save_result.string_value.str,
var->save_result.string_value.length);
addr_buf[var->save_result.string_value.length]= 0;
// TODO: for now 'allow' 0-length string to be valid (default)
return 0;
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL");
return 1;
}
bool wsrep_node_address_update (sys_var *self, THD* thd, enum_var_type type)
{
return 0;
}
void wsrep_node_address_init (const char* value)
{
if (wsrep_node_address && strcmp(wsrep_node_address, value))
my_free ((void*)wsrep_node_address);
2019-01-23 12:30:00 +01:00
wsrep_node_address= (value) ? my_strdup(value, MYF(0)) : NULL;
}
static void wsrep_slave_count_change_update ()
{
MDEV-19746: Galera test failures because of wsrep_slave_threads identification Problem was that tests select INFORMATION_SCHEMA.PROCESSLIST processes from user system user and empty state. Thus, there is not clear state for slave threads. Changes: - Added new status variables that store current amount of applier threads (wsrep_applier_thread_count) and rollbacker threads (wsrep_rollbacker_thread_count). This will make clear how many slave threads of certain type there is. - Added THD state "wsrep applier idle" when applier slave thread is waiting for work. This makes finding slave/applier threads easier. - Added force-restart option for mtr to always restart servers between tests to avoid race on start of the test - Added wait_condition_with_debug to wait until the passed statement returns true, or the operation times out. If operation times out, the additional error statement will be executed Changes to be committed: new file: mysql-test/include/force_restart.inc new file: mysql-test/include/wait_condition_with_debug.inc modified: mysql-test/mysql-test-run.pl modified: mysql-test/suite/galera/disabled.def modified: mysql-test/suite/galera/r/MW-336.result modified: mysql-test/suite/galera/r/galera_kill_applier.result modified: mysql-test/suite/galera/r/galera_var_slave_threads.result new file: mysql-test/suite/galera/t/MW-336.cnf modified: mysql-test/suite/galera/t/MW-336.test modified: mysql-test/suite/galera/t/galera_kill_applier.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test modified: mysql-test/suite/galera/t/galera_var_slave_threads.test modified: mysql-test/suite/wsrep/disabled.def modified: mysql-test/suite/wsrep/r/variables.result modified: mysql-test/suite/wsrep/t/variables.test modified: sql/mysqld.cc modified: sql/wsrep_mysqld.cc modified: sql/wsrep_mysqld.h modified: sql/wsrep_thd.cc modified: sql/wsrep_var.cc
2019-07-11 06:13:58 +02:00
wsrep_slave_count_change = (wsrep_slave_threads - wsrep_running_applier_threads);
WSREP_DEBUG("Change on slave threads: New %ld old %lu difference %d",
wsrep_slave_threads, wsrep_running_applier_threads, wsrep_slave_count_change);
}
bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
{
if (!wsrep_cluster_address_exists())
return false;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_wsrep_slave_threads);
mysql_mutex_lock(&LOCK_global_system_variables);
bool res= false;
wsrep_slave_count_change_update();
if (wsrep_slave_count_change > 0)
{
MDEV-19746: Galera test failures because of wsrep_slave_threads identification Problem was that tests select INFORMATION_SCHEMA.PROCESSLIST processes from user system user and empty state. Thus, there is not clear state for slave threads. Changes: - Added new status variables that store current amount of applier threads (wsrep_applier_thread_count) and rollbacker threads (wsrep_rollbacker_thread_count). This will make clear how many slave threads of certain type there is. - Added THD state "wsrep applier idle" when applier slave thread is waiting for work. This makes finding slave/applier threads easier. - Added force-restart option for mtr to always restart servers between tests to avoid race on start of the test - Added wait_condition_with_debug to wait until the passed statement returns true, or the operation times out. If operation times out, the additional error statement will be executed Changes to be committed: new file: mysql-test/include/force_restart.inc new file: mysql-test/include/wait_condition_with_debug.inc modified: mysql-test/mysql-test-run.pl modified: mysql-test/suite/galera/disabled.def modified: mysql-test/suite/galera/r/MW-336.result modified: mysql-test/suite/galera/r/galera_kill_applier.result modified: mysql-test/suite/galera/r/galera_var_slave_threads.result new file: mysql-test/suite/galera/t/MW-336.cnf modified: mysql-test/suite/galera/t/MW-336.test modified: mysql-test/suite/galera/t/galera_kill_applier.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test modified: mysql-test/suite/galera/t/galera_var_slave_threads.test modified: mysql-test/suite/wsrep/disabled.def modified: mysql-test/suite/wsrep/r/variables.result modified: mysql-test/suite/wsrep/t/variables.test modified: sql/mysqld.cc modified: sql/wsrep_mysqld.cc modified: sql/wsrep_mysqld.h modified: sql/wsrep_thd.cc modified: sql/wsrep_var.cc
2019-07-11 06:13:58 +02:00
WSREP_DEBUG("Creating %d applier threads, total %ld", wsrep_slave_count_change, wsrep_slave_threads);
res= wsrep_create_appliers(wsrep_slave_count_change, true);
MDEV-19746: Galera test failures because of wsrep_slave_threads identification Problem was that tests select INFORMATION_SCHEMA.PROCESSLIST processes from user system user and empty state. Thus, there is not clear state for slave threads. Changes: - Added new status variables that store current amount of applier threads (wsrep_applier_thread_count) and rollbacker threads (wsrep_rollbacker_thread_count). This will make clear how many slave threads of certain type there is. - Added THD state "wsrep applier idle" when applier slave thread is waiting for work. This makes finding slave/applier threads easier. - Added force-restart option for mtr to always restart servers between tests to avoid race on start of the test - Added wait_condition_with_debug to wait until the passed statement returns true, or the operation times out. If operation times out, the additional error statement will be executed Changes to be committed: new file: mysql-test/include/force_restart.inc new file: mysql-test/include/wait_condition_with_debug.inc modified: mysql-test/mysql-test-run.pl modified: mysql-test/suite/galera/disabled.def modified: mysql-test/suite/galera/r/MW-336.result modified: mysql-test/suite/galera/r/galera_kill_applier.result modified: mysql-test/suite/galera/r/galera_var_slave_threads.result new file: mysql-test/suite/galera/t/MW-336.cnf modified: mysql-test/suite/galera/t/MW-336.test modified: mysql-test/suite/galera/t/galera_kill_applier.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test modified: mysql-test/suite/galera/t/galera_var_slave_threads.test modified: mysql-test/suite/wsrep/disabled.def modified: mysql-test/suite/wsrep/r/variables.result modified: mysql-test/suite/wsrep/t/variables.test modified: sql/mysqld.cc modified: sql/wsrep_mysqld.cc modified: sql/wsrep_mysqld.h modified: sql/wsrep_thd.cc modified: sql/wsrep_var.cc
2019-07-11 06:13:58 +02:00
WSREP_DEBUG("Running %lu applier threads", wsrep_running_applier_threads);
wsrep_slave_count_change = 0;
}
mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
return res;
}
bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var)
{
2019-01-23 12:30:00 +01:00
if (!WSREP_ON)
2016-08-26 03:28:26 +02:00
{
my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0));
return true;
}
if (thd->global_read_lock.is_acquired())
{
my_message (ER_CANNOT_USER, "Global read lock acquired. Can't set 'wsrep_desync'", MYF(0));
return true;
}
bool new_wsrep_desync= (bool) var->save_result.ulonglong_value;
if (wsrep_desync == new_wsrep_desync) {
if (new_wsrep_desync) {
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"'wsrep_desync' is already ON.");
} else {
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"'wsrep_desync' is already OFF.");
}
return false;
}
2019-01-23 12:30:00 +01:00
int ret= 1;
if (new_wsrep_desync) {
2019-01-23 12:30:00 +01:00
ret= Wsrep_server_state::instance().provider().desync();
if (ret) {
WSREP_WARN ("SET desync failed %d for schema: %s, query: %s", ret,
thd->db.str, wsrep_thd_query(thd));
my_error (ER_CANNOT_USER, MYF(0), "'desync'", thd->query());
return true;
}
} else {
2019-01-23 12:30:00 +01:00
ret= Wsrep_server_state::instance().provider().resync();
if (ret != WSREP_OK) {
WSREP_WARN ("SET resync failed %d for schema: %s, query: %s", ret,
thd->get_db(), thd->query());
my_error (ER_CANNOT_USER, MYF(0), "'resync'", thd->query());
return true;
}
}
return false;
}
bool wsrep_desync_update (sys_var *self, THD* thd, enum_var_type type)
2016-08-26 03:28:26 +02:00
{
2019-01-23 12:30:00 +01:00
return false;
}
bool wsrep_trx_fragment_size_check (sys_var *self, THD* thd, set_var* var)
{
if (var->value == NULL) {
return false;
}
const ulong new_trx_fragment_size= var->value->val_uint();
if (!WSREP(thd) && new_trx_fragment_size > 0) {
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Cannot set 'wsrep_trx_fragment_size' to a value other than "
"0 because wsrep is switched off.");
return true;
}
if (new_trx_fragment_size > 0 && !wsrep_provider_is_SR_capable()) {
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Cannot set 'wsrep_trx_fragment_size' to a value other than "
"0 because the wsrep_provider does not support streaming "
"replication.");
return true;
}
if (wsrep_protocol_version < 4 && new_trx_fragment_size > 0) {
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Cannot set 'wsrep_trx_fragment_size' to a value other than "
"0 because cluster is not yet operating in Galera 4 mode.");
return true;
}
2019-01-23 12:30:00 +01:00
return false;
}
bool wsrep_trx_fragment_size_update(sys_var* self, THD *thd, enum_var_type)
{
WSREP_DEBUG("wsrep_trx_fragment_size_update: %llu",
thd->variables.wsrep_trx_fragment_size);
// Give error if wsrep_trx_fragment_size is set and wsrep is disabled or
// provider is not loaded
if (!WSREP_ON || !Wsrep_server_state::instance().is_provider_loaded())
{
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Cannot set 'wsrep_trx_fragment_size' because "
"wsrep is switched off");
return true;
}
2019-01-23 12:30:00 +01:00
if (thd->variables.wsrep_trx_fragment_size)
{
return thd->wsrep_cs().enable_streaming(
wsrep_fragment_unit(thd->variables.wsrep_trx_fragment_unit),
size_t(thd->variables.wsrep_trx_fragment_size));
}
else
{
thd->wsrep_cs().disable_streaming();
return false;
}
}
bool wsrep_trx_fragment_unit_update(sys_var* self, THD *thd, enum_var_type)
{
WSREP_DEBUG("wsrep_trx_fragment_unit_update: %lu",
thd->variables.wsrep_trx_fragment_unit);
// Give error if wsrep_trx_fragment_unit is set and wsrep is disabled or
// provider is not loaded
if (!WSREP_ON || !Wsrep_server_state::instance().is_provider_loaded())
{
push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_VAR,
"Cannot set 'wsrep_trx_fragment_unit' because "
"wsrep is switched off");
return true;
}
2019-01-23 12:30:00 +01:00
if (thd->variables.wsrep_trx_fragment_size)
{
return thd->wsrep_cs().enable_streaming(
wsrep_fragment_unit(thd->variables.wsrep_trx_fragment_unit),
size_t(thd->variables.wsrep_trx_fragment_size));
}
2016-08-26 03:28:26 +02:00
return false;
}
bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var)
{
2019-01-23 12:30:00 +01:00
if (!WSREP_ON)
{
my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0));
return true;
}
return false;
}
2019-01-23 12:30:00 +01:00
bool wsrep_max_ws_size_update(sys_var *self, THD *thd, enum_var_type)
{
char max_ws_size_opt[128];
my_snprintf(max_ws_size_opt, sizeof(max_ws_size_opt),
2019-01-23 12:30:00 +01:00
"repl.max_ws_size=%d", wsrep_max_ws_size);
enum wsrep::provider::status ret= Wsrep_server_state::instance().provider().options(max_ws_size_opt);
if (ret)
{
WSREP_ERROR("Set options returned %d", ret);
return true;
}
return refresh_provider_options();
}
2019-01-23 12:30:00 +01:00
#if UNUSED /* eaec266eb16c (Sergei Golubchik 2014-09-28) */
2014-09-28 12:41:51 +02:00
static SHOW_VAR wsrep_status_vars[]=
{
{"connected", (char*) &wsrep_connected, SHOW_BOOL},
2019-01-23 12:30:00 +01:00
{"ready", (char*) &wsrep_show_ready, SHOW_FUNC},
2014-09-28 12:41:51 +02:00
{"cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
{"cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG},
{"cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR},
{"cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH},
{"local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH},
2019-01-23 12:30:00 +01:00
{"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC},
2014-09-28 12:41:51 +02:00
{"provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR},
{"provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR},
{"provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
2019-07-25 17:42:06 +02:00
{"provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
MDEV-19746: Galera test failures because of wsrep_slave_threads identification Problem was that tests select INFORMATION_SCHEMA.PROCESSLIST processes from user system user and empty state. Thus, there is not clear state for slave threads. Changes: - Added new status variables that store current amount of applier threads (wsrep_applier_thread_count) and rollbacker threads (wsrep_rollbacker_thread_count). This will make clear how many slave threads of certain type there is. - Added THD state "wsrep applier idle" when applier slave thread is waiting for work. This makes finding slave/applier threads easier. - Added force-restart option for mtr to always restart servers between tests to avoid race on start of the test - Added wait_condition_with_debug to wait until the passed statement returns true, or the operation times out. If operation times out, the additional error statement will be executed Changes to be committed: new file: mysql-test/include/force_restart.inc new file: mysql-test/include/wait_condition_with_debug.inc modified: mysql-test/mysql-test-run.pl modified: mysql-test/suite/galera/disabled.def modified: mysql-test/suite/galera/r/MW-336.result modified: mysql-test/suite/galera/r/galera_kill_applier.result modified: mysql-test/suite/galera/r/galera_var_slave_threads.result new file: mysql-test/suite/galera/t/MW-336.cnf modified: mysql-test/suite/galera/t/MW-336.test modified: mysql-test/suite/galera/t/galera_kill_applier.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test modified: mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test modified: mysql-test/suite/galera/t/galera_var_slave_threads.test modified: mysql-test/suite/wsrep/disabled.def modified: mysql-test/suite/wsrep/r/variables.result modified: mysql-test/suite/wsrep/t/variables.test modified: sql/mysqld.cc modified: sql/wsrep_mysqld.cc modified: sql/wsrep_mysqld.h modified: sql/wsrep_thd.cc modified: sql/wsrep_var.cc
2019-07-11 06:13:58 +02:00
{"thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH},
{"applier_thread_count", (char*)&wsrep_running_applier_threads, SHOW_LONG_NOFLUSH},
{"rollbacker_thread_count", (char *)&wsrep_running_rollbacker_threads, SHOW_LONG_NOFLUSH},
2014-09-28 12:41:51 +02:00
};
2014-09-28 12:41:51 +02:00
static int show_var_cmp(const void *var1, const void *var2)
{
2014-09-28 12:41:51 +02:00
return strcasecmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
}
2019-02-18 08:33:24 +01:00
2019-01-23 12:30:00 +01:00
/*
* Status variables stuff below
*/
static inline void
wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep_var)
{
mysql->name= wsrep_var->name;
switch (wsrep_var->type) {
case WSREP_VAR_INT64:
mysql->value= (char*) &wsrep_var->value._int64;
mysql->type= SHOW_LONGLONG;
break;
case WSREP_VAR_STRING:
mysql->value= (char*) &wsrep_var->value._string;
mysql->type= SHOW_CHAR_PTR;
break;
case WSREP_VAR_DOUBLE:
mysql->value= (char*) &wsrep_var->value._double;
mysql->type= SHOW_DOUBLE;
break;
}
}
2019-02-18 08:33:24 +01:00
#endif /* UNUSED */
2019-01-23 12:30:00 +01:00
#if DYNAMIC
// somehow this mysql status thing works only with statically allocated arrays.
static SHOW_VAR* mysql_status_vars= NULL;
static int mysql_status_len= -1;
#else
static SHOW_VAR mysql_status_vars[512 + 1];
static const int mysql_status_len= 512;
#endif
static void export_wsrep_status_to_mysql(THD* thd)
2014-09-28 12:41:51 +02:00
{
2019-01-23 12:30:00 +01:00
int wsrep_status_len, i;
2019-01-23 12:30:00 +01:00
thd->wsrep_status_vars= Wsrep_server_state::instance().status();
2019-01-23 12:30:00 +01:00
wsrep_status_len= thd->wsrep_status_vars.size();
2019-01-23 12:30:00 +01:00
#if DYNAMIC
if (wsrep_status_len != mysql_status_len) {
void* tmp= realloc (mysql_status_vars,
(wsrep_status_len + 1) * sizeof(SHOW_VAR));
if (!tmp) {
2019-01-23 12:30:00 +01:00
sql_print_error ("Out of memory for wsrep status variables."
"Number of variables: %d", wsrep_status_len);
return;
}
2019-01-23 12:30:00 +01:00
mysql_status_len= wsrep_status_len;
mysql_status_vars= (SHOW_VAR*)tmp;
}
/* @TODO: fix this: */
#else
if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len;
#endif
for (i= 0; i < wsrep_status_len; i++)
{
mysql_status_vars[i].name= (char*)thd->wsrep_status_vars[i].name().c_str();
mysql_status_vars[i].value= (char*)thd->wsrep_status_vars[i].value().c_str();
mysql_status_vars[i].type= SHOW_CHAR;
}
2019-01-23 12:30:00 +01:00
mysql_status_vars[wsrep_status_len].name = NullS;
mysql_status_vars[wsrep_status_len].value = NullS;
mysql_status_vars[wsrep_status_len].type = SHOW_LONG;
}
2020-10-22 12:27:18 +02:00
int wsrep_show_status (THD *thd, SHOW_VAR *var, void *,
system_status_var *, enum_var_type)
2019-01-23 12:30:00 +01:00
{
/* Note that we should allow show status like 'wsrep%' even
when WSREP(thd) is false. */
2019-01-23 12:30:00 +01:00
if (WSREP_ON)
{
export_wsrep_status_to_mysql(thd);
var->type= SHOW_ARRAY;
var->value= (char *) &mysql_status_vars;
}
return 0;
}
2019-01-23 12:30:00 +01:00
void wsrep_free_status (THD* thd)
{
thd->wsrep_status_vars.clear();
}