diff options
author | Sergei Golubchik <serg@mysql.com> | 2009-11-02 21:05:42 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mysql.com> | 2009-11-02 21:05:42 +0100 |
commit | d101d144df296bb455023225f6477833b7a7b42e (patch) | |
tree | 7a2815b63cb90a92052843088062861e585a181d | |
parent | d3bf417db28f91397ef218984a16bccb14e44a30 (diff) | |
download | mariadb-git-d101d144df296bb455023225f6477833b7a7b42e.tar.gz |
WL#4903 Plugin Service API part I
(mysql-next-mr backport)
34 files changed, 764 insertions, 258 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c6769eca72d..6e53ff30159 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -311,6 +311,7 @@ ADD_SUBDIRECTORY(extra) ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(sql) ADD_SUBDIRECTORY(libmysql) +ADD_SUBDIRECTORY(libservices) ADD_SUBDIRECTORY(tests) IF(WITH_EMBEDDED_SERVER) ADD_SUBDIRECTORY(libmysqld) diff --git a/Makefile.am b/Makefile.am index 53be49768de..79c98d9d4a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common scripts \ - @pstack_dir@ \ + @pstack_dir@ libservices \ @sql_union_dirs@ unittest \ @sql_server@ @man_dirs@ tests \ netware @libmysqld_dirs@ \ @@ -32,7 +32,7 @@ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ DIST_SUBDIRS = . include Docs zlib \ cmd-line-utils sql-common scripts \ - pstack \ + pstack libservices \ strings mysys dbug extra regex libmysql libmysql_r client unittest storage plugin \ vio sql man tests \ netware libmysqld \ diff --git a/configure.in b/configure.in index 1564033cf7a..47e195f92a3 100644 --- a/configure.in +++ b/configure.in @@ -2946,7 +2946,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl man/Makefile BUILD/Makefile vio/Makefile dnl libmysql/Makefile libmysql_r/Makefile client/Makefile dnl sql/Makefile sql/share/Makefile dnl - sql/sql_builtin.cc sql-common/Makefile dnl + sql/sql_builtin.cc sql-common/Makefile libservices/Makefile dnl dbug/Makefile scripts/Makefile include/Makefile dnl tests/Makefile Docs/Makefile support-files/Makefile dnl support-files/MacOSX/Makefile support-files/RHEL4-SElinux/Makefile dnl diff --git a/include/Makefile.am b/include/Makefile.am index dd6f53f7ca2..0a7a35bd6fa 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -21,7 +21,8 @@ HEADERS_GEN_MAKE = my_config.h HEADERS_ABI = mysql.h mysql_com.h mysql_time.h \ my_list.h my_alloc.h typelib.h mysql/plugin.h pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ - my_xml.h mysql_embed.h \ + my_xml.h mysql_embed.h mysql/services.h \ + mysql/service_my_snprintf.h mysql/service_thd_alloc.h \ my_pthread.h my_no_pthread.h \ decimal.h errmsg.h my_global.h my_net.h \ my_getopt.h sslopt-longopts.h my_dir.h \ @@ -36,7 +37,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \ my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \ my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \ thr_lock.h t_ctype.h violite.h my_md5.h base64.h \ - my_handler.h my_time.h \ + my_handler.h my_time.h service_versions.h \ my_vle.h my_user.h my_atomic.h atomic/nolock.h \ atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \ atomic/solaris.h \ diff --git a/include/m_string.h b/include/m_string.h index c24bfd7aa6c..3c4c6ea088a 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -250,16 +250,10 @@ extern size_t my_snprintf(char *to, size_t n, const char *fmt, ...) /* LEX_STRING -- a pair of a C-string and its length. + (it's part of the plugin API as a MYSQL_LEX_STRING) */ -#ifndef _my_plugin_h -/* This definition must match the one given in mysql/plugin.h */ -struct st_mysql_lex_string -{ - char *str; - size_t length; -}; -#endif +#include <mysql/plugin.h> typedef struct st_mysql_lex_string LEX_STRING; #define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1)) diff --git a/include/my_sys.h b/include/my_sys.h index b4366a4cd3d..9121f0f249e 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -683,6 +683,8 @@ extern void my_error _VARARGS((int nr,myf MyFlags, ...)); extern void my_printf_error _VARARGS((uint my_err, const char *format, myf MyFlags, ...)) ATTRIBUTE_FORMAT(printf, 2, 4); +extern void my_printv_error(uint error, const char *format, myf MyFlags, + va_list ap); extern int my_error_register(const char** (*get_errmsgs) (), int first, int last); extern const char **my_error_unregister(int first, int last); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 45d0234cb67..f158dc20999 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc. 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 @@ -16,12 +16,6 @@ #ifndef _my_plugin_h #define _my_plugin_h -/* size_t */ -#include <stdlib.h> - -typedef struct st_mysql MYSQL; - - /* On Windows, exports from DLL need to be declared */ @@ -39,15 +33,7 @@ class Item; #define MYSQL_THD void* #endif -#ifndef _m_string_h -/* This definition must match the one given in m_string.h */ -struct st_mysql_lex_string -{ - char *str; - unsigned int length; -}; -#endif /* _m_string_h */ -typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +#include <mysql/services.h> #define MYSQL_XIDDATASIZE 128 /** @@ -70,7 +56,7 @@ typedef struct st_mysql_xid MYSQL_XID; Plugin API. Common for all plugin types. */ -#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0100 +#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101 /* The allowable types of plugins @@ -126,7 +112,8 @@ enum enum_mysql_show_type { SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG, SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, - SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_always_last }; struct st_mysql_show_var { @@ -750,54 +737,6 @@ int thd_killed(const MYSQL_THD thd); */ unsigned long thd_get_thread_id(const MYSQL_THD thd); - -/** - 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, unsigned int size); -/** - @see thd_alloc() -*/ -void *thd_calloc(MYSQL_THD thd, unsigned int 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, unsigned int size); -/** - @see thd_alloc() -*/ -void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int 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_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str, - const char *str, unsigned int size, - int allocate_lex_string); - /** Get the XID for this connection's transaction @@ -818,64 +757,6 @@ void mysql_query_cache_invalidate4(MYSQL_THD thd, const char *key, unsigned int key_length, int using_trx); -/** - Get the value of user variable as an integer. - - This function will return the value of variable @a name as an - integer. If the original value of the variable is not an integer, - the value will be converted into an integer. - - @param name user variable name - @param value pointer to return the value - @param null_value if not NULL, the function will set it to true if - the value of variable is null, set to false if not - - @retval 0 Success - @retval 1 Variable not found -*/ -int get_user_var_int(const char *name, - long long int *value, int *null_value); - -/** - Get the value of user variable as a double precision float number. - - This function will return the value of variable @a name as real - number. If the original value of the variable is not a real number, - the value will be converted into a real number. - - @param name user variable name - @param value pointer to return the value - @param null_value if not NULL, the function will set it to true if - the value of variable is null, set to false if not - - @retval 0 Success - @retval 1 Variable not found -*/ -int get_user_var_real(const char *name, - double *value, int *null_value); - -/** - Get the value of user variable as a string. - - This function will return the value of variable @a name as - string. If the original value of the variable is not a string, - the value will be converted into a string. - - @param name user variable name - @param value pointer to the value buffer - @param len length of the value buffer - @param precision precision of the value if it is a float number - @param null_value if not NULL, the function will set it to true if - the value of variable is null, set to false if not - - @retval 0 Success - @retval 1 Variable not found -*/ -int get_user_var_str(const char *name, - char *value, unsigned long len, - unsigned int precision, int *null_value); - - #ifdef __cplusplus } #endif diff --git a/include/mysql/plugin.h.pp b/include/mysql/plugin.h.pp index d864140333b..b7dd7bc0032 100644 --- a/include/mysql/plugin.h.pp +++ b/include/mysql/plugin.h.pp @@ -1,11 +1,38 @@ +#include <mysql/services.h> +#include <mysql/service_my_snprintf.h> +#include <stdarg.h> +#include <stdlib.h> +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); +#include <mysql/service_thd_alloc.h> #include <stdlib.h> -typedef struct st_mysql MYSQL; struct st_mysql_lex_string { char *str; - unsigned int length; + size_t length; }; typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(void*, unsigned int); + void *(*thd_calloc_func)(void*, unsigned int); + char *(*thd_strdup_func)(void*, const char *); + char *(*thd_strmake_func)(void*, const char *, unsigned int); + void *(*thd_memdup_func)(void*, const void*, unsigned int); + MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *, + const char *, unsigned int, int); +} *thd_alloc_service; +void *thd_alloc(void* thd, unsigned int size); +void *thd_calloc(void* thd, unsigned int size); +char *thd_strdup(void* thd, const char *str); +char *thd_strmake(void* thd, const char *str, unsigned int size); +void *thd_memdup(void* thd, const void* str, unsigned int size); +MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, + const char *str, unsigned int size, + int allocate_lex_string); struct st_mysql_xid { long formatID; long gtrid_length; @@ -17,7 +44,8 @@ enum enum_mysql_show_type { SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG, SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, - SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_always_last }; struct st_mysql_show_var { const char *name; @@ -107,9 +135,9 @@ struct st_mysql_information_schema { int interface_version; }; -struct Mysql_replication { - int interface_version; -}; + struct Mysql_replication { + int interface_version; + }; struct st_mysql_value { int (*value_type)(struct st_mysql_value *); @@ -130,22 +158,7 @@ void thd_inc_row_count(void* thd); int mysql_tmpfile(const char *prefix); int thd_killed(const void* thd); unsigned long thd_get_thread_id(const void* thd); -void *thd_alloc(void* thd, unsigned int size); -void *thd_calloc(void* thd, unsigned int size); -char *thd_strdup(void* thd, const char *str); -char *thd_strmake(void* thd, const char *str, unsigned int size); -void *thd_memdup(void* thd, const void* str, unsigned int size); -MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, - const char *str, unsigned int size, - int allocate_lex_string); void thd_get_xid(const void* thd, MYSQL_XID *xid); void mysql_query_cache_invalidate4(void* thd, const char *key, unsigned int key_length, int using_trx); -int get_user_var_int(const char *name, - long long int *value, int *null_value); -int get_user_var_real(const char *name, - double *value, int *null_value); -int get_user_var_str(const char *name, - char *value, unsigned long len, - unsigned int precision, int *null_value); diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h new file mode 100644 index 00000000000..a9f205fc4de --- /dev/null +++ b/include/mysql/service_my_snprintf.h @@ -0,0 +1,98 @@ +#ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @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 everithing but the format is optional. + + Three one-character flags are regognized: + '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 '*'. + + <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', 'u', 'x', + 'X', 'p' (works as 0x%x). + + 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'. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +#include <stdlib.h> +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_thd_alloc.h b/include/mysql/service_thd_alloc.h new file mode 100644 index 00000000000..86158ba1359 --- /dev/null +++ b/include/mysql/service_thd_alloc.h @@ -0,0 +1,128 @@ +#ifndef MYSQL_SERVICE_THD_ALLOC_INCLUDED +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + This service provdes 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. +*/ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; + +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(MYSQL_THD, unsigned int); + void *(*thd_calloc_func)(MYSQL_THD, unsigned int); + char *(*thd_strdup_func)(MYSQL_THD, const char *); + char *(*thd_strmake_func)(MYSQL_THD, const char *, unsigned int); + void *(*thd_memdup_func)(MYSQL_THD, const void*, unsigned int); + MYSQL_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD, MYSQL_LEX_STRING *, + const char *, unsigned int, 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, unsigned int size); +/** + @see thd_alloc() +*/ +void *thd_calloc(MYSQL_THD thd, unsigned int 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, unsigned int size); +/** + @see thd_alloc() +*/ +void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int 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_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str, + const char *str, unsigned int size, + int allocate_lex_string); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_ALLOC_INCLUDED +#endif + diff --git a/include/mysql/services.h b/include/mysql/services.h new file mode 100644 index 00000000000..19003e66b96 --- /dev/null +++ b/include/mysql/services.h @@ -0,0 +1,30 @@ +#ifndef MYSQL_SERVICES_INCLUDED +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <mysql/service_my_snprintf.h> +#include <mysql/service_thd_alloc.h> + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICES_INCLUDED +#endif + diff --git a/include/service_versions.h b/include/service_versions.h new file mode 100644 index 00000000000..114957cdd86 --- /dev/null +++ b/include/service_versions.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifdef _WIN32 +#define SERVICE_VERSION __declspec(dllexport) void * +#else +#define SERVICE_VERSION void * +#endif + +#define VERSION_my_snprintf 0x0100 +#define VERSION_thd_alloc 0x0100 + diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt new file mode 100644 index 00000000000..ddfa2495ade --- /dev/null +++ b/libservices/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2006 MySQL 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-1301 USA + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c) + +ADD_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) diff --git a/libservices/HOWTO b/libservices/HOWTO new file mode 100644 index 00000000000..b4960cb11dc --- /dev/null +++ b/libservices/HOWTO @@ -0,0 +1,100 @@ +How to create a new service +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A "service" is a set of C functions in a structure that a +service dynamic linker uses when a dynamic plugin is loaded. + +If you want to export C++ class you need to provide an +extern "C" function that will create a new instance of your class, +and put it in a service. + +Data structures are not part of the service structure, but they are part +of the API you create and usually need to be declared in the same +service_*.h file. + +To turn a set of functions (foo_func1, foo_func2) +into a service "foo" you need to + +1. create a new file include/mysql/service_foo.h + +2. the template is +================================================================== + #ifndef MYSQL_SERVICE_FOO_INCLUDED + /* standard GPL header */ + + /** + @file + *exhaustive* description of the interface you provide. + This file is the main user documentation of the new service + */ + #ifdef __cplusplus + extern "C" { + #endif + + extern struct foo_service_st { + int (*foo_func1_type)(...); /* fix the prototype as appropriate */ + void (*foo_func2_type)(...); /* fix the prototype as appropriate */ + } *foo_service; + + #ifdef MYSQL_DYNAMIC_PLUGIN + + #define foo_func1(...) foo_service->foo_func1_type(...) + #define foo_func2(...) foo_service->foo_func2_type(...) + + #else + + int foo_func1_type(...); /* fix the prototype as appropriate */ + void foo_func2_type(...); /* fix the prototype as appropriate */ + + #endif + + #ifdef __cplusplus + } + #endif + + #define MYSQL_SERVICE_FOO_INCLUDED + #endif +================================================================== + +the service_foo.h file should be self-contained, if it needs system headers - +include them in it, e.g. if you use size_t - #include <stdlib.h> + +it should also declare all the accompanying data structures, as necessary +(e.g. thd_alloc_service declares MYSQL_LEX_STRING). + +3. add the new file to include/Makefile.am (pkginclude_HEADERS) +4. add the new file to include/mysql/services.h +5. increase the minor plugin ABI version in include/mysql/plugin.h + (MYSQL_PLUGIN_INTERFACE_VERSION = MYSQL_PLUGIN_INTERFACE_VERSION+1) +6. add the version of your service to include/service_versions.h: +================================================================== + #define VERSION_foo 0x0100 +================================================================== + +7. create a new file libservices/foo_service.h using the following template: +================================================================== + /* GPL header */ + #include <service_versions.h> + SERVICE_VERSION *foo_service= (void*)VERSION_foo; +================================================================== + +8. add the new file to libservices/CMakeLists.txt (MYSQLSERVICES_SOURCES) +9. add the new file to libservices/Makefile.am (libmysqlservices_a_SOURCES) +10. and finally, register your service for dynamic linking in + sql/sql_plugin_services.h +10.1 fill in the service structure: +================================================================== + static struct foo_service_st foo_handler = { + foo_func1, + foo_func2 + } +================================================================== + +10.2 and add it to the list of services + +================================================================== + { "foo_service", VERSION_foo, &foo_handler } +================================================================== + +that's all. + diff --git a/libservices/Makefile.am b/libservices/Makefile.am new file mode 100644 index 00000000000..642081859c1 --- /dev/null +++ b/libservices/Makefile.am @@ -0,0 +1,19 @@ +# Copyright 2009 Sun Microsystems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +AM_CPPFLAGS = -I$(top_srcdir)/include +pkglib_LIBRARIES = libmysqlservices.a +libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c +EXTRA_DIST = CMakeLists.txt diff --git a/libservices/my_snprintf_service.c b/libservices/my_snprintf_service.c new file mode 100644 index 00000000000..40d778e4b8d --- /dev/null +++ b/libservices/my_snprintf_service.c @@ -0,0 +1,17 @@ +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <service_versions.h> +SERVICE_VERSION my_snprintf_service= (void*)VERSION_my_snprintf; diff --git a/libservices/thd_alloc_service.c b/libservices/thd_alloc_service.c new file mode 100644 index 00000000000..5d4d496774c --- /dev/null +++ b/libservices/thd_alloc_service.c @@ -0,0 +1,17 @@ +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <service_versions.h> +SERVICE_VERSION *thd_alloc_service= (void*)VERSION_thd_alloc; diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index 782d2a5a9a4..85fbd1353cc 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -12,6 +12,15 @@ CREATE TABLE t1(a int) ENGINE=EXAMPLE; SELECT * FROM t1; a DROP TABLE t1; +set global example_ulong_var=500; +set global example_enum_var= e1; +show status like 'example%'; +Variable_name Value +example_func_example enum_var is 0, ulong_var is 500, really +show variables like 'example%'; +Variable_name Value +example_enum_var e1 +example_ulong_var 500 UNINSTALL PLUGIN example; UNINSTALL PLUGIN EXAMPLE; ERROR 42000: PLUGIN EXAMPLE does not exist diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test index 788a7b336ef..0bf86b47dd7 100644 --- a/mysql-test/t/plugin.test +++ b/mysql-test/t/plugin.test @@ -22,6 +22,12 @@ SELECT * FROM t1; DROP TABLE t1; +# a couple of tests for variables +set global example_ulong_var=500; +set global example_enum_var= e1; +show status like 'example%'; +show variables like 'example%'; + UNINSTALL PLUGIN example; --error 1305 UNINSTALL PLUGIN EXAMPLE; diff --git a/mysys/my_error.c b/mysys/my_error.c index ff9156faf82..e2523a39d0b 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -126,6 +126,29 @@ void my_printf_error(uint error, const char *format, myf MyFlags, ...) } /* + Error with va_list + + SYNOPSIS + my_printv_error() + error Errno + format Format string + MyFlags Flags + ... variable list +*/ + +void my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) +{ + char ebuff[ERRMSGSIZE]; + DBUG_ENTER("my_printv_error"); + DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s", + error, MyFlags, errno, format)); + + (void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap); + (*error_handler_hook)(error, ebuff, MyFlags); + DBUG_VOID_RETURN; +} + +/* Give message using error_handler_hook SYNOPSIS diff --git a/plugin/daemon_example/Makefile.am b/plugin/daemon_example/Makefile.am index c5414cd46c7..fce67285a5f 100644 --- a/plugin/daemon_example/Makefile.am +++ b/plugin/daemon_example/Makefile.am @@ -26,7 +26,8 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ EXTRA_LTLIBRARIES = libdaemon_example.la pkgplugin_LTLIBRARIES = @plugin_daemon_example_shared_target@ -libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir) +libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices + libdaemon_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN libdaemon_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN libdaemon_example_la_SOURCES = daemon_example.cc diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 3e350144f74..15c2d950ff9 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -45,7 +45,7 @@ SET (SQL_SOURCE discover.cc ../libmysql/errmsg.c field.cc field_conv.cc filesort.cc gstream.cc ha_partition.cc - handler.cc hash_filo.cc hash_filo.h + handler.cc hash_filo.cc hash_filo.h sql_plugin_services.h hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc item_create.cc item_func.cc item_geofunc.cc item_row.cc item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc diff --git a/sql/Makefile.am b/sql/Makefile.am index 569bb70965e..5c3a1d3a8fe 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -82,7 +82,7 @@ mysqld_LDADD = libndb.la \ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h \ - item_xmlfunc.h \ + item_xmlfunc.h sql_plugin_services.h \ item_create.h item_subselect.h item_row.h \ mysql_priv.h item_geofunc.h sql_bitmap.h \ procedure.h sql_class.h sql_lex.h sql_list.h \ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 05a79957963..c9909298b63 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -28,6 +28,16 @@ #ifndef MYSQL_CLIENT +/* + the following #define adds server-only members to enum_mysql_show_type, + that is defined in mysql/plugin.h + it has to be before mysql/plugin.h is included. +*/ +#define SHOW_always_last SHOW_KEY_CACHE_LONG, \ + SHOW_KEY_CACHE_LONGLONG, SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, \ + SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \ + SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS + #include <my_global.h> #include <mysql_version.h> #include <mysql_embed.h> diff --git a/sql/replication.h b/sql/replication.h index 6b7be58a5b1..eea77ef9f8e 100644 --- a/sql/replication.h +++ b/sql/replication.h @@ -16,6 +16,8 @@ #ifndef REPLICATION_H #define REPLICATION_H +typedef struct st_mysql MYSQL; + #ifdef __cplusplus extern "C" { #endif @@ -483,6 +485,64 @@ const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond, */ void thd_exit_cond(MYSQL_THD thd, const char *old_msg); +/** + Get the value of user variable as an integer. + + This function will return the value of variable @a name as an + integer. If the original value of the variable is not an integer, + the value will be converted into an integer. + + @param name user variable name + @param value pointer to return the value + @param null_value if not NULL, the function will set it to true if + the value of variable is null, set to false if not + + @retval 0 Success + @retval 1 Variable not found +*/ +int get_user_var_int(const char *name, + long long int *value, int *null_value); + +/** + Get the value of user variable as a double precision float number. + + This function will return the value of variable @a name as real + number. If the original value of the variable is not a real number, + the value will be converted into a real number. + + @param name user variable name + @param value pointer to return the value + @param null_value if not NULL, the function will set it to true if + the value of variable is null, set to false if not + + @retval 0 Success + @retval 1 Variable not found +*/ +int get_user_var_real(const char *name, + double *value, int *null_value); + +/** + Get the value of user variable as a string. + + This function will return the value of variable @a name as + string. If the original value of the variable is not a string, + the value will be converted into a string. + + @param name user variable name + @param value pointer to the value buffer + @param len length of the value buffer + @param precision precision of the value if it is a float number + @param null_value if not NULL, the function will set it to true if + the value of variable is null, set to false if not + + @retval 0 Success + @retval 1 Variable not found +*/ +int get_user_var_str(const char *name, + char *value, unsigned long len, + unsigned int precision, int *null_value); + + #ifdef __cplusplus } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 757f6abb00b..1958bbe271c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -272,12 +272,7 @@ const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond, if (!thd) thd= current_thd; - const char* old_msg = thd->proc_info; - safe_mutex_assert_owner(mutex); - thd->mysys_var->current_mutex = mutex; - thd->mysys_var->current_cond = cond; - thd->proc_info = msg; - return old_msg; + return thd->enter_cond(cond, mutex, msg); } extern "C" @@ -286,18 +281,7 @@ void thd_exit_cond(MYSQL_THD thd, const char *old_msg) if (!thd) thd= current_thd; - /* - Putting the mutex unlock in thd_exit_cond() ensures that - mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is - locked (if that would not be the case, you'll get a deadlock if someone - does a THD::awake() on you). - */ - pthread_mutex_unlock(thd->mysys_var->current_mutex); - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex = 0; - thd->mysys_var->current_cond = 0; - thd->proc_info = old_msg; - pthread_mutex_unlock(&thd->mysys_var->mutex); + thd->exit_cond(old_msg); return; } diff --git a/sql/sql_class.h b/sql/sql_class.h index aaa959feae9..3f40195ba5b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -25,7 +25,6 @@ #include "log.h" #include "rpl_tblmap.h" -#include "replication.h" /** An interface that is used to take an action when @@ -1886,11 +1885,28 @@ public: inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex, const char* msg) { - return thd_enter_cond(this, cond, mutex, msg); + const char* old_msg = proc_info; + safe_mutex_assert_owner(mutex); + mysys_var->current_mutex = mutex; + mysys_var->current_cond = cond; + proc_info = msg; + return old_msg; } inline void exit_cond(const char* old_msg) { - thd_exit_cond(this, old_msg); + /* + Putting the mutex unlock in thd->exit_cond() ensures that + mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is + locked (if that would not be the case, you'll get a deadlock if someone + does a THD::awake() on you). + */ + pthread_mutex_unlock(mysys_var->current_mutex); + pthread_mutex_lock(&mysys_var->mutex); + mysys_var->current_mutex = 0; + mysys_var->current_cond = 0; + proc_info = old_msg; + pthread_mutex_unlock(&mysys_var->mutex); + return; } inline time_t query_start() { query_start_used=1; return start_time; } inline void set_time() diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 1278eafce92..fb1da901f1b 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc. 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 @@ -99,7 +99,9 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_REPLICATION_INTERFACE_VERSION, }; -static bool initialized= 0; +/* support for Services */ + +#include "sql_plugin_services.h" /* A mutex LOCK_plugin must be acquired before accessing the @@ -113,6 +115,8 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; static bool reap_needed= false; static int plugin_array_version=0; +static bool initialized= 0; + /* write-lock on LOCK_system_variables_hash is required before modifying the following variables/structures @@ -225,6 +229,22 @@ extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists); #endif /* EMBEDDED_LIBRARY */ +static void report_error(int where_to, uint error, ...) +{ + va_list args; + if (where_to & REPORT_TO_USER) + { + va_start(args, error); + my_printv_error(error, ER(error), MYF(0), args); + va_end(args); + } + if (where_to & REPORT_TO_LOG) + { + va_start(args, error); + error_log_print(ERROR_LEVEL, ER(error), args); + va_end(args); + } +} /**************************************************************************** Value type thunks, allows the C world to play in the C++ world @@ -345,7 +365,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) { #ifdef HAVE_DLOPEN char dlpath[FN_REFLEN]; - uint plugin_dir_len, dummy_errors, dlpathlen; + uint plugin_dir_len, dummy_errors, dlpathlen, i; struct st_plugin_dl *tmp, plugin_dl; void *sym; DBUG_ENTER("plugin_dl_add"); @@ -360,10 +380,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) system_charset_info, 1) || plugin_dir_len + dl->length + 1 >= FN_REFLEN) { - if (report & REPORT_TO_USER) - my_error(ER_UDF_NO_PATHS, MYF(0)); - if (report & REPORT_TO_LOG) - sql_print_error("%s", ER_DEFAULT(ER_UDF_NO_PATHS)); + report_error(report, ER_UDF_NO_PATHS); DBUG_RETURN(0); } /* If this dll is already loaded just increase ref_count. */ @@ -388,21 +405,14 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) if (*errmsg == ':') errmsg++; if (*errmsg == ' ') errmsg++; } - if (report & REPORT_TO_USER) - my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg); + report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg); DBUG_RETURN(0); } /* Determine interface version */ if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym))) { free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_interface_version_sym); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), - plugin_interface_version_sym); + report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym); DBUG_RETURN(0); } plugin_dl.version= *(int *)sym; @@ -411,29 +421,42 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8)) { free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0, - "plugin interface version mismatch"); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dlpath, 0, - "plugin interface version mismatch"); + report_error(report, ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0, + "plugin interface version mismatch"); DBUG_RETURN(0); } + + /* link the services in */ + for (i= 0; i < array_elements(list_of_services); i++) + { + if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name))) + { + uint ver= (uint)(intptr)*(void**)sym; + if (ver > list_of_services[i].version || + (ver >> 8) < (list_of_services[i].version >> 8)) + { + char buf[MYSQL_ERRMSG_SIZE]; + my_snprintf(buf, sizeof(buf), + "service '%s' interface version mismatch", + list_of_services[i].name); + report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf); + DBUG_RETURN(0); + } + *(void**)sym= list_of_services[i].service; + } + } + /* Find plugin declarations */ if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym))) { free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), - plugin_declarations_sym); + report_error(report, ER_CANT_FIND_DL_ENTRY, MYF(0), + plugin_declarations_sym); DBUG_RETURN(0); } if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION) { - int i; uint sizeof_st_plugin; struct st_mysql_plugin *old, *cur; char *ptr= (char *)sym; @@ -443,11 +466,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) else { #ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL - free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), sizeof_st_plugin_sym); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym); + report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym); DBUG_RETURN(0); #else /* @@ -469,10 +488,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) if (!cur) { free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), plugin_dl.dl.length); + report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length); DBUG_RETURN(0); } /* @@ -494,10 +510,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0)))) { free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), plugin_dl.dl.length); + report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length); DBUG_RETURN(0); } plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length, @@ -508,19 +521,13 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl))) { free_plugin_mem(&plugin_dl); - if (report & REPORT_TO_USER) - my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl)); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl)); + report_error(report, ER_OUTOFMEMORY, sizeof(struct st_plugin_dl)); DBUG_RETURN(0); } DBUG_RETURN(tmp); #else DBUG_ENTER("plugin_dl_add"); - if (report & REPORT_TO_USER) - my_error(ER_FEATURE_DISABLED, MYF(0), "plugin", "HAVE_DLOPEN"); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_FEATURE_DISABLED), "plugin", "HAVE_DLOPEN"); + report_error(report, ER_FEATURE_DISABLED, "plugin", "HAVE_DLOPEN"); DBUG_RETURN(0); #endif } @@ -636,7 +643,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) /* For debugging, we do an additional malloc which allows the memory manager and/or valgrind to track locked references and - double unlocks to aid resolving reference counting.problems. + double unlocks to aid resolving reference counting problems. */ if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME)))) DBUG_RETURN(NULL); @@ -719,10 +726,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, DBUG_ENTER("plugin_add"); if (plugin_find_internal(name, MYSQL_ANY_PLUGIN)) { - if (report & REPORT_TO_USER) - my_error(ER_UDF_EXISTS, MYF(0), name->str); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_UDF_EXISTS), name->str); + report_error(report, ER_UDF_EXISTS, name->str); DBUG_RETURN(TRUE); } /* Clear the whole struct to catch future extensions. */ @@ -749,10 +753,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, strxnmov(buf, sizeof(buf) - 1, "API version for ", plugin_type_names[plugin->type].str, " plugin is too different", NullS); - if (report & REPORT_TO_USER) - my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dl->str, 0, buf); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dl->str, 0, buf); + report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf); goto err; } tmp.plugin= plugin; @@ -781,10 +782,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, DBUG_RETURN(FALSE); } } - if (report & REPORT_TO_USER) - my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str); - if (report & REPORT_TO_LOG) - sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), name->str); + report_error(report, ER_CANT_FIND_DL_ENTRY, name->str); err: plugin_dl_del(dl); DBUG_RETURN(TRUE); diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index c6ad846943c..23ce85c994b 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -35,16 +35,6 @@ class sys_var; #define INITIAL_LEX_PLUGIN_LIST_SIZE 16 -/* - the following #define adds server-only members to enum_mysql_show_type, - that is defined in plugin.h -*/ -#define SHOW_FUNC SHOW_FUNC, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_LONGLONG, \ - SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_HAVE, \ - SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH, \ - SHOW_LONGLONG_STATUS -#include <mysql/plugin.h> -#undef SHOW_FUNC typedef enum enum_mysql_show_type SHOW_TYPE; typedef struct st_mysql_show_var SHOW_VAR; diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h new file mode 100644 index 00000000000..7491ddab79d --- /dev/null +++ b/sql/sql_plugin_services.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* support for Services */ +#include <service_versions.h> + +struct st_service_ref { + const char *name; + uint version; + void *service; +}; + +static struct my_snprintf_service_st my_snprintf_handler = { + my_snprintf, + my_vsnprintf +}; + +static struct thd_alloc_service_st thd_alloc_handler= { + thd_alloc, + thd_calloc, + thd_strdup, + thd_strmake, + thd_memdup, + thd_make_lex_string +}; + +static struct st_service_ref list_of_services[]= +{ + { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, + { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler } +}; + diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am index ce269aee59b..1179a338ee2 100644 --- a/storage/example/Makefile.am +++ b/storage/example/Makefile.am @@ -34,7 +34,7 @@ noinst_HEADERS = ha_example.h EXTRA_LTLIBRARIES = ha_example.la pkgplugin_LTLIBRARIES = @plugin_example_shared_target@ -ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir) +ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices ha_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN ha_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN ha_example_la_SOURCES = ha_example.cc diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index 30fc82c82d2..4b982f2943f 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 MySQL AB +/* Copyright (C) 2003 MySQL AB, 2009 Sun Microsystems, Inc. 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 @@ -921,6 +921,24 @@ static struct st_mysql_sys_var* example_system_variables[]= { NULL }; +// this is an example of SHOW_FUNC and of my_snprintf() service +static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var, + char *buf) +{ + var->type= SHOW_CHAR; + var->value= buf; // it's of SHOW_VAR_FUNC_BUFF_SIZE bytes + my_snprintf(buf, SHOW_VAR_FUNC_BUFF_SIZE, + "enum_var is %u, ulong_var is %lu, %.6b", // %b is MySQL extension + srv_enum_var, srv_ulong_var, "really"); + return 0; +} + +static struct st_mysql_show_var func_status[]= +{ + {"example_func_example", (char *)show_func_example, SHOW_FUNC}, + {0,0,SHOW_UNDEF} +}; + mysql_declare_plugin(example) { MYSQL_STORAGE_ENGINE_PLUGIN, @@ -932,7 +950,7 @@ mysql_declare_plugin(example) example_init_func, /* Plugin Init */ example_done_func, /* Plugin Deinit */ 0x0001 /* 0.1 */, - NULL, /* status variables */ + func_status, /* status variables */ example_system_variables, /* system variables */ NULL /* config options */ } diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake index af8c3a85cd1..b920f16452b 100644 --- a/storage/mysql_storage_engine.cmake +++ b/storage/mysql_storage_engine.cmake @@ -34,7 +34,7 @@ IF(NOT SOURCE_SUBLIBS) #The dll is linked to the mysqld executable SET(dyn_libname ha_${libname}) ADD_LIBRARY(${dyn_libname} SHARED ${${engine}_SOURCES}) - TARGET_LINK_LIBRARIES (${dyn_libname} mysqld) + TARGET_LINK_LIBRARIES (${dyn_libname} mysqlservices mysqld) IF(${engine}_LIBS) TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS}) ENDIF(${engine}_LIBS) diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index 3362559972a..46961058eea 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -472,6 +472,8 @@ start: /** Produces output string according to a format string + See the detailed documentation around my_snprintf_service_st + @param cs string charset @param to buffer where processed string will be place @param n size of buffer |