From 369c02674cb024ceb1995433913ef2fb32f815ca Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 22 Nov 2014 14:33:51 -0500 Subject: [PATCH] MDEV-7053: WSREP_STATUS & WSREP_MEMBERSHIP I_S tables wsrep_info INFORMATION_SCHEMA plugin to provide WSREP_STATUS and WSREP_MEMBERSHIP tables. --- .../wsrep => }/include/galera_cluster.inc | 0 .../wsrep => }/include/galera_connect.inc | 0 .../{suite/wsrep => }/include/galera_diff.inc | 0 .../{suite/wsrep => }/include/galera_end.inc | 0 .../{suite/wsrep => }/include/galera_init.inc | 0 .../wsrep => }/include/have_wsrep_enabled.inc | 0 plugin/wsrep_info/CMakeLists.txt | 5 + .../wsrep_info/mysql-test/wsrep_info/my.cnf | 35 +++ .../mysql-test/wsrep_info/r/plugin.result | 17 ++ .../mysql-test/wsrep_info/suite.opt | 1 + .../wsrep_info/mysql-test/wsrep_info/suite.pm | 43 +++ .../mysql-test/wsrep_info/t/plugin.test | 23 ++ plugin/wsrep_info/plugin.cc | 265 ++++++++++++++++++ sql/wsrep_mysqld.cc | 27 +- sql/wsrep_mysqld.h | 1 + sql/wsrep_sst.cc | 4 +- sql/wsrep_utils.h | 70 ++++- 17 files changed, 469 insertions(+), 22 deletions(-) rename mysql-test/{suite/wsrep => }/include/galera_cluster.inc (100%) rename mysql-test/{suite/wsrep => }/include/galera_connect.inc (100%) rename mysql-test/{suite/wsrep => }/include/galera_diff.inc (100%) rename mysql-test/{suite/wsrep => }/include/galera_end.inc (100%) rename mysql-test/{suite/wsrep => }/include/galera_init.inc (100%) rename mysql-test/{suite/wsrep => }/include/have_wsrep_enabled.inc (100%) create mode 100644 plugin/wsrep_info/CMakeLists.txt create mode 100644 plugin/wsrep_info/mysql-test/wsrep_info/my.cnf create mode 100644 plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result create mode 100644 plugin/wsrep_info/mysql-test/wsrep_info/suite.opt create mode 100644 plugin/wsrep_info/mysql-test/wsrep_info/suite.pm create mode 100644 plugin/wsrep_info/mysql-test/wsrep_info/t/plugin.test create mode 100644 plugin/wsrep_info/plugin.cc diff --git a/mysql-test/suite/wsrep/include/galera_cluster.inc b/mysql-test/include/galera_cluster.inc similarity index 100% rename from mysql-test/suite/wsrep/include/galera_cluster.inc rename to mysql-test/include/galera_cluster.inc diff --git a/mysql-test/suite/wsrep/include/galera_connect.inc b/mysql-test/include/galera_connect.inc similarity index 100% rename from mysql-test/suite/wsrep/include/galera_connect.inc rename to mysql-test/include/galera_connect.inc diff --git a/mysql-test/suite/wsrep/include/galera_diff.inc b/mysql-test/include/galera_diff.inc similarity index 100% rename from mysql-test/suite/wsrep/include/galera_diff.inc rename to mysql-test/include/galera_diff.inc diff --git a/mysql-test/suite/wsrep/include/galera_end.inc b/mysql-test/include/galera_end.inc similarity index 100% rename from mysql-test/suite/wsrep/include/galera_end.inc rename to mysql-test/include/galera_end.inc diff --git a/mysql-test/suite/wsrep/include/galera_init.inc b/mysql-test/include/galera_init.inc similarity index 100% rename from mysql-test/suite/wsrep/include/galera_init.inc rename to mysql-test/include/galera_init.inc diff --git a/mysql-test/suite/wsrep/include/have_wsrep_enabled.inc b/mysql-test/include/have_wsrep_enabled.inc similarity index 100% rename from mysql-test/suite/wsrep/include/have_wsrep_enabled.inc rename to mysql-test/include/have_wsrep_enabled.inc diff --git a/plugin/wsrep_info/CMakeLists.txt b/plugin/wsrep_info/CMakeLists.txt new file mode 100644 index 00000000000..4d7c3ed706e --- /dev/null +++ b/plugin/wsrep_info/CMakeLists.txt @@ -0,0 +1,5 @@ +IF (WITH_WSREP) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/wsrep) + MYSQL_ADD_PLUGIN(WSREP_STATUS plugin.cc) +ENDIF() diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf b/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf new file mode 100644 index 00000000000..4af933f1633 --- /dev/null +++ b/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf @@ -0,0 +1,35 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld] +wsrep-on=1 +binlog-format=row +innodb-autoinc-lock-mode=2 +innodb-locks-unsafe-for-binlog=1 +wsrep-cluster-address=gcomm:// +wsrep_provider=@ENV.WSREP_PROVIDER +# enforce read-committed characteristics across the cluster +wsrep_causal_reads=ON + +[mysqld.1] +#galera_port=@OPT.port +#sst_port=@OPT.port +wsrep_provider_options='base_port=@mysqld.1.#galera_port' +wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' +wsrep_node_name=test-node-1 + +[mysqld.2] +#galera_port=@OPT.port +#sst_port=@OPT.port +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='base_port=@mysqld.2.#galera_port' +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +wsrep_node_name=test-node-2 + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +NODE_MYSOCK_2= @mysqld.2.socket + diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result b/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result new file mode 100644 index 00000000000..1aef7c30fc7 --- /dev/null +++ b/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result @@ -0,0 +1,17 @@ +# On node 1 +SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS; +NODE_INDEX NODE_STATUS CLUSTER_STATUS CLUSTER_SIZE CLUSTER_STATE_UUID CLUSTER_STATE_SEQNO CLUSTER_CONF_ID GAP PROTOCOL_VERSION + Synced Primary 2 0 2 NO 3 +SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME; +INDEX UUID NAME ADDRESS + test-node-1
+ test-node-2
+# On node 2 +SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS; +NODE_INDEX NODE_STATUS CLUSTER_STATUS CLUSTER_SIZE CLUSTER_STATE_UUID CLUSTER_STATE_SEQNO CLUSTER_CONF_ID GAP PROTOCOL_VERSION + Synced Primary 2 0 2 YES 3 +SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME; +INDEX UUID NAME ADDRESS + test-node-1
+ test-node-2
+# End of test diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/suite.opt b/plugin/wsrep_info/mysql-test/wsrep_info/suite.opt new file mode 100644 index 00000000000..c806c2e7633 --- /dev/null +++ b/plugin/wsrep_info/mysql-test/wsrep_info/suite.opt @@ -0,0 +1 @@ +--plugin-load-add=$WSREP_STATUS_SO diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm new file mode 100644 index 00000000000..5af1daa673c --- /dev/null +++ b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm @@ -0,0 +1,43 @@ +package My::Suite::WSREP_STATUS; +use File::Basename; +use My::Find; + +@ISA = qw(My::Suite); + +return "Not run for embedded server" if $::opt_embedded_server; + +return "WSREP is not compiled in" unless defined $::mysqld_variables{'wsrep-on'}; + +my ($provider) = grep { -f $_ } $ENV{WSREP_PROVIDER}, + "/usr/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"; + +return "No wsrep provider library" unless -f $provider; + +return "No WSREP_STATUS plugin" unless $ENV{WSREP_STATUS_SO}; + +$ENV{WSREP_PROVIDER} = $provider; + +my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; +return "No SST scripts" unless $spath; + +my ($epath) = grep { -f "$_/my_print_defaults"; } "$::bindir/extra", $::path_client_bindir; +return "No my_print_defaults" unless $epath; + +push @::global_suppressions, + ( + qr(WSREP:.*down context.*), + qr(WSREP: Failed to send state UUID:.*), + qr(WSREP: wsrep_sst_receive_address.*), + qr(WSREP: Could not open saved state file for reading: .*), + qr(WSREP: last inactive check more than .* skipping check), + qr(WSREP: Gap in state sequence. Need state transfer.), + qr(WSREP: Failed to prepare for incremental state transfer: .*), + ); + + +$ENV{PATH}="$epath:$ENV{PATH}"; +$ENV{PATH}="$spath:$ENV{PATH}" unless $epath eq $spath; + +bless { }; + diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/t/plugin.test b/plugin/wsrep_info/mysql-test/wsrep_info/t/plugin.test new file mode 100644 index 00000000000..9b06f15b125 --- /dev/null +++ b/plugin/wsrep_info/mysql-test/wsrep_info/t/plugin.test @@ -0,0 +1,23 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # On node 1 +--connection node_1 + +--replace_column 1 5 +SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS; + +--replace_column 1 2 4
+SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME; + +--echo # On node 2 +--connection node_2 + +--replace_column 1 5 +SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS; + +--replace_column 1 2 4
+SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME; + +--source include/galera_end.inc +--echo # End of test diff --git a/plugin/wsrep_info/plugin.cc b/plugin/wsrep_info/plugin.cc new file mode 100644 index 00000000000..50c2019b8b9 --- /dev/null +++ b/plugin/wsrep_info/plugin.cc @@ -0,0 +1,265 @@ +/* Copyright (C) 2014 MariaDB Corporation. + + 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_SERVER +#define MYSQL_SERVER +#endif + +#include +#include /* ST_SCHEMA_TABLE */ +#include +#include /* check_global_access() */ +#include +#include + +/* WSREP_MEMBERSHIP table fields */ + +/* Node index */ +#define COLUMN_WSREP_MEMB_INDEX 0 +/* Unique member ID */ +#define COLUMN_WSREP_MEMB_UUID 1 +/* Human-readable name */ +#define COLUMN_WSREP_MEMB_NAME 2 +/* Incoming address */ +#define COLUMN_WSREP_MEMB_ADDRESS 3 + +/* WSREP_STATUS table fields */ + +/* Node index */ +#define COLUMN_WSREP_STATUS_NODE_INDEX 0 +/* Node status */ +#define COLUMN_WSREP_STATUS_NODE_STATUS 1 +/* Cluster status */ +#define COLUMN_WSREP_STATUS_CLUSTER_STATUS 2 +/* Cluster size */ +#define COLUMN_WSREP_STATUS_CLUSTER_SIZE 3 +/* Global cluster state UUID */ +#define COLUMN_WSREP_STATUS_CLUSTER_STATE_UUID 4 +/* Global cluster state Sequence number */ +#define COLUMN_WSREP_STATUS_CLUSTER_STATE_SEQNO 5 +/* Cluster membership changes */ +#define COLUMN_WSREP_STATUS_CLUSTER_CONF_ID 6 +/* Gap between global and local states ? */ +#define COLUMN_WSREP_STATUS_GAP 7 +/* Application protocol version */ +#define COLUMN_WSREP_STATUS_PROTO_VERSION 8 + +static const char* get_member_status(wsrep_member_status_t status) +{ + switch (status) + { + case WSREP_MEMBER_UNDEFINED: return "Undefined"; + case WSREP_MEMBER_JOINER: return "Joiner"; + case WSREP_MEMBER_DONOR: return "Donor"; + case WSREP_MEMBER_JOINED: return "Joined"; + case WSREP_MEMBER_SYNCED: return "Synced"; + case WSREP_MEMBER_ERROR: return "Error"; + default: break; + } + return "UNKNOWN"; +} + +static const char* get_cluster_status(wsrep_view_status_t status) +{ + switch (status) + { + case WSREP_VIEW_PRIMARY: return "Primary"; + case WSREP_VIEW_NON_PRIMARY: return "Non-primary"; + case WSREP_VIEW_DISCONNECTED: return "Disconnected"; + default: break; + } + return "UNKNOWN"; +} + +static ST_FIELD_INFO wsrep_memb_fields[]= +{ + {"INDEX", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Index", 0}, + {"UUID", WSREP_UUID_STR_LEN, MYSQL_TYPE_STRING, 0, 0, "Uuid", 0}, + {"NAME", WSREP_MEMBER_NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", 0}, + {"ADDRESS", WSREP_INCOMING_LEN, MYSQL_TYPE_STRING, 0, 0, "Address", 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} +}; + +static ST_FIELD_INFO wsrep_status_fields[]= +{ + {"NODE_INDEX", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, + 0, 0, "Node_Index", 0}, + {"NODE_STATUS", 16, MYSQL_TYPE_STRING, 0, 0, "Node_Status", 0}, + {"CLUSTER_STATUS", 16, MYSQL_TYPE_STRING, 0, 0, "Cluster_Status", 0}, + {"CLUSTER_SIZE", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, + 0, 0, "Cluster_Size", 0}, + {"CLUSTER_STATE_UUID", WSREP_UUID_STR_LEN, MYSQL_TYPE_STRING, + 0, 0, 0, 0}, + {"CLUSTER_STATE_SEQNO", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, + 0, 0, 0, 0}, + {"CLUSTER_CONF_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, + 0, 0, 0, 0}, + {"GAP", 10, MYSQL_TYPE_STRING, 0, 0, 0, 0}, + {"PROTOCOL_VERSION", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, + 0, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} +}; + +static int wsrep_memb_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) +{ + int rc= 0; + + if (check_global_access(thd, SUPER_ACL, true)) + return rc; + + wsrep_config_state.lock(); + + Dynamic_array *memb_arr= + wsrep_config_state.get_member_info(); + + TABLE *table= tables->table; + + for (unsigned int i= 0; i < memb_arr->elements(); i ++) + { + wsrep_member_info_t memb= memb_arr->at(i); + + table->field[COLUMN_WSREP_MEMB_INDEX]->store(i, 0); + + char uuid[40]; + wsrep_uuid_print(&memb.id, uuid, sizeof(uuid)); + table->field[COLUMN_WSREP_MEMB_UUID]->store(uuid, sizeof(uuid), + system_charset_info); + table->field[COLUMN_WSREP_MEMB_NAME]->store(memb.name, strlen(memb.name), + system_charset_info); + table->field[COLUMN_WSREP_MEMB_ADDRESS]->store(memb.incoming, + strlen(memb.incoming), + system_charset_info); + + if (schema_table_store_record(thd, table)) + { + rc= 1; + goto end; + } + } + +end: + wsrep_config_state.unlock(); + return rc; +} + +static int wsrep_memb_plugin_init(void *p) +{ + ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; + + schema->fields_info= wsrep_memb_fields; + schema->fill_table= wsrep_memb_fill_table; + + return 0; +} + +static struct st_mysql_information_schema wsrep_memb_plugin= +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + +static int wsrep_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) +{ + int rc= 0; + + if (check_global_access(thd, SUPER_ACL, true)) + return rc; + + wsrep_config_state.lock(); + + wsrep_view_info_t view= wsrep_config_state.get_view_info(); + wsrep_member_status_t status= wsrep_config_state.get_status(); + + TABLE *table= tables->table; + + table->field[COLUMN_WSREP_STATUS_NODE_INDEX] + ->store(view.my_idx, 0); + table->field[COLUMN_WSREP_STATUS_NODE_STATUS] + ->store(get_member_status(status), strlen(get_member_status(status)), + system_charset_info); + table->field[COLUMN_WSREP_STATUS_CLUSTER_STATUS] + ->store(get_cluster_status(view.status), + strlen(get_cluster_status(view.status)), + system_charset_info); + table->field[COLUMN_WSREP_STATUS_CLUSTER_SIZE]->store(view.memb_num, 0); + + char uuid[40]; + wsrep_uuid_print(&view.state_id.uuid, uuid, sizeof(uuid)); + table->field[COLUMN_WSREP_STATUS_CLUSTER_STATE_UUID] + ->store(uuid, sizeof(uuid), system_charset_info); + + table->field[COLUMN_WSREP_STATUS_CLUSTER_STATE_SEQNO] + ->store(view.state_id.seqno, 0); + table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID]->store(view.view, 0); + + const char *gap= (view.state_gap == true) ? "YES" : "NO"; + table->field[COLUMN_WSREP_STATUS_GAP]->store(gap, strlen(gap), + system_charset_info); + table->field[COLUMN_WSREP_STATUS_PROTO_VERSION]->store(view.proto_ver, 0); + + if (schema_table_store_record(thd, table)) + rc= 1; + + wsrep_config_state.unlock(); + return rc; +} + +static int wsrep_status_plugin_init(void *p) +{ + ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; + + schema->fields_info= wsrep_status_fields; + schema->fill_table= wsrep_status_fill_table; + + return 0; +} + +static struct st_mysql_information_schema wsrep_status_plugin= +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + +/* + Plugin library descriptor +*/ + +maria_declare_plugin(wsrep_status) +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &wsrep_memb_plugin, + "WSREP_MEMBERSHIP", /* Plugin name */ + "Nirbhay Choubey", /* Plugin author */ + "Information about group members", /* Plugin description */ + PLUGIN_LICENSE_GPL, /* License */ + wsrep_memb_plugin_init, /* Plugin Init */ + 0, /* Plugin Deinit */ + 0x0100, /* Version (hex) */ + NULL, /* Status variables */ + NULL, /* System variables */ + "1.0", /* Version (string) */ + MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity */ +}, +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &wsrep_status_plugin, + "WSREP_STATUS", /* Plugin name */ + "Nirbhay Choubey", /* Plugin author */ + "Group view information", /* Plugin description */ + PLUGIN_LICENSE_GPL, /* License */ + wsrep_status_plugin_init, /* Plugin Init */ + 0, /* Plugin Deinit */ + 0x0100, /* Version (hex) */ + NULL, /* Status variables */ + NULL, /* System variables */ + "1.0", /* Version (string) */ + MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity */ +} +maria_declare_plugin_end; + diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 81b1e182282..fed35190447 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -110,6 +110,8 @@ mysql_mutex_t LOCK_wsrep_replaying; mysql_cond_t COND_wsrep_replaying; mysql_mutex_t LOCK_wsrep_slave_threads; mysql_mutex_t LOCK_wsrep_desync; +mysql_mutex_t LOCK_wsrep_config_state; + int wsrep_replaying= 0; ulong wsrep_running_threads = 0; // # of currently running wsrep threads ulong my_bind_addr; @@ -118,7 +120,8 @@ ulong my_bind_addr; PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd, key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst, key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init, - key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync; + key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync, + key_LOCK_wsrep_config_state; PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_thd, key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst, @@ -135,7 +138,8 @@ static PSI_mutex_info wsrep_mutexes[]= { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0}, { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL}, - { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL} + { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL} }; static PSI_cond_info wsrep_conds[]= @@ -186,9 +190,10 @@ const char* wsrep_provider_vendor = provider_vendor; wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; -wsp::node_status local_status; long wsrep_protocol_version = 3; +wsp::Config_state wsrep_config_state; + // Boolean denoting if server is in initial startup phase. This is needed // to make sure that main thread waiting in wsrep_sst_wait() is signaled // if there was no state gap on receiving first view event. @@ -306,7 +311,7 @@ wsrep_view_handler_cb (void* app_ctx, *sst_req = NULL; *sst_req_len = 0; - wsrep_member_status_t new_status= local_status.get(); + wsrep_member_status_t memb_status= wsrep_config_state.get_status(); if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t))) { @@ -331,7 +336,7 @@ wsrep_view_handler_cb (void* app_ctx, /* Proceed further only if view is PRIMARY */ if (WSREP_VIEW_PRIMARY != view->status) { wsrep_ready_set(FALSE); - new_status= WSREP_MEMBER_UNDEFINED; + memb_status= WSREP_MEMBER_UNDEFINED; /* Always record local_uuid and local_seqno in non-prim since this * may lead to re-initializing provider and start position is * determined according to these variables */ @@ -386,13 +391,13 @@ wsrep_view_handler_cb (void* app_ctx, { WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len, strerror(-req_len)); - new_status= WSREP_MEMBER_UNDEFINED; + memb_status= WSREP_MEMBER_UNDEFINED; } else { assert(sst_req != NULL); *sst_req_len= req_len; - new_status= WSREP_MEMBER_JOINER; + memb_status= WSREP_MEMBER_JOINER; } } else @@ -420,7 +425,7 @@ wsrep_view_handler_cb (void* app_ctx, XID xid; wsrep_xid_init(&xid, &local_uuid, local_seqno); wsrep_set_SE_checkpoint(&xid); - new_status= WSREP_MEMBER_JOINED; + memb_status= WSREP_MEMBER_JOINED; #ifdef GTID_SUPPORT wsrep_init_sidno(local_uuid); #endif /* GTID_SUPPORT */ @@ -456,7 +461,7 @@ wsrep_view_handler_cb (void* app_ctx, out: if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE; - local_status.set(new_status, view); + wsrep_config_state.set(memb_status, view); return WSREP_CB_SUCCESS; } @@ -498,7 +503,7 @@ static void wsrep_synced_cb(void* app_ctx) signal_main= true; } - local_status.set(WSREP_MEMBER_SYNCED); + wsrep_config_state.set(WSREP_MEMBER_SYNCED); mysql_mutex_unlock (&LOCK_wsrep_ready); if (signal_main) @@ -601,6 +606,7 @@ int wsrep_init() mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying, NULL); mysql_mutex_init(key_LOCK_wsrep_slave_threads, &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_config_state, &LOCK_wsrep_config_state, MY_MUTEX_INIT_FAST); wsrep_ready_set(FALSE); assert(wsrep_provider); @@ -846,6 +852,7 @@ void wsrep_deinit(bool free_options) mysql_cond_destroy(&COND_wsrep_replaying); mysql_mutex_destroy(&LOCK_wsrep_slave_threads); mysql_mutex_destroy(&LOCK_wsrep_desync); + mysql_mutex_destroy(&LOCK_wsrep_config_state); } void wsrep_recover() diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index ce22dc473fb..22f62dca0e8 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -232,6 +232,7 @@ extern mysql_mutex_t LOCK_wsrep_replaying; extern mysql_cond_t COND_wsrep_replaying; extern mysql_mutex_t LOCK_wsrep_slave_threads; extern mysql_mutex_t LOCK_wsrep_desync; +extern mysql_mutex_t LOCK_wsrep_config_state; extern wsrep_aborting_thd_t wsrep_aborting_thd; extern my_bool wsrep_emulate_bin_log; extern int wsrep_to_isolation; diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 17943308c37..bdd8aa9ec4e 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1102,8 +1102,8 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, { /* This will be reset when sync callback is called. * Should we set wsrep_ready to FALSE here too? */ -// wsrep_notify_status(WSREP_MEMBER_DONOR); - local_status.set(WSREP_MEMBER_DONOR); + + wsrep_config_state.set(WSREP_MEMBER_DONOR); const char* method = (char*)msg; size_t method_len = strlen (method); diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 337678238f8..0e459c7d4b6 100644 --- a/sql/wsrep_utils.h +++ b/sql/wsrep_utils.h @@ -17,32 +17,82 @@ #define WSREP_UTILS_H #include "wsrep_priv.h" +#include "wsrep_mysqld.h" unsigned int wsrep_check_ip (const char* addr); size_t wsrep_guess_ip (char* buf, size_t buf_len); size_t wsrep_guess_address(char* buf, size_t buf_len); namespace wsp { -class node_status + +class Config_state { public: - node_status() : status(WSREP_MEMBER_UNDEFINED) {} - void set(wsrep_member_status_t new_status, - const wsrep_view_info_t* view = 0) + Config_state() : view_(), status_(WSREP_MEMBER_UNDEFINED) + {} + + void set(wsrep_member_status_t status, const wsrep_view_info_t* view) { - if (status != new_status || 0 != view) + wsrep_notify_status(status, view); + + lock(); + + status_= status; + view_= *view; + member_info_.clear(); + + wsrep_member_info_t memb; + for(int i= 0; i < view->memb_num; i ++) { - wsrep_notify_status(new_status, view); - status = new_status; + memb= view->members[i]; + member_info_.append_val(memb); } + + unlock(); } - wsrep_member_status_t get() const { return status; } + + void set(wsrep_member_status_t status) + { + wsrep_notify_status(status, 0); + lock(); + status_= status; + unlock(); + } + + wsrep_view_info_t get_view_info() const + { + return view_; + } + + wsrep_member_status_t get_status() const + { + return status_; + } + + Dynamic_array * get_member_info() + { + return &member_info_; + } + + int lock() + { + return mysql_mutex_lock(&LOCK_wsrep_config_state); + } + + int unlock() + { + return mysql_mutex_unlock(&LOCK_wsrep_config_state); + } + private: - wsrep_member_status_t status; + wsrep_view_info_t view_; + wsrep_member_status_t status_; + Dynamic_array member_info_; }; + } /* namespace wsp */ -extern wsp::node_status local_status; +extern wsp::Config_state wsrep_config_state; namespace wsp { /* A small class to run external programs. */