12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
27
#include <boost/program_options.hpp>
29
#include "drizzled/option.h"
30
#include "drizzled/internal/m_string.h"
32
#include "drizzled/plugin.h"
33
#include "drizzled/module/load_list.h"
34
#include "drizzled/module/library.h"
35
#include "drizzled/module/registry.h"
36
#include "drizzled/module/option_context.h"
37
#include "drizzled/sql_parse.h"
38
#include "drizzled/show.h"
39
#include "drizzled/cursor.h"
40
#include "drizzled/set_var.h"
41
#include "drizzled/session.h"
42
#include "drizzled/item/null.h"
43
#include "drizzled/error.h"
44
#include "drizzled/gettext.h"
45
#include "drizzled/errmsg_print.h"
46
#include "drizzled/strfunc.h"
47
#include "drizzled/pthread_globals.h"
48
#include "drizzled/util/tokenize.h"
50
#include <boost/foreach.hpp>
52
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
61
/** These exist just to prevent symbols from being optimized out */
62
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
drizzled::module::Manifest *drizzled_builtins[]=
67
PANDORA_BUILTIN_SYMBOLS_LIST, NULL
69
drizzled::module::Manifest *drizzled_load_builtins[]=
71
PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
78
typedef vector<string> PluginOptions;
79
static PluginOptions opt_plugin_load;
80
static PluginOptions opt_plugin_add;
81
static PluginOptions opt_plugin_remove;
82
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <drizzled/server_includes.h>
17
#include <mysys/my_getopt.h>
18
#include <authentication.h>
19
#include <drizzled/drizzled_error_messages.h>
20
#define REPORT_TO_LOG 1
21
#define REPORT_TO_USER 2
23
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
24
#define plugin_int_to_ref(A) &(A)
26
extern struct st_mysql_plugin *mysqld_builtins[];
28
char *opt_plugin_load= NULL;
29
char *opt_plugin_dir_ptr;
30
char opt_plugin_dir[FN_REFLEN];
32
When you ad a new plugin type, add both a string and make sure that the
33
init and deinit array are correctly updated.
35
const LEX_STRING plugin_type_names[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
37
{ C_STRING_WITH_LEN("DAEMON") },
38
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
39
{ C_STRING_WITH_LEN("INFORMATION SCHEMA") },
40
{ C_STRING_WITH_LEN("UDF") },
41
{ C_STRING_WITH_LEN("UDA") },
42
{ C_STRING_WITH_LEN("AUDIT") },
43
{ C_STRING_WITH_LEN("LOGGER") },
44
{ C_STRING_WITH_LEN("AUTH") }
47
extern int initialize_schema_table(st_plugin_int *plugin);
48
extern int finalize_schema_table(st_plugin_int *plugin);
50
extern int initialize_udf(st_plugin_int *plugin);
51
extern int finalize_udf(st_plugin_int *plugin);
54
The number of elements in both plugin_type_initialize and
55
plugin_type_deinitialize should equal to the number of plugins
58
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
61
ha_initialize_handlerton, /* Storage Engine */
62
initialize_schema_table, /* Information Schema */
63
initialize_udf, /* UDF */
67
authentication_initializer /* Auth */
70
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
73
ha_finalize_handlerton, /* Storage Engine */
74
finalize_schema_table, /* Information Schema */
75
finalize_udf, /* UDF */
79
authentication_finalizer /* Auth */
82
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
85
84
/* Note that 'int version' must be the first field of every plugin
86
85
sub-structure (plugin->info).
89
static bool initialized= false;
88
static bool initialized= 0;
90
static DYNAMIC_ARRAY plugin_dl_array;
91
static DYNAMIC_ARRAY plugin_array;
92
static HASH plugin_hash[DRIZZLE_MAX_PLUGIN_TYPE_NUM];
92
93
static bool reap_needed= false;
94
static int plugin_array_version=0;
95
97
write-lock on LOCK_system_variables_hash is required before modifying
96
98
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
99
static uint32_t global_variables_dynamic_size= 0;
100
static MEM_ROOT plugin_mem_root;
101
static uint global_variables_dynamic_size= 0;
102
static HASH bookmark_hash;
103
106
hidden part of opaque value passed to variable check functions.
104
107
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
109
struct st_item_value_holder : public st_mysql_value
116
stored in bookmark_hash, this structure is never removed from the
117
hash and is used to mark a single offset for a thd local variable
118
even if plugins have been uninstalled and reinstalled, repeatedly.
119
This structure is allocated from plugin_mem_root.
121
The key format is as follows:
122
1 byte - variable type code
123
name_len bytes - variable name
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
136
skeleton of a plugin variable - portion of structure common to all.
138
struct st_mysql_sys_var
140
DRIZZLE_PLUGIN_VAR_HEADER;
145
sys_var class for access to all plugin variables visible to the user
147
class sys_var_pluginvar: public sys_var
150
struct st_plugin_int *plugin;
151
struct st_mysql_sys_var *plugin_var;
153
static void *operator new(size_t size, MEM_ROOT *mem_root)
154
{ return (void*) alloc_root(mem_root, (uint) size); }
155
static void operator delete(void *ptr_arg __attribute__((unused)),
156
size_t size __attribute__((unused)))
157
{ TRASH(ptr_arg, size); }
159
sys_var_pluginvar(const char *name_arg,
160
struct st_mysql_sys_var *plugin_var_arg)
161
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
162
sys_var_pluginvar *cast_pluginvar() { return this; }
163
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
164
bool check_type(enum_var_type type)
165
{ return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
166
bool check_update_type(Item_result type);
167
SHOW_TYPE show_type();
168
uchar* real_value_ptr(THD *thd, enum_var_type type);
169
TYPELIB* plugin_var_typelib(void);
170
uchar* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
171
bool check(THD *thd, set_var *var);
172
bool check_default(enum_var_type type __attribute__((unused)))
173
{ return is_readonly(); }
174
void set_default(THD *thd,
175
enum_var_type type __attribute__((unused)));
176
bool update(THD *thd, set_var *var);
132
static void plugin_prune_list(vector<string> &plugin_list,
133
const vector<string> &plugins_to_remove);
134
static bool plugin_load_list(module::Registry ®istry,
135
memory::Root *tmp_root,
136
const set<string> &plugin_list,
137
po::options_description &long_options,
138
bool builtin= false);
139
static int test_plugin_options(memory::Root *, module::Module *,
140
po::options_description &long_options);
141
static void unlock_variables(Session *session, drizzle_system_variables *vars);
142
static void cleanup_variables(drizzle_system_variables *vars);
181
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
183
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
185
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
186
struct st_plugin_int **);
187
static void unlock_variables(THD *thd, struct system_variables *vars);
188
static void cleanup_variables(THD *thd, struct system_variables *vars);
189
static void plugin_vars_free_values(sys_var *vars);
190
static void plugin_opt_set_limits(struct my_option *options,
191
const struct st_mysql_sys_var *opt);
192
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
193
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
194
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
196
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
197
static void reap_plugins(void);
144
200
/* declared in set_var.cc */
145
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
201
extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
202
extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
203
const char *name, int64_t val);
205
/****************************************************************************
206
Value type thunks, allows the C world to play in the C++ world
207
****************************************************************************/
209
static int item_value_type(struct st_mysql_value *value)
211
switch (((st_item_value_holder*)value)->item->result_type()) {
213
return DRIZZLE_VALUE_TYPE_INT;
215
return DRIZZLE_VALUE_TYPE_REAL;
217
return DRIZZLE_VALUE_TYPE_STRING;
221
static const char *item_val_str(struct st_mysql_value *value,
222
char *buffer, int *length)
224
String str(buffer, *length, system_charset_info), *res;
225
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
227
*length= res->length();
228
if (res->c_ptr_quick() == buffer)
232
Lets be nice and create a temporary string since the
235
return current_thd->strmake(res->c_ptr_quick(), res->length());
239
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
241
Item *item= ((st_item_value_holder*)value)->item;
242
*buf= item->val_int();
249
static int item_val_real(struct st_mysql_value *value, double *buf)
251
Item *item= ((st_item_value_holder*)value)->item;
252
*buf= item->val_real();
148
259
/****************************************************************************
149
260
Plugin support code
150
261
****************************************************************************/
263
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
266
struct st_plugin_dl *tmp;
267
for (i= 0; i < plugin_dl_array.elements; i++)
269
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
270
if (tmp->ref_count &&
271
! my_strnncoll(files_charset_info,
272
(const uchar *)dl->str, dl->length,
273
(const uchar *)tmp->dl.str, tmp->dl.length))
279
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
282
struct st_plugin_dl *tmp;
283
for (i= 0; i < plugin_dl_array.elements; i++)
285
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
286
if (! tmp->ref_count)
288
memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
292
if (insert_dynamic(&plugin_dl_array, (uchar*)&plugin_dl))
294
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
295
struct st_plugin_dl **)=
296
(struct st_plugin_dl *) memdup_root(&plugin_mem_root, (uchar*)plugin_dl,
297
sizeof(struct st_plugin_dl));
301
static inline void free_plugin_mem(struct st_plugin_dl *p)
305
my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR));
309
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
311
char dlpath[FN_REFLEN];
312
uint plugin_dir_len, dummy_errors, dlpathlen;
313
struct st_plugin_dl *tmp, plugin_dl;
315
plugin_dir_len= strlen(opt_plugin_dir);
317
Ensure that the dll doesn't have a path.
318
This is done to ensure that only approved libraries from the
319
plugin directory are used (to make this even remotely secure).
321
if (strchr(dl->str, FN_LIBCHAR) ||
322
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
323
system_charset_info, 1) ||
324
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
326
if (report & REPORT_TO_USER)
327
my_error(ER_UDF_NO_PATHS, MYF(0));
328
if (report & REPORT_TO_LOG)
329
sql_print_error(ER(ER_UDF_NO_PATHS));
332
/* If this dll is already loaded just increase ref_count. */
333
if ((tmp= plugin_dl_find(dl)))
338
memset(&plugin_dl, 0, sizeof(plugin_dl));
339
/* Compile dll path */
341
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS) -
343
plugin_dl.ref_count= 1;
344
/* Open new dll handle */
345
if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
347
const char *errmsg=dlerror();
348
if (!strncmp(dlpath, errmsg, dlpathlen))
349
{ // if errmsg starts from dlpath, trim this prefix.
351
if (*errmsg == ':') errmsg++;
352
if (*errmsg == ' ') errmsg++;
354
if (report & REPORT_TO_USER)
355
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
356
if (report & REPORT_TO_LOG)
357
sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
361
/* Find plugin declarations */
362
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
364
free_plugin_mem(&plugin_dl);
365
if (report & REPORT_TO_USER)
366
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
367
if (report & REPORT_TO_LOG)
368
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
372
plugin_dl.plugins= (struct st_mysql_plugin *)sym;
374
/* Duplicate and convert dll name */
375
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
376
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
378
free_plugin_mem(&plugin_dl);
379
if (report & REPORT_TO_USER)
380
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
381
if (report & REPORT_TO_LOG)
382
sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
385
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
386
files_charset_info, dl->str, dl->length, system_charset_info,
388
plugin_dl.dl.str[plugin_dl.dl.length]= 0;
389
/* Add this dll to array */
390
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
392
free_plugin_mem(&plugin_dl);
393
if (report & REPORT_TO_USER)
394
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
395
if (report & REPORT_TO_LOG)
396
sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
403
static void plugin_dl_del(const LEX_STRING *dl)
407
for (i= 0; i < plugin_dl_array.elements; i++)
409
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
410
struct st_plugin_dl **);
411
if (tmp->ref_count &&
412
! my_strnncoll(files_charset_info,
413
(const uchar *)dl->str, dl->length,
414
(const uchar *)tmp->dl.str, tmp->dl.length))
416
/* Do not remove this element, unless no other plugin uses this dll. */
417
if (! --tmp->ref_count)
419
free_plugin_mem(tmp);
420
memset(tmp, 0, sizeof(struct st_plugin_dl));
429
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
435
if (type == DRIZZLE_ANY_PLUGIN)
437
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
439
struct st_plugin_int *plugin= (st_plugin_int *)
440
hash_search(&plugin_hash[i], (const uchar *)name->str, name->length);
446
return((st_plugin_int *)
447
hash_search(&plugin_hash[type], (const uchar *)name->str, name->length));
452
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
454
SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
455
struct st_plugin_int *plugin;
456
if ((plugin= plugin_find_internal(name, type)))
458
rc= SHOW_OPTION_DISABLED;
459
if (plugin->state == PLUGIN_IS_READY)
466
bool plugin_is_ready(const LEX_STRING *name, int type)
469
if (plugin_status(name, type) == SHOW_OPTION_YES)
475
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
477
LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
478
return plugin_status(&plugin_name, plugin_type);
482
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
484
st_plugin_int *pi= plugin_ref_to_int(rc);
486
if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
490
For debugging, we do an additional malloc which allows the
491
memory manager and/or valgrind to track locked references and
492
double unlocks to aid resolving reference counting.problems.
494
if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
501
insert_dynamic(&lex->plugins, (uchar*)&plugin);
508
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
510
LEX *lex= thd ? thd->lex : 0;
512
rc= my_intern_plugin_lock_ci(lex, *ptr);
517
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
520
LEX *lex= thd ? thd->lex : 0;
522
st_plugin_int *plugin;
523
if ((plugin= plugin_find_internal(name, type)))
524
rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
529
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
532
struct st_plugin_int *tmp;
533
for (i= 0; i < plugin_array.elements; i++)
535
tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
536
if (tmp->state == PLUGIN_IS_FREED)
538
memcpy(tmp, plugin, sizeof(struct st_plugin_int));
542
if (insert_dynamic(&plugin_array, (uchar*)&plugin))
544
tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
545
struct st_plugin_int **)=
546
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)plugin,
547
sizeof(struct st_plugin_int));
157
554
Requires that a write-lock is held on LOCK_system_variables_hash
159
static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
160
module::Library *library,
161
po::options_description &long_options)
556
static bool plugin_add(MEM_ROOT *tmp_root,
557
const LEX_STRING *name, const LEX_STRING *dl,
558
int *argc, char **argv, int report)
166
if (registry.find(library->getName()))
560
struct st_plugin_int tmp;
561
struct st_mysql_plugin *plugin;
562
if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
168
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
169
library->getName().c_str());
564
if (report & REPORT_TO_USER)
565
my_error(ER_UDF_EXISTS, MYF(0), name->str);
566
if (report & REPORT_TO_LOG)
567
sql_print_error(ER(ER_UDF_EXISTS), name->str);
173
module::Module *tmp= NULL;
570
/* Clear the whole struct to catch future extensions. */
571
memset(&tmp, 0, sizeof(tmp));
572
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
174
574
/* Find plugin by name */
175
const module::Manifest *manifest= library->getManifest();
177
if (registry.find(manifest->name))
179
errmsg_printf(ERRMSG_LVL_ERROR,
180
_("Plugin '%s' contains the name '%s' in its manifest, which "
181
"has already been registered.\n"),
182
library->getName().c_str(),
187
tmp= new (std::nothrow) module::Module(manifest, library);
191
if (!test_plugin_options(tmp_root, tmp, long_options))
196
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY),
197
library->getName().c_str());
202
static void reap_plugins(module::Registry ®istry)
204
std::map<std::string, module::Module *>::const_iterator modules=
205
registry.getModulesMap().begin();
207
while (modules != registry.getModulesMap().end())
209
module::Module *module= (*modules).second;
216
static bool plugin_initialize(module::Registry ®istry,
217
module::Module *module)
219
assert(module->isInited == false);
221
module::Context loading_context(registry, module);
222
if (module->getManifest().init)
224
if (module->getManifest().init(loading_context))
226
errmsg_printf(ERRMSG_LVL_ERROR,
227
_("Plugin '%s' init function returned error.\n"),
228
module->getName().c_str());
232
module->isInited= true;
239
inline static void dashes_to_underscores(std::string &name_in,
240
char from= '-', char to= '_')
242
for (string::iterator p= name_in.begin();
253
inline static void underscores_to_dashes(std::string &name_in)
255
return dashes_to_underscores(name_in, '_', '-');
258
static void compose_plugin_options(vector<string> &target,
259
vector<string> options)
261
for (vector<string>::iterator it= options.begin();
265
tokenize(*it, target, ",", true);
267
for (vector<string>::iterator it= target.begin();
271
dashes_to_underscores(*it);
275
void compose_plugin_add(vector<string> options)
277
compose_plugin_options(opt_plugin_add, options);
280
void compose_plugin_remove(vector<string> options)
282
compose_plugin_options(opt_plugin_remove, options);
285
void notify_plugin_load(string in_plugin_load)
287
tokenize(in_plugin_load, opt_plugin_load, ",", true);
575
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
577
uint name_len= strlen(plugin->name);
578
if (plugin->type >= 0 && plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
579
! my_strnncoll(system_charset_info,
580
(const uchar *)name->str, name->length,
581
(const uchar *)plugin->name,
584
struct st_plugin_int *tmp_plugin_ptr;
587
tmp.name.str= (char *)plugin->name;
588
tmp.name.length= name_len;
590
tmp.state= PLUGIN_IS_UNINITIALIZED;
591
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
593
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
595
plugin_array_version++;
596
if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
598
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
601
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
603
mysql_del_sys_var_chain(tmp.system_vars);
606
/* plugin was disabled */
611
if (report & REPORT_TO_USER)
612
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
613
if (report & REPORT_TO_LOG)
614
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
621
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
623
if (plugin->plugin->status_vars)
627
We have a problem right now where we can not prepend without
628
breaking backwards compatibility. We will fix this shortly so
629
that engines have "use names" and we wil use those for
630
CREATE TABLE, and use the plugin name then for adding automatic
634
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
637
remove_status_vars(array);
639
remove_status_vars(plugin->plugin->status_vars);
640
#endif /* FIX_LATER */
643
if (plugin_type_deinitialize[plugin->plugin->type])
645
if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
647
sql_print_error(_("Plugin '%s' of type %s failed deinitialization"),
648
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
651
else if (plugin->plugin->deinit)
652
plugin->plugin->deinit(plugin);
654
plugin->state= PLUGIN_IS_UNINITIALIZED;
657
We do the check here because NDB has a worker THD which doesn't
658
exit until NDB is shut down.
660
if (ref_check && plugin->ref_count)
661
sql_print_error(_("Plugin '%s' has ref_count=%d after deinitialization."),
662
plugin->name.str, plugin->ref_count);
666
static void plugin_del(struct st_plugin_int *plugin)
668
/* Free allocated strings before deleting the plugin. */
669
plugin_vars_free_values(plugin->system_vars);
670
hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
671
if (plugin->plugin_dl)
672
plugin_dl_del(&plugin->plugin_dl->dl);
673
plugin->state= PLUGIN_IS_FREED;
674
plugin_array_version++;
675
rw_wrlock(&LOCK_system_variables_hash);
676
mysql_del_sys_var_chain(plugin->system_vars);
677
rw_unlock(&LOCK_system_variables_hash);
678
free_root(&plugin->mem_root, MYF(0));
682
static void reap_plugins(void)
685
struct st_plugin_int *plugin, **reap, **list;
691
count= plugin_array.elements;
692
reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
695
for (idx= 0; idx < count; idx++)
697
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
698
if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
700
/* change the status flag to prevent reaping by another thread */
701
plugin->state= PLUGIN_IS_DYING;
707
while ((plugin= *(--list)))
708
plugin_deinitialize(plugin, true);
710
while ((plugin= *(--reap)))
716
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
724
pi= plugin_ref_to_int(plugin);
726
my_free((uchar*) plugin, MYF(MY_WME));
731
Remove one instance of this plugin from the use list.
732
We are searching backwards so that plugins locked last
733
could be unlocked faster - optimizing for LIFO semantics.
735
for (i= lex->plugins.elements - 1; i >= 0; i--)
736
if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
738
delete_dynamic_element(&lex->plugins, i);
744
assert(pi->ref_count);
747
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
754
void plugin_unlock(THD *thd, plugin_ref plugin)
756
LEX *lex= thd ? thd->lex : 0;
759
intern_plugin_unlock(lex, plugin);
764
void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
766
LEX *lex= thd ? thd->lex : 0;
769
intern_plugin_unlock(lex, *list++);
774
static int plugin_initialize(struct st_plugin_int *plugin)
777
if (plugin_type_initialize[plugin->plugin->type])
779
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
781
sql_print_error(_("Plugin '%s' registration as a %s failed."),
782
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
786
else if (plugin->plugin->init)
788
if (plugin->plugin->init(plugin))
790
sql_print_error(_("Plugin '%s' init function returned error."),
796
plugin->state= PLUGIN_IS_READY;
798
if (plugin->plugin->status_vars)
802
We have a problem right now where we can not prepend without
803
breaking backwards compatibility. We will fix this shortly so
804
that engines have "use names" and we wil use those for
805
CREATE TABLE, and use the plugin name then for adding automatic
809
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
812
if (add_status_vars(array)) // add_status_vars makes a copy
815
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
816
#endif /* FIX_LATER */
820
set the plugin attribute of plugin's sys vars so they are pointing
823
if (plugin->system_vars)
825
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
831
var= var->next->cast_pluginvar();
841
extern "C" uchar *get_plugin_hash_key(const uchar *, size_t *, bool);
842
extern "C" uchar *get_bookmark_hash_key(const uchar *, size_t *, bool);
845
uchar *get_plugin_hash_key(const uchar *buff, size_t *length,
846
bool not_used __attribute__((unused)))
848
struct st_plugin_int *plugin= (st_plugin_int *)buff;
849
*length= (uint)plugin->name.length;
850
return((uchar *)plugin->name.str);
854
uchar *get_bookmark_hash_key(const uchar *buff, size_t *length,
855
bool not_used __attribute__((unused)))
857
struct st_bookmark *var= (st_bookmark *)buff;
858
*length= var->name_len + 1;
859
return (uchar*) var->key;
291
864
The logic is that we first load and initialize all compiled in plugins.
295
868
Finally we initialize everything, aka the dynamic that have yet to initialize.
297
bool plugin_init(module::Registry ®istry,
298
po::options_description &long_options)
870
int plugin_init(int *argc, char **argv, int flags)
300
memory::Root tmp_root(4096);
873
struct st_mysql_plugin **builtins;
874
struct st_mysql_plugin *plugin;
875
struct st_plugin_int tmp, *plugin_ptr, **reap;
881
init_alloc_root(&plugin_mem_root, 4096, 4096);
882
init_alloc_root(&tmp_root, 4096, 4096);
884
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
885
get_bookmark_hash_key, NULL, HASH_UNIQUE))
889
if (my_init_dynamic_array(&plugin_dl_array,
890
sizeof(struct st_plugin_dl *),16,16) ||
891
my_init_dynamic_array(&plugin_array,
892
sizeof(struct st_plugin_int *),16,16))
895
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
897
if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
898
get_plugin_hash_key, NULL, HASH_UNIQUE))
307
PluginOptions builtin_load_list;
308
tokenize(builtin_load_plugins, builtin_load_list, ",", true);
310
PluginOptions builtin_list;
311
tokenize(builtin_plugins, builtin_list, ",", true);
313
bool load_failed= false;
315
if (opt_plugin_add.size() > 0)
317
for (PluginOptions::iterator iter= opt_plugin_add.begin();
318
iter != opt_plugin_add.end();
321
if (find(builtin_list.begin(),
322
builtin_list.end(), *iter) != builtin_list.end())
324
builtin_load_list.push_back(*iter);
328
opt_plugin_load.push_back(*iter);
333
if (opt_plugin_remove.size() > 0)
335
plugin_prune_list(opt_plugin_load, opt_plugin_remove);
336
plugin_prune_list(builtin_load_list, opt_plugin_remove);
341
905
First we register builtin plugins
343
const set<string> builtin_list_set(builtin_load_list.begin(),
344
builtin_load_list.end());
345
load_failed= plugin_load_list(registry, &tmp_root,
346
builtin_list_set, long_options, true);
907
for (builtins= mysqld_builtins; *builtins; builtins++)
349
tmp_root.free_root(MYF(0));
909
for (plugin= *builtins; plugin->name; plugin++)
911
memset(&tmp, 0, sizeof(tmp));
913
tmp.name.str= (char *)plugin->name;
914
tmp.name.length= strlen(plugin->name);
916
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
917
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
920
if (register_builtin(plugin, &tmp, &plugin_ptr))
923
if (plugin_initialize(plugin_ptr))
927
initialize the global default storage engine so that it may
928
not be null in any child thread.
930
if (my_strcasecmp(&my_charset_utf8_general_ci, plugin->name, "MyISAM") == 0)
932
assert(!global_system_variables.table_plugin);
933
global_system_variables.table_plugin=
934
my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
935
assert(plugin_ptr->ref_count == 1);
353
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
940
/* should now be set to MyISAM storage engine */
941
assert(global_system_variables.table_plugin);
357
943
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
944
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
362
tmp_root.free_root(MYF(0));
947
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
950
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
374
954
Now we initialize all remaining plugins
376
std::map<std::string, module::Module *>::const_iterator modules=
377
registry.getModulesMap().begin();
379
while (modules != registry.getModulesMap().end())
957
reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
960
for (i= 0; i < plugin_array.elements; i++)
381
module::Module *module= (*modules).second;
383
if (module->isInited == false)
962
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
963
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
385
if (plugin_initialize(registry, module))
965
if (plugin_initialize(plugin_ptr))
387
registry.remove(module);
967
plugin_ptr->state= PLUGIN_IS_DYING;
968
*(reap++)= plugin_ptr;
394
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
396
value.second->prime();
403
public unary_function<string, bool>
405
const string to_match;
407
PrunePlugin& operator=(const PrunePlugin&);
409
explicit PrunePlugin(const string &match_in) :
413
result_type operator()(const string &match_against)
415
return match_against == to_match;
419
static void plugin_prune_list(vector<string> &plugin_list,
420
const vector<string> &plugins_to_remove)
422
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
423
iter != plugins_to_remove.end();
426
plugin_list.erase(remove_if(plugin_list.begin(),
974
Check if any plugins have to be reaped
976
while ((plugin_ptr= *(--reap)))
978
plugin_deinitialize(plugin_ptr, true);
979
plugin_del(plugin_ptr);
985
free_root(&tmp_root, MYF(0));
991
free_root(&tmp_root, MYF(0));
996
static bool register_builtin(struct st_mysql_plugin *plugin,
997
struct st_plugin_int *tmp,
998
struct st_plugin_int **ptr)
1001
tmp->state= PLUGIN_IS_UNINITIALIZED;
1005
if (insert_dynamic(&plugin_array, (uchar*)&tmp))
1008
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1009
struct st_plugin_int **)=
1010
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)tmp,
1011
sizeof(struct st_plugin_int));
1013
if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr))
434
1021
called only by plugin_init()
436
static bool plugin_load_list(module::Registry ®istry,
437
memory::Root *tmp_root,
438
const set<string> &plugin_list,
439
po::options_description &long_options,
1023
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
442
module::Library *library= NULL;
444
for (set<string>::const_iterator iter= plugin_list.begin();
445
iter != plugin_list.end();
1026
char buffer[FN_REFLEN];
1027
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
1028
struct st_plugin_dl *plugin_dl;
1029
struct st_mysql_plugin *plugin;
448
const string plugin_name(*iter);
450
library= registry.addLibrary(plugin_name, builtin);
1033
if (p == buffer + sizeof(buffer) - 1)
453
errmsg_printf(ERRMSG_LVL_ERROR,
454
_("Couldn't load plugin library named '%s'.\n"),
455
plugin_name.c_str());
1035
sql_print_error(_("plugin-load parameter too long"));
459
tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
460
if (plugin_add(registry, tmp_root, library, long_options))
462
registry.removeLibrary(plugin_name);
463
errmsg_printf(ERRMSG_LVL_ERROR,
464
_("Couldn't load plugin named '%s'.\n"),
465
plugin_name.c_str());
1039
switch ((*(p++)= *(list++))) {
1041
list= NULL; /* terminate the loop */
1043
case ':': /* can't use this as delimiter as it may be drive letter */
1045
str->str[str->length]= '\0';
1046
if (str == &name) // load all plugins in named module
1050
p--; /* reset pointer */
1055
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1057
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
1059
name.str= (char *) plugin->name;
1060
name.length= strlen(name.str);
1062
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1063
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1066
plugin_dl_del(&dl); // reduce ref count
1071
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1072
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1075
name.length= dl.length= 0;
1076
dl.str= NULL; name.str= p= buffer;
1083
name.str[name.length]= '\0';
1095
sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
474
void module_shutdown(module::Registry ®istry)
1101
void plugin_shutdown(void)
1103
uint i, count= plugin_array.elements, free_slots= 0;
1104
struct st_plugin_int **plugins, *plugin;
1105
struct st_plugin_dl **dl;
477
1107
if (initialized)
479
1109
reap_needed= true;
481
reap_plugins(registry);
482
unlock_variables(NULL, &global_system_variables);
483
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
1112
We want to shut down plugins in a reasonable order, this will
1113
become important when we have plugins which depend upon each other.
1114
Circular references cannot be reaped so they are forced afterwards.
1115
TODO: Have an additional step here to notify all active plugins that
1116
shutdown is requested to allow plugins to deinitialize in parallel.
1118
while (reap_needed && (count= plugin_array.elements))
1121
for (i= free_slots= 0; i < count; i++)
1123
plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1124
switch (plugin->state) {
1125
case PLUGIN_IS_READY:
1126
plugin->state= PLUGIN_IS_DELETED;
1129
case PLUGIN_IS_FREED:
1130
case PLUGIN_IS_UNINITIALIZED:
1138
release any plugin references held.
1140
unlock_variables(NULL, &global_system_variables);
1141
unlock_variables(NULL, &max_system_variables);
1145
if (count > free_slots)
1146
sql_print_warning(_("Forcing shutdown of %d plugins"),
1147
count - free_slots);
1149
plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1152
If we have any plugins which did not die cleanly, we force shutdown
1154
for (i= 0; i < count; i++)
1156
plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1157
/* change the state to ensure no reaping races */
1158
if (plugins[i]->state == PLUGIN_IS_DELETED)
1159
plugins[i]->state= PLUGIN_IS_DYING;
1163
We loop through all plugins and call deinit() if they have one.
1165
for (i= 0; i < count; i++)
1166
if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1168
sql_print_information(_("Plugin '%s' will be forced to shutdown"),
1169
plugins[i]->name.str);
1171
We are forcing deinit on plugins so we don't want to do a ref_count
1172
check until we have processed all the plugins.
1174
plugin_deinitialize(plugins[i], false);
1178
We defer checking ref_counts until after all plugins are deinitialized
1179
as some may have worker threads holding on to plugin references.
1181
for (i= 0; i < count; i++)
1183
if (plugins[i]->ref_count)
1184
sql_print_error(_("Plugin '%s' has ref_count=%d after shutdown."),
1185
plugins[i]->name.str, plugins[i]->ref_count);
1186
if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1187
plugin_del(plugins[i]);
1191
Now we can deallocate all memory.
1194
cleanup_variables(NULL, &global_system_variables);
1195
cleanup_variables(NULL, &max_system_variables);
491
1202
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
1204
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1205
hash_free(&plugin_hash[i]);
1206
delete_dynamic(&plugin_array);
1208
count= plugin_dl_array.elements;
1209
dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1210
for (i= 0; i < count; i++)
1211
dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1212
for (i= 0; i < plugin_dl_array.elements; i++)
1213
free_plugin_mem(dl[i]);
1215
delete_dynamic(&plugin_dl_array);
1217
hash_free(&bookmark_hash);
1218
free_root(&plugin_mem_root, MYF(0));
494
1220
global_variables_dynamic_size= 0;
1226
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1227
int type, uint state_mask, void *arg)
1230
struct st_plugin_int *plugin, **plugins;
1231
int version=plugin_array_version;
1236
state_mask= ~state_mask; // do it only once
1238
total= type == DRIZZLE_ANY_PLUGIN ? plugin_array.elements
1239
: plugin_hash[type].records;
1241
Do the alloca out here in case we do have a working alloca:
1242
leaving the nested stack frame invalidates alloca allocation.
1244
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1245
if (type == DRIZZLE_ANY_PLUGIN)
1247
for (idx= 0; idx < total; idx++)
1249
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1250
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1255
HASH *hash= plugin_hash + type;
1256
for (idx= 0; idx < total; idx++)
1258
plugin= (struct st_plugin_int *) hash_element(hash, idx);
1259
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1262
for (idx= 0; idx < total; idx++)
1264
if (unlikely(version != plugin_array_version))
1266
for (uint i=idx; i < total; i++)
1267
if (plugins[i] && plugins[i]->state & state_mask)
1270
plugin= plugins[idx];
1271
/* It will stop iterating on first engine error when "func" returns true */
1272
if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
1284
/****************************************************************************
1285
Internal type declarations for variables support
1286
****************************************************************************/
1288
#undef DRIZZLE_SYSVAR_NAME
1289
#define DRIZZLE_SYSVAR_NAME(name) name
1290
#define PLUGIN_VAR_TYPEMASK 0x007f
1292
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1294
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1295
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_bool_t, bool);
1296
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1297
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_str_t, char *);
1299
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1300
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
1301
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1302
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
1304
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1305
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1306
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1307
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1308
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1309
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1311
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int_t, int);
1312
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_long_t, long);
1313
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int64_t_t, int64_t);
1314
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint_t, uint);
1315
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
1316
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint64_t_t, uint64_t);
1318
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
1321
/****************************************************************************
1322
default variable data check and update functions
1323
****************************************************************************/
1325
static int check_func_bool(THD *thd __attribute__((unused)),
1326
struct st_mysql_sys_var *var,
1327
void *save, st_mysql_value *value)
1329
char buff[STRING_BUFFER_USUAL_SIZE];
1330
const char *strvalue= "NULL", *str;
1334
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1336
length= sizeof(buff);
1337
if (!(str= value->val_str(value, buff, &length)) ||
1338
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
1347
if (value->val_int(value, &tmp) < 0)
1357
*(int*)save= -result;
1360
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1365
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
1366
void *save, st_mysql_value *value)
1370
struct my_option options;
1371
value->val_int(value, &tmp);
1372
plugin_opt_set_limits(&options, var);
1374
if (var->flags & PLUGIN_VAR_UNSIGNED)
1375
*(uint *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
1378
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1380
return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1381
var->name, (int64_t) tmp);
1385
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
1386
void *save, st_mysql_value *value)
1390
struct my_option options;
1391
value->val_int(value, &tmp);
1392
plugin_opt_set_limits(&options, var);
1394
if (var->flags & PLUGIN_VAR_UNSIGNED)
1395
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
1398
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1400
return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1401
var->name, (int64_t) tmp);
1405
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
1406
void *save, st_mysql_value *value)
1410
struct my_option options;
1411
value->val_int(value, &tmp);
1412
plugin_opt_set_limits(&options, var);
1414
if (var->flags & PLUGIN_VAR_UNSIGNED)
1415
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
1418
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1420
return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1421
var->name, (int64_t) tmp);
1424
static int check_func_str(THD *thd,
1425
struct st_mysql_sys_var *var __attribute__((unused)),
1426
void *save, st_mysql_value *value)
1428
char buff[STRING_BUFFER_USUAL_SIZE];
1432
length= sizeof(buff);
1433
if ((str= value->val_str(value, buff, &length)))
1434
str= thd->strmake(str, length);
1435
*(const char**)save= str;
1440
static int check_func_enum(THD *thd __attribute__((unused)),
1441
struct st_mysql_sys_var *var,
1442
void *save, st_mysql_value *value)
1444
char buff[STRING_BUFFER_USUAL_SIZE];
1445
const char *strvalue= "NULL", *str;
1451
if (var->flags & PLUGIN_VAR_THDLOCAL)
1452
typelib= ((thdvar_enum_t*) var)->typelib;
1454
typelib= ((sysvar_enum_t*) var)->typelib;
1456
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1458
length= sizeof(buff);
1459
if (!(str= value->val_str(value, buff, &length)))
1461
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1469
if (value->val_int(value, &tmp))
1471
if (tmp >= typelib->count)
1479
*(long*)save= result;
1482
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1487
static int check_func_set(THD *thd __attribute__((unused)),
1488
struct st_mysql_sys_var *var,
1489
void *save, st_mysql_value *value)
1491
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1492
const char *strvalue= "NULL", *str;
1499
if (var->flags & PLUGIN_VAR_THDLOCAL)
1500
typelib= ((thdvar_set_t*) var)->typelib;
1502
typelib= ((sysvar_set_t*)var)->typelib;
1504
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1506
length= sizeof(buff);
1507
if (!(str= value->val_str(value, buff, &length)))
1509
result= find_set(typelib, str, length, NULL,
1510
&error, &error_len, ¬_used);
1513
strmake(buff, error, min(sizeof(buff), (unsigned long)error_len));
1520
if (value->val_int(value, (int64_t *)&result))
1522
if (unlikely((result >= (1ULL << typelib->count)) &&
1523
(typelib->count < sizeof(long)*8)))
1525
llstr(result, buff);
1530
*(uint64_t*)save= result;
1533
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1538
static void update_func_bool(THD *thd __attribute__((unused)),
1539
struct st_mysql_sys_var *var __attribute__((unused)),
1540
void *tgt, const void *save)
1542
*(bool *) tgt= *(int *) save ? 1 : 0;
1546
static void update_func_int(THD *thd __attribute__((unused)),
1547
struct st_mysql_sys_var *var __attribute__((unused)),
1548
void *tgt, const void *save)
1550
*(int *)tgt= *(int *) save;
1554
static void update_func_long(THD *thd __attribute__((unused)),
1555
struct st_mysql_sys_var *var __attribute__((unused)),
1556
void *tgt, const void *save)
1558
*(long *)tgt= *(long *) save;
1562
static void update_func_int64_t(THD *thd __attribute__((unused)),
1563
struct st_mysql_sys_var *var __attribute__((unused)),
1564
void *tgt, const void *save)
1566
*(int64_t *)tgt= *(uint64_t *) save;
1570
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
1571
void *tgt, const void *save)
1573
char *old= *(char **) tgt;
1574
*(char **)tgt= *(char **) save;
1575
if (var->flags & PLUGIN_VAR_MEMALLOC)
1577
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
1578
my_free(old, MYF(0));
500
1585
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
509
void plugin_sessionvar_init(Session *session)
511
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
514
session->variables= global_system_variables;
515
session->variables.storage_engine= NULL;
1588
sys_var *find_sys_var(THD *thd, const char *str, uint length)
1591
sys_var_pluginvar *pi= NULL;
1594
rw_rdlock(&LOCK_system_variables_hash);
1595
if ((var= intern_find_sys_var(str, length, false)) &&
1596
(pi= var->cast_pluginvar()))
1598
rw_unlock(&LOCK_system_variables_hash);
1599
LEX *lex= thd ? thd->lex : 0;
1600
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1601
var= NULL; /* failed to lock it, it must be uninstalling */
1603
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
1605
/* initialization not completed */
1607
intern_plugin_unlock(lex, plugin);
1611
rw_unlock(&LOCK_system_variables_hash);
1614
If the variable exists but the plugin it is associated with is not ready
1615
then the intern_plugin_lock did not raise an error, so we do it here.
1618
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1624
called by register_var, construct_options and test_plugin_options.
1625
Returns the 'bookmark' for the named variable.
1626
LOCK_system_variables_hash should be at least read locked
1628
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1630
st_bookmark *result= NULL;
1631
uint namelen, length, pluginlen= 0;
1634
if (!(flags & PLUGIN_VAR_THDLOCAL))
1637
namelen= strlen(name);
1639
pluginlen= strlen(plugin) + 1;
1640
length= namelen + pluginlen + 2;
1641
varname= (char*) my_alloca(length);
1645
strxmov(varname + 1, plugin, "_", name, NullS);
1646
for (p= varname + 1; *p; p++)
1651
memcpy(varname + 1, name, namelen + 1);
1653
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1655
result= (st_bookmark*) hash_search(&bookmark_hash,
1656
(const uchar*) varname, length - 1);
1664
returns a bookmark for thd-local variables, creating if neccessary.
1665
returns null for non thd-local variables.
1666
Requires that a write lock is obtained on LOCK_system_variables_hash
1668
static st_bookmark *register_var(const char *plugin, const char *name,
1671
uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1672
st_bookmark *result;
1675
if (!(flags & PLUGIN_VAR_THDLOCAL))
1678
switch (flags & PLUGIN_VAR_TYPEMASK) {
1679
case PLUGIN_VAR_BOOL:
1682
case PLUGIN_VAR_INT:
1685
case PLUGIN_VAR_LONG:
1686
case PLUGIN_VAR_ENUM:
1689
case PLUGIN_VAR_LONGLONG:
1690
case PLUGIN_VAR_SET:
1691
size= sizeof(uint64_t);
1693
case PLUGIN_VAR_STR:
1694
size= sizeof(char*);
1701
varname= ((char*) my_alloca(length));
1702
strxmov(varname + 1, plugin, "_", name, NullS);
1703
for (p= varname + 1; *p; p++)
1707
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1709
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1710
sizeof(struct st_bookmark) + length-1);
1711
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1712
memcpy(result->key, varname, length);
1713
result->name_len= length - 2;
1716
assert(size && !(size & (size-1))); /* must be power of 2 */
1718
offset= global_system_variables.dynamic_variables_size;
1719
offset= (offset + size - 1) & ~(size - 1);
1720
result->offset= (int) offset;
1722
new_size= (offset + size + 63) & ~63;
1724
if (new_size > global_variables_dynamic_size)
1726
global_system_variables.dynamic_variables_ptr= (char*)
1727
my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1728
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1729
max_system_variables.dynamic_variables_ptr= (char*)
1730
my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1731
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1733
Clear the new variable value space. This is required for string
1734
variables. If their value is non-NULL, it must point to a valid
1737
memset(global_system_variables.dynamic_variables_ptr +
1738
global_variables_dynamic_size, 0,
1739
new_size - global_variables_dynamic_size);
1740
memset(max_system_variables.dynamic_variables_ptr +
1741
global_variables_dynamic_size, 0,
1742
new_size - global_variables_dynamic_size);
1743
global_variables_dynamic_size= new_size;
1746
global_system_variables.dynamic_variables_head= offset;
1747
max_system_variables.dynamic_variables_head= offset;
1748
global_system_variables.dynamic_variables_size= offset + size;
1749
max_system_variables.dynamic_variables_size= offset + size;
1750
global_system_variables.dynamic_variables_version++;
1751
max_system_variables.dynamic_variables_version++;
1753
result->version= global_system_variables.dynamic_variables_version;
1755
/* this should succeed because we have already checked if a dup exists */
1756
if (my_hash_insert(&bookmark_hash, (uchar*) result))
1758
fprintf(stderr, "failed to add placeholder to hash");
1768
returns a pointer to the memory which holds the thd-local variable or
1769
a pointer to the global variable if thd==null.
1770
If required, will sync with global variables if the requested variable
1771
has not yet been allocated in the current thread.
1773
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
1775
assert(offset >= 0);
1776
assert((uint)offset <= global_system_variables.dynamic_variables_head);
1779
return (uchar*) global_system_variables.dynamic_variables_ptr + offset;
1782
dynamic_variables_head points to the largest valid offset
1784
if (!thd->variables.dynamic_variables_ptr ||
1785
(uint)offset > thd->variables.dynamic_variables_head)
1789
rw_rdlock(&LOCK_system_variables_hash);
1791
thd->variables.dynamic_variables_ptr= (char*)
1792
my_realloc(thd->variables.dynamic_variables_ptr,
1793
global_variables_dynamic_size,
1794
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1797
pthread_mutex_lock(&LOCK_global_system_variables);
1799
safe_mutex_assert_owner(&LOCK_global_system_variables);
1801
memcpy(thd->variables.dynamic_variables_ptr +
1802
thd->variables.dynamic_variables_size,
1803
global_system_variables.dynamic_variables_ptr +
1804
thd->variables.dynamic_variables_size,
1805
global_system_variables.dynamic_variables_size -
1806
thd->variables.dynamic_variables_size);
1809
now we need to iterate through any newly copied 'defaults'
1810
and if it is a string type with MEMALLOC flag, we need to strdup
1812
for (idx= 0; idx < bookmark_hash.records; idx++)
1814
sys_var_pluginvar *pi;
1816
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1818
if (v->version <= thd->variables.dynamic_variables_version ||
1819
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1820
!(pi= var->cast_pluginvar()) ||
1821
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1824
/* Here we do anything special that may be required of the data types */
1826
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1827
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1829
char **pp= (char**) (thd->variables.dynamic_variables_ptr +
1830
*(int*)(pi->plugin_var + 1));
1831
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1832
*(int*)(pi->plugin_var + 1))))
1833
*pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
1838
pthread_mutex_unlock(&LOCK_global_system_variables);
1840
thd->variables.dynamic_variables_version=
1841
global_system_variables.dynamic_variables_version;
1842
thd->variables.dynamic_variables_head=
1843
global_system_variables.dynamic_variables_head;
1844
thd->variables.dynamic_variables_size=
1845
global_system_variables.dynamic_variables_size;
1847
rw_unlock(&LOCK_system_variables_hash);
1849
return (uchar*)thd->variables.dynamic_variables_ptr + offset;
1852
static bool *mysql_sys_var_ptr_bool(THD* a_thd, int offset)
1854
return (bool *)intern_sys_var_ptr(a_thd, offset, true);
1857
static int *mysql_sys_var_ptr_int(THD* a_thd, int offset)
1859
return (int *)intern_sys_var_ptr(a_thd, offset, true);
1862
static long *mysql_sys_var_ptr_long(THD* a_thd, int offset)
1864
return (long *)intern_sys_var_ptr(a_thd, offset, true);
1867
static int64_t *mysql_sys_var_ptr_int64_t(THD* a_thd, int offset)
1869
return (int64_t *)intern_sys_var_ptr(a_thd, offset, true);
1872
static char **mysql_sys_var_ptr_str(THD* a_thd, int offset)
1874
return (char **)intern_sys_var_ptr(a_thd, offset, true);
1877
static uint64_t *mysql_sys_var_ptr_set(THD* a_thd, int offset)
1879
return (uint64_t *)intern_sys_var_ptr(a_thd, offset, true);
1882
static unsigned long *mysql_sys_var_ptr_enum(THD* a_thd, int offset)
1884
return (unsigned long *)intern_sys_var_ptr(a_thd, offset, true);
1888
void plugin_thdvar_init(THD *thd)
1890
plugin_ref old_table_plugin= thd->variables.table_plugin;
1892
thd->variables.table_plugin= NULL;
1893
cleanup_variables(thd, &thd->variables);
1895
thd->variables= global_system_variables;
1896
thd->variables.table_plugin= NULL;
517
1898
/* we are going to allocate these lazily */
518
session->variables.dynamic_variables_version= 0;
519
session->variables.dynamic_variables_size= 0;
520
session->variables.dynamic_variables_ptr= 0;
1899
thd->variables.dynamic_variables_version= 0;
1900
thd->variables.dynamic_variables_size= 0;
1901
thd->variables.dynamic_variables_ptr= 0;
522
session->variables.storage_engine= global_system_variables.storage_engine;
1903
thd->variables.table_plugin=
1904
my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1905
intern_plugin_unlock(NULL, old_table_plugin);
527
1911
Unlocks all system variables which hold a reference
529
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
1913
static void unlock_variables(THD *thd __attribute__((unused)),
1914
struct system_variables *vars)
531
vars->storage_engine= NULL;
1916
intern_plugin_unlock(NULL, vars->table_plugin);
1917
vars->table_plugin= NULL;
538
1924
Unlike plugin_vars_free_values() it frees all variables of all plugins,
539
1925
it's used on shutdown.
541
static void cleanup_variables(drizzle_system_variables *vars)
1927
static void cleanup_variables(THD *thd, struct system_variables *vars)
543
assert(vars->storage_engine == NULL);
545
free(vars->dynamic_variables_ptr);
1930
sys_var_pluginvar *pivar;
1935
rw_rdlock(&LOCK_system_variables_hash);
1936
for (idx= 0; idx < bookmark_hash.records; idx++)
1938
v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1939
if (v->version > vars->dynamic_variables_version ||
1940
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1941
!(pivar= var->cast_pluginvar()) ||
1942
v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1945
flags= pivar->plugin_var->flags;
1947
if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1948
flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1950
char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
1951
my_free(*ptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1955
rw_unlock(&LOCK_system_variables_hash);
1957
assert(vars->table_plugin == NULL);
1959
my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR));
546
1960
vars->dynamic_variables_ptr= NULL;
547
1961
vars->dynamic_variables_size= 0;
548
1962
vars->dynamic_variables_version= 0;
552
void plugin_sessionvar_cleanup(Session *session)
554
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1966
void plugin_thdvar_cleanup(THD *thd)
1971
unlock_variables(thd, &thd->variables);
1972
cleanup_variables(thd, &thd->variables);
1974
if ((idx= thd->lex->plugins.elements))
1976
list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
1977
while ((uchar*) list >= thd->lex->plugins.buffer)
1978
intern_plugin_unlock(NULL, *list--);
1981
reset_dynamic(&thd->lex->plugins);
1988
@brief Free values of thread variables of a plugin.
1990
This must be called before a plugin is deleted. Otherwise its
1991
variables are no longer accessible and the value space is lost. Note
1992
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1995
@param[in] vars Chain of system variables of a plugin
1998
static void plugin_vars_free_values(sys_var *vars)
2001
for (sys_var *var= vars; var; var= var->next)
2003
sys_var_pluginvar *piv= var->cast_pluginvar();
2005
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
2006
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
2008
/* Free the string from global_system_variables. */
2009
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2010
my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
2018
bool sys_var_pluginvar::check_update_type(Item_result type)
2022
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2023
case PLUGIN_VAR_INT:
2024
case PLUGIN_VAR_LONG:
2025
case PLUGIN_VAR_LONGLONG:
2026
return type != INT_RESULT;
2027
case PLUGIN_VAR_STR:
2028
return type != STRING_RESULT;
2035
SHOW_TYPE sys_var_pluginvar::show_type()
2037
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2038
case PLUGIN_VAR_BOOL:
2039
return SHOW_MY_BOOL;
2040
case PLUGIN_VAR_INT:
2042
case PLUGIN_VAR_LONG:
2044
case PLUGIN_VAR_LONGLONG:
2045
return SHOW_LONGLONG;
2046
case PLUGIN_VAR_STR:
2047
return SHOW_CHAR_PTR;
2048
case PLUGIN_VAR_ENUM:
2049
case PLUGIN_VAR_SET:
2058
uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
2060
assert(thd || (type == OPT_GLOBAL));
2061
if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
2063
if (type == OPT_GLOBAL)
2066
return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
2068
return *(uchar**) (plugin_var+1);
2072
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2074
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
2075
case PLUGIN_VAR_ENUM:
2076
return ((sysvar_enum_t *)plugin_var)->typelib;
2077
case PLUGIN_VAR_SET:
2078
return ((sysvar_set_t *)plugin_var)->typelib;
2079
case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2080
return ((thdvar_enum_t *)plugin_var)->typelib;
2081
case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2082
return ((thdvar_set_t *)plugin_var)->typelib;
2090
uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
2091
LEX_STRING *base __attribute__((unused)))
2095
result= real_value_ptr(thd, type);
2097
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2098
result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result);
2099
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2101
char buffer[STRING_BUFFER_USUAL_SIZE];
2102
String str(buffer, sizeof(buffer), system_charset_info);
2103
TYPELIB *typelib= plugin_var_typelib();
2104
uint64_t mask= 1, value= *(uint64_t*) result;
2108
for (i= 0; i < typelib->count; i++, mask<<=1)
2110
if (!(value & mask))
2112
str.append(typelib->type_names[i], typelib->type_lengths[i]);
2116
result= (uchar*) "";
2118
result= (uchar*) thd->strmake(str.ptr(), str.length()-1);
2124
bool sys_var_pluginvar::check(THD *thd, set_var *var)
2126
st_item_value_holder value;
2127
assert(is_readonly() || plugin_var->check);
2129
value.value_type= item_value_type;
2130
value.val_str= item_val_str;
2131
value.val_int= item_val_int;
2132
value.val_real= item_val_real;
2133
value.item= var->value;
2135
return is_readonly() ||
2136
plugin_var->check(thd, plugin_var, &var->save_result, &value);
2140
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
2145
assert(is_readonly() || plugin_var->update);
2150
pthread_mutex_lock(&LOCK_global_system_variables);
2151
tgt= real_value_ptr(thd, type);
2152
src= ((void **) (plugin_var + 1) + 1);
2154
if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
2156
if (type != OPT_GLOBAL)
2157
src= real_value_ptr(thd, OPT_GLOBAL);
2159
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2160
case PLUGIN_VAR_INT:
2161
src= &((thdvar_uint_t*) plugin_var)->def_val;
2163
case PLUGIN_VAR_LONG:
2164
src= &((thdvar_ulong_t*) plugin_var)->def_val;
2166
case PLUGIN_VAR_LONGLONG:
2167
src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
2169
case PLUGIN_VAR_ENUM:
2170
src= &((thdvar_enum_t*) plugin_var)->def_val;
2172
case PLUGIN_VAR_SET:
2173
src= &((thdvar_set_t*) plugin_var)->def_val;
2175
case PLUGIN_VAR_BOOL:
2176
src= &((thdvar_bool_t*) plugin_var)->def_val;
2178
case PLUGIN_VAR_STR:
2179
src= &((thdvar_str_t*) plugin_var)->def_val;
2186
/* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2187
assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2188
thd == current_thd);
2190
if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
2192
plugin_var->update(thd, plugin_var, tgt, src);
2193
pthread_mutex_unlock(&LOCK_global_system_variables);
2197
pthread_mutex_unlock(&LOCK_global_system_variables);
2198
plugin_var->update(thd, plugin_var, tgt, src);
2203
bool sys_var_pluginvar::update(THD *thd, set_var *var)
2207
assert(is_readonly() || plugin_var->update);
2209
/* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2210
assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2211
thd == current_thd);
2216
pthread_mutex_lock(&LOCK_global_system_variables);
2217
tgt= real_value_ptr(thd, var->type);
2219
if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
2221
/* variable we are updating has global scope, so we unlock after updating */
2222
plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2223
pthread_mutex_unlock(&LOCK_global_system_variables);
2227
pthread_mutex_unlock(&LOCK_global_system_variables);
2228
plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2234
#define OPTION_SET_LIMITS(type, options, opt) \
2235
options->var_type= type; \
2236
options->def_value= (opt)->def_val; \
2237
options->min_value= (opt)->min_val; \
2238
options->max_value= (opt)->max_val; \
2239
options->block_size= (long) (opt)->blk_sz
2242
static void plugin_opt_set_limits(struct my_option *options,
2243
const struct st_mysql_sys_var *opt)
2245
options->sub_size= 0;
2247
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2248
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
2249
/* global system variables */
2250
case PLUGIN_VAR_INT:
2251
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2253
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
2254
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
2256
case PLUGIN_VAR_LONG:
2257
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2259
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2260
OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
2262
case PLUGIN_VAR_LONGLONG:
2263
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2265
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
2266
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
2268
case PLUGIN_VAR_ENUM:
2269
options->var_type= GET_ENUM;
2270
options->typelib= ((sysvar_enum_t*) opt)->typelib;
2271
options->def_value= ((sysvar_enum_t*) opt)->def_val;
2272
options->min_value= options->block_size= 0;
2273
options->max_value= options->typelib->count - 1;
2275
case PLUGIN_VAR_SET:
2276
options->var_type= GET_SET;
2277
options->typelib= ((sysvar_set_t*) opt)->typelib;
2278
options->def_value= ((sysvar_set_t*) opt)->def_val;
2279
options->min_value= options->block_size= 0;
2280
options->max_value= (1ULL << options->typelib->count) - 1;
2282
case PLUGIN_VAR_BOOL:
2283
options->var_type= GET_BOOL;
2284
options->def_value= ((sysvar_bool_t*) opt)->def_val;
2286
case PLUGIN_VAR_STR:
2287
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2288
GET_STR_ALLOC : GET_STR);
2289
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2291
/* threadlocal variables */
2292
case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
2293
OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
2295
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2296
OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
2298
case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
2299
OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
2301
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2302
OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
2304
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
2305
OPTION_SET_LIMITS(GET_LL, options, (thdvar_int64_t_t*) opt);
2307
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2308
OPTION_SET_LIMITS(GET_ULL, options, (thdvar_uint64_t_t*) opt);
2310
case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2311
options->var_type= GET_ENUM;
2312
options->typelib= ((thdvar_enum_t*) opt)->typelib;
2313
options->def_value= ((thdvar_enum_t*) opt)->def_val;
2314
options->min_value= options->block_size= 0;
2315
options->max_value= options->typelib->count - 1;
2317
case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2318
options->var_type= GET_SET;
2319
options->typelib= ((thdvar_set_t*) opt)->typelib;
2320
options->def_value= ((thdvar_set_t*) opt)->def_val;
2321
options->min_value= options->block_size= 0;
2322
options->max_value= (1ULL << options->typelib->count) - 1;
2324
case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
2325
options->var_type= GET_BOOL;
2326
options->def_value= ((thdvar_bool_t*) opt)->def_val;
2328
case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
2329
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2330
GET_STR_ALLOC : GET_STR);
2331
options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
2336
options->arg_type= REQUIRED_ARG;
2337
if (opt->flags & PLUGIN_VAR_NOCMDARG)
2338
options->arg_type= NO_ARG;
2339
if (opt->flags & PLUGIN_VAR_OPCMDARG)
2340
options->arg_type= OPT_ARG;
2343
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2346
bool get_one_plugin_option(int optid __attribute__((unused)),
2347
const struct my_option *opt __attribute__((unused)),
2348
char *argument __attribute__((unused)))
2354
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
2355
my_option *options, bool can_disable)
2357
const char *plugin_name= tmp->plugin->name;
2358
uint namelen= strlen(plugin_name), optnamelen;
2359
uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2360
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2362
int index= 0, offset= 0;
2363
st_mysql_sys_var *opt, **plugin_option;
2366
/* support --skip-plugin-foo syntax */
2367
memcpy(name, plugin_name, namelen + 1);
2368
my_casedn_str(&my_charset_utf8_general_ci, name);
2369
strxmov(name + namelen + 1, "plugin-", name, NullS);
2370
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2372
for (p= name + namelen*2 + 8; p > name; p--)
2378
strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2379
"Disable with --skip-", name," (will save memory).", NullS);
2381
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2382
20 + namelen + 20 + 1 == namelen * 4 + 67.
2385
options[0].comment= name + namelen*2 + 10;
2388
options[1].name= (options[0].name= name) + namelen + 1;
2389
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2390
options[0].var_type= options[1].var_type= GET_BOOL;
2391
options[0].arg_type= options[1].arg_type= NO_ARG;
2392
options[0].def_value= options[1].def_value= true;
2393
options[0].value= options[0].u_max_value=
2394
options[1].value= options[1].u_max_value= (char**) (name - 1);
2398
Two passes as the 2nd pass will take pointer addresses for use
2399
by my_getopt and register_var() in the first pass uses realloc
2402
for (plugin_option= tmp->plugin->system_vars;
2403
plugin_option && *plugin_option; plugin_option++, index++)
2405
opt= *plugin_option;
2406
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
2408
if (!(register_var(name, opt->name, opt->flags)))
2410
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2411
case PLUGIN_VAR_BOOL:
2412
(((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2414
case PLUGIN_VAR_INT:
2415
(((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2417
case PLUGIN_VAR_LONG:
2418
(((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2420
case PLUGIN_VAR_LONGLONG:
2421
(((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2423
case PLUGIN_VAR_STR:
2424
(((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2426
case PLUGIN_VAR_ENUM:
2427
(((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2429
case PLUGIN_VAR_SET:
2430
(((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2433
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2434
opt->flags, plugin_name);
2439
for (plugin_option= tmp->plugin->system_vars;
2440
plugin_option && *plugin_option; plugin_option++, index++)
2442
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
2443
case PLUGIN_VAR_BOOL:
2445
opt->check= check_func_bool;
2447
opt->update= update_func_bool;
2449
case PLUGIN_VAR_INT:
2451
opt->check= check_func_int;
2453
opt->update= update_func_int;
2455
case PLUGIN_VAR_LONG:
2457
opt->check= check_func_long;
2459
opt->update= update_func_long;
2461
case PLUGIN_VAR_LONGLONG:
2463
opt->check= check_func_int64_t;
2465
opt->update= update_func_int64_t;
2467
case PLUGIN_VAR_STR:
2469
opt->check= check_func_str;
2472
opt->update= update_func_str;
2473
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2475
opt->flags|= PLUGIN_VAR_READONLY;
2476
sql_print_warning(_("Server variable %s of plugin %s was forced "
2477
"to be read-only: string variable without "
2478
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2479
opt->name, plugin_name);
2483
case PLUGIN_VAR_ENUM:
2485
opt->check= check_func_enum;
2487
opt->update= update_func_long;
2489
case PLUGIN_VAR_SET:
2491
opt->check= check_func_set;
2493
opt->update= update_func_int64_t;
2496
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2497
opt->flags, plugin_name);
2501
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
2502
== PLUGIN_VAR_NOCMDOPT)
2507
sql_print_error(_("Missing variable name in plugin '%s'."),
2512
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
2514
optnamelen= strlen(opt->name);
2515
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2516
strxmov(optname, name, "-", opt->name, NullS);
2517
optnamelen= namelen + optnamelen + 1;
2521
/* this should not fail because register_var should create entry */
2522
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2524
sql_print_error(_("Thread local variable '%s' not allocated "
2525
"in plugin '%s'."), opt->name, plugin_name);
2529
*(int*)(opt + 1)= offset= v->offset;
2531
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2534
optname= (char*) memdup_root(mem_root, v->key + 1,
2535
(optnamelen= v->name_len) + 1);
2538
/* convert '_' to '-' */
2539
for (p= optname; *p; p++)
2543
options->name= optname;
2544
options->comment= opt->comment;
2545
options->app_type= opt;
2546
options->id= (options-1)->id + 1;
2548
plugin_opt_set_limits(options, opt);
2550
if (opt->flags & PLUGIN_VAR_THDLOCAL)
2551
options->value= options->u_max_value= (char**)
2552
(global_system_variables.dynamic_variables_ptr + offset);
2554
options->value= options->u_max_value= *(char***) (opt + 1);
2556
options[1]= options[0];
2557
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2558
options[1].comment= 0; // hidden
2559
strxmov(p, "plugin-", optname, NullS);
2568
static my_option *construct_help_options(MEM_ROOT *mem_root,
2569
struct st_plugin_int *p)
2571
st_mysql_sys_var **opt;
2574
uint count= EXTRA_OPTIONS;
2576
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2578
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2581
memset(opts, 0, sizeof(my_option) * count);
2583
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2585
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2591
if (construct_options(mem_root, p, opts, can_disable))