| 1 | /* Copyright (C) 2014 MariaDB Corporation. |
| 2 | |
| 3 | This program is free software; you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation; version 2 of the License. |
| 6 | |
| 7 | This program is distributed in the hope that it will be useful, |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | GNU General Public License for more details. |
| 11 | |
| 12 | You should have received a copy of the GNU General Public License |
| 13 | along with this program; if not, write to the Free Software |
| 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
| 15 | |
| 16 | #ifndef MYSQL_SERVER |
| 17 | #define MYSQL_SERVER |
| 18 | #endif |
| 19 | |
| 20 | #include <my_global.h> |
| 21 | #include <mysql/plugin.h> |
| 22 | #include <table.h> /* ST_SCHEMA_TABLE */ |
| 23 | #include <sql_show.h> |
| 24 | #include <sql_acl.h> /* check_global_access() */ |
| 25 | #include <wsrep_mysqld.h> |
| 26 | #include <wsrep_utils.h> |
| 27 | |
| 28 | /* WSREP_MEMBERSHIP table fields */ |
| 29 | |
| 30 | /* Node index */ |
| 31 | #define COLUMN_WSREP_MEMB_INDEX 0 |
| 32 | /* Unique member ID */ |
| 33 | #define COLUMN_WSREP_MEMB_UUID 1 |
| 34 | /* Human-readable name */ |
| 35 | #define COLUMN_WSREP_MEMB_NAME 2 |
| 36 | /* Incoming address */ |
| 37 | #define COLUMN_WSREP_MEMB_ADDRESS 3 |
| 38 | |
| 39 | /* WSREP_STATUS table fields */ |
| 40 | |
| 41 | /* Node index */ |
| 42 | #define COLUMN_WSREP_STATUS_NODE_INDEX 0 |
| 43 | /* Node status */ |
| 44 | #define COLUMN_WSREP_STATUS_NODE_STATUS 1 |
| 45 | /* Cluster status */ |
| 46 | #define COLUMN_WSREP_STATUS_CLUSTER_STATUS 2 |
| 47 | /* Cluster size */ |
| 48 | #define COLUMN_WSREP_STATUS_CLUSTER_SIZE 3 |
| 49 | /* Global cluster state UUID */ |
| 50 | #define COLUMN_WSREP_STATUS_CLUSTER_STATE_UUID 4 |
| 51 | /* Global cluster state Sequence number */ |
| 52 | #define COLUMN_WSREP_STATUS_CLUSTER_STATE_SEQNO 5 |
| 53 | /* Cluster membership changes */ |
| 54 | #define COLUMN_WSREP_STATUS_CLUSTER_CONF_ID 6 |
| 55 | /* Gap between global and local states ? */ |
| 56 | #define COLUMN_WSREP_STATUS_GAP 7 |
| 57 | /* Application protocol version */ |
| 58 | #define COLUMN_WSREP_STATUS_PROTO_VERSION 8 |
| 59 | |
| 60 | static const char* get_member_status(wsrep_member_status_t status) |
| 61 | { |
| 62 | switch (status) |
| 63 | { |
| 64 | case WSREP_MEMBER_UNDEFINED: return "Undefined" ; |
| 65 | case WSREP_MEMBER_JOINER: return "Joiner" ; |
| 66 | case WSREP_MEMBER_DONOR: return "Donor" ; |
| 67 | case WSREP_MEMBER_JOINED: return "Joined" ; |
| 68 | case WSREP_MEMBER_SYNCED: return "Synced" ; |
| 69 | case WSREP_MEMBER_ERROR: return "Error" ; |
| 70 | default: break; |
| 71 | } |
| 72 | return "UNKNOWN" ; |
| 73 | } |
| 74 | |
| 75 | static const char* get_cluster_status(wsrep_view_status_t status) |
| 76 | { |
| 77 | switch (status) |
| 78 | { |
| 79 | case WSREP_VIEW_PRIMARY: return "Primary" ; |
| 80 | case WSREP_VIEW_NON_PRIMARY: return "Non-primary" ; |
| 81 | case WSREP_VIEW_DISCONNECTED: return "Disconnected" ; |
| 82 | default: break; |
| 83 | } |
| 84 | return "UNKNOWN" ; |
| 85 | } |
| 86 | |
| 87 | static ST_FIELD_INFO wsrep_memb_fields[]= |
| 88 | { |
| 89 | {"INDEX" , MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Index" , 0}, |
| 90 | {"UUID" , WSREP_UUID_STR_LEN, MYSQL_TYPE_STRING, 0, 0, "Uuid" , 0}, |
| 91 | {"NAME" , WSREP_MEMBER_NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name" , 0}, |
| 92 | {"ADDRESS" , WSREP_INCOMING_LEN, MYSQL_TYPE_STRING, 0, 0, "Address" , 0}, |
| 93 | {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} |
| 94 | }; |
| 95 | |
| 96 | static ST_FIELD_INFO wsrep_status_fields[]= |
| 97 | { |
| 98 | {"NODE_INDEX" , MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, |
| 99 | 0, 0, "Node_Index" , 0}, |
| 100 | {"NODE_STATUS" , 16, MYSQL_TYPE_STRING, 0, 0, "Node_Status" , 0}, |
| 101 | {"CLUSTER_STATUS" , 16, MYSQL_TYPE_STRING, 0, 0, "Cluster_Status" , 0}, |
| 102 | {"CLUSTER_SIZE" , MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, |
| 103 | 0, 0, "Cluster_Size" , 0}, |
| 104 | {"CLUSTER_STATE_UUID" , WSREP_UUID_STR_LEN, MYSQL_TYPE_STRING, |
| 105 | 0, 0, 0, 0}, |
| 106 | {"CLUSTER_STATE_SEQNO" , MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, |
| 107 | 0, 0, 0, 0}, |
| 108 | {"CLUSTER_CONF_ID" , MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, |
| 109 | 0, 0, 0, 0}, |
| 110 | {"GAP" , 10, MYSQL_TYPE_STRING, 0, 0, 0, 0}, |
| 111 | {"PROTOCOL_VERSION" , MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, |
| 112 | 0, 0, 0, 0}, |
| 113 | {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} |
| 114 | }; |
| 115 | |
| 116 | static int wsrep_memb_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) |
| 117 | { |
| 118 | int rc= 0; |
| 119 | |
| 120 | if (check_global_access(thd, SUPER_ACL, true)) |
| 121 | return rc; |
| 122 | |
| 123 | wsrep_config_state->lock(); |
| 124 | |
| 125 | Dynamic_array<wsrep_member_info_t> *memb_arr= |
| 126 | wsrep_config_state->get_member_info(); |
| 127 | |
| 128 | TABLE *table= tables->table; |
| 129 | |
| 130 | for (unsigned int i= 0; i < memb_arr->elements(); i ++) |
| 131 | { |
| 132 | wsrep_member_info_t memb= memb_arr->at(i); |
| 133 | |
| 134 | table->field[COLUMN_WSREP_MEMB_INDEX]->store(i, 0); |
| 135 | |
| 136 | char uuid[40]; |
| 137 | wsrep_uuid_print(&memb.id, uuid, sizeof(uuid)); |
| 138 | table->field[COLUMN_WSREP_MEMB_UUID]->store(uuid, sizeof(uuid), |
| 139 | system_charset_info); |
| 140 | table->field[COLUMN_WSREP_MEMB_NAME]->store(memb.name, strlen(memb.name), |
| 141 | system_charset_info); |
| 142 | table->field[COLUMN_WSREP_MEMB_ADDRESS]->store(memb.incoming, |
| 143 | strlen(memb.incoming), |
| 144 | system_charset_info); |
| 145 | |
| 146 | if (schema_table_store_record(thd, table)) |
| 147 | { |
| 148 | rc= 1; |
| 149 | goto end; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | end: |
| 154 | wsrep_config_state->unlock(); |
| 155 | return rc; |
| 156 | } |
| 157 | |
| 158 | static int wsrep_memb_plugin_init(void *p) |
| 159 | { |
| 160 | ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; |
| 161 | |
| 162 | schema->fields_info= wsrep_memb_fields; |
| 163 | schema->fill_table= wsrep_memb_fill_table; |
| 164 | |
| 165 | return 0; |
| 166 | } |
| 167 | |
| 168 | static struct st_mysql_information_schema wsrep_memb_plugin= |
| 169 | { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; |
| 170 | |
| 171 | static int wsrep_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) |
| 172 | { |
| 173 | int rc= 0; |
| 174 | |
| 175 | if (check_global_access(thd, SUPER_ACL, true)) |
| 176 | return rc; |
| 177 | |
| 178 | wsrep_config_state->lock(); |
| 179 | |
| 180 | wsrep_view_info_t view= wsrep_config_state->get_view_info(); |
| 181 | wsrep_member_status_t status= wsrep_config_state->get_status(); |
| 182 | |
| 183 | TABLE *table= tables->table; |
| 184 | |
| 185 | table->field[COLUMN_WSREP_STATUS_NODE_INDEX] |
| 186 | ->store(view.my_idx, 0); |
| 187 | table->field[COLUMN_WSREP_STATUS_NODE_STATUS] |
| 188 | ->store(get_member_status(status), strlen(get_member_status(status)), |
| 189 | system_charset_info); |
| 190 | table->field[COLUMN_WSREP_STATUS_CLUSTER_STATUS] |
| 191 | ->store(get_cluster_status(view.status), |
| 192 | strlen(get_cluster_status(view.status)), |
| 193 | system_charset_info); |
| 194 | table->field[COLUMN_WSREP_STATUS_CLUSTER_SIZE]->store(view.memb_num, 0); |
| 195 | |
| 196 | char uuid[40]; |
| 197 | wsrep_uuid_print(&view.state_id.uuid, uuid, sizeof(uuid)); |
| 198 | table->field[COLUMN_WSREP_STATUS_CLUSTER_STATE_UUID] |
| 199 | ->store(uuid, sizeof(uuid), system_charset_info); |
| 200 | |
| 201 | table->field[COLUMN_WSREP_STATUS_CLUSTER_STATE_SEQNO] |
| 202 | ->store(view.state_id.seqno, 0); |
| 203 | table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID]->store(view.view, 0); |
| 204 | |
| 205 | const char *gap= (view.state_gap == true) ? "YES" : "NO" ; |
| 206 | table->field[COLUMN_WSREP_STATUS_GAP]->store(gap, strlen(gap), |
| 207 | system_charset_info); |
| 208 | table->field[COLUMN_WSREP_STATUS_PROTO_VERSION]->store(view.proto_ver, 0); |
| 209 | |
| 210 | if (schema_table_store_record(thd, table)) |
| 211 | rc= 1; |
| 212 | |
| 213 | wsrep_config_state->unlock(); |
| 214 | return rc; |
| 215 | } |
| 216 | |
| 217 | static int wsrep_status_plugin_init(void *p) |
| 218 | { |
| 219 | ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; |
| 220 | |
| 221 | schema->fields_info= wsrep_status_fields; |
| 222 | schema->fill_table= wsrep_status_fill_table; |
| 223 | |
| 224 | return 0; |
| 225 | } |
| 226 | |
| 227 | static struct st_mysql_information_schema wsrep_status_plugin= |
| 228 | { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; |
| 229 | |
| 230 | /* |
| 231 | Plugin library descriptor |
| 232 | */ |
| 233 | |
| 234 | maria_declare_plugin(wsrep_info) |
| 235 | { |
| 236 | MYSQL_INFORMATION_SCHEMA_PLUGIN, |
| 237 | &wsrep_memb_plugin, |
| 238 | "WSREP_MEMBERSHIP" , /* Plugin name */ |
| 239 | "Nirbhay Choubey" , /* Plugin author */ |
| 240 | "Information about group members" , /* Plugin description */ |
| 241 | PLUGIN_LICENSE_GPL, /* License */ |
| 242 | wsrep_memb_plugin_init, /* Plugin Init */ |
| 243 | 0, /* Plugin Deinit */ |
| 244 | 0x0100, /* Version (hex) */ |
| 245 | NULL, /* Status variables */ |
| 246 | NULL, /* System variables */ |
| 247 | "1.0" , /* Version (string) */ |
| 248 | MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */ |
| 249 | }, |
| 250 | { |
| 251 | MYSQL_INFORMATION_SCHEMA_PLUGIN, |
| 252 | &wsrep_status_plugin, |
| 253 | "WSREP_STATUS" , /* Plugin name */ |
| 254 | "Nirbhay Choubey" , /* Plugin author */ |
| 255 | "Group view information" , /* Plugin description */ |
| 256 | PLUGIN_LICENSE_GPL, /* License */ |
| 257 | wsrep_status_plugin_init, /* Plugin Init */ |
| 258 | 0, /* Plugin Deinit */ |
| 259 | 0x0100, /* Version (hex) */ |
| 260 | NULL, /* Status variables */ |
| 261 | NULL, /* System variables */ |
| 262 | "1.0" , /* Version (string) */ |
| 263 | MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */ |
| 264 | } |
| 265 | maria_declare_plugin_end; |
| 266 | |
| 267 | |