diff options
Diffstat (limited to 'sql/sql_plugin.cc')
-rw-r--r-- | sql/sql_plugin.cc | 159 |
1 files changed, 74 insertions, 85 deletions
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 6da247ee153..df826e4cdd6 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -138,7 +138,7 @@ struct st_bookmark uint name_len; int offset; uint version; - char key[0]; + char key[1]; }; @@ -187,11 +187,10 @@ public: static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv); static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, const char *list); -static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, - int *argc, char **argv, my_bool default_enabled); -static bool register_builtin(struct st_mysql_plugin *plugin, - struct st_plugin_int *tmp, - struct st_plugin_int **ptr); +static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *, + int *, char **, my_bool); +static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *, + struct st_plugin_int **); static void unlock_variables(THD *thd, struct system_variables *vars); static void cleanup_variables(THD *thd, struct system_variables *vars); static void plugin_opt_set_limits(struct my_option *options, @@ -242,44 +241,20 @@ static const char *item_val_str(struct st_mysql_value *value, } -static int item_val_int(struct st_mysql_value *value, void *buf, int intsize) +static int item_val_int(struct st_mysql_value *value, long long *buf) { Item *item= ((st_item_value_holder*)value)->item; - switch (intsize) { - case 1: - *(char*)buf= item->val_int(); - break; - case 2: - *(short*)buf= item->val_int(); - break; - case 4: - *(int*)buf= item->val_int(); - break; - case 8: - *(longlong*)buf= item->val_int(); - break; - default: - return -1; - } + *buf= item->val_int(); if (item->is_null()) return 1; return 0; } -static int item_val_real(struct st_mysql_value *value, void *buf, int realsize) +static int item_val_real(struct st_mysql_value *value, double *buf) { Item *item= ((st_item_value_holder*)value)->item; - switch (realsize) { - case 8: - *(double*)buf= item->val_real(); - break; - case 4: - *(float*)buf= item->val_real(); - break; - default: - return -1; - } + *buf= item->val_real(); if (item->is_null()) return 1; return 0; @@ -794,8 +769,7 @@ err: } -static void plugin_deinitialize(struct st_plugin_int *plugin, - bool ref_check= TRUE) +static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check) { /* we don't want to hold the LOCK_plugin mutex as it may cause @@ -911,7 +885,7 @@ static void reap_plugins(void) list= reap; while ((plugin= *(--list))) - plugin_deinitialize(plugin); + plugin_deinitialize(plugin, true); pthread_mutex_lock(&LOCK_plugin); @@ -1149,6 +1123,8 @@ int plugin_init(int *argc, char **argv, int flags) my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0; bzero(&tmp, sizeof(tmp)); tmp.plugin= plugin; + tmp.name.str= (char *)plugin->name; + tmp.name.length= strlen(plugin->name); free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); if (test_plugin_options(&tmp_root, &tmp, argc, argv, def_enabled)) @@ -1226,7 +1202,7 @@ int plugin_init(int *argc, char **argv, int flags) while ((plugin_ptr= *(--reap))) { pthread_mutex_unlock(&LOCK_plugin); - plugin_deinitialize(plugin_ptr); + plugin_deinitialize(plugin_ptr, true); pthread_mutex_lock(&LOCK_plugin); plugin_del(plugin_ptr); } @@ -1252,9 +1228,6 @@ static bool register_builtin(struct st_mysql_plugin *plugin, { DBUG_ENTER("register_builtin"); - tmp->plugin= plugin; - tmp->name.str= (char *)plugin->name; - tmp->name.length= strlen(plugin->name); tmp->state= PLUGIN_IS_UNINITIALIZED; tmp->ref_count= 0; tmp->plugin_dl= 0; @@ -1294,6 +1267,8 @@ bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin) bzero(&tmp, sizeof(tmp)); tmp.plugin= plugin; + tmp.name.str= (char *)plugin->name; + tmp.name.length= strlen(plugin->name); pthread_mutex_lock(&LOCK_plugin); rw_wrlock(&LOCK_system_variables_hash); @@ -1451,7 +1426,7 @@ error: void plugin_shutdown(void) { - uint i, count= plugin_array.elements; + uint i, count= plugin_array.elements, free_slots; struct st_plugin_int **plugins, *plugin; struct st_plugin_dl **dl; DBUG_ENTER("plugin_shutdown"); @@ -1472,13 +1447,18 @@ void plugin_shutdown(void) while (reap_needed && (count= plugin_array.elements)) { reap_plugins(); - for (i= 0; i < count; i++) + for (i= free_slots= 0; i < count; i++) { plugin= dynamic_element(&plugin_array, i, struct st_plugin_int *); - if (plugin->state == PLUGIN_IS_READY) - { + switch (plugin->state) { + case PLUGIN_IS_READY: plugin->state= PLUGIN_IS_DELETED; reap_needed= true; + break; + case PLUGIN_IS_FREED: + case PLUGIN_IS_UNINITIALIZED: + free_slots++; + break; } } if (!reap_needed) @@ -1491,8 +1471,8 @@ void plugin_shutdown(void) } } - if (count > 0) - sql_print_warning("Forcing shutdown of %d plugins", count); + if (count > free_slots) + sql_print_warning("Forcing shutdown of %d plugins", count - free_slots); plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1)); @@ -1523,26 +1503,30 @@ void plugin_shutdown(void) plugin_deinitialize(plugins[i], false); } + /* + It's perfectly safe not to lock LOCK_plugin, as there're no + concurrent threads anymore. But some functions called from here + use safe_mutex_assert_owner(), so we lock the mutex to satisfy it + */ + pthread_mutex_lock(&LOCK_plugin); /* We defer checking ref_counts until after all plugins are deinitialized as some may have worker threads holding on to plugin references. */ for (i= 0; i < count; i++) + { if (plugins[i]->ref_count) sql_print_error("Plugin '%s' has ref_count=%d after shutdown.", plugins[i]->name.str, plugins[i]->ref_count); - - for (i= 0; i < count; i++) if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED) plugin_del(plugins[i]); + } /* Now we can deallocate all memory. */ - /* neccessary to avoid safe_mutex_assert_owner() trap */ - pthread_mutex_lock(&LOCK_plugin); cleanup_variables(NULL, &global_system_variables); cleanup_variables(NULL, &max_system_variables); pthread_mutex_unlock(&LOCK_plugin); @@ -1802,7 +1786,7 @@ static int check_func_bool(THD *thd, struct st_mysql_sys_var *var, char buff[STRING_BUFFER_USUAL_SIZE]; const char *strvalue= "NULL", *str; int result, length; - ulonglong tmp; + long long tmp; if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) { @@ -1817,7 +1801,7 @@ static int check_func_bool(THD *thd, struct st_mysql_sys_var *var, } else { - if (value->val_int(value, &tmp, sizeof(tmp)) < 0) + if (value->val_int(value, &tmp) < 0) goto err; if (tmp > 1) { @@ -1838,9 +1822,9 @@ err: static int check_func_int(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { - ulonglong tmp; + long long tmp; struct my_option options; - value->val_int(value, &tmp, sizeof(tmp)); + value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); *(int *)save= (int) getopt_ull_limit_value(tmp, &options); return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && @@ -1851,9 +1835,9 @@ static int check_func_int(THD *thd, struct st_mysql_sys_var *var, static int check_func_long(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { - ulonglong tmp; + long long tmp; struct my_option options; - value->val_int(value, &tmp, sizeof(tmp)); + value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); *(long *)save= (long) getopt_ull_limit_value(tmp, &options); return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && @@ -1864,13 +1848,13 @@ static int check_func_long(THD *thd, struct st_mysql_sys_var *var, static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { - ulonglong tmp; + long long tmp; struct my_option options; - value->val_int(value, &tmp, sizeof(tmp)); + value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); *(ulonglong *)save= getopt_ull_limit_value(tmp, &options); return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && - (*(ulonglong *)save != tmp); + (*(long long *)save != tmp); } static int check_func_str(THD *thd, struct st_mysql_sys_var *var, @@ -1894,7 +1878,7 @@ static int check_func_enum(THD *thd, struct st_mysql_sys_var *var, char buff[STRING_BUFFER_USUAL_SIZE]; const char *strvalue= "NULL", *str; TYPELIB *typelib; - ulonglong tmp; + long long tmp; long result; int length; @@ -1916,7 +1900,7 @@ static int check_func_enum(THD *thd, struct st_mysql_sys_var *var, } else { - if (value->val_int(value, &tmp, sizeof(tmp))) + if (value->val_int(value, &tmp)) goto err; if (tmp >= typelib->count) { @@ -1967,7 +1951,7 @@ static int check_func_set(THD *thd, struct st_mysql_sys_var *var, } else { - if (value->val_int(value, &tmp, sizeof(tmp))) + if (value->val_int(value, (long long *)&tmp)) goto err; if (unlikely((tmp >= (ULL(1) << typelib->count)) && (typelib->count < sizeof(long)*8))) @@ -2156,7 +2140,7 @@ static st_bookmark *register_var(const char *plugin, const char *name, if (!(result= find_bookmark(NULL, varname + 1, flags))) { result= (st_bookmark*) alloc_root(&plugin_mem_root, - sizeof(struct st_bookmark) + length); + sizeof(struct st_bookmark) + length-1); varname[0]= flags & PLUGIN_VAR_TYPEMASK; memcpy(result->key, varname, length); result->name_len= length - 2; @@ -2349,6 +2333,8 @@ static void cleanup_variables(THD *thd, struct system_variables *vars) } rw_unlock(&LOCK_system_variables_hash); + DBUG_ASSERT(vars->table_plugin == NULL); + my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR)); vars->dynamic_variables_ptr= NULL; vars->dynamic_variables_size= 0; @@ -2680,10 +2666,9 @@ static my_bool get_one_option(int optid __attribute__((unused)), } -static int construct_options(MEM_ROOT *mem_root, - struct st_plugin_int *tmp, - my_option *options, - my_bool **enabled, bool can_disable) +static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, + my_option *options, my_bool **enabled, + bool can_disable) { const char *plugin_name= tmp->plugin->name; uint namelen= strlen(plugin_name), optnamelen; @@ -2707,7 +2692,7 @@ static int construct_options(MEM_ROOT *mem_root, if (can_disable) { strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. " - "Disable with --skip-plugin-", name," (will save memory).", NullS); + "Disable with --skip-", name," (will save memory).", NullS); options[0].comment= name + namelen*2 + 10; } @@ -2868,7 +2853,7 @@ static int construct_options(MEM_ROOT *mem_root, options[1]= options[0]; options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8); - options[1].comment= NULL; /* hide this option */ + options[1].comment= 0; // hidden strxmov(p, "plugin-", optname, NullS); options+= 2; @@ -2883,19 +2868,23 @@ static my_option *construct_help_options(MEM_ROOT *mem_root, { st_mysql_sys_var **opt; my_option *opts; - my_bool dummy; + my_bool dummy, can_disable; my_bool *dummy2= &dummy; uint count= EXTRA_OPTIONS; DBUG_ENTER("construct_help_options"); - for (opt= p->plugin->system_vars; opt && *opt; opt++, count++); + for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2); if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count))) DBUG_RETURN(NULL); bzero(opts, sizeof(my_option) * count); - if (construct_options(mem_root, p, opts, &dummy2, FALSE)) + can_disable= + my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") && + my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY"); + + if (construct_options(mem_root, p, opts, &dummy2, can_disable)) DBUG_RETURN(NULL); DBUG_RETURN(opts); @@ -2932,27 +2921,27 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, struct st_bookmark *var; uint len, count= EXTRA_OPTIONS; DBUG_ENTER("test_plugin_options"); - DBUG_ASSERT(tmp->plugin && tmp->plugin->name); + DBUG_ASSERT(tmp->plugin && tmp->name.str); for (opt= tmp->plugin->system_vars; opt && *opt; opt++) count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */ can_disable= - my_strcasecmp(&my_charset_latin1, tmp->plugin->name, "MyISAM") && - my_strcasecmp(&my_charset_latin1, tmp->plugin->name, "MEMORY"); + my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") && + my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY"); if (count > EXTRA_OPTIONS || (*argc > 1)) { if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count))) { - sql_print_error("Out of memory for plugin '%s'.", tmp->plugin->name); + sql_print_error("Out of memory for plugin '%s'.", tmp->name.str); DBUG_RETURN(-1); } bzero(opts, sizeof(my_option) * count); if (construct_options(tmp_root, tmp, opts, &enabled, can_disable)) { - sql_print_error("Bad options for plugin '%s'.", tmp->plugin->name); + sql_print_error("Bad options for plugin '%s'.", tmp->name.str); DBUG_RETURN(-1); } @@ -2962,14 +2951,14 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (error) { sql_print_error("Parsing options for plugin '%s' failed.", - tmp->plugin->name); + tmp->name.str); DBUG_RETURN(error); } } if (!*enabled && !can_disable) { - sql_print_warning("Plugin '%s' cannot be disabled", tmp->plugin->name); + sql_print_warning("Plugin '%s' cannot be disabled", tmp->name.str); *enabled= TRUE; } @@ -2980,13 +2969,13 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR)) continue; - if ((var= find_bookmark(tmp->plugin->name, o->name, o->flags))) + if ((var= find_bookmark(tmp->name.str, o->name, o->flags))) v= new (mem_root) sys_var_pluginvar(var->key + 1, o); else { - len= strlen(tmp->plugin->name) + strlen(o->name) + 2; + len= tmp->name.length + strlen(o->name) + 2; varname= (char*) alloc_root(mem_root, len); - strxmov(varname, tmp->plugin->name, "-", o->name, NullS); + strxmov(varname, tmp->name.str, "-", o->name, NullS); my_casedn_str(&my_charset_latin1, varname); for (p= varname; *p; p++) @@ -3010,7 +2999,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (mysql_add_sys_var_chain(chain.first, NULL)) { sql_print_error("Plugin '%s' has conflicting system variables", - tmp->plugin->name); + tmp->name.str); DBUG_RETURN(1); } tmp->system_vars= chain.first; @@ -3020,7 +3009,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (enabled_saved) sql_print_information("Plugin '%s' disabled by command line option", - tmp->plugin->name); + tmp->name.str); DBUG_RETURN(1); } |