1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

mwl:98 - libservices

This commit is contained in:
Sergei Golubchik
2010-03-03 15:44:14 +01:00
parent abb87914ec
commit 2ceaffc467
33 changed files with 1368 additions and 305 deletions

View File

@ -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
@ -104,7 +104,9 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
};
static bool initialized= 0;
/* support for Services */
#include "sql_plugin_services.h"
/*
A mutex LOCK_plugin must be acquired before accessing the
@ -118,6 +120,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
@ -230,6 +234,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
@ -350,7 +370,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");
@ -365,10 +385,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 | REPORT_TO_USER)) == REPORT_TO_LOG)
sql_print_error("%s", ER(ER_UDF_NO_PATHS));
report_error(report, ER_UDF_NO_PATHS);
DBUG_RETURN(0);
}
/* If this dll is already loaded just increase ref_count. */
@ -393,20 +410,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(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(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;
@ -415,28 +426,41 @@ 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(ER_CANT_OPEN_LIBRARY), dlpath, 0,
"plugin interface version mismatch");
report_error(report, ER_CANT_OPEN_LIBRARY, 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(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
report_error(report, ER_CANT_FIND_DL_ENTRY, 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;
@ -447,10 +471,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
#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(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
/*
@ -472,10 +493,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(ER_OUTOFMEMORY), plugin_dl.dl.length);
report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
DBUG_RETURN(0);
}
/*
@ -497,10 +515,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(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,
@ -511,19 +526,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(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(ER_FEATURE_DISABLED), "plugin", "HAVE_DLOPEN");
report_error(report, ER_FEATURE_DISABLED, "plugin", "HAVE_DLOPEN");
DBUG_RETURN(0);
#endif
}
@ -639,7 +648,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);
@ -722,10 +731,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(ER_UDF_EXISTS), name->str);
report_error(report, ER_UDF_EXISTS, name->str);
DBUG_RETURN(TRUE);
}
/* Clear the whole struct to catch future extensions. */
@ -752,10 +758,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(ER_CANT_OPEN_LIBRARY), dl->str, 0, buf);
report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
goto err;
}
tmp.plugin= plugin;
@ -784,10 +787,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(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);
@ -1006,9 +1006,14 @@ void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
static int plugin_initialize(struct st_plugin_int *plugin)
{
int ret= 1;
DBUG_ENTER("plugin_initialize");
safe_mutex_assert_owner(&LOCK_plugin);
uint state= plugin->state;
DBUG_ASSERT(state == PLUGIN_IS_UNINITIALIZED);
pthread_mutex_unlock(&LOCK_plugin);
if (plugin_type_initialize[plugin->plugin->type])
{
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
@ -1027,8 +1032,7 @@ static int plugin_initialize(struct st_plugin_int *plugin)
goto err;
}
}
plugin->state= PLUGIN_IS_READY;
state= PLUGIN_IS_READY; // plugin->init() succeeded
if (plugin->plugin->status_vars)
{
@ -1047,7 +1051,8 @@ static int plugin_initialize(struct st_plugin_int *plugin)
if (add_status_vars(array)) // add_status_vars makes a copy
goto err;
#else
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
if (add_status_vars(plugin->plugin->status_vars))
goto err;
#endif /* FIX_LATER */
}
@ -1067,9 +1072,13 @@ static int plugin_initialize(struct st_plugin_int *plugin)
}
}
DBUG_RETURN(0);
ret= 0;
err:
DBUG_RETURN(1);
pthread_mutex_lock(&LOCK_plugin);
plugin->state= state;
DBUG_RETURN(ret);
}