95
72
write-lock on LOCK_system_variables_hash is required before modifying
96
73
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
75
static MEM_ROOT plugin_mem_root;
99
76
static uint32_t global_variables_dynamic_size= 0;
77
static HASH bookmark_hash;
103
81
hidden part of opaque value passed to variable check functions.
104
82
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
84
struct st_item_value_holder : public st_mysql_value
91
stored in bookmark_hash, this structure is never removed from the
92
hash and is used to mark a single offset for a session local variable
93
even if plugins have been uninstalled and reinstalled, repeatedly.
94
This structure is allocated from plugin_mem_root.
96
The key format is as follows:
97
1 byte - variable type code
98
name_len bytes - variable name
122
105
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
111
skeleton of a plugin variable - portion of structure common to all.
113
struct st_mysql_sys_var
115
DRIZZLE_PLUGIN_VAR_HEADER;
120
sys_var class for access to all plugin variables visible to the user
122
class sys_var_pluginvar: public sys_var
125
struct st_plugin_int *plugin;
126
struct st_mysql_sys_var *plugin_var;
128
static void *operator new(size_t size, MEM_ROOT *mem_root)
129
{ return (void*) alloc_root(mem_root, (uint32_t) size); }
130
static void operator delete(void *, size_t)
131
{ TRASH(ptr_arg, size); }
133
sys_var_pluginvar(const char *name_arg,
134
struct st_mysql_sys_var *plugin_var_arg)
135
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
136
sys_var_pluginvar *cast_pluginvar() { return this; }
137
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
138
bool check_type(enum_var_type type)
139
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
140
bool check_update_type(Item_result type);
141
SHOW_TYPE show_type();
142
unsigned char* real_value_ptr(Session *session, enum_var_type type);
143
TYPELIB* plugin_var_typelib(void);
144
unsigned char* value_ptr(Session *session, enum_var_type type,
145
const LEX_STRING *base);
146
bool check(Session *session, set_var *var);
147
bool check_default(enum_var_type)
148
{ return is_readonly(); }
149
void set_default(Session *session, enum_var_type);
150
bool update(Session *session, 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);
155
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
157
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
159
static bool register_builtin(struct st_plugin_int *,
160
struct st_plugin_int **);
161
static void unlock_variables(Session *session, struct system_variables *vars);
162
static void cleanup_variables(Session *session, struct system_variables *vars);
163
static void plugin_vars_free_values(sys_var *vars);
164
static void plugin_opt_set_limits(struct my_option *options,
165
const struct st_mysql_sys_var *opt);
166
static void reap_plugins(void);
144
169
/* declared in set_var.cc */
145
170
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
171
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
172
const std::string &name, int64_t val);
174
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
175
const char *name, int64_t val)
177
const std::string name_str(name);
178
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
181
/****************************************************************************
182
Value type thunks, allows the C world to play in the C++ world
183
****************************************************************************/
185
static int item_value_type(struct st_mysql_value *value)
187
switch (((st_item_value_holder*)value)->item->result_type()) {
189
return DRIZZLE_VALUE_TYPE_INT;
191
return DRIZZLE_VALUE_TYPE_REAL;
193
return DRIZZLE_VALUE_TYPE_STRING;
197
static const char *item_val_str(struct st_mysql_value *value,
198
char *buffer, int *length)
200
String str(buffer, *length, system_charset_info), *res;
201
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
203
*length= res->length();
204
if (res->c_ptr_quick() == buffer)
208
Lets be nice and create a temporary string since the
211
return current_session->strmake(res->c_ptr_quick(), res->length());
215
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
217
Item *item= ((st_item_value_holder*)value)->item;
218
*buf= item->val_int();
225
static int item_val_real(struct st_mysql_value *value, double *buf)
227
Item *item= ((st_item_value_holder*)value)->item;
228
*buf= item->val_real();
148
235
/****************************************************************************
149
236
Plugin support code
150
237
****************************************************************************/
239
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
242
struct st_plugin_dl *tmp;
244
for (i= 0; i < plugin_dl_array.elements; i++)
246
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
247
if (! my_strnncoll(files_charset_info,
248
(const unsigned char *)dl->str, dl->length,
249
(const unsigned char *)tmp->dl.str, tmp->dl.length))
255
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
258
struct st_plugin_dl *tmp;
260
for (i= 0; i < plugin_dl_array.elements; i++)
262
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
264
memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
268
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
270
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
271
struct st_plugin_dl **)=
272
(struct st_plugin_dl *) memdup_root(&plugin_mem_root, (unsigned char*)plugin_dl,
273
sizeof(struct st_plugin_dl));
277
static inline void free_plugin_mem(struct st_plugin_dl *p)
285
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
288
uint32_t plugin_dir_len, dummy_errors;
289
struct st_plugin_dl *tmp, plugin_dl;
291
plugin_dir_len= strlen(opt_plugin_dir);
292
dlpath.reserve(FN_REFLEN);
294
Ensure that the dll doesn't have a path.
295
This is done to ensure that only approved libraries from the
296
plugin directory are used (to make this even remotely secure).
298
if (strchr(dl->str, FN_LIBCHAR) ||
299
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
300
system_charset_info, 1) ||
301
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
303
if (report & REPORT_TO_USER)
304
my_error(ER_UDF_NO_PATHS, MYF(0));
305
if (report & REPORT_TO_LOG)
306
errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
309
/* If this dll is already loaded just increase ref_count. */
310
if ((tmp= plugin_dl_find(dl)))
314
memset(&plugin_dl, 0, sizeof(plugin_dl));
315
/* Compile dll path */
316
dlpath.append(opt_plugin_dir);
318
dlpath.append(dl->str);
319
/* Open new dll handle */
320
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
322
const char *errmsg=dlerror();
323
uint32_t dlpathlen= dlpath.length();
324
if (!dlpath.compare(0, dlpathlen, errmsg))
325
{ // if errmsg starts from dlpath, trim this prefix.
327
if (*errmsg == ':') errmsg++;
328
if (*errmsg == ' ') errmsg++;
330
if (report & REPORT_TO_USER)
331
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
332
if (report & REPORT_TO_LOG)
333
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
337
/* Find plugin declarations */
338
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
340
free_plugin_mem(&plugin_dl);
341
if (report & REPORT_TO_USER)
342
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
343
if (report & REPORT_TO_LOG)
344
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
348
plugin_dl.plugins= (struct drizzled_plugin_manifest *)sym;
350
/* Duplicate and convert dll name */
351
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
352
if (! (plugin_dl.dl.str= (char*) malloc(plugin_dl.dl.length)))
354
free_plugin_mem(&plugin_dl);
355
if (report & REPORT_TO_USER)
356
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
357
if (report & REPORT_TO_LOG)
358
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
361
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
362
files_charset_info, dl->str, dl->length, system_charset_info,
364
plugin_dl.dl.str[plugin_dl.dl.length]= 0;
365
/* Add this dll to array */
366
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
368
free_plugin_mem(&plugin_dl);
369
if (report & REPORT_TO_USER)
370
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
371
if (report & REPORT_TO_LOG)
372
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
379
static void plugin_dl_del(const LEX_STRING *dl)
383
for (i= 0; i < plugin_dl_array.elements; i++)
385
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
386
struct st_plugin_dl **);
387
if (! my_strnncoll(files_charset_info,
388
(const unsigned char *)dl->str, dl->length,
389
(const unsigned char *)tmp->dl.str, tmp->dl.length))
391
/* Do not remove this element, unless no other plugin uses this dll. */
393
free_plugin_mem(tmp);
394
memset(tmp, 0, sizeof(struct st_plugin_dl));
404
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
406
struct st_plugin_int *tmp;
407
if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
409
tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
410
struct st_plugin_int **)=
411
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)plugin,
412
sizeof(struct st_plugin_int));
157
419
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)
421
static bool plugin_add(MEM_ROOT *tmp_root,
422
const LEX_STRING *name, const LEX_STRING *dl,
423
int *argc, char **argv, int report)
425
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
427
struct st_plugin_int tmp;
428
struct drizzled_plugin_manifest *plugin;
163
429
if (! initialized)
166
if (registry.find(library->getName()))
432
if (registry.find(name))
168
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
169
library->getName().c_str());
434
if (report & REPORT_TO_USER)
435
my_error(ER_UDF_EXISTS, MYF(0), name->str);
436
if (report & REPORT_TO_LOG)
437
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
173
module::Module *tmp= NULL;
440
/* Clear the whole struct to catch future extensions. */
441
memset(&tmp, 0, sizeof(tmp));
442
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
174
444
/* 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());
445
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
447
uint32_t name_len= strlen(plugin->name);
448
if (! my_strnncoll(system_charset_info,
449
(const unsigned char *)name->str, name->length,
450
(const unsigned char *)plugin->name,
453
struct st_plugin_int *tmp_plugin_ptr;
456
tmp.name.str= (char *)plugin->name;
457
tmp.name.length= name_len;
459
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
461
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
463
registry.add(tmp_plugin_ptr);
464
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
467
mysql_del_sys_var_chain(tmp.system_vars);
470
/* plugin was disabled */
475
if (report & REPORT_TO_USER)
476
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
477
if (report & REPORT_TO_LOG)
478
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
485
static void plugin_del(struct st_plugin_int *plugin)
487
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
488
if (plugin->isInited)
490
if (plugin->plugin->status_vars)
492
remove_status_vars(plugin->plugin->status_vars);
495
if (plugin->plugin->deinit)
496
plugin->plugin->deinit(registry);
499
/* Free allocated strings before deleting the plugin. */
500
plugin_vars_free_values(plugin->system_vars);
501
if (plugin->plugin_dl)
502
plugin_dl_del(&plugin->plugin_dl->dl);
503
plugin->isInited= false;
504
pthread_rwlock_wrlock(&LOCK_system_variables_hash);
505
mysql_del_sys_var_chain(plugin->system_vars);
506
pthread_rwlock_unlock(&LOCK_system_variables_hash);
507
free_root(&plugin->mem_root, MYF(0));
510
static void reap_plugins(void)
514
struct st_plugin_int *plugin;
516
count= plugin_array.elements;
518
for (idx= 0; idx < count; idx++)
520
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
525
static bool plugin_initialize(struct st_plugin_int *plugin)
527
assert(plugin->isInited == false);
529
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
530
if (plugin->plugin->init)
532
if (plugin->plugin->init(registry))
534
errmsg_printf(ERRMSG_LVL_ERROR,
535
_("Plugin '%s' init function returned error.\n"),
540
plugin->isInited= true;
542
if (plugin->plugin->status_vars)
544
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
548
set the plugin attribute of plugin's sys vars so they are pointing
551
if (plugin->system_vars)
553
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
559
var= var->next->cast_pluginvar();
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);
569
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
572
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
574
struct st_bookmark *var= (st_bookmark *)buff;
575
*length= var->name_len + 1;
576
return (unsigned char*) var->key;
291
581
The logic is that we first load and initialize all compiled in plugins.
295
585
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)
587
int plugin_init(int *argc, char **argv, int flags)
300
memory::Root tmp_root(4096);
590
struct drizzled_plugin_manifest **builtins;
591
struct drizzled_plugin_manifest *plugin;
592
struct st_plugin_int tmp, *plugin_ptr;
598
init_alloc_root(&plugin_mem_root, 4096, 4096);
599
init_alloc_root(&tmp_root, 4096, 4096);
601
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
602
get_bookmark_hash_key, NULL, HASH_UNIQUE))
606
if (my_init_dynamic_array(&plugin_dl_array,
607
sizeof(struct st_plugin_dl *),16,16) ||
608
my_init_dynamic_array(&plugin_array,
609
sizeof(struct st_plugin_int *),16,16))
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
615
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);
617
for (builtins= drizzled_builtins; *builtins; builtins++)
349
tmp_root.free_root(MYF(0));
619
for (plugin= *builtins; plugin->name; plugin++)
621
memset(&tmp, 0, sizeof(tmp));
623
tmp.name.str= (char *)plugin->name;
624
tmp.name.length= strlen(plugin->name);
626
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
627
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
630
if (register_builtin(&tmp, &plugin_ptr))
633
if (plugin_initialize(plugin_ptr))
353
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
357
640
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
641
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
362
tmp_root.free_root(MYF(0));
644
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
647
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
374
651
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())
653
for (idx= 0; idx < plugin_array.elements; idx++)
381
module::Module *module= (*modules).second;
383
if (module->isInited == false)
655
plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
656
if (plugin_ptr->isInited == false)
385
if (plugin_initialize(registry, module))
387
registry.remove(module);
658
if (plugin_initialize(plugin_ptr))
659
plugin_del(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(),
665
free_root(&tmp_root, MYF(0));
671
free_root(&tmp_root, MYF(0));
676
static bool register_builtin(struct st_plugin_int *tmp,
677
struct st_plugin_int **ptr)
680
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
682
tmp->isInited= false;
685
if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
688
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
689
struct st_plugin_int **)=
690
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
691
sizeof(struct st_plugin_int));
434
700
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,
702
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();
705
char buffer[FN_REFLEN];
706
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
707
struct st_plugin_dl *plugin_dl;
708
struct drizzled_plugin_manifest *plugin;
448
const string plugin_name(*iter);
450
library= registry.addLibrary(plugin_name, builtin);
712
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());
714
errmsg_printf(ERRMSG_LVL_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());
718
switch ((*(p++)= *(list++))) {
720
list= NULL; /* terminate the loop */
722
case ':': /* can't use this as delimiter as it may be drive letter */
724
str->str[str->length]= '\0';
725
if (str == &name) // load all plugins in named module
729
p--; /* reset pointer */
734
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
736
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
738
name.str= (char *) plugin->name;
739
name.length= strlen(name.str);
741
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
742
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
745
plugin_dl_del(&dl); // reduce ref count
750
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
751
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
754
name.length= dl.length= 0;
755
dl.str= NULL; name.str= p= buffer;
762
name.str[name.length]= '\0';
774
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
474
void module_shutdown(module::Registry ®istry)
780
void plugin_shutdown(void)
783
size_t count= plugin_array.elements;
784
vector<st_plugin_int *> plugins;
785
vector<st_plugin_dl *> dl;
479
789
reap_needed= true;
481
reap_plugins(registry);
482
792
unlock_variables(NULL, &global_system_variables);
483
793
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
795
cleanup_variables(NULL, &global_system_variables);
796
cleanup_variables(NULL, &max_system_variables);
491
801
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
803
delete_dynamic(&plugin_array);
805
count= plugin_dl_array.elements;
807
for (idx= 0; idx < count; idx++)
808
dl.push_back(*dynamic_element(&plugin_dl_array, idx,
809
struct st_plugin_dl **));
810
for (idx= 0; idx < count; idx++)
811
free_plugin_mem(dl[idx]);
812
delete_dynamic(&plugin_dl_array);
814
hash_free(&bookmark_hash);
815
free_root(&plugin_mem_root, MYF(0));
494
817
global_variables_dynamic_size= 0;
820
/****************************************************************************
821
Internal type declarations for variables support
822
****************************************************************************/
824
#undef DRIZZLE_SYSVAR_NAME
825
#define DRIZZLE_SYSVAR_NAME(name) name
826
#define PLUGIN_VAR_TYPEMASK 0x007f
828
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
830
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
831
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
832
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
833
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
835
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
836
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
837
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
838
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
840
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
841
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
842
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
843
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
844
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
845
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
847
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
848
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
849
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
850
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
851
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
852
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
854
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
857
/****************************************************************************
858
default variable data check and update functions
859
****************************************************************************/
861
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
862
void *save, st_mysql_value *value)
864
char buff[STRING_BUFFER_USUAL_SIZE];
865
const char *strvalue= "NULL", *str;
869
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
871
length= sizeof(buff);
872
if (!(str= value->val_str(value, buff, &length)) ||
873
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
882
if (value->val_int(value, &tmp) < 0)
892
*(int*)save= -result;
895
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
900
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
901
void *save, st_mysql_value *value)
905
struct my_option options;
906
value->val_int(value, &tmp);
907
plugin_opt_set_limits(&options, var);
909
if (var->flags & PLUGIN_VAR_UNSIGNED)
910
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
913
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
915
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
916
var->name, (int64_t) tmp);
920
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
921
void *save, st_mysql_value *value)
925
struct my_option options;
926
value->val_int(value, &tmp);
927
plugin_opt_set_limits(&options, var);
929
if (var->flags & PLUGIN_VAR_UNSIGNED)
930
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
933
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
935
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
936
var->name, (int64_t) tmp);
940
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
941
void *save, st_mysql_value *value)
945
struct my_option options;
946
value->val_int(value, &tmp);
947
plugin_opt_set_limits(&options, var);
949
if (var->flags & PLUGIN_VAR_UNSIGNED)
950
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
953
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
955
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
956
var->name, (int64_t) tmp);
959
static int check_func_str(Session *session, struct st_mysql_sys_var *,
960
void *save, st_mysql_value *value)
962
char buff[STRING_BUFFER_USUAL_SIZE];
966
length= sizeof(buff);
967
if ((str= value->val_str(value, buff, &length)))
968
str= session->strmake(str, length);
969
*(const char**)save= str;
974
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
975
void *save, st_mysql_value *value)
977
char buff[STRING_BUFFER_USUAL_SIZE];
978
const char *strvalue= "NULL", *str;
984
if (var->flags & PLUGIN_VAR_SessionLOCAL)
985
typelib= ((sessionvar_enum_t*) var)->typelib;
987
typelib= ((sysvar_enum_t*) var)->typelib;
989
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
991
length= sizeof(buff);
992
if (!(str= value->val_str(value, buff, &length)))
994
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1002
if (value->val_int(value, &tmp))
1004
if (tmp >= typelib->count)
1012
*(long*)save= result;
1015
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1020
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1021
void *save, st_mysql_value *value)
1023
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1024
const char *strvalue= "NULL", *str;
1031
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1032
typelib= ((sessionvar_set_t*) var)->typelib;
1034
typelib= ((sysvar_set_t*)var)->typelib;
1036
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1038
length= sizeof(buff);
1039
if (!(str= value->val_str(value, buff, &length)))
1041
result= find_set(typelib, str, length, NULL,
1042
&error, &error_len, ¬_used);
1045
length= cmin(sizeof(buff), (unsigned long)error_len);
1046
strncpy(buff, error, length);
1054
if (value->val_int(value, (int64_t *)&result))
1056
if (unlikely((result >= (1UL << typelib->count)) &&
1057
(typelib->count < sizeof(long)*8)))
1059
llstr(result, buff);
1064
*(uint64_t*)save= result;
1067
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1072
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1073
void *tgt, const void *save)
1075
*(bool *) tgt= *(int *) save ? 1 : 0;
1079
static void update_func_int(Session *, struct st_mysql_sys_var *,
1080
void *tgt, const void *save)
1082
*(int *)tgt= *(int *) save;
1086
static void update_func_long(Session *, struct st_mysql_sys_var *,
1087
void *tgt, const void *save)
1089
*(long *)tgt= *(long *) save;
1093
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1094
void *tgt, const void *save)
1096
*(int64_t *)tgt= *(uint64_t *) save;
1100
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1101
void *tgt, const void *save)
1103
char *old= *(char **) tgt;
1104
*(char **)tgt= *(char **) save;
1105
if (var->flags & PLUGIN_VAR_MEMALLOC)
1107
*(char **)tgt= strdup(*(char **) save);
1110
* There isn't a _really_ good thing to do here until this whole set_var
1111
* mess gets redesigned
1114
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
1120
/****************************************************************************
499
1121
System Variables support
500
1122
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
1125
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
1128
sys_var_pluginvar *pi= NULL;
1129
st_plugin_int *plugin;
1131
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1132
if ((var= intern_find_sys_var(str, length, false)) &&
1133
(pi= var->cast_pluginvar()))
1135
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1136
if (!(plugin= pi->plugin))
1137
var= NULL; /* failed to lock it, it must be uninstalling */
1138
else if (plugin->isInited == false)
1144
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1147
If the variable exists but the plugin it is associated with is not ready
1148
then the intern_plugin_lock did not raise an error, so we do it here.
1151
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1157
called by register_var, construct_options and test_plugin_options.
1158
Returns the 'bookmark' for the named variable.
1159
LOCK_system_variables_hash should be at least read locked
1161
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1163
st_bookmark *result= NULL;
1164
uint32_t namelen, length, pluginlen= 0;
1167
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1170
namelen= strlen(name);
1172
pluginlen= strlen(plugin) + 1;
1173
length= namelen + pluginlen + 2;
1174
varname= (char*) malloc(length);
1178
sprintf(varname+1,"%s_%s",plugin,name);
1179
for (p= varname + 1; *p; p++)
1184
memcpy(varname + 1, name, namelen + 1);
1186
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1188
result= (st_bookmark*) hash_search(&bookmark_hash,
1189
(const unsigned char*) varname, length - 1);
1197
returns a bookmark for session-local variables, creating if neccessary.
1198
returns null for non session-local variables.
1199
Requires that a write lock is obtained on LOCK_system_variables_hash
1201
static st_bookmark *register_var(const char *plugin, const char *name,
1204
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1205
st_bookmark *result;
1208
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1211
switch (flags & PLUGIN_VAR_TYPEMASK) {
1212
case PLUGIN_VAR_BOOL:
1213
size= ALIGN_SIZE(sizeof(bool));
1215
case PLUGIN_VAR_INT:
1216
size= ALIGN_SIZE(sizeof(int));
1218
case PLUGIN_VAR_LONG:
1219
case PLUGIN_VAR_ENUM:
1220
size= ALIGN_SIZE(sizeof(long));
1222
case PLUGIN_VAR_LONGLONG:
1223
case PLUGIN_VAR_SET:
1224
size= ALIGN_SIZE(sizeof(uint64_t));
1226
case PLUGIN_VAR_STR:
1227
size= ALIGN_SIZE(sizeof(char*));
1234
varname= ((char*) malloc(length));
1235
sprintf(varname+1, "%s_%s", plugin, name);
1236
for (p= varname + 1; *p; p++)
1240
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1242
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1243
sizeof(struct st_bookmark) + length-1);
1244
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1245
memcpy(result->key, varname, length);
1246
result->name_len= length - 2;
1249
assert(size && !(size & (size-1))); /* must be power of 2 */
1251
offset= global_system_variables.dynamic_variables_size;
1252
offset= (offset + size - 1) & ~(size - 1);
1253
result->offset= (int) offset;
1255
new_size= (offset + size + 63) & ~63;
1257
if (new_size > global_variables_dynamic_size)
1261
(char *)realloc(global_system_variables.dynamic_variables_ptr,
1264
global_system_variables.dynamic_variables_ptr= tmpptr;
1267
(char *)realloc(max_system_variables.dynamic_variables_ptr,
1270
max_system_variables.dynamic_variables_ptr= tmpptr;
1273
Clear the new variable value space. This is required for string
1274
variables. If their value is non-NULL, it must point to a valid
1277
memset(global_system_variables.dynamic_variables_ptr +
1278
global_variables_dynamic_size, 0,
1279
new_size - global_variables_dynamic_size);
1280
memset(max_system_variables.dynamic_variables_ptr +
1281
global_variables_dynamic_size, 0,
1282
new_size - global_variables_dynamic_size);
1283
global_variables_dynamic_size= new_size;
1286
global_system_variables.dynamic_variables_head= offset;
1287
max_system_variables.dynamic_variables_head= offset;
1288
global_system_variables.dynamic_variables_size= offset + size;
1289
max_system_variables.dynamic_variables_size= offset + size;
1290
global_system_variables.dynamic_variables_version++;
1291
max_system_variables.dynamic_variables_version++;
1293
result->version= global_system_variables.dynamic_variables_version;
1295
/* this should succeed because we have already checked if a dup exists */
1296
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1298
fprintf(stderr, "failed to add placeholder to hash");
1308
returns a pointer to the memory which holds the session-local variable or
1309
a pointer to the global variable if session==null.
1310
If required, will sync with global variables if the requested variable
1311
has not yet been allocated in the current thread.
1313
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1315
assert(offset >= 0);
1316
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1319
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1322
dynamic_variables_head points to the largest valid offset
1324
if (!session->variables.dynamic_variables_ptr ||
1325
(uint32_t)offset > session->variables.dynamic_variables_head)
1329
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1332
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1333
global_variables_dynamic_size)))
1335
session->variables.dynamic_variables_ptr= tmpptr;
1338
pthread_mutex_lock(&LOCK_global_system_variables);
1340
safe_mutex_assert_owner(&LOCK_global_system_variables);
1342
memcpy(session->variables.dynamic_variables_ptr +
1343
session->variables.dynamic_variables_size,
1344
global_system_variables.dynamic_variables_ptr +
1345
session->variables.dynamic_variables_size,
1346
global_system_variables.dynamic_variables_size -
1347
session->variables.dynamic_variables_size);
1350
now we need to iterate through any newly copied 'defaults'
1351
and if it is a string type with MEMALLOC flag, we need to strdup
1353
for (idx= 0; idx < bookmark_hash.records; idx++)
1355
sys_var_pluginvar *pi;
1357
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1359
if (v->version <= session->variables.dynamic_variables_version ||
1360
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1361
!(pi= var->cast_pluginvar()) ||
1362
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1365
/* Here we do anything special that may be required of the data types */
1367
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1368
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1370
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1371
*(int*)(pi->plugin_var + 1));
1372
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1373
*(int*)(pi->plugin_var + 1))))
1381
pthread_mutex_unlock(&LOCK_global_system_variables);
1383
session->variables.dynamic_variables_version=
1384
global_system_variables.dynamic_variables_version;
1385
session->variables.dynamic_variables_head=
1386
global_system_variables.dynamic_variables_head;
1387
session->variables.dynamic_variables_size=
1388
global_system_variables.dynamic_variables_size;
1390
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1392
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1395
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1397
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1400
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1402
return (int *)intern_sys_var_ptr(a_session, offset, true);
1405
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1407
return (long *)intern_sys_var_ptr(a_session, offset, true);
1410
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1412
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1415
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1417
return (char **)intern_sys_var_ptr(a_session, offset, true);
1420
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1422
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1425
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1427
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
509
1431
void plugin_sessionvar_init(Session *session)
511
1433
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1434
cleanup_variables(session, &session->variables);
514
1436
session->variables= global_system_variables;
515
1437
session->variables.storage_engine= NULL;
552
1502
void plugin_sessionvar_cleanup(Session *session)
554
1504
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1505
cleanup_variables(session, &session->variables);
1510
@brief Free values of thread variables of a plugin.
1512
This must be called before a plugin is deleted. Otherwise its
1513
variables are no longer accessible and the value space is lost. Note
1514
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1517
@param[in] vars Chain of system variables of a plugin
1520
static void plugin_vars_free_values(sys_var *vars)
1523
for (sys_var *var= vars; var; var= var->next)
1525
sys_var_pluginvar *piv= var->cast_pluginvar();
1527
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1528
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1530
/* Free the string from global_system_variables. */
1531
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1540
bool sys_var_pluginvar::check_update_type(Item_result type)
1544
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1545
case PLUGIN_VAR_INT:
1546
case PLUGIN_VAR_LONG:
1547
case PLUGIN_VAR_LONGLONG:
1548
return type != INT_RESULT;
1549
case PLUGIN_VAR_STR:
1550
return type != STRING_RESULT;
1557
SHOW_TYPE sys_var_pluginvar::show_type()
1559
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1560
case PLUGIN_VAR_BOOL:
1561
return SHOW_MY_BOOL;
1562
case PLUGIN_VAR_INT:
1564
case PLUGIN_VAR_LONG:
1566
case PLUGIN_VAR_LONGLONG:
1567
return SHOW_LONGLONG;
1568
case PLUGIN_VAR_STR:
1569
return SHOW_CHAR_PTR;
1570
case PLUGIN_VAR_ENUM:
1571
case PLUGIN_VAR_SET:
1580
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1582
assert(session || (type == OPT_GLOBAL));
1583
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1585
if (type == OPT_GLOBAL)
1588
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1590
return *(unsigned char**) (plugin_var+1);
1594
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1596
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1597
case PLUGIN_VAR_ENUM:
1598
return ((sysvar_enum_t *)plugin_var)->typelib;
1599
case PLUGIN_VAR_SET:
1600
return ((sysvar_set_t *)plugin_var)->typelib;
1601
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1602
return ((sessionvar_enum_t *)plugin_var)->typelib;
1603
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1604
return ((sessionvar_set_t *)plugin_var)->typelib;
1612
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1614
unsigned char* result;
1616
result= real_value_ptr(session, type);
1618
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
1619
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
1620
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
1622
char buffer[STRING_BUFFER_USUAL_SIZE];
1623
String str(buffer, sizeof(buffer), system_charset_info);
1624
TYPELIB *typelib= plugin_var_typelib();
1625
uint64_t mask= 1, value= *(uint64_t*) result;
1629
for (i= 0; i < typelib->count; i++, mask<<=1)
1631
if (!(value & mask))
1633
str.append(typelib->type_names[i], typelib->type_lengths[i]);
1637
result= (unsigned char*) "";
1639
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
1645
bool sys_var_pluginvar::check(Session *session, set_var *var)
1647
st_item_value_holder value;
1648
assert(is_readonly() || plugin_var->check);
1650
value.value_type= item_value_type;
1651
value.val_str= item_val_str;
1652
value.val_int= item_val_int;
1653
value.val_real= item_val_real;
1654
value.item= var->value;
1656
return is_readonly() ||
1657
plugin_var->check(session, plugin_var, &var->save_result, &value);
1661
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1666
assert(is_readonly() || plugin_var->update);
1671
pthread_mutex_lock(&LOCK_global_system_variables);
1672
tgt= real_value_ptr(session, type);
1673
src= ((void **) (plugin_var + 1) + 1);
1675
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1677
if (type != OPT_GLOBAL)
1678
src= real_value_ptr(session, OPT_GLOBAL);
1680
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1681
case PLUGIN_VAR_INT:
1682
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1684
case PLUGIN_VAR_LONG:
1685
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1687
case PLUGIN_VAR_LONGLONG:
1688
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1690
case PLUGIN_VAR_ENUM:
1691
src= &((sessionvar_enum_t*) plugin_var)->def_val;
1693
case PLUGIN_VAR_SET:
1694
src= &((sessionvar_set_t*) plugin_var)->def_val;
1696
case PLUGIN_VAR_BOOL:
1697
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1699
case PLUGIN_VAR_STR:
1700
src= &((sessionvar_str_t*) plugin_var)->def_val;
1707
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1708
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1709
session == current_session);
1711
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1713
plugin_var->update(session, plugin_var, tgt, src);
1714
pthread_mutex_unlock(&LOCK_global_system_variables);
1718
pthread_mutex_unlock(&LOCK_global_system_variables);
1719
plugin_var->update(session, plugin_var, tgt, src);
1724
bool sys_var_pluginvar::update(Session *session, set_var *var)
1728
assert(is_readonly() || plugin_var->update);
1730
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1731
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1732
session == current_session);
1737
pthread_mutex_lock(&LOCK_global_system_variables);
1738
tgt= real_value_ptr(session, var->type);
1740
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1742
/* variable we are updating has global scope, so we unlock after updating */
1743
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1744
pthread_mutex_unlock(&LOCK_global_system_variables);
1748
pthread_mutex_unlock(&LOCK_global_system_variables);
1749
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1755
#define OPTION_SET_LIMITS(type, options, opt) \
1756
options->var_type= type; \
1757
options->def_value= (opt)->def_val; \
1758
options->min_value= (opt)->min_val; \
1759
options->max_value= (opt)->max_val; \
1760
options->block_size= (long) (opt)->blk_sz
1763
static void plugin_opt_set_limits(struct my_option *options,
1764
const struct st_mysql_sys_var *opt)
1766
options->sub_size= 0;
1768
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1769
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1770
/* global system variables */
1771
case PLUGIN_VAR_INT:
1772
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1774
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1775
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1777
case PLUGIN_VAR_LONG:
1778
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1780
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1781
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1783
case PLUGIN_VAR_LONGLONG:
1784
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1786
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1787
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1789
case PLUGIN_VAR_ENUM:
1790
options->var_type= GET_ENUM;
1791
options->typelib= ((sysvar_enum_t*) opt)->typelib;
1792
options->def_value= ((sysvar_enum_t*) opt)->def_val;
1793
options->min_value= options->block_size= 0;
1794
options->max_value= options->typelib->count - 1;
1796
case PLUGIN_VAR_SET:
1797
options->var_type= GET_SET;
1798
options->typelib= ((sysvar_set_t*) opt)->typelib;
1799
options->def_value= ((sysvar_set_t*) opt)->def_val;
1800
options->min_value= options->block_size= 0;
1801
options->max_value= (1UL << options->typelib->count) - 1;
1803
case PLUGIN_VAR_BOOL:
1804
options->var_type= GET_BOOL;
1805
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1807
case PLUGIN_VAR_STR:
1808
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1809
GET_STR_ALLOC : GET_STR);
1810
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1812
/* threadlocal variables */
1813
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1814
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1816
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1817
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1819
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1820
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1822
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1823
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1825
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1826
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1828
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1829
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1831
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1832
options->var_type= GET_ENUM;
1833
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
1834
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
1835
options->min_value= options->block_size= 0;
1836
options->max_value= options->typelib->count - 1;
1838
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1839
options->var_type= GET_SET;
1840
options->typelib= ((sessionvar_set_t*) opt)->typelib;
1841
options->def_value= ((sessionvar_set_t*) opt)->def_val;
1842
options->min_value= options->block_size= 0;
1843
options->max_value= (1UL << options->typelib->count) - 1;
1845
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1846
options->var_type= GET_BOOL;
1847
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1849
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1850
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1851
GET_STR_ALLOC : GET_STR);
1852
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1857
options->arg_type= REQUIRED_ARG;
1858
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1859
options->arg_type= NO_ARG;
1860
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1861
options->arg_type= OPT_ARG;
1864
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
1867
bool get_one_plugin_option(int, const struct my_option *, char *)
1873
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
1874
my_option *options, bool can_disable)
1876
const char *plugin_name= tmp->plugin->name;
1877
uint32_t namelen= strlen(plugin_name), optnamelen;
1878
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
1879
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
1881
int index= 0, offset= 0;
1882
st_mysql_sys_var *opt, **plugin_option;
1885
/* support --skip-plugin-foo syntax */
1886
memcpy(name, plugin_name, namelen + 1);
1887
my_casedn_str(&my_charset_utf8_general_ci, name);
1888
sprintf(name+namelen+1, "plugin-%s", name);
1889
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
1891
for (p= name + namelen*2 + 8; p > name; p--)
1897
sprintf(name+namelen*2+10,
1898
"Enable %s plugin. Disable with --skip-%s (will save memory).",
1901
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
1902
20 + namelen + 20 + 1 == namelen * 4 + 67.
1905
options[0].comment= name + namelen*2 + 10;
1908
options[1].name= (options[0].name= name) + namelen + 1;
1909
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
1910
options[0].var_type= options[1].var_type= GET_BOOL;
1911
options[0].arg_type= options[1].arg_type= NO_ARG;
1912
options[0].def_value= options[1].def_value= true;
1913
options[0].value= options[0].u_max_value=
1914
options[1].value= options[1].u_max_value= (char**) (name - 1);
1918
Two passes as the 2nd pass will take pointer addresses for use
1919
by my_getopt and register_var() in the first pass uses realloc
1922
for (plugin_option= tmp->plugin->system_vars;
1923
plugin_option && *plugin_option; plugin_option++, index++)
1925
opt= *plugin_option;
1926
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1928
if (!(register_var(name, opt->name, opt->flags)))
1930
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1931
case PLUGIN_VAR_BOOL:
1932
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1934
case PLUGIN_VAR_INT:
1935
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1937
case PLUGIN_VAR_LONG:
1938
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1940
case PLUGIN_VAR_LONGLONG:
1941
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1943
case PLUGIN_VAR_STR:
1944
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1946
case PLUGIN_VAR_ENUM:
1947
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
1949
case PLUGIN_VAR_SET:
1950
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1953
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1954
opt->flags, plugin_name);
1959
for (plugin_option= tmp->plugin->system_vars;
1960
plugin_option && *plugin_option; plugin_option++, index++)
1962
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1963
case PLUGIN_VAR_BOOL:
1965
opt->check= check_func_bool;
1967
opt->update= update_func_bool;
1969
case PLUGIN_VAR_INT:
1971
opt->check= check_func_int;
1973
opt->update= update_func_int;
1975
case PLUGIN_VAR_LONG:
1977
opt->check= check_func_long;
1979
opt->update= update_func_long;
1981
case PLUGIN_VAR_LONGLONG:
1983
opt->check= check_func_int64_t;
1985
opt->update= update_func_int64_t;
1987
case PLUGIN_VAR_STR:
1989
opt->check= check_func_str;
1992
opt->update= update_func_str;
1993
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1995
opt->flags|= PLUGIN_VAR_READONLY;
1996
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1997
"to be read-only: string variable without "
1998
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1999
opt->name, plugin_name);
2003
case PLUGIN_VAR_ENUM:
2005
opt->check= check_func_enum;
2007
opt->update= update_func_long;
2009
case PLUGIN_VAR_SET:
2011
opt->check= check_func_set;
2013
opt->update= update_func_int64_t;
2016
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2017
opt->flags, plugin_name);
2021
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2022
== PLUGIN_VAR_NOCMDOPT)
2027
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2032
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2034
optnamelen= strlen(opt->name);
2035
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2036
sprintf(optname, "%s-%s", name, opt->name);
2037
optnamelen= namelen + optnamelen + 1;
2041
/* this should not fail because register_var should create entry */
2042
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2044
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2045
"in plugin '%s'."), opt->name, plugin_name);
2049
*(int*)(opt + 1)= offset= v->offset;
2051
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2054
optname= (char*) memdup_root(mem_root, v->key + 1,
2055
(optnamelen= v->name_len) + 1);
2058
/* convert '_' to '-' */
2059
for (p= optname; *p; p++)
2063
options->name= optname;
2064
options->comment= opt->comment;
2065
options->app_type= opt;
2066
options->id= (options-1)->id + 1;
2068
plugin_opt_set_limits(options, opt);
2070
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2071
options->value= options->u_max_value= (char**)
2072
(global_system_variables.dynamic_variables_ptr + offset);
2074
options->value= options->u_max_value= *(char***) (opt + 1);
2076
options[1]= options[0];
2077
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2078
options[1].comment= 0; // hidden
2079
sprintf(p,"plugin-%s",optname);
2088
static my_option *construct_help_options(MEM_ROOT *mem_root,
2089
struct st_plugin_int *p)
2091
st_mysql_sys_var **opt;
2094
uint32_t count= EXTRA_OPTIONS;
2096
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2098
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2101
memset(opts, 0, sizeof(my_option) * count);
2103
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2105
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2111
if (construct_options(mem_root, p, opts, can_disable))