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);
169
/* declared in set_var.cc */
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();
145
235
/****************************************************************************
146
236
Plugin support code
147
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;
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*) calloc(plugin_dl.dl.length, sizeof(char))))
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
strcpy(plugin_dl.dl.str, dl->str);
362
/* Add this dll to array */
363
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
365
free_plugin_mem(&plugin_dl);
366
if (report & REPORT_TO_USER)
367
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
368
if (report & REPORT_TO_LOG)
369
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
376
static void plugin_dl_del(const LEX_STRING *dl)
380
for (i= 0; i < plugin_dl_array.elements; i++)
382
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
383
struct st_plugin_dl **);
384
if (! my_strnncoll(files_charset_info,
385
(const unsigned char *)dl->str, dl->length,
386
(const unsigned char *)tmp->dl.str, tmp->dl.length))
388
/* Do not remove this element, unless no other plugin uses this dll. */
390
free_plugin_mem(tmp);
391
memset(tmp, 0, sizeof(struct st_plugin_dl));
401
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
403
struct st_plugin_int *tmp;
404
if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
406
tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
407
struct st_plugin_int **)=
408
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)plugin,
409
sizeof(struct st_plugin_int));
154
416
Requires that a write-lock is held on LOCK_system_variables_hash
156
static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
157
module::Library *library,
158
po::options_description &long_options)
418
static bool plugin_add(MEM_ROOT *tmp_root,
419
const LEX_STRING *name, const LEX_STRING *dl,
420
int *argc, char **argv, int report)
422
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
424
struct st_plugin_int tmp;
425
struct drizzled_plugin_manifest *plugin;
160
426
if (! initialized)
163
if (registry.find(library->getName()))
429
if (registry.find(name))
165
errmsg_printf(error::WARN, ER(ER_PLUGIN_EXISTS),
166
library->getName().c_str());
431
if (report & REPORT_TO_USER)
432
my_error(ER_UDF_EXISTS, MYF(0), name->str);
433
if (report & REPORT_TO_LOG)
434
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
170
module::Module *tmp= NULL;
437
/* Clear the whole struct to catch future extensions. */
438
memset(&tmp, 0, sizeof(tmp));
439
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
171
441
/* Find plugin by name */
172
const module::Manifest *manifest= library->getManifest();
174
if (registry.find(manifest->name))
176
errmsg_printf(error::ERROR,
177
_("Plugin '%s' contains the name '%s' in its manifest, which "
178
"has already been registered.\n"),
179
library->getName().c_str(),
184
tmp= new (std::nothrow) module::Module(manifest, library);
188
if (!test_plugin_options(tmp_root, tmp, long_options))
193
errmsg_printf(error::ERROR, ER(ER_CANT_FIND_DL_ENTRY),
194
library->getName().c_str());
442
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
444
uint32_t name_len= strlen(plugin->name);
445
if (! my_strnncoll(system_charset_info,
446
(const unsigned char *)name->str, name->length,
447
(const unsigned char *)plugin->name,
450
struct st_plugin_int *tmp_plugin_ptr;
453
tmp.name.str= (char *)plugin->name;
454
tmp.name.length= name_len;
456
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
458
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
460
registry.add(tmp_plugin_ptr);
461
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
464
mysql_del_sys_var_chain(tmp.system_vars);
467
/* plugin was disabled */
472
if (report & REPORT_TO_USER)
473
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
474
if (report & REPORT_TO_LOG)
475
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
482
static void plugin_del(struct st_plugin_int *plugin)
484
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
485
if (plugin->isInited)
487
if (plugin->plugin->status_vars)
489
remove_status_vars(plugin->plugin->status_vars);
492
if (plugin->plugin->deinit)
493
plugin->plugin->deinit(registry);
496
/* Free allocated strings before deleting the plugin. */
497
plugin_vars_free_values(plugin->system_vars);
498
if (plugin->plugin_dl)
499
plugin_dl_del(&plugin->plugin_dl->dl);
500
plugin->isInited= false;
501
pthread_rwlock_wrlock(&LOCK_system_variables_hash);
502
mysql_del_sys_var_chain(plugin->system_vars);
503
pthread_rwlock_unlock(&LOCK_system_variables_hash);
504
free_root(&plugin->mem_root, MYF(0));
507
static void reap_plugins(void)
511
struct st_plugin_int *plugin;
513
count= plugin_array.elements;
515
for (idx= 0; idx < count; idx++)
517
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
522
static bool plugin_initialize(struct st_plugin_int *plugin)
524
assert(plugin->isInited == false);
526
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
527
if (plugin->plugin->init)
529
if (plugin->plugin->init(registry))
531
errmsg_printf(ERRMSG_LVL_ERROR,
532
_("Plugin '%s' init function returned error.\n"),
537
plugin->isInited= true;
539
if (plugin->plugin->status_vars)
541
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
545
set the plugin attribute of plugin's sys vars so they are pointing
548
if (plugin->system_vars)
550
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
554
if (! var->getNext())
556
var= var->getNext()->cast_pluginvar();
199
static void reap_plugins(module::Registry ®istry)
201
std::map<std::string, module::Module *>::const_iterator modules=
202
registry.getModulesMap().begin();
204
while (modules != registry.getModulesMap().end())
206
module::Module *module= (*modules).second;
213
static bool plugin_initialize(module::Registry ®istry,
214
module::Module *module)
216
assert(module->isInited == false);
218
module::Context loading_context(registry, module);
219
if (module->getManifest().init)
221
if (module->getManifest().init(loading_context))
223
errmsg_printf(error::ERROR,
224
_("Plugin '%s' init function returned error.\n"),
225
module->getName().c_str());
229
module->isInited= true;
236
inline static void dashes_to_underscores(std::string &name_in,
237
char from= '-', char to= '_')
239
for (string::iterator p= name_in.begin();
250
inline static void underscores_to_dashes(std::string &name_in)
252
return dashes_to_underscores(name_in, '_', '-');
255
static void compose_plugin_options(vector<string> &target,
256
vector<string> options)
258
for (vector<string>::iterator it= options.begin();
262
tokenize(*it, target, ",", true);
264
for (vector<string>::iterator it= target.begin();
268
dashes_to_underscores(*it);
272
void compose_plugin_add(vector<string> options)
274
compose_plugin_options(opt_plugin_add, options);
277
void compose_plugin_remove(vector<string> options)
279
compose_plugin_options(opt_plugin_remove, options);
282
void notify_plugin_load(string in_plugin_load)
284
tokenize(in_plugin_load, opt_plugin_load, ",", true);
566
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
569
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
571
struct st_bookmark *var= (st_bookmark *)buff;
572
*length= var->name_len + 1;
573
return (unsigned char*) var->key;
288
578
The logic is that we first load and initialize all compiled in plugins.
292
582
Finally we initialize everything, aka the dynamic that have yet to initialize.
294
bool plugin_init(module::Registry ®istry,
295
po::options_description &long_options)
584
int plugin_init(int *argc, char **argv, int flags)
297
memory::Root tmp_root(4096);
587
struct drizzled_plugin_manifest **builtins;
588
struct drizzled_plugin_manifest *plugin;
589
struct st_plugin_int tmp, *plugin_ptr;
595
init_alloc_root(&plugin_mem_root, 4096, 4096);
596
init_alloc_root(&tmp_root, 4096, 4096);
598
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
599
get_bookmark_hash_key, NULL, HASH_UNIQUE))
603
if (my_init_dynamic_array(&plugin_dl_array,
604
sizeof(struct st_plugin_dl *),16,16) ||
605
my_init_dynamic_array(&plugin_array,
606
sizeof(struct st_plugin_int *),16,16))
304
PluginOptions builtin_load_list;
305
tokenize(builtin_load_plugins, builtin_load_list, ",", true);
307
PluginOptions builtin_list;
308
tokenize(builtin_plugins, builtin_list, ",", true);
310
bool load_failed= false;
312
if (opt_plugin_add.size() > 0)
314
for (PluginOptions::iterator iter= opt_plugin_add.begin();
315
iter != opt_plugin_add.end();
318
if (find(builtin_list.begin(),
319
builtin_list.end(), *iter) != builtin_list.end())
321
builtin_load_list.push_back(*iter);
325
opt_plugin_load.push_back(*iter);
330
if (opt_plugin_remove.size() > 0)
332
plugin_prune_list(opt_plugin_load, opt_plugin_remove);
333
plugin_prune_list(builtin_load_list, opt_plugin_remove);
338
612
First we register builtin plugins
340
const set<string> builtin_list_set(builtin_load_list.begin(),
341
builtin_load_list.end());
342
load_failed= plugin_load_list(registry, &tmp_root,
343
builtin_list_set, long_options, true);
614
for (builtins= drizzled_builtins; *builtins; builtins++)
346
tmp_root.free_root(MYF(0));
616
for (plugin= *builtins; plugin->name; plugin++)
618
memset(&tmp, 0, sizeof(tmp));
620
tmp.name.str= (char *)plugin->name;
621
tmp.name.length= strlen(plugin->name);
623
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
624
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
627
if (register_builtin(&tmp, &plugin_ptr))
630
if (plugin_initialize(plugin_ptr))
350
/* Uniquify the list */
351
const set<string> plugin_list_set(opt_plugin_load.begin(),
352
opt_plugin_load.end());
354
637
/* Register all dynamic plugins */
355
load_failed= plugin_load_list(registry, &tmp_root,
356
plugin_list_set, long_options);
638
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
359
tmp_root.free_root(MYF(0));
641
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
363
tmp_root.free_root(MYF(0));
368
bool plugin_finalize(module::Registry ®istry)
644
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
371
648
Now we initialize all remaining plugins
373
module::Registry::ModuleList module_list= registry.getList();
374
module::Registry::ModuleList::iterator modules= module_list.begin();
376
while (modules != module_list.end())
650
for (idx= 0; idx < plugin_array.elements; idx++)
378
module::Module *module= *modules;
380
if (module->isInited == false)
652
plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
653
if (plugin_ptr->isInited == false)
382
if (plugin_initialize(registry, module))
384
registry.remove(module);
655
if (plugin_initialize(plugin_ptr))
656
plugin_del(plugin_ptr);
392
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
394
value.second->prime();
401
Window of opportunity for plugins to issue any queries with the database up and running but with no user's connected.
403
void plugin_startup_window(module::Registry ®istry, drizzled::Session &session)
405
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
407
value.second->startup(session);
412
public unary_function<string, bool>
414
const string to_match;
416
PrunePlugin& operator=(const PrunePlugin&);
418
explicit PrunePlugin(const string &match_in) :
422
result_type operator()(const string &match_against)
424
return match_against == to_match;
428
static void plugin_prune_list(vector<string> &plugin_list,
429
const vector<string> &plugins_to_remove)
431
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
432
iter != plugins_to_remove.end();
435
plugin_list.erase(remove_if(plugin_list.begin(),
662
free_root(&tmp_root, MYF(0));
668
free_root(&tmp_root, MYF(0));
673
static bool register_builtin(struct st_plugin_int *tmp,
674
struct st_plugin_int **ptr)
677
PluginRegistry ®istry= PluginRegistry::getPluginRegistry();
679
tmp->isInited= false;
682
if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
685
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
686
struct st_plugin_int **)=
687
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
688
sizeof(struct st_plugin_int));
443
697
called only by plugin_init()
445
static bool plugin_load_list(module::Registry ®istry,
446
memory::Root *tmp_root,
447
const set<string> &plugin_list,
448
po::options_description &long_options,
699
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
451
module::Library *library= NULL;
453
for (set<string>::const_iterator iter= plugin_list.begin();
454
iter != plugin_list.end();
702
char buffer[FN_REFLEN];
703
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
704
struct st_plugin_dl *plugin_dl;
705
struct drizzled_plugin_manifest *plugin;
457
const string plugin_name(*iter);
459
library= registry.addLibrary(plugin_name, builtin);
709
if (p == buffer + sizeof(buffer) - 1)
462
errmsg_printf(error::ERROR,
463
_("Couldn't load plugin library named '%s'.\n"),
464
plugin_name.c_str());
711
errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
468
tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
469
if (plugin_add(registry, tmp_root, library, long_options))
471
registry.removeLibrary(plugin_name);
472
errmsg_printf(error::ERROR,
473
_("Couldn't load plugin named '%s'.\n"),
474
plugin_name.c_str());
715
switch ((*(p++)= *(list++))) {
717
list= NULL; /* terminate the loop */
719
case ':': /* can't use this as delimiter as it may be drive letter */
721
str->str[str->length]= '\0';
722
if (str == &name) // load all plugins in named module
726
p--; /* reset pointer */
731
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
733
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
735
name.str= (char *) plugin->name;
736
name.length= strlen(name.str);
738
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
739
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
742
plugin_dl_del(&dl); // reduce ref count
747
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
748
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
751
name.length= dl.length= 0;
752
dl.str= NULL; name.str= p= buffer;
759
name.str[name.length]= '\0';
771
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
483
void module_shutdown(module::Registry ®istry)
777
void plugin_shutdown(void)
780
size_t count= plugin_array.elements;
781
vector<st_plugin_int *> plugins;
782
vector<st_plugin_dl *> dl;
488
786
reap_needed= true;
490
reap_plugins(registry);
491
789
unlock_variables(NULL, &global_system_variables);
492
790
unlock_variables(NULL, &max_system_variables);
494
cleanup_variables(&global_system_variables);
495
cleanup_variables(&max_system_variables);
792
cleanup_variables(NULL, &global_system_variables);
793
cleanup_variables(NULL, &max_system_variables);
500
798
/* Dispose of the memory */
501
plugin_mem_root.free_root(MYF(0));
800
delete_dynamic(&plugin_array);
802
count= plugin_dl_array.elements;
804
for (idx= 0; idx < count; idx++)
805
dl.push_back(*dynamic_element(&plugin_dl_array, idx,
806
struct st_plugin_dl **));
807
for (idx= 0; idx < count; idx++)
808
free_plugin_mem(dl[idx]);
809
delete_dynamic(&plugin_dl_array);
811
hash_free(&bookmark_hash);
812
free_root(&plugin_mem_root, MYF(0));
503
814
global_variables_dynamic_size= 0;
817
/****************************************************************************
818
Internal type declarations for variables support
819
****************************************************************************/
821
#undef DRIZZLE_SYSVAR_NAME
822
#define DRIZZLE_SYSVAR_NAME(name) name
823
#define PLUGIN_VAR_TYPEMASK 0x007f
825
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
827
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
828
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
829
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
830
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
832
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
833
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
834
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
835
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
837
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
838
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
839
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
840
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
841
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
842
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
844
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
845
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
846
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
847
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
848
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
849
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
851
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
854
/****************************************************************************
855
default variable data check and update functions
856
****************************************************************************/
858
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
859
void *save, st_mysql_value *value)
861
char buff[STRING_BUFFER_USUAL_SIZE];
862
const char *strvalue= "NULL", *str;
866
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
868
length= sizeof(buff);
869
if (!(str= value->val_str(value, buff, &length)) ||
870
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
879
if (value->val_int(value, &tmp) < 0)
889
*(int*)save= -result;
892
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
897
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
898
void *save, st_mysql_value *value)
902
struct my_option options;
903
value->val_int(value, &tmp);
904
plugin_opt_set_limits(&options, var);
906
if (var->flags & PLUGIN_VAR_UNSIGNED)
907
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
910
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
912
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
913
var->name, (int64_t) tmp);
917
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
918
void *save, st_mysql_value *value)
922
struct my_option options;
923
value->val_int(value, &tmp);
924
plugin_opt_set_limits(&options, var);
926
if (var->flags & PLUGIN_VAR_UNSIGNED)
927
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
930
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
932
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
933
var->name, (int64_t) tmp);
937
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
938
void *save, st_mysql_value *value)
942
struct my_option options;
943
value->val_int(value, &tmp);
944
plugin_opt_set_limits(&options, var);
946
if (var->flags & PLUGIN_VAR_UNSIGNED)
947
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
950
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
952
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
953
var->name, (int64_t) tmp);
956
static int check_func_str(Session *session, struct st_mysql_sys_var *,
957
void *save, st_mysql_value *value)
959
char buff[STRING_BUFFER_USUAL_SIZE];
963
length= sizeof(buff);
964
if ((str= value->val_str(value, buff, &length)))
965
str= session->strmake(str, length);
966
*(const char**)save= str;
971
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
972
void *save, st_mysql_value *value)
974
char buff[STRING_BUFFER_USUAL_SIZE];
975
const char *strvalue= "NULL", *str;
981
if (var->flags & PLUGIN_VAR_SessionLOCAL)
982
typelib= ((sessionvar_enum_t*) var)->typelib;
984
typelib= ((sysvar_enum_t*) var)->typelib;
986
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
988
length= sizeof(buff);
989
if (!(str= value->val_str(value, buff, &length)))
991
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
999
if (value->val_int(value, &tmp))
1001
if (tmp >= typelib->count)
1009
*(long*)save= result;
1012
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1017
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1018
void *save, st_mysql_value *value)
1020
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1021
const char *strvalue= "NULL", *str;
1028
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1029
typelib= ((sessionvar_set_t*) var)->typelib;
1031
typelib= ((sysvar_set_t*)var)->typelib;
1033
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1035
length= sizeof(buff);
1036
if (!(str= value->val_str(value, buff, &length)))
1038
result= find_set(typelib, str, length, NULL,
1039
&error, &error_len, ¬_used);
1042
length= cmin(sizeof(buff), (unsigned long)error_len);
1043
strncpy(buff, error, length);
1051
if (value->val_int(value, (int64_t *)&result))
1053
if (unlikely((result >= (1UL << typelib->count)) &&
1054
(typelib->count < sizeof(long)*8)))
1056
llstr(result, buff);
1061
*(uint64_t*)save= result;
1064
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1069
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1070
void *tgt, const void *save)
1072
*(bool *) tgt= *(int *) save ? 1 : 0;
1076
static void update_func_int(Session *, struct st_mysql_sys_var *,
1077
void *tgt, const void *save)
1079
*(int *)tgt= *(int *) save;
1083
static void update_func_long(Session *, struct st_mysql_sys_var *,
1084
void *tgt, const void *save)
1086
*(long *)tgt= *(long *) save;
1090
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1091
void *tgt, const void *save)
1093
*(int64_t *)tgt= *(uint64_t *) save;
1097
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1098
void *tgt, const void *save)
1100
char *old= *(char **) tgt;
1101
*(char **)tgt= *(char **) save;
1102
if (var->flags & PLUGIN_VAR_MEMALLOC)
1104
*(char **)tgt= strdup(*(char **) save);
1107
* There isn't a _really_ good thing to do here until this whole set_var
1108
* mess gets redesigned
1111
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
507
1117
/****************************************************************************
508
1118
System Variables support
509
1119
****************************************************************************/
1122
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
1125
sys_var_pluginvar *pi= NULL;
1126
st_plugin_int *plugin;
1128
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1129
if ((var= intern_find_sys_var(str, length, false)) &&
1130
(pi= var->cast_pluginvar()))
1132
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1133
if (!(plugin= pi->plugin))
1134
var= NULL; /* failed to lock it, it must be uninstalling */
1135
else if (plugin->isInited == false)
1141
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1144
If the variable exists but the plugin it is associated with is not ready
1145
then the intern_plugin_lock did not raise an error, so we do it here.
1148
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1154
called by register_var, construct_options and test_plugin_options.
1155
Returns the 'bookmark' for the named variable.
1156
LOCK_system_variables_hash should be at least read locked
1158
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1160
st_bookmark *result= NULL;
1161
uint32_t namelen, length, pluginlen= 0;
1164
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1167
namelen= strlen(name);
1169
pluginlen= strlen(plugin) + 1;
1170
length= namelen + pluginlen + 2;
1171
varname= (char*) malloc(length);
1175
sprintf(varname+1,"%s_%s",plugin,name);
1176
for (p= varname + 1; *p; p++)
1181
memcpy(varname + 1, name, namelen + 1);
1183
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1185
result= (st_bookmark*) hash_search(&bookmark_hash,
1186
(const unsigned char*) varname, length - 1);
1194
returns a bookmark for session-local variables, creating if neccessary.
1195
returns null for non session-local variables.
1196
Requires that a write lock is obtained on LOCK_system_variables_hash
1198
static st_bookmark *register_var(const char *plugin, const char *name,
1201
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1202
st_bookmark *result;
1205
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1208
switch (flags & PLUGIN_VAR_TYPEMASK) {
1209
case PLUGIN_VAR_BOOL:
1210
size= ALIGN_SIZE(sizeof(bool));
1212
case PLUGIN_VAR_INT:
1213
size= ALIGN_SIZE(sizeof(int));
1215
case PLUGIN_VAR_LONG:
1216
case PLUGIN_VAR_ENUM:
1217
size= ALIGN_SIZE(sizeof(long));
1219
case PLUGIN_VAR_LONGLONG:
1220
case PLUGIN_VAR_SET:
1221
size= ALIGN_SIZE(sizeof(uint64_t));
1223
case PLUGIN_VAR_STR:
1224
size= ALIGN_SIZE(sizeof(char*));
1231
varname= ((char*) malloc(length));
1232
sprintf(varname+1, "%s_%s", plugin, name);
1233
for (p= varname + 1; *p; p++)
1237
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1239
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1240
sizeof(struct st_bookmark) + length-1);
1241
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1242
memcpy(result->key, varname, length);
1243
result->name_len= length - 2;
1246
assert(size && !(size & (size-1))); /* must be power of 2 */
1248
offset= global_system_variables.dynamic_variables_size;
1249
offset= (offset + size - 1) & ~(size - 1);
1250
result->offset= (int) offset;
1252
new_size= (offset + size + 63) & ~63;
1254
if (new_size > global_variables_dynamic_size)
1258
(char *)realloc(global_system_variables.dynamic_variables_ptr,
1261
global_system_variables.dynamic_variables_ptr= tmpptr;
1264
(char *)realloc(max_system_variables.dynamic_variables_ptr,
1267
max_system_variables.dynamic_variables_ptr= tmpptr;
1270
Clear the new variable value space. This is required for string
1271
variables. If their value is non-NULL, it must point to a valid
1274
memset(global_system_variables.dynamic_variables_ptr +
1275
global_variables_dynamic_size, 0,
1276
new_size - global_variables_dynamic_size);
1277
memset(max_system_variables.dynamic_variables_ptr +
1278
global_variables_dynamic_size, 0,
1279
new_size - global_variables_dynamic_size);
1280
global_variables_dynamic_size= new_size;
1283
global_system_variables.dynamic_variables_head= offset;
1284
max_system_variables.dynamic_variables_head= offset;
1285
global_system_variables.dynamic_variables_size= offset + size;
1286
max_system_variables.dynamic_variables_size= offset + size;
1287
global_system_variables.dynamic_variables_version++;
1288
max_system_variables.dynamic_variables_version++;
1290
result->version= global_system_variables.dynamic_variables_version;
1292
/* this should succeed because we have already checked if a dup exists */
1293
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1295
fprintf(stderr, "failed to add placeholder to hash");
1305
returns a pointer to the memory which holds the session-local variable or
1306
a pointer to the global variable if session==null.
1307
If required, will sync with global variables if the requested variable
1308
has not yet been allocated in the current thread.
1310
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1312
assert(offset >= 0);
1313
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1316
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1319
dynamic_variables_head points to the largest valid offset
1321
if (!session->variables.dynamic_variables_ptr ||
1322
(uint32_t)offset > session->variables.dynamic_variables_head)
1326
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1329
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1330
global_variables_dynamic_size)))
1332
session->variables.dynamic_variables_ptr= tmpptr;
1335
pthread_mutex_lock(&LOCK_global_system_variables);
1337
safe_mutex_assert_owner(&LOCK_global_system_variables);
1339
memcpy(session->variables.dynamic_variables_ptr +
1340
session->variables.dynamic_variables_size,
1341
global_system_variables.dynamic_variables_ptr +
1342
session->variables.dynamic_variables_size,
1343
global_system_variables.dynamic_variables_size -
1344
session->variables.dynamic_variables_size);
1347
now we need to iterate through any newly copied 'defaults'
1348
and if it is a string type with MEMALLOC flag, we need to strdup
1350
for (idx= 0; idx < bookmark_hash.records; idx++)
1352
sys_var_pluginvar *pi;
1354
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1356
if (v->version <= session->variables.dynamic_variables_version ||
1357
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1358
!(pi= var->cast_pluginvar()) ||
1359
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1362
/* Here we do anything special that may be required of the data types */
1364
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1365
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1367
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1368
*(int*)(pi->plugin_var + 1));
1369
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1370
*(int*)(pi->plugin_var + 1))))
1378
pthread_mutex_unlock(&LOCK_global_system_variables);
1380
session->variables.dynamic_variables_version=
1381
global_system_variables.dynamic_variables_version;
1382
session->variables.dynamic_variables_head=
1383
global_system_variables.dynamic_variables_head;
1384
session->variables.dynamic_variables_size=
1385
global_system_variables.dynamic_variables_size;
1387
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1389
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1392
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1394
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1397
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1399
return (int *)intern_sys_var_ptr(a_session, offset, true);
1402
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1404
return (long *)intern_sys_var_ptr(a_session, offset, true);
1407
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1409
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1412
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1414
return (char **)intern_sys_var_ptr(a_session, offset, true);
1417
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1419
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1422
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1424
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
513
1428
void plugin_sessionvar_init(Session *session)
515
1430
session->variables.storage_engine= NULL;
516
cleanup_variables(&session->variables);
1431
cleanup_variables(session, &session->variables);
518
1433
session->variables= global_system_variables;
519
1434
session->variables.storage_engine= NULL;
556
1499
void plugin_sessionvar_cleanup(Session *session)
558
1501
unlock_variables(session, &session->variables);
559
cleanup_variables(&session->variables);
1502
cleanup_variables(session, &session->variables);
1507
@brief Free values of thread variables of a plugin.
1509
This must be called before a plugin is deleted. Otherwise its
1510
variables are no longer accessible and the value space is lost. Note
1511
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1514
@param[in] vars Chain of system variables of a plugin
1517
static void plugin_vars_free_values(sys_var *vars)
1520
for (sys_var *var= vars; var; var= var->getNext())
1522
sys_var_pluginvar *piv= var->cast_pluginvar();
1524
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1525
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1527
/* Free the string from global_system_variables. */
1528
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1537
bool sys_var_pluginvar::check_update_type(Item_result type)
1541
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1542
case PLUGIN_VAR_INT:
1543
case PLUGIN_VAR_LONG:
1544
case PLUGIN_VAR_LONGLONG:
1545
return type != INT_RESULT;
1546
case PLUGIN_VAR_STR:
1547
return type != STRING_RESULT;
1554
SHOW_TYPE sys_var_pluginvar::show_type()
1556
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1557
case PLUGIN_VAR_BOOL:
1558
return SHOW_MY_BOOL;
1559
case PLUGIN_VAR_INT:
1561
case PLUGIN_VAR_LONG:
1563
case PLUGIN_VAR_LONGLONG:
1564
return SHOW_LONGLONG;
1565
case PLUGIN_VAR_STR:
1566
return SHOW_CHAR_PTR;
1567
case PLUGIN_VAR_ENUM:
1568
case PLUGIN_VAR_SET:
1577
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1579
assert(session || (type == OPT_GLOBAL));
1580
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1582
if (type == OPT_GLOBAL)
1585
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1587
return *(unsigned char**) (plugin_var+1);
1591
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1593
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1594
case PLUGIN_VAR_ENUM:
1595
return ((sysvar_enum_t *)plugin_var)->typelib;
1596
case PLUGIN_VAR_SET:
1597
return ((sysvar_set_t *)plugin_var)->typelib;
1598
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1599
return ((sessionvar_enum_t *)plugin_var)->typelib;
1600
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1601
return ((sessionvar_set_t *)plugin_var)->typelib;
1609
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1611
unsigned char* result;
1613
result= real_value_ptr(session, type);
1615
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
1616
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
1617
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
1619
char buffer[STRING_BUFFER_USUAL_SIZE];
1620
String str(buffer, sizeof(buffer), system_charset_info);
1621
TYPELIB *typelib= plugin_var_typelib();
1622
uint64_t mask= 1, value= *(uint64_t*) result;
1626
for (i= 0; i < typelib->count; i++, mask<<=1)
1628
if (!(value & mask))
1630
str.append(typelib->type_names[i], typelib->type_lengths[i]);
1634
result= (unsigned char*) "";
1636
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
1642
bool sys_var_pluginvar::check(Session *session, set_var *var)
1644
st_item_value_holder value;
1645
assert(is_readonly() || plugin_var->check);
1647
value.value_type= item_value_type;
1648
value.val_str= item_val_str;
1649
value.val_int= item_val_int;
1650
value.val_real= item_val_real;
1651
value.item= var->value;
1653
return is_readonly() ||
1654
plugin_var->check(session, plugin_var, &var->save_result, &value);
1658
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1663
assert(is_readonly() || plugin_var->update);
1668
pthread_mutex_lock(&LOCK_global_system_variables);
1669
tgt= real_value_ptr(session, type);
1670
src= ((void **) (plugin_var + 1) + 1);
1672
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1674
if (type != OPT_GLOBAL)
1675
src= real_value_ptr(session, OPT_GLOBAL);
1677
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1678
case PLUGIN_VAR_INT:
1679
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1681
case PLUGIN_VAR_LONG:
1682
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1684
case PLUGIN_VAR_LONGLONG:
1685
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1687
case PLUGIN_VAR_ENUM:
1688
src= &((sessionvar_enum_t*) plugin_var)->def_val;
1690
case PLUGIN_VAR_SET:
1691
src= &((sessionvar_set_t*) plugin_var)->def_val;
1693
case PLUGIN_VAR_BOOL:
1694
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1696
case PLUGIN_VAR_STR:
1697
src= &((sessionvar_str_t*) plugin_var)->def_val;
1704
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1705
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1706
session == current_session);
1708
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1710
plugin_var->update(session, plugin_var, tgt, src);
1711
pthread_mutex_unlock(&LOCK_global_system_variables);
1715
pthread_mutex_unlock(&LOCK_global_system_variables);
1716
plugin_var->update(session, plugin_var, tgt, src);
1721
bool sys_var_pluginvar::update(Session *session, set_var *var)
1725
assert(is_readonly() || plugin_var->update);
1727
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1728
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1729
session == current_session);
1734
pthread_mutex_lock(&LOCK_global_system_variables);
1735
tgt= real_value_ptr(session, var->type);
1737
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1739
/* variable we are updating has global scope, so we unlock after updating */
1740
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1741
pthread_mutex_unlock(&LOCK_global_system_variables);
1745
pthread_mutex_unlock(&LOCK_global_system_variables);
1746
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1752
#define OPTION_SET_LIMITS(type, options, opt) \
1753
options->var_type= type; \
1754
options->def_value= (opt)->def_val; \
1755
options->min_value= (opt)->min_val; \
1756
options->max_value= (opt)->max_val; \
1757
options->block_size= (long) (opt)->blk_sz
1760
static void plugin_opt_set_limits(struct my_option *options,
1761
const struct st_mysql_sys_var *opt)
1763
options->sub_size= 0;
1765
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1766
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1767
/* global system variables */
1768
case PLUGIN_VAR_INT:
1769
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1771
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1772
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1774
case PLUGIN_VAR_LONG:
1775
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1777
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1778
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1780
case PLUGIN_VAR_LONGLONG:
1781
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1783
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1784
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1786
case PLUGIN_VAR_ENUM:
1787
options->var_type= GET_ENUM;
1788
options->typelib= ((sysvar_enum_t*) opt)->typelib;
1789
options->def_value= ((sysvar_enum_t*) opt)->def_val;
1790
options->min_value= options->block_size= 0;
1791
options->max_value= options->typelib->count - 1;
1793
case PLUGIN_VAR_SET:
1794
options->var_type= GET_SET;
1795
options->typelib= ((sysvar_set_t*) opt)->typelib;
1796
options->def_value= ((sysvar_set_t*) opt)->def_val;
1797
options->min_value= options->block_size= 0;
1798
options->max_value= (1UL << options->typelib->count) - 1;
1800
case PLUGIN_VAR_BOOL:
1801
options->var_type= GET_BOOL;
1802
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1804
case PLUGIN_VAR_STR:
1805
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1806
GET_STR_ALLOC : GET_STR);
1807
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1809
/* threadlocal variables */
1810
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1811
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1813
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1814
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1816
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1817
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1819
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1820
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1822
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1823
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1825
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1826
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1828
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1829
options->var_type= GET_ENUM;
1830
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
1831
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
1832
options->min_value= options->block_size= 0;
1833
options->max_value= options->typelib->count - 1;
1835
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1836
options->var_type= GET_SET;
1837
options->typelib= ((sessionvar_set_t*) opt)->typelib;
1838
options->def_value= ((sessionvar_set_t*) opt)->def_val;
1839
options->min_value= options->block_size= 0;
1840
options->max_value= (1UL << options->typelib->count) - 1;
1842
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1843
options->var_type= GET_BOOL;
1844
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1846
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1847
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1848
GET_STR_ALLOC : GET_STR);
1849
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1854
options->arg_type= REQUIRED_ARG;
1855
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1856
options->arg_type= NO_ARG;
1857
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1858
options->arg_type= OPT_ARG;
1861
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
1864
bool get_one_plugin_option(int, const struct my_option *, char *)
1870
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
1871
my_option *options, bool can_disable)
1873
const char *plugin_name= tmp->plugin->name;
1874
uint32_t namelen= strlen(plugin_name), optnamelen;
1875
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
1876
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
1878
int index= 0, offset= 0;
1879
st_mysql_sys_var *opt, **plugin_option;
1882
/* support --skip-plugin-foo syntax */
1883
memcpy(name, plugin_name, namelen + 1);
1884
my_casedn_str(&my_charset_utf8_general_ci, name);
1885
sprintf(name+namelen+1, "plugin-%s", name);
1886
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
1888
for (p= name + namelen*2 + 8; p > name; p--)
1894
sprintf(name+namelen*2+10,
1895
"Enable %s plugin. Disable with --skip-%s (will save memory).",
1898
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
1899
20 + namelen + 20 + 1 == namelen * 4 + 67.
1902
options[0].comment= name + namelen*2 + 10;
1905
options[1].name= (options[0].name= name) + namelen + 1;
1906
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
1907
options[0].var_type= options[1].var_type= GET_BOOL;
1908
options[0].arg_type= options[1].arg_type= NO_ARG;
1909
options[0].def_value= options[1].def_value= true;
1910
options[0].value= options[0].u_max_value=
1911
options[1].value= options[1].u_max_value= (char**) (name - 1);
1915
Two passes as the 2nd pass will take pointer addresses for use
1916
by my_getopt and register_var() in the first pass uses realloc
1919
for (plugin_option= tmp->plugin->system_vars;
1920
plugin_option && *plugin_option; plugin_option++, index++)
1922
opt= *plugin_option;
1923
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1925
if (!(register_var(name, opt->name, opt->flags)))
1927
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1928
case PLUGIN_VAR_BOOL:
1929
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1931
case PLUGIN_VAR_INT:
1932
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1934
case PLUGIN_VAR_LONG:
1935
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1937
case PLUGIN_VAR_LONGLONG:
1938
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1940
case PLUGIN_VAR_STR:
1941
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1943
case PLUGIN_VAR_ENUM:
1944
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
1946
case PLUGIN_VAR_SET:
1947
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1950
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1951
opt->flags, plugin_name);
1956
for (plugin_option= tmp->plugin->system_vars;
1957
plugin_option && *plugin_option; plugin_option++, index++)
1959
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1960
case PLUGIN_VAR_BOOL:
1962
opt->check= check_func_bool;
1964
opt->update= update_func_bool;
1966
case PLUGIN_VAR_INT:
1968
opt->check= check_func_int;
1970
opt->update= update_func_int;
1972
case PLUGIN_VAR_LONG:
1974
opt->check= check_func_long;
1976
opt->update= update_func_long;
1978
case PLUGIN_VAR_LONGLONG:
1980
opt->check= check_func_int64_t;
1982
opt->update= update_func_int64_t;
1984
case PLUGIN_VAR_STR:
1986
opt->check= check_func_str;
1989
opt->update= update_func_str;
1990
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1992
opt->flags|= PLUGIN_VAR_READONLY;
1993
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1994
"to be read-only: string variable without "
1995
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1996
opt->name, plugin_name);
2000
case PLUGIN_VAR_ENUM:
2002
opt->check= check_func_enum;
2004
opt->update= update_func_long;
2006
case PLUGIN_VAR_SET:
2008
opt->check= check_func_set;
2010
opt->update= update_func_int64_t;
2013
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2014
opt->flags, plugin_name);
2018
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2019
== PLUGIN_VAR_NOCMDOPT)
2024
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2029
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2031
optnamelen= strlen(opt->name);
2032
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2033
sprintf(optname, "%s-%s", name, opt->name);
2034
optnamelen= namelen + optnamelen + 1;
2038
/* this should not fail because register_var should create entry */
2039
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2041
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2042
"in plugin '%s'."), opt->name, plugin_name);
2046
*(int*)(opt + 1)= offset= v->offset;
2048
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2051
optname= (char*) memdup_root(mem_root, v->key + 1,
2052
(optnamelen= v->name_len) + 1);
2055
/* convert '_' to '-' */
2056
for (p= optname; *p; p++)
2060
options->name= optname;
2061
options->comment= opt->comment;
2062
options->app_type= opt;
2063
options->id= (options-1)->id + 1;
2065
plugin_opt_set_limits(options, opt);
2067
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2068
options->value= options->u_max_value= (char**)
2069
(global_system_variables.dynamic_variables_ptr + offset);
2071
options->value= options->u_max_value= *(char***) (opt + 1);
2073
options[1]= options[0];
2074
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2075
options[1].comment= 0; // hidden
2076
sprintf(p,"plugin-%s",optname);
2085
static my_option *construct_help_options(MEM_ROOT *mem_root,
2086
struct st_plugin_int *p)
2088
st_mysql_sys_var **opt;
2091
uint32_t count= EXTRA_OPTIONS;
2093
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2095
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2098
memset(opts, 0, sizeof(my_option) * count);
2100
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2102
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2108
if (construct_options(mem_root, p, opts, can_disable))