diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:24:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:24:36 +0000 |
commit | 06eaf7232e9a920468c0f8d74dcf2fe8b555501c (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /include/mysql | |
parent | Initial commit. (diff) | |
download | mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.tar.xz mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/mysql')
65 files changed, 19687 insertions, 0 deletions
diff --git a/include/mysql/auth_dialog_client.h b/include/mysql/auth_dialog_client.h new file mode 100644 index 00000000..f1ad3e69 --- /dev/null +++ b/include/mysql/auth_dialog_client.h @@ -0,0 +1,56 @@ +#ifndef MYSQL_AUTH_DIALOG_CLIENT_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Definitions needed to use Dialog client authentication plugin +*/ + +struct st_mysql; + +#define MYSQL_AUTH_DIALOG_CLIENT_INCLUDED + +/** + type of the mysql_authentication_dialog_ask function + + @param mysql mysql + @param type type of the input + 1 - ordinary string input + 2 - password string + @param prompt prompt + @param buf a buffer to store the use input + @param buf_len the length of the buffer + + @retval a pointer to the user input string. + It may be equal to 'buf' or to 'mysql->password'. + In all other cases it is assumed to be an allocated + string, and the "dialog" plugin will free() it. +*/ +typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, + int type, const char *prompt, char *buf, int buf_len); + +/** + first byte of the question string is the question "type". + It can be an "ordinary" or a "password" question. + The last bit set marks a last question in the authentication exchange. +*/ +#define ORDINARY_QUESTION "\2" +#define LAST_QUESTION "\3" +#define PASSWORD_QUESTION "\4" +#define LAST_PASSWORD "\5" + +#endif diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h new file mode 100644 index 00000000..990cecc9 --- /dev/null +++ b/include/mysql/client_plugin.h @@ -0,0 +1,188 @@ +#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, 2011, Oracle and/or its affiliates. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + MySQL Client Plugin API + + This file defines the API for plugins that work on the client side +*/ +#define MYSQL_CLIENT_PLUGIN_INCLUDED + +/* + On Windows, exports from DLL need to be declared + Also, plugin needs to be declared as extern "C" because MSVC + unlike other compilers, uses C++ mangling for variables not only + for functions. +*/ +#undef MYSQL_PLUGIN_EXPORT +#if defined(_MSC_VER) + #define MYSQL_PLUGIN_EXPORT_C __declspec(dllexport) +#else /*_MSC_VER */ + #define MYSQL_PLUGIN_EXPORT_C +#endif +#ifdef __cplusplus +#define MYSQL_PLUGIN_EXPORT extern "C" MYSQL_PLUGIN_EXPORT_C +#define C_MODE_START extern "C" { +#define C_MODE_END } +#else +#define MYSQL_PLUGIN_EXPORT MYSQL_PLUGIN_EXPORT_C +#define C_MODE_START +#define C_MODE_END +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#include <stdlib.h> +#endif + +/* known plugin types */ +#define MYSQL_CLIENT_reserved1 0 +#define MYSQL_CLIENT_reserved2 1 +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 + +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100 + +#define MYSQL_CLIENT_MAX_PLUGINS 3 + +#define mysql_declare_client_plugin(X) \ + C_MODE_START MYSQL_PLUGIN_EXPORT_C \ + struct st_mysql_client_plugin_ ## X \ + _mysql_client_plugin_declaration_ = { \ + MYSQL_CLIENT_ ## X ## _PLUGIN, \ + MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION, +#define mysql_end_client_plugin }; C_MODE_END + +/* generic plugin header structure */ +#define MYSQL_CLIENT_PLUGIN_HEADER \ + int type; \ + unsigned int interface_version; \ + const char *name; \ + const char *author; \ + const char *desc; \ + unsigned int version[3]; \ + const char *license; \ + void *mysql_api; \ + int (*init)(char *, size_t, int, va_list); \ + int (*deinit)(); \ + int (*options)(const char *option, const void *); + +struct st_mysql_client_plugin +{ + MYSQL_CLIENT_PLUGIN_HEADER +}; + +struct st_mysql; + +/******** authentication plugin specific declarations *********/ +#include <mysql/plugin_auth_common.h> + +struct st_mysql_client_plugin_AUTHENTICATION +{ + MYSQL_CLIENT_PLUGIN_HEADER + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; + +#include <mysql/auth_dialog_client.h> + +/******** using plugins ************/ + +/** + loads a plugin and initializes it + + @param mysql MYSQL structure. + @param name a name of the plugin to load + @param type type of plugin that should be loaded, -1 to disable type check + @param argc number of arguments to pass to the plugin initialization + function + @param ... arguments for the plugin initialization function + + @retval + a pointer to the loaded plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, + int argc, ...); + +/** + loads a plugin and initializes it, taking va_list as an argument + + This is the same as mysql_load_plugin, but take va_list instead of + a list of arguments. + + @param mysql MYSQL structure. + @param name a name of the plugin to load + @param type type of plugin that should be loaded, -1 to disable type check + @param argc number of arguments to pass to the plugin initialization + function + @param args arguments for the plugin initialization function + + @retval + a pointer to the loaded plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, + int argc, va_list args); + +/** + finds an already loaded plugin by name, or loads it, if necessary + + @param mysql MYSQL structure. + @param name a name of the plugin to load + @param type type of plugin that should be loaded + + @retval + a pointer to the plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); + +/** + adds a plugin structure to the list of loaded plugins + + This is useful if an application has the necessary functionality + (for example, a special load data handler) statically linked into + the application binary. It can use this function to register the plugin + directly, avoiding the need to factor it out into a shared object. + + @param mysql MYSQL structure. It is only used for error reporting + @param plugin an st_mysql_client_plugin structure to register + + @retval + a pointer to the plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_client_register_plugin(struct st_mysql *mysql, + struct st_mysql_client_plugin *plugin); + +/** + set plugin options + + Can be used to set extra options and affect behavior for a plugin. + This function may be called multiple times to set several options + + @param plugin an st_mysql_client_plugin structure + @param option a string which specifies the option to set + @param value value for the option. + + @retval 0 on success, 1 in case of failure +**/ +int mysql_plugin_options(struct st_mysql_client_plugin *plugin, + const char *option, const void *value); +#endif + diff --git a/include/mysql/client_plugin.h.pp b/include/mysql/client_plugin.h.pp new file mode 100644 index 00000000..b6ba9cf0 --- /dev/null +++ b/include/mysql/client_plugin.h.pp @@ -0,0 +1,41 @@ +struct st_mysql_client_plugin +{ + int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *); +}; +struct st_mysql; +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; +} MYSQL_PLUGIN_VIO_INFO; +typedef struct st_plugin_vio +{ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); +} MYSQL_PLUGIN_VIO; +struct st_mysql_client_plugin_AUTHENTICATION +{ + int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *); + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; +struct st_mysql; +typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, + int type, const char *prompt, char *buf, int buf_len); +struct st_mysql_client_plugin * +mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, + int argc, ...); +struct st_mysql_client_plugin * +mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, + int argc, va_list args); +struct st_mysql_client_plugin * +mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); +struct st_mysql_client_plugin * +mysql_client_register_plugin(struct st_mysql *mysql, + struct st_mysql_client_plugin *plugin); +int mysql_plugin_options(struct st_mysql_client_plugin *plugin, + const char *option, const void *value); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h new file mode 100644 index 00000000..14c75251 --- /dev/null +++ b/include/mysql/plugin.h @@ -0,0 +1,794 @@ +/* Copyright (c) 2005, 2013, Oracle and/or its affiliates + Copyright (C) 2009, 2017, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PLUGIN_INCLUDED +#define MYSQL_PLUGIN_INCLUDED + +/* + On Windows, exports from DLL need to be declared + Also, plugin needs to be declared as extern "C" because MSVC + unlike other compilers, uses C++ mangling for variables not only + for functions. +*/ +#ifdef MYSQL_DYNAMIC_PLUGIN + #ifdef _MSC_VER + #define MYSQL_DLLEXPORT _declspec(dllexport) + #else + #define MYSQL_DLLEXPORT + #endif +#else + #define MYSQL_DLLEXPORT +#endif + +#ifdef __cplusplus + #define MYSQL_PLUGIN_EXPORT extern "C" MYSQL_DLLEXPORT +#else + #define MYSQL_PLUGIN_EXPORT MYSQL_DLLEXPORT +#endif + +#ifdef __cplusplus +class THD; +class Item; +#define MYSQL_THD THD* +#else +#define MYSQL_THD void* +#endif + +typedef char my_bool; +typedef void * MYSQL_PLUGIN; + +#include <mysql/services.h> + +#define MYSQL_XIDDATASIZE 128 +/** + struct st_mysql_xid is binary compatible with the XID structure as + in the X/Open CAE Specification, Distributed Transaction Processing: + The XA Specification, X/Open Company Ltd., 1991. + http://www.opengroup.org/bookstore/catalog/c193.htm + + @see XID in sql/handler.h +*/ +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[MYSQL_XIDDATASIZE]; /* Not \0-terminated */ +}; +typedef struct st_mysql_xid MYSQL_XID; + +/************************************************************************* + Plugin API. Common for all plugin types. +*/ + +/* MySQL plugin interface version */ +#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104 + +/* MariaDB plugin interface version */ +#define MARIA_PLUGIN_INTERFACE_VERSION 0x010f + +/* + The allowable types of plugins +*/ +#define MYSQL_UDF_PLUGIN 0 /* not implemented */ +#define MYSQL_STORAGE_ENGINE_PLUGIN 1 +#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ +#define MYSQL_DAEMON_PLUGIN 3 +#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 +#define MYSQL_AUDIT_PLUGIN 5 +#define MYSQL_REPLICATION_PLUGIN 6 +#define MYSQL_AUTHENTICATION_PLUGIN 7 +#define MYSQL_MAX_PLUGIN_TYPE_NUM 12 /* The number of plugin types */ + +/* MariaDB plugin types */ +#define MariaDB_PASSWORD_VALIDATION_PLUGIN 8 +#define MariaDB_ENCRYPTION_PLUGIN 9 +#define MariaDB_DATA_TYPE_PLUGIN 10 +#define MariaDB_FUNCTION_PLUGIN 11 + +/* We use the following strings to define licenses for plugins */ +#define PLUGIN_LICENSE_PROPRIETARY 0 +#define PLUGIN_LICENSE_GPL 1 +#define PLUGIN_LICENSE_BSD 2 + +#define PLUGIN_LICENSE_PROPRIETARY_STRING "PROPRIETARY" +#define PLUGIN_LICENSE_GPL_STRING "GPL" +#define PLUGIN_LICENSE_BSD_STRING "BSD" + +/* definitions of code maturity for plugins */ +#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0 +#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1 +#define MariaDB_PLUGIN_MATURITY_ALPHA 2 +#define MariaDB_PLUGIN_MATURITY_BETA 3 +#define MariaDB_PLUGIN_MATURITY_GAMMA 4 +#define MariaDB_PLUGIN_MATURITY_STABLE 5 + +/* + Macros for beginning and ending plugin declarations. Between + mysql_declare_plugin and mysql_declare_plugin_end there should + be a st_mysql_plugin struct for each plugin to be declared. +*/ + + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \ +int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \ +int PSIZE= sizeof(struct st_mysql_plugin); \ +struct st_mysql_plugin DECLS[]= { + +#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \ +MYSQL_PLUGIN_EXPORT int VERSION; \ +int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \ +MYSQL_PLUGIN_EXPORT int PSIZE; \ +int PSIZE= sizeof(struct st_maria_plugin); \ +MYSQL_PLUGIN_EXPORT struct st_maria_plugin DECLS[]; \ +struct st_maria_plugin DECLS[]= { +#else + +#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \ +MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_; \ +int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \ +MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_; \ +int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \ +MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]; \ +struct st_mysql_plugin _mysql_plugin_declarations_[]= { + +#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \ +MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_; \ +int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \ +MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_; \ +int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \ +MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]; \ +struct st_maria_plugin _maria_plugin_declarations_[]= { + +#endif + +#define mysql_declare_plugin(NAME) \ +__MYSQL_DECLARE_PLUGIN(NAME, \ + builtin_ ## NAME ## _plugin_interface_version, \ + builtin_ ## NAME ## _sizeof_struct_st_plugin, \ + builtin_ ## NAME ## _plugin) + +#define maria_declare_plugin(NAME) \ +MARIA_DECLARE_PLUGIN__(NAME, \ + builtin_maria_ ## NAME ## _plugin_interface_version, \ + builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \ + builtin_maria_ ## NAME ## _plugin) + +#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}} +#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}} + +/* + declarations for SHOW STATUS support in plugins +*/ +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; + +/* backward compatibility mapping. */ +#define SHOW_INT SHOW_UINT +#define SHOW_LONG SHOW_ULONG +#define SHOW_LONGLONG SHOW_ULONGLONG + +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; + +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; + +struct system_status_var; + +#define SHOW_VAR_FUNC_BUFF_SIZE (256 * sizeof(void*)) +typedef int (*mysql_show_var_func)(MYSQL_THD, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); + + +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; + + +/* + Constants for plugin flags. + */ + +#define PLUGIN_OPT_NO_INSTALL 1UL /* Not dynamically loadable */ +#define PLUGIN_OPT_NO_UNINSTALL 2UL /* Not dynamically unloadable */ + + +/* + declarations for server variables and command line options +*/ + + +#define PLUGIN_VAR_BOOL 0x0001 +#define PLUGIN_VAR_INT 0x0002 +#define PLUGIN_VAR_LONG 0x0003 +#define PLUGIN_VAR_LONGLONG 0x0004 +#define PLUGIN_VAR_STR 0x0005 +#define PLUGIN_VAR_ENUM 0x0006 +#define PLUGIN_VAR_SET 0x0007 +#define PLUGIN_VAR_DOUBLE 0x0008 +#define PLUGIN_VAR_UNSIGNED 0x0080 +#define PLUGIN_VAR_THDLOCAL 0x0100 /* Variable is per-connection */ +#define PLUGIN_VAR_READONLY 0x0200 /* Server variable is read only */ +#define PLUGIN_VAR_NOSYSVAR 0x0400 /* Not a server variable */ +#define PLUGIN_VAR_NOCMDOPT 0x0800 /* Not a command line option */ +#define PLUGIN_VAR_NOCMDARG 0x1000 /* No argument for cmd line */ +#define PLUGIN_VAR_RQCMDARG 0x0000 /* Argument required for cmd line */ +#define PLUGIN_VAR_OPCMDARG 0x2000 /* Argument optional for cmd line */ +#define PLUGIN_VAR_DEPRECATED 0x4000 /* Server variable is deprecated */ +#define PLUGIN_VAR_MEMALLOC 0x8000 /* String needs memory allocated */ + +struct st_mysql_sys_var; +struct st_mysql_value; + +/* + SYNOPSIS + (*mysql_var_check_func)() + thd thread handle + var dynamic variable being altered + save pointer to temporary storage + value user provided value + RETURN + 0 user provided value is OK and the update func may be called. + any other value indicates error. + + This function should parse the user provided value and store in the + provided temporary storage any data as required by the update func. + There is sufficient space in the temporary storage to store a double. + Note that the update func may not be called if any other error occurs + so any memory allocated should be thread-local so that it may be freed + automatically at the end of the statement. +*/ + +typedef int (*mysql_var_check_func)(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); + +/* + SYNOPSIS + (*mysql_var_update_func)() + thd thread handle + var dynamic variable being altered + var_ptr pointer to dynamic variable + save pointer to temporary storage + RETURN + NONE + + This function should use the validated value stored in the temporary store + and persist it in the provided pointer to the dynamic variable. + For example, strings may require memory to be allocated. +*/ +typedef void (*mysql_var_update_func)(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); + + +/* the following declarations are for internal use only */ + + +#define PLUGIN_VAR_MASK \ + (PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR | \ + PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_NOCMDARG | \ + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_RQCMDARG | \ + PLUGIN_VAR_DEPRECATED | PLUGIN_VAR_MEMALLOC) + +#define MYSQL_PLUGIN_VAR_HEADER \ + int flags; \ + const char *name; \ + const char *comment; \ + mysql_var_check_func check; \ + mysql_var_update_func update + +#define MYSQL_SYSVAR_NAME(name) mysql_sysvar_ ## name +#define MYSQL_SYSVAR(name) \ + ((struct st_mysql_sys_var *)&(MYSQL_SYSVAR_NAME(name))) + +/* + for global variables, the value pointer is the first + element after the header, the default value is the second. + for thread variables, the value offset is the first + element after the header, the default value is the second. +*/ + + +#define DECLARE_MYSQL_SYSVAR_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value; \ + const type def_val; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_CONST_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + const type *value; \ + const type def_val; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_SIMPLE(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value; type def_val; \ + type min_val; type max_val; \ + type blk_sz; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_TYPELIB(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value; type def_val; \ + TYPELIB *typelib; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_THDVAR_FUNC(type) \ + type *(*resolve)(MYSQL_THD thd, int offset) + +#define DECLARE_MYSQL_THDVAR_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + const type def_val; \ + DECLARE_THDVAR_FUNC(type); \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_THDVAR_SIMPLE(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + type def_val; type min_val; \ + type max_val; type blk_sz; \ + DECLARE_THDVAR_FUNC(type); \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_THDVAR_TYPELIB(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + const type def_val; \ + DECLARE_THDVAR_FUNC(type); \ + TYPELIB *typelib; \ +} MYSQL_SYSVAR_NAME(name) + + +/* + the following declarations are for use by plugin implementors +*/ + +#define MYSQL_SYSVAR_BOOL(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_BASIC(name, char) = { \ + PLUGIN_VAR_BOOL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_STR(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_CONST_STR(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_CONST_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_INT(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, int) = { \ + PLUGIN_VAR_INT | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_UINT(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_LONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, long) = { \ + PLUGIN_VAR_LONG | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ULONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_LONGLONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, long long) = { \ + PLUGIN_VAR_LONGLONG | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ULONGLONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned long long) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_UINT64_T(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, uint64_t) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#ifdef _WIN64 +#define MYSQL_SYSVAR_SIZE_T(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, size_t) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } +#else +#define MYSQL_SYSVAR_SIZE_T(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, size_t) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } +#endif + +#define MYSQL_SYSVAR_ENUM(name, varname, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_SYSVAR_TYPELIB(name, unsigned long) = { \ + PLUGIN_VAR_ENUM | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, typelib } + +#define MYSQL_SYSVAR_SET(name, varname, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_SYSVAR_TYPELIB(name, unsigned long long) = { \ + PLUGIN_VAR_SET | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, typelib } + +#define MYSQL_SYSVAR_DOUBLE(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, double) = { \ + PLUGIN_VAR_DOUBLE | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_THDVAR_BOOL(name, opt, comment, check, update, def) \ +DECLARE_MYSQL_THDVAR_BASIC(name, char) = { \ + PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL} + +#define MYSQL_THDVAR_STR(name, opt, comment, check, update, def) \ +DECLARE_MYSQL_THDVAR_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL} + +#define MYSQL_THDVAR_INT(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_UINT(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_LONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ULONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_LONGLONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, long long) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ULONGLONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned long long) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ENUM(name, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_THDVAR_TYPELIB(name, unsigned long) = { \ + PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL, typelib } + +#define MYSQL_THDVAR_SET(name, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_THDVAR_TYPELIB(name, unsigned long long) = { \ + PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL, typelib } + +#define MYSQL_THDVAR_DOUBLE(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, double) = { \ + PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +/* accessor macros */ + +#define SYSVAR(name) \ + (*(MYSQL_SYSVAR_NAME(name).value)) + +/* when thd == null, result points to global value */ +#define THDVAR(thd, name) \ + (*(MYSQL_SYSVAR_NAME(name).resolve(thd, MYSQL_SYSVAR_NAME(name).offset))) + + +/* + Plugin description structure. +*/ + +struct st_mysql_plugin +{ + int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + void *info; /* pointer to type-specific plugin descriptor */ + const char *name; /* plugin name */ + const char *author; /* plugin author (for I_S.PLUGINS) */ + const char *descr; /* general descriptive text (for I_S.PLUGINS) */ + int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ + int (*init)(void *); /* the function to invoke when plugin is loaded */ + int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ + unsigned int version; /* plugin version (for I_S.PLUGINS) */ + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; /* reserved for dependency checking */ + unsigned long flags; /* flags for plugin */ +}; + +/* + MariaDB extension for plugins declaration structure. + + It also copy current MySQL plugin fields to have more independency + in plugins extension +*/ + +struct st_maria_plugin +{ + int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + void *info; /* pointer to type-specific plugin descriptor */ + const char *name; /* plugin name */ + const char *author; /* plugin author (for SHOW PLUGINS) */ + const char *descr; /* general descriptive text (for SHOW PLUGINS ) */ + int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ + int (*init)(void *); /* the function to invoke when plugin is loaded */ + int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ + unsigned int version; /* plugin version (for SHOW PLUGINS) */ + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; /* plugin version string */ + unsigned int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */ +}; + +/************************************************************************* + API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) +*/ +#include "plugin_ftparser.h" + +/************************************************************************* + API for Storage Engine plugin. (MYSQL_DAEMON_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_DAEMON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_daemon +{ + int interface_version; +}; + + +/************************************************************************* + API for I_S plugin. (MYSQL_INFORMATION_SCHEMA_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_information_schema +{ + int interface_version; +}; + + +/************************************************************************* + API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_HANDLERTON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + The real API is in the sql/handler.h + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_storage_engine +{ + int interface_version; +}; + +struct handlerton; + + +/* + API for Replication plugin. (MYSQL_REPLICATION_PLUGIN) +*/ + #define MYSQL_REPLICATION_INTERFACE_VERSION 0x0200 + + /** + Replication plugin descriptor + */ + struct Mysql_replication { + int interface_version; + }; + +/************************************************************************* + st_mysql_value struct for reading values from mysqld. + Used by server variables framework to parse user-provided values. + Will be used for arguments when implementing UDFs. + + Note that val_str() returns a string in temporary memory + that will be freed at the end of statement. Copy the string + if you need it to persist. +*/ + +#define MYSQL_VALUE_TYPE_STRING 0 +#define MYSQL_VALUE_TYPE_REAL 1 +#define MYSQL_VALUE_TYPE_INT 2 + +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; + + +/************************************************************************* + Miscellaneous functions for plugin implementors +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int thd_in_lock_tables(const MYSQL_THD thd); +int thd_tablespace_op(const MYSQL_THD thd); +long long thd_test_options(const MYSQL_THD thd, long long test_options); +int thd_sql_command(const MYSQL_THD thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const MYSQL_THD thd); +void thd_storage_lock_wait(MYSQL_THD thd, long long value); +int thd_tx_isolation(const MYSQL_THD thd); +int thd_tx_is_read_only(const MYSQL_THD thd); +/** + Create a temporary file. + + @details + The temporary file is created in a location specified by the mysql + server configuration (--tmpdir option). The caller does not need to + delete the file, it will be deleted automatically. + + @param prefix prefix for temporary file name + @retval -1 error + @retval >= 0 a file handle that can be passed to dup or my_close +*/ +int mysql_tmpfile(const char *prefix); + +/** + Return the thread id of a user thread + + @param thd user thread connection handle + @return thread id +*/ +unsigned long thd_get_thread_id(const MYSQL_THD thd); + +/** + Get the XID for this connection's transaction + + @param thd user thread connection handle + @param xid location where identifier is stored +*/ +void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid); + +/** + Invalidate the query cache for a given table. + + @param thd user thread connection handle + @param key databasename\\0tablename\\0 + @param key_length length of key in bytes, including the NUL bytes + @param using_trx flag: TRUE if using transactions, FALSE otherwise +*/ +void mysql_query_cache_invalidate4(MYSQL_THD thd, + const char *key, unsigned int key_length, + int using_trx); + + +/** + Provide a handler data getter to simplify coding +*/ +void *thd_get_ha_data(const MYSQL_THD thd, const struct handlerton *hton); + + +/** + Provide a handler data setter to simplify coding + + @details + Set ha_data pointer (storage engine per-connection information). + + To avoid unclean deactivation (uninstall) of storage engine plugin + in the middle of transaction, additional storage engine plugin + lock is acquired. + + If ha_data is not null and storage engine plugin was not locked + by thd_set_ha_data() in this connection before, storage engine + plugin gets locked. + + If ha_data is null and storage engine plugin was locked by + thd_set_ha_data() in this connection before, storage engine + plugin lock gets released. + + If handlerton::close_connection() didn't reset ha_data, server does + it immediately after calling handlerton::close_connection(). +*/ +void thd_set_ha_data(MYSQL_THD thd, const struct handlerton *hton, + const void *ha_data); + + +/** + Signal that the first part of handler commit is finished, and that the + committed transaction is now visible and has fixed commit ordering with + respect to other transactions. The commit need _not_ be durable yet, and + typically will not be when this call makes sense. + + This call is optional, if the storage engine does not call it the upper + layer will after the handler commit() method is done. However, the storage + engine may choose to call it itself to increase the possibility for group + commit. + + In-order parallel replication uses this to apply different transaction in + parallel, but delay the commits of later transactions until earlier + transactions have committed first, thus achieving increased performance on + multi-core systems while still preserving full transaction consistency. + + The storage engine can call this from within the commit() method, typically + after the commit record has been written to the transaction log, but before + the log has been fsync()'ed. This will allow the next replicated transaction + to proceed to commit before the first one has done fsync() or similar. Thus, + it becomes possible for multiple sequential replicated transactions to share + a single fsync() inside the engine in group commit. + + Note that this method should _not_ be called from within the commit_ordered() + method, or any other place in the storage engine. When commit_ordered() is + used (typically when binlog is enabled), the transaction coordinator takes + care of this and makes group commit in the storage engine possible without + any other action needed on the part of the storage engine. This function + thd_wakeup_subsequent_commits() is only needed when no transaction + coordinator is used, meaning a single storage engine and no binary log. +*/ +void thd_wakeup_subsequent_commits(MYSQL_THD thd, int wakeup_error); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_audit.h b/include/mysql/plugin_audit.h new file mode 100644 index 00000000..bfa6621b --- /dev/null +++ b/include/mysql/plugin_audit.h @@ -0,0 +1,181 @@ +/* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_audit_h +#define _my_audit_h + +/************************************************************************* + API for Audit plugin. (MYSQL_AUDIT_PLUGIN) +*/ + +#include "plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MYSQL_AUDIT_CLASS_MASK_SIZE 1 + +#define MYSQL_AUDIT_INTERFACE_VERSION 0x0302 + + +/************************************************************************* + AUDIT CLASS : GENERAL + + LOG events occurs before emitting to the general query log. + ERROR events occur before transmitting errors to the user. + RESULT events occur after transmitting a resultset to the user. + STATUS events occur after transmitting a resultset or errors + to the user. +*/ + +#define MYSQL_AUDIT_GENERAL_CLASS 0 +#define MYSQL_AUDIT_GENERAL_CLASSMASK (1 << MYSQL_AUDIT_GENERAL_CLASS) +#define MYSQL_AUDIT_GENERAL_LOG 0 +#define MYSQL_AUDIT_GENERAL_ERROR 1 +#define MYSQL_AUDIT_GENERAL_RESULT 2 +#define MYSQL_AUDIT_GENERAL_STATUS 3 +#define MYSQL_AUDIT_GENERAL_WARNING 4 + +struct mysql_event_general +{ + unsigned int event_subclass; + int general_error_code; + unsigned long general_thread_id; + const char *general_user; + unsigned int general_user_length; + const char *general_command; + unsigned int general_command_length; + const char *general_query; + unsigned int general_query_length; + const struct charset_info_st *general_charset; + unsigned long long general_time; + unsigned long long general_rows; + /* Added in version 0x302 */ + unsigned long long query_id; + MYSQL_CONST_LEX_STRING database; +}; + + +/* + AUDIT CLASS : CONNECTION + + CONNECT occurs after authentication phase is completed. + DISCONNECT occurs after connection is terminated. + CHANGE_USER occurs after COM_CHANGE_USER RPC is completed. +*/ + +#define MYSQL_AUDIT_CONNECTION_CLASS 1 +#define MYSQL_AUDIT_CONNECTION_CLASSMASK (1 << MYSQL_AUDIT_CONNECTION_CLASS) +#define MYSQL_AUDIT_CONNECTION_CONNECT 0 +#define MYSQL_AUDIT_CONNECTION_DISCONNECT 1 +#define MYSQL_AUDIT_CONNECTION_CHANGE_USER 2 + +struct mysql_event_connection +{ + unsigned int event_subclass; + int status; + unsigned long thread_id; + const char *user; + unsigned int user_length; + const char *priv_user; + unsigned int priv_user_length; + const char *external_user; + unsigned int external_user_length; + const char *proxy_user; + unsigned int proxy_user_length; + const char *host; + unsigned int host_length; + const char *ip; + unsigned int ip_length; + MYSQL_CONST_LEX_STRING database; +}; + +/* + AUDIT CLASS : TABLE + + LOCK occurs when a connection "locks" (this does not necessarily mean a table + lock and also happens for row-locking engines) the table at the beginning of + a statement. This event is generated at the beginning of every statement for + every affected table, unless there's a LOCK TABLES statement in effect (in + which case it is generated once for LOCK TABLES and then is suppressed until + the tables are unlocked). + + CREATE/DROP/RENAME occur when a table is created, dropped, or renamed. +*/ + +#define MYSQL_AUDIT_TABLE_CLASS 15 +#define MYSQL_AUDIT_TABLE_CLASSMASK (1 << MYSQL_AUDIT_TABLE_CLASS) +#define MYSQL_AUDIT_TABLE_LOCK 0 +#define MYSQL_AUDIT_TABLE_CREATE 1 +#define MYSQL_AUDIT_TABLE_DROP 2 +#define MYSQL_AUDIT_TABLE_RENAME 3 +#define MYSQL_AUDIT_TABLE_ALTER 4 + +struct mysql_event_table +{ + unsigned int event_subclass; + unsigned long thread_id; + const char *user; + const char *priv_user; + const char *priv_host; + const char *external_user; + const char *proxy_user; + const char *host; + const char *ip; + MYSQL_CONST_LEX_STRING database; + MYSQL_CONST_LEX_STRING table; + /* for MYSQL_AUDIT_TABLE_RENAME */ + MYSQL_CONST_LEX_STRING new_database; + MYSQL_CONST_LEX_STRING new_table; + /* for MYSQL_AUDIT_TABLE_LOCK, true if read-only, false if read/write */ + int read_only; + /* Added in version 0x302 */ + unsigned long long query_id; +}; + +/************************************************************************* + Here we define the descriptor structure, that is referred from + st_mysql_plugin. + + release_thd() event occurs when the event class consumer is to be + disassociated from the specified THD. This would typically occur + before some operation which may require sleeping - such as when + waiting for the next query from the client. + + event_notify() is invoked whenever an event occurs which is of any + class for which the plugin has interest. The second argument + indicates the specific event class and the third argument is data + as required for that class. + + class_mask is an array of bits used to indicate what event classes + that this plugin wants to receive. +*/ + +struct st_mysql_audit +{ + int interface_version; + void (*release_thd)(MYSQL_THD); + void (*event_notify)(MYSQL_THD, unsigned int, const void *); + unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp new file mode 100644 index 00000000..a01e4ff8 --- /dev/null +++ b/include/mysql/plugin_audit.h.pp @@ -0,0 +1,725 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +struct mysql_event_general +{ + unsigned int event_subclass; + int general_error_code; + unsigned long general_thread_id; + const char *general_user; + unsigned int general_user_length; + const char *general_command; + unsigned int general_command_length; + const char *general_query; + unsigned int general_query_length; + const struct charset_info_st *general_charset; + unsigned long long general_time; + unsigned long long general_rows; + unsigned long long query_id; + MYSQL_CONST_LEX_STRING database; +}; +struct mysql_event_connection +{ + unsigned int event_subclass; + int status; + unsigned long thread_id; + const char *user; + unsigned int user_length; + const char *priv_user; + unsigned int priv_user_length; + const char *external_user; + unsigned int external_user_length; + const char *proxy_user; + unsigned int proxy_user_length; + const char *host; + unsigned int host_length; + const char *ip; + unsigned int ip_length; + MYSQL_CONST_LEX_STRING database; +}; +struct mysql_event_table +{ + unsigned int event_subclass; + unsigned long thread_id; + const char *user; + const char *priv_user; + const char *priv_host; + const char *external_user; + const char *proxy_user; + const char *host; + const char *ip; + MYSQL_CONST_LEX_STRING database; + MYSQL_CONST_LEX_STRING table; + MYSQL_CONST_LEX_STRING new_database; + MYSQL_CONST_LEX_STRING new_table; + int read_only; + unsigned long long query_id; +}; +struct st_mysql_audit +{ + int interface_version; + void (*release_thd)(THD*); + void (*event_notify)(THD*, unsigned int, const void *); + unsigned long class_mask[1]; +}; +} diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h new file mode 100644 index 00000000..3827db33 --- /dev/null +++ b/include/mysql/plugin_auth.h @@ -0,0 +1,183 @@ +#ifndef MYSQL_PLUGIN_AUTH_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, Oracle and/or its affiliates. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Authentication Plugin API. + + This file defines the API for server authentication plugins. +*/ + +#define MYSQL_PLUGIN_AUTH_INCLUDED + +#include <mysql/plugin.h> + +#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0202 + +#include <mysql/plugin_auth_common.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* defines for MYSQL_SERVER_AUTH_INFO.password_used */ + +#define PASSWORD_USED_NO 0 +#define PASSWORD_USED_YES 1 +#define PASSWORD_USED_NO_MENTION 2 + + +/** + Provides server plugin access to authentication information +*/ +typedef struct st_mysql_server_auth_info +{ + /** + User name as sent by the client and shown in USER(). + NULL if the client packet with the user name was not received yet. + */ + const char *user_name; + + /** + Length of user_name + */ + unsigned int user_name_length; + + /** + A corresponding column value from the mysql.user table for the + matching account name or the preprocessed value, if preprocess_hash + method is not NULL + */ + const char *auth_string; + + /** + Length of auth_string + */ + unsigned long auth_string_length; + + /** + Matching account name as found in the mysql.user table. + A plugin can override it with another name that will be + used by MySQL for authorization, and shown in CURRENT_USER() + */ + char authenticated_as[MYSQL_USERNAME_LENGTH+1]; + + + /** + The unique user name that was used by the plugin to authenticate. + Not used by the server. + Available through the @@EXTERNAL_USER variable. + */ + char external_user[MYSQL_USERNAME_LENGTH+1]; + + /** + This only affects the "Authentication failed. Password used: %s" + error message. has the following values : + 0 : %s will be NO. + 1 : %s will be YES. + 2 : there will be no %s. + Set it as appropriate or ignore at will. + */ + int password_used; + + /** + Set to the name of the connected client host, if it can be resolved, + or to its IP address otherwise. + */ + const char *host_or_ip; + + /** + Length of host_or_ip + */ + unsigned int host_or_ip_length; + + /** + Current THD pointer (to use with various services) + */ + MYSQL_THD thd; + +} MYSQL_SERVER_AUTH_INFO; + +/** + Server authentication plugin descriptor +*/ +struct st_mysql_auth +{ + int interface_version; /**< version plugin uses */ + /** + A plugin that a client must use for authentication with this server + plugin. Can be NULL to mean "any plugin". + */ + const char *client_auth_plugin; + /** + Function provided by the plugin which should perform authentication (using + the vio functions if necessary) and return 0 if successful. The plugin can + also fill the info.authenticated_as field if a different username should be + used for authorization. + */ + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); + /** + Create a password hash (or digest) out of a plain-text password + + Used in SET PASSWORD, GRANT, and CREATE USER to convert user specified + plain-text password into a value that will be stored in mysql.user table. + + @see preprocess_hash + + @param password plain-text password + @param password_length plain-text password length + @param hash the digest will be stored there + @param hash_length in: hash buffer size + out: the actual length of the hash + + @return 0 for ok, 1 for error + + Can be NULL, in this case one will not be able to use SET PASSWORD or + PASSWORD('...') in GRANT, CREATE USER, ALTER USER. + */ + int (*hash_password)(const char *password, size_t password_length, + char *hash, size_t *hash_length); + + /** + Prepare the password hash for authentication. + + Password hash is stored in the authentication_string column of the + mysql.user table in a text form. If a plugin needs to preprocess the + value somehow before the authentication (e.g. convert from hex or base64 + to binary), it can do it in this method. This way the conversion + will happen only once, not for every authentication attempt. + + The value written to the out buffer will be cached and later made + available to the authenticate_user() method in the + MYSQL_SERVER_AUTH_INFO::auth_string[] buffer. + + @return 0 for ok, 1 for error + + Can be NULL, in this case the mysql.user.authentication_string value will + be given to the authenticate_user() method as is, unconverted. + */ + int (*preprocess_hash)(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length); +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp new file mode 100644 index 00000000..1844f7b7 --- /dev/null +++ b/include/mysql/plugin_auth.h.pp @@ -0,0 +1,702 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; +} MYSQL_PLUGIN_VIO_INFO; +typedef struct st_plugin_vio +{ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); +} MYSQL_PLUGIN_VIO; +extern "C" { +typedef struct st_mysql_server_auth_info +{ + const char *user_name; + unsigned int user_name_length; + const char *auth_string; + unsigned long auth_string_length; + char authenticated_as[512 +1]; + char external_user[512 +1]; + int password_used; + const char *host_or_ip; + unsigned int host_or_ip_length; + THD* thd; +} MYSQL_SERVER_AUTH_INFO; +struct st_mysql_auth +{ + int interface_version; + const char *client_auth_plugin; + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); + int (*hash_password)(const char *password, size_t password_length, + char *hash, size_t *hash_length); + int (*preprocess_hash)(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length); +}; +} diff --git a/include/mysql/plugin_auth_common.h b/include/mysql/plugin_auth_common.h new file mode 100644 index 00000000..8edd7128 --- /dev/null +++ b/include/mysql/plugin_auth_common.h @@ -0,0 +1,131 @@ +#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, Oracle and/or its affiliates. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef _WIN32 +#include <windows.h> +#endif + +/** + @file + + This file defines constants and data structures that are the same for + both client- and server-side authentication plugins. +*/ +#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED + +/** the max allowed length for a user name */ +#define MYSQL_USERNAME_LENGTH 512 + +/** + return values of the plugin authenticate_user() method. +*/ + + /** + Authentication failed, plugin internal error. + An error occurred in the authentication plugin itself. + These errors are reported in table performance_schema.host_cache, + column COUNT_AUTH_PLUGIN_ERRORS. +*/ +#define CR_AUTH_PLUGIN_ERROR 3 +/** + Authentication failed, client server handshake. + An error occurred during the client server handshake. + These errors are reported in table performance_schema.host_cache, + column COUNT_HANDSHAKE_ERRORS. +*/ +#define CR_AUTH_HANDSHAKE 2 +/** + Authentication failed, user credentials. + For example, wrong passwords. + These errors are reported in table performance_schema.host_cache, + column COUNT_AUTHENTICATION_ERRORS. +*/ +#define CR_AUTH_USER_CREDENTIALS 1 +/** + Authentication failed. Additionally, all other CR_xxx values + (libmysql error code) can be used too. + + The client plugin may set the error code and the error message directly + in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error + code was returned, an error message in the MYSQL structure will be + overwritten. If CR_ERROR is returned without setting the error in MYSQL, + CR_UNKNOWN_ERROR will be user. +*/ +#define CR_ERROR 0 +/** + Authentication (client part) was successful. It does not mean that the + authentication as a whole was successful, usually it only means + that the client was able to send the user name and the password to the + server. If CR_OK is returned, the libmysql reads the next packet expecting + it to be one of OK, ERROR, or CHANGE_PLUGIN packets. +*/ +#define CR_OK -1 +/** + Authentication was successful. + It means that the client has done its part successfully and also that + a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN). + In this case, libmysql will not read a packet from the server, + but it will use the data at mysql->net.read_pos. + + A plugin may return this value if the number of roundtrips in the + authentication protocol is not known in advance, and the client plugin + needs to read one packet more to determine if the authentication is finished + or not. +*/ +#define CR_OK_HANDSHAKE_COMPLETE -2 + +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; /**< it's set, if the protocol is SOCKET or TCP */ +#ifdef _WIN32 + HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */ +#endif +} MYSQL_PLUGIN_VIO_INFO; + +/** + Provides plugin access to communication channel +*/ +typedef struct st_plugin_vio +{ + /** + Plugin provides a pointer reference and this function sets it to the + contents of any incoming packet. Returns the packet length, or -1 if + the plugin should terminate. + */ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + + /** + Plugin provides a buffer with data and the length and this + function sends it as a packet. Returns 0 on success, 1 on failure. + */ + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + + /** + Fills in a st_plugin_vio_info structure, providing the information + about the connection. + */ + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); + +} MYSQL_PLUGIN_VIO; + +#endif + diff --git a/include/mysql/plugin_data_type.h b/include/mysql/plugin_data_type.h new file mode 100644 index 00000000..77aa9fb2 --- /dev/null +++ b/include/mysql/plugin_data_type.h @@ -0,0 +1,49 @@ +#ifndef MARIADB_PLUGIN_DATA_TYPE_INCLUDED +#define MARIADB_PLUGIN_DATA_TYPE_INCLUDED +/* Copyright (C) 2019, Alexander Barkov and MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Data Type Plugin API. + + This file defines the API for server plugins that manage data types. +*/ + +#ifdef __cplusplus + +#include <mysql/plugin.h> + +/* + API for data type plugins. (MariaDB_DATA_TYPE_PLUGIN) +*/ +#define MariaDB_DATA_TYPE_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + + +struct st_mariadb_data_type +{ + int interface_version; + class Type_handler *type_handler; +}; + + +/** + Data type plugin descriptor +*/ + +#endif /* __cplusplus */ + +#endif /* MARIADB_PLUGIN_DATA_TYPE_INCLUDED */ diff --git a/include/mysql/plugin_data_type.h.pp b/include/mysql/plugin_data_type.h.pp new file mode 100644 index 00000000..80b5a863 --- /dev/null +++ b/include/mysql/plugin_data_type.h.pp @@ -0,0 +1,667 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +struct st_mariadb_data_type +{ + int interface_version; + class Type_handler *type_handler; +}; diff --git a/include/mysql/plugin_encryption.h b/include/mysql/plugin_encryption.h new file mode 100644 index 00000000..3c574aa4 --- /dev/null +++ b/include/mysql/plugin_encryption.h @@ -0,0 +1,126 @@ +#ifndef MYSQL_PLUGIN_ENCRYPTION_INCLUDED +/* Copyright (C) 2014, 2015 Sergei Golubchik and MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Encryption Plugin API. + + This file defines the API for server plugins that manage encryption + keys for MariaDB on-disk data encryption. +*/ + +#define MYSQL_PLUGIN_ENCRYPTION_INCLUDED + +#include <mysql/plugin.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MariaDB_ENCRYPTION_INTERFACE_VERSION 0x0300 + +/** + Encryption plugin descriptor +*/ +struct st_mariadb_encryption +{ + int interface_version; /**< version plugin uses */ + + /*********** KEY MANAGEMENT ********************************************/ + + /** + function returning latest key version for a given key id + + @return a version or ENCRYPTION_KEY_VERSION_INVALID to indicate an error. + */ + unsigned int (*get_latest_key_version)(unsigned int key_id); + + /** + function returning a key for a key version + + @param version the requested key version + @param key the key will be stored there. Can be NULL - + in which case no key will be returned + @param key_length in: key buffer size + out: the actual length of the key + + This method can be used to query the key length - the required + buffer size - by passing key==NULL. + + If the buffer size is less than the key length the content of the + key buffer is undefined (the plugin is free to partially fill it with + the key data or leave it untouched). + + @return 0 on success, or + ENCRYPTION_KEY_VERSION_INVALID, ENCRYPTION_KEY_BUFFER_TOO_SMALL + or any other non-zero number for errors + */ + unsigned int (*get_key)(unsigned int key_id, unsigned int version, + unsigned char *key, unsigned int *key_length); + + /*********** ENCRYPTION ************************************************/ + /* + the caller uses encryption as follows: + 1. create the encryption context object of the crypt_ctx_size() bytes. + 2. initialize it with crypt_ctx_init(). + 3. repeat crypt_ctx_update() until there are no more data to encrypt. + 4. write the remaining output bytes and destroy the context object + with crypt_ctx_finish(). + */ + + /** + returns the size of the encryption context object in bytes + */ + unsigned int (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version); + /** + initializes the encryption context object. + */ + int (*crypt_ctx_init)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + /** + processes (encrypts or decrypts) a chunk of data + + writes the output to th dst buffer. note that it might write + more bytes that were in the input. or less. or none at all. + */ + int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + /** + writes the remaining output bytes and destroys the encryption context + + crypt_ctx_update might've cached part of the output in the context, + this method will flush these data out. + */ + int (*crypt_ctx_finish)(void *ctx, unsigned char* dst, unsigned int* dlen); + /** + returns the length of the encrypted data + + it returns the exact length, given only the source length. + which means, this API only supports encryption algorithms where + the length of the encrypted data only depends on the length of the + input (a.k.a. compression is not supported). + */ + unsigned int (*encrypted_length)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp new file mode 100644 index 00000000..ac5798b1 --- /dev/null +++ b/include/mysql/plugin_encryption.h.pp @@ -0,0 +1,680 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +struct st_mariadb_encryption +{ + int interface_version; + unsigned int (*get_latest_key_version)(unsigned int key_id); + unsigned int (*get_key)(unsigned int key_id, unsigned int version, + unsigned char *key, unsigned int *key_length); + unsigned int (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version); + int (*crypt_ctx_init)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*crypt_ctx_finish)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encrypted_length)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +} diff --git a/include/mysql/plugin_ftparser.h b/include/mysql/plugin_ftparser.h new file mode 100644 index 00000000..511b34bb --- /dev/null +++ b/include/mysql/plugin_ftparser.h @@ -0,0 +1,222 @@ +/* Copyright (c) 2005 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_plugin_ftparser_h +#define _my_plugin_ftparser_h +#include "plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************* + API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) +*/ + +#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100 + +/* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */ +enum enum_ftparser_mode +{ +/* + Fast and simple mode. This mode is used for indexing, and natural + language queries. + + The parser is expected to return only those words that go into the + index. Stopwords or too short/long words should not be returned. The + 'boolean_info' argument of mysql_add_word() does not have to be set. +*/ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + +/* + Parse with stopwords mode. This mode is used in boolean searches for + "phrase matching." + + The parser is not allowed to ignore words in this mode. Every word + should be returned, including stopwords and words that are too short + or long. The 'boolean_info' argument of mysql_add_word() does not + have to be set. +*/ + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + +/* + Parse in boolean mode. This mode is used to parse a boolean query string. + + The parser should provide a valid MYSQL_FTPARSER_BOOLEAN_INFO + structure in the 'boolean_info' argument to mysql_add_word(). + Usually that means that the parser should recognize boolean operators + in the parsing stream and set appropriate fields in + MYSQL_FTPARSER_BOOLEAN_INFO structure accordingly. As for + MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored. + Instead, use FT_TOKEN_STOPWORD for the token type of such a word. +*/ + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; + +/* + Token types for boolean mode searching (used for the type member of + MYSQL_FTPARSER_BOOLEAN_INFO struct) + + FT_TOKEN_EOF: End of data. + FT_TOKEN_WORD: Regular word. + FT_TOKEN_LEFT_PAREN: Left parenthesis (start of group/sub-expression). + FT_TOKEN_RIGHT_PAREN: Right parenthesis (end of group/sub-expression). + FT_TOKEN_STOPWORD: Stopword. +*/ + +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; + +/* + This structure is used in boolean search mode only. It conveys + boolean-mode metadata to the MySQL search engine for every word in + the search query. A valid instance of this structure must be filled + in by the plugin parser and passed as an argument in the call to + mysql_add_word (the callback function in the MYSQL_FTPARSER_PARAM + structure) when a query is parsed in boolean mode. + + type: The token type. Should be one of the enum_ft_token_type values. + + yesno: Whether the word must be present for a match to occur: + >0 Must be present + <0 Must not be present + 0 Neither; the word is optional but its presence increases the relevance + With the default settings of the ft_boolean_syntax system variable, + >0 corresponds to the '+' operator, <0 corresponds to the '-' operator, + and 0 means neither operator was used. + + weight_adjust: A weighting factor that determines how much a match + for the word counts. Positive values increase, negative - decrease the + relative word's importance in the query. + + wasign: The sign of the word's weight in the query. If it's non-negative + the match for the word will increase document relevance, if it's + negative - decrease (the word becomes a "noise word", the less of it the + better). + + trunc: Corresponds to the '*' operator in the default setting of the + ft_boolean_syntax system variable. +*/ + +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + /* These are parser state and must be removed. */ + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; + +/* + The following flag means that buffer with a string (document, word) + may be overwritten by the caller before the end of the parsing (that is + before st_mysql_ftparser::deinit() call). If one needs the string + to survive between two successive calls of the parsing function, she + needs to save a copy of it. The flag may be set by MySQL before calling + st_mysql_ftparser::parse(), or it may be set by a plugin before calling + st_mysql_ftparser_param::mysql_parse() or + st_mysql_ftparser_param::mysql_add_word(). +*/ +#define MYSQL_FTFLAGS_NEED_COPY 1 + +/* + An argument of the full-text parser plugin. This structure is + filled in by MySQL server and passed to the parsing function of the + plugin as an in/out parameter. + + mysql_parse: A pointer to the built-in parser implementation of the + server. It's set by the server and can be used by the parser plugin + to invoke the MySQL default parser. If plugin's role is to extract + textual data from .doc, .pdf or .xml content, it might extract + plaintext from the content, and then pass the text to the default + MySQL parser to be parsed. + + mysql_add_word: A server callback to add a new word. When parsing + a document, the server sets this to point at a function that adds + the word to MySQL full-text index. When parsing a search query, + this function will add the new word to the list of words to search + for. The boolean_info argument can be NULL for all cases except + when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. A plugin can replace this + callback to post-process every parsed word before passing it to the original + mysql_add_word function. + + ftparser_state: A generic pointer. The plugin can set it to point + to information to be used internally for its own purposes. + + mysql_ftparam: This is set by the server. It is used by MySQL functions + called via mysql_parse() and mysql_add_word() callback. The plugin + should not modify it. + + cs: Information about the character set of the document or query string. + + doc: A pointer to the document or query string to be parsed. + + length: Length of the document or query string, in bytes. + + flags: See MYSQL_FTFLAGS_* constants above. + + mode: The parsing mode. With boolean operators, with stopwords, or + nothing. See enum_ftparser_mode above. +*/ + +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; + +/* + Full-text parser descriptor. + + interface_version is, e.g., MYSQL_FTPARSER_INTERFACE_VERSION. + The parsing, initialization, and deinitialization functions are + invoked per SQL statement for which the parser is used. +*/ + +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp new file mode 100644 index 00000000..919c9aae --- /dev/null +++ b/include/mysql/plugin_ftparser.h.pp @@ -0,0 +1,662 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} diff --git a/include/mysql/plugin_function.h b/include/mysql/plugin_function.h new file mode 100644 index 00000000..117acd43 --- /dev/null +++ b/include/mysql/plugin_function.h @@ -0,0 +1,54 @@ +#ifndef MARIADB_PLUGIN_FUNCTION_INCLUDED +#define MARIADB_PLUGIN_FUNCTION_INCLUDED +/* Copyright (C) 2019, Alexander Barkov and MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Function Plugin API. + + This file defines the API for server plugins that manage functions. +*/ + +#ifdef __cplusplus + +#include <mysql/plugin.h> + +/* + API for function plugins. (MariaDB_FUNCTION_PLUGIN) +*/ +#define MariaDB_FUNCTION_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + + +class Plugin_function +{ + int m_interface_version; + Create_func *m_builder; +public: + Plugin_function(Create_func *builder) + :m_interface_version(MariaDB_FUNCTION_INTERFACE_VERSION), + m_builder(builder) + { } + Create_func *create_func() + { + return m_builder; + } +}; + + +#endif /* __cplusplus */ + +#endif /* MARIADB_PLUGIN_FUNCTION_INCLUDED */ diff --git a/include/mysql/plugin_function.h.pp b/include/mysql/plugin_function.h.pp new file mode 100644 index 00000000..f5b22dbd --- /dev/null +++ b/include/mysql/plugin_function.h.pp @@ -0,0 +1,676 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +class Plugin_function +{ + int m_interface_version; + Create_func *m_builder; +public: + Plugin_function(Create_func *builder) + :m_interface_version((MYSQL_VERSION_ID << 8)), + m_builder(builder) + { } + Create_func *create_func() + { + return m_builder; + } +}; diff --git a/include/mysql/plugin_password_validation.h b/include/mysql/plugin_password_validation.h new file mode 100644 index 00000000..94d6c639 --- /dev/null +++ b/include/mysql/plugin_password_validation.h @@ -0,0 +1,55 @@ +#ifndef MYSQL_PLUGIN_PASSWORD_VALIDATION_INCLUDED +/* Copyright (C) 2014 Sergei Golubchik and MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Password Validation Plugin API. + + This file defines the API for server password validation plugins. +*/ + +#define MYSQL_PLUGIN_PASSWORD_VALIDATION_INCLUDED + +#include <mysql/plugin.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION 0x0101 + +/** + Password validation plugin descriptor +*/ +struct st_mariadb_password_validation +{ + int interface_version; /**< version plugin uses */ + /** + Function provided by the plugin which should perform password validation + and return 0 if the password has passed the validation. + */ + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password, + const MYSQL_CONST_LEX_STRING *hostname); +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp new file mode 100644 index 00000000..115cbf26 --- /dev/null +++ b/include/mysql/plugin_password_validation.h.pp @@ -0,0 +1,671 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +struct st_mariadb_password_validation +{ + int interface_version; + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password, + const MYSQL_CONST_LEX_STRING *hostname); +}; +} diff --git a/include/mysql/psi/mysql_file.h b/include/mysql/psi/mysql_file.h new file mode 100644 index 00000000..fd3b29cc --- /dev/null +++ b/include/mysql/psi/mysql_file.h @@ -0,0 +1,1454 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_FILE_H +#define MYSQL_FILE_H + +/* For strlen() */ +#include <string.h> +/* For MY_STAT */ +#include <my_dir.h> +/* For my_chsize */ +#include <my_sys.h> + +/** + @file mysql/psi/mysql_file.h + Instrumentation helpers for mysys file io. + This header file provides the necessary declarations + to use the mysys file API with the performance schema instrumentation. + In some compilers (SunStudio), 'static inline' functions, when declared + but not used, are not optimized away (because they are unused) by default, + so that including a static inline function from a header file does + create unwanted dependencies, causing unresolved symbols at link time. + Other compilers, like gcc, optimize these dependencies by default. + + Since the instrumented APIs declared here are wrapper on top + of mysys file io APIs, including mysql/psi/mysql_file.h assumes that + the dependency on my_sys already exists. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_FILE_CALL +#define PSI_FILE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup File_instrumentation File Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_file_register(P1, P2, P3) + File registration. +*/ +#define mysql_file_register(P1, P2, P3) \ + inline_mysql_file_register(P1, P2, P3) + +/** + @def mysql_file_fgets(P1, P2, F) + Instrumented fgets. + @c mysql_file_fgets is a replacement for @c fgets. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fgets(P1, P2, F) \ + inline_mysql_file_fgets(__FILE__, __LINE__, P1, P2, F) +#else + #define mysql_file_fgets(P1, P2, F) \ + inline_mysql_file_fgets(P1, P2, F) +#endif + +/** + @def mysql_file_fgetc(F) + Instrumented fgetc. + @c mysql_file_fgetc is a replacement for @c fgetc. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fgetc(F) inline_mysql_file_fgetc(__FILE__, __LINE__, F) +#else + #define mysql_file_fgetc(F) inline_mysql_file_fgetc(F) +#endif + +/** + @def mysql_file_fputs(P1, F) + Instrumented fputs. + @c mysql_file_fputs is a replacement for @c fputs. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fputs(P1, F) \ + inline_mysql_file_fputs(__FILE__, __LINE__, P1, F) +#else + #define mysql_file_fputs(P1, F)\ + inline_mysql_file_fputs(P1, F) +#endif + +/** + @def mysql_file_fputc(P1, F) + Instrumented fputc. + @c mysql_file_fputc is a replacement for @c fputc. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fputc(P1, F) \ + inline_mysql_file_fputc(__FILE__, __LINE__, P1, F) +#else + #define mysql_file_fputc(P1, F) \ + inline_mysql_file_fputc(P1, F) +#endif + +/** + @def mysql_file_fprintf + Instrumented fprintf. + @c mysql_file_fprintf is a replacement for @c fprintf. +*/ +#define mysql_file_fprintf inline_mysql_file_fprintf + +/** + @def mysql_file_vfprintf(F, P1, P2) + Instrumented vfprintf. + @c mysql_file_vfprintf is a replacement for @c vfprintf. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_vfprintf(F, P1, P2) \ + inline_mysql_file_vfprintf(__FILE__, __LINE__, F, P1, P2) +#else + #define mysql_file_vfprintf(F, P1, P2) \ + inline_mysql_file_vfprintf(F, P1, P2) +#endif + +/** + @def mysql_file_fflush(F, P1, P2) + Instrumented fflush. + @c mysql_file_fflush is a replacement for @c fflush. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fflush(F) \ + inline_mysql_file_fflush(__FILE__, __LINE__, F) +#else + #define mysql_file_fflush(F) \ + inline_mysql_file_fflush(F) +#endif + +/** + @def mysql_file_feof(F) + Instrumented feof. + @c mysql_file_feof is a replacement for @c feof. +*/ +#define mysql_file_feof(F) inline_mysql_file_feof(F) + +/** + @def mysql_file_fstat(FN, S, FL) + Instrumented fstat. + @c mysql_file_fstat is a replacement for @c my_fstat. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fstat(FN, S, FL) \ + inline_mysql_file_fstat(__FILE__, __LINE__, FN, S, FL) +#else + #define mysql_file_fstat(FN, S, FL) \ + inline_mysql_file_fstat(FN, S, FL) +#endif + +/** + @def mysql_file_stat(K, FN, S, FL) + Instrumented stat. + @c mysql_file_stat is a replacement for @c my_stat. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_stat(K, FN, S, FL) \ + inline_mysql_file_stat(K, __FILE__, __LINE__, FN, S, FL) +#else + #define mysql_file_stat(K, FN, S, FL) \ + inline_mysql_file_stat(FN, S, FL) +#endif + +/** + @def mysql_file_chsize(F, P1, P2, P3) + Instrumented chsize. + @c mysql_file_chsize is a replacement for @c my_chsize. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_chsize(F, P1, P2, P3) \ + inline_mysql_file_chsize(__FILE__, __LINE__, F, P1, P2, P3) +#else + #define mysql_file_chsize(F, P1, P2, P3) \ + inline_mysql_file_chsize(F, P1, P2, P3) +#endif + +/** + @def mysql_file_fopen(K, N, F1, F2) + Instrumented fopen. + @c mysql_file_fopen is a replacement for @c my_fopen. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fopen(K, N, F1, F2) \ + inline_mysql_file_fopen(K, __FILE__, __LINE__, N, F1, F2) +#else + #define mysql_file_fopen(K, N, F1, F2) \ + inline_mysql_file_fopen(N, F1, F2) +#endif + +/** + @def mysql_file_fclose(FD, FL) + Instrumented fclose. + @c mysql_file_fclose is a replacement for @c my_fclose. + Without the instrumentation, this call will have the same behavior as the + undocumented and possibly platform specific my_fclose(NULL, ...) behavior. + With the instrumentation, mysql_fclose(NULL, ...) will safely return 0, + which is an extension compared to my_fclose and is therefore compliant. + mysql_fclose is on purpose *not* implementing + @code assert(file != NULL) @endcode, + since doing so could introduce regressions. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fclose(FD, FL) \ + inline_mysql_file_fclose(__FILE__, __LINE__, FD, FL) +#else + #define mysql_file_fclose(FD, FL) \ + inline_mysql_file_fclose(FD, FL) +#endif + +/** + @def mysql_file_fread(FD, P1, P2, P3) + Instrumented fread. + @c mysql_file_fread is a replacement for @c my_fread. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fread(FD, P1, P2, P3) \ + inline_mysql_file_fread(__FILE__, __LINE__, FD, P1, P2, P3) +#else + #define mysql_file_fread(FD, P1, P2, P3) \ + inline_mysql_file_fread(FD, P1, P2, P3) +#endif + +/** + @def mysql_file_fwrite(FD, P1, P2, P3) + Instrumented fwrite. + @c mysql_file_fwrite is a replacement for @c my_fwrite. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fwrite(FD, P1, P2, P3) \ + inline_mysql_file_fwrite(__FILE__, __LINE__, FD, P1, P2, P3) +#else + #define mysql_file_fwrite(FD, P1, P2, P3) \ + inline_mysql_file_fwrite(FD, P1, P2, P3) +#endif + +/** + @def mysql_file_fseek(FD, P, W, F) + Instrumented fseek. + @c mysql_file_fseek is a replacement for @c my_fseek. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fseek(FD, P, W, F) \ + inline_mysql_file_fseek(__FILE__, __LINE__, FD, P, W, F) +#else + #define mysql_file_fseek(FD, P, W, F) \ + inline_mysql_file_fseek(FD, P, W, F) +#endif + +/** + @def mysql_file_ftell(FD, F) + Instrumented ftell. + @c mysql_file_ftell is a replacement for @c my_ftell. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_ftell(FD, F) \ + inline_mysql_file_ftell(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_ftell(FD, F) \ + inline_mysql_file_ftell(FD, F) +#endif + +/** + @def mysql_file_create(K, N, F1, F2, F3) + Instrumented create. + @c mysql_file_create is a replacement for @c my_create. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_create(K, N, F1, F2, F3) \ + inline_mysql_file_create(K, __FILE__, __LINE__, N, F1, F2, F3) +#else + #define mysql_file_create(K, N, F1, F2, F3) \ + inline_mysql_file_create(N, F1, F2, F3) +#endif + +/** + @def mysql_file_create_temp(K, T, D, P, M, F) + Instrumented create_temp_file. + @c mysql_file_create_temp is a replacement for @c create_temp_file. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_create_temp(K, T, D, P, M, F) \ + inline_mysql_file_create_temp(K, __FILE__, __LINE__, T, D, P, M, F) +#else + #define mysql_file_create_temp(K, T, D, P, M, F) \ + inline_mysql_file_create_temp(T, D, P, M, F) +#endif + +/** + @def mysql_file_open(K, N, F1, F2) + Instrumented open. + @c mysql_file_open is a replacement for @c my_open. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_open(K, N, F1, F2) \ + inline_mysql_file_open(K, __FILE__, __LINE__, N, F1, F2) +#else + #define mysql_file_open(K, N, F1, F2) \ + inline_mysql_file_open(N, F1, F2) +#endif + +/** + @def mysql_file_close(FD, F) + Instrumented close. + @c mysql_file_close is a replacement for @c my_close. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_close(FD, F) \ + inline_mysql_file_close(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_close(FD, F) \ + inline_mysql_file_close(FD, F) +#endif + +/** + @def mysql_file_read(FD, B, S, F) + Instrumented read. + @c mysql_read is a replacement for @c my_read. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_read(FD, B, S, F) \ + inline_mysql_file_read(__FILE__, __LINE__, FD, B, S, F) +#else + #define mysql_file_read(FD, B, S, F) \ + inline_mysql_file_read(FD, B, S, F) +#endif + +/** + @def mysql_file_write(FD, B, S, F) + Instrumented write. + @c mysql_file_write is a replacement for @c my_write. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_write(FD, B, S, F) \ + inline_mysql_file_write(__FILE__, __LINE__, FD, B, S, F) +#else + #define mysql_file_write(FD, B, S, F) \ + inline_mysql_file_write(FD, B, S, F) +#endif + +/** + @def mysql_file_pread(FD, B, S, O, F) + Instrumented pread. + @c mysql_pread is a replacement for @c my_pread. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_pread(FD, B, S, O, F) \ + inline_mysql_file_pread(__FILE__, __LINE__, FD, B, S, O, F) +#else + #define mysql_file_pread(FD, B, S, O, F) \ + inline_mysql_file_pread(FD, B, S, O, F) +#endif + +/** + @def mysql_file_pwrite(FD, B, S, O, F) + Instrumented pwrite. + @c mysql_file_pwrite is a replacement for @c my_pwrite. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_pwrite(FD, B, S, O, F) \ + inline_mysql_file_pwrite(__FILE__, __LINE__, FD, B, S, O, F) +#else + #define mysql_file_pwrite(FD, B, S, O, F) \ + inline_mysql_file_pwrite(FD, B, S, O, F) +#endif + +/** + @def mysql_file_seek(FD, P, W, F) + Instrumented seek. + @c mysql_file_seek is a replacement for @c my_seek. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_seek(FD, P, W, F) \ + inline_mysql_file_seek(__FILE__, __LINE__, FD, P, W, F) +#else + #define mysql_file_seek(FD, P, W, F) \ + inline_mysql_file_seek(FD, P, W, F) +#endif + +/** + @def mysql_file_tell(FD, F) + Instrumented tell. + @c mysql_file_tell is a replacement for @c my_tell. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_tell(FD, F) \ + inline_mysql_file_tell(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_tell(FD, F) \ + inline_mysql_file_tell(FD, F) +#endif + +/** + @def mysql_file_delete(K, P1, P2) + Instrumented delete. + @c mysql_file_delete is a replacement for @c my_delete. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_delete(K, P1, P2) \ + inline_mysql_file_delete(K, __FILE__, __LINE__, P1, P2) +#else + #define mysql_file_delete(K, P1, P2) \ + inline_mysql_file_delete(P1, P2) +#endif + +/** + @def mysql_file_rename(K, P1, P2, P3) + Instrumented rename. + @c mysql_file_rename is a replacement for @c my_rename. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_rename(K, P1, P2, P3) \ + inline_mysql_file_rename(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_rename(K, P1, P2, P3) \ + inline_mysql_file_rename(P1, P2, P3) +#endif + +/** + @def mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) + Instrumented create with symbolic link. + @c mysql_file_create_with_symlink is a replacement + for @c my_create_with_symlink. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ + inline_mysql_file_create_with_symlink(K, __FILE__, __LINE__, \ + P1, P2, P3, P4, P5) +#else + #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ + inline_mysql_file_create_with_symlink(P1, P2, P3, P4, P5) +#endif + +/** + @def mysql_file_delete_with_symlink(K, P1, P2, P3) + Instrumented delete with symbolic link. + @c mysql_file_delete_with_symlink is a replacement + for @c my_handler_delete_with_symlink. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_delete_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_delete_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_delete_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_delete_with_symlink(P1, P2, P3) +#endif + +/** + @def mysql_file_rename_with_symlink(K, P1, P2, P3) + Instrumented rename with symbolic link. + @c mysql_file_rename_with_symlink is a replacement + for @c my_rename_with_symlink. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_rename_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_rename_with_symlink(P1, P2, P3) +#endif + +/** + @def mysql_file_sync(P1, P2) + Instrumented file sync. + @c mysql_file_sync is a replacement for @c my_sync. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_sync(P1, P2) \ + inline_mysql_file_sync(__FILE__, __LINE__, P1, P2) +#else + #define mysql_file_sync(P1, P2) \ + inline_mysql_file_sync(P1, P2) +#endif + +/** + An instrumented FILE structure. + @sa MYSQL_FILE +*/ +struct st_mysql_file +{ + /** The real file. */ + FILE *m_file; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c MYSQL_FILE interface. + */ + struct PSI_file *m_psi; +}; + +/** + Type of an instrumented file. + @c MYSQL_FILE is a drop-in replacement for @c FILE. + @sa mysql_file_open +*/ +typedef struct st_mysql_file MYSQL_FILE; + +static inline void inline_mysql_file_register( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *category, + PSI_file_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_FILE_CALL(register_file)(category, info, count); +#endif +} + +static inline char * +inline_mysql_file_fgets( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + char *str, int size, MYSQL_FILE *file) +{ + char *result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_READ); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) size, src_file, src_line); + result= fgets(str, size, file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, result ? strlen(result) : 0); + return result; + } + } +#endif + + result= fgets(str, size, file->m_file); + return result; +} + +static inline int +inline_mysql_file_fgetc( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_READ); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line); + result= fgetc(file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1); + return result; + } + } +#endif + + result= fgetc(file->m_file); + return result; +} + +static inline int +inline_mysql_file_fputs( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + const char *str, MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + bytes= str ? strlen(str) : 0; + PSI_FILE_CALL(start_file_wait)(locker, bytes, src_file, src_line); + result= fputs(str, file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, bytes); + return result; + } + } +#endif + + result= fputs(str, file->m_file); + return result; +} + +static inline int +inline_mysql_file_fputc( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + char c, MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line); + result= fputc(c, file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1); + return result; + } + } +#endif + + result= fputc(c, file->m_file); + return result; +} + +static inline int +inline_mysql_file_fprintf(MYSQL_FILE *file, const char *format, ...) +{ + /* + TODO: figure out how to pass src_file and src_line from the caller. + */ + int result; + va_list args; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, __FILE__, __LINE__); + va_start(args, format); + result= vfprintf(file->m_file, format, args); + va_end(args); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) result); + return result; + } + } +#endif + + va_start(args, format); + result= vfprintf(file->m_file, format, args); + va_end(args); + return result; +} + +static inline int +inline_mysql_file_vfprintf( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, const char *format, va_list args) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= vfprintf(file->m_file, format, args); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) result); + return result; + } + } +#endif + + result= vfprintf(file->m_file, format, args); + return result; +} + +static inline int +inline_mysql_file_fflush( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_FLUSH); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= fflush(file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } + } +#endif + + result= fflush(file->m_file); + return result; +} + +static inline int inline_mysql_file_feof(MYSQL_FILE *file) +{ + /* Not instrumented, there is no wait involved */ + return feof(file->m_file); +} + +static inline int +inline_mysql_file_fstat( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + int filenr, MY_STAT *stat_area, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, filenr, PSI_FILE_FSTAT); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_fstat(filenr, stat_area, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_fstat(filenr, stat_area, flags); + return result; +} + +static inline MY_STAT * +inline_mysql_file_stat( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *path, MY_STAT *stat_area, myf flags) +{ + MY_STAT *result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_STAT, path, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + result= my_stat(path, stat_area, flags); + PSI_FILE_CALL(end_file_open_wait)(locker, result); + return result; + } +#endif + + result= my_stat(path, stat_area, flags); + return result; +} + +static inline int +inline_mysql_file_chsize( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, my_off_t newlength, int filler, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_CHSIZE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) newlength, src_file, + src_line); + result= my_chsize(file, newlength, filler, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) newlength); + return result; + } +#endif + + result= my_chsize(file, newlength, filler, flags); + return result; +} + +static inline MYSQL_FILE* +inline_mysql_file_fopen( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int flags, myf myFlags) +{ + MYSQL_FILE *that; + that= (MYSQL_FILE*) my_malloc(PSI_NOT_INSTRUMENTED, + sizeof(MYSQL_FILE), MYF(MY_WME)); + if (likely(that != NULL)) + { +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_STREAM_OPEN, + filename, that); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + that->m_file= my_fopen(filename, flags, myFlags); + that->m_psi= PSI_FILE_CALL(end_file_open_wait)(locker, that->m_file); + if (unlikely(that->m_file == NULL)) + { + my_free(that); + return NULL; + } + return that; + } +#endif + + that->m_psi= NULL; + that->m_file= my_fopen(filename, flags, myFlags); + if (unlikely(that->m_file == NULL)) + { + my_free(that); + return NULL; + } + } + return that; +} + +static inline int +inline_mysql_file_fclose( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, myf flags) +{ + int result= 0; + if (likely(file != NULL)) + { +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, + PSI_FILE_STREAM_CLOSE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_fclose(file->m_file, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + my_free(file); + return result; + } + } +#endif + + result= my_fclose(file->m_file, flags); + my_free(file); + } + return result; +} + +static inline size_t +inline_mysql_file_fread( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_read; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_READ); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_fread(file->m_file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_read); + return result; + } + } +#endif + + result= my_fread(file->m_file, buffer, count, flags); + return result; +} + +static inline size_t +inline_mysql_file_fwrite( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, const uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_written; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_fwrite(file->m_file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_written); + return result; + } + } +#endif + + result= my_fwrite(file->m_file, buffer, count, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_fseek( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, my_off_t pos, int whence, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_SEEK); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_fseek(file->m_file, pos, whence, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } + } +#endif + + result= my_fseek(file->m_file, pos, whence, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_ftell( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_TELL); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_ftell(file->m_file, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } + } +#endif + + result= my_ftell(file->m_file, flags); + return result; +} + +static inline File +inline_mysql_file_create( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int create_flags, int access_flags, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE, filename, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + file= my_create(filename, create_flags, access_flags, myFlags); + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); + return file; + } +#endif + + file= my_create(filename, create_flags, access_flags, myFlags); + return file; +} + +static inline File +inline_mysql_file_create_temp( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + char *to, const char *dir, const char *pfx, int mode, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker) + (&state, key, PSI_FILE_CREATE, NULL, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + /* The file name is generated by create_temp_file(). */ + file= create_temp_file(to, dir, pfx, mode, myFlags); + PSI_FILE_CALL(end_temp_file_open_wait_and_bind_to_descriptor)(locker, file, (const char*)to); + return file; + } +#endif + + file= create_temp_file(to, dir, pfx, mode, myFlags); + return file; +} + +static inline File +inline_mysql_file_open( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int flags, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_OPEN, filename, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + file= my_open(filename, flags, myFlags); + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); + return file; + } +#endif + + file= my_open(filename, flags, myFlags); + return file; +} + +static inline int +inline_mysql_file_close( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_CLOSE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_close(file, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + return result; + } +#endif + + result= my_close(file, flags); + return result; +} + +static inline size_t +inline_mysql_file_read( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_read; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_READ); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_read(file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_read); + return result; + } +#endif + + result= my_read(file, buffer, count, flags); + return result; +} + +static inline size_t +inline_mysql_file_write( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, const uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_written; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_WRITE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_write(file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_written); + return result; + } +#endif + + result= my_write(file, buffer, count, flags); + return result; +} + +static inline size_t +inline_mysql_file_pread( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, uchar *buffer, size_t count, my_off_t offset, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_read; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_READ); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_pread(file, buffer, count, offset, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_read); + return result; + } +#endif + + result= my_pread(file, buffer, count, offset, flags); + return result; +} + +static inline size_t +inline_mysql_file_pwrite( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, const uchar *buffer, size_t count, my_off_t offset, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_written; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_WRITE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_pwrite(file, buffer, count, offset, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_written); + return result; + } +#endif + + result= my_pwrite(file, buffer, count, offset, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_seek( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, my_off_t pos, int whence, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_SEEK); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_seek(file, pos, whence, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_seek(file, pos, whence, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_tell( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_TELL); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_tell(file, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_tell(file, flags); + return result; +} + +static inline int +inline_mysql_file_delete( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, name, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_delete(name, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + return result; + } +#endif + + result= my_delete(name, flags); + return result; +} + +static inline int +inline_mysql_file_rename( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *from, const char *to, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker) + (&state, key, PSI_FILE_RENAME, from, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_rename(from, to, flags); + PSI_FILE_CALL(end_file_rename_wait)(locker, from, to, result); + return result; + } +#endif + + result= my_rename(from, to, flags); + return result; +} + + +static inline File +inline_mysql_file_create_with_symlink( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *linkname, const char *filename, int create_flags, + int access_flags, myf flags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE, filename, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + file= my_create_with_symlink(linkname, filename, create_flags, access_flags, + flags); + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); + return file; + } +#endif + + file= my_create_with_symlink(linkname, filename, create_flags, access_flags, + flags); + return file; +} + + +static inline int +inline_mysql_file_delete_with_symlink( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, const char *ext, myf flags) +{ + int result; + char buf[FN_REFLEN]; + char *fullname= fn_format(buf, name, "", ext, MY_UNPACK_FILENAME | MY_APPEND_EXT); +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, fullname, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_handler_delete_with_symlink(fullname, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + return result; + } +#endif + + result= my_handler_delete_with_symlink(fullname, flags); + return result; +} + + +static inline int +inline_mysql_file_rename_with_symlink( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *from, const char *to, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker) + (&state, key, PSI_FILE_RENAME, from, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_rename_with_symlink(from, to, flags); + PSI_FILE_CALL(end_file_rename_wait)(locker, from, to, result); + return result; + } +#endif + + result= my_rename_with_symlink(from, to, flags); + return result; +} + +static inline int +inline_mysql_file_sync( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File fd, myf flags) +{ + int result= 0; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, fd, PSI_FILE_SYNC); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_sync(fd, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_sync(fd, flags); + return result; +} + +/** @} (end of group File_instrumentation) */ + +#endif diff --git a/include/mysql/psi/mysql_idle.h b/include/mysql/psi/mysql_idle.h new file mode 100644 index 00000000..dc7f5180 --- /dev/null +++ b/include/mysql/psi/mysql_idle.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2011, 2023, Oracle and/or its affiliates + Copyright (c) 2017, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_IDLE_H +#define MYSQL_IDLE_H + +/** + @file mysql/psi/mysql_idle.h + Instrumentation helpers for idle waits. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_IDLE_CALL +#define PSI_IDLE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Idle_instrumentation Idle Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def MYSQL_START_IDLE_WAIT + Instrumentation helper for table io_waits. + This instrumentation marks the start of a wait event. + @param LOCKER the locker + @param STATE the locker state + @sa MYSQL_END_IDLE_WAIT. +*/ +#ifdef HAVE_PSI_IDLE_INTERFACE + #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ + LOCKER= inline_mysql_start_idle_wait(STATE, __FILE__, __LINE__) +#else + #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ + do {} while (0) +#endif + +/** + @def MYSQL_END_IDLE_WAIT + Instrumentation helper for idle waits. + This instrumentation marks the end of a wait event. + @param LOCKER the locker + @sa MYSQL_START_IDLE_WAIT. +*/ +#ifdef HAVE_PSI_IDLE_INTERFACE + #define MYSQL_END_IDLE_WAIT(LOCKER) \ + inline_mysql_end_idle_wait(LOCKER) +#else + #define MYSQL_END_IDLE_WAIT(LOCKER) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_IDLE_INTERFACE +/** + Instrumentation calls for MYSQL_START_IDLE_WAIT. + @sa MYSQL_END_IDLE_WAIT. +*/ +static inline struct PSI_idle_locker * +inline_mysql_start_idle_wait(PSI_idle_locker_state *state, + const char *src_file, uint src_line) +{ + struct PSI_idle_locker *locker; + locker= PSI_IDLE_CALL(start_idle_wait)(state, src_file, src_line); + return locker; +} + +/** + Instrumentation calls for MYSQL_END_IDLE_WAIT. + @sa MYSQL_START_IDLE_WAIT. +*/ +static inline void +inline_mysql_end_idle_wait(struct PSI_idle_locker *locker) +{ + if (psi_likely(locker != NULL)) + PSI_IDLE_CALL(end_idle_wait)(locker); +} +#endif + +/** @} (end of group Idle_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_mdl.h b/include/mysql/psi/mysql_mdl.h new file mode 100644 index 00000000..8721a191 --- /dev/null +++ b/include/mysql/psi/mysql_mdl.h @@ -0,0 +1,143 @@ +/* Copyright (c) 2012, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_MDL_H +#define MYSQL_MDL_H + +/** + @file mysql/psi/mysql_mdl.h + Instrumentation helpers for metadata locks. +*/ + +#include "mysql/psi/psi.h" + +#ifdef HAVE_PSI_METADATA_INTERFACE + +#ifndef PSI_METADATA_CALL +#define PSI_METADATA_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#define PSI_CALL_start_metadata_wait(A,B,C,D) PSI_METADATA_CALL(start_metadata_wait)(A,B,C,D) +#define PSI_CALL_end_metadata_wait(A,B) PSI_METADATA_CALL(end_metadata_wait)(A,B) +#define PSI_CALL_create_metadata_lock(A,B,C,D,E,F,G) PSI_METADATA_CALL(create_metadata_lock)(A,B,C,D,E,F,G) +#define PSI_CALL_set_metadata_lock_status(A,B) PSI_METADATA_CALL(set_metadata_lock_status)(A,B) +#define PSI_CALL_destroy_metadata_lock(A) PSI_METADATA_CALL(destroy_metadata_lock)(A) +#else +#define PSI_CALL_start_metadata_wait(A,B,C,D) 0 +#define PSI_CALL_end_metadata_wait(A,B) do { } while(0) +#define PSI_CALL_create_metadata_lock(A,B,C,D,E,F,G) 0 +#define PSI_CALL_set_metadata_lock_status(A,B) do {} while(0) +#define PSI_CALL_destroy_metadata_lock(A) do {} while(0) +#endif + +/** + @defgroup Thread_instrumentation Metadata Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_mdl_create(K, M, A) + Instrumented metadata lock creation. + @param I Metadata lock identity + @param K Metadata key + @param T Metadata lock type + @param D Metadata lock duration + @param S Metadata lock status + @param F request source file + @param L request source line +*/ + +#ifdef HAVE_PSI_METADATA_INTERFACE + #define mysql_mdl_create(I, K, T, D, S, F, L) \ + inline_mysql_mdl_create(I, K, T, D, S, F, L) +#else + #define mysql_mdl_create(I, K, T, D, S, F, L) NULL +#endif + +#ifdef HAVE_PSI_METADATA_INTERFACE + #define mysql_mdl_set_status(L, S) \ + inline_mysql_mdl_set_status(L, S) +#else + #define mysql_mdl_set_status(L, S) \ + do {} while (0) +#endif + + +/** + @def mysql_mdl_destroy(M) + Instrumented metadata lock destruction. + @param M Metadata lock +*/ +#ifdef HAVE_PSI_METADATA_INTERFACE + #define mysql_mdl_destroy(M) \ + inline_mysql_mdl_destroy(M, __FILE__, __LINE__) +#else + #define mysql_mdl_destroy(M) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_METADATA_INTERFACE + +static inline PSI_metadata_lock * +inline_mysql_mdl_create(void *identity, + const MDL_key *mdl_key, + enum_mdl_type mdl_type, + enum_mdl_duration mdl_duration, + MDL_ticket::enum_psi_status mdl_status, + const char *src_file, uint src_line) +{ + PSI_metadata_lock *result; + + /* static_cast: Fit a round C++ enum peg into a square C int hole ... */ + result= PSI_METADATA_CALL(create_metadata_lock) + (identity, + mdl_key, + static_cast<opaque_mdl_type> (mdl_type), + static_cast<opaque_mdl_duration> (mdl_duration), + static_cast<opaque_mdl_status> (mdl_status), + src_file, src_line); + + return result; +} + +static inline void inline_mysql_mdl_set_status( + PSI_metadata_lock *psi, + MDL_ticket::enum_psi_status mdl_status) +{ + if (psi != NULL) + PSI_METADATA_CALL(set_metadata_lock_status)(psi, mdl_status); +} + +static inline void inline_mysql_mdl_destroy( + PSI_metadata_lock *psi, + const char *src_file, uint src_line) +{ + if (psi != NULL) + PSI_METADATA_CALL(destroy_metadata_lock)(psi); +} +#endif /* HAVE_PSI_METADATA_INTERFACE */ + +/** @} (end of group Metadata_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_memory.h b/include/mysql/psi/mysql_memory.h new file mode 100644 index 00000000..7f54b00d --- /dev/null +++ b/include/mysql/psi/mysql_memory.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2012, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_MEMORY_H +#define MYSQL_MEMORY_H + +/** + @file mysql/psi/mysql_memory.h + Instrumentation helpers for memory allocation. +*/ + +#include "mysql/psi/psi.h" + +#ifdef HAVE_PSI_MEMORY_INTERFACE +#define PSI_CALL_memory_alloc(A1,A2,A3) PSI_MEMORY_CALL(memory_alloc)(A1,A2,A3) +#define PSI_CALL_memory_free(A1,A2,A3) PSI_MEMORY_CALL(memory_free)(A1,A2,A3) +#define PSI_CALL_memory_realloc(A1,A2,A3,A4) PSI_MEMORY_CALL(memory_realloc)(A1,A2,A3,A4) +#define PSI_CALL_register_memory(A1,A2,A3) PSI_MEMORY_CALL(register_memory)(A1,A2,A3) +#else +#define PSI_CALL_memory_alloc(A1,A2,A3) 0 +#define PSI_CALL_memory_free(A1,A2,A3) do { } while(0) +#define PSI_CALL_memory_realloc(A1,A2,A3,A4) 0 +#define PSI_CALL_register_memory(A1,A2,A3) do { } while(0) +#endif + +#ifndef PSI_MEMORY_CALL +#define PSI_MEMORY_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Memory_instrumentation Memory Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_memory_register(P1, P2, P3) + Memory registration. +*/ +#define mysql_memory_register(P1, P2, P3) \ + inline_mysql_memory_register(P1, P2, P3) + +static inline void inline_mysql_memory_register( +#ifdef HAVE_PSI_MEMORY_INTERFACE + const char *category, + PSI_memory_info *info, + int count) +#else + const char *category __attribute__((unused)), + void *info __attribute__((unused)), + int count __attribute__((unused))) +#endif +{ + PSI_CALL_register_memory(category, info, count); +} + +/** @} (end of group Memory_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_ps.h b/include/mysql/psi/mysql_ps.h new file mode 100644 index 00000000..89f34ef6 --- /dev/null +++ b/include/mysql/psi/mysql_ps.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2014, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MYSQL_PS_H +#define MYSQL_PS_H + +/** + @file mysql/psi/mysql_ps.h + Instrumentation helpers for prepared statements. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_PS_CALL +#define PSI_PS_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifdef HAVE_PSI_PS_INTERFACE + #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH) \ + inline_mysql_create_prepared_stmt(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH) + #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ + inline_mysql_execute_prepared_stmt(LOCKER, PREPARED_STMT) + #define MYSQL_DESTROY_PS(PREPARED_STMT) \ + inline_mysql_destroy_prepared_stmt(PREPARED_STMT) + #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ + inline_mysql_reprepare_prepared_stmt(PREPARED_STMT) + #define MYSQL_SET_PS_TEXT(PREPARED_STMT, SQLTEXT, SQLTEXT_LENGTH) \ + inline_mysql_set_prepared_stmt_text(PREPARED_STMT, SQLTEXT, SQLTEXT_LENGTH) +#else + #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH) \ + NULL + #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ + do {} while (0) + #define MYSQL_DESTROY_PS(PREPARED_STMT) \ + do {} while (0) + #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ + do {} while (0) + #define MYSQL_SET_PS_TEXT(PREPARED_STMT, SQLTEXT, SQLTEXT_LENGTH) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_PS_INTERFACE +static inline struct PSI_prepared_stmt* +inline_mysql_create_prepared_stmt(void *identity, uint stmt_id, + PSI_statement_locker *locker, + const char *stmt_name, size_t stmt_name_length) +{ + if (locker == NULL) + return NULL; + return PSI_PS_CALL(create_prepared_stmt)(identity, stmt_id, + locker, + stmt_name, stmt_name_length); +} + +static inline void +inline_mysql_execute_prepared_stmt(PSI_statement_locker *locker, + PSI_prepared_stmt* prepared_stmt) +{ + if (prepared_stmt != NULL && locker != NULL) + PSI_PS_CALL(execute_prepared_stmt)(locker, prepared_stmt); +} + +static inline void +inline_mysql_destroy_prepared_stmt(PSI_prepared_stmt *prepared_stmt) +{ + if (prepared_stmt != NULL) + PSI_PS_CALL(destroy_prepared_stmt)(prepared_stmt); +} + +static inline void +inline_mysql_reprepare_prepared_stmt(PSI_prepared_stmt *prepared_stmt) +{ + if (prepared_stmt != NULL) + PSI_PS_CALL(reprepare_prepared_stmt)(prepared_stmt); +} + +static inline void +inline_mysql_set_prepared_stmt_text(PSI_prepared_stmt *prepared_stmt, + const char *text, + uint text_len) +{ + if (prepared_stmt != NULL) + { + PSI_PS_CALL(set_prepared_stmt_text)(prepared_stmt, text, text_len); + } +} +#endif + +#endif diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h new file mode 100644 index 00000000..95cb02a5 --- /dev/null +++ b/include/mysql/psi/mysql_socket.h @@ -0,0 +1,1353 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. + Copyright (c) 2017, MariaDB Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2.0, +as published by the Free Software Foundation. + +This program is also distributed with certain software (including +but not limited to OpenSSL) that is licensed under separate terms, +as designated in a particular file or component or in included license +documentation. The authors of MySQL hereby grant you an additional +permission to link the program and your derivative works with the +separately licensed software that they have included with MySQL. + +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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA +02110-1335 USA +*/ + +#ifndef MYSQL_SOCKET_H +#define MYSQL_SOCKET_H + +/* For MY_STAT */ +#include <my_dir.h> +/* For my_chsize */ +#include <my_sys.h> +/* For socket api */ +#ifdef _WIN32 + #include <ws2def.h> + #include <winsock2.h> + #include <MSWSock.h> + #define SOCKBUF_T char +#else + #include <netinet/in.h> + #define SOCKBUF_T void +#endif +/** + @file mysql/psi/mysql_socket.h +[...] +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_SOCKET_CALL +#define PSI_SOCKET_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Socket_instrumentation Socket Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_socket_register(P1, P2, P3) + Socket registration. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_register(P1, P2, P3) \ + inline_mysql_socket_register(P1, P2, P3) +#else + #define mysql_socket_register(P1, P2, P3) \ + do {} while (0) +#endif + +/** An instrumented socket. */ +struct st_mysql_socket +{ + /** The real socket descriptor. */ + my_socket fd; + + /** Is this a Unix-domain socket? */ + char is_unix_domain_socket; + + /** Is this a socket opened for the extra port? */ + char is_extra_port; + + /** Address family of the socket. (See sa_family from struct sockaddr). */ + unsigned short address_family; + + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c MYSQL_SOCKET interface. + */ + struct PSI_socket *m_psi; +}; + +/** + An instrumented socket. + @c MYSQL_SOCKET is a replacement for @c my_socket. +*/ +typedef struct st_mysql_socket MYSQL_SOCKET; + + +/** + @def MYSQL_INVALID_SOCKET + MYSQL_SOCKET initial value. +*/ +//MYSQL_SOCKET MYSQL_INVALID_SOCKET= {INVALID_SOCKET, NULL}; +#define MYSQL_INVALID_SOCKET mysql_socket_invalid() + +/** + MYSQL_SOCKET helper. Initialize instrumented socket. + @sa mysql_socket_getfd + @sa mysql_socket_setfd +*/ +static inline MYSQL_SOCKET +mysql_socket_invalid() +{ + MYSQL_SOCKET mysql_socket= {INVALID_SOCKET, 0, 0, 0, NULL}; + return mysql_socket; +} + +/** + Set socket descriptor and address. + @param socket nstrumented socket + @param addr unformatted socket address + @param addr_len length of socket address +*/ + +static inline void +mysql_socket_set_address( +#ifdef HAVE_PSI_SOCKET_INTERFACE + MYSQL_SOCKET socket, + const struct sockaddr *addr, + socklen_t addr_len +#else + MYSQL_SOCKET socket __attribute__ ((unused)), + const struct sockaddr *addr __attribute__ ((unused)), + socklen_t addr_len __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (socket.m_psi != NULL) + PSI_SOCKET_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len); +#endif +} + +/** + Set socket descriptor and address. + @param socket instrumented socket +*/ +static inline void +mysql_socket_set_thread_owner( +#ifdef HAVE_PSI_SOCKET_INTERFACE +MYSQL_SOCKET socket +#else +MYSQL_SOCKET socket __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (socket.m_psi != NULL) + PSI_SOCKET_CALL(set_socket_thread_owner)(socket.m_psi); +#endif +} + +/** + MYSQL_SOCKET helper. Get socket descriptor. + @param mysql_socket Instrumented socket + @sa mysql_socket_getfd +*/ +static inline my_socket +mysql_socket_getfd(MYSQL_SOCKET mysql_socket) +{ + return mysql_socket.fd; +} + +/** + MYSQL_SOCKET helper. Set socket descriptor. + @param mysql_socket Instrumented socket + @param fd Socket descriptor + @sa mysql_socket_setfd +*/ +static inline void +mysql_socket_setfd(MYSQL_SOCKET *mysql_socket, my_socket fd) +{ + if (likely(mysql_socket != NULL)) + mysql_socket->fd= fd; +} + +/** + @def MYSQL_SOCKET_WAIT_VARIABLES + Instrumentation helper for socket waits. + This instrumentation declares local variables. + Do not use a ';' after this macro + @param LOCKER locker + @param STATE locker state + @sa MYSQL_START_SOCKET_WAIT. + @sa MYSQL_END_SOCKET_WAIT. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) \ + struct PSI_socket_locker* LOCKER; \ + PSI_socket_locker_state STATE; +#else + #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) +#endif + +/** + @def MYSQL_START_SOCKET_WAIT + Instrumentation helper for socket waits. + This instrumentation marks the start of a wait event. + @param LOCKER locker + @param STATE locker state + @param SOCKET instrumented socket + @param OP The socket operation to be performed + @param COUNT bytes to be written/read + @sa MYSQL_END_SOCKET_WAIT. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \ + LOCKER= inline_mysql_start_socket_wait(STATE, SOCKET, OP, COUNT,\ + __FILE__, __LINE__) +#else + #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \ + do {} while (0) +#endif + +/** + @def MYSQL_END_SOCKET_WAIT + Instrumentation helper for socket waits. + This instrumentation marks the end of a wait event. + @param LOCKER locker + @param COUNT actual bytes written/read, or -1 + @sa MYSQL_START_SOCKET_WAIT. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \ + inline_mysql_end_socket_wait(LOCKER, COUNT) +#else + #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \ + do {} while (0) +#endif + +/** + @def MYSQL_SOCKET_SET_STATE + Set the state (IDLE, ACTIVE) of an instrumented socket. + @param SOCKET the instrumented socket + @param STATE the new state + @sa PSI_socket_state +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \ + inline_mysql_socket_set_state(SOCKET, STATE) +#else + #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_SOCKET_INTERFACE +/** + Instrumentation calls for MYSQL_START_SOCKET_WAIT. + @sa MYSQL_START_SOCKET_WAIT. +*/ +static inline struct PSI_socket_locker* +inline_mysql_start_socket_wait(PSI_socket_locker_state *state, + MYSQL_SOCKET mysql_socket, + enum PSI_socket_operation op, + size_t byte_count, + const char *src_file, uint src_line) +{ + struct PSI_socket_locker *locker; + if (psi_likely(mysql_socket.m_psi != NULL)) + { + locker= PSI_SOCKET_CALL(start_socket_wait) + (state, mysql_socket.m_psi, op, byte_count, src_file, src_line); + } + else + locker= NULL; + return locker; +} + +/** + Instrumentation calls for MYSQL_END_SOCKET_WAIT. + @sa MYSQL_END_SOCKET_WAIT. +*/ +static inline void +inline_mysql_end_socket_wait(struct PSI_socket_locker *locker, size_t byte_count) +{ + if (psi_likely(locker != NULL)) + PSI_SOCKET_CALL(end_socket_wait)(locker, byte_count); +} + +/** + Set the state (IDLE, ACTIVE) of an instrumented socket. + @param socket the instrumented socket + @param state the new state + @sa PSI_socket_state +*/ +static inline void +inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state state) +{ + if (socket.m_psi != NULL) + PSI_SOCKET_CALL(set_socket_state)(socket.m_psi, state); +} +#endif /* HAVE_PSI_SOCKET_INTERFACE */ + +/** + @def mysql_socket_fd(K, F) + Create a socket. + @c mysql_socket_fd is a replacement for @c socket. + @param K PSI_socket_key for this instrumented socket + @param F File descriptor +*/ + +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_fd(K, F) \ + inline_mysql_socket_fd(K, F) +#else + #define mysql_socket_fd(K, F) \ + inline_mysql_socket_fd(F) +#endif + +/** + @def mysql_socket_socket(K, D, T, P) + Create a socket. + @c mysql_socket_socket is a replacement for @c socket. + @param K PSI_socket_key for this instrumented socket + @param D Socket domain + @param T Protocol type + @param P Transport protocol +*/ + +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_socket(K, D, T, P) \ + inline_mysql_socket_socket(K, D, T, P) +#else + #define mysql_socket_socket(K, D, T, P) \ + inline_mysql_socket_socket(D, T, P) +#endif + +/** + @def mysql_socket_bind(FD, AP, L) + Bind a socket to a local port number and IP address + @c mysql_socket_bind is a replacement for @c bind. + @param FD Instrumented socket descriptor returned by socket() + @param AP Pointer to local port number and IP address in sockaddr structure + @param L Length of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_bind(FD, AP, L) \ + inline_mysql_socket_bind(__FILE__, __LINE__, FD, AP, L) +#else + #define mysql_socket_bind(FD, AP, L) \ + inline_mysql_socket_bind(FD, AP, L) +#endif + +/** + @def mysql_socket_getsockname(FD, AP, LP) + Return port number and IP address of the local host + @c mysql_socket_getsockname is a replacement for @c getsockname. + @param FD Instrumented socket descriptor returned by socket() + @param AP Pointer to returned address of local host in @c sockaddr structure + @param LP Pointer to length of @c sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_getsockname(FD, AP, LP) \ + inline_mysql_socket_getsockname(__FILE__, __LINE__, FD, AP, LP) +#else + #define mysql_socket_getsockname(FD, AP, LP) \ + inline_mysql_socket_getsockname(FD, AP, LP) +#endif + +/** + @def mysql_socket_connect(FD, AP, L) + Establish a connection to a remote host. + @c mysql_socket_connect is a replacement for @c connect. + @param FD Instrumented socket descriptor returned by socket() + @param AP Pointer to target address in sockaddr structure + @param L Length of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_connect(FD, AP, L) \ + inline_mysql_socket_connect(__FILE__, __LINE__, FD, AP, L) +#else + #define mysql_socket_connect(FD, AP, L) \ + inline_mysql_socket_connect(FD, AP, L) +#endif + +/** + @def mysql_socket_getpeername(FD, AP, LP) + Get port number and IP address of remote host that a socket is connected to. + @c mysql_socket_getpeername is a replacement for @c getpeername. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param AP Pointer to returned address of remote host in sockaddr structure + @param LP Pointer to length of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_getpeername(FD, AP, LP) \ + inline_mysql_socket_getpeername(__FILE__, __LINE__, FD, AP, LP) +#else + #define mysql_socket_getpeername(FD, AP, LP) \ + inline_mysql_socket_getpeername(FD, AP, LP) +#endif + +/** + @def mysql_socket_send(FD, B, N, FL) + Send data from the buffer, B, to a connected socket. + @c mysql_socket_send is a replacement for @c send. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param B Buffer to send + @param N Number of bytes to send + @param FL Control flags +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_send(FD, B, N, FL) \ + inline_mysql_socket_send(__FILE__, __LINE__, FD, B, N, FL) +#else + #define mysql_socket_send(FD, B, N, FL) \ + inline_mysql_socket_send(FD, B, N, FL) +#endif + +/** + @def mysql_socket_recv(FD, B, N, FL) + Receive data from a connected socket. + @c mysql_socket_recv is a replacement for @c recv. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param B Buffer to receive to + @param N Maximum bytes to receive + @param FL Control flags +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_recv(FD, B, N, FL) \ + inline_mysql_socket_recv(__FILE__, __LINE__, FD, B, N, FL) +#else + #define mysql_socket_recv(FD, B, N, FL) \ + inline_mysql_socket_recv(FD, B, N, FL) +#endif + +/** + @def mysql_socket_sendto(FD, B, N, FL, AP, L) + Send data to a socket at the specified address. + @c mysql_socket_sendto is a replacement for @c sendto. + @param FD Instrumented socket descriptor returned by socket() + @param B Buffer to send + @param N Number of bytes to send + @param FL Control flags + @param AP Pointer to destination sockaddr structure + @param L Size of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_sendto(FD, B, N, FL, AP, L) \ + inline_mysql_socket_sendto(__FILE__, __LINE__, FD, B, N, FL, AP, L) +#else + #define mysql_socket_sendto(FD, B, N, FL, AP, L) \ + inline_mysql_socket_sendto(FD, B, N, FL, AP, L) +#endif + +/** + @def mysql_socket_recvfrom(FD, B, N, FL, AP, L) + Receive data from a socket and return source address information + @c mysql_socket_recvfrom is a replacement for @c recvfrom. + @param FD Instrumented socket descriptor returned by socket() + @param B Buffer to receive to + @param N Maximum bytes to receive + @param FL Control flags + @param AP Pointer to source address in sockaddr_storage structure + @param LP Size of sockaddr_storage structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \ + inline_mysql_socket_recvfrom(__FILE__, __LINE__, FD, B, N, FL, AP, LP) +#else + #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \ + inline_mysql_socket_recvfrom(FD, B, N, FL, AP, LP) +#endif + +/** + @def mysql_socket_getsockopt(FD, LV, ON, OP, OL) + Get a socket option for the specified socket. + @c mysql_socket_getsockopt is a replacement for @c getsockopt. + @param FD Instrumented socket descriptor returned by socket() + @param LV Protocol level + @param ON Option to query + @param OP Buffer which will contain the value for the requested option + @param OL Pointer to length of OP +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_getsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL) +#else + #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_getsockopt(FD, LV, ON, OP, OL) +#endif + +/** + @def mysql_socket_setsockopt(FD, LV, ON, OP, OL) + Set a socket option for the specified socket. + @c mysql_socket_setsockopt is a replacement for @c setsockopt. + @param FD Instrumented socket descriptor returned by socket() + @param LV Protocol level + @param ON Option to modify + @param OP Buffer containing the value for the specified option + @param OL Pointer to length of OP +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_setsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL) +#else + #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_setsockopt(FD, LV, ON, OP, OL) +#endif + +/** + @def mysql_sock_set_nonblocking + Set socket to non-blocking. + @param FD instrumented socket descriptor +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_sock_set_nonblocking(FD) \ + inline_mysql_sock_set_nonblocking(__FILE__, __LINE__, FD) +#else + #define mysql_sock_set_nonblocking(FD) \ + inline_mysql_sock_set_nonblocking(FD) +#endif + +/** + @def mysql_socket_listen(FD, N) + Set socket state to listen for an incoming connection. + @c mysql_socket_listen is a replacement for @c listen. + @param FD Instrumented socket descriptor, bound and connected + @param N Maximum number of pending connections allowed. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_listen(FD, N) \ + inline_mysql_socket_listen(__FILE__, __LINE__, FD, N) +#else + #define mysql_socket_listen(FD, N) \ + inline_mysql_socket_listen(FD, N) +#endif + +/** + @def mysql_socket_accept(K, FD, AP, LP) + Accept a connection from any remote host; TCP only. + @c mysql_socket_accept is a replacement for @c accept. + @param K PSI_socket_key for this instrumented socket + @param FD Instrumented socket descriptor, bound and placed in a listen state + @param AP Pointer to sockaddr structure with returned IP address and port of connected host + @param LP Pointer to length of valid information in AP +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_accept(K, FD, AP, LP) \ + inline_mysql_socket_accept(__FILE__, __LINE__, K, FD, AP, LP) +#else + #define mysql_socket_accept(K, FD, AP, LP) \ + inline_mysql_socket_accept(FD, AP, LP) +#endif + +/** + @def mysql_socket_close(FD) + Close a socket and sever any connections. + @c mysql_socket_close is a replacement for @c close. + @param FD Instrumented socket descriptor returned by socket() or accept() +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_close(FD) \ + inline_mysql_socket_close(__FILE__, __LINE__, FD) +#else + #define mysql_socket_close(FD) \ + inline_mysql_socket_close(FD) +#endif + +/** + @def mysql_socket_shutdown(FD, H) + Disable receives and/or sends on a socket. + @c mysql_socket_shutdown is a replacement for @c shutdown. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param H Specifies which operations to shutdown +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_shutdown(FD, H) \ + inline_mysql_socket_shutdown(__FILE__, __LINE__, FD, H) +#else + #define mysql_socket_shutdown(FD, H) \ + inline_mysql_socket_shutdown(FD, H) +#endif + +#ifdef HAVE_PSI_SOCKET_INTERFACE +static inline void inline_mysql_socket_register( + const char *category, + PSI_socket_info *info, + int count) +{ + PSI_SOCKET_CALL(register_socket)(category, info, count); +} +#endif + +/** mysql_socket_fd */ + +static inline MYSQL_SOCKET +inline_mysql_socket_fd +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + PSI_socket_key key, +#endif + int fd) +{ + MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET; + mysql_socket.fd= fd; + + DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET); +#ifdef HAVE_PSI_SOCKET_INTERFACE + mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket) + (key, (const my_socket*)&mysql_socket.fd, NULL, 0); +#endif + /** + Currently systemd socket activation is the user of this + function. Its API (man sd_listen_fds) says FD_CLOSE_EXEC + is already called. If there becomes another user, we + can call it again without detriment. + + If needed later: + #if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + (void) fcntl(mysql_socket.fd, F_SETFD, FD_CLOEXEC); + #endif + */ + + return mysql_socket; +} + +/** mysql_socket_socket */ + +static inline MYSQL_SOCKET +inline_mysql_socket_socket +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + PSI_socket_key key, +#endif + int domain, int type, int protocol) +{ + MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET; + mysql_socket.fd= socket(domain, type | SOCK_CLOEXEC, protocol); + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (likely(mysql_socket.fd != INVALID_SOCKET)) + { + mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket) + (key, (const my_socket*)&mysql_socket.fd, NULL, 0); + } +#endif + + /* SOCK_CLOEXEC isn't always a number - can't preprocessor compare */ +#if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) && !defined(HAVE_SOCK_CLOEXEC) + (void) fcntl(mysql_socket.fd, F_SETFD, FD_CLOEXEC); +#endif + + return mysql_socket; +} + +/** mysql_socket_bind */ + +static inline int +inline_mysql_socket_bind +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, size_t len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker_state state; + PSI_socket_locker *locker; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= bind(mysql_socket.fd, addr, (int)len); + + /* Instrumentation end */ + if (result == 0) + PSI_SOCKET_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, (socklen_t)len); + + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= bind(mysql_socket.fd, addr, (int)len); + return result; +} + +/** mysql_socket_getsockname */ + +static inline int +inline_mysql_socket_getsockname +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= getsockname(mysql_socket.fd, addr, len); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= getsockname(mysql_socket.fd, addr, len); + + return result; +} + +/** mysql_socket_connect */ + +static inline int +inline_mysql_socket_connect +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, socklen_t len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= connect(mysql_socket.fd, addr, len); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= connect(mysql_socket.fd, addr, len); + + return result; +} + +/** mysql_socket_getpeername */ + +static inline int +inline_mysql_socket_getpeername +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= getpeername(mysql_socket.fd, addr, len); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= getpeername(mysql_socket.fd, addr, len); + + return result; +} + +/** mysql_socket_send */ + +static inline ssize_t +inline_mysql_socket_send +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags) +{ + ssize_t result; + DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET); +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line); + + /* Instrumented code */ + result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_written= (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + return result; +} + +/** mysql_socket_recv */ + +static inline ssize_t +inline_mysql_socket_recv +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags) +{ + ssize_t result; + DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET); +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_read= (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + return result; +} + +/** mysql_socket_sendto */ + +static inline ssize_t +inline_mysql_socket_sendto +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len) +{ + ssize_t result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line); + + /* Instrumented code */ + result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_written = (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + return result; +} + +/** mysql_socket_recvfrom */ + +static inline ssize_t +inline_mysql_socket_recvfrom +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags, + struct sockaddr *addr, socklen_t *addr_len) +{ + ssize_t result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_read= (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + return result; +} + +/** mysql_socket_getsockopt */ + +static inline int +inline_mysql_socket_getsockopt +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int level, int optname, SOCKBUF_T *optval, socklen_t *optlen) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= getsockopt(mysql_socket.fd, level, optname, optval, optlen); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= getsockopt(mysql_socket.fd, level, optname, optval, optlen); + + return result; +} + +/** mysql_socket_setsockopt */ + +static inline int +inline_mysql_socket_setsockopt +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int level, int optname, const SOCKBUF_T *optval, + socklen_t optlen) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= setsockopt(mysql_socket.fd, level, optname, optval, optlen); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= setsockopt(mysql_socket.fd, level, optname, optval, optlen); + + return result; +} + +/** set_socket_nonblock */ +static inline int +set_socket_nonblock(my_socket fd) +{ + int ret= 0; +#ifdef _WIN32 + { + u_long nonblocking= 1; + ret= ioctlsocket(fd, FIONBIO, &nonblocking); + } +#else + { + int fd_flags; + fd_flags= fcntl(fd, F_GETFL, 0); + if (fd_flags < 0) + return errno; +#if defined(O_NONBLOCK) + fd_flags |= O_NONBLOCK; +#elif defined(O_NDELAY) + fd_flags |= O_NDELAY; +#elif defined(O_FNDELAY) + fd_flags |= O_FNDELAY; +#else +#error "No definition of non-blocking flag found." +#endif /* O_NONBLOCK */ + if (fcntl(fd, F_SETFL, fd_flags) == -1) + ret= errno; + } +#endif /* _WIN32 */ + return ret; +} + +/** mysql_socket_set_nonblocking */ + +static inline int +inline_mysql_sock_set_nonblocking +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket +) +{ + int result= 0; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (mysql_socket.m_psi) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, + (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= set_socket_nonblock(mysql_socket.fd); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= set_socket_nonblock(mysql_socket.fd); + + return result; +} + +/** mysql_socket_listen */ + +static inline int +inline_mysql_socket_listen +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int backlog) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= listen(mysql_socket.fd, backlog); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= listen(mysql_socket.fd, backlog); + + return result; +} + +/** mysql_socket_accept */ + +static inline MYSQL_SOCKET +inline_mysql_socket_accept +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, PSI_socket_key key, +#endif + MYSQL_SOCKET socket_listen, struct sockaddr *addr, socklen_t *addr_len) +{ +#ifdef FD_CLOEXEC + int flags __attribute__ ((unused)); +#endif + + MYSQL_SOCKET socket_accept; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (socket_listen.m_psi != NULL) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); + + /* Instrumented code */ +#ifdef HAVE_ACCEPT4 + socket_accept.fd= accept4(socket_listen.fd, addr, addr_len, SOCK_CLOEXEC); +#else + socket_accept.fd= accept(socket_listen.fd, addr, addr_len); +#ifdef FD_CLOEXEC + if (socket_accept.fd != INVALID_SOCKET) + { + flags= fcntl(socket_accept.fd, F_GETFD); + if (flags != -1) + { + flags |= FD_CLOEXEC; + fcntl(socket_accept.fd, F_SETFD, flags); + } + } +#endif +#endif + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + } + else +#endif + { + /* Non instrumented code */ +#ifdef HAVE_ACCEPT4 + socket_accept.fd= accept4(socket_listen.fd, addr, addr_len, SOCK_CLOEXEC); +#else + socket_accept.fd= accept(socket_listen.fd, addr, addr_len); +#ifdef FD_CLOEXEC + if (socket_accept.fd != INVALID_SOCKET) + { + flags= fcntl(socket_accept.fd, F_GETFD); + if (flags != -1) + { + flags |= FD_CLOEXEC; + fcntl(socket_accept.fd, F_SETFD, flags); + } + } +#endif +#endif + } + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (likely(socket_accept.fd != INVALID_SOCKET)) + { + /* Initialize the instrument with the new socket descriptor and address */ + socket_accept.m_psi= PSI_SOCKET_CALL(init_socket) + (key, (const my_socket*)&socket_accept.fd, addr, *addr_len); + } +#endif + + return socket_accept; +} + +/** mysql_socket_close */ + +static inline int +inline_mysql_socket_close +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= closesocket(mysql_socket.fd); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + /* Remove the instrumentation for this socket. */ + if (mysql_socket.m_psi != NULL) + PSI_SOCKET_CALL(destroy_socket)(mysql_socket.m_psi); + + return result; + } +#endif + + /* Non instrumented code */ + result= closesocket(mysql_socket.fd); + + return result; +} + +/** mysql_socket_shutdown */ + +static inline int +inline_mysql_socket_shutdown +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int how) +{ + int result; + +#ifdef _WIN32 + static LPFN_DISCONNECTEX DisconnectEx = NULL; + if (DisconnectEx == NULL) + { + DWORD dwBytesReturned; + GUID guidDisconnectEx = WSAID_DISCONNECTEX; + WSAIoctl(mysql_socket.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, + &guidDisconnectEx, sizeof(GUID), + &DisconnectEx, sizeof(DisconnectEx), + &dwBytesReturned, NULL, NULL); + } +#endif + +/* Instrumentation start */ +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line); + + /* Instrumented code */ +#ifdef _WIN32 + if (DisconnectEx) + result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL, + (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; + else +#endif + result= shutdown(mysql_socket.fd, how); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ +#ifdef _WIN32 + if (DisconnectEx) + result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL, + (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; + else +#endif + result= shutdown(mysql_socket.fd, how); + + return result; +} + +/** @} (end of group Socket_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_sp.h b/include/mysql/psi/mysql_sp.h new file mode 100644 index 00000000..c2524745 --- /dev/null +++ b/include/mysql/psi/mysql_sp.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2013, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MYSQL_SP_H +#define MYSQL_SP_H + +/** + @file mysql/psi/mysql_sp.h + Instrumentation helpers for stored programs. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_SP_CALL +#define PSI_SP_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_START_SP(STATE, SP_SHARE) \ + inline_mysql_start_sp(STATE, SP_SHARE) +#else + #define MYSQL_START_SP(STATE, SP_SHARE) \ + NULL +#endif + + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_END_SP(LOCKER) \ + inline_mysql_end_sp(LOCKER) +#else + #define MYSQL_END_SP(LOCKER) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ + inline_mysql_drop_sp(OT, SN, SNL, ON, ONL) +#else + #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ + inline_mysql_get_sp_share(OT, SN, SNL, ON, ONL) +#else + #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ + NULL +#endif + +#ifdef HAVE_PSI_SP_INTERFACE +static inline struct PSI_sp_locker* +inline_mysql_start_sp(PSI_sp_locker_state *state, PSI_sp_share *sp_share) +{ + return PSI_SP_CALL(start_sp)(state, sp_share); +} + +static inline void inline_mysql_end_sp(PSI_sp_locker *locker) +{ + if (likely(locker != NULL)) + PSI_SP_CALL(end_sp)(locker); +} + +static inline void +inline_mysql_drop_sp(uint sp_type, + const char* schema_name, uint shcema_name_length, + const char* object_name, uint object_name_length) +{ + PSI_SP_CALL(drop_sp)(sp_type, + schema_name, shcema_name_length, + object_name, object_name_length); +} + +static inline PSI_sp_share* +inline_mysql_get_sp_share(uint sp_type, + const char* schema_name, uint shcema_name_length, + const char* object_name, uint object_name_length) +{ + return PSI_SP_CALL(get_sp_share)(sp_type, + schema_name, shcema_name_length, + object_name, object_name_length); +} +#endif + +#endif diff --git a/include/mysql/psi/mysql_stage.h b/include/mysql/psi/mysql_stage.h new file mode 100644 index 00000000..b6bc5ce3 --- /dev/null +++ b/include/mysql/psi/mysql_stage.h @@ -0,0 +1,205 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_STAGE_H +#define MYSQL_STAGE_H + +/** + @file mysql/psi/mysql_stage.h + Instrumentation helpers for stages. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_STAGE_CALL +#define PSI_STAGE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Stage_instrumentation Stage Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_stage_register(P1, P2, P3) + Stage registration. +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_register(P1, P2, P3) \ + inline_mysql_stage_register(P1, P2, P3) +#else +#define mysql_stage_register(P1, P2, P3) \ + do {} while (0) +#endif + +/** + @def MYSQL_SET_STAGE + Set the current stage. + Use this API when the file and line + is passed from the caller. + @param K the stage key + @param F the source file name + @param L the source file line + @return the current stage progress +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE + #define MYSQL_SET_STAGE(K, F, L) \ + inline_mysql_set_stage(K, F, L) +#else + #define MYSQL_SET_STAGE(K, F, L) \ + NULL +#endif + +/** + @def mysql_set_stage + Set the current stage. + @param K the stage key + @return the current stage progress +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE + #define mysql_set_stage(K) \ + inline_mysql_set_stage(K, __FILE__, __LINE__) +#else + #define mysql_set_stage(K) \ + NULL +#endif + +/** + @def mysql_end_stage + End the last stage +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE + #define mysql_end_stage() \ + inline_mysql_end_stage() +#else + #define mysql_end_stage() \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void inline_mysql_stage_register( + const char *category, PSI_stage_info **info, int count) +{ + PSI_STAGE_CALL(register_stage)(category, info, count); +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline PSI_stage_progress* +inline_mysql_set_stage(PSI_stage_key key, + const char *src_file, int src_line) +{ + return PSI_STAGE_CALL(start_stage)(key, src_file, src_line); +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_end_stage() +{ + PSI_STAGE_CALL(end_stage)(); +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_set_work_completed(P1, P2) \ + inline_mysql_stage_set_work_completed(P1, P2) + +#define mysql_stage_get_work_completed(P1) \ + inline_mysql_stage_get_work_completed(P1) +#else +#define mysql_stage_set_work_completed(P1, P2) \ + do {} while (0) + +#define mysql_stage_get_work_completed(P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_inc_work_completed(P1, P2) \ + inline_mysql_stage_inc_work_completed(P1, P2) +#else +#define mysql_stage_inc_work_completed(P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_set_work_estimated(P1, P2) \ + inline_mysql_stage_set_work_estimated(P1, P2) + +#define mysql_stage_get_work_estimated(P1) \ + inline_mysql_stage_get_work_estimated(P1) +#else +#define mysql_stage_set_work_estimated(P1, P2) \ + do {} while (0) + +#define mysql_stage_get_work_estimated(P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_stage_set_work_completed(PSI_stage_progress *progress, + ulonglong val) +{ + if (progress != NULL) + progress->m_work_completed= val; +} + +static inline ulonglong +inline_mysql_stage_get_work_completed(PSI_stage_progress *progress) +{ + return progress->m_work_completed; +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_stage_inc_work_completed(PSI_stage_progress *progress, + ulonglong val) +{ + if (progress != NULL) + progress->m_work_completed+= val; +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_stage_set_work_estimated(PSI_stage_progress *progress, + ulonglong val) +{ + if (progress != NULL) + progress->m_work_estimated= val; +} + +static inline ulonglong +inline_mysql_stage_get_work_estimated(PSI_stage_progress *progress) +{ + return progress->m_work_estimated; +} +#endif + +/** @} (end of group Stage_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_statement.h b/include/mysql/psi/mysql_statement.h new file mode 100644 index 00000000..544bba67 --- /dev/null +++ b/include/mysql/psi/mysql_statement.h @@ -0,0 +1,243 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. + Copyright (c) 2017, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_STATEMENT_H +#define MYSQL_STATEMENT_H + +/** + @file mysql/psi/mysql_statement.h + Instrumentation helpers for statements. +*/ + +#include "mysql/psi/psi.h" + +class Diagnostics_area; +typedef const struct charset_info_st CHARSET_INFO; + +#ifndef PSI_STATEMENT_CALL +#define PSI_STATEMENT_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_DIGEST_CALL +#define PSI_DIGEST_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Statement_instrumentation Statement Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_statement_register(P1, P2, P3) + Statement registration. +*/ +#ifdef HAVE_PSI_STATEMENT_INTERFACE +#define mysql_statement_register(P1, P2, P3) \ + inline_mysql_statement_register(P1, P2, P3) +#else +#define mysql_statement_register(P1, P2, P3) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE + #define MYSQL_DIGEST_START(LOCKER) \ + inline_mysql_digest_start(LOCKER) +#else + #define MYSQL_DIGEST_START(LOCKER) \ + NULL +#endif + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE + #define MYSQL_DIGEST_END(LOCKER, DIGEST) \ + inline_mysql_digest_end(LOCKER, DIGEST) +#else + #define MYSQL_DIGEST_END(LOCKER, DIGEST) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS, SPS) \ + inline_mysql_start_statement(STATE, K, DB, DB_LEN, CS, SPS, __FILE__, __LINE__) +#else + #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS, SPS) \ + NULL +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_REFINE_STATEMENT(LOCKER, K) \ + inline_mysql_refine_statement(LOCKER, K) +#else + #define MYSQL_REFINE_STATEMENT(LOCKER, K) \ + NULL +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \ + inline_mysql_set_statement_text(LOCKER, P1, P2) +#else + #define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \ + inline_mysql_set_statement_lock_time(LOCKER, P1) +#else + #define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \ + inline_mysql_set_statement_rows_sent(LOCKER, P1) +#else + #define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \ + inline_mysql_set_statement_rows_examined(LOCKER, P1) +#else + #define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_END_STATEMENT(LOCKER, DA) \ + inline_mysql_end_statement(LOCKER, DA) +#else + #define MYSQL_END_STATEMENT(LOCKER, DA) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE +static inline void inline_mysql_statement_register( + const char *category, PSI_statement_info *info, int count) +{ + PSI_STATEMENT_CALL(register_statement)(category, info, count); +} + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE +static inline struct PSI_digest_locker * +inline_mysql_digest_start(PSI_statement_locker *locker) +{ + PSI_digest_locker* digest_locker= NULL; + + if (psi_likely(locker != NULL)) + digest_locker= PSI_DIGEST_CALL(digest_start)(locker); + return digest_locker; +} +#endif + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE +static inline void +inline_mysql_digest_end(PSI_digest_locker *locker, const sql_digest_storage *digest) +{ + if (psi_likely(locker != NULL)) + PSI_DIGEST_CALL(digest_end)(locker, digest); +} +#endif + +static inline struct PSI_statement_locker * +inline_mysql_start_statement(PSI_statement_locker_state *state, + PSI_statement_key key, + const char *db, size_t db_len, + CHARSET_INFO *charset, + PSI_sp_share *sp_share, + const char *src_file, uint src_line) +{ + PSI_statement_locker *locker; + locker= PSI_STATEMENT_CALL(get_thread_statement_locker)(state, key, charset, + sp_share); + if (psi_likely(locker != NULL)) + PSI_STATEMENT_CALL(start_statement)(locker, db, (uint)db_len, src_file, src_line); + return locker; +} + +static inline struct PSI_statement_locker * +inline_mysql_refine_statement(PSI_statement_locker *locker, + PSI_statement_key key) +{ + if (psi_likely(locker != NULL)) + { + locker= PSI_STATEMENT_CALL(refine_statement)(locker, key); + } + return locker; +} + +static inline void +inline_mysql_set_statement_text(PSI_statement_locker *locker, + const char *text, uint text_len) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_text)(locker, text, text_len); + } +} + +static inline void +inline_mysql_set_statement_lock_time(PSI_statement_locker *locker, + ulonglong count) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_lock_time)(locker, count); + } +} + +static inline void +inline_mysql_set_statement_rows_sent(PSI_statement_locker *locker, + ulonglong count) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_rows_sent)(locker, count); + } +} + +static inline void +inline_mysql_set_statement_rows_examined(PSI_statement_locker *locker, + ulonglong count) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_rows_examined)(locker, count); + } +} + +static inline void +inline_mysql_end_statement(struct PSI_statement_locker *locker, + Diagnostics_area *stmt_da) +{ + PSI_STAGE_CALL(end_stage)(); + if (psi_likely(locker != NULL)) + PSI_STATEMENT_CALL(end_statement)(locker, stmt_da); +} +#endif + +/** @} (end of group Statement_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_table.h b/include/mysql/psi/mysql_table.h new file mode 100644 index 00000000..317627a6 --- /dev/null +++ b/include/mysql/psi/mysql_table.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_TABLE_H +#define MYSQL_TABLE_H + +/** + @file mysql/psi/mysql_table.h + Instrumentation helpers for table io. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_TABLE_CALL +#define PSI_TABLE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Table_instrumentation Table Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +#ifdef HAVE_PSI_TABLE_INTERFACE +#define MYSQL_UNBIND_TABLE(handler) (handler)->unbind_psi() + +#define PSI_CALL_unbind_table PSI_TABLE_CALL(unbind_table) +#define PSI_CALL_rebind_table PSI_TABLE_CALL(rebind_table) +#define PSI_CALL_open_table PSI_TABLE_CALL(open_table) +#define PSI_CALL_close_table PSI_TABLE_CALL(close_table) +#define PSI_CALL_get_table_share PSI_TABLE_CALL(get_table_share) +#define PSI_CALL_release_table_share PSI_TABLE_CALL(release_table_share) +#define PSI_CALL_drop_table_share PSI_TABLE_CALL(drop_table_share) +#else +#define MYSQL_UNBIND_TABLE(handler) do { } while(0) + +#define PSI_CALL_unbind_table(A1) do { } while(0) +#define PSI_CALL_rebind_table(A1,A2,A3) NULL +#define PSI_CALL_close_table(A1,A2) do { } while(0) +#define PSI_CALL_open_table(A1,A2) NULL +#define PSI_CALL_get_table_share(A1,A2) NULL +#define PSI_CALL_release_table_share(A1) do { } while(0) +#define PSI_CALL_drop_table_share(A1,A2,A3,A4,A5) do { } while(0) +#endif + +/** + @def MYSQL_TABLE_WAIT_VARIABLES + Instrumentation helper for table waits. + This instrumentation declares local variables. + Do not use a ';' after this macro + @param LOCKER the locker + @param STATE the locker state + @sa MYSQL_START_TABLE_IO_WAIT. + @sa MYSQL_END_TABLE_IO_WAIT. + @sa MYSQL_START_TABLE_LOCK_WAIT. + @sa MYSQL_END_TABLE_LOCK_WAIT. +*/ +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) \ + struct PSI_table_locker* LOCKER; \ + PSI_table_locker_state STATE; +#else + #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) +#endif + +/** + @def MYSQL_START_TABLE_LOCK_WAIT + Instrumentation helper for table lock waits. + This instrumentation marks the start of a wait event. + @param LOCKER the locker + @param STATE the locker state + @param PSI the instrumented table + @param OP the table operation to be performed + @param FLAGS per table operation flags. + @sa MYSQL_END_TABLE_LOCK_WAIT. +*/ +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ + LOCKER= inline_mysql_start_table_lock_wait(STATE, PSI, \ + OP, FLAGS, __FILE__, __LINE__) +#else + #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ + do {} while (0) +#endif + +/** + @def MYSQL_END_TABLE_LOCK_WAIT + Instrumentation helper for table lock waits. + This instrumentation marks the end of a wait event. + @param LOCKER the locker + @sa MYSQL_START_TABLE_LOCK_WAIT. +*/ +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ + inline_mysql_end_table_lock_wait(LOCKER) +#else + #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_UNLOCK_TABLE(T) \ + inline_mysql_unlock_table(T) +#else + #define MYSQL_UNLOCK_TABLE(T) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TABLE_INTERFACE +/** + Instrumentation calls for MYSQL_START_TABLE_LOCK_WAIT. + @sa MYSQL_END_TABLE_LOCK_WAIT. +*/ +static inline struct PSI_table_locker * +inline_mysql_start_table_lock_wait(PSI_table_locker_state *state, + struct PSI_table *psi, + enum PSI_table_lock_operation op, + ulong flags, const char *src_file, uint src_line) +{ + if (psi_likely(psi != NULL)) + { + struct PSI_table_locker *locker; + locker= PSI_TABLE_CALL(start_table_lock_wait) + (state, psi, op, flags, src_file, src_line); + return locker; + } + return NULL; +} + +/** + Instrumentation calls for MYSQL_END_TABLE_LOCK_WAIT. + @sa MYSQL_START_TABLE_LOCK_WAIT. +*/ +static inline void +inline_mysql_end_table_lock_wait(struct PSI_table_locker *locker) +{ + if (psi_likely(locker != NULL)) + PSI_TABLE_CALL(end_table_lock_wait)(locker); +} + +static inline void +inline_mysql_unlock_table(struct PSI_table *table) +{ + if (table != NULL) + PSI_TABLE_CALL(unlock_table)(table); +} +#endif + +/** @} (end of group Table_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_thread.h b/include/mysql/psi/mysql_thread.h new file mode 100644 index 00000000..11cf3548 --- /dev/null +++ b/include/mysql/psi/mysql_thread.h @@ -0,0 +1,1172 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + Copyright (c) 2020, 2021, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_THREAD_H +#define MYSQL_THREAD_H + +/** + @file mysql/psi/mysql_thread.h + Instrumentation helpers for mysys threads, mutexes, + read write locks and conditions. + This header file provides the necessary declarations + to use the mysys thread API with the performance schema instrumentation. + In some compilers (SunStudio), 'static inline' functions, when declared + but not used, are not optimized away (because they are unused) by default, + so that including a static inline function from a header file does + create unwanted dependencies, causing unresolved symbols at link time. + Other compilers, like gcc, optimize these dependencies by default. + + Since the instrumented APIs declared here are wrapper on top + of my_pthread / safemutex / etc APIs, + including mysql/psi/mysql_thread.h assumes that + the dependency on my_pthread and safemutex already exists. +*/ +/* + Note: there are several orthogonal dimensions here. + + Dimension 1: Instrumentation + HAVE_PSI_INTERFACE is defined when the instrumentation is compiled in. + This may happen both in debug or production builds. + + Dimension 2: Debug + SAFE_MUTEX is defined when debug is compiled in. + This may happen both with and without instrumentation. + + Dimension 3: Platform + Mutexes are implemented with one of: + - the pthread library + - fast mutexes + - window apis + This is implemented by various macro definitions in my_pthread.h + + This causes complexity with '#ifdef'-ery that can't be avoided. +*/ + +#include "mysql/psi/psi.h" +#ifdef MYSQL_SERVER +#ifndef MYSQL_DYNAMIC_PLUGIN +#include "pfs_thread_provider.h" +#endif +#endif + +#ifndef PSI_MUTEX_CALL +#define PSI_MUTEX_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_RWLOCK_CALL +#define PSI_RWLOCK_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_COND_CALL +#define PSI_COND_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_THREAD_CALL +#define PSI_THREAD_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Thread_instrumentation Thread Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +#ifdef HAVE_PSI_THREAD_INTERFACE +#define PSI_CALL_delete_current_thread PSI_THREAD_CALL(delete_current_thread) +#define PSI_CALL_get_thread PSI_THREAD_CALL(get_thread) +#define PSI_CALL_new_thread PSI_THREAD_CALL(new_thread) +#define PSI_CALL_register_thread PSI_THREAD_CALL(register_thread) +#define PSI_CALL_set_thread PSI_THREAD_CALL(set_thread) +#define PSI_CALL_set_thread_THD PSI_THREAD_CALL(set_thread_THD) +#define PSI_CALL_set_thread_connect_attrs PSI_THREAD_CALL(set_thread_connect_attrs) +#define PSI_CALL_set_thread_db PSI_THREAD_CALL(set_thread_db) +#define PSI_CALL_set_thread_id PSI_THREAD_CALL(set_thread_id) +#define PSI_CALL_set_thread_os_id PSI_THREAD_CALL(set_thread_os_id) +#define PSI_CALL_set_thread_info PSI_THREAD_CALL(set_thread_info) +#define PSI_CALL_set_thread_start_time PSI_THREAD_CALL(set_thread_start_time) +#define PSI_CALL_set_thread_account PSI_THREAD_CALL(set_thread_account) +#define PSI_CALL_spawn_thread PSI_THREAD_CALL(spawn_thread) +#define PSI_CALL_set_connection_type PSI_THREAD_CALL(set_connection_type) +#else +#define PSI_CALL_delete_current_thread() do { } while(0) +#define PSI_CALL_get_thread() NULL +#define PSI_CALL_new_thread(A1,A2,A3) NULL +#define PSI_CALL_register_thread(A1,A2,A3) do { } while(0) +#define PSI_CALL_set_thread(A1) do { } while(0) +#define PSI_CALL_set_thread_THD(A1,A2) do { } while(0) +#define PSI_CALL_set_thread_connect_attrs(A1,A2,A3) 0 +#define PSI_CALL_set_thread_db(A1,A2) do { } while(0) +#define PSI_CALL_set_thread_id(A1,A2) do { } while(0) +#define PSI_CALL_set_thread_os_id(A1) do { } while(0) +#define PSI_CALL_set_thread_info(A1, A2) do { } while(0) +#define PSI_CALL_set_thread_start_time(A1) do { } while(0) +#define PSI_CALL_set_thread_account(A1, A2, A3, A4) do { } while(0) +#define PSI_CALL_spawn_thread(A1, A2, A3, A4, A5) 0 +#define PSI_CALL_set_connection_type(A) do { } while(0) +#endif + + +/** + An instrumented mutex structure. + @sa mysql_mutex_t +*/ +struct st_mysql_mutex +{ + /** The real mutex. */ +#ifdef SAFE_MUTEX + safe_mutex_t m_mutex; +#else + pthread_mutex_t m_mutex; +#endif + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_mutex_t interface. + */ + struct PSI_mutex *m_psi; +}; + +/** + Type of an instrumented mutex. + @c mysql_mutex_t is a drop-in replacement for @c pthread_mutex_t. + @sa mysql_mutex_assert_owner + @sa mysql_mutex_assert_not_owner + @sa mysql_mutex_init + @sa mysql_mutex_lock + @sa mysql_mutex_unlock + @sa mysql_mutex_destroy +*/ +typedef struct st_mysql_mutex mysql_mutex_t; + +/** + An instrumented rwlock structure. + @sa mysql_rwlock_t +*/ +struct st_mysql_rwlock +{ + /** The real rwlock */ + rw_lock_t m_rwlock; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_rwlock_t interface. + */ + struct PSI_rwlock *m_psi; +}; + +/** + An instrumented prlock structure. + @sa mysql_prlock_t +*/ +struct st_mysql_prlock +{ + /** The real prlock */ + rw_pr_lock_t m_prlock; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_rwlock_t interface. + */ + struct PSI_rwlock *m_psi; +}; + +/** + Type of an instrumented rwlock. + @c mysql_rwlock_t is a drop-in replacement for @c pthread_rwlock_t. + @sa mysql_rwlock_init + @sa mysql_rwlock_rdlock + @sa mysql_rwlock_tryrdlock + @sa mysql_rwlock_wrlock + @sa mysql_rwlock_trywrlock + @sa mysql_rwlock_unlock + @sa mysql_rwlock_destroy +*/ +typedef struct st_mysql_rwlock mysql_rwlock_t; + +/** + Type of an instrumented prlock. + A prlock is a read write lock that 'prefers readers' (pr). + @c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t. + @sa mysql_prlock_init + @sa mysql_prlock_rdlock + @sa mysql_prlock_wrlock + @sa mysql_prlock_unlock + @sa mysql_prlock_destroy +*/ +typedef struct st_mysql_prlock mysql_prlock_t; + +/** + An instrumented cond structure. + @sa mysql_cond_t +*/ +struct st_mysql_cond +{ + /** The real condition */ + pthread_cond_t m_cond; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_cond_t interface. + */ + struct PSI_cond *m_psi; +}; + +/** + Type of an instrumented condition. + @c mysql_cond_t is a drop-in replacement for @c pthread_cond_t. + @sa mysql_cond_init + @sa mysql_cond_wait + @sa mysql_cond_timedwait + @sa mysql_cond_signal + @sa mysql_cond_broadcast + @sa mysql_cond_destroy +*/ +typedef struct st_mysql_cond mysql_cond_t; + +/* + Consider the following code: + static inline void foo() { bar(); } + when foo() is never called. + + With gcc, foo() is a local static function, so the dependencies + are optimized away at compile time, and there is no dependency on bar(). + With other compilers (HP, Sun Studio), the function foo() implementation + is compiled, and bar() needs to be present to link. + + Due to the existing header dependencies in MySQL code, this header file + is sometime used when it is not needed, which in turn cause link failures + on some platforms. + The proper fix would be to cut these extra dependencies in the calling code. + DISABLE_MYSQL_THREAD_H is a work around to limit dependencies. + DISABLE_MYSQL_PRLOCK_H is similar, and is used to disable specifically + the prlock wrappers. +*/ +#ifndef DISABLE_MYSQL_THREAD_H + +#define mysql_mutex_is_owner(M) safe_mutex_is_owner(&(M)->m_mutex) +/** + @def mysql_mutex_assert_owner(M) + Wrapper, to use safe_mutex_assert_owner with instrumented mutexes. + @c mysql_mutex_assert_owner is a drop-in replacement + for @c safe_mutex_assert_owner. +*/ +#define mysql_mutex_assert_owner(M) \ + safe_mutex_assert_owner(&(M)->m_mutex) + +/** + @def mysql_mutex_assert_not_owner(M) + Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes. + @c mysql_mutex_assert_not_owner is a drop-in replacement + for @c safe_mutex_assert_not_owner. +*/ +#define mysql_mutex_assert_not_owner(M) \ + safe_mutex_assert_not_owner(&(M)->m_mutex) + +#define mysql_mutex_setflags(M, F) \ + safe_mutex_setflags(&(M)->m_mutex, (F)) + +/** + @def mysql_prlock_assert_write_owner(M) + Drop-in replacement + for @c rw_pr_lock_assert_write_owner. +*/ +#define mysql_prlock_assert_write_owner(M) \ + rw_pr_lock_assert_write_owner(&(M)->m_prlock) + +/** + @def mysql_prlock_assert_not_write_owner(M) + Drop-in replacement + for @c rw_pr_lock_assert_not_write_owner. +*/ +#define mysql_prlock_assert_not_write_owner(M) \ + rw_pr_lock_assert_not_write_owner(&(M)->m_prlock) + +/** + @def mysql_mutex_register(P1, P2, P3) + Mutex registration. +*/ +#define mysql_mutex_register(P1, P2, P3) \ + inline_mysql_mutex_register(P1, P2, P3) + +/** + @def mysql_mutex_init(K, M, A) + Instrumented mutex_init. + @c mysql_mutex_init is a replacement for @c pthread_mutex_init. + @param K The PSI_mutex_key for this instrumented mutex + @param M The mutex to initialize + @param A Mutex attributes +*/ + +#ifdef HAVE_PSI_MUTEX_INTERFACE + #ifdef SAFE_MUTEX + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(K, M, A, #M, __FILE__, __LINE__) + #else + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(K, M, A) + #endif +#else + #ifdef SAFE_MUTEX + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(M, A, #M, __FILE__, __LINE__) + #else + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(M, A) + #endif +#endif + +/** + @def mysql_mutex_destroy(M) + Instrumented mutex_destroy. + @c mysql_mutex_destroy is a drop-in replacement + for @c pthread_mutex_destroy. +*/ +#ifdef SAFE_MUTEX + #define mysql_mutex_destroy(M) \ + inline_mysql_mutex_destroy(M, __FILE__, __LINE__) +#else + #define mysql_mutex_destroy(M) \ + inline_mysql_mutex_destroy(M) +#endif + +/** + @def mysql_mutex_lock(M) + Instrumented mutex_lock. + @c mysql_mutex_lock is a drop-in replacement for @c pthread_mutex_lock. + @param M The mutex to lock +*/ + +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + #define mysql_mutex_lock(M) \ + inline_mysql_mutex_lock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_lock(M) \ + inline_mysql_mutex_lock(M) +#endif + +/** + @def mysql_mutex_trylock(M) + Instrumented mutex_lock. + @c mysql_mutex_trylock is a drop-in replacement + for @c pthread_mutex_trylock. +*/ + +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + #define mysql_mutex_trylock(M) \ + inline_mysql_mutex_trylock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_trylock(M) \ + inline_mysql_mutex_trylock(M) +#endif + +/** + @def mysql_mutex_unlock(M) + Instrumented mutex_unlock. + @c mysql_mutex_unlock is a drop-in replacement for @c pthread_mutex_unlock. +*/ +#ifdef SAFE_MUTEX + #define mysql_mutex_unlock(M) \ + inline_mysql_mutex_unlock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_unlock(M) \ + inline_mysql_mutex_unlock(M) +#endif + +/** + @def mysql_rwlock_register(P1, P2, P3) + Rwlock registration. +*/ +#define mysql_rwlock_register(P1, P2, P3) \ + inline_mysql_rwlock_register(P1, P2, P3) + +/** + @def mysql_rwlock_init(K, RW) + Instrumented rwlock_init. + @c mysql_rwlock_init is a replacement for @c pthread_rwlock_init. + Note that pthread_rwlockattr_t is not supported in MySQL. + @param K The PSI_rwlock_key for this instrumented rwlock + @param RW The rwlock to initialize +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(K, RW) +#else + #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(RW) +#endif + +/** + @def mysql_prlock_init(K, RW) + Instrumented rw_pr_init. + @c mysql_prlock_init is a replacement for @c rw_pr_init. + @param K The PSI_rwlock_key for this instrumented prlock + @param RW The prlock to initialize +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(K, RW) +#else + #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(RW) +#endif + +/** + @def mysql_rwlock_destroy(RW) + Instrumented rwlock_destroy. + @c mysql_rwlock_destroy is a drop-in replacement + for @c pthread_rwlock_destroy. +*/ +#define mysql_rwlock_destroy(RW) inline_mysql_rwlock_destroy(RW) + +/** + @def mysql_prlock_destroy(RW) + Instrumented rw_pr_destroy. + @c mysql_prlock_destroy is a drop-in replacement + for @c rw_pr_destroy. +*/ +#define mysql_prlock_destroy(RW) inline_mysql_prlock_destroy(RW) + +/** + @def mysql_rwlock_rdlock(RW) + Instrumented rwlock_rdlock. + @c mysql_rwlock_rdlock is a drop-in replacement + for @c pthread_rwlock_rdlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_rdlock(RW) \ + inline_mysql_rwlock_rdlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_rdlock(RW) \ + inline_mysql_rwlock_rdlock(RW) +#endif + +/** + @def mysql_prlock_rdlock(RW) + Instrumented rw_pr_rdlock. + @c mysql_prlock_rdlock is a drop-in replacement + for @c rw_pr_rdlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_prlock_rdlock(RW) \ + inline_mysql_prlock_rdlock(RW, __FILE__, __LINE__) +#else + #define mysql_prlock_rdlock(RW) \ + inline_mysql_prlock_rdlock(RW) +#endif + +/** + @def mysql_rwlock_wrlock(RW) + Instrumented rwlock_wrlock. + @c mysql_rwlock_wrlock is a drop-in replacement + for @c pthread_rwlock_wrlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_wrlock(RW) \ + inline_mysql_rwlock_wrlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_wrlock(RW) \ + inline_mysql_rwlock_wrlock(RW) +#endif + +/** + @def mysql_prlock_wrlock(RW) + Instrumented rw_pr_wrlock. + @c mysql_prlock_wrlock is a drop-in replacement + for @c rw_pr_wrlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_prlock_wrlock(RW) \ + inline_mysql_prlock_wrlock(RW, __FILE__, __LINE__) +#else + #define mysql_prlock_wrlock(RW) \ + inline_mysql_prlock_wrlock(RW) +#endif + +/** + @def mysql_rwlock_tryrdlock(RW) + Instrumented rwlock_tryrdlock. + @c mysql_rwlock_tryrdlock is a drop-in replacement + for @c pthread_rwlock_tryrdlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_tryrdlock(RW) \ + inline_mysql_rwlock_tryrdlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_tryrdlock(RW) \ + inline_mysql_rwlock_tryrdlock(RW) +#endif + +/** + @def mysql_rwlock_trywrlock(RW) + Instrumented rwlock_trywrlock. + @c mysql_rwlock_trywrlock is a drop-in replacement + for @c pthread_rwlock_trywrlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_trywrlock(RW) \ + inline_mysql_rwlock_trywrlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_trywrlock(RW) \ + inline_mysql_rwlock_trywrlock(RW) +#endif + +/** + @def mysql_rwlock_unlock(RW) + Instrumented rwlock_unlock. + @c mysql_rwlock_unlock is a drop-in replacement + for @c pthread_rwlock_unlock. +*/ +#define mysql_rwlock_unlock(RW) inline_mysql_rwlock_unlock(RW) + +/** + @def mysql_prlock_unlock(RW) + Instrumented rw_pr_unlock. + @c mysql_prlock_unlock is a drop-in replacement + for @c rw_pr_unlock. +*/ +#define mysql_prlock_unlock(RW) inline_mysql_prlock_unlock(RW) + +/** + @def mysql_cond_register(P1, P2, P3) + Cond registration. +*/ +#define mysql_cond_register(P1, P2, P3) \ + inline_mysql_cond_register(P1, P2, P3) + +/** + @def mysql_cond_init(K, C, A) + Instrumented cond_init. + @c mysql_cond_init is a replacement for @c pthread_cond_init. + @param C The cond to initialize + @param K The PSI_cond_key for this instrumented cond + @param A Condition attributes +*/ +#ifdef HAVE_PSI_COND_INTERFACE + #define mysql_cond_init(K, C, A) inline_mysql_cond_init(K, C, A) +#else + #define mysql_cond_init(K, C, A) inline_mysql_cond_init(C, A) +#endif + +/** + @def mysql_cond_destroy(C) + Instrumented cond_destroy. + @c mysql_cond_destroy is a drop-in replacement for @c pthread_cond_destroy. +*/ +#define mysql_cond_destroy(C) inline_mysql_cond_destroy(C) + +/** + @def mysql_cond_wait(C) + Instrumented cond_wait. + @c mysql_cond_wait is a drop-in replacement for @c pthread_cond_wait. +*/ +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + #define mysql_cond_wait(C, M) \ + inline_mysql_cond_wait(C, M, __FILE__, __LINE__) +#else + #define mysql_cond_wait(C, M) \ + inline_mysql_cond_wait(C, M) +#endif + +/** + @def mysql_cond_timedwait(C, M, W) + Instrumented cond_timedwait. + @c mysql_cond_timedwait is a drop-in replacement + for @c pthread_cond_timedwait. +*/ +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + #define mysql_cond_timedwait(C, M, W) \ + inline_mysql_cond_timedwait(C, M, W, __FILE__, __LINE__) +#else + #define mysql_cond_timedwait(C, M, W) \ + inline_mysql_cond_timedwait(C, M, W) +#endif + +/** + @def mysql_cond_signal(C) + Instrumented cond_signal. + @c mysql_cond_signal is a drop-in replacement for @c pthread_cond_signal. +*/ +#define mysql_cond_signal(C) inline_mysql_cond_signal(C) + +/** + @def mysql_cond_broadcast(C) + Instrumented cond_broadcast. + @c mysql_cond_broadcast is a drop-in replacement + for @c pthread_cond_broadcast. +*/ +#define mysql_cond_broadcast(C) inline_mysql_cond_broadcast(C) + +/** + @def mysql_thread_register(P1, P2, P3) + Thread registration. +*/ +#define mysql_thread_register(P1, P2, P3) \ + inline_mysql_thread_register(P1, P2, P3) + +/** + @def mysql_thread_create(K, P1, P2, P3, P4) + Instrumented pthread_create. + This function creates both the thread instrumentation and a thread. + @c mysql_thread_create is a replacement for @c pthread_create. + The parameter P4 (or, if it is NULL, P1) will be used as the + instrumented thread "identity". + Providing a P1 / P4 parameter with a different value for each call + will on average improve performances, since this thread identity value + is used internally to randomize access to data and prevent contention. + This is optional, and the improvement is not guaranteed, only statistical. + @param K The PSI_thread_key for this instrumented thread + @param P1 pthread_create parameter 1 + @param P2 pthread_create parameter 2 + @param P3 pthread_create parameter 3 + @param P4 pthread_create parameter 4 +*/ +#ifdef HAVE_PSI_THREAD_INTERFACE + #define mysql_thread_create(K, P1, P2, P3, P4) \ + inline_mysql_thread_create(K, P1, P2, P3, P4) +#else + #define mysql_thread_create(K, P1, P2, P3, P4) \ + pthread_create(P1, P2, P3, P4) +#endif + +/** + @def mysql_thread_set_psi_id(I) + Set the thread identifier for the instrumentation. + @param I The thread identifier +*/ +#ifdef HAVE_PSI_THREAD_INTERFACE + #define mysql_thread_set_psi_id(I) inline_mysql_thread_set_psi_id(I) +#else + #define mysql_thread_set_psi_id(I) do {} while (0) +#endif + +/** + @def mysql_thread_set_psi_THD(T) + Set the thread sql session for the instrumentation. + @param I The thread identifier +*/ +#ifdef HAVE_PSI_THREAD_INTERFACE + #define mysql_thread_set_psi_THD(T) inline_mysql_thread_set_psi_THD(T) +#else + #define mysql_thread_set_psi_THD(T) do {} while (0) +#endif + +static inline void inline_mysql_mutex_register( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char *category, + PSI_mutex_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + PSI_MUTEX_CALL(register_mutex)(category, info, count); +#endif +} + +static inline int inline_mysql_mutex_init( +#ifdef HAVE_PSI_MUTEX_INTERFACE + PSI_mutex_key key, +#endif + mysql_mutex_t *that, + const pthread_mutexattr_t *attr +#ifdef SAFE_MUTEX + , const char *src_name, const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + that->m_psi= PSI_MUTEX_CALL(init_mutex)(key, &that->m_mutex); +#else + that->m_psi= NULL; +#endif +#ifdef SAFE_MUTEX + return safe_mutex_init(&that->m_mutex, attr, src_name, src_file, src_line); +#else + return pthread_mutex_init(&that->m_mutex, attr); +#endif +} + +static inline int inline_mysql_mutex_destroy( + mysql_mutex_t *that +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (that->m_psi != NULL) + { + PSI_MUTEX_CALL(destroy_mutex)(that->m_psi); + that->m_psi= NULL; + } +#endif +#ifdef SAFE_MUTEX + return safe_mutex_destroy(&that->m_mutex, src_file, src_line); +#else + return pthread_mutex_destroy(&that->m_mutex); +#endif +} + +#ifdef HAVE_PSI_MUTEX_INTERFACE +ATTRIBUTE_COLD int psi_mutex_lock(mysql_mutex_t *that, + const char *file, uint line); +ATTRIBUTE_COLD int psi_mutex_trylock(mysql_mutex_t *that, + const char *file, uint line); +#endif + +static inline int inline_mysql_mutex_lock( + mysql_mutex_t *that +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_mutex_lock(that, src_file, src_line); +#endif + /* Non instrumented code */ +#ifdef SAFE_MUTEX + return safe_mutex_lock(&that->m_mutex, FALSE, src_file, src_line); +#else + return pthread_mutex_lock(&that->m_mutex); +#endif +} + +static inline int inline_mysql_mutex_trylock( + mysql_mutex_t *that +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_mutex_trylock(that, src_file, src_line); +#endif + /* Non instrumented code */ +#ifdef SAFE_MUTEX + return safe_mutex_lock(&that->m_mutex, TRUE, src_file, src_line); +#else + return pthread_mutex_trylock(&that->m_mutex); +#endif +} + +static inline int inline_mysql_mutex_unlock( + mysql_mutex_t *that +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ + int result; + +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_MUTEX_CALL(unlock_mutex)(that->m_psi); +#endif + +#ifdef SAFE_MUTEX + result= safe_mutex_unlock(&that->m_mutex, src_file, src_line); +#else + result= pthread_mutex_unlock(&that->m_mutex); +#endif + + return result; +} + +static inline void inline_mysql_rwlock_register( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char *category, + PSI_rwlock_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + PSI_RWLOCK_CALL(register_rwlock)(category, info, count); +#endif +} + +static inline int inline_mysql_rwlock_init( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + PSI_rwlock_key key, +#endif + mysql_rwlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_rwlock); +#else + that->m_psi= NULL; +#endif + /* + pthread_rwlockattr_t is not used in MySQL. + */ + return my_rwlock_init(&that->m_rwlock, NULL); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_init( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + PSI_rwlock_key key, +#endif + mysql_prlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_prlock); +#else + that->m_psi= NULL; +#endif + return rw_pr_init(&that->m_prlock); +} +#endif + +static inline int inline_mysql_rwlock_destroy( + mysql_rwlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + { + PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi); + that->m_psi= NULL; + } +#endif + return rwlock_destroy(&that->m_rwlock); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_destroy( + mysql_prlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + { + PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi); + that->m_psi= NULL; + } +#endif + return rw_pr_destroy(&that->m_prlock); +} +#endif + +#ifdef HAVE_PSI_RWLOCK_INTERFACE +ATTRIBUTE_COLD +int psi_rwlock_rdlock(mysql_rwlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_rwlock_tryrdlock(mysql_rwlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_rwlock_wrlock(mysql_rwlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_rwlock_trywrlock(mysql_rwlock_t *that, const char *file, uint line); +# ifndef DISABLE_MYSQL_PRLOCK_H +ATTRIBUTE_COLD +int psi_prlock_rdlock(mysql_prlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_prlock_wrlock(mysql_prlock_t *that, const char *file, uint line); +# endif +#endif + +static inline int inline_mysql_rwlock_rdlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_rdlock(that, src_file, src_line); +#endif + return rw_rdlock(&that->m_rwlock); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_rdlock( + mysql_prlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_prlock_rdlock(that, src_file, src_line); +#endif + return rw_pr_rdlock(&that->m_prlock); +} +#endif + +static inline int inline_mysql_rwlock_wrlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_wrlock(that, src_file, src_line); +#endif + return rw_wrlock(&that->m_rwlock); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_wrlock( + mysql_prlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_prlock_wrlock(that, src_file, src_line); +#endif + return rw_pr_wrlock(&that->m_prlock); +} +#endif + +static inline int inline_mysql_rwlock_tryrdlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_tryrdlock(that, src_file, src_line); +#endif + return rw_tryrdlock(&that->m_rwlock); +} + +static inline int inline_mysql_rwlock_trywrlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_trywrlock(that, src_file, src_line); +#endif + return rw_trywrlock(&that->m_rwlock); +} + +static inline int inline_mysql_rwlock_unlock( + mysql_rwlock_t *that) +{ + int result; +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi); +#endif + result= rw_unlock(&that->m_rwlock); + return result; +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_unlock( + mysql_prlock_t *that) +{ + int result; +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi); +#endif + result= rw_pr_unlock(&that->m_prlock); + return result; +} +#endif + +static inline void inline_mysql_cond_register( +#ifdef HAVE_PSI_COND_INTERFACE + const char *category, + PSI_cond_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_COND_INTERFACE + PSI_COND_CALL(register_cond)(category, info, count); +#endif +} + +static inline int inline_mysql_cond_init( +#ifdef HAVE_PSI_COND_INTERFACE + PSI_cond_key key, +#endif + mysql_cond_t *that, + const pthread_condattr_t *attr) +{ +#ifdef HAVE_PSI_COND_INTERFACE + that->m_psi= PSI_COND_CALL(init_cond)(key, &that->m_cond); +#else + that->m_psi= NULL; +#endif + return pthread_cond_init(&that->m_cond, attr); +} + +static inline int inline_mysql_cond_destroy( + mysql_cond_t *that) +{ +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + { + PSI_COND_CALL(destroy_cond)(that->m_psi); + that->m_psi= NULL; + } +#endif + return pthread_cond_destroy(&that->m_cond); +} + +#ifdef HAVE_PSI_COND_INTERFACE +ATTRIBUTE_COLD int psi_cond_wait(mysql_cond_t *that, mysql_mutex_t *mutex, + const char *file, uint line); +ATTRIBUTE_COLD int psi_cond_timedwait(mysql_cond_t *that, mysql_mutex_t *mutex, + const struct timespec *abstime, + const char *file, uint line); +#endif + +static inline int inline_mysql_cond_wait( + mysql_cond_t *that, + mysql_mutex_t *mutex +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_cond_wait(that, mutex, src_file, src_line); +#endif + return my_cond_wait(&that->m_cond, &mutex->m_mutex); +} + +static inline int inline_mysql_cond_timedwait( + mysql_cond_t *that, + mysql_mutex_t *mutex, + const struct timespec *abstime +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_cond_timedwait(that, mutex, abstime, src_file, src_line); +#endif + return my_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime); +} + +static inline int inline_mysql_cond_signal( + mysql_cond_t *that) +{ + int result; +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_COND_CALL(signal_cond)(that->m_psi); +#endif + result= pthread_cond_signal(&that->m_cond); + return result; +} + +static inline int inline_mysql_cond_broadcast( + mysql_cond_t *that) +{ + int result; +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_COND_CALL(broadcast_cond)(that->m_psi); +#endif + result= pthread_cond_broadcast(&that->m_cond); + return result; +} + +static inline void inline_mysql_thread_register( +#ifdef HAVE_PSI_THREAD_INTERFACE + const char *category, + PSI_thread_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_THREAD_CALL(register_thread)(category, info, count); +#endif +} + +#ifdef HAVE_PSI_THREAD_INTERFACE +static inline int inline_mysql_thread_create( + PSI_thread_key key, + pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg) +{ + int result; + result= PSI_THREAD_CALL(spawn_thread)(key, thread, attr, start_routine, arg); + return result; +} + +static inline void inline_mysql_thread_set_psi_id(my_thread_id id) +{ + struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); + PSI_THREAD_CALL(set_thread_id)(psi, id); +} + +#ifdef __cplusplus +class THD; +static inline void inline_mysql_thread_set_psi_THD(THD *thd) +{ + struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); + PSI_THREAD_CALL(set_thread_THD)(psi, thd); +} +#endif /* __cplusplus */ + +static inline void mysql_thread_set_peer_port(uint port __attribute__ ((unused))) { +#ifdef HAVE_PSI_THREAD_INTERFACE + struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)(); + PSI_THREAD_CALL(set_thread_peer_port)(psi, port); +#endif +} + +#endif + +#endif /* DISABLE_MYSQL_THREAD_H */ + +/** @} (end of group Thread_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_transaction.h b/include/mysql/psi/mysql_transaction.h new file mode 100644 index 00000000..a4444804 --- /dev/null +++ b/include/mysql/psi/mysql_transaction.h @@ -0,0 +1,220 @@ +/* Copyright (c) 2013, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MYSQL_TRANSACTION_H +#define MYSQL_TRANSACTION_H + +/** + @file mysql/psi/mysql_transaction.h + Instrumentation helpers for transactions. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_TRANSACTION_CALL +#define PSI_TRANSACTION_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Transaction_instrumentation Transaction Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_START_TRANSACTION(STATE, XID, TRXID, ISO, RO, AC) \ + inline_mysql_start_transaction(STATE, XID, TRXID, ISO, RO, AC, __FILE__, __LINE__) +#else + #define MYSQL_START_TRANSACTION(STATE, XID, TRXID, ISO, RO, AC) \ + 0 +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_GTID(LOCKER, P1, P2) \ + inline_mysql_set_transaction_gtid(LOCKER, P1, P2) +#else + #define MYSQL_SET_TRANSACTION_GTID(LOCKER, P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_XID(LOCKER, P1, P2) \ + inline_mysql_set_transaction_xid(LOCKER, P1, P2) +#else + #define MYSQL_SET_TRANSACTION_XID(LOCKER, P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_XA_STATE(LOCKER, P1) \ + inline_mysql_set_transaction_xa_state(LOCKER, P1) +#else + #define MYSQL_SET_TRANSACTION_XA_STATE(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_TRXID(LOCKER, P1) \ + inline_mysql_set_transaction_trxid(LOCKER, P1) +#else + #define MYSQL_SET_TRANSACTION_TRXID(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_INC_TRANSACTION_SAVEPOINTS(LOCKER, P1) \ + inline_mysql_inc_transaction_savepoints(LOCKER, P1) +#else + #define MYSQL_INC_TRANSACTION_SAVEPOINTS(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(LOCKER, P1) \ + inline_mysql_inc_transaction_rollback_to_savepoint(LOCKER, P1) +#else + #define MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(LOCKER, P1) \ + inline_mysql_inc_transaction_release_savepoint(LOCKER, P1) +#else + #define MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_ROLLBACK_TRANSACTION(LOCKER) \ + inline_mysql_rollback_transaction(LOCKER) +#else + #define MYSQL_ROLLBACK_TRANSACTION(LOCKER) \ + do { } while(0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_COMMIT_TRANSACTION(LOCKER) \ + inline_mysql_commit_transaction(LOCKER) +#else + #define MYSQL_COMMIT_TRANSACTION(LOCKER) \ + do { } while(0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE +static inline struct PSI_transaction_locker * +inline_mysql_start_transaction(PSI_transaction_locker_state *state, + const void *xid, + ulonglong trxid, + int isolation_level, + my_bool read_only, + my_bool autocommit, + const char *src_file, int src_line) +{ + PSI_transaction_locker *locker; + locker= PSI_TRANSACTION_CALL(get_thread_transaction_locker)(state, + xid, trxid, + isolation_level, + read_only, + autocommit); + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(start_transaction)(locker, src_file, src_line); + return locker; +} + +static inline void +inline_mysql_set_transaction_gtid(PSI_transaction_locker *locker, + const void *sid, + const void *gtid_spec) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_gtid)(locker, sid, gtid_spec); +} + +static inline void +inline_mysql_set_transaction_xid(PSI_transaction_locker *locker, + const void *xid, + int xa_state) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_xid)(locker, xid, xa_state); +} + +static inline void +inline_mysql_set_transaction_xa_state(PSI_transaction_locker *locker, + int xa_state) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_xa_state)(locker, xa_state); +} + +static inline void +inline_mysql_set_transaction_trxid(PSI_transaction_locker *locker, + const ulonglong *trxid) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_trxid)(locker, trxid); +} + +static inline void +inline_mysql_inc_transaction_savepoints(PSI_transaction_locker *locker, + ulong count) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(inc_transaction_savepoints)(locker, count); +} + +static inline void +inline_mysql_inc_transaction_rollback_to_savepoint(PSI_transaction_locker *locker, + ulong count) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(inc_transaction_rollback_to_savepoint)(locker, count); +} + +static inline void +inline_mysql_inc_transaction_release_savepoint(PSI_transaction_locker *locker, + ulong count) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(inc_transaction_release_savepoint)(locker, count); +} + +static inline void +inline_mysql_rollback_transaction(struct PSI_transaction_locker *locker) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(end_transaction)(locker, false); +} + +static inline void +inline_mysql_commit_transaction(struct PSI_transaction_locker *locker) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(end_transaction)(locker, true); +} +#endif + +/** @} (end of group Transaction_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/psi.h b/include/mysql/psi/psi.h new file mode 100644 index 00000000..702d31fa --- /dev/null +++ b/include/mysql/psi/psi.h @@ -0,0 +1,3039 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H +#define MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H + +#ifndef MY_GLOBAL_INCLUDED +/* + Make sure a .c or .cc file contains an include to my_global.h first. + When this include is missing, all the #ifdef HAVE_XXX have no effect, + and the resulting binary won't build, or won't link, + or will crash at runtime + since various structures will have different binary definitions. +*/ +#error "You must include my_global.h in the code for the build to be correct." +#endif + +/* + If PSI_ON_BY_DFAULT is defined, assume PSI will be enabled by default and + optimize jumps testing for PSI this case. If not, optimize the binary for + that PSI is not enabled +*/ + +#ifdef PSI_ON_BY_DEFAULT +#define psi_likely(A) likely(A) +#define psi_unlikely(A) unlikely(A) +#else +#define psi_likely(A) unlikely(A) +#define psi_unlikely(A) likely(A) +#endif + +#include "psi_base.h" +#include "psi_memory.h" + +#ifdef _WIN32 +typedef struct thread_attr pthread_attr_t; +typedef DWORD pthread_t; +typedef DWORD pthread_key_t; +#endif + +/* + MAINTAINER: + The following pattern: + typedef struct XYZ XYZ; + is not needed in C++, but required for C. +*/ + +C_MODE_START + +/** @sa MDL_key. */ +struct MDL_key; +typedef struct MDL_key MDL_key; + +/** @sa enum_mdl_type. */ +typedef int opaque_mdl_type; + +/** @sa enum_mdl_duration. */ +typedef int opaque_mdl_duration; + +/** @sa MDL_wait::enum_wait_status. */ +typedef int opaque_mdl_status; + +/** @sa enum_vio_type. */ +typedef int opaque_vio_type; + +struct TABLE_SHARE; + +struct sql_digest_storage; + +#ifdef __cplusplus + class THD; +#else + /* + Phony declaration when compiling C code. + This is ok, because the C code will never have a THD anyway. + */ + struct opaque_THD + { + int dummy; + }; + typedef struct opaque_THD THD; +#endif + +/** + @file mysql/psi/psi.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +/** + Interface for an instrumented mutex. + This is an opaque structure. +*/ +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; + +/** + Interface for an instrumented rwlock. + This is an opaque structure. +*/ +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; + +/** + Interface for an instrumented condition. + This is an opaque structure. +*/ +struct PSI_cond; +typedef struct PSI_cond PSI_cond; + +/** + Interface for an instrumented table share. + This is an opaque structure. +*/ +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; + +/** + Interface for an instrumented table handle. + This is an opaque structure. +*/ +struct PSI_table; +typedef struct PSI_table PSI_table; + +/** + Interface for an instrumented thread. + This is an opaque structure. +*/ +struct PSI_thread; +typedef struct PSI_thread PSI_thread; + +/** + Interface for an instrumented file handle. + This is an opaque structure. +*/ +struct PSI_file; +typedef struct PSI_file PSI_file; + +/** + Interface for an instrumented socket descriptor. + This is an opaque structure. +*/ +struct PSI_socket; +typedef struct PSI_socket PSI_socket; + +/** + Interface for an instrumented prepared statement. + This is an opaque structure. +*/ +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; + +/** + Interface for an instrumented table operation. + This is an opaque structure. +*/ +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; + +/** + Interface for an instrumented statement. + This is an opaque structure. +*/ +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; + +/** + Interface for an instrumented transaction. + This is an opaque structure. +*/ +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; + +/** + Interface for an instrumented idle operation. + This is an opaque structure. +*/ +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; + +/** + Interface for an instrumented statement digest operation. + This is an opaque structure. +*/ +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; + +/** + Interface for an instrumented stored procedure share. + This is an opaque structure. +*/ +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; + +/** + Interface for an instrumented stored program. + This is an opaque structure. +*/ +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; + +/** + Interface for an instrumented metadata lock. + This is an opaque structure. +*/ +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; + +/** + Interface for an instrumented stage progress. + This is a public structure, for efficiency. +*/ +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; + +/** IO operation performed on an instrumented table. */ +enum PSI_table_io_operation +{ + /** Row fetch. */ + PSI_TABLE_FETCH_ROW= 0, + /** Row write. */ + PSI_TABLE_WRITE_ROW= 1, + /** Row update. */ + PSI_TABLE_UPDATE_ROW= 2, + /** Row delete. */ + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; + +/** + State data storage for @c start_table_io_wait_v1_t, + @c start_table_lock_wait_v1_t. + This structure provide temporary storage to a table locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_table_io_wait_v1_t + @sa start_table_lock_wait_v1_t +*/ +struct PSI_table_locker_state +{ + /** Internal state. */ + uint m_flags; + /** Current io operation. */ + enum PSI_table_io_operation m_io_operation; + /** Current table handle. */ + struct PSI_table *m_table; + /** Current table share. */ + struct PSI_table_share *m_table_share; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; + /** + Implementation specific. + For table io, the table io index. + For table lock, the lock type. + */ + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; + +/** Entry point for the performance schema interface. */ +struct PSI_bootstrap +{ + /** + ABI interface finder. + Calling this method with an interface version number returns either + an instance of the ABI for this version, or NULL. + @param version the interface version number to find + @return a versioned interface (PSI_v1, PSI_v2 or PSI) + @sa PSI_VERSION_1 + @sa PSI_v1 + @sa PSI_VERSION_2 + @sa PSI_v2 + @sa PSI_CURRENT_VERSION + @sa PSI + */ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; + +#ifdef HAVE_PSI_INTERFACE + +#ifdef DISABLE_ALL_PSI + +#ifndef DISABLE_PSI_THREAD +#define DISABLE_PSI_THREAD +#endif + +#ifndef DISABLE_PSI_MUTEX +#define DISABLE_PSI_MUTEX +#endif + +#ifndef DISABLE_PSI_RWLOCK +#define DISABLE_PSI_RWLOCK +#endif + +#ifndef DISABLE_PSI_COND +#define DISABLE_PSI_COND +#endif + +#ifndef DISABLE_PSI_FILE +#define DISABLE_PSI_FILE +#endif + +#ifndef DISABLE_PSI_TABLE +#define DISABLE_PSI_TABLE +#endif + +#ifndef DISABLE_PSI_SOCKET +#define DISABLE_PSI_SOCKET +#endif + +#ifndef DISABLE_PSI_STAGE +#define DISABLE_PSI_STAGE +#endif + +#ifndef DISABLE_PSI_STATEMENT +#define DISABLE_PSI_STATEMENT +#endif + +#ifndef DISABLE_PSI_SP +#define DISABLE_PSI_SP +#endif + +#ifndef DISABLE_PSI_IDLE +#define DISABLE_PSI_IDLE +#endif + +#ifndef DISABLE_PSI_STATEMENT_DIGEST +#define DISABLE_PSI_STATEMENT_DIGEST +#endif + +#ifndef DISABLE_PSI_METADATA +#define DISABLE_PSI_METADATA +#endif + +#ifndef DISABLE_PSI_MEMORY +#define DISABLE_PSI_MEMORY +#endif + +#ifndef DISABLE_PSI_TRANSACTION +#define DISABLE_PSI_TRANSACTION +#endif + +#ifndef DISABLE_PSI_SP +#define DISABLE_PSI_SP +#endif + +#ifndef DISABLE_PSI_PS +#define DISABLE_PSI_PS +#endif + +#endif + +/** + @def DISABLE_PSI_MUTEX + Compiling option to disable the mutex instrumentation. + This option is mostly intended to be used during development, + when doing special builds with only a subset of the performance schema instrumentation, + for code analysis / profiling / performance tuning of a specific instrumentation alone. + @sa DISABLE_PSI_RWLOCK + @sa DISABLE_PSI_COND + @sa DISABLE_PSI_FILE + @sa DISABLE_PSI_THREAD + @sa DISABLE_PSI_TABLE + @sa DISABLE_PSI_STAGE + @sa DISABLE_PSI_STATEMENT + @sa DISABLE_PSI_SP + @sa DISABLE_PSI_STATEMENT_DIGEST + @sa DISABLE_PSI_SOCKET + @sa DISABLE_PSI_MEMORY + @sa DISABLE_PSI_IDLE + @sa DISABLE_PSI_METADATA + @sa DISABLE PSI_TRANSACTION +*/ + +#ifndef DISABLE_PSI_MUTEX +#define HAVE_PSI_MUTEX_INTERFACE +#endif + +/** + @def DISABLE_PSI_RWLOCK + Compiling option to disable the rwlock instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_RWLOCK +#define HAVE_PSI_RWLOCK_INTERFACE +#endif + +/** + @def DISABLE_PSI_COND + Compiling option to disable the cond instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_COND +#define HAVE_PSI_COND_INTERFACE +#endif + +/** + @def DISABLE_PSI_FILE + Compiling option to disable the file instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_FILE +#define HAVE_PSI_FILE_INTERFACE +#endif + +/** + @def DISABLE_PSI_THREAD + Compiling option to disable the thread instrumentation. + @sa DISABLE_PSI_MUTEX +*/ +#ifndef DISABLE_PSI_THREAD +#define HAVE_PSI_THREAD_INTERFACE +#endif + +/** + @def DISABLE_PSI_TABLE + Compiling option to disable the table instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_TABLE +#define HAVE_PSI_TABLE_INTERFACE +#endif + +/** + @def DISABLE_PSI_STAGE + Compiling option to disable the stage instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_STAGE +#define HAVE_PSI_STAGE_INTERFACE +#endif + +/** + @def DISABLE_PSI_STATEMENT + Compiling option to disable the statement instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_STATEMENT +#define HAVE_PSI_STATEMENT_INTERFACE +#endif + +/** + @def DISABLE_PSI_SP + Compiling option to disable the stored program instrumentation. + @sa DISABLE_PSI_MUTEX +*/ +#ifndef DISABLE_PSI_SP +#define HAVE_PSI_SP_INTERFACE +#endif + +/** + @def DISABLE_PSI_PS + Compiling option to disable the prepared statement instrumentation. + @sa DISABLE_PSI_MUTEX +*/ +#ifndef DISABLE_PSI_STATEMENT +#ifndef DISABLE_PSI_PS +#define HAVE_PSI_PS_INTERFACE +#endif +#endif + +/** + @def DISABLE_PSI_STATEMENT_DIGEST + Compiling option to disable the statement digest instrumentation. +*/ + +#ifndef DISABLE_PSI_STATEMENT +#ifndef DISABLE_PSI_STATEMENT_DIGEST +#define HAVE_PSI_STATEMENT_DIGEST_INTERFACE +#endif +#endif + +/** + @def DISABLE_PSI_TRANSACTION + Compiling option to disable the transaction instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_TRANSACTION +#define HAVE_PSI_TRANSACTION_INTERFACE +#endif + +/** + @def DISABLE_PSI_SOCKET + Compiling option to disable the statement instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_SOCKET +#define HAVE_PSI_SOCKET_INTERFACE +#endif + +/** + @def DISABLE_PSI_MEMORY + Compiling option to disable the memory instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_MEMORY +#define HAVE_PSI_MEMORY_INTERFACE +#endif + +/** + @def DISABLE_PSI_IDLE + Compiling option to disable the idle instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_IDLE +#define HAVE_PSI_IDLE_INTERFACE +#endif + +/** + @def DISABLE_PSI_METADATA + Compiling option to disable the metadata instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_METADATA +#define HAVE_PSI_METADATA_INTERFACE +#endif + +/** + @def PSI_VERSION_1 + Performance Schema Interface number for version 1. + This version is supported. +*/ +#define PSI_VERSION_1 1 + +/** + @def PSI_VERSION_2 + Performance Schema Interface number for version 2. + This version is not implemented, it's a placeholder. +*/ +#define PSI_VERSION_2 2 + +/** + @def PSI_CURRENT_VERSION + Performance Schema Interface number for the most recent version. + The most current version is @c PSI_VERSION_1 +*/ +#define PSI_CURRENT_VERSION 1 + +#ifndef USE_PSI_2 +#ifndef USE_PSI_1 +#define USE_PSI_1 +#endif +#endif + +/** + Interface for an instrumented mutex operation. + This is an opaque structure. +*/ +struct PSI_mutex_locker; +typedef struct PSI_mutex_locker PSI_mutex_locker; + +/** + Interface for an instrumented rwlock operation. + This is an opaque structure. +*/ +struct PSI_rwlock_locker; +typedef struct PSI_rwlock_locker PSI_rwlock_locker; + +/** + Interface for an instrumented condition operation. + This is an opaque structure. +*/ +struct PSI_cond_locker; +typedef struct PSI_cond_locker PSI_cond_locker; + +/** + Interface for an instrumented file operation. + This is an opaque structure. +*/ +struct PSI_file_locker; +typedef struct PSI_file_locker PSI_file_locker; + +/** + Interface for an instrumented socket operation. + This is an opaque structure. +*/ +struct PSI_socket_locker; +typedef struct PSI_socket_locker PSI_socket_locker; + +/** + Interface for an instrumented MDL operation. + This is an opaque structure. +*/ +struct PSI_metadata_locker; +typedef struct PSI_metadata_locker PSI_metadata_locker; + +/** Operation performed on an instrumented mutex. */ +enum PSI_mutex_operation +{ + /** Lock. */ + PSI_MUTEX_LOCK= 0, + /** Lock attempt. */ + PSI_MUTEX_TRYLOCK= 1 +}; +typedef enum PSI_mutex_operation PSI_mutex_operation; + +/** + Operation performed on an instrumented rwlock. + For basic READ / WRITE lock, + operations are "READ" or "WRITE". + For SX-locks, operations are "SHARED", "SHARED-EXCLUSIVE" or "EXCLUSIVE". +*/ +enum PSI_rwlock_operation +{ + /** Read lock. */ + PSI_RWLOCK_READLOCK= 0, + /** Write lock. */ + PSI_RWLOCK_WRITELOCK= 1, + /** Read lock attempt. */ + PSI_RWLOCK_TRYREADLOCK= 2, + /** Write lock attempt. */ + PSI_RWLOCK_TRYWRITELOCK= 3, + + /** Shared lock. */ + PSI_RWLOCK_SHAREDLOCK= 4, + /** Shared Exclusive lock. */ + PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, + /** Exclusive lock. */ + PSI_RWLOCK_EXCLUSIVELOCK= 6, + /** Shared lock attempt. */ + PSI_RWLOCK_TRYSHAREDLOCK= 7, + /** Shared Exclusive lock attempt. */ + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, + /** Exclusive lock attempt. */ + PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 + +}; +typedef enum PSI_rwlock_operation PSI_rwlock_operation; + +/** Operation performed on an instrumented condition. */ +enum PSI_cond_operation +{ + /** Wait. */ + PSI_COND_WAIT= 0, + /** Wait, with timeout. */ + PSI_COND_TIMEDWAIT= 1 +}; +typedef enum PSI_cond_operation PSI_cond_operation; + +/** Operation performed on an instrumented file. */ +enum PSI_file_operation +{ + /** File creation, as in @c create(). */ + PSI_FILE_CREATE= 0, + /** Temporary file creation, as in @c create_temp_file(). */ + PSI_FILE_CREATE_TMP= 1, + /** File open, as in @c open(). */ + PSI_FILE_OPEN= 2, + /** File open, as in @c fopen(). */ + PSI_FILE_STREAM_OPEN= 3, + /** File close, as in @c close(). */ + PSI_FILE_CLOSE= 4, + /** File close, as in @c fclose(). */ + PSI_FILE_STREAM_CLOSE= 5, + /** + Generic file read, such as @c fgets(), @c fgetc(), @c fread(), @c read(), + @c pread(). + */ + PSI_FILE_READ= 6, + /** + Generic file write, such as @c fputs(), @c fputc(), @c fprintf(), + @c vfprintf(), @c fwrite(), @c write(), @c pwrite(). + */ + PSI_FILE_WRITE= 7, + /** Generic file seek, such as @c fseek() or @c seek(). */ + PSI_FILE_SEEK= 8, + /** Generic file tell, such as @c ftell() or @c tell(). */ + PSI_FILE_TELL= 9, + /** File flush, as in @c fflush(). */ + PSI_FILE_FLUSH= 10, + /** File stat, as in @c stat(). */ + PSI_FILE_STAT= 11, + /** File stat, as in @c fstat(). */ + PSI_FILE_FSTAT= 12, + /** File chsize, as in @c my_chsize(). */ + PSI_FILE_CHSIZE= 13, + /** File delete, such as @c my_delete() or @c my_handler_delete_with_symlink(). */ + PSI_FILE_DELETE= 14, + /** File rename, such as @c my_rename() or @c my_rename_with_symlink(). */ + PSI_FILE_RENAME= 15, + /** File sync, as in @c fsync() or @c my_sync(). */ + PSI_FILE_SYNC= 16 +}; +typedef enum PSI_file_operation PSI_file_operation; + +/** Lock operation performed on an instrumented table. */ +enum PSI_table_lock_operation +{ + /** Table lock, in the server layer. */ + PSI_TABLE_LOCK= 0, + /** Table lock, in the storage engine layer. */ + PSI_TABLE_EXTERNAL_LOCK= 1 +}; +typedef enum PSI_table_lock_operation PSI_table_lock_operation; + +/** State of an instrumented socket. */ +enum PSI_socket_state +{ + /** Idle, waiting for the next command. */ + PSI_SOCKET_STATE_IDLE= 1, + /** Active, executing a command. */ + PSI_SOCKET_STATE_ACTIVE= 2 +}; +typedef enum PSI_socket_state PSI_socket_state; + +/** Operation performed on an instrumented socket. */ +enum PSI_socket_operation +{ + /** Socket creation, as in @c socket() or @c socketpair(). */ + PSI_SOCKET_CREATE= 0, + /** Socket connection, as in @c connect(), @c listen() and @c accept(). */ + PSI_SOCKET_CONNECT= 1, + /** Socket bind, as in @c bind(), @c getsockname() and @c getpeername(). */ + PSI_SOCKET_BIND= 2, + /** Socket close, as in @c shutdown(). */ + PSI_SOCKET_CLOSE= 3, + /** Socket send, @c send(). */ + PSI_SOCKET_SEND= 4, + /** Socket receive, @c recv(). */ + PSI_SOCKET_RECV= 5, + /** Socket send, @c sendto(). */ + PSI_SOCKET_SENDTO= 6, + /** Socket receive, @c recvfrom). */ + PSI_SOCKET_RECVFROM= 7, + /** Socket send, @c sendmsg(). */ + PSI_SOCKET_SENDMSG= 8, + /** Socket receive, @c recvmsg(). */ + PSI_SOCKET_RECVMSG= 9, + /** Socket seek, such as @c fseek() or @c seek(). */ + PSI_SOCKET_SEEK= 10, + /** Socket options, as in @c getsockopt() and @c setsockopt(). */ + PSI_SOCKET_OPT= 11, + /** Socket status, as in @c sockatmark() and @c isfdtype(). */ + PSI_SOCKET_STAT= 12, + /** Socket shutdown, as in @c shutdown(). */ + PSI_SOCKET_SHUTDOWN= 13, + /** Socket select, as in @c select() and @c poll(). */ + PSI_SOCKET_SELECT= 14 +}; +typedef enum PSI_socket_operation PSI_socket_operation; + +#endif +/** + Instrumented mutex key. + To instrument a mutex, a mutex key must be obtained using @c register_mutex. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_mutex_key; + +/** + Instrumented rwlock key. + To instrument a rwlock, a rwlock key must be obtained + using @c register_rwlock. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_rwlock_key; + +/** + Instrumented cond key. + To instrument a condition, a condition key must be obtained + using @c register_cond. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_cond_key; + +/** + Instrumented thread key. + To instrument a thread, a thread key must be obtained + using @c register_thread. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_thread_key; + +/** + Instrumented file key. + To instrument a file, a file key must be obtained using @c register_file. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_file_key; + +/** + Instrumented stage key. + To instrument a stage, a stage key must be obtained using @c register_stage. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_stage_key; + +/** + Instrumented statement key. + To instrument a statement, a statement key must be obtained using @c register_statement. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_statement_key; + +/** + Instrumented socket key. + To instrument a socket, a socket key must be obtained using @c register_socket. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_socket_key; + +#ifdef HAVE_PSI_1 + +/** + @defgroup Group_PSI_v1 Application Binary Interface, version 1 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Mutex information. + @since PSI_VERSION_1 + This structure is used to register an instrumented mutex. +*/ +struct PSI_mutex_info_v1 +{ + /** + Pointer to the key assigned to the registered mutex. + */ + PSI_mutex_key *m_key; + /** + The name of the mutex to register. + */ + const char *m_name; + /** + The flags of the mutex to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_mutex_info_v1 PSI_mutex_info_v1; + +/** + Rwlock information. + @since PSI_VERSION_1 + This structure is used to register an instrumented rwlock. +*/ +struct PSI_rwlock_info_v1 +{ + /** + Pointer to the key assigned to the registered rwlock. + */ + PSI_rwlock_key *m_key; + /** + The name of the rwlock to register. + */ + const char *m_name; + /** + The flags of the rwlock to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info_v1; + +/** + Condition information. + @since PSI_VERSION_1 + This structure is used to register an instrumented cond. +*/ +struct PSI_cond_info_v1 +{ + /** + Pointer to the key assigned to the registered cond. + */ + PSI_cond_key *m_key; + /** + The name of the cond to register. + */ + const char *m_name; + /** + The flags of the cond to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_cond_info_v1 PSI_cond_info_v1; + +/** + Thread instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented thread. +*/ +struct PSI_thread_info_v1 +{ + /** + Pointer to the key assigned to the registered thread. + */ + PSI_thread_key *m_key; + /** + The name of the thread instrument to register. + */ + const char *m_name; + /** + The flags of the thread to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_thread_info_v1 PSI_thread_info_v1; + +/** + File instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented file. +*/ +struct PSI_file_info_v1 +{ + /** + Pointer to the key assigned to the registered file. + */ + PSI_file_key *m_key; + /** + The name of the file instrument to register. + */ + const char *m_name; + /** + The flags of the file instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_file_info_v1 PSI_file_info_v1; + +/** + Stage instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented stage. +*/ +struct PSI_stage_info_v1 +{ + /** The registered stage key. */ + PSI_stage_key m_key; + /** The name of the stage instrument to register. */ + const char *m_name; + /** The flags of the stage instrument to register. */ + int m_flags; +}; +typedef struct PSI_stage_info_v1 PSI_stage_info_v1; + +/** + Statement instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented statement. +*/ +struct PSI_statement_info_v1 +{ + /** The registered statement key. */ + PSI_statement_key m_key; + /** The name of the statement instrument to register. */ + const char *m_name; + /** The flags of the statement instrument to register. */ + int m_flags; +}; +typedef struct PSI_statement_info_v1 PSI_statement_info_v1; + +/** + Socket instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented socket. +*/ +struct PSI_socket_info_v1 +{ + /** + Pointer to the key assigned to the registered socket. + */ + PSI_socket_key *m_key; + /** + The name of the socket instrument to register. + */ + const char *m_name; + /** + The flags of the socket instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_socket_info_v1 PSI_socket_info_v1; + +/** + State data storage for @c start_idle_wait_v1_t. + This structure provide temporary storage to an idle locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_idle_wait_v1_t. +*/ +struct PSI_idle_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state_v1; + +/** + State data storage for @c start_mutex_wait_v1_t. + This structure provide temporary storage to a mutex locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_mutex_wait_v1_t +*/ +struct PSI_mutex_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_mutex_operation m_operation; + /** Current mutex. */ + struct PSI_mutex *m_mutex; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state_v1; + +/** + State data storage for @c start_rwlock_rdwait_v1_t, @c start_rwlock_wrwait_v1_t. + This structure provide temporary storage to a rwlock locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_rwlock_rdwait_v1_t + @sa start_rwlock_wrwait_v1_t +*/ +struct PSI_rwlock_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_rwlock_operation m_operation; + /** Current rwlock. */ + struct PSI_rwlock *m_rwlock; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state_v1; + +/** + State data storage for @c start_cond_wait_v1_t. + This structure provide temporary storage to a condition locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_cond_wait_v1_t +*/ +struct PSI_cond_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_cond_operation m_operation; + /** Current condition. */ + struct PSI_cond *m_cond; + /** Current mutex. */ + struct PSI_mutex *m_mutex; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state_v1; + +/** + State data storage for @c get_thread_file_name_locker_v1_t. + This structure provide temporary storage to a file locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa get_thread_file_name_locker_v1_t + @sa get_thread_file_stream_locker_v1_t + @sa get_thread_file_descriptor_locker_v1_t +*/ +struct PSI_file_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_file_operation m_operation; + /** Current file. */ + struct PSI_file *m_file; + /** Current file name. */ + const char *m_name; + /** Current file class. */ + void *m_class; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Operation number of bytes. */ + size_t m_number_of_bytes; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state_v1; + +/** + State data storage for @c start_metadata_wait_v1_t. + This structure provide temporary storage to a metadata locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_metadata_wait_v1_t +*/ +struct PSI_metadata_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current metadata lock. */ + struct PSI_metadata_lock *m_metadata_lock; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state_v1; + +/* Duplicate of NAME_LEN, to avoid dependency on mysql_com.h */ +#define PSI_SCHEMA_NAME_LEN (64 * 3) + +/** + State data storage for @c get_thread_statement_locker_v1_t, + @c get_thread_statement_locker_v1_t. + This structure provide temporary storage to a statement locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa get_thread_statement_locker_v1_t +*/ +struct PSI_statement_locker_state_v1 +{ + /** Discarded flag. */ + my_bool m_discarded; + /** In prepare flag. */ + my_bool m_in_prepare; + /** Metric, no index used flag. */ + uchar m_no_index_used; + /** Metric, no good index used flag. */ + uchar m_no_good_index_used; + /** Internal state. */ + uint m_flags; + /** Instrumentation class. */ + void *m_class; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_statement; + /** Locked time. */ + ulonglong m_lock_time; + /** Rows sent. */ + ulonglong m_rows_sent; + /** Rows examined. */ + ulonglong m_rows_examined; + /** Metric, temporary tables created on disk. */ + ulong m_created_tmp_disk_tables; + /** Metric, temporary tables created. */ + ulong m_created_tmp_tables; + /** Metric, number of select full join. */ + ulong m_select_full_join; + /** Metric, number of select full range join. */ + ulong m_select_full_range_join; + /** Metric, number of select range. */ + ulong m_select_range; + /** Metric, number of select range check. */ + ulong m_select_range_check; + /** Metric, number of select scan. */ + ulong m_select_scan; + /** Metric, number of sort merge passes. */ + ulong m_sort_merge_passes; + /** Metric, number of sort merge. */ + ulong m_sort_range; + /** Metric, number of sort rows. */ + ulong m_sort_rows; + /** Metric, number of sort scans. */ + ulong m_sort_scan; + /** Statement digest. */ + const struct sql_digest_storage *m_digest; + /** Current schema name. */ + char m_schema_name[PSI_SCHEMA_NAME_LEN]; + /** Length in bytes of @c m_schema_name. */ + uint m_schema_name_length; + /** Statement character set number. */ + uint m_cs_number; + PSI_sp_share *m_parent_sp_share; + PSI_prepared_stmt *m_parent_prepared_stmt; +}; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state_v1; + +/** + State data storage for @c get_thread_transaction_locker_v1_t, + @c get_thread_transaction_locker_v1_t. + This structure provide temporary storage to a transaction locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa get_thread_transaction_locker_v1_t +*/ +struct PSI_transaction_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Instrumentation class. */ + void *m_class; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_transaction; + /** True if read-only transaction, false if read-write. */ + my_bool m_read_only; + /** True if transaction is autocommit. */ + my_bool m_autocommit; + /** Number of statements. */ + ulong m_statement_count; + /** Total number of savepoints. */ + ulong m_savepoint_count; + /** Number of rollback_to_savepoint. */ + ulong m_rollback_to_savepoint_count; + /** Number of release_savepoint. */ + ulong m_release_savepoint_count; +}; + +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state_v1; + +/** + State data storage for @c start_socket_wait_v1_t. + This structure provide temporary storage to a socket locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_socket_wait_v1_t +*/ +struct PSI_socket_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current socket. */ + struct PSI_socket *m_socket; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Operation number of bytes. */ + size_t m_number_of_bytes; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Current operation. */ + enum PSI_socket_operation m_operation; + /** Source file. */ + const char* m_src_file; + /** Source line number. */ + int m_src_line; + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state_v1; + +struct PSI_sp_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Stored Procedure share. */ + PSI_sp_share* m_sp_share; +}; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state_v1; + +/* Using typedef to make reuse between PSI_v1 and PSI_v2 easier later. */ + +/** + Mutex registration API. + @param category a category name (typically a plugin name) + @param info an array of mutex info to register + @param count the size of the info array +*/ +typedef void (*register_mutex_v1_t) + (const char *category, struct PSI_mutex_info_v1 *info, int count); + +/** + Rwlock registration API. + @param category a category name (typically a plugin name) + @param info an array of rwlock info to register + @param count the size of the info array +*/ +typedef void (*register_rwlock_v1_t) + (const char *category, struct PSI_rwlock_info_v1 *info, int count); + +/** + Cond registration API. + @param category a category name (typically a plugin name) + @param info an array of cond info to register + @param count the size of the info array +*/ +typedef void (*register_cond_v1_t) + (const char *category, struct PSI_cond_info_v1 *info, int count); + +/** + Thread registration API. + @param category a category name (typically a plugin name) + @param info an array of thread info to register + @param count the size of the info array +*/ +typedef void (*register_thread_v1_t) + (const char *category, struct PSI_thread_info_v1 *info, int count); + +/** + File registration API. + @param category a category name (typically a plugin name) + @param info an array of file info to register + @param count the size of the info array +*/ +typedef void (*register_file_v1_t) + (const char *category, struct PSI_file_info_v1 *info, int count); + +/** + Stage registration API. + @param category a category name + @param info an array of stage info to register + @param count the size of the info array +*/ +typedef void (*register_stage_v1_t) + (const char *category, struct PSI_stage_info_v1 **info, int count); + +/** + Statement registration API. + @param category a category name + @param info an array of stage info to register + @param count the size of the info array +*/ +typedef void (*register_statement_v1_t) + (const char *category, struct PSI_statement_info_v1 *info, int count); + +/** + Socket registration API. + @param category a category name (typically a plugin name) + @param info an array of socket info to register + @param count the size of the info array +*/ +typedef void (*register_socket_v1_t) + (const char *category, struct PSI_socket_info_v1 *info, int count); + +/** + Mutex instrumentation initialisation API. + @param key the registered mutex key + @param identity the address of the mutex itself + @return an instrumented mutex +*/ +typedef struct PSI_mutex* (*init_mutex_v1_t) + (PSI_mutex_key key, void *identity); + +/** + Mutex instrumentation destruction API. + @param mutex the mutex to destroy +*/ +typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); + +/** + Rwlock instrumentation initialisation API. + @param key the registered rwlock key + @param identity the address of the rwlock itself + @return an instrumented rwlock +*/ +typedef struct PSI_rwlock* (*init_rwlock_v1_t) + (PSI_rwlock_key key, void *identity); + +/** + Rwlock instrumentation destruction API. + @param rwlock the rwlock to destroy +*/ +typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); + +/** + Cond instrumentation initialisation API. + @param key the registered key + @param identity the address of the rwlock itself + @return an instrumented cond +*/ +typedef struct PSI_cond* (*init_cond_v1_t) + (PSI_cond_key key, void *identity); + +/** + Cond instrumentation destruction API. + @param cond the rcond to destroy +*/ +typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); + +/** + Socket instrumentation initialisation API. + @param key the registered mutex key + @param socket descriptor + @param addr the socket ip address + @param addr_len length of socket ip address + @return an instrumented socket +*/ +typedef struct PSI_socket* (*init_socket_v1_t) + (PSI_socket_key key, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len); + +/** + socket instrumentation destruction API. + @param socket the socket to destroy +*/ +typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket); + +/** + Acquire a table share instrumentation. + @param temporary True for temporary tables + @param share The SQL layer table share + @return a table share instrumentation, or NULL +*/ +typedef struct PSI_table_share* (*get_table_share_v1_t) + (my_bool temporary, struct TABLE_SHARE *share); + +/** + Release a table share. + @param info the table share to release +*/ +typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); + +/** + Drop a table share. + @param temporary True for temporary tables + @param schema_name the table schema name + @param schema_name_length the table schema name length + @param table_name the table name + @param table_name_length the table name length +*/ +typedef void (*drop_table_share_v1_t) + (my_bool temporary, const char *schema_name, int schema_name_length, + const char *table_name, int table_name_length); + +/** + Open an instrumentation table handle. + @param share the table to open + @param identity table handle identity + @return a table handle, or NULL +*/ +typedef struct PSI_table* (*open_table_v1_t) + (struct PSI_table_share *share, const void *identity); + +/** + Unbind a table handle from the current thread. + This operation happens when an opened table is added to the open table cache. + @param table the table to unbind +*/ +typedef void (*unbind_table_v1_t) + (struct PSI_table *table); + +/** + Rebind a table handle to the current thread. + This operation happens when a table from the open table cache + is reused for a thread. + @param table the table to unbind +*/ +typedef PSI_table* (*rebind_table_v1_t) + (PSI_table_share *share, const void *identity, PSI_table *table); + +/** + Close an instrumentation table handle. + Note that the table handle is invalid after this call. + @param table the table handle to close +*/ +typedef void (*close_table_v1_t)(struct TABLE_SHARE *server_share, + struct PSI_table *table); + +/** + Create a file instrumentation for a created file. + This method does not create the file itself, but is used to notify the + instrumentation interface that a file was just created. + @param key the file instrumentation key for this file + @param name the file name + @param file the file handle +*/ +typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, + File file); + +/** + Spawn a thread. + This method creates a new thread, with instrumentation. + @param key the instrumentation key for this thread + @param thread the resulting thread + @param attr the thread attributes + @param start_routine the thread start routine + @param arg the thread start routine argument +*/ +typedef int (*spawn_thread_v1_t)(PSI_thread_key key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); + +/** + Create instrumentation for a thread. + @param key the registered key + @param identity an address typical of the thread + @return an instrumented thread +*/ +typedef struct PSI_thread* (*new_thread_v1_t) + (PSI_thread_key key, const void *identity, ulonglong thread_id); + +/** + Assign a THD to an instrumented thread. + @param thread the instrumented thread + @param THD the sql layer THD to assign +*/ +typedef void (*set_thread_THD_v1_t)(struct PSI_thread *thread, + THD *thd); + +/** + Assign an id to an instrumented thread. + @param thread the instrumented thread + @param id the id to assign +*/ +typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, + ulonglong id); + +/** + Assign the current operating system thread id to an instrumented thread. + The operating system task id is obtained from @c gettid() + @param thread the instrumented thread +*/ +typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread); + +/** + Get the instrumentation for the running thread. + For this function to return a result, + the thread instrumentation must have been attached to the + running thread using @c set_thread() + @return the instrumentation for the running thread +*/ +typedef struct PSI_thread* (*get_thread_v1_t)(void); + +/** + Assign a user name to the instrumented thread. + @param user the user name + @param user_len the user name length +*/ +typedef void (*set_thread_user_v1_t)(const char *user, int user_len); + +/** + Assign a user name and host name to the instrumented thread. + @param user the user name + @param user_len the user name length + @param host the host name + @param host_len the host name length +*/ +typedef void (*set_thread_account_v1_t)(const char *user, int user_len, + const char *host, int host_len); + +/** + Assign a current database to the instrumented thread. + @param db the database name + @param db_len the database name length +*/ +typedef void (*set_thread_db_v1_t)(const char* db, int db_len); + +/** + Assign a current command to the instrumented thread. + @param command the current command +*/ +typedef void (*set_thread_command_v1_t)(int command); + +/** + Assign a connection type to the instrumented thread. + @param conn_type the connection type +*/ +typedef void (*set_connection_type_v1_t)(opaque_vio_type conn_type); + + +/** + Assign a start time to the instrumented thread. + @param start_time the thread start time +*/ +typedef void (*set_thread_start_time_v1_t)(time_t start_time); + +/** + Assign a state to the instrumented thread. + @param state the thread state +*/ +typedef void (*set_thread_state_v1_t)(const char* state); + +/** + Assign a process info to the instrumented thread. + @param info the process into string + @param info_len the process into string length +*/ +typedef void (*set_thread_info_v1_t)(const char* info, uint info_len); + +/** + Attach a thread instrumentation to the running thread. + In case of thread pools, this method should be called when + a worker thread picks a work item and runs it. + Also, this method should be called if the instrumented code does not + keep the pointer returned by @c new_thread() and relies on @c get_thread() + instead. + @param thread the thread instrumentation +*/ +typedef void (*set_thread_v1_t)(struct PSI_thread *thread); + +/** + Assign the remote (peer) port to the instrumented thread. + + @param thread pointer to the thread instrumentation + @param port the remote port +*/ +typedef void (*set_thread_peer_port_v1_t)(PSI_thread *thread, + unsigned int port); + +/** Delete the current thread instrumentation. */ +typedef void (*delete_current_thread_v1_t)(void); + +/** Delete a thread instrumentation. */ +typedef void (*delete_thread_v1_t)(struct PSI_thread *thread); + +/** + Get a file instrumentation locker, for opening or creating a file. + @param state data storage for the locker + @param key the file instrumentation key + @param op the operation to perform + @param name the file name + @param identity a pointer representative of this file. + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + PSI_file_key key, enum PSI_file_operation op, const char *name, + const void *identity); + +/** + Get a file stream instrumentation locker. + @param state data storage for the locker + @param file the file stream to access + @param op the operation to perform + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + struct PSI_file *file, enum PSI_file_operation op); + +/** + Get a file instrumentation locker. + @param state data storage for the locker + @param file the file descriptor to access + @param op the operation to perform + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + File file, enum PSI_file_operation op); + +/** + Record a mutex instrumentation unlock event. + @param mutex the mutex instrumentation +*/ +typedef void (*unlock_mutex_v1_t) + (struct PSI_mutex *mutex); + +/** + Record a rwlock instrumentation unlock event. + @param rwlock the rwlock instrumentation +*/ +typedef void (*unlock_rwlock_v1_t) + (struct PSI_rwlock *rwlock); + +/** + Record a condition instrumentation signal event. + @param cond the cond instrumentation +*/ +typedef void (*signal_cond_v1_t) + (struct PSI_cond *cond); + +/** + Record a condition instrumentation broadcast event. + @param cond the cond instrumentation +*/ +typedef void (*broadcast_cond_v1_t) + (struct PSI_cond *cond); + +/** + Record an idle instrumentation wait start event. + @param state data storage for the locker + @param file the source file name + @param line the source line number + @return an idle locker, or NULL +*/ +typedef struct PSI_idle_locker* (*start_idle_wait_v1_t) + (struct PSI_idle_locker_state_v1 *state, const char *src_file, uint src_line); + +/** + Record an idle instrumentation wait end event. + @param locker a thread locker for the running thread +*/ +typedef void (*end_idle_wait_v1_t) + (struct PSI_idle_locker *locker); + +/** + Record a mutex instrumentation wait start event. + @param state data storage for the locker + @param mutex the instrumented mutex to lock + @param op the operation to perform + @param file the source file name + @param line the source line number + @return a mutex locker, or NULL +*/ +typedef struct PSI_mutex_locker* (*start_mutex_wait_v1_t) + (struct PSI_mutex_locker_state_v1 *state, + struct PSI_mutex *mutex, + enum PSI_mutex_operation op, + const char *src_file, uint src_line); + +/** + Record a mutex instrumentation wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, int rc); + +/** + Record a rwlock instrumentation read wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for lock, 0 for trylock +*/ +typedef struct PSI_rwlock_locker* (*start_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); + +/** + Record a rwlock instrumentation read wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); + +/** + Record a rwlock instrumentation write wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for lock, 0 for trylock +*/ +typedef struct PSI_rwlock_locker* (*start_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); + +/** + Record a rwlock instrumentation write wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); + +/** + Record a condition instrumentation wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for wait, 0 for timedwait +*/ +typedef struct PSI_cond_locker* (*start_cond_wait_v1_t) + (struct PSI_cond_locker_state_v1 *state, + struct PSI_cond *cond, + struct PSI_mutex *mutex, + enum PSI_cond_operation op, + const char *src_file, uint src_line); + +/** + Record a condition instrumentation wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_cond_wait_v1_t) + (struct PSI_cond_locker *locker, int rc); + +/** + Record a table instrumentation io wait start event. + @param locker a table locker for the running thread + @param file the source file name + @param line the source line number +*/ +typedef struct PSI_table_locker* (*start_table_io_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_io_operation op, + uint index, + const char *src_file, uint src_line); + +/** + Record a table instrumentation io wait end event. + @param locker a table locker for the running thread + @param numrows the number of rows involved in io +*/ +typedef void (*end_table_io_wait_v1_t) + (struct PSI_table_locker *locker, + ulonglong numrows); + +/** + Record a table instrumentation lock wait start event. + @param locker a table locker for the running thread + @param file the source file name + @param line the source line number +*/ +typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_lock_operation op, + ulong flags, + const char *src_file, uint src_line); + +/** + Record a table instrumentation lock wait end event. + @param locker a table locker for the running thread +*/ +typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker); + +typedef void (*unlock_table_v1_t)(struct PSI_table *table); + +/** + Start a file instrumentation open operation. + @param locker the file locker + @param op the operation to perform + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_open_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); + +/** + End a file instrumentation open operation, for file streams. + @param locker the file locker. + @param result the opened file (NULL indicates failure, non NULL success). + @return an instrumented file handle +*/ +typedef struct PSI_file* (*end_file_open_wait_v1_t) + (struct PSI_file_locker *locker, void *result); + +/** + End a file instrumentation open operation, for non stream files. + @param locker the file locker. + @param file the file number assigned by open() or create() for this file. +*/ +typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file); + +/** + End a file instrumentation open operation, for non stream temporary files. + @param locker the file locker. + @param file the file number assigned by open() or create() for this file. + @param filename the file name generated during temporary file creation. +*/ +typedef void (*end_temp_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file, const char *filename); + +/** + Record a file instrumentation start event. + @param locker a file locker for the running thread + @param op file operation to be performed + @param count the number of bytes requested, or 0 if not applicable + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count, + const char *src_file, uint src_line); + +/** + Record a file instrumentation end event. + Note that for file close operations, the instrumented file handle + associated with the file (which was provided to obtain a locker) + is invalid after this call. + @param locker a file locker for the running thread + @param count the number of bytes actually used in the operation, + or 0 if not applicable, or -1 if the operation failed + @sa get_thread_file_name_locker + @sa get_thread_file_stream_locker + @sa get_thread_file_descriptor_locker +*/ +typedef void (*end_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count); + +/** + Start a file instrumentation close operation. + @param locker the file locker + @param op the operation to perform + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_close_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); + +/** + End a file instrumentation close operation. + @param locker the file locker. + @param rc the close operation return code (0 for success). + @return an instrumented file handle +*/ +typedef void (*end_file_close_wait_v1_t) + (struct PSI_file_locker *locker, int rc); + +/** + Rename a file instrumentation close operation. + @param locker the file locker. + @param old_name name of the file to be renamed. + @param new_name name of the file after rename. + @param rc the rename operation return code (0 for success). +*/ +typedef void (*end_file_rename_wait_v1_t) + (struct PSI_file_locker *locker, const char *old_name, + const char *new_name, int rc); + +/** + Start a new stage, and implicitly end the previous stage. + @param key the key of the new stage + @param src_file the source file name + @param src_line the source line number + @return the new stage progress +*/ +typedef PSI_stage_progress* (*start_stage_v1_t) + (PSI_stage_key key, const char *src_file, int src_line); + +typedef PSI_stage_progress* (*get_current_stage_progress_v1_t)(void); + +/** End the current stage. */ +typedef void (*end_stage_v1_t) (void); + +/** + Get a statement instrumentation locker. + @param state data storage for the locker + @param key the statement instrumentation key + @param charset client character set + @return a statement locker, or NULL +*/ +typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t) + (struct PSI_statement_locker_state_v1 *state, + PSI_statement_key key, const void *charset, PSI_sp_share *sp_share); + +/** + Refine a statement locker to a more specific key. + Note that only events declared mutable can be refined. + @param the statement locker for the current event + @param key the new key for the event + @sa PSI_FLAG_MUTABLE +*/ +typedef struct PSI_statement_locker* (*refine_statement_v1_t) + (struct PSI_statement_locker *locker, + PSI_statement_key key); + +/** + Start a new statement event. + @param locker the statement locker for this event + @param db the active database name for this statement + @param db_length the active database name length for this statement + @param src_file source file name + @param src_line source line number +*/ +typedef void (*start_statement_v1_t) + (struct PSI_statement_locker *locker, + const char *db, uint db_length, + const char *src_file, uint src_line); + +/** + Set the statement text for a statement event. + @param locker the current statement locker + @param text the statement text + @param text_len the statement text length +*/ +typedef void (*set_statement_text_v1_t) + (struct PSI_statement_locker *locker, + const char *text, uint text_len); + +/** + Set a statement event lock time. + @param locker the statement locker + @param lock_time the locked time, in microseconds +*/ +typedef void (*set_statement_lock_time_t) + (struct PSI_statement_locker *locker, ulonglong lock_time); + +/** + Set a statement event rows sent metric. + @param locker the statement locker + @param count the number of rows sent +*/ +typedef void (*set_statement_rows_sent_t) + (struct PSI_statement_locker *locker, ulonglong count); + +/** + Set a statement event rows examined metric. + @param locker the statement locker + @param count the number of rows examined +*/ +typedef void (*set_statement_rows_examined_t) + (struct PSI_statement_locker *locker, ulonglong count); + +/** + Increment a statement event "created tmp disk tables" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_created_tmp_disk_tables_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "created tmp tables" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_created_tmp_tables_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select full join" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_full_join_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select full range join" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_full_range_join_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select range join" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_range_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select range check" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_range_check_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select scan" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_scan_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort merge passes" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_merge_passes_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort range" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_range_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort rows" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_rows_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort scan" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_scan_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Set a statement event "no index used" metric. + @param locker the statement locker + @param count the metric value +*/ +typedef void (*set_statement_no_index_used_t) + (struct PSI_statement_locker *locker); + +/** + Set a statement event "no good index used" metric. + @param locker the statement locker + @param count the metric value +*/ +typedef void (*set_statement_no_good_index_used_t) + (struct PSI_statement_locker *locker); + +/** + End a statement event. + @param locker the statement locker + @param stmt_da the statement diagnostics area. + @sa Diagnostics_area +*/ +typedef void (*end_statement_v1_t) + (struct PSI_statement_locker *locker, void *stmt_da); + +/** + Get a transaction instrumentation locker. + @param state data storage for the locker + @param xid the xid for this transaction + @param trxid the InnoDB transaction id + @param iso_level isolation level for this transaction + @param read_only true if transaction access mode is read-only + @param autocommit true if transaction is autocommit + @return a transaction locker, or NULL +*/ +typedef struct PSI_transaction_locker* (*get_thread_transaction_locker_v1_t) + (struct PSI_transaction_locker_state_v1 *state, const void *xid, + ulonglong trxid, int isolation_level, my_bool read_only, + my_bool autocommit); + +/** + Start a new transaction event. + @param locker the transaction locker for this event + @param src_file source file name + @param src_line source line number +*/ +typedef void (*start_transaction_v1_t) + (struct PSI_transaction_locker *locker, + const char *src_file, uint src_line); + +/** + Set the transaction xid. + @param locker the transaction locker for this event + @param xid the id of the XA transaction + #param xa_state is the state of the XA transaction +*/ +typedef void (*set_transaction_xid_v1_t) + (struct PSI_transaction_locker *locker, + const void *xid, int xa_state); + +/** + Set the state of the XA transaction. + @param locker the transaction locker for this event + @param xa_state the new state of the xa transaction +*/ +typedef void (*set_transaction_xa_state_v1_t) + (struct PSI_transaction_locker *locker, + int xa_state); + +/** + Set the transaction gtid. + @param locker the transaction locker for this event + @param sid the source id for the transaction, mapped from sidno + @param gtid_spec the gtid specifier for the transaction +*/ +typedef void (*set_transaction_gtid_v1_t) + (struct PSI_transaction_locker *locker, + const void *sid, const void *gtid_spec); + +/** + Set the transaction trx_id. + @param locker the transaction locker for this event + @param trxid the storage engine transaction ID +*/ +typedef void (*set_transaction_trxid_v1_t) + (struct PSI_transaction_locker *locker, + const ulonglong *trxid); + +/** + Increment a transaction event savepoint count. + @param locker the transaction locker + @param count the increment value +*/ +typedef void (*inc_transaction_savepoints_v1_t) + (struct PSI_transaction_locker *locker, ulong count); + +/** + Increment a transaction event rollback to savepoint count. + @param locker the transaction locker + @param count the increment value +*/ +typedef void (*inc_transaction_rollback_to_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); + +/** + Increment a transaction event release savepoint count. + @param locker the transaction locker + @param count the increment value +*/ +typedef void (*inc_transaction_release_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); + +/** + Commit or rollback the transaction. + @param locker the transaction locker for this event + @param commit true if transaction was committed, false if rolled back +*/ +typedef void (*end_transaction_v1_t) + (struct PSI_transaction_locker *locker, + my_bool commit); + +/** + Record a socket instrumentation start event. + @param locker a socket locker for the running thread + @param op socket operation to be performed + @param count the number of bytes requested, or 0 if not applicable + @param src_file the source file name + @param src_line the source line number +*/ +typedef struct PSI_socket_locker* (*start_socket_wait_v1_t) + (struct PSI_socket_locker_state_v1 *state, + struct PSI_socket *socket, + enum PSI_socket_operation op, + size_t count, + const char *src_file, uint src_line); + +/** + Record a socket instrumentation end event. + Note that for socket close operations, the instrumented socket handle + associated with the socket (which was provided to obtain a locker) + is invalid after this call. + @param locker a socket locker for the running thread + @param count the number of bytes actually used in the operation, + or 0 if not applicable, or -1 if the operation failed + @sa get_thread_socket_locker +*/ +typedef void (*end_socket_wait_v1_t) + (struct PSI_socket_locker *locker, size_t count); + +/** + Set the socket state for an instrumented socket. + @param socket the instrumented socket + @param state socket state + */ +typedef void (*set_socket_state_v1_t)(struct PSI_socket *socket, + enum PSI_socket_state state); + +/** + Set the socket info for an instrumented socket. + @param socket the instrumented socket + @param fd the socket descriptor + @param addr the socket ip address + @param addr_len length of socket ip address + @param thread_id associated thread id +*/ +typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket, + const my_socket *fd, + const struct sockaddr *addr, + socklen_t addr_len); + +/** + Bind a socket to the thread that owns it. + @param socket instrumented socket +*/ +typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket); + +/** + Get a prepare statement. + @param locker a statement locker for the running thread. +*/ +typedef PSI_prepared_stmt* (*create_prepared_stmt_v1_t) + (void *identity, uint stmt_id, PSI_statement_locker *locker, + const char *stmt_name, size_t stmt_name_length); + +/** + destroy a prepare statement. + @param prepared_stmt prepared statement. +*/ +typedef void (*destroy_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); + +/** + repreare a prepare statement. + @param prepared_stmt prepared statement. +*/ +typedef void (*reprepare_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); + +/** + Record a prepare statement instrumentation execute event. + @param locker a statement locker for the running thread. + @param prepared_stmt prepared statement. +*/ +typedef void (*execute_prepared_stmt_v1_t) + (PSI_statement_locker *locker, PSI_prepared_stmt* prepared_stmt); + +/** + Set the statement text for a prepared statement event. + @param prepared_stmt prepared statement. + @param text the prepared statement text + @param text_len the prepared statement text length +*/ +typedef void (*set_prepared_stmt_text_v1_t)(PSI_prepared_stmt *prepared_stmt, + const char *text, + uint text_len); +/** + Get a digest locker for the current statement. + @param locker a statement locker for the running thread +*/ +typedef struct PSI_digest_locker * (*digest_start_v1_t) + (struct PSI_statement_locker *locker); + +/** + Add a token to the current digest instrumentation. + @param locker a digest locker for the current statement + @param token the lexical token to add + @param yylval the lexical token attributes +*/ +typedef void (*digest_end_v1_t) + (struct PSI_digest_locker *locker, const struct sql_digest_storage *digest); + +typedef PSI_sp_locker* (*start_sp_v1_t) + (struct PSI_sp_locker_state_v1 *state, struct PSI_sp_share* sp_share); + +typedef void (*end_sp_v1_t) + (struct PSI_sp_locker *locker); + +typedef void (*drop_sp_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); + +/** + Acquire a sp share instrumentation. + @param type of stored program + @param schema name of stored program + @param name of stored program + @return a stored program share instrumentation, or NULL +*/ +typedef struct PSI_sp_share* (*get_sp_share_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); + +/** + Release a stored program share. + @param info the stored program share to release +*/ +typedef void (*release_sp_share_v1_t)(struct PSI_sp_share *share); + +typedef PSI_metadata_lock* (*create_metadata_lock_v1_t) + (void *identity, + const MDL_key *key, + opaque_mdl_type mdl_type, + opaque_mdl_duration mdl_duration, + opaque_mdl_status mdl_status, + const char *src_file, + uint src_line); + +typedef void (*set_metadata_lock_status_v1_t)(PSI_metadata_lock *lock, + opaque_mdl_status mdl_status); + +typedef void (*destroy_metadata_lock_v1_t)(PSI_metadata_lock *lock); + +typedef struct PSI_metadata_locker* (*start_metadata_wait_v1_t) + (struct PSI_metadata_locker_state_v1 *state, + struct PSI_metadata_lock *mdl, + const char *src_file, uint src_line); + +typedef void (*end_metadata_wait_v1_t) + (struct PSI_metadata_locker *locker, int rc); + +/** + Stores an array of connection attributes + @param buffer char array of length encoded connection attributes + in network format + @param length length of the data in buffer + @param from_cs charset in which @c buffer is encoded + @return state + @retval non_0 attributes truncated + @retval 0 stored the attribute +*/ +typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length, + const void *from_cs); + +/** + Performance Schema Interface, version 1. + @since PSI_VERSION_1 +*/ +struct PSI_v1 +{ + /** @sa register_mutex_v1_t. */ + register_mutex_v1_t register_mutex; + /** @sa register_rwlock_v1_t. */ + register_rwlock_v1_t register_rwlock; + /** @sa register_cond_v1_t. */ + register_cond_v1_t register_cond; + /** @sa register_thread_v1_t. */ + register_thread_v1_t register_thread; + /** @sa register_file_v1_t. */ + register_file_v1_t register_file; + /** @sa register_stage_v1_t. */ + register_stage_v1_t register_stage; + /** @sa register_statement_v1_t. */ + register_statement_v1_t register_statement; + /** @sa register_socket_v1_t. */ + register_socket_v1_t register_socket; + /** @sa init_mutex_v1_t. */ + init_mutex_v1_t init_mutex; + /** @sa destroy_mutex_v1_t. */ + destroy_mutex_v1_t destroy_mutex; + /** @sa init_rwlock_v1_t. */ + init_rwlock_v1_t init_rwlock; + /** @sa destroy_rwlock_v1_t. */ + destroy_rwlock_v1_t destroy_rwlock; + /** @sa init_cond_v1_t. */ + init_cond_v1_t init_cond; + /** @sa destroy_cond_v1_t. */ + destroy_cond_v1_t destroy_cond; + /** @sa init_socket_v1_t. */ + init_socket_v1_t init_socket; + /** @sa destroy_socket_v1_t. */ + destroy_socket_v1_t destroy_socket; + + /** @sa get_table_share_v1_t. */ + get_table_share_v1_t get_table_share; + /** @sa release_table_share_v1_t. */ + release_table_share_v1_t release_table_share; + /** @sa drop_table_share_v1_t. */ + drop_table_share_v1_t drop_table_share; + /** @sa open_table_v1_t. */ + open_table_v1_t open_table; + /** @sa unbind_table_v1_t. */ + unbind_table_v1_t unbind_table; + /** @sa rebind_table_v1_t. */ + rebind_table_v1_t rebind_table; + /** @sa close_table_v1_t. */ + close_table_v1_t close_table; + /** @sa create_file_v1_t. */ + create_file_v1_t create_file; + /** @sa spawn_thread_v1_t. */ + spawn_thread_v1_t spawn_thread; + /** @sa new_thread_v1_t. */ + new_thread_v1_t new_thread; + /** @sa set_thread_id_v1_t. */ + set_thread_id_v1_t set_thread_id; + /** @sa set_thread_THD_v1_t. */ + set_thread_THD_v1_t set_thread_THD; + /** @sa set_thread_os_id_v1_t. */ + set_thread_os_id_v1_t set_thread_os_id; + /** @sa get_thread_v1_t. */ + get_thread_v1_t get_thread; + /** @sa set_thread_user_v1_t. */ + set_thread_user_v1_t set_thread_user; + /** @sa set_thread_account_v1_t. */ + set_thread_account_v1_t set_thread_account; + /** @sa set_thread_db_v1_t. */ + set_thread_db_v1_t set_thread_db; + /** @sa set_thread_command_v1_t. */ + set_thread_command_v1_t set_thread_command; + /** @sa set_connection_type_v1_t. */ + set_connection_type_v1_t set_connection_type; + /** @sa set_thread_start_time_v1_t. */ + set_thread_start_time_v1_t set_thread_start_time; + /** @sa set_thread_state_v1_t. */ + set_thread_state_v1_t set_thread_state; + /** @sa set_thread_info_v1_t. */ + set_thread_info_v1_t set_thread_info; + /** @sa set_thread_v1_t. */ + set_thread_v1_t set_thread; + /** @sa delete_current_thread_v1_t. */ + delete_current_thread_v1_t delete_current_thread; + /** @sa delete_thread_v1_t. */ + delete_thread_v1_t delete_thread; + /** @sa get_thread_file_name_locker_v1_t. */ + get_thread_file_name_locker_v1_t get_thread_file_name_locker; + /** @sa get_thread_file_stream_locker_v1_t. */ + get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; + /** @sa get_thread_file_descriptor_locker_v1_t. */ + get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; + /** @sa unlock_mutex_v1_t. */ + unlock_mutex_v1_t unlock_mutex; + /** @sa unlock_rwlock_v1_t. */ + unlock_rwlock_v1_t unlock_rwlock; + /** @sa signal_cond_v1_t. */ + signal_cond_v1_t signal_cond; + /** @sa broadcast_cond_v1_t. */ + broadcast_cond_v1_t broadcast_cond; + /** @sa start_idle_wait_v1_t. */ + start_idle_wait_v1_t start_idle_wait; + /** @sa end_idle_wait_v1_t. */ + end_idle_wait_v1_t end_idle_wait; + /** @sa start_mutex_wait_v1_t. */ + start_mutex_wait_v1_t start_mutex_wait; + /** @sa end_mutex_wait_v1_t. */ + end_mutex_wait_v1_t end_mutex_wait; + /** @sa start_rwlock_rdwait_v1_t. */ + start_rwlock_rdwait_v1_t start_rwlock_rdwait; + /** @sa end_rwlock_rdwait_v1_t. */ + end_rwlock_rdwait_v1_t end_rwlock_rdwait; + /** @sa start_rwlock_wrwait_v1_t. */ + start_rwlock_wrwait_v1_t start_rwlock_wrwait; + /** @sa end_rwlock_wrwait_v1_t. */ + end_rwlock_wrwait_v1_t end_rwlock_wrwait; + /** @sa start_cond_wait_v1_t. */ + start_cond_wait_v1_t start_cond_wait; + /** @sa end_cond_wait_v1_t. */ + end_cond_wait_v1_t end_cond_wait; + /** @sa start_table_io_wait_v1_t. */ + start_table_io_wait_v1_t start_table_io_wait; + /** @sa end_table_io_wait_v1_t. */ + end_table_io_wait_v1_t end_table_io_wait; + /** @sa start_table_lock_wait_v1_t. */ + start_table_lock_wait_v1_t start_table_lock_wait; + /** @sa end_table_lock_wait_v1_t. */ + end_table_lock_wait_v1_t end_table_lock_wait; + /** @sa start_file_open_wait_v1_t. */ + start_file_open_wait_v1_t start_file_open_wait; + /** @sa end_file_open_wait_v1_t. */ + end_file_open_wait_v1_t end_file_open_wait; + /** @sa end_file_open_wait_and_bind_to_descriptor_v1_t. */ + end_file_open_wait_and_bind_to_descriptor_v1_t + end_file_open_wait_and_bind_to_descriptor; + /** @sa end_temp_file_open_wait_and_bind_to_descriptor_v1_t. */ + end_temp_file_open_wait_and_bind_to_descriptor_v1_t + end_temp_file_open_wait_and_bind_to_descriptor; + /** @sa start_file_wait_v1_t. */ + start_file_wait_v1_t start_file_wait; + /** @sa end_file_wait_v1_t. */ + end_file_wait_v1_t end_file_wait; + /** @sa start_file_close_wait_v1_t. */ + start_file_close_wait_v1_t start_file_close_wait; + /** @sa end_file_close_wait_v1_t. */ + end_file_close_wait_v1_t end_file_close_wait; + /** @sa rename_file_close_wait_v1_t. */ + end_file_rename_wait_v1_t end_file_rename_wait; + /** @sa start_stage_v1_t. */ + start_stage_v1_t start_stage; + /** @sa get_current_stage_progress_v1_t. */ + get_current_stage_progress_v1_t get_current_stage_progress; + /** @sa end_stage_v1_t. */ + end_stage_v1_t end_stage; + /** @sa get_thread_statement_locker_v1_t. */ + get_thread_statement_locker_v1_t get_thread_statement_locker; + /** @sa refine_statement_v1_t. */ + refine_statement_v1_t refine_statement; + /** @sa start_statement_v1_t. */ + start_statement_v1_t start_statement; + /** @sa set_statement_text_v1_t. */ + set_statement_text_v1_t set_statement_text; + /** @sa set_statement_lock_time_t. */ + set_statement_lock_time_t set_statement_lock_time; + /** @sa set_statement_rows_sent_t. */ + set_statement_rows_sent_t set_statement_rows_sent; + /** @sa set_statement_rows_examined_t. */ + set_statement_rows_examined_t set_statement_rows_examined; + /** @sa inc_statement_created_tmp_disk_tables. */ + inc_statement_created_tmp_disk_tables_t inc_statement_created_tmp_disk_tables; + /** @sa inc_statement_created_tmp_tables. */ + inc_statement_created_tmp_tables_t inc_statement_created_tmp_tables; + /** @sa inc_statement_select_full_join. */ + inc_statement_select_full_join_t inc_statement_select_full_join; + /** @sa inc_statement_select_full_range_join. */ + inc_statement_select_full_range_join_t inc_statement_select_full_range_join; + /** @sa inc_statement_select_range. */ + inc_statement_select_range_t inc_statement_select_range; + /** @sa inc_statement_select_range_check. */ + inc_statement_select_range_check_t inc_statement_select_range_check; + /** @sa inc_statement_select_scan. */ + inc_statement_select_scan_t inc_statement_select_scan; + /** @sa inc_statement_sort_merge_passes. */ + inc_statement_sort_merge_passes_t inc_statement_sort_merge_passes; + /** @sa inc_statement_sort_range. */ + inc_statement_sort_range_t inc_statement_sort_range; + /** @sa inc_statement_sort_rows. */ + inc_statement_sort_rows_t inc_statement_sort_rows; + /** @sa inc_statement_sort_scan. */ + inc_statement_sort_scan_t inc_statement_sort_scan; + /** @sa set_statement_no_index_used. */ + set_statement_no_index_used_t set_statement_no_index_used; + /** @sa set_statement_no_good_index_used. */ + set_statement_no_good_index_used_t set_statement_no_good_index_used; + /** @sa end_statement_v1_t. */ + end_statement_v1_t end_statement; + /** @sa get_thread_transaction_locker_v1_t. */ + get_thread_transaction_locker_v1_t get_thread_transaction_locker; + /** @sa start_transaction_v1_t. */ + start_transaction_v1_t start_transaction; + /** @sa set_transaction_xid_v1_t. */ + set_transaction_xid_v1_t set_transaction_xid; + /** @sa set_transaction_xa_state_v1_t. */ + set_transaction_xa_state_v1_t set_transaction_xa_state; + /** @sa set_transaction_gtid_v1_t. */ + set_transaction_gtid_v1_t set_transaction_gtid; + /** @sa set_transaction_trxid_v1_t. */ + set_transaction_trxid_v1_t set_transaction_trxid; + /** @sa inc_transaction_savepoints_v1_t. */ + inc_transaction_savepoints_v1_t inc_transaction_savepoints; + /** @sa inc_transaction_rollback_to_savepoint_v1_t. */ + inc_transaction_rollback_to_savepoint_v1_t inc_transaction_rollback_to_savepoint; + /** @sa inc_transaction_release_savepoint_v1_t. */ + inc_transaction_release_savepoint_v1_t inc_transaction_release_savepoint; + /** @sa end_transaction_v1_t. */ + end_transaction_v1_t end_transaction; + /** @sa start_socket_wait_v1_t. */ + start_socket_wait_v1_t start_socket_wait; + /** @sa end_socket_wait_v1_t. */ + end_socket_wait_v1_t end_socket_wait; + /** @sa set_socket_state_v1_t. */ + set_socket_state_v1_t set_socket_state; + /** @sa set_socket_info_v1_t. */ + set_socket_info_v1_t set_socket_info; + /** @sa set_socket_thread_owner_v1_t. */ + set_socket_thread_owner_v1_t set_socket_thread_owner; + /** @sa create_prepared_stmt_v1_t. */ + create_prepared_stmt_v1_t create_prepared_stmt; + /** @sa destroy_prepared_stmt_v1_t. */ + destroy_prepared_stmt_v1_t destroy_prepared_stmt; + /** @sa reprepare_prepared_stmt_v1_t. */ + reprepare_prepared_stmt_v1_t reprepare_prepared_stmt; + /** @sa execute_prepared_stmt_v1_t. */ + execute_prepared_stmt_v1_t execute_prepared_stmt; + /** @sa set_prepared_stmt_text_v1_t. */ + set_prepared_stmt_text_v1_t set_prepared_stmt_text; + /** @sa digest_start_v1_t. */ + digest_start_v1_t digest_start; + /** @sa digest_end_v1_t. */ + digest_end_v1_t digest_end; + /** @sa set_thread_connect_attrs_v1_t. */ + set_thread_connect_attrs_v1_t set_thread_connect_attrs; + /** @sa start_sp_v1_t. */ + start_sp_v1_t start_sp; + /** @sa start_sp_v1_t. */ + end_sp_v1_t end_sp; + /** @sa drop_sp_v1_t. */ + drop_sp_v1_t drop_sp; + /** @sa get_sp_share_v1_t. */ + get_sp_share_v1_t get_sp_share; + /** @sa release_sp_share_v1_t. */ + release_sp_share_v1_t release_sp_share; + /** @sa register_memory_v1_t. */ + register_memory_v1_t register_memory; + /** @sa memory_alloc_v1_t. */ + memory_alloc_v1_t memory_alloc; + /** @sa memory_realloc_v1_t. */ + memory_realloc_v1_t memory_realloc; + /** @sa memory_claim_v1_t. */ + memory_claim_v1_t memory_claim; + /** @sa memory_free_v1_t. */ + memory_free_v1_t memory_free; + + unlock_table_v1_t unlock_table; + + create_metadata_lock_v1_t create_metadata_lock; + set_metadata_lock_status_v1_t set_metadata_lock_status; + destroy_metadata_lock_v1_t destroy_metadata_lock; + + start_metadata_wait_v1_t start_metadata_wait; + end_metadata_wait_v1_t end_metadata_wait; + + set_thread_peer_port_v1_t set_thread_peer_port; +}; + +/** @} (end of group Group_PSI_v1) */ + +#endif /* HAVE_PSI_1 */ + +#ifdef USE_PSI_2 +#define HAVE_PSI_2 +#endif + +#ifdef HAVE_PSI_2 + +/** + @defgroup Group_PSI_v2 Application Binary Interface, version 2 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Performance Schema Interface, version 2. + This is a placeholder, this interface is not defined yet. + @since PSI_VERSION_2 +*/ +struct PSI_v2 +{ + /** Placeholder */ + int placeholder; + /* ... extended interface ... */ +}; + +/** Placeholder */ +struct PSI_mutex_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_rwlock_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_cond_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_thread_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_file_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_stage_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_statement_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_transaction_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_idle_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_mutex_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_rwlock_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_cond_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_file_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_statement_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_transaction_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_socket_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +struct PSI_metadata_locker_state_v2 +{ + int placeholder; +}; + +/** @} (end of group Group_PSI_v2) */ + +#endif /* HAVE_PSI_2 */ + +/** + @typedef PSI + The instrumentation interface for the current version. + @sa PSI_CURRENT_VERSION +*/ + +/** + @typedef PSI_mutex_info + The mutex information structure for the current version. +*/ + +/** + @typedef PSI_rwlock_info + The rwlock information structure for the current version. +*/ + +/** + @typedef PSI_cond_info + The cond information structure for the current version. +*/ + +/** + @typedef PSI_thread_info + The thread information structure for the current version. +*/ + +/** + @typedef PSI_file_info + The file information structure for the current version. +*/ + +/* Export the required version */ +#ifdef USE_PSI_1 +typedef struct PSI_v1 PSI; +typedef struct PSI_mutex_info_v1 PSI_mutex_info; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; +typedef struct PSI_cond_info_v1 PSI_cond_info; +typedef struct PSI_thread_info_v1 PSI_thread_info; +typedef struct PSI_file_info_v1 PSI_file_info; +typedef struct PSI_stage_info_v1 PSI_stage_info; +typedef struct PSI_statement_info_v1 PSI_statement_info; +typedef struct PSI_transaction_info_v1 PSI_transaction_info; +typedef struct PSI_socket_info_v1 PSI_socket_info; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state; +#endif + +#ifdef USE_PSI_2 +typedef struct PSI_v2 PSI; +typedef struct PSI_mutex_info_v2 PSI_mutex_info; +typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; +typedef struct PSI_cond_info_v2 PSI_cond_info; +typedef struct PSI_thread_info_v2 PSI_thread_info; +typedef struct PSI_file_info_v2 PSI_file_info; +typedef struct PSI_stage_info_v2 PSI_stage_info; +typedef struct PSI_statement_info_v2 PSI_statement_info; +typedef struct PSI_transaction_info_v2 PSI_transaction_info; +typedef struct PSI_socket_info_v2 PSI_socket_info; +typedef struct PSI_idle_locker_state_v2 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v2 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v2 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v2 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v2 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v2 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v2 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v2 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v2 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v2 PSI_metadata_locker_state; +#endif + +#ifndef HAVE_PSI_INTERFACE + +/** + Dummy structure, used to declare PSI_server when no instrumentation + is available. + The content does not matter, since PSI_server will be NULL. +*/ +struct PSI_none +{ + int opaque; +}; +typedef struct PSI_none PSI; + +/** + Stage instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented stage. +*/ +struct PSI_stage_info_none +{ + /** Unused stage key. */ + unsigned int m_key; + /** The name of the stage instrument. */ + const char *m_name; + /** Unused stage flags. */ + int m_flags; +}; + +/** + The stage instrumentation has to co exist with the legacy + THD::set_proc_info instrumentation. + To avoid duplication of the instrumentation in the server, + the common PSI_stage_info structure is used, + so we export it here, even when not building + with HAVE_PSI_INTERFACE. +*/ +typedef struct PSI_stage_info_none PSI_stage_info; +typedef struct PSI_stage_info_none PSI_statement_info; +typedef struct PSI_stage_info_none PSI_sp_locker_state; +typedef struct PSI_stage_info_none PSI_metadata_locker_state; +typedef struct PSI_stage_info_none PSI_metadata_locker; + +#endif /* HAVE_PSI_INTERFACE */ + +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; + +/* + Allow to override PSI_XXX_CALL at compile time + with more efficient implementations, if available. + If nothing better is available, + make a dynamic call using the PSI_server function pointer. +*/ + +#define PSI_DYNAMIC_CALL(M) PSI_server->M + +/** @} */ + +C_MODE_END +#endif /* MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H */ + diff --git a/include/mysql/psi/psi_abi_v0.h b/include/mysql/psi/psi_abi_v0.h new file mode 100644 index 00000000..c75a51f7 --- /dev/null +++ b/include/mysql/psi/psi_abi_v0.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2011, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file mysql/psi/psi_abi_v0.h + ABI check for mysql/psi/psi.h, when compiling without instrumentation. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define MY_GLOBAL_INCLUDED +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v0.h.pp b/include/mysql/psi/psi_abi_v0.h.pp new file mode 100644 index 00000000..47dc72b7 --- /dev/null +++ b/include/mysql/psi/psi_abi_v0.h.pp @@ -0,0 +1,100 @@ +#include "mysql/psi/psi.h" +#include "psi_base.h" +#include "psi_memory.h" +#include "psi_base.h" +struct PSI_thread; +typedef unsigned int PSI_memory_key; +C_MODE_START +struct MDL_key; +typedef struct MDL_key MDL_key; +typedef int opaque_mdl_type; +typedef int opaque_mdl_duration; +typedef int opaque_mdl_status; +typedef int opaque_vio_type; +struct TABLE_SHARE; +struct sql_digest_storage; + struct opaque_THD + { + int dummy; + }; + typedef struct opaque_THD THD; +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; +struct PSI_cond; +typedef struct PSI_cond PSI_cond; +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; +struct PSI_table; +typedef struct PSI_table PSI_table; +struct PSI_thread; +typedef struct PSI_thread PSI_thread; +struct PSI_file; +typedef struct PSI_file PSI_file; +struct PSI_socket; +typedef struct PSI_socket PSI_socket; +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; +enum PSI_table_io_operation +{ + PSI_TABLE_FETCH_ROW= 0, + PSI_TABLE_WRITE_ROW= 1, + PSI_TABLE_UPDATE_ROW= 2, + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; +struct PSI_table_locker_state +{ + uint m_flags; + enum PSI_table_io_operation m_io_operation; + struct PSI_table *m_table; + struct PSI_table_share *m_table_share; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; +struct PSI_none +{ + int opaque; +}; +typedef struct PSI_none PSI; +struct PSI_stage_info_none +{ + unsigned int m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_stage_info_none PSI_stage_info; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_abi_v1.h b/include/mysql/psi/psi_abi_v1.h new file mode 100644 index 00000000..e195ea5b --- /dev/null +++ b/include/mysql/psi/psi_abi_v1.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file mysql/psi/psi_abi_v1.h + ABI check for mysql/psi/psi.h, when using PSI_VERSION_1. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define USE_PSI_1 +#define HAVE_PSI_INTERFACE +#define MY_GLOBAL_INCLUDED +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v1.h.pp b/include/mysql/psi/psi_abi_v1.h.pp new file mode 100644 index 00000000..ca0d0206 --- /dev/null +++ b/include/mysql/psi/psi_abi_v1.h.pp @@ -0,0 +1,857 @@ +extern "C" { +typedef unsigned int PSI_memory_key; +} +extern "C" { +struct PSI_thread; +struct PSI_memory_info_v1 +{ + PSI_memory_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_memory_info_v1 PSI_memory_info_v1; +typedef void (*register_memory_v1_t) + (const char *category, struct PSI_memory_info_v1 *info, int count); +typedef PSI_memory_key (*memory_alloc_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); +typedef PSI_memory_key (*memory_realloc_v1_t) + (PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner); +typedef PSI_memory_key (*memory_claim_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); +typedef void (*memory_free_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread * owner); +typedef struct PSI_memory_info_v1 PSI_memory_info; +} +C_MODE_START +struct MDL_key; +typedef struct MDL_key MDL_key; +typedef int opaque_mdl_type; +typedef int opaque_mdl_duration; +typedef int opaque_mdl_status; +typedef int opaque_vio_type; +struct TABLE_SHARE; +struct sql_digest_storage; + class THD; +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; +struct PSI_cond; +typedef struct PSI_cond PSI_cond; +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; +struct PSI_table; +typedef struct PSI_table PSI_table; +struct PSI_thread; +typedef struct PSI_thread PSI_thread; +struct PSI_file; +typedef struct PSI_file PSI_file; +struct PSI_socket; +typedef struct PSI_socket PSI_socket; +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; +enum PSI_table_io_operation +{ + PSI_TABLE_FETCH_ROW= 0, + PSI_TABLE_WRITE_ROW= 1, + PSI_TABLE_UPDATE_ROW= 2, + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; +struct PSI_table_locker_state +{ + uint m_flags; + enum PSI_table_io_operation m_io_operation; + struct PSI_table *m_table; + struct PSI_table_share *m_table_share; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; +struct PSI_mutex_locker; +typedef struct PSI_mutex_locker PSI_mutex_locker; +struct PSI_rwlock_locker; +typedef struct PSI_rwlock_locker PSI_rwlock_locker; +struct PSI_cond_locker; +typedef struct PSI_cond_locker PSI_cond_locker; +struct PSI_file_locker; +typedef struct PSI_file_locker PSI_file_locker; +struct PSI_socket_locker; +typedef struct PSI_socket_locker PSI_socket_locker; +struct PSI_metadata_locker; +typedef struct PSI_metadata_locker PSI_metadata_locker; +enum PSI_mutex_operation +{ + PSI_MUTEX_LOCK= 0, + PSI_MUTEX_TRYLOCK= 1 +}; +typedef enum PSI_mutex_operation PSI_mutex_operation; +enum PSI_rwlock_operation +{ + PSI_RWLOCK_READLOCK= 0, + PSI_RWLOCK_WRITELOCK= 1, + PSI_RWLOCK_TRYREADLOCK= 2, + PSI_RWLOCK_TRYWRITELOCK= 3, + PSI_RWLOCK_SHAREDLOCK= 4, + PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, + PSI_RWLOCK_EXCLUSIVELOCK= 6, + PSI_RWLOCK_TRYSHAREDLOCK= 7, + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, + PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 +}; +typedef enum PSI_rwlock_operation PSI_rwlock_operation; +enum PSI_cond_operation +{ + PSI_COND_WAIT= 0, + PSI_COND_TIMEDWAIT= 1 +}; +typedef enum PSI_cond_operation PSI_cond_operation; +enum PSI_file_operation +{ + PSI_FILE_CREATE= 0, + PSI_FILE_CREATE_TMP= 1, + PSI_FILE_OPEN= 2, + PSI_FILE_STREAM_OPEN= 3, + PSI_FILE_CLOSE= 4, + PSI_FILE_STREAM_CLOSE= 5, + PSI_FILE_READ= 6, + PSI_FILE_WRITE= 7, + PSI_FILE_SEEK= 8, + PSI_FILE_TELL= 9, + PSI_FILE_FLUSH= 10, + PSI_FILE_STAT= 11, + PSI_FILE_FSTAT= 12, + PSI_FILE_CHSIZE= 13, + PSI_FILE_DELETE= 14, + PSI_FILE_RENAME= 15, + PSI_FILE_SYNC= 16 +}; +typedef enum PSI_file_operation PSI_file_operation; +enum PSI_table_lock_operation +{ + PSI_TABLE_LOCK= 0, + PSI_TABLE_EXTERNAL_LOCK= 1 +}; +typedef enum PSI_table_lock_operation PSI_table_lock_operation; +enum PSI_socket_state +{ + PSI_SOCKET_STATE_IDLE= 1, + PSI_SOCKET_STATE_ACTIVE= 2 +}; +typedef enum PSI_socket_state PSI_socket_state; +enum PSI_socket_operation +{ + PSI_SOCKET_CREATE= 0, + PSI_SOCKET_CONNECT= 1, + PSI_SOCKET_BIND= 2, + PSI_SOCKET_CLOSE= 3, + PSI_SOCKET_SEND= 4, + PSI_SOCKET_RECV= 5, + PSI_SOCKET_SENDTO= 6, + PSI_SOCKET_RECVFROM= 7, + PSI_SOCKET_SENDMSG= 8, + PSI_SOCKET_RECVMSG= 9, + PSI_SOCKET_SEEK= 10, + PSI_SOCKET_OPT= 11, + PSI_SOCKET_STAT= 12, + PSI_SOCKET_SHUTDOWN= 13, + PSI_SOCKET_SELECT= 14 +}; +typedef enum PSI_socket_operation PSI_socket_operation; +typedef unsigned int PSI_mutex_key; +typedef unsigned int PSI_rwlock_key; +typedef unsigned int PSI_cond_key; +typedef unsigned int PSI_thread_key; +typedef unsigned int PSI_file_key; +typedef unsigned int PSI_stage_key; +typedef unsigned int PSI_statement_key; +typedef unsigned int PSI_socket_key; +struct PSI_mutex_info_v1 +{ + PSI_mutex_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_mutex_info_v1 PSI_mutex_info_v1; +struct PSI_rwlock_info_v1 +{ + PSI_rwlock_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info_v1; +struct PSI_cond_info_v1 +{ + PSI_cond_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_cond_info_v1 PSI_cond_info_v1; +struct PSI_thread_info_v1 +{ + PSI_thread_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_thread_info_v1 PSI_thread_info_v1; +struct PSI_file_info_v1 +{ + PSI_file_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_file_info_v1 PSI_file_info_v1; +struct PSI_stage_info_v1 +{ + PSI_stage_key m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_stage_info_v1 PSI_stage_info_v1; +struct PSI_statement_info_v1 +{ + PSI_statement_key m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_statement_info_v1 PSI_statement_info_v1; +struct PSI_socket_info_v1 +{ + PSI_socket_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_socket_info_v1 PSI_socket_info_v1; +struct PSI_idle_locker_state_v1 +{ + uint m_flags; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state_v1; +struct PSI_mutex_locker_state_v1 +{ + uint m_flags; + enum PSI_mutex_operation m_operation; + struct PSI_mutex *m_mutex; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state_v1; +struct PSI_rwlock_locker_state_v1 +{ + uint m_flags; + enum PSI_rwlock_operation m_operation; + struct PSI_rwlock *m_rwlock; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state_v1; +struct PSI_cond_locker_state_v1 +{ + uint m_flags; + enum PSI_cond_operation m_operation; + struct PSI_cond *m_cond; + struct PSI_mutex *m_mutex; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state_v1; +struct PSI_file_locker_state_v1 +{ + uint m_flags; + enum PSI_file_operation m_operation; + struct PSI_file *m_file; + const char *m_name; + void *m_class; + struct PSI_thread *m_thread; + size_t m_number_of_bytes; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state_v1; +struct PSI_metadata_locker_state_v1 +{ + uint m_flags; + struct PSI_metadata_lock *m_metadata_lock; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state_v1; +struct PSI_statement_locker_state_v1 +{ + my_bool m_discarded; + my_bool m_in_prepare; + uchar m_no_index_used; + uchar m_no_good_index_used; + uint m_flags; + void *m_class; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_statement; + ulonglong m_lock_time; + ulonglong m_rows_sent; + ulonglong m_rows_examined; + ulong m_created_tmp_disk_tables; + ulong m_created_tmp_tables; + ulong m_select_full_join; + ulong m_select_full_range_join; + ulong m_select_range; + ulong m_select_range_check; + ulong m_select_scan; + ulong m_sort_merge_passes; + ulong m_sort_range; + ulong m_sort_rows; + ulong m_sort_scan; + const struct sql_digest_storage *m_digest; + char m_schema_name[(64 * 3)]; + uint m_schema_name_length; + uint m_cs_number; + PSI_sp_share *m_parent_sp_share; + PSI_prepared_stmt *m_parent_prepared_stmt; +}; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state_v1; +struct PSI_transaction_locker_state_v1 +{ + uint m_flags; + void *m_class; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_transaction; + my_bool m_read_only; + my_bool m_autocommit; + ulong m_statement_count; + ulong m_savepoint_count; + ulong m_rollback_to_savepoint_count; + ulong m_release_savepoint_count; +}; +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state_v1; +struct PSI_socket_locker_state_v1 +{ + uint m_flags; + struct PSI_socket *m_socket; + struct PSI_thread *m_thread; + size_t m_number_of_bytes; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + enum PSI_socket_operation m_operation; + const char* m_src_file; + int m_src_line; + void *m_wait; +}; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state_v1; +struct PSI_sp_locker_state_v1 +{ + uint m_flags; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + PSI_sp_share* m_sp_share; +}; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state_v1; +typedef void (*register_mutex_v1_t) + (const char *category, struct PSI_mutex_info_v1 *info, int count); +typedef void (*register_rwlock_v1_t) + (const char *category, struct PSI_rwlock_info_v1 *info, int count); +typedef void (*register_cond_v1_t) + (const char *category, struct PSI_cond_info_v1 *info, int count); +typedef void (*register_thread_v1_t) + (const char *category, struct PSI_thread_info_v1 *info, int count); +typedef void (*register_file_v1_t) + (const char *category, struct PSI_file_info_v1 *info, int count); +typedef void (*register_stage_v1_t) + (const char *category, struct PSI_stage_info_v1 **info, int count); +typedef void (*register_statement_v1_t) + (const char *category, struct PSI_statement_info_v1 *info, int count); +typedef void (*register_socket_v1_t) + (const char *category, struct PSI_socket_info_v1 *info, int count); +typedef struct PSI_mutex* (*init_mutex_v1_t) + (PSI_mutex_key key, void *identity); +typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); +typedef struct PSI_rwlock* (*init_rwlock_v1_t) + (PSI_rwlock_key key, void *identity); +typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); +typedef struct PSI_cond* (*init_cond_v1_t) + (PSI_cond_key key, void *identity); +typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); +typedef struct PSI_socket* (*init_socket_v1_t) + (PSI_socket_key key, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len); +typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket); +typedef struct PSI_table_share* (*get_table_share_v1_t) + (my_bool temporary, struct TABLE_SHARE *share); +typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); +typedef void (*drop_table_share_v1_t) + (my_bool temporary, const char *schema_name, int schema_name_length, + const char *table_name, int table_name_length); +typedef struct PSI_table* (*open_table_v1_t) + (struct PSI_table_share *share, const void *identity); +typedef void (*unbind_table_v1_t) + (struct PSI_table *table); +typedef PSI_table* (*rebind_table_v1_t) + (PSI_table_share *share, const void *identity, PSI_table *table); +typedef void (*close_table_v1_t)(struct TABLE_SHARE *server_share, + struct PSI_table *table); +typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, + File file); +typedef int (*spawn_thread_v1_t)(PSI_thread_key key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); +typedef struct PSI_thread* (*new_thread_v1_t) + (PSI_thread_key key, const void *identity, ulonglong thread_id); +typedef void (*set_thread_THD_v1_t)(struct PSI_thread *thread, + THD *thd); +typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, + ulonglong id); +typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread); +typedef struct PSI_thread* (*get_thread_v1_t)(void); +typedef void (*set_thread_user_v1_t)(const char *user, int user_len); +typedef void (*set_thread_account_v1_t)(const char *user, int user_len, + const char *host, int host_len); +typedef void (*set_thread_db_v1_t)(const char* db, int db_len); +typedef void (*set_thread_command_v1_t)(int command); +typedef void (*set_connection_type_v1_t)(opaque_vio_type conn_type); +typedef void (*set_thread_start_time_v1_t)(time_t start_time); +typedef void (*set_thread_state_v1_t)(const char* state); +typedef void (*set_thread_info_v1_t)(const char* info, uint info_len); +typedef void (*set_thread_v1_t)(struct PSI_thread *thread); +typedef void (*set_thread_peer_port_v1_t)(PSI_thread *thread, + unsigned int port); +typedef void (*delete_current_thread_v1_t)(void); +typedef void (*delete_thread_v1_t)(struct PSI_thread *thread); +typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + PSI_file_key key, enum PSI_file_operation op, const char *name, + const void *identity); +typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + struct PSI_file *file, enum PSI_file_operation op); +typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + File file, enum PSI_file_operation op); +typedef void (*unlock_mutex_v1_t) + (struct PSI_mutex *mutex); +typedef void (*unlock_rwlock_v1_t) + (struct PSI_rwlock *rwlock); +typedef void (*signal_cond_v1_t) + (struct PSI_cond *cond); +typedef void (*broadcast_cond_v1_t) + (struct PSI_cond *cond); +typedef struct PSI_idle_locker* (*start_idle_wait_v1_t) + (struct PSI_idle_locker_state_v1 *state, const char *src_file, uint src_line); +typedef void (*end_idle_wait_v1_t) + (struct PSI_idle_locker *locker); +typedef struct PSI_mutex_locker* (*start_mutex_wait_v1_t) + (struct PSI_mutex_locker_state_v1 *state, + struct PSI_mutex *mutex, + enum PSI_mutex_operation op, + const char *src_file, uint src_line); +typedef void (*end_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, int rc); +typedef struct PSI_rwlock_locker* (*start_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); +typedef void (*end_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); +typedef struct PSI_rwlock_locker* (*start_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); +typedef void (*end_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); +typedef struct PSI_cond_locker* (*start_cond_wait_v1_t) + (struct PSI_cond_locker_state_v1 *state, + struct PSI_cond *cond, + struct PSI_mutex *mutex, + enum PSI_cond_operation op, + const char *src_file, uint src_line); +typedef void (*end_cond_wait_v1_t) + (struct PSI_cond_locker *locker, int rc); +typedef struct PSI_table_locker* (*start_table_io_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_io_operation op, + uint index, + const char *src_file, uint src_line); +typedef void (*end_table_io_wait_v1_t) + (struct PSI_table_locker *locker, + ulonglong numrows); +typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_lock_operation op, + ulong flags, + const char *src_file, uint src_line); +typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker); +typedef void (*unlock_table_v1_t)(struct PSI_table *table); +typedef void (*start_file_open_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); +typedef struct PSI_file* (*end_file_open_wait_v1_t) + (struct PSI_file_locker *locker, void *result); +typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file); +typedef void (*end_temp_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file, const char *filename); +typedef void (*start_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count, + const char *src_file, uint src_line); +typedef void (*end_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count); +typedef void (*start_file_close_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); +typedef void (*end_file_close_wait_v1_t) + (struct PSI_file_locker *locker, int rc); +typedef void (*end_file_rename_wait_v1_t) + (struct PSI_file_locker *locker, const char *old_name, + const char *new_name, int rc); +typedef PSI_stage_progress* (*start_stage_v1_t) + (PSI_stage_key key, const char *src_file, int src_line); +typedef PSI_stage_progress* (*get_current_stage_progress_v1_t)(void); +typedef void (*end_stage_v1_t) (void); +typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t) + (struct PSI_statement_locker_state_v1 *state, + PSI_statement_key key, const void *charset, PSI_sp_share *sp_share); +typedef struct PSI_statement_locker* (*refine_statement_v1_t) + (struct PSI_statement_locker *locker, + PSI_statement_key key); +typedef void (*start_statement_v1_t) + (struct PSI_statement_locker *locker, + const char *db, uint db_length, + const char *src_file, uint src_line); +typedef void (*set_statement_text_v1_t) + (struct PSI_statement_locker *locker, + const char *text, uint text_len); +typedef void (*set_statement_lock_time_t) + (struct PSI_statement_locker *locker, ulonglong lock_time); +typedef void (*set_statement_rows_sent_t) + (struct PSI_statement_locker *locker, ulonglong count); +typedef void (*set_statement_rows_examined_t) + (struct PSI_statement_locker *locker, ulonglong count); +typedef void (*inc_statement_created_tmp_disk_tables_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_created_tmp_tables_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_full_join_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_full_range_join_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_range_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_range_check_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_scan_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_merge_passes_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_range_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_rows_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_scan_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*set_statement_no_index_used_t) + (struct PSI_statement_locker *locker); +typedef void (*set_statement_no_good_index_used_t) + (struct PSI_statement_locker *locker); +typedef void (*end_statement_v1_t) + (struct PSI_statement_locker *locker, void *stmt_da); +typedef struct PSI_transaction_locker* (*get_thread_transaction_locker_v1_t) + (struct PSI_transaction_locker_state_v1 *state, const void *xid, + ulonglong trxid, int isolation_level, my_bool read_only, + my_bool autocommit); +typedef void (*start_transaction_v1_t) + (struct PSI_transaction_locker *locker, + const char *src_file, uint src_line); +typedef void (*set_transaction_xid_v1_t) + (struct PSI_transaction_locker *locker, + const void *xid, int xa_state); +typedef void (*set_transaction_xa_state_v1_t) + (struct PSI_transaction_locker *locker, + int xa_state); +typedef void (*set_transaction_gtid_v1_t) + (struct PSI_transaction_locker *locker, + const void *sid, const void *gtid_spec); +typedef void (*set_transaction_trxid_v1_t) + (struct PSI_transaction_locker *locker, + const ulonglong *trxid); +typedef void (*inc_transaction_savepoints_v1_t) + (struct PSI_transaction_locker *locker, ulong count); +typedef void (*inc_transaction_rollback_to_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); +typedef void (*inc_transaction_release_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); +typedef void (*end_transaction_v1_t) + (struct PSI_transaction_locker *locker, + my_bool commit); +typedef struct PSI_socket_locker* (*start_socket_wait_v1_t) + (struct PSI_socket_locker_state_v1 *state, + struct PSI_socket *socket, + enum PSI_socket_operation op, + size_t count, + const char *src_file, uint src_line); +typedef void (*end_socket_wait_v1_t) + (struct PSI_socket_locker *locker, size_t count); +typedef void (*set_socket_state_v1_t)(struct PSI_socket *socket, + enum PSI_socket_state state); +typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket, + const my_socket *fd, + const struct sockaddr *addr, + socklen_t addr_len); +typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket); +typedef PSI_prepared_stmt* (*create_prepared_stmt_v1_t) + (void *identity, uint stmt_id, PSI_statement_locker *locker, + const char *stmt_name, size_t stmt_name_length); +typedef void (*destroy_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); +typedef void (*reprepare_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); +typedef void (*execute_prepared_stmt_v1_t) + (PSI_statement_locker *locker, PSI_prepared_stmt* prepared_stmt); +typedef void (*set_prepared_stmt_text_v1_t)(PSI_prepared_stmt *prepared_stmt, + const char *text, + uint text_len); +typedef struct PSI_digest_locker * (*digest_start_v1_t) + (struct PSI_statement_locker *locker); +typedef void (*digest_end_v1_t) + (struct PSI_digest_locker *locker, const struct sql_digest_storage *digest); +typedef PSI_sp_locker* (*start_sp_v1_t) + (struct PSI_sp_locker_state_v1 *state, struct PSI_sp_share* sp_share); +typedef void (*end_sp_v1_t) + (struct PSI_sp_locker *locker); +typedef void (*drop_sp_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); +typedef struct PSI_sp_share* (*get_sp_share_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); +typedef void (*release_sp_share_v1_t)(struct PSI_sp_share *share); +typedef PSI_metadata_lock* (*create_metadata_lock_v1_t) + (void *identity, + const MDL_key *key, + opaque_mdl_type mdl_type, + opaque_mdl_duration mdl_duration, + opaque_mdl_status mdl_status, + const char *src_file, + uint src_line); +typedef void (*set_metadata_lock_status_v1_t)(PSI_metadata_lock *lock, + opaque_mdl_status mdl_status); +typedef void (*destroy_metadata_lock_v1_t)(PSI_metadata_lock *lock); +typedef struct PSI_metadata_locker* (*start_metadata_wait_v1_t) + (struct PSI_metadata_locker_state_v1 *state, + struct PSI_metadata_lock *mdl, + const char *src_file, uint src_line); +typedef void (*end_metadata_wait_v1_t) + (struct PSI_metadata_locker *locker, int rc); +typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length, + const void *from_cs); +struct PSI_v1 +{ + register_mutex_v1_t register_mutex; + register_rwlock_v1_t register_rwlock; + register_cond_v1_t register_cond; + register_thread_v1_t register_thread; + register_file_v1_t register_file; + register_stage_v1_t register_stage; + register_statement_v1_t register_statement; + register_socket_v1_t register_socket; + init_mutex_v1_t init_mutex; + destroy_mutex_v1_t destroy_mutex; + init_rwlock_v1_t init_rwlock; + destroy_rwlock_v1_t destroy_rwlock; + init_cond_v1_t init_cond; + destroy_cond_v1_t destroy_cond; + init_socket_v1_t init_socket; + destroy_socket_v1_t destroy_socket; + get_table_share_v1_t get_table_share; + release_table_share_v1_t release_table_share; + drop_table_share_v1_t drop_table_share; + open_table_v1_t open_table; + unbind_table_v1_t unbind_table; + rebind_table_v1_t rebind_table; + close_table_v1_t close_table; + create_file_v1_t create_file; + spawn_thread_v1_t spawn_thread; + new_thread_v1_t new_thread; + set_thread_id_v1_t set_thread_id; + set_thread_THD_v1_t set_thread_THD; + set_thread_os_id_v1_t set_thread_os_id; + get_thread_v1_t get_thread; + set_thread_user_v1_t set_thread_user; + set_thread_account_v1_t set_thread_account; + set_thread_db_v1_t set_thread_db; + set_thread_command_v1_t set_thread_command; + set_connection_type_v1_t set_connection_type; + set_thread_start_time_v1_t set_thread_start_time; + set_thread_state_v1_t set_thread_state; + set_thread_info_v1_t set_thread_info; + set_thread_v1_t set_thread; + delete_current_thread_v1_t delete_current_thread; + delete_thread_v1_t delete_thread; + get_thread_file_name_locker_v1_t get_thread_file_name_locker; + get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; + get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; + unlock_mutex_v1_t unlock_mutex; + unlock_rwlock_v1_t unlock_rwlock; + signal_cond_v1_t signal_cond; + broadcast_cond_v1_t broadcast_cond; + start_idle_wait_v1_t start_idle_wait; + end_idle_wait_v1_t end_idle_wait; + start_mutex_wait_v1_t start_mutex_wait; + end_mutex_wait_v1_t end_mutex_wait; + start_rwlock_rdwait_v1_t start_rwlock_rdwait; + end_rwlock_rdwait_v1_t end_rwlock_rdwait; + start_rwlock_wrwait_v1_t start_rwlock_wrwait; + end_rwlock_wrwait_v1_t end_rwlock_wrwait; + start_cond_wait_v1_t start_cond_wait; + end_cond_wait_v1_t end_cond_wait; + start_table_io_wait_v1_t start_table_io_wait; + end_table_io_wait_v1_t end_table_io_wait; + start_table_lock_wait_v1_t start_table_lock_wait; + end_table_lock_wait_v1_t end_table_lock_wait; + start_file_open_wait_v1_t start_file_open_wait; + end_file_open_wait_v1_t end_file_open_wait; + end_file_open_wait_and_bind_to_descriptor_v1_t + end_file_open_wait_and_bind_to_descriptor; + end_temp_file_open_wait_and_bind_to_descriptor_v1_t + end_temp_file_open_wait_and_bind_to_descriptor; + start_file_wait_v1_t start_file_wait; + end_file_wait_v1_t end_file_wait; + start_file_close_wait_v1_t start_file_close_wait; + end_file_close_wait_v1_t end_file_close_wait; + end_file_rename_wait_v1_t end_file_rename_wait; + start_stage_v1_t start_stage; + get_current_stage_progress_v1_t get_current_stage_progress; + end_stage_v1_t end_stage; + get_thread_statement_locker_v1_t get_thread_statement_locker; + refine_statement_v1_t refine_statement; + start_statement_v1_t start_statement; + set_statement_text_v1_t set_statement_text; + set_statement_lock_time_t set_statement_lock_time; + set_statement_rows_sent_t set_statement_rows_sent; + set_statement_rows_examined_t set_statement_rows_examined; + inc_statement_created_tmp_disk_tables_t inc_statement_created_tmp_disk_tables; + inc_statement_created_tmp_tables_t inc_statement_created_tmp_tables; + inc_statement_select_full_join_t inc_statement_select_full_join; + inc_statement_select_full_range_join_t inc_statement_select_full_range_join; + inc_statement_select_range_t inc_statement_select_range; + inc_statement_select_range_check_t inc_statement_select_range_check; + inc_statement_select_scan_t inc_statement_select_scan; + inc_statement_sort_merge_passes_t inc_statement_sort_merge_passes; + inc_statement_sort_range_t inc_statement_sort_range; + inc_statement_sort_rows_t inc_statement_sort_rows; + inc_statement_sort_scan_t inc_statement_sort_scan; + set_statement_no_index_used_t set_statement_no_index_used; + set_statement_no_good_index_used_t set_statement_no_good_index_used; + end_statement_v1_t end_statement; + get_thread_transaction_locker_v1_t get_thread_transaction_locker; + start_transaction_v1_t start_transaction; + set_transaction_xid_v1_t set_transaction_xid; + set_transaction_xa_state_v1_t set_transaction_xa_state; + set_transaction_gtid_v1_t set_transaction_gtid; + set_transaction_trxid_v1_t set_transaction_trxid; + inc_transaction_savepoints_v1_t inc_transaction_savepoints; + inc_transaction_rollback_to_savepoint_v1_t inc_transaction_rollback_to_savepoint; + inc_transaction_release_savepoint_v1_t inc_transaction_release_savepoint; + end_transaction_v1_t end_transaction; + start_socket_wait_v1_t start_socket_wait; + end_socket_wait_v1_t end_socket_wait; + set_socket_state_v1_t set_socket_state; + set_socket_info_v1_t set_socket_info; + set_socket_thread_owner_v1_t set_socket_thread_owner; + create_prepared_stmt_v1_t create_prepared_stmt; + destroy_prepared_stmt_v1_t destroy_prepared_stmt; + reprepare_prepared_stmt_v1_t reprepare_prepared_stmt; + execute_prepared_stmt_v1_t execute_prepared_stmt; + set_prepared_stmt_text_v1_t set_prepared_stmt_text; + digest_start_v1_t digest_start; + digest_end_v1_t digest_end; + set_thread_connect_attrs_v1_t set_thread_connect_attrs; + start_sp_v1_t start_sp; + end_sp_v1_t end_sp; + drop_sp_v1_t drop_sp; + get_sp_share_v1_t get_sp_share; + release_sp_share_v1_t release_sp_share; + register_memory_v1_t register_memory; + memory_alloc_v1_t memory_alloc; + memory_realloc_v1_t memory_realloc; + memory_claim_v1_t memory_claim; + memory_free_v1_t memory_free; + unlock_table_v1_t unlock_table; + create_metadata_lock_v1_t create_metadata_lock; + set_metadata_lock_status_v1_t set_metadata_lock_status; + destroy_metadata_lock_v1_t destroy_metadata_lock; + start_metadata_wait_v1_t start_metadata_wait; + end_metadata_wait_v1_t end_metadata_wait; + set_thread_peer_port_v1_t set_thread_peer_port; +}; +typedef struct PSI_v1 PSI; +typedef struct PSI_mutex_info_v1 PSI_mutex_info; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; +typedef struct PSI_cond_info_v1 PSI_cond_info; +typedef struct PSI_thread_info_v1 PSI_thread_info; +typedef struct PSI_file_info_v1 PSI_file_info; +typedef struct PSI_stage_info_v1 PSI_stage_info; +typedef struct PSI_statement_info_v1 PSI_statement_info; +typedef struct PSI_transaction_info_v1 PSI_transaction_info; +typedef struct PSI_socket_info_v1 PSI_socket_info; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_abi_v2.h b/include/mysql/psi/psi_abi_v2.h new file mode 100644 index 00000000..fdbd36f2 --- /dev/null +++ b/include/mysql/psi/psi_abi_v2.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file mysql/psi/psi_abi_v1.h + ABI check for mysql/psi/psi.h, when using PSI_VERSION_2. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define USE_PSI_2 +#define HAVE_PSI_INTERFACE +#define MY_GLOBAL_INCLUDED +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v2.h.pp b/include/mysql/psi/psi_abi_v2.h.pp new file mode 100644 index 00000000..91889548 --- /dev/null +++ b/include/mysql/psi/psi_abi_v2.h.pp @@ -0,0 +1,279 @@ +extern "C" { +typedef unsigned int PSI_memory_key; +} +extern "C" { +struct PSI_thread; +struct PSI_memory_info_v2 +{ + int placeholder; +}; +typedef struct PSI_memory_info_v2 PSI_memory_info; +} +C_MODE_START +struct MDL_key; +typedef struct MDL_key MDL_key; +typedef int opaque_mdl_type; +typedef int opaque_mdl_duration; +typedef int opaque_mdl_status; +typedef int opaque_vio_type; +struct TABLE_SHARE; +struct sql_digest_storage; + class THD; +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; +struct PSI_cond; +typedef struct PSI_cond PSI_cond; +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; +struct PSI_table; +typedef struct PSI_table PSI_table; +struct PSI_thread; +typedef struct PSI_thread PSI_thread; +struct PSI_file; +typedef struct PSI_file PSI_file; +struct PSI_socket; +typedef struct PSI_socket PSI_socket; +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; +enum PSI_table_io_operation +{ + PSI_TABLE_FETCH_ROW= 0, + PSI_TABLE_WRITE_ROW= 1, + PSI_TABLE_UPDATE_ROW= 2, + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; +struct PSI_table_locker_state +{ + uint m_flags; + enum PSI_table_io_operation m_io_operation; + struct PSI_table *m_table; + struct PSI_table_share *m_table_share; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; +struct PSI_mutex_locker; +typedef struct PSI_mutex_locker PSI_mutex_locker; +struct PSI_rwlock_locker; +typedef struct PSI_rwlock_locker PSI_rwlock_locker; +struct PSI_cond_locker; +typedef struct PSI_cond_locker PSI_cond_locker; +struct PSI_file_locker; +typedef struct PSI_file_locker PSI_file_locker; +struct PSI_socket_locker; +typedef struct PSI_socket_locker PSI_socket_locker; +struct PSI_metadata_locker; +typedef struct PSI_metadata_locker PSI_metadata_locker; +enum PSI_mutex_operation +{ + PSI_MUTEX_LOCK= 0, + PSI_MUTEX_TRYLOCK= 1 +}; +typedef enum PSI_mutex_operation PSI_mutex_operation; +enum PSI_rwlock_operation +{ + PSI_RWLOCK_READLOCK= 0, + PSI_RWLOCK_WRITELOCK= 1, + PSI_RWLOCK_TRYREADLOCK= 2, + PSI_RWLOCK_TRYWRITELOCK= 3, + PSI_RWLOCK_SHAREDLOCK= 4, + PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, + PSI_RWLOCK_EXCLUSIVELOCK= 6, + PSI_RWLOCK_TRYSHAREDLOCK= 7, + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, + PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 +}; +typedef enum PSI_rwlock_operation PSI_rwlock_operation; +enum PSI_cond_operation +{ + PSI_COND_WAIT= 0, + PSI_COND_TIMEDWAIT= 1 +}; +typedef enum PSI_cond_operation PSI_cond_operation; +enum PSI_file_operation +{ + PSI_FILE_CREATE= 0, + PSI_FILE_CREATE_TMP= 1, + PSI_FILE_OPEN= 2, + PSI_FILE_STREAM_OPEN= 3, + PSI_FILE_CLOSE= 4, + PSI_FILE_STREAM_CLOSE= 5, + PSI_FILE_READ= 6, + PSI_FILE_WRITE= 7, + PSI_FILE_SEEK= 8, + PSI_FILE_TELL= 9, + PSI_FILE_FLUSH= 10, + PSI_FILE_STAT= 11, + PSI_FILE_FSTAT= 12, + PSI_FILE_CHSIZE= 13, + PSI_FILE_DELETE= 14, + PSI_FILE_RENAME= 15, + PSI_FILE_SYNC= 16 +}; +typedef enum PSI_file_operation PSI_file_operation; +enum PSI_table_lock_operation +{ + PSI_TABLE_LOCK= 0, + PSI_TABLE_EXTERNAL_LOCK= 1 +}; +typedef enum PSI_table_lock_operation PSI_table_lock_operation; +enum PSI_socket_state +{ + PSI_SOCKET_STATE_IDLE= 1, + PSI_SOCKET_STATE_ACTIVE= 2 +}; +typedef enum PSI_socket_state PSI_socket_state; +enum PSI_socket_operation +{ + PSI_SOCKET_CREATE= 0, + PSI_SOCKET_CONNECT= 1, + PSI_SOCKET_BIND= 2, + PSI_SOCKET_CLOSE= 3, + PSI_SOCKET_SEND= 4, + PSI_SOCKET_RECV= 5, + PSI_SOCKET_SENDTO= 6, + PSI_SOCKET_RECVFROM= 7, + PSI_SOCKET_SENDMSG= 8, + PSI_SOCKET_RECVMSG= 9, + PSI_SOCKET_SEEK= 10, + PSI_SOCKET_OPT= 11, + PSI_SOCKET_STAT= 12, + PSI_SOCKET_SHUTDOWN= 13, + PSI_SOCKET_SELECT= 14 +}; +typedef enum PSI_socket_operation PSI_socket_operation; +typedef unsigned int PSI_mutex_key; +typedef unsigned int PSI_rwlock_key; +typedef unsigned int PSI_cond_key; +typedef unsigned int PSI_thread_key; +typedef unsigned int PSI_file_key; +typedef unsigned int PSI_stage_key; +typedef unsigned int PSI_statement_key; +typedef unsigned int PSI_socket_key; +struct PSI_v2 +{ + int placeholder; +}; +struct PSI_mutex_info_v2 +{ + int placeholder; +}; +struct PSI_rwlock_info_v2 +{ + int placeholder; +}; +struct PSI_cond_info_v2 +{ + int placeholder; +}; +struct PSI_thread_info_v2 +{ + int placeholder; +}; +struct PSI_file_info_v2 +{ + int placeholder; +}; +struct PSI_stage_info_v2 +{ + int placeholder; +}; +struct PSI_statement_info_v2 +{ + int placeholder; +}; +struct PSI_transaction_info_v2 +{ + int placeholder; +}; +struct PSI_idle_locker_state_v2 +{ + int placeholder; +}; +struct PSI_mutex_locker_state_v2 +{ + int placeholder; +}; +struct PSI_rwlock_locker_state_v2 +{ + int placeholder; +}; +struct PSI_cond_locker_state_v2 +{ + int placeholder; +}; +struct PSI_file_locker_state_v2 +{ + int placeholder; +}; +struct PSI_statement_locker_state_v2 +{ + int placeholder; +}; +struct PSI_transaction_locker_state_v2 +{ + int placeholder; +}; +struct PSI_socket_locker_state_v2 +{ + int placeholder; +}; +struct PSI_metadata_locker_state_v2 +{ + int placeholder; +}; +typedef struct PSI_v2 PSI; +typedef struct PSI_mutex_info_v2 PSI_mutex_info; +typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; +typedef struct PSI_cond_info_v2 PSI_cond_info; +typedef struct PSI_thread_info_v2 PSI_thread_info; +typedef struct PSI_file_info_v2 PSI_file_info; +typedef struct PSI_stage_info_v2 PSI_stage_info; +typedef struct PSI_statement_info_v2 PSI_statement_info; +typedef struct PSI_transaction_info_v2 PSI_transaction_info; +typedef struct PSI_socket_info_v2 PSI_socket_info; +typedef struct PSI_idle_locker_state_v2 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v2 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v2 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v2 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v2 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v2 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v2 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v2 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v2 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v2 PSI_metadata_locker_state; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_base.h b/include/mysql/psi/psi_base.h new file mode 100644 index 00000000..6cf53195 --- /dev/null +++ b/include/mysql/psi/psi_base.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PSI_BASE_H +#define MYSQL_PSI_BASE_H + +#ifdef EMBEDDED_LIBRARY +#define DISABLE_ALL_PSI +#endif /* EMBEDDED_LIBRARY */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @file mysql/psi/psi_base.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +#define PSI_INSTRUMENT_ME 0 +#define PSI_INSTRUMENT_MEM ((PSI_memory_key)0) + +#define PSI_NOT_INSTRUMENTED 0 + +/** + Global flag. + This flag indicate that an instrumentation point is a global variable, + or a singleton. +*/ +#define PSI_FLAG_GLOBAL (1 << 0) + +/** + Mutable flag. + This flag indicate that an instrumentation point is a general placeholder, + that can mutate into a more specific instrumentation point. +*/ +#define PSI_FLAG_MUTABLE (1 << 1) + +#define PSI_FLAG_THREAD (1 << 2) + +/** + Stage progress flag. + This flag apply to the stage instruments only. + It indicates the instrumentation provides progress data. +*/ +#define PSI_FLAG_STAGE_PROGRESS (1 << 3) + +/** + Shared Exclusive flag. + Indicates that rwlock support the shared exclusive state. +*/ +#define PSI_RWLOCK_FLAG_SX (1 << 4) + +/** + Transferable flag. + This flag indicate that an instrumented object can + be created by a thread and destroyed by another thread. +*/ +#define PSI_FLAG_TRANSFER (1 << 5) + +/** + Volatility flag. + This flag indicate that an instrumented object + has a volatility (life cycle) comparable + to the volatility of a session. +*/ +#define PSI_FLAG_VOLATILITY_SESSION (1 << 6) + +/** + System thread flag. + Indicates that the instrumented object exists on a system thread. +*/ +#define PSI_FLAG_THREAD_SYSTEM (1 << 9) + +#ifdef HAVE_PSI_INTERFACE + +/** + @def PSI_VERSION_1 + Performance Schema Interface number for version 1. + This version is supported. +*/ +#define PSI_VERSION_1 1 + +/** + @def PSI_VERSION_2 + Performance Schema Interface number for version 2. + This version is not implemented, it's a placeholder. +*/ +#define PSI_VERSION_2 2 + +/** + @def PSI_CURRENT_VERSION + Performance Schema Interface number for the most recent version. + The most current version is @c PSI_VERSION_1 +*/ +#define PSI_CURRENT_VERSION 1 + +/** + @def USE_PSI_1 + Define USE_PSI_1 to use the interface version 1. +*/ + +/** + @def USE_PSI_2 + Define USE_PSI_2 to use the interface version 2. +*/ + +/** + @def HAVE_PSI_1 + Define HAVE_PSI_1 if the interface version 1 needs to be compiled in. +*/ + +/** + @def HAVE_PSI_2 + Define HAVE_PSI_2 if the interface version 2 needs to be compiled in. +*/ + +#ifndef USE_PSI_2 +#ifndef USE_PSI_1 +#define USE_PSI_1 +#endif +#endif + +#ifdef USE_PSI_1 +#define HAVE_PSI_1 +#endif + +#ifdef USE_PSI_2 +#define HAVE_PSI_2 +#endif + +/* + Allow to override PSI_XXX_CALL at compile time + with more efficient implementations, if available. + If nothing better is available, + make a dynamic call using the PSI_server function pointer. +*/ + +#define PSI_DYNAMIC_CALL(M) PSI_server->M + +#endif /* HAVE_PSI_INTERFACE */ + +/** @} */ + +/** + Instrumented memory key. + To instrument memory, a memory key must be obtained using @c register_memory. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_memory_key; + +#ifdef __cplusplus +} +#endif + +#endif /* MYSQL_PSI_BASE_H */ + diff --git a/include/mysql/psi/psi_memory.h b/include/mysql/psi/psi_memory.h new file mode 100644 index 00000000..f06ec525 --- /dev/null +++ b/include/mysql/psi/psi_memory.h @@ -0,0 +1,164 @@ +/* Copyright (c) 2013, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PSI_MEMORY_H +#define MYSQL_PSI_MEMORY_H + +#include "psi_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @file mysql/psi/psi_memory.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +#ifdef HAVE_PSI_INTERFACE +#ifndef DISABLE_ALL_PSI +#ifndef DISABLE_PSI_MEMORY +#define HAVE_PSI_MEMORY_INTERFACE +#endif /* DISABLE_PSI_MEMORY */ +#endif /* DISABLE_ALL_PSI */ +#endif /* HAVE_PSI_INTERFACE */ + +struct PSI_thread; + +#ifdef HAVE_PSI_1 + +/** + @defgroup Group_PSI_v1 Application Binary Interface, version 1 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Memory instrument information. + @since PSI_VERSION_1 + This structure is used to register instrumented memory. +*/ +struct PSI_memory_info_v1 +{ + /** Pointer to the key assigned to the registered memory. */ + PSI_memory_key *m_key; + /** The name of the memory instrument to register. */ + const char *m_name; + /** + The flags of the socket instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_memory_info_v1 PSI_memory_info_v1; + +/** + Memory registration API. + @param category a category name (typically a plugin name) + @param info an array of memory info to register + @param count the size of the info array +*/ +typedef void (*register_memory_v1_t) + (const char *category, struct PSI_memory_info_v1 *info, int count); + +/** + Instrument memory allocation. + @param key the memory instrument key + @param size the size of memory allocated + @param[out] owner the memory owner + @return the effective memory instrument key +*/ +typedef PSI_memory_key (*memory_alloc_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); + +/** + Instrument memory re allocation. + @param key the memory instrument key + @param old_size the size of memory previously allocated + @param new_size the size of memory re allocated + @param[in, out] owner the memory owner + @return the effective memory instrument key +*/ +typedef PSI_memory_key (*memory_realloc_v1_t) + (PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner); + +/** + Instrument memory claim. + @param key the memory instrument key + @param size the size of memory allocated + @param[in, out] owner the memory owner + @return the effective memory instrument key +*/ +typedef PSI_memory_key (*memory_claim_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); + +/** + Instrument memory free. + @param key the memory instrument key + @param size the size of memory allocated + @param owner the memory owner +*/ +typedef void (*memory_free_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread * owner); + +/** @} (end of group Group_PSI_v1) */ + +#ifdef _AIX +PSI_memory_key key_memory_log_event; +#endif + +#endif /* HAVE_PSI_1 */ + +#ifdef HAVE_PSI_2 +struct PSI_memory_info_v2 +{ + int placeholder; +}; + +#endif /* HAVE_PSI_2 */ + +#ifdef USE_PSI_1 +typedef struct PSI_memory_info_v1 PSI_memory_info; +#endif + +#ifdef USE_PSI_2 +typedef struct PSI_memory_info_v2 PSI_memory_info; +#endif + +/** @} (end of group Instrumentation_interface) */ + +#ifdef __cplusplus +} +#endif + + +#endif /* MYSQL_PSI_MEMORY_H */ + diff --git a/include/mysql/service_base64.h b/include/mysql/service_base64.h new file mode 100644 index 00000000..fa54b492 --- /dev/null +++ b/include/mysql/service_base64.h @@ -0,0 +1,82 @@ +#ifndef MYSQL_SERVICE_BASE64_INCLUDED +/* Copyright (c) 2017, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my base64 service + + Functions for base64 en- and decoding +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +/* Allow multiple chunks 'AAA= AA== AA==', binlog uses this */ +#define MY_BASE64_DECODE_ALLOW_MULTIPLE_CHUNKS 1 + +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_base64_needed_encoded_length(A) base64_service->base64_needed_encoded_length_ptr(A) +#define my_base64_encode_max_arg_length() base64_service->base64_encode_max_arg_length_ptr() +#define my_base64_needed_decoded_length(A) base64_service->base64_needed_decoded_length_ptr(A) +#define my_base64_decode_max_arg_length() base64_service->base64_decode_max_arg_length_ptr() +#define my_base64_encode(A,B,C) base64_service->base64_encode_ptr(A,B,C) +#define my_base64_decode(A,B,C,D,E) base64_service->base64_decode_ptr(A,B,C,D,E) + +#else + +/* Calculate how much memory needed for dst of my_base64_encode() */ +int my_base64_needed_encoded_length(int length_of_data); + +/* Maximum length my_base64_encode_needed_length() can accept with no overflow. */ +int my_base64_encode_max_arg_length(void); + +/* Calculate how much memory needed for dst of my_base64_decode() */ +int my_base64_needed_decoded_length(int length_of_encoded_data); + +/* Maximum length my_base64_decode_needed_length() can accept with no overflow. */ +int my_base64_decode_max_arg_length(); + +/* Encode data as a my_base64 string */ +int my_base64_encode(const void *src, size_t src_len, char *dst); + +/* Decode a my_base64 string into data */ +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_BASE64_INCLUDED +#endif diff --git a/include/mysql/service_debug_sync.h b/include/mysql/service_debug_sync.h new file mode 100644 index 00000000..0bd49a13 --- /dev/null +++ b/include/mysql/service_debug_sync.h @@ -0,0 +1,361 @@ +#ifndef MYSQL_SERVICE_DEBUG_SYNC_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, Monty Program Ab + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + == Debug Sync Facility == + + The Debug Sync Facility allows placement of synchronization points in + the server code by using the DEBUG_SYNC macro: + + open_tables(...) + + DEBUG_SYNC(thd, "after_open_tables"); + + lock_tables(...) + + When activated, a sync point can + + - Emit a signal and/or + - Wait for a signal + + Nomenclature: + + - signal: A value of a global variable that persists + until overwritten by a new signal. The global + variable can also be seen as a "signal post" + or "flag mast". Then the signal is what is + attached to the "signal post" or "flag mast". + + - emit a signal: Assign the value (the signal) to the global + variable ("set a flag") and broadcast a + global condition to wake those waiting for + a signal. + + - wait for a signal: Loop over waiting for the global condition until + the global value matches the wait-for signal. + + By default, all sync points are inactive. They do nothing (except to + burn a couple of CPU cycles for checking if they are active). + + A sync point becomes active when an action is requested for it. + To do so, put a line like this in the test case file: + + SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; + + This activates the sync point 'after_open_tables'. It requests it to + emit the signal 'opened' and wait for another thread to emit the signal + 'flushed' when the thread's execution runs through the sync point. + + For every sync point there can be one action per thread only. Every + thread can request multiple actions, but only one per sync point. In + other words, a thread can activate multiple sync points. + + Here is an example how to activate and use the sync points: + + --connection conn1 + SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; + send INSERT INTO t1 VALUES(1); + --connection conn2 + SET DEBUG_SYNC= 'now WAIT_FOR opened'; + SET DEBUG_SYNC= 'after_abort_locks SIGNAL flushed'; + FLUSH TABLE t1; + + When conn1 runs through the INSERT statement, it hits the sync point + 'after_open_tables'. It notices that it is active and executes its + action. It emits the signal 'opened' and waits for another thread to + emit the signal 'flushed'. + + conn2 waits immediately at the special sync point 'now' for another + thread to emit the 'opened' signal. + + A signal remains in effect until it is overwritten. If conn1 signals + 'opened' before conn2 reaches 'now', conn2 will still find the 'opened' + signal. It does not wait in this case. + + When conn2 reaches 'after_abort_locks', it signals 'flushed', which lets + conn1 awake. + + Normally the activation of a sync point is cleared when it has been + executed. Sometimes it is necessary to keep the sync point active for + another execution. You can add an execute count to the action: + + SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 3'; + + This sets the signal point's activation counter to 3. Each execution + decrements the counter. After the third execution the sync point + becomes inactive. + + One of the primary goals of this facility is to eliminate sleeps from + the test suite. In most cases it should be possible to rewrite test + cases so that they do not need to sleep. (But this facility cannot + synchronize multiple processes.) However, to support test development, + and as a last resort, sync point waiting times out. There is a default + timeout, but it can be overridden: + + SET DEBUG_SYNC= 'name WAIT_FOR sig TIMEOUT 10 EXECUTE 2'; + + TIMEOUT 0 is special: If the signal is not present, the wait times out + immediately. + + When a wait timed out (even on TIMEOUT 0), a warning is generated so + that it shows up in the test result. + + You can throw an error message and kill the query when a synchronization + point is hit a certain number of times: + + SET DEBUG_SYNC= 'name HIT_LIMIT 3'; + + Or combine it with signal and/or wait: + + SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 2 HIT_LIMIT 3'; + + Here the first two hits emit the signal, the third hit returns the error + message and kills the query. + + For cases where you are not sure that an action is taken and thus + cleared in any case, you can force to clear (deactivate) a sync point: + + SET DEBUG_SYNC= 'name CLEAR'; + + If you want to clear all actions and clear the global signal, use: + + SET DEBUG_SYNC= 'RESET'; + + This is the only way to reset the global signal to an empty string. + + For testing of the facility itself you can execute a sync point just + as if it had been hit: + + SET DEBUG_SYNC= 'name TEST'; + + + === Formal Syntax === + + The string to "assign" to the DEBUG_SYNC variable can contain: + + {RESET | + <sync point name> TEST | + <sync point name> CLEAR | + <sync point name> {{SIGNAL <signal name> | + WAIT_FOR <signal name> [TIMEOUT <seconds>]} + [EXECUTE <count>] &| HIT_LIMIT <count>} + + Here '&|' means 'and/or'. This means that one of the sections + separated by '&|' must be present or both of them. + + + === Activation/Deactivation === + + The facility is an optional part of the MySQL server. + It is enabled in a debug server by default. + + ./configure --enable-debug-sync + + The Debug Sync Facility, when compiled in, is disabled by default. It + can be enabled by a mysqld command line option: + + --debug-sync-timeout[=default_wait_timeout_value_in_seconds] + + 'default_wait_timeout_value_in_seconds' is the default timeout for the + WAIT_FOR action. If set to zero, the facility stays disabled. + + The facility is enabled by default in the test suite, but can be + disabled with: + + mysql-test-run.pl ... --debug-sync-timeout=0 ... + + Likewise the default wait timeout can be set: + + mysql-test-run.pl ... --debug-sync-timeout=10 ... + + The command line option influences the readable value of the system + variable 'debug_sync'. + + * If the facility is not compiled in, the system variable does not exist. + + * If --debug-sync-timeout=0 the value of the variable reads as "OFF". + + * Otherwise the value reads as "ON - current signal: " followed by the + current signal string, which can be empty. + + The readable variable value is the same, regardless if read as global + or session value. + + Setting the 'debug-sync' system variable requires 'SUPER' privilege. + You can never read back the string that you assigned to the variable, + unless you assign the value that the variable does already have. But + that would give a parse error. A syntactically correct string is + parsed into a debug sync action and stored apart from the variable value. + + + === Implementation === + + Pseudo code for a sync point: + + #define DEBUG_SYNC(thd, sync_point_name) + if (unlikely(opt_debug_sync_timeout)) + debug_sync(thd, STRING_WITH_LEN(sync_point_name)) + + The sync point performs a binary search in a sorted array of actions + for this thread. + + The SET DEBUG_SYNC statement adds a requested action to the array or + overwrites an existing action for the same sync point. When it adds a + new action, the array is sorted again. + + + === A typical synchronization pattern === + + There are quite a few places in MySQL, where we use a synchronization + pattern like this: + + mysql_mutex_lock(&mutex); + thd->enter_cond(&condition_variable, &mutex, new_message); + #if defined(ENABLE_DEBUG_SYNC) + if (!thd->killed && !end_of_wait_condition) + DEBUG_SYNC(thd, "sync_point_name"); + #endif + while (!thd->killed && !end_of_wait_condition) + mysql_cond_wait(&condition_variable, &mutex); + thd->exit_cond(old_message); + + Here some explanations: + + thd->enter_cond() is used to register the condition variable and the + mutex in thd->mysys_var. This is done to allow the thread to be + interrupted (killed) from its sleep. Another thread can find the + condition variable to signal and mutex to use for synchronization in + this thread's THD::mysys_var. + + thd->enter_cond() requires the mutex to be acquired in advance. + + thd->exit_cond() unregisters the condition variable and mutex and + releases the mutex. + + If you want to have a Debug Sync point with the wait, please place it + behind enter_cond(). Only then you can safely decide, if the wait will + be taken. Also you will have THD::proc_info correct when the sync + point emits a signal. DEBUG_SYNC sets its own proc_info, but restores + the previous one before releasing its internal mutex. As soon as + another thread sees the signal, it does also see the proc_info from + before entering the sync point. In this case it will be "new_message", + which is associated with the wait that is to be synchronized. + + In the example above, the wait condition is repeated before the sync + point. This is done to skip the sync point, if no wait takes place. + The sync point is before the loop (not inside the loop) to have it hit + once only. It is possible that the condition variable is signaled + multiple times without the wait condition to be true. + + A bit off-topic: At some places, the loop is taken around the whole + synchronization pattern: + + while (!thd->killed && !end_of_wait_condition) + { + mysql_mutex_lock(&mutex); + thd->enter_cond(&condition_variable, &mutex, new_message); + if (!thd->killed [&& !end_of_wait_condition]) + { + [DEBUG_SYNC(thd, "sync_point_name");] + mysql_cond_wait(&condition_variable, &mutex); + } + thd->exit_cond(old_message); + } + + Note that it is important to repeat the test for thd->killed after + enter_cond(). Otherwise the killing thread may kill this thread after + it tested thd->killed in the loop condition and before it registered + the condition variable and mutex in enter_cond(). In this case, the + killing thread does not know that this thread is going to wait on a + condition variable. It would just set THD::killed. But if we would not + test it again, we would go asleep though we are killed. If the killing + thread would kill us when we are after the second test, but still + before sleeping, we hold the mutex, which is registered in mysys_var. + The killing thread would try to acquire the mutex before signaling + the condition variable. Since the mutex is only released implicitly in + mysql_cond_wait(), the signaling happens at the right place. We + have a safe synchronization. + + === Co-work with the DBUG facility === + + When running the MySQL test suite with the --debug-dbug command line + option, the Debug Sync Facility writes trace messages to the DBUG + trace. The following shell commands proved very useful in extracting + relevant information: + + egrep 'query:|debug_sync_exec:' mysql-test/var/log/mysqld.1.trace + + It shows all executed SQL statements and all actions executed by + synchronization points. + + Sometimes it is also useful to see, which synchronization points have + been run through (hit) with or without executing actions. Then add + "|debug_sync_point:" to the egrep pattern. + + === Further reading === + + For a discussion of other methods to synchronize threads see + http://forge.mysql.com/wiki/MySQL_Internals_Test_Synchronization + + For complete syntax tests, functional tests, and examples see the test + case debug_sync.test. + + See also http://forge.mysql.com/worklog/task.php?id=4259 +*/ + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef MYSQL_DYNAMIC_PLUGIN +extern void (*debug_sync_service)(MYSQL_THD, const char *, size_t); +#else +#define debug_sync_service debug_sync_C_callback_ptr +extern void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t); +#endif + +#ifdef ENABLED_DEBUG_SYNC +#define DEBUG_SYNC(thd, name) \ + do { \ + if (debug_sync_service) \ + debug_sync_service(thd, STRING_WITH_LEN(name)); \ + } while(0) + +#define DEBUG_SYNC_C_IF_THD(thd, name) \ + do { \ + if (debug_sync_service && thd) \ + debug_sync_service((MYSQL_THD) thd, STRING_WITH_LEN(name)); \ + } while(0) +#else +#define DEBUG_SYNC(thd,name) do { } while(0) +#define DEBUG_SYNC_C_IF_THD(thd, _sync_point_name_) do { } while(0) +#endif /* defined(ENABLED_DEBUG_SYNC) */ + +/* compatibility macro */ +#define DEBUG_SYNC_C(name) DEBUG_SYNC(NULL, name) + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_DEBUG_SYNC_INCLUDED +#endif diff --git a/include/mysql/service_encryption.h b/include/mysql/service_encryption.h new file mode 100644 index 00000000..49639407 --- /dev/null +++ b/include/mysql/service_encryption.h @@ -0,0 +1,127 @@ +#ifndef MYSQL_SERVICE_ENCRYPTION_INCLUDED +/* Copyright (c) 2015, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + encryption service + + Functions to support data encryption and encryption key management. + They are normally implemented in an encryption plugin, so this service + connects encryption *consumers* (e.g. storage engines) to the encryption + *provider* (encryption plugin). +*/ + +#ifndef MYSQL_ABI_CHECK +#include <my_alloca.h> +#ifdef _WIN32 +#ifndef __cplusplus +#define inline __inline +#endif +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* returned from encryption_key_get_latest_version() */ +#define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0) +#define ENCRYPTION_KEY_NOT_ENCRYPTED (0) + +#define ENCRYPTION_KEY_SYSTEM_DATA 1 +#define ENCRYPTION_KEY_TEMPORARY_DATA 2 + +/* returned from encryption_key_get() */ +#define ENCRYPTION_KEY_BUFFER_TOO_SMALL (100) + +#define ENCRYPTION_FLAG_DECRYPT 0 +#define ENCRYPTION_FLAG_ENCRYPT 1 +#define ENCRYPTION_FLAG_NOPAD 2 + +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +extern struct encryption_service_st *encryption_service; + +#define encryption_key_get_latest_version(KI) encryption_service->encryption_key_get_latest_version_func(KI) +#define encryption_key_get(KI,KV,K,S) encryption_service->encryption_key_get_func((KI),(KV),(K),(S)) +#define encryption_ctx_size(KI,KV) encryption_service->encryption_ctx_size_func((KI),(KV)) +#define encryption_ctx_init(CTX,K,KL,IV,IVL,F,KI,KV) encryption_service->encryption_ctx_init_func((CTX),(K),(KL),(IV),(IVL),(F),(KI),(KV)) +#define encryption_ctx_update(CTX,S,SL,D,DL) encryption_service->encryption_ctx_update_func((CTX),(S),(SL),(D),(DL)) +#define encryption_ctx_finish(CTX,D,DL) encryption_service->encryption_ctx_finish_func((CTX),(D),(DL)) +#define encryption_encrypted_length(SL,KI,KV) encryption_service->encryption_encrypted_length_func((SL),(KI),(KV)) +#else + +extern struct encryption_service_st encryption_handler; + +#define encryption_key_get_latest_version(KI) encryption_handler.encryption_key_get_latest_version_func(KI) +#define encryption_key_get(KI,KV,K,S) encryption_handler.encryption_key_get_func((KI),(KV),(K),(S)) +#define encryption_ctx_size(KI,KV) encryption_handler.encryption_ctx_size_func((KI),(KV)) +#define encryption_ctx_init(CTX,K,KL,IV,IVL,F,KI,KV) encryption_handler.encryption_ctx_init_func((CTX),(K),(KL),(IV),(IVL),(F),(KI),(KV)) +#define encryption_ctx_update(CTX,S,SL,D,DL) encryption_handler.encryption_ctx_update_func((CTX),(S),(SL),(D),(DL)) +#define encryption_ctx_finish(CTX,D,DL) encryption_handler.encryption_ctx_finish_func((CTX),(D),(DL)) +#define encryption_encrypted_length(SL,KI,KV) encryption_handler.encryption_encrypted_length_func((SL),(KI),(KV)) +#endif + +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_key_get_latest_version(id) != ENCRYPTION_KEY_VERSION_INVALID; +} + +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_key_get(id, version, NULL, &unused) != ENCRYPTION_KEY_VERSION_INVALID; +} + +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_ctx_size(key_id, key_version)); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_ctx_init(ctx, key, klen, iv, ivlen, flags, key_id, key_version))) + return res1; + res1= encryption_ctx_update(ctx, src, slen, dst, &d1); + res2= encryption_ctx_finish(ctx, dst + d1, &d2); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_ENCRYPTION_INCLUDED +#endif + diff --git a/include/mysql/service_encryption_scheme.h b/include/mysql/service_encryption_scheme.h new file mode 100644 index 00000000..bcd4d646 --- /dev/null +++ b/include/mysql/service_encryption_scheme.h @@ -0,0 +1,133 @@ +#ifndef MYSQL_SERVICE_ENCRYPTION_SCHEME_INCLUDED +/* Copyright (c) 2015, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + encryption scheme service + + A higher-level access to encryption service. + + This is a helper service that storage engines use to encrypt tables on disk. + It requests keys from the plugin, generates temporary or local keys + from the global (as returned by the plugin) keys, etc. + + To use the service: + + * st_encryption_scheme object is created per space. A "space" can be + a table space in XtraDB/InnoDB, a file in Aria, etc. The whole + space is encrypted with the one key id. + + * The service does not take the key and the IV as parameters for + encryption or decryption. Instead it takes two 32-bit integers and + one 64-bit integer (and requests the key from an encryption + plugin, if needed). + + * The service requests the global key from the encryption plugin + automatically as needed. Three last keys are cached in the + st_encryption_scheme. Number of key requests (number of cache + misses) are counted in st_encryption_scheme::keyserver_requests + + * If an st_encryption_scheme can be used concurrently by different + threads, it needs to be able to lock itself when accessing the key + cache. Set the st_encryption_scheme::locker appropriately. If + non-zero, it will be invoked by encrypt/decrypt functions to lock + and unlock the scheme when needed. + + * Implementation details (in particular, key derivation) are defined + by the scheme type. Currently only schema type 1 is supported. + + In the schema type 1, every "space" (table space in XtraDB/InnoDB, + file in Aria) is encrypted with a different space-local key: + + * Every space has a 16-byte unique identifier (typically it's + generated randomly and stored in the space). The caller should + put it into st_encryption_scheme::iv. + + * Space-local key is generated by encrypting this identifier with + the global encryption key (of the given id and version) using AES_ECB. + + * Encryption/decryption parameters for a page are typically the + 4-byte space id, 4-byte page position (offset, page number, etc), + and the 8-byte LSN. This guarantees that they'll be different for + any two pages (of the same or different tablespaces) and also that + they'll change for the same page when it's modified. They don't need + to be secret (they create the IV, not the encryption key). +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ENCRYPTION_SCHEME_KEY_INVALID -1 +#define ENCRYPTION_SCHEME_BLOCK_LENGTH 16 + +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[ENCRYPTION_SCHEME_BLOCK_LENGTH]; +}; + +struct st_encryption_scheme { + unsigned char iv[ENCRYPTION_SCHEME_BLOCK_LENGTH]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + + void (*locker)(struct st_encryption_scheme *self, int release); +}; + +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define encryption_scheme_encrypt(S,SL,D,DL,SCH,KV,I32,J32,I64) encryption_scheme_service->encryption_scheme_encrypt_func(S,SL,D,DL,SCH,KV,I32,J32,I64) +#define encryption_scheme_decrypt(S,SL,D,DL,SCH,KV,I32,J32,I64) encryption_scheme_service->encryption_scheme_decrypt_func(S,SL,D,DL,SCH,KV,I32,J32,I64) + +#else + +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + +#endif + + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_ENCRYPTION_SCHEME_INCLUDED +#endif diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h new file mode 100644 index 00000000..cb748c0c --- /dev/null +++ b/include/mysql/service_json.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#ifndef MYSQL_SERVICE_JSON +#define MYSQL_SERVICE_JSON + +/** + @file + json service + + Exports JSON parsing methods for plugins to use. + + Functions of the service: + json_type - returns the type of the JSON argument, + and the parsed value if it's scalar (not object or array) + + json_get_array_item - expects JSON array as an argument, + and returns the type of the element at index `n_item`. + Returns JSV_NOTHING type if the array is shorter + than n_item and the actual length of the array in value_len. + If successful, then `value` up till `value[value_len]` contains the array + element at the desired index (n_item). + + json_get_object_key - expects JSON object as an argument, + searches for a key in the object, return it's type and stores its value in `value`. + JSV_NOTHING if no such key found, the number of keys + in v_len. + + json_get_object_nkey - expects JSON object as an argument. + finds n_key's key in the object, returns it's name, type and value. + JSV_NOTHING if object has less keys than n_key. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; + +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define json_type json_service->json_type +#define json_get_array_item json_service->json_get_array_item +#define json_get_object_key json_service->json_get_object_key +#define json_get_object_nkey json_service->json_get_object_nkey +#define json_escape_string json_service->json_escape_string +#define json_unescape_json json_service->json_unescape_json + +#else + +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); + +#endif /*MYSQL_DYNAMIC_PLUGIN*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_JSON */ + + diff --git a/include/mysql/service_kill_statement.h b/include/mysql/service_kill_statement.h new file mode 100644 index 00000000..9f3415a7 --- /dev/null +++ b/include/mysql/service_kill_statement.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2013, 2018, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_KILL_STATEMENT_INCLUDED +#define MYSQL_SERVICE_KILL_STATEMENT_INCLUDED + +/** + @file + This service provides functions that allow plugins to support + the KILL statement. + + In MySQL support for the KILL statement is cooperative. The KILL + statement only sets a "killed" flag. This function returns the value + of that flag. A thread should check it often, especially inside + time-consuming loops, and gracefully abort the operation if it is + non-zero. + + thd_killed(thd) + @return 0 - no KILL statement was issued, continue normally + @return 1 - there was a KILL statement, abort the execution. + + thd_kill_level(thd) + @return thd_kill_levels_enum values +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, /**< abort when possible, don't leave tables corrupted */ + THD_ABORT_ASAP=100, /**< abort asap */ +}; + +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const MYSQL_THD); +} *thd_kill_statement_service; + +/* backward compatibility helper */ +#define thd_killed(THD) (thd_kill_level(THD) == THD_ABORT_ASAP) + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_kill_level(THD) \ + thd_kill_statement_service->thd_kill_level_func(THD) + +#else + +enum thd_kill_levels thd_kill_level(const MYSQL_THD); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/service_logger.h b/include/mysql/service_logger.h new file mode 100644 index 00000000..5979901b --- /dev/null +++ b/include/mysql/service_logger.h @@ -0,0 +1,105 @@ +/* Copyright (C) 2012 Monty Program Ab + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_LOGGER_INCLUDED +#define MYSQL_SERVICE_LOGGER_INCLUDED + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#endif + +/** + @file + logger service + + Log file with rotation implementation. + + This service implements logging with possible rotation + of the log files. Interface intentionally tries to be similar to FILE* + related functions. + + So that one can open the log with logger_open(), specifying + the limit on the logfile size and the rotations number. + + Then it's possible to write messages to the log with + logger_printf or logger_vprintf functions. + + As the size of the logfile grows over the specified limit, + it is renamed to 'logfile.1'. The former 'logfile.1' becomes + 'logfile.2', etc. The file 'logfile.rotations' is removed. + That's how the rotation works. + + The rotation can be forced with the logger_rotate() call. + + Finally the log should be closed with logger_close(). + +@notes: + Implementation checks the size of the log file before it starts new + printf into it. So the size of the file gets over the limit when it rotates. + + The access is secured with the mutex, so the log is threadsafe. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct logger_handle_st LOGGER_HANDLE; + +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define logger_init_mutexes logger_service->logger_init_mutexes +#define logger_open(path, size_limit, rotations) \ + (logger_service->open(path, size_limit, rotations)) +#define logger_close(log) (logger_service->close(log)) +#define logger_rotate(log) (logger_service->rotate(log)) +#define logger_vprintf(log, fmt, argptr) (logger_service->\ + vprintf(log, fmt, argptr)) +#define logger_printf (*logger_service->printf) +#define logger_write(log, buffer, size) \ + (logger_service->write(log, buffer, size)) +#else + + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_LOGGER_INCLUDED*/ + diff --git a/include/mysql/service_md5.h b/include/mysql/service_md5.h new file mode 100644 index 00000000..336cf70f --- /dev/null +++ b/include/mysql/service_md5.h @@ -0,0 +1,69 @@ +#ifndef MYSQL_SERVICE_MD5_INCLUDED +/* Copyright (c) 2014, Monty Program Ab + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my md5 service + + Functions to calculate MD5 hash from a memory buffer +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#define MY_MD5_HASH_SIZE 16 /* Hash size in bytes */ + +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_md5(A,B,C) my_md5_service->my_md5_type(A,B,C) +#define my_md5_multi my_md5_service->my_md5_multi_type +#define my_md5_context_size() my_md5_service->my_md5_context_size_type() +#define my_md5_init(A) my_md5_service->my_md5_init_type(A) +#define my_md5_input(A,B,C) my_md5_service->my_md5_input_type(A,B,C) +#define my_md5_result(A,B) my_md5_service->my_md5_result_type(A,B) + +#else + +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_MD5_INCLUDED +#endif + diff --git a/include/mysql/service_my_crypt.h b/include/mysql/service_my_crypt.h new file mode 100644 index 00000000..1a4ebcfd --- /dev/null +++ b/include/mysql/service_my_crypt.h @@ -0,0 +1,120 @@ +#ifndef MYSQL_SERVICE_MY_CRYPT_INCLUDED +#define MYSQL_SERVICE_MY_CRYPT_INCLUDED + +/* + Copyright (c) 2014 Google Inc. + Copyright (c) 2014, 2015 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my crypt service + + AES encryption functions, and a function to generate random bytes. + + Include my_config.h before this file to use CTR and GCM modes + (they only work if server was compiled with openssl). +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* return values from my_aes_encrypt/my_aes_decrypt functions */ +#define MY_AES_OK 0 +#define MY_AES_BAD_DATA -100 +#define MY_AES_OPENSSL_ERROR -101 +#define MY_AES_BAD_KEYSIZE -102 + +/* The block size for all supported algorithms */ +#define MY_AES_BLOCK_SIZE 16 + +/* The max key length of all supported algorithms */ +#define MY_AES_MAX_KEY_LENGTH 32 + +#define MY_AES_CTX_SIZE 1040 + +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +#ifdef HAVE_EncryptAes128Ctr + , MY_AES_CTR +#endif +#ifdef HAVE_EncryptAes128Gcm + , MY_AES_GCM +#endif +}; + +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_aes_crypt_init(A,B,C,D,E,F,G) \ + my_crypt_service->my_aes_crypt_init(A,B,C,D,E,F,G) + +#define my_aes_crypt_update(A,B,C,D,E) \ + my_crypt_service->my_aes_crypt_update(A,B,C,D,E) + +#define my_aes_crypt_finish(A,B,C) \ + my_crypt_service->my_aes_crypt_finish(A,B,C) + +#define my_aes_crypt(A,B,C,D,E,F,G,H,I,J) \ + my_crypt_service->my_aes_crypt(A,B,C,D,E,F,G,H,I,J) + +#define my_aes_get_size(A,B)\ + my_crypt_service->my_aes_get_size(A,B) + +#define my_aes_ctx_size(A)\ + my_crypt_service->my_aes_ctx_size(A) + +#define my_random_bytes(A,B)\ + my_crypt_service->my_random_bytes(A,B) + +#else + +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* MYSQL_SERVICE_MY_CRYPT_INCLUDED */ diff --git a/include/mysql/service_my_print_error.h b/include/mysql/service_my_print_error.h new file mode 100644 index 00000000..74ba6a2a --- /dev/null +++ b/include/mysql/service_my_print_error.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2016, MariaDB + +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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_MY_PRINT_ERROR_INCLUDED +#define MYSQL_SERVICE_MY_PRINT_ERROR_INCLUDED + +/** + @file include/mysql/service_my_print_error.h + + This service provides functions for plugins to report + errors to client (without client, the errors are written to the error log). + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#include <stdlib.h> +#endif + +#define ME_ERROR_LOG 64 /* Write the message to the error log */ +#define ME_ERROR_LOG_ONLY 128 /* Write the error message to error log only */ +#define ME_NOTE 1024 /* Not an error, just a note */ +#define ME_WARNING 2048 /* Not an error, just a warning */ +#define ME_FATAL 4096 /* Fatal statement error */ + +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_error my_print_error_service->my_error_func +#define my_printf_error my_print_error_service->my_printf_error_func +#define my_printv_error(A,B,C,D) my_print_error_service->my_printv_error_func(A,B,C,D) + +#else +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +#endif /* MYSQL_DYNAMIC_PLUGIN */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h new file mode 100644 index 00000000..fcc832fc --- /dev/null +++ b/include/mysql/service_my_snprintf.h @@ -0,0 +1,110 @@ +#ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED +/* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my_snprintf service + + Portable and limited vsnprintf() implementation. + + This is a portable, limited vsnprintf() implementation, with some + extra features. "Portable" means that it'll produce identical result + on all platforms (for example, on Windows and Linux system printf %e + formats the exponent differently, on different systems %p either + prints leading 0x or not, %s may accept null pointer or crash on + it). "Limited" means that it does not support all the C89 features. + But it supports few extensions, not in any standard. + + my_vsnprintf(to, n, fmt, ap) + + @param[out] to A buffer to store the result in + @param[in] n Store up to n-1 characters, followed by an end 0 + @param[in] fmt printf-like format string + @param[in] ap Arguments + + @return a number of bytes written to a buffer *excluding* terminating '\0' + + @post + The syntax of a format string is generally the same: + % <flag> <width> <precision> <length modifier> <format> + where everything but the format is optional. + + Three one-character flags are recognized: + '0' has the standard zero-padding semantics; + '-' is parsed, but silently ignored; + '`' (backtick) is only supported for strings (%s) and means that the + string will be quoted according to MySQL identifier quoting rules. + + Both <width> and <precision> can be specified as numbers or '*'. + If an asterisk is used, an argument of type int is consumed. + + <length modifier> can be 'l', 'll', or 'z'. + + Supported formats are 's' (null pointer is accepted, printed as + "(null)"), 'b' (extension, see below), 'c', 'd', 'i', 'u', 'x', 'o', + 'X', 'p' (works as 0x%x), 'f', 'g', 'M' (extension, see below), + 'T' (extension, see below). + + Standard syntax for positional arguments $n is supported. + + Extensions: + + Flag '`' (backtick): see above. + + Format 'b': binary buffer, prints exactly <precision> bytes from the + argument, without stopping at '\0'. + + Format 'M': takes one integer, prints this integer, space, double quote + error message, double quote. In other words + printf("%M", n) === printf("%d \"%s\"", n, strerror(n)) + + Format 'T': takes string and print it like s but if the strints should be + truncated puts "..." at the end. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#include <stdlib.h> +#endif + +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_vsnprintf my_snprintf_service->my_vsnprintf_type +#define my_snprintf my_snprintf_service->my_snprintf_type + +#else + +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED +#endif + diff --git a/include/mysql/service_progress_report.h b/include/mysql/service_progress_report.h new file mode 100644 index 00000000..11fc24dc --- /dev/null +++ b/include/mysql/service_progress_report.h @@ -0,0 +1,82 @@ +#ifndef MYSQL_SERVICE_PROGRESS_REPORT_INCLUDED +/* Copyright (C) 2011 Monty Program Ab + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service allows plugins to report progress of long running operations + to the server. The progress report is visible in SHOW PROCESSLIST, + INFORMATION_SCHEMA.PROCESSLIST, and is sent to the client + if requested. + + The functions are documented at + https://mariadb.com/kb/en/progress-reporting/#how-to-add-support-for-progress-reporting-to-a-storage-engine +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define thd_proc_info(thd, msg) set_thd_proc_info(thd, msg, \ + __func__, __FILE__, __LINE__) + +extern struct progress_report_service_st { + void (*thd_progress_init_func)(MYSQL_THD thd, unsigned int max_stage); + void (*thd_progress_report_func)(MYSQL_THD thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(MYSQL_THD thd); + void (*thd_progress_end_func)(MYSQL_THD thd); + const char *(*set_thd_proc_info_func)(MYSQL_THD, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_progress_init(thd,max_stage) (progress_report_service->thd_progress_init_func((thd),(max_stage))) +#define thd_progress_report(thd, progress, max_progress) (progress_report_service->thd_progress_report_func((thd), (progress), (max_progress))) +#define thd_progress_next_stage(thd) (progress_report_service->thd_progress_next_stage_func(thd)) +#define thd_progress_end(thd) (progress_report_service->thd_progress_end_func(thd)) +#define set_thd_proc_info(thd,info,func,file,line) (progress_report_service->set_thd_proc_info_func((thd),(info),(func),(file),(line))) + +#else + +/** + Report progress for long running operations + + @param thd User thread connection handle + @param progress Where we are now + @param max_progress Progress will continue up to this +*/ +void thd_progress_init(MYSQL_THD thd, unsigned int max_stage); +void thd_progress_report(MYSQL_THD thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(MYSQL_THD thd); +void thd_progress_end(MYSQL_THD thd); +const char *set_thd_proc_info(MYSQL_THD, const char * info, const char *func, + const char *file, unsigned int line); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_PROGRESS_REPORT_INCLUDED +#endif + diff --git a/include/mysql/service_sha1.h b/include/mysql/service_sha1.h new file mode 100644 index 00000000..d864e23f --- /dev/null +++ b/include/mysql/service_sha1.h @@ -0,0 +1,69 @@ +#ifndef MYSQL_SERVICE_SHA1_INCLUDED +/* Copyright (c) 2013, 2014, Monty Program Ab + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my sha1 service + + Functions to calculate SHA1 hash from a memory buffer +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#define MY_SHA1_HASH_SIZE 20 /* Hash size in bytes */ + +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_sha1(A,B,C) my_sha1_service->my_sha1_type(A,B,C) +#define my_sha1_multi my_sha1_service->my_sha1_multi_type +#define my_sha1_context_size() my_sha1_service->my_sha1_context_size_type() +#define my_sha1_init(A) my_sha1_service->my_sha1_init_type(A) +#define my_sha1_input(A,B,C) my_sha1_service->my_sha1_input_type(A,B,C) +#define my_sha1_result(A,B) my_sha1_service->my_sha1_result_type(A,B) + +#else + +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_SHA1_INCLUDED +#endif + diff --git a/include/mysql/service_sha2.h b/include/mysql/service_sha2.h new file mode 100644 index 00000000..00834a9b --- /dev/null +++ b/include/mysql/service_sha2.h @@ -0,0 +1,130 @@ +#ifndef MYSQL_SERVICE_SHA2_INCLUDED +/* Copyright (c) 2017, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my sha2 service + + Functions to calculate SHA2 hash from a memory buffer +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_sha224(A,B,C) my_sha2_service->my_sha224_type(A,B,C) +#define my_sha224_multi my_sha2_service->my_sha224_multi_type +#define my_sha224_context_size() my_sha2_service->my_sha224_context_size_type() +#define my_sha224_init(A) my_sha2_service->my_sha224_init_type(A) +#define my_sha224_input(A,B,C) my_sha2_service->my_sha224_input_type(A,B,C) +#define my_sha224_result(A,B) my_sha2_service->my_sha224_result_type(A,B) + +#define my_sha256(A,B,C) my_sha2_service->my_sha256_type(A,B,C) +#define my_sha256_multi my_sha2_service->my_sha256_multi_type +#define my_sha256_context_size() my_sha2_service->my_sha256_context_size_type() +#define my_sha256_init(A) my_sha2_service->my_sha256_init_type(A) +#define my_sha256_input(A,B,C) my_sha2_service->my_sha256_input_type(A,B,C) +#define my_sha256_result(A,B) my_sha2_service->my_sha256_result_type(A,B) + +#define my_sha384(A,B,C) my_sha2_service->my_sha384_type(A,B,C) +#define my_sha384_multi my_sha2_service->my_sha384_multi_type +#define my_sha384_context_size() my_sha2_service->my_sha384_context_size_type() +#define my_sha384_init(A) my_sha2_service->my_sha384_init_type(A) +#define my_sha384_input(A,B,C) my_sha2_service->my_sha384_input_type(A,B,C) +#define my_sha384_result(A,B) my_sha2_service->my_sha384_result_type(A,B) + +#define my_sha512(A,B,C) my_sha2_service->my_sha512_type(A,B,C) +#define my_sha512_multi my_sha2_service->my_sha512_multi_type +#define my_sha512_context_size() my_sha2_service->my_sha512_context_size_type() +#define my_sha512_init(A) my_sha2_service->my_sha512_init_type(A) +#define my_sha512_input(A,B,C) my_sha2_service->my_sha512_input_type(A,B,C) +#define my_sha512_result(A,B) my_sha2_service->my_sha512_result_type(A,B) + +#else + +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); + +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); + +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); + +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_SHA2_INCLUDED +#endif + diff --git a/include/mysql/service_sql.h b/include/mysql/service_sql.h new file mode 100644 index 00000000..2fee56ca --- /dev/null +++ b/include/mysql/service_sql.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#ifndef MYSQL_SERVICE_SQL +#define MYSQL_SERVICE_SQL + +#ifndef MYSQL_ABI_CHECK +#include <mysql.h> +#endif + +/** + @file + SQL service + + Interface for plugins to execute SQL queries on the local server. + + Functions of the service are the 'server-limited' client library: + mysql_init + mysql_real_connect_local + mysql_real_connect + mysql_errno + mysql_error + mysql_real_query + mysql_affected_rows + mysql_num_rows + mysql_store_result + mysql_free_result + mysql_fetch_row + mysql_close +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define mysql_init(M) sql_service->mysql_init_func(M) +#define mysql_real_connect_local(M) sql_service->mysql_real_connect_local_func(M) +#define mysql_real_connect(M,H,U,PW,D,P,S,F) sql_service->mysql_real_connect_func(M,H,U,PW,D,P,S,F) +#define mysql_errno(M) sql_service->mysql_errno_func(M) +#define mysql_error(M) sql_service->mysql_error_func(M) +#define mysql_real_query sql_service->mysql_real_query_func +#define mysql_affected_rows(M) sql_service->mysql_affected_rows_func(M) +#define mysql_num_rows(R) sql_service->mysql_num_rows_func(R) +#define mysql_store_result(M) sql_service->mysql_store_result_func(M) +#define mysql_free_result(R) sql_service->mysql_free_result_func(R) +#define mysql_fetch_row(R) sql_service->mysql_fetch_row_func(R) +#define mysql_close(M) sql_service->mysql_close_func(M) +#define mysql_options(M,O,V) sql_service->mysql_options_func(M,O,V) +#define mysql_fetch_lengths(R) sql_service->mysql_fetch_lengths_func(R) +#define mysql_set_character_set(M,C) sql_service->mysql_set_character_set_func(M,C) +#define mysql_num_fields(R) sql_service->mysql_num_fields_func(R) +#define mysql_select_db(M,D) sql_service->mysql_select_db_func(M,D) + +#else + +/* + Establishes the connection to the 'local' server that started the plugin. + Like the mysql_real_connect() does for the remote server. + The established connection has no user/host associated to it, + neither it has the current db, so the queries should have + database/table name specified. +*/ +MYSQL *mysql_real_connect_local(MYSQL *mysql); + +/* The rest of the function declarations must be taken from the mysql.h */ + +#endif /*MYSQL_DYNAMIC_PLUGIN*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_SQL */ + + diff --git a/include/mysql/service_thd_alloc.h b/include/mysql/service_thd_alloc.h new file mode 100644 index 00000000..0be4687b --- /dev/null +++ b/include/mysql/service_thd_alloc.h @@ -0,0 +1,139 @@ +#ifndef MYSQL_SERVICE_THD_ALLOC_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides functions to allocate memory in a connection local + memory pool. The memory allocated there will be automatically freed at the + end of the statement, don't use it for allocations that should live longer + than that. For short living allocations this is more efficient than + using my_malloc and friends, and automatic "garbage collection" allows not + to think about memory leaks. + + The pool is best for small to medium objects, don't use it for large + allocations - they are better served with my_malloc. +*/ + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; + +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; + +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(MYSQL_THD, size_t); + void *(*thd_calloc_func)(MYSQL_THD, size_t); + char *(*thd_strdup_func)(MYSQL_THD, const char *); + char *(*thd_strmake_func)(MYSQL_THD, const char *, size_t); + void *(*thd_memdup_func)(MYSQL_THD, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_alloc(thd,size) (thd_alloc_service->thd_alloc_func((thd), (size))) + +#define thd_calloc(thd,size) (thd_alloc_service->thd_calloc_func((thd), (size))) + +#define thd_strdup(thd,str) (thd_alloc_service->thd_strdup_func((thd), (str))) + +#define thd_strmake(thd,str,size) \ + (thd_alloc_service->thd_strmake_func((thd), (str), (size))) + +#define thd_memdup(thd,str,size) \ + (thd_alloc_service->thd_memdup_func((thd), (str), (size))) + +#define thd_make_lex_string(thd, lex_str, str, size, allocate_lex_string) \ + (thd_alloc_service->thd_make_lex_string_func((thd), (lex_str), (str), \ + (size), (allocate_lex_string))) + +#else + +/** + Allocate memory in the connection's local memory pool + + @details + When properly used in place of @c my_malloc(), this can significantly + improve concurrency. Don't use this or related functions to allocate + large chunks of memory. Use for temporary storage only. The memory + will be freed automatically at the end of the statement; no explicit + code is required to prevent memory leaks. + + @see alloc_root() +*/ +void *thd_alloc(MYSQL_THD thd, size_t size); +/** + @see thd_alloc() +*/ +void *thd_calloc(MYSQL_THD thd, size_t size); +/** + @see thd_alloc() +*/ +char *thd_strdup(MYSQL_THD thd, const char *str); +/** + @see thd_alloc() +*/ +char *thd_strmake(MYSQL_THD thd, const char *str, size_t size); +/** + @see thd_alloc() +*/ +void *thd_memdup(MYSQL_THD thd, const void* str, size_t size); + +/** + Create a LEX_STRING in this connection's local memory pool + + @param thd user thread connection handle + @param lex_str pointer to LEX_STRING object to be initialized + @param str initializer to be copied into lex_str + @param size length of str, in bytes + @param allocate_lex_string flag: if TRUE, allocate new LEX_STRING object, + instead of using lex_str value + @return NULL on failure, or pointer to the LEX_STRING object + + @see thd_alloc() +*/ +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(MYSQL_THD thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_ALLOC_INCLUDED +#endif + diff --git a/include/mysql/service_thd_autoinc.h b/include/mysql/service_thd_autoinc.h new file mode 100644 index 00000000..28bd2bb1 --- /dev/null +++ b/include/mysql/service_thd_autoinc.h @@ -0,0 +1,53 @@ +#ifndef MYSQL_SERVICE_THD_AUTOINC_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides access to the auto_increment related system variables: + + @@auto_increment_offset + @@auto_increment_increment +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const MYSQL_THD thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define thd_get_autoinc(thd, off, inc) \ + (thd_autoinc_service->thd_get_autoinc_func((thd), (off), (inc))) +#else +/** + Return autoincrement system variables + @param IN thd user thread connection handle + @param OUT off the value of @@SESSION.auto_increment_offset + @param OUT inc the value of @@SESSION.auto_increment_increment +*/ +void thd_get_autoinc(const MYSQL_THD thd, + unsigned long* off, unsigned long* inc); +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_AUTOINC_INCLUDED +#endif diff --git a/include/mysql/service_thd_error_context.h b/include/mysql/service_thd_error_context.h new file mode 100644 index 00000000..0b9082dd --- /dev/null +++ b/include/mysql/service_thd_error_context.h @@ -0,0 +1,93 @@ +#ifndef MYSQL_SERVICE_THD_STMT_DA_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides access to the statement diagnostics area: + - error message + - error number + - row for warning (e.g. for multi-row INSERT statements) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const MYSQL_THD thd); + unsigned int (*thd_get_error_number_func)(const MYSQL_THD thd); + unsigned long (*thd_get_error_row_func)(const MYSQL_THD thd); + void (*thd_inc_error_row_func)(MYSQL_THD thd); + char *(*thd_get_error_context_description_func)(MYSQL_THD thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define thd_get_error_message(thd) \ + (thd_error_context_service->thd_get_error_message_func((thd))) +#define thd_get_error_number(thd) \ + (thd_error_context_service->thd_get_error_number_func((thd))) +#define thd_get_error_row(thd) \ + (thd_error_context_service->thd_get_error_row_func((thd))) +#define thd_inc_error_row(thd) \ + (thd_error_context_service->thd_inc_error_row_func((thd))) +#define thd_get_error_context_description(thd, buffer, length, max_query_len) \ + (thd_error_context_service->thd_get_error_context_description_func((thd), \ + (buffer), \ + (length), \ + (max_query_len))) +#else +/** + Return error message + @param thd user thread connection handle + @return error text +*/ +const char *thd_get_error_message(const MYSQL_THD thd); +/** + Return error number + @param thd user thread connection handle + @return error number +*/ +unsigned int thd_get_error_number(const MYSQL_THD thd); +/** + Return the current row number (i.e. in a multiple INSERT statement) + @param thd user thread connection handle + @return row number +*/ +unsigned long thd_get_error_row(const MYSQL_THD thd); +/** + Increment the current row number + @param thd user thread connection handle +*/ +void thd_inc_error_row(MYSQL_THD thd); +/** + Return a text description of a thread, its security context (user,host) + and the current query. +*/ +char *thd_get_error_context_description(MYSQL_THD thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_STMT_DA_INCLUDED +#endif diff --git a/include/mysql/service_thd_mdl.h b/include/mysql/service_thd_mdl.h new file mode 100644 index 00000000..19b04769 --- /dev/null +++ b/include/mysql/service_thd_mdl.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2019, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#pragma once + +/** + @file include/mysql/service_thd_mdl.h + This service provides functions for plugins and storage engines to access + metadata locks. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_mdl_service_st { + void *(*thd_mdl_context)(MYSQL_THD); +} *thd_mdl_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +# define thd_mdl_context(_THD) thd_mdl_service->thd_mdl_context(_THD) +#else +/** + MDL_context accessor + @param thd the current session + @return pointer to thd->mdl_context +*/ +void *thd_mdl_context(MYSQL_THD thd); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/include/mysql/service_thd_rnd.h b/include/mysql/service_thd_rnd.h new file mode 100644 index 00000000..8761077e --- /dev/null +++ b/include/mysql/service_thd_rnd.h @@ -0,0 +1,62 @@ +#ifndef MYSQL_SERVICE_THD_RND_INCLUDED +/* Copyright (C) 2017 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides access to the thd-local random number generator. + + It's preferable over the global one, because concurrent threads + can generate random numbers without fighting each other over the access + to the shared rnd state. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(MYSQL_THD thd); + void (*thd_c_r_p_ptr)(MYSQL_THD thd, char *to, size_t length); +} *thd_rnd_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define thd_rnd(A) thd_rnd_service->thd_rnd_ptr(A) +#define thd_create_random_password(A,B,C) thd_rnd_service->thd_c_r_p_ptr(A,B,C) +#else + +double thd_rnd(MYSQL_THD thd); + +/** + Generate string of printable random characters of requested length. + + @param to[out] Buffer for generation; must be at least length+1 bytes + long; result string is always null-terminated + @param length[in] How many random characters to put in buffer +*/ +void thd_create_random_password(MYSQL_THD thd, char *to, size_t length); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_RND_INCLUDED +#endif diff --git a/include/mysql/service_thd_specifics.h b/include/mysql/service_thd_specifics.h new file mode 100644 index 00000000..a4078bd5 --- /dev/null +++ b/include/mysql/service_thd_specifics.h @@ -0,0 +1,110 @@ +#ifndef MYSQL_SERVICE_THD_SPECIFICS_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + THD specific for plugin(s) + + This API provides pthread_getspecific like functionality to plugin authors. + This is a functional alternative to the declarative MYSQL_THDVAR + + A plugin should at init call thd_key_create that create a key that + will have storage in each THD. The key should be used by all threads + and can be used concurrently from all threads. + + A plugin should at deinit call thd_key_delete. + + Alternatively, a plugin can use thd_key_create_from_var(K,V) to create + a key that corresponds to a named MYSQL_THDVAR variable. + + This API is also safe when using pool-of-threads in which case + pthread_getspecific is not, because the actual OS thread may change. + + @note + + Normally one should prefer MYSQL_THDVAR declarative API. + + The benefits are: + + - It supports typed variables (int, char*, enum, etc), not only void*. + - The memory allocated for MYSQL_THDVAR is free'd automatically + (if PLUGIN_VAR_MEMALLOC is specified). + - Continuous loading and unloading of the same plugin does not allocate + memory for same variables over and over again. + + An example of using MYSQL_THDVAR for a thd local storage: + + MYSQL_THDVAR_STR(my_tls, + PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT, + "thd local storage example", 0, 0, 0); +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int MYSQL_THD_KEY_T; + +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(MYSQL_THD thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(MYSQL_THD thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; + +#define thd_key_create_from_var(K, V) do { *(K)= MYSQL_SYSVAR_NAME(V).offset; } while(0) + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_key_create(K) (thd_specifics_service->thd_key_create_func(K)) +#define thd_key_delete(K) (thd_specifics_service->thd_key_delete_func(K)) +#define thd_getspecific(T, K) (thd_specifics_service->thd_getspecific_func(T, K)) +#define thd_setspecific(T, K, V) (thd_specifics_service->thd_setspecific_func(T, K, V)) + +#else + +/** + * create THD specific storage + * @return 0 on success + * else errno is returned + */ +int thd_key_create(MYSQL_THD_KEY_T *key); + +/** + * delete THD specific storage + */ +void thd_key_delete(MYSQL_THD_KEY_T *key); + +/** + * get/set thd specific storage + * - first time this is called from a thread it will return 0 + * - this call is thread-safe in that different threads may call this + * simultaneously if operating on different THDs. + * - this call acquires no mutexes and is implemented as an array lookup + */ +void* thd_getspecific(MYSQL_THD thd, MYSQL_THD_KEY_T key); +int thd_setspecific(MYSQL_THD thd, MYSQL_THD_KEY_T key, void *value); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_SPECIFICS_INCLUDED +#endif + diff --git a/include/mysql/service_thd_timezone.h b/include/mysql/service_thd_timezone.h new file mode 100644 index 00000000..66713774 --- /dev/null +++ b/include/mysql/service_thd_timezone.h @@ -0,0 +1,73 @@ +#ifndef MYSQL_SERVICE_THD_TIMEZONE_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides functions to convert between my_time_t and + MYSQL_TIME taking into account the current value of the time_zone + session variable. + + The values of the my_time_t type are in Unix timestamp format, + i.e. the number of seconds since "1970-01-01 00:00:00 UTC". + + The values of the MYSQL_TIME type are in the current time zone, + according to thd->variables.time_zone. + + If the MYSQL_THD parameter is NULL, then global_system_variables.time_zone + is used for conversion. +*/ + +#ifndef MYSQL_ABI_CHECK +/* + This service currently does not depend on any system headers. + If it needs system headers in the future, make sure to put + them inside this ifndef. +*/ +#endif + +#include "mysql_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(MYSQL_THD thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_TIME_to_gmt_sec(thd, ltime, errcode) \ + (thd_timezone_service->thd_TIME_to_gmt_sec((thd), (ltime), (errcode))) + +#define thd_gmt_sec_to_TIME(thd, ltime, t) \ + (thd_timezone_service->thd_gmt_sec_to_TIME((thd), (ltime), (t))) + +#else + +my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_TIMEZONE_INCLUDED +#endif diff --git a/include/mysql/service_thd_wait.h b/include/mysql/service_thd_wait.h new file mode 100644 index 00000000..c20878fd --- /dev/null +++ b/include/mysql/service_thd_wait.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_THD_WAIT_INCLUDED +#define MYSQL_SERVICE_THD_WAIT_INCLUDED + +/** + @file include/mysql/service_thd_wait.h + This service provides functions for plugins and storage engines to report + when they are going to sleep/stall. + + SYNOPSIS + thd_wait_begin() - call just before a wait begins + thd Thread object + Use NULL if the thd is NOT known. + wait_type Type of wait + 1 -- short wait (e.g. for mutex) + 2 -- medium wait (e.g. for disk io) + 3 -- large wait (e.g. for locked row/table) + NOTES + This is used by the threadpool to have better knowledge of which + threads that currently are actively running on CPUs. When a thread + reports that it's going to sleep/stall, the threadpool scheduler is + free to start another thread in the pool most likely. The expected wait + time is simply an indication of how long the wait is expected to + become, the real wait time could be very different. + + thd_wait_end() called immediately after the wait is complete + + thd_wait_end() MUST be called if thd_wait_begin() was called. + + Using thd_wait_...() service is optional but recommended. Using it will + improve performance as the thread pool will be more active at managing the + thread workload. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + One should only report wait events that could potentially block for a + long time. A mutex wait is too short of an event to report. The reason + is that an event which is reported leads to a new thread starts + executing a query and this has a negative impact of usage of CPU caches + and thus the expected gain of starting a new thread must be higher than + the expected cost of lost performance due to starting a new thread. + + Good examples of events that should be reported are waiting for row locks + that could easily be for many milliseconds or even seconds and the same + holds true for global read locks, table locks and other meta data locks. + Another event of interest is going to sleep for an extended time. +*/ +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; + +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(MYSQL_THD, int); + void (*thd_wait_end_func)(MYSQL_THD); +} *thd_wait_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_wait_begin(_THD, _WAIT_TYPE) \ + thd_wait_service->thd_wait_begin_func(_THD, _WAIT_TYPE) +#define thd_wait_end(_THD) thd_wait_service->thd_wait_end_func(_THD) + +#else + +void thd_wait_begin(MYSQL_THD thd, int wait_type); +void thd_wait_end(MYSQL_THD thd); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h new file mode 100644 index 00000000..8add7093 --- /dev/null +++ b/include/mysql/service_wsrep.h @@ -0,0 +1,257 @@ +#ifndef MYSQL_SERVICE_WSREP_INCLUDED +#define MYSQL_SERVICE_WSREP_INCLUDED + +enum Wsrep_service_key_type +{ + WSREP_SERVICE_KEY_SHARED, + WSREP_SERVICE_KEY_REFERENCE, + WSREP_SERVICE_KEY_UPDATE, + WSREP_SERVICE_KEY_EXCLUSIVE +}; + +#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED)) + +#else + +/* Copyright (c) 2015, 2020, MariaDB Corporation Ab + 2018 Codership Oy <info@codership.com> + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + wsrep service + + Interface to WSREP functionality in the server. + For engines that want to support galera. +*/ +#include <my_pthread.h> +#ifdef __cplusplus +#endif + +struct xid_t; +struct wsrep_ws_handle; +struct wsrep_buf; + +/* Must match to definition in sql/mysqld.h */ +typedef int64 query_id_t; + + +extern struct wsrep_service_st { + my_bool (*get_wsrep_recovery_func)(); + bool (*wsrep_consistency_check_func)(MYSQL_THD thd); + int (*wsrep_is_wsrep_xid_func)(const void *xid); + long long (*wsrep_xid_seqno_func)(const struct xid_t *xid); + const unsigned char* (*wsrep_xid_uuid_func)(const struct xid_t *xid); + my_bool (*wsrep_on_func)(const MYSQL_THD thd); + bool (*wsrep_prepare_key_for_innodb_func)(MYSQL_THD thd, const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*); + void (*wsrep_thd_LOCK_func)(const MYSQL_THD thd); + int (*wsrep_thd_TRYLOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_UNLOCK_func)(const MYSQL_THD thd); + const char * (*wsrep_thd_query_func)(const MYSQL_THD thd); + int (*wsrep_thd_retry_counter_func)(const MYSQL_THD thd); + bool (*wsrep_thd_ignore_table_func)(MYSQL_THD thd); + long long (*wsrep_thd_trx_seqno_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_is_aborting_func)(const MYSQL_THD thd); + void (*wsrep_set_data_home_dir_func)(const char *data_dir); + my_bool (*wsrep_thd_is_BF_func)(const MYSQL_THD thd, my_bool sync); + my_bool (*wsrep_thd_is_local_func)(const MYSQL_THD thd); + void (*wsrep_thd_self_abort_func)(MYSQL_THD thd); + int (*wsrep_thd_append_key_func)(MYSQL_THD thd, const struct wsrep_key* key, + int n_keys, enum Wsrep_service_key_type); + int (*wsrep_thd_append_table_key_func)(MYSQL_THD thd, const char* db, + const char* table, enum Wsrep_service_key_type); + my_bool (*wsrep_thd_is_local_transaction)(const MYSQL_THD thd); + const char* (*wsrep_thd_client_state_str_func)(const MYSQL_THD thd); + const char* (*wsrep_thd_client_mode_str_func)(const MYSQL_THD thd); + const char* (*wsrep_thd_transaction_state_str_func)(const MYSQL_THD thd); + query_id_t (*wsrep_thd_transaction_id_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_bf_abort_func)(MYSQL_THD bf_thd, + MYSQL_THD victim_thd, + my_bool signal); + my_bool (*wsrep_thd_order_before_func)(const MYSQL_THD left, const MYSQL_THD right); + void (*wsrep_handle_SR_rollback_func)(MYSQL_THD BF_thd, MYSQL_THD victim_thd); + my_bool (*wsrep_thd_skip_locking_func)(const MYSQL_THD thd); + const char* (*wsrep_get_sr_table_name_func)(); + my_bool (*wsrep_get_debug_func)(); + void (*wsrep_commit_ordered_func)(MYSQL_THD thd); + my_bool (*wsrep_thd_is_applying_func)(const MYSQL_THD thd); + ulong (*wsrep_OSU_method_get_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_has_ignored_error_func)(const MYSQL_THD thd); + void (*wsrep_thd_set_ignored_error_func)(MYSQL_THD thd, my_bool val); + void (*wsrep_report_bf_lock_wait_func)(const MYSQL_THD thd, + unsigned long long trx_id); + void (*wsrep_thd_kill_LOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_kill_UNLOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_set_wsrep_PA_unsafe_func)(MYSQL_THD thd); +} *wsrep_service; + +#define MYSQL_SERVICE_WSREP_INCLUDED +#endif + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED +#define get_wsrep_recovery() wsrep_service->get_wsrep_recovery_func() +#define wsrep_consistency_check(T) wsrep_service->wsrep_consistency_check_func(T) +#define wsrep_is_wsrep_xid(X) wsrep_service->wsrep_is_wsrep_xid_func(X) +#define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X) +#define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X) +#define wsrep_on(thd) (thd) && WSREP_ON && wsrep_service->wsrep_on_func(thd) +#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F,G) +#define wsrep_thd_LOCK(T) wsrep_service->wsrep_thd_LOCK_func(T) +#define wsrep_thd_TRYLOCK(T) wsrep_service->wsrep_thd_TRYLOCK_func(T) +#define wsrep_thd_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T) +#define wsrep_thd_kill_LOCK(T) wsrep_service->wsrep_thd_kill_LOCK_func(T) +#define wsrep_thd_kill_UNLOCK(T) wsrep_service->wsrep_thd_kill_UNLOCK_func(T) +#define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T) +#define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T) +#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T) +#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T) +#define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) +#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) +#define wsrep_thd_is_aborting(T) wsrep_service->wsrep_thd_is_aborting_func(T) +#define wsrep_thd_is_local(T) wsrep_service->wsrep_thd_is_local_func(T) +#define wsrep_thd_self_abort(T) wsrep_service->wsrep_thd_self_abort_func(T) +#define wsrep_thd_append_key(T,W,N,K) wsrep_service->wsrep_thd_append_key_func(T,W,N,K) +#define wsrep_thd_append_table_key(T,D,B,K) wsrep_service->wsrep_thd_append_table_key_func(T,D,B,K) +#define wsrep_thd_is_local_transaction(T) wsrep_service->wsrep_thd_is_local_transaction_func(T) +#define wsrep_thd_client_state_str(T) wsrep_service->wsrep_thd_client_state_str_func(T) +#define wsrep_thd_client_mode_str(T) wsrep_service->wsrep_thd_client_mode_str_func(T) +#define wsrep_thd_transaction_state_str(T) wsrep_service->wsrep_thd_transaction_state_str_func(T) +#define wsrep_thd_transaction_id(T) wsrep_service->wsrep_thd_transaction_id_func(T) +#define wsrep_thd_bf_abort(T,T2,S) wsrep_service->wsrep_thd_bf_abort_func(T,T2,S) +#define wsrep_thd_order_before(L,R) wsrep_service->wsrep_thd_order_before_func(L,R) +#define wsrep_handle_SR_rollback(B,V) wsrep_service->wsrep_handle_SR_rollback_func(B,V) +#define wsrep_thd_skip_locking(T) wsrep_service->wsrep_thd_skip_locking_func(T) +#define wsrep_get_sr_table_name() wsrep_service->wsrep_get_sr_table_name_func() +#define wsrep_get_debug() wsrep_service->wsrep_get_debug_func() +#define wsrep_commit_ordered(T) wsrep_service->wsrep_commit_ordered_func(T) +#define wsrep_thd_is_applying(T) wsrep_service->wsrep_thd_is_applying_func(T) +#define wsrep_OSU_method_get(T) wsrep_service->wsrep_OSU_method_get_func(T) +#define wsrep_thd_has_ignored_error(T) wsrep_service->wsrep_thd_has_ignored_error_func(T) +#define wsrep_thd_set_ignored_error(T,V) wsrep_service->wsrep_thd_set_ignored_error_func(T,V) +#define wsrep_report_bf_lock_wait(T,I) wsrep_service->wsrep_report_bf_lock_wait(T,I) +#define wsrep_thd_set_PA_unsafe(T) wsrep_service->wsrep_thd_set_PA_unsafe_func(T) +#else + +#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED +extern ulong wsrep_debug; +extern my_bool wsrep_log_conflicts; +extern my_bool wsrep_certify_nonPK; +extern my_bool wsrep_load_data_splitting; +extern my_bool wsrep_drupal_282555_workaround; +extern my_bool wsrep_recovery; +extern long wsrep_protocol_version; + +extern "C" bool wsrep_consistency_check(MYSQL_THD thd); +bool wsrep_prepare_key_for_innodb(MYSQL_THD thd, const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len); +extern "C" const char *wsrep_thd_query(const MYSQL_THD thd); +extern "C" int wsrep_is_wsrep_xid(const void* xid); +extern "C" long long wsrep_xid_seqno(const struct xid_t* xid); +const unsigned char* wsrep_xid_uuid(const struct xid_t* xid); +extern "C" long long wsrep_thd_trx_seqno(const MYSQL_THD thd); +my_bool get_wsrep_recovery(); +bool wsrep_thd_ignore_table(MYSQL_THD thd); +void wsrep_set_data_home_dir(const char *data_dir); + +/* from mysql wsrep-lib */ +#include "my_global.h" +#include "my_pthread.h" + +/* Return true if wsrep is enabled for a thd. This means that + wsrep is enabled globally and the thd has wsrep on */ +extern "C" my_bool wsrep_on(const MYSQL_THD thd); +/* Lock thd wsrep lock */ +extern "C" void wsrep_thd_LOCK(const MYSQL_THD thd); +/* Try thd wsrep lock. Return non-zero if lock could not be taken. */ +extern "C" int wsrep_thd_TRYLOCK(const MYSQL_THD thd); +/* Unlock thd wsrep lock */ +extern "C" void wsrep_thd_UNLOCK(const MYSQL_THD thd); + +extern "C" void wsrep_thd_kill_LOCK(const MYSQL_THD thd); +extern "C" void wsrep_thd_kill_UNLOCK(const MYSQL_THD thd); + +/* Return thd client state string */ +extern "C" const char* wsrep_thd_client_state_str(const MYSQL_THD thd); +/* Return thd client mode string */ +extern "C" const char* wsrep_thd_client_mode_str(const MYSQL_THD thd); +/* Return thd transaction state string */ +extern "C" const char* wsrep_thd_transaction_state_str(const MYSQL_THD thd); + +/* Return current transaction id */ +extern "C" query_id_t wsrep_thd_transaction_id(const MYSQL_THD thd); +/* Mark thd own transaction as aborted */ +extern "C" void wsrep_thd_self_abort(MYSQL_THD thd); +/* Return true if thd is in replicating mode */ +extern "C" my_bool wsrep_thd_is_local(const MYSQL_THD thd); +/* Return true if thd is in high priority mode */ +/* todo: rename to is_high_priority() */ +extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd); +/* Return true if thd is in TOI mode */ +extern "C" my_bool wsrep_thd_is_toi(const MYSQL_THD thd); +/* Return true if thd is in replicating TOI mode */ +extern "C" my_bool wsrep_thd_is_local_toi(const MYSQL_THD thd); +/* Return true if thd is in RSU mode */ +extern "C" my_bool wsrep_thd_is_in_rsu(const MYSQL_THD thd); +/* Return true if thd is in BF mode, either high_priority or TOI */ +extern "C" my_bool wsrep_thd_is_BF(const MYSQL_THD thd, my_bool sync); +/* Return true if thd is streaming */ +extern "C" my_bool wsrep_thd_is_SR(const MYSQL_THD thd); +extern "C" void wsrep_handle_SR_rollback(MYSQL_THD BF_thd, MYSQL_THD victim_thd); +/* Return thd retry counter */ +extern "C" int wsrep_thd_retry_counter(const MYSQL_THD thd); +/* BF abort victim_thd */ +extern "C" my_bool wsrep_thd_bf_abort(MYSQL_THD bf_thd, + MYSQL_THD victim_thd, + my_bool signal); +/* Return true if left thd is ordered before right thd */ +extern "C" my_bool wsrep_thd_order_before(const MYSQL_THD left, const MYSQL_THD right); +/* Return true if thd should skip locking. This means that the thd + is operating on shared resource inside commit order critical section. */ +extern "C" my_bool wsrep_thd_skip_locking(const MYSQL_THD thd); +/* Return true if thd is aborting */ +extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd); + +struct wsrep_key; +struct wsrep_key_array; +extern "C" int wsrep_thd_append_key(MYSQL_THD thd, + const struct wsrep_key* key, + int n_keys, + enum Wsrep_service_key_type); + +extern "C" int wsrep_thd_append_table_key(MYSQL_THD thd, + const char* db, + const char* table, + enum Wsrep_service_key_type); + +extern "C" my_bool wsrep_thd_is_local_transaction(const MYSQL_THD thd); + +extern const char* wsrep_sr_table_name_full; + +extern "C" const char* wsrep_get_sr_table_name(); + +extern "C" my_bool wsrep_get_debug(); + +extern "C" void wsrep_commit_ordered(MYSQL_THD thd); +extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd); +extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd); +extern "C" my_bool wsrep_thd_has_ignored_error(const MYSQL_THD thd); +extern "C" void wsrep_thd_set_ignored_error(MYSQL_THD thd, my_bool val); +extern "C" void wsrep_report_bf_lock_wait(const THD *thd, + unsigned long long trx_id); +/* declare parallel applying unsafety for the THD */ +extern "C" void wsrep_thd_set_PA_unsafe(MYSQL_THD thd); +#endif +#endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/include/mysql/services.h b/include/mysql/services.h new file mode 100644 index 00000000..94f7bb3b --- /dev/null +++ b/include/mysql/services.h @@ -0,0 +1,52 @@ +#ifndef MYSQL_SERVICES_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 2017, MariaDB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <mysql/service_base64.h> +#include <mysql/service_debug_sync.h> +#include <mysql/service_encryption.h> +#include <mysql/service_encryption_scheme.h> +#include <mysql/service_kill_statement.h> +#include <mysql/service_logger.h> +#include <mysql/service_md5.h> +#include <mysql/service_my_crypt.h> +#include <mysql/service_my_print_error.h> +#include <mysql/service_my_snprintf.h> +#include <mysql/service_progress_report.h> +#include <mysql/service_sha1.h> +#include <mysql/service_sha2.h> +#include <mysql/service_thd_alloc.h> +#include <mysql/service_thd_autoinc.h> +#include <mysql/service_thd_error_context.h> +#include <mysql/service_thd_rnd.h> +#include <mysql/service_thd_specifics.h> +#include <mysql/service_thd_timezone.h> +#include <mysql/service_thd_wait.h> +#include <mysql/service_json.h> +/*#include <mysql/service_wsrep.h>*/ +#include <mysql/service_sql.h> + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICES_INCLUDED +#endif + |