summaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay@mariadb.com>2014-11-22 14:33:51 -0500
committerNirbhay Choubey <nirbhay@mariadb.com>2014-11-22 14:33:51 -0500
commit369c02674cb024ceb1995433913ef2fb32f815ca (patch)
tree1d237e09056dfceb996305fb0cfa4f87c083e72a /plugin
parentcbc318fcf3680c01dca1320b87f625124a497528 (diff)
downloadmariadb-git-369c02674cb024ceb1995433913ef2fb32f815ca.tar.gz
MDEV-7053: WSREP_STATUS & WSREP_MEMBERSHIP I_S tables
wsrep_info INFORMATION_SCHEMA plugin to provide WSREP_STATUS and WSREP_MEMBERSHIP tables.
Diffstat (limited to 'plugin')
-rw-r--r--plugin/wsrep_info/CMakeLists.txt5
-rw-r--r--plugin/wsrep_info/mysql-test/wsrep_info/my.cnf35
-rw-r--r--plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result17
-rw-r--r--plugin/wsrep_info/mysql-test/wsrep_info/suite.opt1
-rw-r--r--plugin/wsrep_info/mysql-test/wsrep_info/suite.pm43
-rw-r--r--plugin/wsrep_info/mysql-test/wsrep_info/t/plugin.test23
-rw-r--r--plugin/wsrep_info/plugin.cc265
7 files changed, 389 insertions, 0 deletions
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
+<IDX> Synced Primary 2 <CLUSTER_STATE_UUID> 0 2 NO 3
+SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME;
+INDEX UUID NAME ADDRESS
+<IDX> <MEMBER_ID> test-node-1 <ADDRESS>
+<IDX> <MEMBER_ID> test-node-2 <ADDRESS>
+# 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
+<IDX> Synced Primary 2 <CLUSTER_STATE_UUID> 0 2 YES 3
+SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME;
+INDEX UUID NAME ADDRESS
+<IDX> <MEMBER_ID> test-node-1 <ADDRESS>
+<IDX> <MEMBER_ID> test-node-2 <ADDRESS>
+# 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 <IDX> 5 <CLUSTER_STATE_UUID>
+SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS;
+
+--replace_column 1 <IDX> 2 <MEMBER_ID> 4 <ADDRESS>
+SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME;
+
+--echo # On node 2
+--connection node_2
+
+--replace_column 1 <IDX> 5 <CLUSTER_STATE_UUID>
+SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS;
+
+--replace_column 1 <IDX> 2 <MEMBER_ID> 4 <ADDRESS>
+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 <mysql/plugin.h>
+#include <table.h> /* ST_SCHEMA_TABLE */
+#include <sql_show.h>
+#include <sql_acl.h> /* check_global_access() */
+#include <wsrep_mysqld.h>
+#include <wsrep_utils.h>
+
+/* 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<wsrep_member_info_t> *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;
+