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 | |