1 /*
2 Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <my_config.h>
26
27 #include <mysql/plugin.h>
28 #include <mysql_version.h>
29
30 #include "xpl_session.h"
31 #include "xpl_system_variables.h"
32 #include "xpl_server.h"
33 #include "xpl_performance_schema.h"
34 #include "mysqlx_version.h"
35 #include "xpl_log.h"
36
37 #include <stdio.h> // Solaris header file bug.
38 #include <limits>
39
40 #define BYTE(X) (X)
41 #define KBYTE(X) ((X) * 1024)
42 #define MBYTE(X) ((X) * 1024 * 1024)
43 #define GBYTE(X) ((X) * 1024 * 1024 * 1024)
44
45 namespace
46 {
47
48 typedef void (*Xpl_status_variable_get)(THD *, st_mysql_show_var *, char *);
49
xpl_func_ptr(Xpl_status_variable_get callback)50 char *xpl_func_ptr(Xpl_status_variable_get callback)
51 {
52 union
53 {
54 char *ptr;
55 Xpl_status_variable_get callback;
56 } ptr_cast;
57
58 ptr_cast.callback = callback;
59
60 return ptr_cast.ptr;
61 }
62
exit_hook()63 void exit_hook()
64 {
65 google::protobuf::ShutdownProtobufLibrary();
66 }
67
68 } // namespace
69
70
71 /*
72 Start the plugin: start webservers
73
74 SYNOPSIS
75 xpl_plugin_init()
76 p plugin handle
77
78 RETURN
79 0 success
80 1 error
81 */
xpl_plugin_init(MYSQL_PLUGIN p)82 int xpl_plugin_init(MYSQL_PLUGIN p)
83 {
84 static bool atexit_installed = false;
85 if (!atexit_installed)
86 {
87 atexit_installed = true;
88 atexit(exit_hook);
89 }
90
91 xpl::Plugin_system_variables::clean_callbacks();
92
93 xpl_init_performance_schema();
94
95 return xpl::Server::main(p);
96 }
97
98 /*
99 Shutdown the plugin: stop webservers
100
101 SYNOPSIS
102 xpl_plugin_deinit()
103 p plugin handle
104
105 RETURN
106 0 success
107 1 error
108 */
xpl_plugin_deinit(MYSQL_PLUGIN p)109 int xpl_plugin_deinit(MYSQL_PLUGIN p)
110 {
111 return xpl::Server::exit(p);
112 }
113
114
115 static struct st_mysql_daemon xpl_plugin_info ={
116 MYSQL_DAEMON_INTERFACE_VERSION
117 };
118
119
120 static MYSQL_SYSVAR_UINT(port, xpl::Plugin_system_variables::port,
121 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
122 "Port on which X Plugin is going to accept incoming connections.",
123 NULL, NULL, MYSQLX_TCP_PORT, 1, std::numeric_limits<uint16>::max(), 0);
124
125 static MYSQL_SYSVAR_INT(max_connections, xpl::Plugin_system_variables::max_connections,
126 PLUGIN_VAR_OPCMDARG,
127 "Maximum number of concurrent X protocol connections. Actual number of connections is also affected by the general max_connections.",
128 NULL, NULL, 100, 1, std::numeric_limits<unsigned short>::max(), 0);
129
130 static MYSQL_SYSVAR_UINT(min_worker_threads, xpl::Plugin_system_variables::min_worker_threads,
131 PLUGIN_VAR_OPCMDARG,
132 "Minimal number of worker threads.",
133 NULL, &xpl::Plugin_system_variables::update_func<unsigned int>, 2U, 1, 100, 0);
134
135 static MYSQL_SYSVAR_UINT(idle_worker_thread_timeout, xpl::Plugin_system_variables::idle_worker_thread_timeout,
136 PLUGIN_VAR_OPCMDARG,
137 "Time after which an idle worker thread is terminated (in seconds).",
138 NULL, &xpl::Plugin_system_variables::update_func<unsigned int>, 60, 0, 60 * 60, 0);
139
140 static MYSQL_SYSVAR_UINT(max_allowed_packet, xpl::Plugin_system_variables::max_allowed_packet,
141 PLUGIN_VAR_OPCMDARG,
142 "Size of largest message that client is going to handle.",
143 NULL, &xpl::Plugin_system_variables::update_func<unsigned int>, MBYTE(1), BYTE(512), GBYTE(1), 0);
144
145 static MYSQL_SYSVAR_UINT(connect_timeout, xpl::Plugin_system_variables::connect_timeout,
146 PLUGIN_VAR_OPCMDARG,
147 "Maximum allowed waiting time for connection to setup a session (in seconds).",
148 NULL, &xpl::Plugin_system_variables::update_func<unsigned int>, 30, 1, 1000000000, 0);
149
150 static MYSQL_SYSVAR_STR(ssl_key, xpl::Plugin_system_variables::ssl_config.ssl_key,
151 PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
152 "X509 key in PEM format.", NULL, NULL, NULL);
153
154 static MYSQL_SYSVAR_STR(ssl_ca, xpl::Plugin_system_variables::ssl_config.ssl_ca,
155 PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
156 "CA file in PEM format.", NULL, NULL, NULL);
157
158 static MYSQL_SYSVAR_STR(ssl_capath, xpl::Plugin_system_variables::ssl_config.ssl_capath,
159 PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
160 "CA directory.", NULL, NULL, NULL);
161
162 static MYSQL_SYSVAR_STR(ssl_cert, xpl::Plugin_system_variables::ssl_config.ssl_cert,
163 PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
164 "X509 cert in PEM format.", NULL, NULL, NULL);
165
166 static MYSQL_SYSVAR_STR(ssl_cipher, xpl::Plugin_system_variables::ssl_config.ssl_cipher,
167 PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
168 "SSL cipher to use.", NULL, NULL, NULL);
169
170 static MYSQL_SYSVAR_STR(ssl_crl, xpl::Plugin_system_variables::ssl_config.ssl_crl,
171 PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
172 "Certificate revocation list.", NULL, NULL, NULL);
173
174 static MYSQL_SYSVAR_STR(ssl_crlpath, xpl::Plugin_system_variables::ssl_config.ssl_crlpath,
175 PLUGIN_VAR_READONLY,
176 "Certificate revocation list path.", NULL, NULL, NULL);
177
178 static MYSQL_SYSVAR_STR(socket, xpl::Plugin_system_variables::socket,
179 PLUGIN_VAR_READONLY | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
180 "X Plugin's unix socket for local connection.", NULL, NULL, NULL);
181
182 static MYSQL_SYSVAR_STR(bind_address, xpl::Plugin_system_variables::bind_address,
183 PLUGIN_VAR_READONLY | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
184 "Address to which X Plugin should bind the TCP socket.", NULL, NULL, "*");
185
186 static MYSQL_SYSVAR_UINT(port_open_timeout, xpl::Plugin_system_variables::port_open_timeout,
187 PLUGIN_VAR_READONLY | PLUGIN_VAR_OPCMDARG ,
188 "How long X Plugin is going to retry binding of server socket (in case of failure)",
189 NULL, &xpl::Plugin_system_variables::update_func<unsigned int>, 0, 0, 120, 0);
190
191 static struct st_mysql_sys_var* xpl_plugin_system_variables[]= {
192 MYSQL_SYSVAR(port),
193 MYSQL_SYSVAR(max_connections),
194 MYSQL_SYSVAR(min_worker_threads),
195 MYSQL_SYSVAR(idle_worker_thread_timeout),
196 MYSQL_SYSVAR(max_allowed_packet),
197 MYSQL_SYSVAR(connect_timeout),
198 MYSQL_SYSVAR(ssl_key),
199 MYSQL_SYSVAR(ssl_ca),
200 MYSQL_SYSVAR(ssl_capath),
201 MYSQL_SYSVAR(ssl_cert),
202 MYSQL_SYSVAR(ssl_cipher),
203 MYSQL_SYSVAR(ssl_crl),
204 MYSQL_SYSVAR(ssl_crlpath),
205 MYSQL_SYSVAR(socket),
206 MYSQL_SYSVAR(bind_address),
207 MYSQL_SYSVAR(port_open_timeout),
208 NULL
209 };
210
211 #define SESSION_STATUS_VARIABLE_ENTRY_LONGLONG(NAME, METHOD) \
212 { MYSQLX_STATUS_VARIABLE_PREFIX(NAME), \
213 xpl_func_ptr(xpl::Server::common_status_variable<long long, &METHOD>), \
214 SHOW_FUNC, \
215 SHOW_SCOPE_GLOBAL }
216
217 #define GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG(NAME, METHOD) \
218 { MYSQLX_STATUS_VARIABLE_PREFIX(NAME), \
219 xpl_func_ptr(xpl::Server::global_status_variable_server<long long, &METHOD>), \
220 SHOW_FUNC, \
221 SHOW_SCOPE_GLOBAL }
222
223 #define GLOBAL_SSL_STATUS_VARIABLE_ENTRY(NAME, TYPE, METHOD) \
224 { MYSQLX_STATUS_VARIABLE_PREFIX(NAME), \
225 xpl_func_ptr(xpl::Server::global_status_variable<TYPE, &METHOD>), \
226 SHOW_FUNC, \
227 SHOW_SCOPE_GLOBAL }
228
229 #define SESSION_SSL_STATUS_VARIABLE_ENTRY(NAME, TYPE, METHOD) \
230 { MYSQLX_STATUS_VARIABLE_PREFIX(NAME), \
231 xpl_func_ptr(xpl::Server::session_status_variable<TYPE, &METHOD>), \
232 SHOW_FUNC, \
233 SHOW_SCOPE_GLOBAL }
234
235 #define SESSION_SSL_STATUS_VARIABLE_ENTRY_ARRAY(NAME, METHOD) \
236 { MYSQLX_STATUS_VARIABLE_PREFIX(NAME), \
237 xpl_func_ptr(xpl::Server::session_status_variable<&METHOD>), \
238 SHOW_FUNC, \
239 SHOW_SCOPE_GLOBAL }
240
241 #define GLOBAL_CUSTOM_STATUS_VARIABLE_ENTRY(NAME, TYPE, METHOD) \
242 { MYSQLX_STATUS_VARIABLE_PREFIX(NAME), \
243 xpl_func_ptr(xpl::Server::global_status_variable_server_with_return<TYPE, &METHOD>), \
244 SHOW_FUNC, \
245 SHOW_SCOPE_GLOBAL }
246
247 static struct st_mysql_show_var xpl_plugin_status[]=
248 {
249 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_execute_sql", xpl::Common_status_variables::m_stmt_execute_sql),
250 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_execute_xplugin", xpl::Common_status_variables::m_stmt_execute_xplugin),
251 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_execute_mysqlx", xpl::Common_status_variables::m_stmt_execute_mysqlx),
252 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_update", xpl::Common_status_variables::m_crud_update),
253 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_delete", xpl::Common_status_variables::m_crud_delete),
254 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_find", xpl::Common_status_variables::m_crud_find),
255 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_insert", xpl::Common_status_variables::m_crud_insert),
256 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_create_view", xpl::Common_status_variables::m_crud_create_view),
257 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_modify_view", xpl::Common_status_variables::m_crud_modify_view),
258 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("crud_drop_view", xpl::Common_status_variables::m_crud_drop_view),
259 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("expect_open", xpl::Common_status_variables::m_expect_open),
260 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("expect_close", xpl::Common_status_variables::m_expect_close),
261 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_create_collection", xpl::Common_status_variables::m_stmt_create_collection),
262 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_create_collection_index", xpl::Common_status_variables::m_stmt_create_collection_index),
263 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_drop_collection", xpl::Common_status_variables::m_stmt_drop_collection),
264 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_ensure_collection", xpl::Common_status_variables::m_stmt_ensure_collection),
265 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_drop_collection_index", xpl::Common_status_variables::m_stmt_drop_collection_index),
266 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_list_objects", xpl::Common_status_variables::m_stmt_list_objects),
267 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_enable_notices", xpl::Common_status_variables::m_stmt_enable_notices),
268 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_disable_notices", xpl::Common_status_variables::m_stmt_disable_notices),
269 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_list_notices", xpl::Common_status_variables::m_stmt_list_notices),
270 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_list_clients", xpl::Common_status_variables::m_stmt_list_clients),
271 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_kill_client", xpl::Common_status_variables::m_stmt_kill_client),
272 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("stmt_ping", xpl::Common_status_variables::m_stmt_ping),
273 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("bytes_sent", xpl::Common_status_variables::m_bytes_sent),
274 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("bytes_received", xpl::Common_status_variables::m_bytes_received),
275 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("errors_sent", xpl::Common_status_variables::m_errors_sent),
276 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("rows_sent", xpl::Common_status_variables::m_rows_sent),
277 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("notice_warning_sent", xpl::Common_status_variables::m_notice_warning_sent),
278 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("notice_other_sent", xpl::Common_status_variables::m_notice_other_sent),
279 SESSION_STATUS_VARIABLE_ENTRY_LONGLONG("errors_unknown_message_type", xpl::Common_status_variables::m_errors_unknown_message_type),
280 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("sessions", xpl::Global_status_variables::m_sessions_count),
281 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("sessions_closed", xpl::Global_status_variables::m_closed_sessions_count),
282 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("sessions_fatal_error", xpl::Global_status_variables::m_sessions_fatal_errors_count),
283 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("init_error", xpl::Global_status_variables::m_init_errors_count),
284 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("sessions_accepted", xpl::Global_status_variables::m_accepted_sessions_count),
285 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("sessions_rejected", xpl::Global_status_variables::m_rejected_sessions_count),
286 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("sessions_killed", xpl::Global_status_variables::m_killed_sessions_count),
287 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("connections_closed", xpl::Global_status_variables::m_closed_connections_count),
288 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("connections_accepted", xpl::Global_status_variables::m_accepted_connections_count),
289 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("connections_rejected", xpl::Global_status_variables::m_rejected_connections_count),
290 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("connection_accept_errors", xpl::Global_status_variables::m_connection_accept_errors_count),
291 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("connection_errors", xpl::Global_status_variables::m_connection_errors_count),
292 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("worker_threads", xpl::Global_status_variables::m_worker_thread_count),
293 GLOBAL_STATUS_VARIABLE_ENTRY_LONGLONG("worker_threads_active", xpl::Global_status_variables::m_active_worker_thread_count),
294
295 SESSION_SSL_STATUS_VARIABLE_ENTRY_ARRAY("ssl_cipher_list", xpl::Client::get_status_ssl_cipher_list),
296 SESSION_SSL_STATUS_VARIABLE_ENTRY("ssl_active", bool, ngs::IOptions_session::active_tls),
297 SESSION_SSL_STATUS_VARIABLE_ENTRY("ssl_cipher", std::string, ngs::IOptions_session::ssl_cipher),
298 SESSION_SSL_STATUS_VARIABLE_ENTRY("ssl_version", std::string, ngs::IOptions_session::ssl_version),
299 SESSION_SSL_STATUS_VARIABLE_ENTRY("ssl_verify_depth", long, ngs::IOptions_session::ssl_verify_depth),
300 SESSION_SSL_STATUS_VARIABLE_ENTRY("ssl_verify_mode", long, ngs::IOptions_session::ssl_verify_mode),
301 GLOBAL_SSL_STATUS_VARIABLE_ENTRY("ssl_ctx_verify_depth", long, ngs::IOptions_context::ssl_ctx_verify_depth),
302 GLOBAL_SSL_STATUS_VARIABLE_ENTRY("ssl_ctx_verify_mode", long, ngs::IOptions_context::ssl_ctx_verify_mode),
303 GLOBAL_SSL_STATUS_VARIABLE_ENTRY("ssl_finished_accepts", long, ngs::IOptions_context::ssl_sess_accept_good),
304 GLOBAL_SSL_STATUS_VARIABLE_ENTRY("ssl_accepts", long, ngs::IOptions_context::ssl_sess_accept),
305 GLOBAL_SSL_STATUS_VARIABLE_ENTRY("ssl_server_not_after", std::string, ngs::IOptions_context::ssl_server_not_after),
306 GLOBAL_SSL_STATUS_VARIABLE_ENTRY("ssl_server_not_before", std::string, ngs::IOptions_context::ssl_server_not_before),
307
308 GLOBAL_CUSTOM_STATUS_VARIABLE_ENTRY("socket", std::string, xpl::Server::get_socket_file),
309 GLOBAL_CUSTOM_STATUS_VARIABLE_ENTRY("port", std::string, xpl::Server::get_tcp_port),
310 GLOBAL_CUSTOM_STATUS_VARIABLE_ENTRY("address", std::string, xpl::Server::get_tcp_bind_address),
311
312 { NULL, NULL, SHOW_BOOL, SHOW_SCOPE_GLOBAL}
313 };
314
315
mysql_declare_plugin(xpl)316 mysql_declare_plugin(xpl)
317 {
318 MYSQL_DAEMON_PLUGIN,
319 &xpl_plugin_info,
320 MYSQLX_PLUGIN_NAME,
321 "Oracle Corp",
322 "X Plugin for MySQL",
323 PLUGIN_LICENSE_GPL,
324 xpl_plugin_init, /* init */
325 xpl_plugin_deinit, /* deinit */
326 MYSQLX_PLUGIN_VERSION, /* version */
327 xpl_plugin_status, /* status var */
328 xpl_plugin_system_variables, /* system var */
329 NULL, /* options */
330 0 /* flags */
331 }
332 mysql_declare_plugin_end;
333