19 #include "my_global.h"
20 #include "sql_class.h"
22 #include "sql_locale.h"
23 #include "sql_plugin.h"
24 #include "sql_parse.h"
31 #include <my_pthread.h>
32 #include <my_getopt.h>
33 #include "sql_audit.h"
36 #include <mysql/plugin_validate_password.h>
37 #include "my_default.h"
44 #define REPORT_TO_LOG 1
45 #define REPORT_TO_USER 2
54 const char *global_plugin_typelib_names[]=
55 {
"OFF",
"ON",
"FORCE",
"FORCE_PLUS_PERMANENT", NULL };
56 static TYPELIB global_plugin_typelib=
57 { array_elements(global_plugin_typelib_names)-1,
58 "", global_plugin_typelib_names, NULL };
62 char *opt_plugin_dir_ptr;
63 char opt_plugin_dir[FN_REFLEN];
68 const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
70 { C_STRING_WITH_LEN(
"UDF") },
71 { C_STRING_WITH_LEN(
"STORAGE ENGINE") },
72 { C_STRING_WITH_LEN(
"FTPARSER") },
73 { C_STRING_WITH_LEN(
"DAEMON") },
74 { C_STRING_WITH_LEN(
"INFORMATION SCHEMA") },
75 { C_STRING_WITH_LEN(
"AUDIT") },
76 { C_STRING_WITH_LEN(
"REPLICATION") },
77 { C_STRING_WITH_LEN(
"AUTHENTICATION") },
78 { C_STRING_WITH_LEN(
"VALIDATE PASSWORD") }
92 plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
94 0,ha_initialize_handlerton,0,0,initialize_schema_table,
95 initialize_audit_plugin,0,0,0
98 plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
100 0,ha_finalize_handlerton,0,0,finalize_schema_table,
101 finalize_audit_plugin,0,0,0
105 static const char *plugin_interface_version_sym=
106 "_mysql_plugin_interface_version_";
107 static const char *sizeof_st_plugin_sym=
108 "_mysql_sizeof_struct_st_plugin_";
109 static const char *plugin_declarations_sym=
"_mysql_plugin_declarations_";
110 static int min_plugin_interface_version= MYSQL_PLUGIN_INTERFACE_VERSION & ~0xFF;
113 static void* innodb_callback_data;
118 static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
121 MYSQL_HANDLERTON_INTERFACE_VERSION,
122 MYSQL_FTPARSER_INTERFACE_VERSION,
123 MYSQL_DAEMON_INTERFACE_VERSION,
124 MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
125 MYSQL_AUDIT_INTERFACE_VERSION,
126 MYSQL_REPLICATION_INTERFACE_VERSION,
127 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
128 MYSQL_VALIDATE_PASSWORD_INTERFACE_VERSION
130 static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
133 MYSQL_HANDLERTON_INTERFACE_VERSION,
134 MYSQL_FTPARSER_INTERFACE_VERSION,
135 MYSQL_DAEMON_INTERFACE_VERSION,
136 MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
137 MYSQL_AUDIT_INTERFACE_VERSION,
138 MYSQL_REPLICATION_INTERFACE_VERSION,
139 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
140 MYSQL_VALIDATE_PASSWORD_INTERFACE_VERSION
145 #include "sql_plugin_services.h"
155 static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
156 static bool reap_needed=
false;
157 static int plugin_array_version=0;
159 static bool initialized= 0;
166 static uint global_variables_dynamic_size= 0;
167 static HASH bookmark_hash;
205 MYSQL_PLUGIN_VAR_HEADER;
228 static void *
operator new(
size_t size,
MEM_ROOT *mem_root)
229 {
return (
void*) alloc_root(mem_root,
size); }
230 static void operator delete(
void *ptr_arg,
size_t size)
231 { TRASH(ptr_arg,
size); }
235 :
sys_var(chain, name_arg, plugin_var_arg->comment,
236 (plugin_var_arg->
flags & PLUGIN_VAR_THDLOCAL ? SESSION : GLOBAL) |
237 (plugin_var_arg->
flags & PLUGIN_VAR_READONLY ? READONLY : 0),
238 0, -1, NO_ARG, pluginvar_show_type(plugin_var_arg), 0, 0,
239 VARIABLE_NOT_IN_BINLOG, NULL, NULL, NULL, PARSE_NORMAL),
241 { plugin_var->name= name_arg; }
243 bool check_update_type(Item_result
type);
244 SHOW_TYPE show_type();
245 uchar* real_value_ptr(THD *thd, enum_var_type
type);
246 TYPELIB* plugin_var_typelib(
void);
247 uchar* do_value_ptr(THD *thd, enum_var_type
type,
LEX_STRING *base);
249 {
return do_value_ptr(thd, OPT_SESSION, base); }
250 uchar* global_value_ptr(THD *thd,
LEX_STRING *base)
251 {
return do_value_ptr(thd, OPT_GLOBAL, base); }
252 bool do_check(THD *thd,
set_var *var);
255 bool session_update(THD *thd,
set_var *var);
256 bool global_update(THD *thd,
set_var *var);
261 static void plugin_load(
MEM_ROOT *tmp_root,
int *argc,
char **argv);
262 static bool plugin_load_list(
MEM_ROOT *tmp_root,
int *argc,
char **argv,
264 static my_bool check_if_option_is_deprecated(
int optid,
273 static void plugin_vars_free_values(
sys_var *vars);
274 static bool plugin_var_memalloc_session_update(THD *thd,
276 char **dest,
const char *value);
277 static bool plugin_var_memalloc_global_update(THD *thd,
279 char **dest,
const char *value);
281 static void restore_pluginvar_names(
sys_var *first);
282 static void plugin_opt_set_limits(
struct my_option *,
284 #define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
285 #define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
287 static void intern_plugin_unlock(LEX *lex,
plugin_ref plugin);
288 static void reap_plugins(
void);
290 static void report_error(
int where_to, uint error, ...)
293 if (where_to & REPORT_TO_USER)
295 va_start(args, error);
296 my_printv_error(error, ER(error), MYF(0), args);
299 if (where_to & REPORT_TO_LOG)
301 va_start(args, error);
302 error_log_print(ERROR_LEVEL, ER_DEFAULT(error), args);
320 bool check_valid_path(
const char *path,
size_t len)
322 size_t prefix= my_strcspn(files_charset_info, path, path + len, FN_DIRSEP);
335 return MYSQL_VALUE_TYPE_INT;
337 return MYSQL_VALUE_TYPE_REAL;
339 return MYSQL_VALUE_TYPE_STRING;
344 char *buffer,
int *length)
346 String str(buffer, *length, system_charset_info), *res;
349 *length= res->length();
350 if (res->c_ptr_quick() == buffer)
357 return current_thd->strmake(res->c_ptr_quick(), res->length());
364 *buf= item->val_int();
373 return item->unsigned_flag;
376 static int item_val_real(
struct st_mysql_value *value,
double *buf)
379 *buf= item->val_real();
396 DBUG_ENTER(
"plugin_dl_find");
397 for (i= 0; i < plugin_dl_array.elements; i++)
399 tmp= *dynamic_element(&plugin_dl_array, i,
struct st_plugin_dl **);
400 if (tmp->ref_count &&
401 ! my_strnncoll(files_charset_info,
402 (
const uchar *)dl->str, dl->length,
403 (
const uchar *)tmp->dl.str, tmp->dl.length))
414 DBUG_ENTER(
"plugin_dl_insert_or_reuse");
415 for (i= 0; i < plugin_dl_array.elements; i++)
417 tmp= *dynamic_element(&plugin_dl_array, i,
struct st_plugin_dl **);
418 if (! tmp->ref_count)
424 if (insert_dynamic(&plugin_dl_array, &plugin_dl))
426 tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
428 (
struct st_plugin_dl *) memdup_root(&plugin_mem_root, (uchar*)plugin_dl,
435 static inline void free_plugin_mem(
struct st_plugin_dl *p)
442 if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION)
450 char dlpath[FN_REFLEN];
451 uint plugin_dir_len, dummy_errors, dlpathlen,
i;
454 DBUG_ENTER(
"plugin_dl_add");
455 DBUG_PRINT(
"enter", (
"dl->str: '%s', dl->length: %d",
456 dl->str, (
int) dl->length));
457 plugin_dir_len= strlen(opt_plugin_dir);
463 if (check_valid_path(dl->str, dl->length) ||
464 check_string_char_length((
LEX_STRING *) dl,
"", NAME_CHAR_LEN,
465 system_charset_info, 1) ||
466 plugin_dir_len + dl->length + 1 >= FN_REFLEN)
468 report_error(report, ER_UDF_NO_PATHS);
472 if ((tmp= plugin_dl_find(dl)))
477 memset(&plugin_dl, 0,
sizeof(plugin_dl));
480 strxnmov(dlpath,
sizeof(dlpath) - 1, opt_plugin_dir,
"/", dl->str, NullS) -
482 (void) unpack_filename(dlpath, dlpath);
483 plugin_dl.ref_count= 1;
485 if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
488 int error_number= dlopen_errno;
489 DLERROR_GENERATE(errmsg, error_number);
491 if (!strncmp(dlpath, errmsg, dlpathlen))
494 if (*errmsg ==
':') errmsg++;
495 if (*errmsg ==
' ') errmsg++;
497 report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, error_number, errmsg);
501 if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
503 free_plugin_mem(&plugin_dl);
504 report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
507 plugin_dl.version= *(
int *)sym;
509 if (plugin_dl.version < min_plugin_interface_version ||
510 (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
512 free_plugin_mem(&plugin_dl);
513 report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
514 "plugin interface version mismatch");
519 for (i= 0; i < array_elements(list_of_services); i++)
521 if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
523 uint ver= (uint)(intptr)*(
void**)sym;
524 if (ver > list_of_services[i].version ||
525 (ver >> 8) < (list_of_services[
i].version >> 8))
527 char buf[MYSQL_ERRMSG_SIZE];
528 my_snprintf(buf,
sizeof(buf),
529 "service '%s' interface version mismatch",
530 list_of_services[i].
name);
531 report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
534 *(
void**)sym= list_of_services[i].service;
539 if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
541 free_plugin_mem(&plugin_dl);
542 report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
546 if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
548 uint sizeof_st_plugin;
550 char *ptr= (
char *)sym;
552 if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
553 sizeof_st_plugin= *(
int *)sym;
556 #ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
557 report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
564 DBUG_ASSERT(min_plugin_interface_version == 0);
580 my_malloc((i+1)*
sizeof(
struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
583 free_plugin_mem(&plugin_dl);
584 report_error(report, ER_OUTOFMEMORY,
585 static_cast<int>(plugin_dl.dl.length));
596 memcpy(cur+i, old, min<size_t>(
sizeof(cur[i]), sizeof_st_plugin));
607 if (report == REPORT_TO_USER)
610 for ( ; plugin->info ; ++plugin)
611 if (plugin->flags & PLUGIN_OPT_NO_INSTALL)
613 report_error(report, ER_PLUGIN_NO_INSTALL, plugin->name);
614 free_plugin_mem(&plugin_dl);
620 plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
621 if (! (plugin_dl.dl.str= (
char*) my_malloc(plugin_dl.dl.length, MYF(0))))
623 free_plugin_mem(&plugin_dl);
624 report_error(report, ER_OUTOFMEMORY,
625 static_cast<int>(plugin_dl.dl.length));
628 plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
629 files_charset_info, dl->str, dl->length, system_charset_info,
631 plugin_dl.dl.str[plugin_dl.dl.length]= 0;
633 if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
635 free_plugin_mem(&plugin_dl);
636 report_error(report, ER_OUTOFMEMORY,
642 DBUG_ENTER(
"plugin_dl_add");
643 report_error(report, ER_FEATURE_DISABLED,
"plugin",
"HAVE_DLOPEN");
649 static void plugin_dl_del(
const LEX_STRING *dl)
653 DBUG_ENTER(
"plugin_dl_del");
657 for (i= 0; i < plugin_dl_array.elements; i++)
659 struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
661 if (tmp->ref_count &&
662 ! my_strnncoll(files_charset_info,
663 (
const uchar *)dl->str, dl->length,
664 (
const uchar *)tmp->dl.str, tmp->dl.length))
667 if (! --tmp->ref_count)
669 free_plugin_mem(tmp);
683 DBUG_ENTER(
"plugin_find_internal");
689 if (type == MYSQL_ANY_PLUGIN)
691 for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
694 my_hash_search(&plugin_hash[i], (
const uchar *)name->str, name->length);
701 my_hash_search(&plugin_hash[type], (
const uchar *)name->str,
707 static SHOW_COMP_OPTION plugin_status(
const LEX_STRING *name,
int type)
709 SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
711 DBUG_ENTER(
"plugin_is_ready");
713 if ((plugin= plugin_find_internal(name, type)))
715 rc= SHOW_OPTION_DISABLED;
716 if (plugin->state == PLUGIN_IS_READY)
724 bool plugin_is_ready(
const LEX_STRING *name,
int type)
727 if (plugin_status(name, type) == SHOW_OPTION_YES)
733 SHOW_COMP_OPTION plugin_status(
const char *name,
size_t len,
int type)
735 LEX_STRING plugin_name= { (
char *) name, len };
736 return plugin_status(&plugin_name, type);
743 DBUG_ENTER(
"intern_plugin_lock");
747 if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
762 if (!(plugin= (
plugin_ref) my_malloc(
sizeof(pi), MYF(MY_WME))))
768 DBUG_PRINT(
"info",(
"thd: %p, plugin: \"%s\", ref_count: %d",
769 current_thd, pi->name.str, pi->ref_count));
771 insert_dynamic(&lex->plugins, &plugin);
780 LEX *lex= thd ? thd->lex : 0;
782 DBUG_ENTER(
"plugin_lock");
784 rc= my_intern_plugin_lock_ci(lex, *ptr);
792 LEX *lex= thd ? thd->lex : 0;
795 DBUG_ENTER(
"plugin_lock_by_name");
797 if ((plugin= plugin_find_internal(name, type)))
798 rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
808 DBUG_ENTER(
"plugin_insert_or_reuse");
809 for (i= 0; i < plugin_array.elements; i++)
811 tmp= *dynamic_element(&plugin_array, i,
struct st_plugin_int **);
812 if (tmp->state == PLUGIN_IS_FREED)
818 if (insert_dynamic(&plugin_array, &plugin))
820 tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
822 (
struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)plugin,
832 static bool plugin_add(
MEM_ROOT *tmp_root,
834 int *argc,
char **argv,
int report)
838 DBUG_ENTER(
"plugin_add");
839 if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
841 report_error(report, ER_UDF_EXISTS, name->str);
845 memset(&tmp, 0,
sizeof(tmp));
846 if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
849 for (plugin= tmp.plugin_dl->plugins; plugin->info; plugin++)
851 uint name_len= strlen(plugin->name);
852 if (plugin->type >= 0 && plugin->type < MYSQL_MAX_PLUGIN_TYPE_NUM &&
853 ! my_strnncoll(system_charset_info,
854 (
const uchar *)name->str, name->length,
855 (
const uchar *)plugin->name,
859 if (*(
int*)plugin->info <
860 min_plugin_info_interface_version[plugin->type] ||
861 ((*(
int*)plugin->info) >> 8) >
862 (cur_plugin_info_interface_version[plugin->type] >> 8))
865 strxnmov(buf,
sizeof(buf) - 1,
"API version for ",
866 plugin_type_names[plugin->type].str,
867 " plugin is too different", NullS);
868 report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
872 tmp.name.str= (
char *)plugin->name;
873 tmp.name.length= name_len;
875 tmp.state= PLUGIN_IS_UNINITIALIZED;
876 tmp.load_option= PLUGIN_ON;
877 if (test_plugin_options(tmp_root, &tmp, argc, argv))
878 tmp.state= PLUGIN_IS_DISABLED;
880 if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
882 plugin_array_version++;
883 if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
885 init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
888 tmp_plugin_ptr->state= PLUGIN_IS_FREED;
890 mysql_del_sys_var_chain(tmp.system_vars);
891 restore_pluginvar_names(tmp.system_vars);
899 report_error(report, ER_CANT_FIND_DL_ENTRY, name->str);
906 static void plugin_deinitialize(
struct st_plugin_int *plugin,
bool ref_check)
915 if (plugin->plugin->status_vars)
926 {plugin->plugin->name, (
char*)plugin->plugin->status_vars, SHOW_ARRAY},
929 remove_status_vars(array);
931 remove_status_vars(plugin->plugin->status_vars);
935 if (plugin_type_deinitialize[plugin->plugin->type])
937 if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
939 sql_print_error(
"Plugin '%s' of type %s failed deinitialization",
940 plugin->name.str, plugin_type_names[plugin->plugin->type].str);
943 else if (plugin->plugin->deinit)
945 DBUG_PRINT(
"info", (
"Deinitializing plugin: '%s'", plugin->name.str));
946 if (plugin->plugin->deinit(plugin))
948 DBUG_PRINT(
"warning", (
"Plugin '%s' deinit function returned error.",
952 plugin->state= PLUGIN_IS_UNINITIALIZED;
958 if (ref_check && plugin->ref_count)
959 sql_print_error(
"Plugin '%s' has ref_count=%d after deinitialization.",
960 plugin->name.str, plugin->ref_count);
965 DBUG_ENTER(
"plugin_del(plugin)");
969 mysql_del_sys_var_chain(plugin->system_vars);
971 restore_pluginvar_names(plugin->system_vars);
972 plugin_vars_free_values(plugin->system_vars);
973 my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
974 if (plugin->plugin_dl)
975 plugin_dl_del(&plugin->plugin_dl->dl);
976 plugin->state= PLUGIN_IS_FREED;
977 plugin_array_version++;
978 free_root(&plugin->mem_root, MYF(0));
982 static void reap_plugins(
void)
993 count= plugin_array.elements;
994 reap= (
struct st_plugin_int **)my_alloca(
sizeof(plugin)*(count+1));
997 for (idx= 0; idx < count; idx++)
999 plugin= *dynamic_element(&plugin_array, idx,
struct st_plugin_int **);
1000 if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
1003 plugin->state= PLUGIN_IS_DYING;
1011 while ((plugin= *(--list)))
1014 sql_print_information(
"Shutting down plugin '%s'", plugin->name.str);
1015 plugin_deinitialize(plugin,
true);
1020 while ((plugin= *(--reap)))
1026 static void intern_plugin_unlock(LEX *lex,
plugin_ref plugin)
1030 DBUG_ENTER(
"intern_plugin_unlock");
1037 pi= plugin_ref_to_int(plugin);
1046 DBUG_PRINT(
"info",(
"unlocking plugin, name= %s, ref_count= %d",
1047 pi->name.str, pi->ref_count));
1055 for (i= lex->plugins.elements - 1; i >= 0; i--)
1056 if (plugin == *dynamic_element(&lex->plugins, i,
plugin_ref*))
1058 delete_dynamic_element(&lex->plugins, i);
1061 DBUG_ASSERT(i >= 0);
1064 DBUG_ASSERT(pi->ref_count);
1067 if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
1074 void plugin_unlock(THD *thd,
plugin_ref plugin)
1076 LEX *lex= thd ? thd->lex : 0;
1077 DBUG_ENTER(
"plugin_unlock");
1082 if (!plugin_dlib(plugin))
1086 intern_plugin_unlock(lex, plugin);
1093 void plugin_unlock_list(THD *thd,
plugin_ref *list, uint count)
1095 LEX *lex= thd ? thd->lex : 0;
1096 DBUG_ENTER(
"plugin_unlock_list");
1108 intern_plugin_unlock(lex, *list++);
1117 DBUG_ENTER(
"plugin_initialize");
1120 uint state= plugin->state;
1121 DBUG_ASSERT(state == PLUGIN_IS_UNINITIALIZED);
1124 if (plugin_type_initialize[plugin->plugin->type])
1126 if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
1128 sql_print_error(
"Plugin '%s' registration as a %s failed.",
1129 plugin->name.str, plugin_type_names[plugin->plugin->type].str);
1135 if (strcmp(plugin->name.str,
"InnoDB") == 0) {
1136 innodb_callback_data = ((
handlerton*)plugin->data)->data;
1139 else if (plugin->plugin->init)
1141 if (strcmp(plugin->name.str,
"daemon_memcached") == 0) {
1142 plugin->data = (
void*)innodb_callback_data;
1145 if (plugin->plugin->init(plugin))
1147 sql_print_error(
"Plugin '%s' init function returned error.",
1152 state= PLUGIN_IS_READY;
1154 if (plugin->plugin->status_vars)
1165 {plugin->plugin->name, (
char*)plugin->plugin->status_vars, SHOW_ARRAY},
1168 if (add_status_vars(array))
1171 if (add_status_vars(plugin->plugin->status_vars))
1180 if (plugin->system_vars)
1185 var->plugin= plugin;
1196 plugin->state= state;
1202 extern "C" uchar *get_plugin_hash_key(
const uchar *,
size_t *, my_bool);
1203 extern "C" uchar *get_bookmark_hash_key(
const uchar *,
size_t *, my_bool);
1206 uchar *get_plugin_hash_key(
const uchar *buff,
size_t *length,
1207 my_bool not_used __attribute__((unused)))
1210 *length= (uint)plugin->name.length;
1211 return((uchar *)plugin->name.str);
1215 uchar *get_bookmark_hash_key(
const uchar *buff,
size_t *length,
1216 my_bool not_used __attribute__((unused)))
1219 *length= var->name_len + 1;
1220 return (uchar*) var->key;
1223 static inline void convert_dash_to_underscore(
char *str,
int len)
1225 for (
char *p= str; p <= str+len; p++)
1230 static inline void convert_underscore_to_dash(
char *str,
int len)
1232 for (
char *p= str; p <= str+len; p++)
1237 #ifdef HAVE_PSI_INTERFACE
1238 static PSI_mutex_key key_LOCK_plugin;
1240 static PSI_mutex_info all_plugin_mutexes[]=
1242 { &key_LOCK_plugin,
"LOCK_plugin", PSI_FLAG_GLOBAL}
1245 static void init_plugin_psi_keys(
void)
1247 const char* category=
"sql";
1250 count= array_elements(all_plugin_mutexes);
1262 int plugin_init(
int *argc,
char **argv,
int flags)
1270 bool reaped_mandatory_plugin=
false;
1271 bool mandatory=
true;
1272 DBUG_ENTER(
"plugin_init");
1277 #ifdef HAVE_PSI_INTERFACE
1278 init_plugin_psi_keys();
1281 init_alloc_root(&plugin_mem_root, 4096, 4096);
1282 init_alloc_root(&tmp_root, 4096, 4096);
1284 if (my_hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
1285 get_bookmark_hash_key, NULL, HASH_UNIQUE))
1291 if (my_init_dynamic_array(&plugin_dl_array,
1293 my_init_dynamic_array(&plugin_array,
1297 for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
1299 if (my_hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
1300 get_plugin_hash_key, NULL, HASH_UNIQUE))
1311 for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++)
1315 builtins= mysql_optional_plugins;
1320 for (plugin= *builtins; plugin->info; plugin++)
1322 memset(&tmp, 0,
sizeof(tmp));
1324 tmp.name.str= (
char *)plugin->name;
1325 tmp.name.length= strlen(plugin->name);
1327 tmp.load_option= mandatory ? PLUGIN_FORCE : PLUGIN_ON;
1345 if (!my_strcasecmp(&my_charset_latin1, plugin->name,
"PERFORMANCE_SCHEMA"))
1346 tmp.load_option= PLUGIN_FORCE;
1348 free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1349 if (test_plugin_options(&tmp_root, &tmp, argc, argv))
1350 tmp.state= PLUGIN_IS_DISABLED;
1352 tmp.state= PLUGIN_IS_UNINITIALIZED;
1353 if (register_builtin(plugin, &tmp, &plugin_ptr))
1358 !my_strcasecmp(&my_charset_latin1, plugin->name,
"MyISAM")) &&
1359 my_strcasecmp(&my_charset_latin1, plugin->name,
"CSV"))
1362 if (plugin_ptr->state != PLUGIN_IS_UNINITIALIZED ||
1363 plugin_initialize(plugin_ptr))
1372 DBUG_ASSERT(!global_system_variables.table_plugin);
1373 DBUG_ASSERT(!global_system_variables.temp_table_plugin);
1374 global_system_variables.table_plugin=
1375 my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
1376 global_system_variables.temp_table_plugin=
1377 my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
1378 DBUG_ASSERT(plugin_ptr->ref_count == 2);
1384 DBUG_ASSERT(global_system_variables.table_plugin);
1385 DBUG_ASSERT(global_system_variables.temp_table_plugin);
1390 if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
1394 while (NULL != (item= iter++))
1395 plugin_load_list(&tmp_root, argc, argv, item->ptr);
1397 if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE))
1398 plugin_load(&tmp_root, argc, argv);
1401 if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
1409 reap= (
st_plugin_int **) my_alloca((plugin_array.elements+1) *
sizeof(
void*));
1412 for (i= 0; i < plugin_array.elements; i++)
1414 plugin_ptr= *dynamic_element(&plugin_array, i,
struct st_plugin_int **);
1415 if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
1417 if (plugin_initialize(plugin_ptr))
1419 plugin_ptr->state= PLUGIN_IS_DYING;
1420 *(reap++)= plugin_ptr;
1428 while ((plugin_ptr= *(--reap)))
1431 if (plugin_ptr->load_option == PLUGIN_FORCE ||
1432 plugin_ptr->load_option == PLUGIN_FORCE_PLUS_PERMANENT)
1433 reaped_mandatory_plugin= TRUE;
1434 plugin_deinitialize(plugin_ptr,
true);
1436 plugin_del(plugin_ptr);
1441 if (reaped_mandatory_plugin)
1445 free_root(&tmp_root, MYF(0));
1452 free_root(&tmp_root, MYF(0));
1461 DBUG_ENTER(
"register_builtin");
1465 if (insert_dynamic(&plugin_array, &tmp))
1468 *ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1470 (
struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)tmp,
1473 if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr))
1483 static void plugin_load(
MEM_ROOT *tmp_root,
int *argc,
char **argv)
1492 #ifdef EMBEDDED_LIBRARY
1495 DBUG_ENTER(
"plugin_load");
1497 new_thd->thread_stack= (
char*) &tables;
1498 new_thd->store_globals();
1499 new_thd->db= my_strdup(
"mysql", MYF(0));
1500 new_thd->db_length= 5;
1501 memset(&thd.net, 0,
sizeof(thd.net));
1502 tables.
init_one_table(
"mysql", 5,
"plugin", 6,
"plugin", TL_READ);
1504 #ifdef EMBEDDED_LIBRARY
1509 new_thd->push_internal_handler(&error_handler);
1514 #ifdef EMBEDDED_LIBRARY
1515 new_thd->pop_internal_handler();
1522 DBUG_PRINT(
"error",(
"Can't open plugin table"));
1523 sql_print_error(
"Can't open the mysql.plugin table. Please "
1524 "run mysql_upgrade to create it.");
1527 table= tables.table;
1528 if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 1, FALSE))
1530 table->use_all_columns();
1538 while (!(error= read_record_info.read_record(&read_record_info)))
1540 DBUG_PRINT(
"info", (
"init plugin record"));
1542 get_field(tmp_root, table->field[0], &str_name);
1543 get_field(tmp_root, table->field[1], &str_dl);
1545 LEX_STRING name= {(
char *)str_name.ptr(), str_name.length()};
1546 LEX_STRING dl= {(
char *)str_dl.ptr(), str_dl.length()};
1548 if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1549 sql_print_warning(
"Couldn't load plugin named '%s' with soname '%s'.",
1550 str_name.c_ptr(), str_dl.c_ptr());
1551 free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1555 sql_print_error(ER(ER_GET_ERRNO), my_errno);
1556 end_read_record(&read_record_info);
1557 table->m_needs_reopen= TRUE;
1561 my_pthread_setspecific_ptr(THR_THD, 0);
1569 static bool plugin_load_list(
MEM_ROOT *tmp_root,
int *argc,
char **argv,
1572 char buffer[FN_REFLEN];
1577 DBUG_ENTER(
"plugin_load_list");
1580 if (p == buffer +
sizeof(buffer) - 1)
1582 sql_print_error(
"plugin-load parameter too long");
1586 switch ((*(p++)= *(list++))) {
1594 str->str[str->length]=
'\0';
1605 if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1607 for (plugin= plugin_dl->plugins; plugin->info; plugin++)
1609 name.str= (
char *) plugin->name;
1610 name.length= strlen(name.str);
1612 free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1613 if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1621 free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1623 if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1627 name.length= dl.length= 0;
1628 dl.str= NULL; name.str= p= buffer;
1635 name.str[name.length]=
'\0';
1648 sql_print_error(
"Couldn't load plugin named '%s' with soname '%s'.",
1656 void memcached_shutdown(
void)
1661 for (uint i= 0; i < plugin_array.elements; i++)
1663 plugin= *dynamic_element(&plugin_array, i,
struct st_plugin_int **);
1665 if (plugin->state == PLUGIN_IS_READY
1666 && strcmp(plugin->name.str,
"daemon_memcached") == 0)
1668 plugin_deinitialize(plugin,
true);
1669 plugin->state= PLUGIN_IS_DYING;
1676 void plugin_shutdown(
void)
1678 uint
i, count= plugin_array.elements;
1681 bool skip_binlog =
true;
1683 DBUG_ENTER(
"plugin_shutdown");
1698 while (reap_needed && (count= plugin_array.elements))
1701 for (i= 0; i < count; i++)
1703 plugin= *dynamic_element(&plugin_array, i,
struct st_plugin_int **);
1705 if (plugin->state == PLUGIN_IS_READY
1706 && strcmp(plugin->name.str,
"binlog") == 0 && skip_binlog)
1708 skip_binlog =
false;
1710 }
else if (plugin->state == PLUGIN_IS_READY)
1712 plugin->state= PLUGIN_IS_DELETED;
1721 unlock_variables(NULL, &global_system_variables);
1722 unlock_variables(NULL, &max_system_variables);
1726 plugins= (
struct st_plugin_int **) my_alloca(
sizeof(
void*) * (count+1));
1731 for (i= 0; i < count; i++)
1733 plugins[
i]= *dynamic_element(&plugin_array, i,
struct st_plugin_int **);
1735 if (plugins[i]->state == PLUGIN_IS_DELETED)
1736 plugins[
i]->state= PLUGIN_IS_DYING;
1743 for (i= 0; i < count; i++)
1744 if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED |
1745 PLUGIN_IS_DISABLED)))
1747 sql_print_warning(
"Plugin '%s' will be forced to shutdown",
1748 plugins[i]->name.str);
1753 plugin_deinitialize(plugins[i],
false);
1767 for (i= 0; i < count; i++)
1769 if (plugins[i]->ref_count)
1770 sql_print_error(
"Plugin '%s' has ref_count=%d after shutdown.",
1771 plugins[i]->name.str, plugins[i]->ref_count);
1772 if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1773 plugin_del(plugins[i]);
1780 cleanup_variables(NULL, &global_system_variables);
1781 cleanup_variables(NULL, &max_system_variables);
1792 for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
1793 my_hash_free(&plugin_hash[i]);
1794 delete_dynamic(&plugin_array);
1796 count= plugin_dl_array.elements;
1797 dl= (
struct st_plugin_dl **)my_alloca(
sizeof(
void*) * count);
1798 for (i= 0; i < count; i++)
1799 dl[i]= *dynamic_element(&plugin_dl_array, i,
struct st_plugin_dl **);
1800 for (i= 0; i < plugin_dl_array.elements; i++)
1801 free_plugin_mem(dl[i]);
1803 delete_dynamic(&plugin_dl_array);
1805 my_hash_free(&bookmark_hash);
1806 free_root(&plugin_mem_root, MYF(0));
1808 global_variables_dynamic_size= 0;
1818 int error, argc=orig_argc;
1819 char **argv=orig_argv;
1821 DBUG_ENTER(
"mysql_install_plugin");
1825 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-grant-tables");
1829 tables.
init_one_table(
"mysql", 5,
"plugin", 6,
"plugin", TL_WRITE);
1834 if (! (table = open_ltable(thd, &tables, TL_WRITE,
1835 MYSQL_LOCK_IGNORE_TIMEOUT)))
1857 mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
1862 if (my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL))
1865 report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str);
1868 error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER);
1870 free_defaults(argv);
1873 if (error || !(tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
1876 if (tmp->state == PLUGIN_IS_DISABLED)
1878 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1879 ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
1880 name->str,
"Plugin is disabled");
1884 if (plugin_initialize(tmp))
1887 my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
1888 "Plugin initialization function failed.");
1899 tmp_disable_binlog(thd);
1900 table->use_all_columns();
1901 restore_record(table, s->default_values);
1902 table->field[0]->store(name->str, name->length, system_charset_info);
1903 table->field[1]->store(dl->str, dl->length, files_charset_info);
1904 error= table->file->ha_write_row(table->record[0]);
1905 reenable_binlog(thd);
1914 tmp->state= PLUGIN_IS_DELETED;
1923 bool mysql_uninstall_plugin(THD *thd,
const LEX_STRING *name)
1928 DBUG_ENTER(
"mysql_uninstall_plugin");
1932 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-grant-tables");
1936 tables.
init_one_table(
"mysql", 5,
"plugin", 6,
"plugin", TL_WRITE);
1942 if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
1945 if (!table->key_info)
1947 my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
1948 table->s->table_name.str);
1971 mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
1974 if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)) ||
1975 plugin->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_DYING))
1977 my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
"PLUGIN", name->str);
1980 if (!plugin->plugin_dl)
1982 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
1983 WARN_PLUGIN_DELETE_BUILTIN, ER(WARN_PLUGIN_DELETE_BUILTIN));
1984 my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
"PLUGIN", name->str);
1987 if (plugin->load_option == PLUGIN_FORCE_PLUS_PERMANENT)
1989 my_error(ER_PLUGIN_IS_PERMANENT, MYF(0), name->str);
1997 if (plugin->plugin->flags & PLUGIN_OPT_NO_UNINSTALL)
1999 my_error(ER_PLUGIN_NO_UNINSTALL, MYF(0), plugin->plugin->name);
2003 plugin->state= PLUGIN_IS_DELETED;
2004 if (plugin->ref_count)
2005 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
2006 WARN_PLUGIN_BUSY, ER(WARN_PLUGIN_BUSY));
2012 uchar user_key[MAX_KEY_LENGTH];
2013 table->use_all_columns();
2014 table->field[0]->store(name->str, name->length, system_charset_info);
2015 key_copy(user_key, table->record[0], table->key_info,
2018 HA_WHOLE_KEY, HA_READ_KEY_EXACT))
2026 tmp_disable_binlog(thd);
2027 error= table->file->ha_delete_row(table->record[0]);
2028 reenable_binlog(thd);
2042 bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
2043 int type, uint state_mask,
void *arg)
2047 int version=plugin_array_version;
2048 DBUG_ENTER(
"plugin_foreach_with_mask");
2053 state_mask= ~state_mask;
2056 total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements
2057 : plugin_hash[
type].records;
2062 plugins=(
struct st_plugin_int **)my_alloca(total*
sizeof(plugin));
2063 if (type == MYSQL_ANY_PLUGIN)
2065 for (idx= 0; idx < total; idx++)
2067 plugin= *dynamic_element(&plugin_array, idx,
struct st_plugin_int **);
2068 plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
2074 for (idx= 0; idx < total; idx++)
2076 plugin= (
struct st_plugin_int *) my_hash_element(hash, idx);
2077 plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
2082 for (idx= 0; idx < total; idx++)
2084 if (unlikely(version != plugin_array_version))
2087 for (uint i=idx; i < total; i++)
2088 if (plugins[i] && plugins[i]->state & state_mask)
2092 plugin= plugins[idx];
2094 if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
2110 #undef MYSQL_SYSVAR_NAME
2111 #define MYSQL_SYSVAR_NAME(name) name
2112 #define PLUGIN_VAR_TYPEMASK 0x007f
2114 #define EXTRA_OPTIONS 3
2116 typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_bool_t, my_bool);
2117 typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_bool_t, my_bool);
2118 typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_str_t,
char *);
2119 typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_str_t,
char *);
2121 typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_enum_t,
unsigned long);
2122 typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_enum_t,
unsigned long);
2123 typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_set_t, ulonglong);
2124 typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_set_t, ulonglong);
2126 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_int_t,
int);
2127 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_long_t,
long);
2128 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_longlong_t, longlong);
2129 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint_t, uint);
2130 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
2131 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulonglong_t, ulonglong);
2132 typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_double_t,
double);
2134 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int_t,
int);
2135 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_long_t,
long);
2136 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_longlong_t, longlong);
2137 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint);
2138 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
2139 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong);
2140 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_double_t,
double);
2150 char buff[STRING_BUFFER_USUAL_SIZE];
2155 if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
2157 length=
sizeof(buff);
2158 if (!(str= value->val_str(value, buff, &length)) ||
2159 (result= find_type(&bool_typelib, str, length, 1)-1) < 0)
2164 if (value->val_int(value, &tmp) < 0)
2170 *(my_bool *) save= result ? TRUE : FALSE;
2180 my_bool fixed1, fixed2;
2181 long long orig, val;
2183 value->val_int(value, &orig);
2185 plugin_opt_set_limits(&options, var);
2187 if (var->flags & PLUGIN_VAR_UNSIGNED)
2189 if ((fixed1= (!value->is_unsigned(value) && val < 0)))
2191 *(uint *)save= (uint) getopt_ull_limit_value((ulonglong) val, &options,
2196 if ((fixed1= (value->is_unsigned(value) && val < 0)))
2198 *(
int *)save= (
int) getopt_ll_limit_value(val, &options, &fixed2);
2201 return throw_bounds_warning(thd, var->name, fixed1 || fixed2,
2202 value->is_unsigned(value), (longlong) orig);
2209 my_bool fixed1, fixed2;
2210 long long orig, val;
2212 value->val_int(value, &orig);
2214 plugin_opt_set_limits(&options, var);
2216 if (var->flags & PLUGIN_VAR_UNSIGNED)
2218 if ((fixed1= (!value->is_unsigned(value) && val < 0)))
2220 *(ulong *)save= (ulong) getopt_ull_limit_value((ulonglong) val, &options,
2225 if ((fixed1= (value->is_unsigned(value) && val < 0)))
2227 *(
long *)save= (
long) getopt_ll_limit_value(val, &options, &fixed2);
2230 return throw_bounds_warning(thd, var->name, fixed1 || fixed2,
2231 value->is_unsigned(value), (longlong) orig);
2238 my_bool fixed1, fixed2;
2239 long long orig, val;
2241 value->val_int(value, &orig);
2243 plugin_opt_set_limits(&options, var);
2245 if (var->flags & PLUGIN_VAR_UNSIGNED)
2247 if ((fixed1= (!value->is_unsigned(value) && val < 0)))
2249 *(ulonglong *)save= getopt_ull_limit_value((ulonglong) val, &options,
2254 if ((fixed1= (value->is_unsigned(value) && val < 0)))
2256 *(longlong *)save= getopt_ll_limit_value(val, &options, &fixed2);
2259 return throw_bounds_warning(thd, var->name, fixed1 || fixed2,
2260 value->is_unsigned(value), (longlong) orig);
2266 char buff[STRING_BUFFER_USUAL_SIZE];
2270 length=
sizeof(buff);
2271 if ((str= value->val_str(value, buff, &length)))
2272 str= thd->strmake(str, length);
2273 *(
const char**)save= str;
2281 char buff[STRING_BUFFER_USUAL_SIZE];
2288 if (var->flags & PLUGIN_VAR_THDLOCAL)
2289 typelib= ((thdvar_enum_t*) var)->typelib;
2291 typelib= ((sysvar_enum_t*) var)->typelib;
2293 if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
2295 length=
sizeof(buff);
2296 if (!(str= value->val_str(value, buff, &length)))
2298 if ((result= (
long)find_type(typelib, str, length, 0) - 1) < 0)
2303 if (value->val_int(value, &tmp))
2305 if (tmp < 0 || tmp >= typelib->count)
2309 *(
long*)save= result;
2319 char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
2327 if (var->flags & PLUGIN_VAR_THDLOCAL)
2328 typelib= ((thdvar_set_t*) var)->typelib;
2330 typelib= ((sysvar_set_t*)var)->typelib;
2332 if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
2334 length=
sizeof(buff);
2335 if (!(str= value->val_str(value, buff, &length)))
2337 result= find_set(typelib, str, length, NULL,
2338 &error, &error_len, ¬_used);
2344 if (value->val_int(value, (
long long *)&result))
2346 if (unlikely((result >= (1ULL << typelib->count)) &&
2347 (typelib->count <
sizeof(
long)*8)))
2350 *(ulonglong*)save= result;
2363 value->val_real(value, &v);
2364 plugin_opt_set_limits(&
option, var);
2365 *(
double *) save= getopt_double_limit_value(v, &
option, &fixed);
2367 return throw_bounds_warning(thd, var->name, fixed, v);
2372 void *tgt,
const void *save)
2374 *(my_bool *) tgt= *(my_bool *) save ? TRUE : FALSE;
2379 void *tgt,
const void *save)
2381 *(
int *)tgt= *(
int *) save;
2386 void *tgt,
const void *save)
2388 *(
long *)tgt= *(
long *) save;
2393 void *tgt,
const void *save)
2395 *(longlong *)tgt= *(ulonglong *) save;
2400 void *tgt,
const void *save)
2402 *(
char **) tgt= *(
char **) save;
2406 void *tgt,
const void *save)
2408 *(
double *) tgt= *(
double *) save;
2416 sys_var *find_sys_var(THD *thd,
const char *str, uint length)
2421 DBUG_ENTER(
"find_sys_var");
2425 if ((var= intern_find_sys_var(str, length)) &&
2429 LEX *lex= thd ? thd->lex : 0;
2430 if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
2433 if (!(plugin_state(plugin) & PLUGIN_IS_READY))
2437 intern_plugin_unlock(lex, plugin);
2445 my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (
char*) str);
2455 static st_bookmark *find_bookmark(
const char *plugin,
const char *name,
2459 uint namelen, length, pluginlen= 0;
2462 if (!(flags & PLUGIN_VAR_THDLOCAL))
2465 namelen= strlen(name);
2467 pluginlen= strlen(plugin) + 1;
2468 length= namelen + pluginlen + 2;
2469 varname= (
char*) my_alloca(length);
2473 strxmov(varname + 1, plugin,
"_", name, NullS);
2474 for (p= varname + 1; *p; p++)
2479 memcpy(varname + 1, name, namelen + 1);
2481 varname[0]= flags & PLUGIN_VAR_TYPEMASK;
2483 result= (
st_bookmark*) my_hash_search(&bookmark_hash,
2484 (
const uchar*) varname, length - 1);
2496 static st_bookmark *register_var(
const char *plugin,
const char *name,
2499 uint length= strlen(plugin) + strlen(name) + 3,
size= 0,
offset, new_size;
2503 if (!(flags & PLUGIN_VAR_THDLOCAL))
2506 switch (flags & PLUGIN_VAR_TYPEMASK) {
2507 case PLUGIN_VAR_BOOL:
2508 size=
sizeof(my_bool);
2510 case PLUGIN_VAR_INT:
2513 case PLUGIN_VAR_LONG:
2514 case PLUGIN_VAR_ENUM:
2517 case PLUGIN_VAR_LONGLONG:
2518 case PLUGIN_VAR_SET:
2519 size=
sizeof(ulonglong);
2521 case PLUGIN_VAR_STR:
2522 size=
sizeof(
char*);
2524 case PLUGIN_VAR_DOUBLE:
2525 size=
sizeof(double);
2532 varname= ((
char*) my_alloca(length));
2533 strxmov(varname + 1, plugin,
"_", name, NullS);
2534 for (p= varname + 1; *p; p++)
2538 if (!(result= find_bookmark(NULL, varname + 1, flags)))
2540 result= (
st_bookmark*) alloc_root(&plugin_mem_root,
2542 varname[0]= flags & PLUGIN_VAR_TYPEMASK;
2543 memcpy(result->key, varname, length);
2544 result->name_len= length - 2;
2549 offset= global_system_variables.dynamic_variables_size;
2551 result->offset= (int)
offset;
2555 if (new_size > global_variables_dynamic_size)
2557 global_system_variables.dynamic_variables_ptr= (
char*)
2558 my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
2559 MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
2560 max_system_variables.dynamic_variables_ptr= (
char*)
2561 my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
2562 MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
2568 memset(global_system_variables.dynamic_variables_ptr +
2569 global_variables_dynamic_size, 0,
2570 new_size - global_variables_dynamic_size);
2571 memset(max_system_variables.dynamic_variables_ptr +
2572 global_variables_dynamic_size, 0,
2573 new_size - global_variables_dynamic_size);
2574 global_variables_dynamic_size= new_size;
2577 global_system_variables.dynamic_variables_head=
offset;
2578 max_system_variables.dynamic_variables_head=
offset;
2579 global_system_variables.dynamic_variables_size=
offset +
size;
2580 max_system_variables.dynamic_variables_size=
offset +
size;
2581 global_system_variables.dynamic_variables_version++;
2582 max_system_variables.dynamic_variables_version++;
2584 result->version= global_system_variables.dynamic_variables_version;
2587 if (my_hash_insert(&bookmark_hash, (uchar*) result))
2589 fprintf(stderr,
"failed to add placeholder to hash");
2597 static void restore_pluginvar_names(
sys_var *first)
2599 for (
sys_var *var= first; var; var= var->next)
2613 static uchar *intern_sys_var_ptr(THD* thd,
int offset,
bool global_lock)
2615 DBUG_ASSERT(offset >= 0);
2616 DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head);
2619 return (uchar*) global_system_variables.dynamic_variables_ptr +
offset;
2624 if (!thd->variables.dynamic_variables_ptr ||
2625 (uint)offset > thd->variables.dynamic_variables_head)
2631 thd->variables.dynamic_variables_ptr= (
char*)
2632 my_realloc(thd->variables.dynamic_variables_ptr,
2633 global_variables_dynamic_size,
2634 MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
2641 memcpy(thd->variables.dynamic_variables_ptr +
2642 thd->variables.dynamic_variables_size,
2643 global_system_variables.dynamic_variables_ptr +
2644 thd->variables.dynamic_variables_size,
2645 global_system_variables.dynamic_variables_size -
2646 thd->variables.dynamic_variables_size);
2652 for (idx= 0; idx < bookmark_hash.records; idx++)
2658 if (v->version <= thd->variables.dynamic_variables_version ||
2659 !(var= intern_find_sys_var(v->key + 1, v->name_len)) ||
2661 v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
2666 if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
2667 pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
2669 int varoff= *(
int *) (pi->plugin_var + 1);
2670 char **thdvar= (
char **) (thd->variables.
2671 dynamic_variables_ptr + varoff);
2672 char **sysvar= (
char **) (global_system_variables.
2673 dynamic_variables_ptr + varoff);
2675 plugin_var_memalloc_session_update(thd, NULL, thdvar, *sysvar);
2682 thd->variables.dynamic_variables_version=
2683 global_system_variables.dynamic_variables_version;
2684 thd->variables.dynamic_variables_head=
2685 global_system_variables.dynamic_variables_head;
2686 thd->variables.dynamic_variables_size=
2687 global_system_variables.dynamic_variables_size;
2691 return (uchar*)thd->variables.dynamic_variables_ptr +
offset;
2703 static char *mysql_sys_var_char(THD* thd,
int offset)
2705 return (
char *) intern_sys_var_ptr(thd, offset,
true);
2708 static int *mysql_sys_var_int(THD* thd,
int offset)
2710 return (
int *) intern_sys_var_ptr(thd, offset,
true);
2713 static long *mysql_sys_var_long(THD* thd,
int offset)
2715 return (
long *) intern_sys_var_ptr(thd, offset,
true);
2718 static unsigned long *mysql_sys_var_ulong(THD* thd,
int offset)
2720 return (
unsigned long *) intern_sys_var_ptr(thd, offset,
true);
2723 static long long *mysql_sys_var_longlong(THD* thd,
int offset)
2725 return (
long long *) intern_sys_var_ptr(thd, offset,
true);
2728 static unsigned long long *mysql_sys_var_ulonglong(THD* thd,
int offset)
2730 return (
unsigned long long *) intern_sys_var_ptr(thd, offset,
true);
2733 static char **mysql_sys_var_str(THD* thd,
int offset)
2735 return (
char **) intern_sys_var_ptr(thd, offset,
true);
2738 static double *mysql_sys_var_double(THD* thd,
int offset)
2740 return (
double *) intern_sys_var_ptr(thd, offset,
true);
2743 void plugin_thdvar_init(THD *thd,
bool enable_plugins)
2745 plugin_ref old_table_plugin= thd->variables.table_plugin;
2746 plugin_ref old_temp_table_plugin= thd->variables.temp_table_plugin;
2747 DBUG_ENTER(
"plugin_thdvar_init");
2749 thd->variables.table_plugin= NULL;
2750 thd->variables.temp_table_plugin= NULL;
2751 cleanup_variables(thd, &thd->variables);
2753 thd->variables= global_system_variables;
2754 thd->variables.table_plugin= NULL;
2755 thd->variables.temp_table_plugin= NULL;
2758 thd->variables.dynamic_variables_version= 0;
2759 thd->variables.dynamic_variables_size= 0;
2760 thd->variables.dynamic_variables_ptr= 0;
2765 thd->variables.table_plugin=
2766 my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
2767 intern_plugin_unlock(NULL, old_table_plugin);
2768 thd->variables.temp_table_plugin=
2769 my_intern_plugin_lock(NULL, global_system_variables.temp_table_plugin);
2770 intern_plugin_unlock(NULL, old_temp_table_plugin);
2782 intern_plugin_unlock(NULL, vars->table_plugin);
2783 intern_plugin_unlock(NULL, vars->temp_table_plugin);
2784 vars->table_plugin= NULL;
2785 vars->temp_table_plugin= NULL;
2798 plugin_var_memalloc_free(&thd->variables);
2800 DBUG_ASSERT(vars->table_plugin == NULL);
2801 DBUG_ASSERT(vars->temp_table_plugin == NULL);
2803 my_free(vars->dynamic_variables_ptr);
2804 vars->dynamic_variables_ptr= NULL;
2805 vars->dynamic_variables_size= 0;
2806 vars->dynamic_variables_version= 0;
2810 void plugin_thdvar_cleanup(THD *thd)
2814 DBUG_ENTER(
"plugin_thdvar_cleanup");
2818 unlock_variables(thd, &thd->variables);
2819 cleanup_variables(thd, &thd->variables);
2821 if ((idx= thd->lex->plugins.elements))
2823 list= ((
plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
2824 DBUG_PRINT(
"info",(
"unlocking %d plugins", idx));
2825 while ((uchar*) list >= thd->lex->plugins.buffer)
2826 intern_plugin_unlock(thd->lex, *list--);
2832 reset_dynamic(&thd->lex->plugins);
2849 static void plugin_vars_free_values(
sys_var *vars)
2851 DBUG_ENTER(
"plugin_vars_free_values");
2853 for (
sys_var *var= vars; var; var= var->next)
2857 ((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
2858 (piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
2861 char **valptr= (
char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2862 DBUG_PRINT(
"plugin", (
"freeing value for: '%s' addr: 0x%lx",
2863 var->name.str, (
long) valptr));
2873 switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2874 case PLUGIN_VAR_BOOL:
2875 return SHOW_MY_BOOL;
2876 case PLUGIN_VAR_INT:
2878 case PLUGIN_VAR_LONG:
2880 case PLUGIN_VAR_LONGLONG:
2881 return SHOW_LONGLONG;
2882 case PLUGIN_VAR_STR:
2883 return SHOW_CHAR_PTR;
2884 case PLUGIN_VAR_ENUM:
2885 case PLUGIN_VAR_SET:
2887 case PLUGIN_VAR_DOUBLE:
2933 static bool plugin_var_memalloc_session_update(THD *thd,
2935 char **dest,
const char *value)
2938 LIST *old_element= NULL;
2940 DBUG_ENTER(
"plugin_var_memalloc_session_update");
2944 size_t length= strlen(value) + 1;
2946 if (!(element= (
LIST *) my_malloc(
sizeof(
LIST) + length, MYF(MY_WME))))
2948 memcpy(element + 1, value, length);
2949 value= (
const char *) (element + 1);
2950 vars->dynamic_variables_allocs= list_add(vars->dynamic_variables_allocs,
2955 old_element= (
LIST *) (*dest -
sizeof(
LIST));
2958 var->update(thd, var, (
void **) dest, (
const void *) &value);
2960 *dest= (
char *) value;
2964 vars->dynamic_variables_allocs= list_delete(vars->dynamic_variables_allocs,
2966 my_free(old_element);
2983 DBUG_ENTER(
"plugin_var_memalloc_free");
2984 for (root= vars->dynamic_variables_allocs; root; root= next)
2989 vars->dynamic_variables_allocs= NULL;
3007 static bool plugin_var_memalloc_global_update(THD *thd,
3009 char **dest,
const char *value)
3011 char *old_value= *dest;
3012 DBUG_ENTER(
"plugin_var_memalloc_global_update");
3014 if (value && !(value= my_strdup(value, MYF(MY_WME))))
3017 var->update(thd, var, (
void **) dest, (
const void *) &value);
3026 bool sys_var_pluginvar::check_update_type(Item_result type)
3028 switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
3029 case PLUGIN_VAR_INT:
3030 case PLUGIN_VAR_LONG:
3031 case PLUGIN_VAR_LONGLONG:
3032 return type != INT_RESULT;
3033 case PLUGIN_VAR_STR:
3034 return type != STRING_RESULT;
3035 case PLUGIN_VAR_ENUM:
3036 case PLUGIN_VAR_BOOL:
3037 case PLUGIN_VAR_SET:
3038 return type != STRING_RESULT && type != INT_RESULT;
3039 case PLUGIN_VAR_DOUBLE:
3040 return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT;
3047 uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
3049 DBUG_ASSERT(thd || (type == OPT_GLOBAL));
3050 if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
3052 if (type == OPT_GLOBAL)
3055 return intern_sys_var_ptr(thd, *(
int*) (plugin_var+1),
false);
3057 return *(uchar**) (plugin_var+1);
3061 TYPELIB* sys_var_pluginvar::plugin_var_typelib(
void)
3063 switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
3064 case PLUGIN_VAR_ENUM:
3065 return ((sysvar_enum_t *)plugin_var)->typelib;
3066 case PLUGIN_VAR_SET:
3067 return ((sysvar_set_t *)plugin_var)->typelib;
3068 case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
3069 return ((thdvar_enum_t *)plugin_var)->typelib;
3070 case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
3071 return ((thdvar_set_t *)plugin_var)->typelib;
3079 uchar* sys_var_pluginvar::do_value_ptr(THD *thd, enum_var_type type,
3084 result= real_value_ptr(thd, type);
3086 if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
3087 result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result);
3088 else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
3089 result= (uchar*) set_to_string(thd, 0, *(ulonglong*) result,
3090 plugin_var_typelib()->type_names);
3094 bool sys_var_pluginvar::do_check(THD *thd,
set_var *var)
3097 DBUG_ASSERT(!is_readonly());
3098 DBUG_ASSERT(plugin_var->check);
3100 value.value_type= item_value_type;
3101 value.val_str= item_val_str;
3102 value.val_int= item_val_int;
3103 value.val_real= item_val_real;
3104 value.is_unsigned= item_is_unsigned;
3105 value.item= var->
value;
3107 return plugin_var->check(thd, plugin_var, &var->save_result, &value);
3110 bool sys_var_pluginvar::session_update(THD *thd,
set_var *var)
3113 DBUG_ASSERT(!is_readonly());
3114 DBUG_ASSERT(plugin_var->flags & PLUGIN_VAR_THDLOCAL);
3115 DBUG_ASSERT(thd == current_thd);
3118 void *tgt= real_value_ptr(thd, var->type);
3119 const void *src= var->
value ? (
void*)&var->save_result
3120 : (
void*)real_value_ptr(thd, OPT_GLOBAL);
3123 if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
3124 plugin_var->flags & PLUGIN_VAR_MEMALLOC)
3125 rc= plugin_var_memalloc_session_update(thd, plugin_var, (
char **) tgt,
3126 *(
const char **) src);
3128 plugin_var->update(thd, plugin_var, tgt, src);
3133 bool sys_var_pluginvar::global_update(THD *thd,
set_var *var)
3136 DBUG_ASSERT(!is_readonly());
3139 void *tgt= real_value_ptr(thd, var->type);
3140 const void *src= &var->save_result;
3144 switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
3145 case PLUGIN_VAR_INT:
3146 src= &((sysvar_uint_t*) plugin_var)->def_val;
3148 case PLUGIN_VAR_LONG:
3149 src= &((sysvar_ulong_t*) plugin_var)->def_val;
3151 case PLUGIN_VAR_LONGLONG:
3152 src= &((sysvar_ulonglong_t*) plugin_var)->def_val;
3154 case PLUGIN_VAR_ENUM:
3155 src= &((sysvar_enum_t*) plugin_var)->def_val;
3157 case PLUGIN_VAR_SET:
3158 src= &((sysvar_set_t*) plugin_var)->def_val;
3160 case PLUGIN_VAR_BOOL:
3161 src= &((sysvar_bool_t*) plugin_var)->def_val;
3163 case PLUGIN_VAR_STR:
3164 src= &((sysvar_str_t*) plugin_var)->def_val;
3166 case PLUGIN_VAR_DOUBLE:
3167 src= &((sysvar_double_t*) plugin_var)->def_val;
3169 case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
3170 src= &((thdvar_uint_t*) plugin_var)->def_val;
3172 case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
3173 src= &((thdvar_ulong_t*) plugin_var)->def_val;
3175 case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
3176 src= &((thdvar_ulonglong_t*) plugin_var)->def_val;
3178 case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
3179 src= &((thdvar_enum_t*) plugin_var)->def_val;
3181 case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
3182 src= &((thdvar_set_t*) plugin_var)->def_val;
3184 case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
3185 src= &((thdvar_bool_t*) plugin_var)->def_val;
3187 case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
3188 src= &((thdvar_str_t*) plugin_var)->def_val;
3190 case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL:
3191 src= &((thdvar_double_t*) plugin_var)->def_val;
3198 if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
3199 plugin_var->flags & PLUGIN_VAR_MEMALLOC)
3200 rc= plugin_var_memalloc_global_update(thd, plugin_var, (
char **) tgt,
3201 *(
const char **) src);
3203 plugin_var->update(thd, plugin_var, tgt, src);
3209 #define OPTION_SET_LIMITS(type, options, opt) \
3210 options->var_type= type; \
3211 options->def_value= (opt)->def_val; \
3212 options->min_value= (opt)->min_val; \
3213 options->max_value= (opt)->max_val; \
3214 options->block_size= (long) (opt)->blk_sz
3216 #define OPTION_SET_LIMITS_DOUBLE(options, opt) \
3217 options->var_type= GET_DOUBLE; \
3218 options->def_value= (longlong) getopt_double2ulonglong((opt)->def_val); \
3219 options->min_value= (longlong) getopt_double2ulonglong((opt)->min_val); \
3220 options->max_value= getopt_double2ulonglong((opt)->max_val); \
3221 options->block_size= (long) (opt)->blk_sz;
3224 static void plugin_opt_set_limits(
struct my_option *options,
3229 switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
3230 PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
3232 case PLUGIN_VAR_INT:
3233 OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
3235 case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
3236 OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
3238 case PLUGIN_VAR_LONG:
3239 OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
3241 case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
3242 OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
3244 case PLUGIN_VAR_LONGLONG:
3245 OPTION_SET_LIMITS(GET_LL, options, (sysvar_longlong_t*) opt);
3247 case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
3248 OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) opt);
3250 case PLUGIN_VAR_ENUM:
3252 options->
typelib= ((sysvar_enum_t*) opt)->typelib;
3253 options->
def_value= ((sysvar_enum_t*) opt)->def_val;
3257 case PLUGIN_VAR_SET:
3259 options->
typelib= ((sysvar_set_t*) opt)->typelib;
3260 options->
def_value= ((sysvar_set_t*) opt)->def_val;
3264 case PLUGIN_VAR_BOOL:
3266 options->
def_value= ((sysvar_bool_t*) opt)->def_val;
3268 case PLUGIN_VAR_STR:
3269 options->
var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
3270 GET_STR_ALLOC : GET_STR);
3271 options->
def_value= (intptr) ((sysvar_str_t*) opt)->def_val;
3273 case PLUGIN_VAR_DOUBLE:
3274 OPTION_SET_LIMITS_DOUBLE(options, (sysvar_double_t*) opt);
3277 case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
3278 OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
3280 case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
3281 OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
3283 case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
3284 OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
3286 case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
3287 OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
3289 case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
3290 OPTION_SET_LIMITS(GET_LL, options, (thdvar_longlong_t*) opt);
3292 case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
3293 OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) opt);
3295 case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL:
3296 OPTION_SET_LIMITS_DOUBLE(options, (thdvar_double_t*) opt);
3298 case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
3300 options->
typelib= ((thdvar_enum_t*) opt)->typelib;
3301 options->
def_value= ((thdvar_enum_t*) opt)->def_val;
3305 case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
3307 options->
typelib= ((thdvar_set_t*) opt)->typelib;
3308 options->
def_value= ((thdvar_set_t*) opt)->def_val;
3312 case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
3314 options->
def_value= ((thdvar_bool_t*) opt)->def_val;
3316 case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
3317 options->
var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
3318 GET_STR_ALLOC : GET_STR);
3319 options->
def_value= (intptr) ((thdvar_str_t*) opt)->def_val;
3325 if (opt->flags & PLUGIN_VAR_NOCMDARG)
3327 if (opt->flags & PLUGIN_VAR_OPCMDARG)
3331 extern "C" my_bool get_one_plugin_option(
int optid,
const struct my_option *,
3334 my_bool get_one_plugin_option(
int optid __attribute__((unused)),
3364 const char *plugin_name= tmp->plugin->name;
3365 const LEX_STRING plugin_dash = { C_STRING_WITH_LEN(
"plugin-") };
3366 uint plugin_name_len= strlen(plugin_name);
3368 const int max_comment_len= 180;
3369 char *comment= (
char *) alloc_root(mem_root, max_comment_len + 1);
3372 int index= 0, offset= 0;
3377 char *plugin_name_ptr, *plugin_name_with_prefix_ptr;
3379 DBUG_ENTER(
"construct_options");
3381 plugin_name_ptr= (
char*) alloc_root(mem_root, plugin_name_len + 1);
3382 strcpy(plugin_name_ptr, plugin_name);
3383 my_casedn_str(&my_charset_latin1, plugin_name_ptr);
3384 convert_underscore_to_dash(plugin_name_ptr, plugin_name_len);
3385 plugin_name_with_prefix_ptr= (
char*) alloc_root(mem_root,
3387 plugin_dash.length + 1);
3388 strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, plugin_name_ptr, NullS);
3390 if (tmp->load_option != PLUGIN_FORCE &&
3391 tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT)
3394 options[0].
name= plugin_name_ptr;
3395 options[1].
name= plugin_name_with_prefix_ptr;
3403 strxnmov(comment, max_comment_len,
"Enable or disable ", plugin_name,
3404 " plugin. Possible values are ON, OFF, FORCE (don't start "
3405 "if the plugin fails to load).", NullS);
3414 (uchar **)alloc_root(mem_root,
sizeof(ulong));
3415 *((ulong*) options[0].value)= (ulong) options[0].def_value;
3420 if (!my_strcasecmp(&my_charset_latin1, plugin_name_ptr,
"NDBCLUSTER"))
3422 plugin_name_ptr=
const_cast<char*
>(
"ndb");
3431 for (plugin_option= tmp->plugin->system_vars;
3432 plugin_option && *plugin_option; plugin_option++, index++)
3434 opt= *plugin_option;
3435 if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
3437 if (!(register_var(plugin_name_ptr, opt->name, opt->flags)))
3439 switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
3440 case PLUGIN_VAR_BOOL:
3441 ((thdvar_bool_t *) opt)->resolve= mysql_sys_var_char;
3443 case PLUGIN_VAR_INT:
3444 ((thdvar_int_t *) opt)->resolve= mysql_sys_var_int;
3446 case PLUGIN_VAR_LONG:
3447 ((thdvar_long_t *) opt)->resolve= mysql_sys_var_long;
3449 case PLUGIN_VAR_LONGLONG:
3450 ((thdvar_longlong_t *) opt)->resolve= mysql_sys_var_longlong;
3452 case PLUGIN_VAR_STR:
3453 ((thdvar_str_t *) opt)->resolve= mysql_sys_var_str;
3455 case PLUGIN_VAR_ENUM:
3456 ((thdvar_enum_t *) opt)->resolve= mysql_sys_var_ulong;
3458 case PLUGIN_VAR_SET:
3459 ((thdvar_set_t *) opt)->resolve= mysql_sys_var_ulonglong;
3461 case PLUGIN_VAR_DOUBLE:
3462 ((thdvar_double_t *) opt)->resolve= mysql_sys_var_double;
3465 sql_print_error(
"Unknown variable type code 0x%x in plugin '%s'.",
3466 opt->flags, plugin_name);
3471 for (plugin_option= tmp->plugin->system_vars;
3472 plugin_option && *plugin_option; plugin_option++, index++)
3474 switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
3475 case PLUGIN_VAR_BOOL:
3477 opt->check= check_func_bool;
3479 opt->update= update_func_bool;
3481 case PLUGIN_VAR_INT:
3483 opt->check= check_func_int;
3485 opt->update= update_func_int;
3487 case PLUGIN_VAR_LONG:
3489 opt->check= check_func_long;
3491 opt->update= update_func_long;
3493 case PLUGIN_VAR_LONGLONG:
3495 opt->check= check_func_longlong;
3497 opt->update= update_func_longlong;
3499 case PLUGIN_VAR_STR:
3501 opt->check= check_func_str;
3504 opt->update= update_func_str;
3505 if (!(opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)))
3507 opt->flags|= PLUGIN_VAR_READONLY;
3508 sql_print_warning(
"Server variable %s of plugin %s was forced "
3509 "to be read-only: string variable without "
3510 "update_func and PLUGIN_VAR_MEMALLOC flag",
3511 opt->name, plugin_name);
3515 case PLUGIN_VAR_ENUM:
3517 opt->check= check_func_enum;
3519 opt->update= update_func_long;
3521 case PLUGIN_VAR_SET:
3523 opt->check= check_func_set;
3525 opt->update= update_func_longlong;
3527 case PLUGIN_VAR_DOUBLE:
3529 opt->check= check_func_double;
3531 opt->update= update_func_double;
3534 sql_print_error(
"Unknown variable type code 0x%x in plugin '%s'.",
3535 opt->flags, plugin_name);
3539 if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
3540 == PLUGIN_VAR_NOCMDOPT)
3545 sql_print_error(
"Missing variable name in plugin '%s'.",
3550 if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
3552 optnamelen= strlen(opt->name);
3553 optname= (
char*) alloc_root(mem_root, plugin_name_len + optnamelen + 2);
3554 strxmov(optname, plugin_name_ptr,
"-", opt->name, NullS);
3555 optnamelen= plugin_name_len + optnamelen + 1;
3560 if (!(v= find_bookmark(plugin_name_ptr, opt->name, opt->flags)))
3562 sql_print_error(
"Thread local variable '%s' not allocated "
3563 "in plugin '%s'.", opt->name, plugin_name);
3567 *(
int*)(opt + 1)= offset= v->offset;
3569 if (opt->flags & PLUGIN_VAR_NOCMDOPT)
3572 optname= (
char*) memdup_root(mem_root, v->key + 1,
3573 (optnamelen= v->name_len) + 1);
3576 convert_underscore_to_dash(optname, optnamelen);
3578 options->
name= optname;
3579 options->
comment= opt->comment;
3583 plugin_opt_set_limits(options, opt);
3585 if (opt->flags & PLUGIN_VAR_THDLOCAL)
3587 (global_system_variables.dynamic_variables_ptr + offset);
3591 char *option_name_ptr;
3592 options[1]= options[0];
3594 options[1].
name= option_name_ptr= (
char*) alloc_root(mem_root,
3595 plugin_dash.length +
3598 strxmov(option_name_ptr, plugin_dash.str, optname, NullS);
3612 uint count= EXTRA_OPTIONS;
3613 DBUG_ENTER(
"construct_help_options");
3615 for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2)
3621 memset(opts, 0,
sizeof(
my_option) * count);
3629 restore_pluginvar_names(p->system_vars);
3631 if (construct_options(mem_root, p, opts))
3653 static my_bool check_if_option_is_deprecated(
int optid,
3655 char *argument __attribute__((unused)))
3659 WARN_DEPRECATED(NULL, opt->
name, (opt->
name + strlen(
"plugin-")));
3686 int *argc,
char **argv)
3689 bool disable_plugin;
3690 enum_plugin_load_option plugin_load_option= tmp->load_option;
3692 MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
3693 &tmp->mem_root : &plugin_mem_root;
3699 sys_var *v __attribute__((unused));
3701 uint len, count= EXTRA_OPTIONS;
3702 DBUG_ENTER(
"test_plugin_options");
3703 DBUG_ASSERT(tmp->plugin && tmp->name.str);
3709 if (!(my_strcasecmp(&my_charset_latin1, tmp->name.str,
"federated") &&
3710 my_strcasecmp(&my_charset_latin1, tmp->name.str,
"ndbcluster")))
3711 plugin_load_option= PLUGIN_OFF;
3713 for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
3716 if (count > EXTRA_OPTIONS || (*argc > 1))
3720 sql_print_error(
"Out of memory for plugin '%s'.", tmp->name.str);
3723 memset(opts, 0,
sizeof(
my_option) * count);
3725 if (construct_options(tmp_root, tmp, opts))
3727 sql_print_error(
"Bad options for plugin '%s'.", tmp->name.str);
3735 if (tmp->load_option != PLUGIN_FORCE &&
3736 tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT)
3739 error= handle_options(argc, &argv, opts, check_if_option_is_deprecated);
3744 sql_print_error(
"Parsing options for plugin '%s' failed.",
3752 if (tmp->load_option != PLUGIN_FORCE &&
3753 tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT)
3754 plugin_load_option= (enum_plugin_load_option) *(ulong*) opts[0].
value;
3757 disable_plugin= (plugin_load_option == PLUGIN_OFF);
3758 tmp->load_option= plugin_load_option;
3766 sql_print_information(
"Plugin '%s' is disabled.",
3769 my_cleanup_options(opts);
3773 if (!my_strcasecmp(&my_charset_latin1, tmp->name.str,
"NDBCLUSTER"))
3775 plugin_name.str=
const_cast<char*
>(
"ndb");
3776 plugin_name.length= 3;
3779 plugin_name= tmp->name;
3782 for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
3785 if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
3787 if ((var= find_bookmark(plugin_name.str, o->name, o->flags)))
3791 len= plugin_name.length + strlen(o->name) + 2;
3792 varname= (
char*) alloc_root(mem_root, len);
3793 strxmov(varname, plugin_name.str,
"-", o->name, NullS);
3794 my_casedn_str(&my_charset_latin1, varname);
3795 convert_dash_to_underscore(varname, len-1);
3802 chain.last->next = NULL;
3803 if (mysql_add_sys_var_chain(chain.first))
3805 sql_print_error(
"Plugin '%s' has conflicting system variables",
3809 tmp->system_vars= chain.first;
3815 my_cleanup_options(opts);
3825 void add_plugin_options(std::vector<my_option> *options,
MEM_ROOT *mem_root)
3833 for (uint idx= 0; idx < plugin_array.elements; idx++)
3835 p= *dynamic_element(&plugin_array, idx,
struct st_plugin_int **);
3837 if (!(opt= construct_help_options(mem_root, p)))
3841 for (;opt->
name; opt++)
3843 options->push_back(*opt);
3857 DBUG_ENTER(
"plugin_find_by_type");
3859 ret= plugin_find_internal(plugin, type);
3860 DBUG_RETURN(ret && ret->state == PLUGIN_IS_READY ? ret : NULL);
3869 int lock_plugin_data()
3871 DBUG_ENTER(
"lock_plugin_data");
3879 int unlock_plugin_data()
3881 DBUG_ENTER(
"unlock_plugin_data");