95
80
write-lock on LOCK_system_variables_hash is required before modifying
96
81
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
83
static MEM_ROOT plugin_mem_root;
99
84
static uint32_t global_variables_dynamic_size= 0;
85
static HASH bookmark_hash;
103
89
hidden part of opaque value passed to variable check functions.
104
90
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
92
struct st_item_value_holder : public st_mysql_value
99
stored in bookmark_hash, this structure is never removed from the
100
hash and is used to mark a single offset for a session local variable
101
even if plugins have been uninstalled and reinstalled, repeatedly.
102
This structure is allocated from plugin_mem_root.
104
The key format is as follows:
105
1 byte - variable type code
106
name_len bytes - variable name
122
113
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
119
skeleton of a plugin variable - portion of structure common to all.
121
struct st_mysql_sys_var
123
DRIZZLE_PLUGIN_VAR_HEADER;
128
sys_var class for access to all plugin variables visible to the user
130
class sys_var_pluginvar: public sys_var
133
plugin::Module *plugin;
134
struct st_mysql_sys_var *plugin_var;
136
sys_var_pluginvar(const std::string name_arg,
137
struct st_mysql_sys_var *plugin_var_arg)
138
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
139
sys_var_pluginvar *cast_pluginvar() { return this; }
140
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
141
bool check_type(enum_var_type type)
142
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
143
bool check_update_type(Item_result type);
144
SHOW_TYPE show_type();
145
unsigned char* real_value_ptr(Session *session, enum_var_type type);
146
TYPELIB* plugin_var_typelib(void);
147
unsigned char* value_ptr(Session *session, enum_var_type type,
148
const LEX_STRING *base);
149
bool check(Session *session, set_var *var);
150
bool check_default(enum_var_type)
151
{ return is_readonly(); }
152
void set_default(Session *session, enum_var_type);
153
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);
158
static bool plugin_load_list(plugin::Registry ®istry,
159
MEM_ROOT *tmp_root, int *argc, char **argv,
161
static int test_plugin_options(MEM_ROOT *, plugin::Module *,
163
static bool register_builtin(plugin::Registry ®istry,
166
static void unlock_variables(Session *session, struct system_variables *vars);
167
static void cleanup_variables(Session *session, struct system_variables *vars);
168
static void plugin_vars_free_values(sys_var *vars);
169
static void plugin_opt_set_limits(struct my_option *options,
170
const struct st_mysql_sys_var *opt);
171
static void reap_plugins(plugin::Registry &plugins);
144
174
/* declared in set_var.cc */
145
175
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
176
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
177
const std::string &name, int64_t val);
179
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
180
const char *name, int64_t val)
182
const std::string name_str(name);
183
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
186
/****************************************************************************
187
Value type thunks, allows the C world to play in the C++ world
188
****************************************************************************/
190
static int item_value_type(struct st_mysql_value *value)
192
switch (((st_item_value_holder*)value)->item->result_type()) {
194
return DRIZZLE_VALUE_TYPE_INT;
196
return DRIZZLE_VALUE_TYPE_REAL;
198
return DRIZZLE_VALUE_TYPE_STRING;
202
static const char *item_val_str(struct st_mysql_value *value,
203
char *buffer, int *length)
205
String str(buffer, *length, system_charset_info), *res;
206
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
208
*length= res->length();
209
if (res->c_ptr_quick() == buffer)
213
Lets be nice and create a temporary string since the
216
return current_session->strmake(res->c_ptr_quick(), res->length());
220
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
222
Item *item= ((st_item_value_holder*)value)->item;
223
*buf= item->val_int();
230
static int item_val_real(struct st_mysql_value *value, double *buf)
232
Item *item= ((st_item_value_holder*)value)->item;
233
*buf= item->val_real();
148
240
/****************************************************************************
149
241
Plugin support code
150
242
****************************************************************************/
244
static plugin::Library *plugin_dl_find(const LEX_STRING *dl)
247
plugin::Library *tmp;
249
for (i= 0; i < plugin_dl_array.elements; i++)
251
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
252
if (! my_strnncoll(files_charset_info,
253
(const unsigned char *)dl->str, dl->length,
254
(const unsigned char *)tmp->dl.str, tmp->dl.length))
260
static plugin::Library *plugin_dl_insert_or_reuse(plugin::Library *plugin_dl)
263
plugin::Library *tmp;
265
for (i= 0; i < plugin_dl_array.elements; i++)
267
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
269
memcpy(tmp, plugin_dl, sizeof(plugin::Library));
273
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
275
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
277
(plugin::Library *) memdup_root(&plugin_mem_root,
278
(unsigned char*)plugin_dl,
279
sizeof(plugin::Library));
283
static inline void free_plugin_mem(plugin::Library *p)
291
static plugin::Library *plugin_dl_add(const LEX_STRING *dl, int report)
294
uint32_t plugin_dir_len;
295
plugin::Library *tmp, plugin_dl;
297
plugin_dir_len= strlen(opt_plugin_dir);
298
dlpath.reserve(FN_REFLEN);
300
Ensure that the dll doesn't have a path.
301
This is done to ensure that only approved libraries from the
302
plugin directory are used (to make this even remotely secure).
304
if (strchr(dl->str, FN_LIBCHAR) ||
305
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
306
system_charset_info, 1) ||
307
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
309
if (report & REPORT_TO_USER)
310
my_error(ER_UDF_NO_PATHS, MYF(0));
311
if (report & REPORT_TO_LOG)
312
errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
315
/* If this dll is already loaded just increase ref_count. */
316
if ((tmp= plugin_dl_find(dl)))
320
memset(&plugin_dl, 0, sizeof(plugin_dl));
321
/* Compile dll path */
322
dlpath.append(opt_plugin_dir);
324
dlpath.append(dl->str);
325
/* Open new dll handle */
326
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
328
const char *errmsg=dlerror();
329
uint32_t dlpathlen= dlpath.length();
330
if (!dlpath.compare(0, dlpathlen, errmsg))
331
{ // if errmsg starts from dlpath, trim this prefix.
333
if (*errmsg == ':') errmsg++;
334
if (*errmsg == ' ') errmsg++;
336
if (report & REPORT_TO_USER)
337
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
338
if (report & REPORT_TO_LOG)
339
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
343
/* Find plugin declarations */
344
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
346
free_plugin_mem(&plugin_dl);
347
if (report & REPORT_TO_USER)
348
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
349
if (report & REPORT_TO_LOG)
350
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
354
plugin_dl.plugins= static_cast<plugin::Manifest *>(sym);
356
/* Duplicate and convert dll name */
357
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
358
if (! (plugin_dl.dl.str= (char*) calloc(plugin_dl.dl.length, sizeof(char))))
360
free_plugin_mem(&plugin_dl);
361
if (report & REPORT_TO_USER)
362
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
363
if (report & REPORT_TO_LOG)
364
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
367
strcpy(plugin_dl.dl.str, dl->str);
368
/* Add this dll to array */
369
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
371
free_plugin_mem(&plugin_dl);
372
if (report & REPORT_TO_USER)
373
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(plugin::Library));
374
if (report & REPORT_TO_LOG)
375
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY),
376
sizeof(plugin::Library));
383
static void plugin_dl_del(const LEX_STRING *dl)
387
for (i= 0; i < plugin_dl_array.elements; i++)
389
plugin::Library *tmp= *dynamic_element(&plugin_dl_array, i,
391
if (! my_strnncoll(files_charset_info,
392
(const unsigned char *)dl->str, dl->length,
393
(const unsigned char *)tmp->dl.str, tmp->dl.length))
395
/* Do not remove this element, unless no other plugin uses this dll. */
397
free_plugin_mem(tmp);
398
memset(tmp, 0, sizeof(plugin::Library));
408
static plugin::Module *plugin_insert_or_reuse(plugin::Module *module)
410
if (insert_dynamic(&module_array, (unsigned char*)&module))
412
module= *dynamic_element(&module_array, module_array.elements - 1,
157
420
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)
422
static bool plugin_add(plugin::Registry ®istry, MEM_ROOT *tmp_root,
423
const LEX_STRING *name, const LEX_STRING *dl,
424
int *argc, char **argv, int report)
426
plugin::Manifest *manifest;
163
427
if (! initialized)
166
if (registry.find(library->getName()))
430
if (registry.find(name))
168
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
169
library->getName().c_str());
432
if (report & REPORT_TO_USER)
433
my_error(ER_UDF_EXISTS, MYF(0), name->str);
434
if (report & REPORT_TO_LOG)
435
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
438
plugin::Library *library= plugin_dl_add(dl, report);
173
module::Module *tmp= NULL;
442
plugin::Module *tmp= NULL;
174
443
/* Find plugin by name */
175
const module::Manifest *manifest= library->getManifest();
177
if (registry.find(manifest->name))
179
errmsg_printf(ERRMSG_LVL_ERROR,
180
_("Plugin '%s' contains the name '%s' in its manifest, which "
181
"has already been registered.\n"),
182
library->getName().c_str(),
187
tmp= new (std::nothrow) module::Module(manifest, library);
191
if (!test_plugin_options(tmp_root, tmp, long_options))
196
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY),
197
library->getName().c_str());
202
static void reap_plugins(module::Registry ®istry)
204
std::map<std::string, module::Module *>::const_iterator modules=
205
registry.getModulesMap().begin();
207
while (modules != registry.getModulesMap().end())
209
module::Module *module= (*modules).second;
216
static bool plugin_initialize(module::Registry ®istry,
217
module::Module *module)
444
for (manifest= library->plugins; manifest->name; manifest++)
446
if (! my_strnncoll(system_charset_info,
447
(const unsigned char *)name->str, name->length,
448
(const unsigned char *)manifest->name,
449
strlen(manifest->name)))
451
tmp= new (std::nothrow) plugin::Module(manifest, library);
455
if (!test_plugin_options(tmp_root, tmp, argc, argv))
457
if ((tmp= plugin_insert_or_reuse(tmp)))
460
init_alloc_root(&tmp->mem_root, 4096, 4096);
463
mysql_del_sys_var_chain(tmp->system_vars);
466
/* plugin was disabled */
471
if (report & REPORT_TO_USER)
472
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
473
if (report & REPORT_TO_LOG)
474
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
481
static void delete_module(plugin::Registry ®istry, plugin::Module *module)
483
plugin::Manifest manifest= module->getManifest();
485
if (module->isInited)
487
if (manifest.status_vars)
489
remove_status_vars(manifest.status_vars);
493
manifest.deinit(registry);
496
/* Free allocated strings before deleting the plugin. */
497
plugin_vars_free_values(module->system_vars);
498
if (module->plugin_dl)
499
plugin_dl_del(&module->plugin_dl->dl);
500
module->isInited= false;
501
pthread_rwlock_wrlock(&LOCK_system_variables_hash);
502
mysql_del_sys_var_chain(module->system_vars);
503
pthread_rwlock_unlock(&LOCK_system_variables_hash);
507
static void reap_plugins(plugin::Registry &plugins)
511
plugin::Module *module;
513
count= module_array.elements;
515
for (idx= 0; idx < count; idx++)
517
module= *dynamic_element(&module_array, idx, plugin::Module **);
518
delete_module(plugins, module);
520
drizzle_del_plugin_sysvar();
524
static void plugin_initialize_vars(plugin::Module *module)
526
if (module->getManifest().status_vars)
528
add_status_vars(module->getManifest().status_vars); // add_status_vars makes a copy
532
set the plugin attribute of plugin's sys vars so they are pointing
535
if (module->system_vars)
537
sys_var_pluginvar *var= module->system_vars->cast_pluginvar();
541
if (! var->getNext())
543
var= var->getNext()->cast_pluginvar();
549
static bool plugin_initialize(plugin::Registry ®istry,
550
plugin::Module *module)
219
552
assert(module->isInited == false);
221
module::Context loading_context(registry, module);
554
registry.setCurrentModule(module);
222
555
if (module->getManifest().init)
224
if (module->getManifest().init(loading_context))
557
if (module->getManifest().init(registry))
226
559
errmsg_printf(ERRMSG_LVL_ERROR,
227
560
_("Plugin '%s' init function returned error.\n"),
295
589
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)
591
int plugin_init(plugin::Registry ®istry, int *argc, char **argv, int flags)
300
memory::Root tmp_root(4096);
594
plugin::Manifest **builtins;
595
plugin::Manifest *manifest;
596
plugin::Module *module;
602
init_alloc_root(&plugin_mem_root, 4096, 4096);
603
init_alloc_root(&tmp_root, 4096, 4096);
605
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
606
get_bookmark_hash_key, NULL, HASH_UNIQUE))
610
if (my_init_dynamic_array(&plugin_dl_array,
611
sizeof(plugin::Library *),16,16) ||
612
my_init_dynamic_array(&module_array,
613
sizeof(plugin::Module *),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
619
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);
621
for (builtins= drizzled_builtins; *builtins; builtins++)
349
tmp_root.free_root(MYF(0));
623
for (manifest= *builtins; manifest->name; manifest++)
625
module= new (std::nothrow) plugin::Module(manifest);
629
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
630
if (test_plugin_options(&tmp_root, module, argc, argv))
633
if (register_builtin(registry, module, &module))
636
plugin_initialize_vars(module);
638
if (! (flags & PLUGIN_INIT_SKIP_INITIALIZATION))
640
if (plugin_initialize(registry, module))
353
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
357
647
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
648
if (! (flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
362
tmp_root.free_root(MYF(0));
651
plugin_load_list(registry, &tmp_root, argc, argv, opt_plugin_load);
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
654
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
374
658
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())
660
for (idx= 0; idx < module_array.elements; idx++)
381
module::Module *module= (*modules).second;
662
module= *dynamic_element(&module_array, idx, plugin::Module **);
383
663
if (module->isInited == false)
665
plugin_initialize_vars(module);
385
667
if (plugin_initialize(registry, module))
387
registry.remove(module);
668
delete_module(registry, module);
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(),
674
free_root(&tmp_root, MYF(0));
680
free_root(&tmp_root, MYF(0));
685
static bool register_builtin(plugin::Registry ®istry,
687
plugin::Module **ptr)
690
tmp->isInited= false;
693
if (insert_dynamic(&module_array, (unsigned char*)&tmp))
696
*ptr= *dynamic_element(&module_array, module_array.elements - 1,
434
706
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,
708
static bool plugin_load_list(plugin::Registry &plugins,
709
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();
712
char buffer[FN_REFLEN];
713
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
714
plugin::Library *plugin_dl;
715
plugin::Manifest *plugin;
448
const string plugin_name(*iter);
450
library= registry.addLibrary(plugin_name, builtin);
719
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());
721
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());
725
switch ((*(p++)= *(list++))) {
727
list= NULL; /* terminate the loop */
729
case ':': /* can't use this as delimiter as it may be drive letter */
731
str->str[str->length]= '\0';
732
if (str == &name) // load all plugins in named module
736
p--; /* reset pointer */
741
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
743
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
745
name.str= (char *) plugin->name;
746
name.length= strlen(name.str);
748
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
749
if (plugin_add(plugins, tmp_root, &name, &dl,
750
argc, argv, REPORT_TO_LOG))
753
plugin_dl_del(&dl); // reduce ref count
758
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
759
if (plugin_add(plugins, tmp_root, &name, &dl,
760
argc, argv, REPORT_TO_LOG))
763
name.length= dl.length= 0;
764
dl.str= NULL; name.str= p= buffer;
771
name.str[name.length]= '\0';
783
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
474
void module_shutdown(module::Registry ®istry)
789
void plugin_shutdown(plugin::Registry ®istry)
792
size_t count= module_array.elements;
793
vector<plugin::Library *> dl;
482
800
unlock_variables(NULL, &global_system_variables);
483
801
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
803
cleanup_variables(NULL, &global_system_variables);
804
cleanup_variables(NULL, &max_system_variables);
491
809
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
811
delete_dynamic(&module_array);
813
count= plugin_dl_array.elements;
815
for (idx= 0; idx < count; idx++)
816
dl.push_back(*dynamic_element(&plugin_dl_array, idx,
817
plugin::Library **));
818
for (idx= 0; idx < count; idx++)
819
free_plugin_mem(dl[idx]);
820
delete_dynamic(&plugin_dl_array);
822
hash_free(&bookmark_hash);
823
free_root(&plugin_mem_root, MYF(0));
494
825
global_variables_dynamic_size= 0;
828
/****************************************************************************
829
Internal type declarations for variables support
830
****************************************************************************/
832
#undef DRIZZLE_SYSVAR_NAME
833
#define DRIZZLE_SYSVAR_NAME(name) name
834
#define PLUGIN_VAR_TYPEMASK 0x007f
836
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
838
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
839
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
840
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
841
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
843
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
844
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
845
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
846
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
848
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
849
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
850
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
851
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
852
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
853
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
855
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
856
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
857
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
858
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
859
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
860
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
862
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
865
/****************************************************************************
866
default variable data check and update functions
867
****************************************************************************/
869
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
870
void *save, st_mysql_value *value)
872
char buff[STRING_BUFFER_USUAL_SIZE];
873
const char *strvalue= "NULL", *str;
877
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
879
length= sizeof(buff);
880
if (!(str= value->val_str(value, buff, &length)) ||
881
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
890
if (value->val_int(value, &tmp) < 0)
900
*(int*)save= -result;
903
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
908
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
909
void *save, st_mysql_value *value)
913
struct my_option options;
914
value->val_int(value, &tmp);
915
plugin_opt_set_limits(&options, var);
917
if (var->flags & PLUGIN_VAR_UNSIGNED)
918
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
921
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
923
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
924
var->name, (int64_t) tmp);
928
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
929
void *save, st_mysql_value *value)
933
struct my_option options;
934
value->val_int(value, &tmp);
935
plugin_opt_set_limits(&options, var);
937
if (var->flags & PLUGIN_VAR_UNSIGNED)
938
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
941
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
943
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
944
var->name, (int64_t) tmp);
948
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
949
void *save, st_mysql_value *value)
953
struct my_option options;
954
value->val_int(value, &tmp);
955
plugin_opt_set_limits(&options, var);
957
if (var->flags & PLUGIN_VAR_UNSIGNED)
958
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
961
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
963
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
964
var->name, (int64_t) tmp);
967
static int check_func_str(Session *session, struct st_mysql_sys_var *,
968
void *save, st_mysql_value *value)
970
char buff[STRING_BUFFER_USUAL_SIZE];
974
length= sizeof(buff);
975
if ((str= value->val_str(value, buff, &length)))
976
str= session->strmake(str, length);
977
*(const char**)save= str;
982
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
983
void *save, st_mysql_value *value)
985
char buff[STRING_BUFFER_USUAL_SIZE];
986
const char *strvalue= "NULL", *str;
992
if (var->flags & PLUGIN_VAR_SessionLOCAL)
993
typelib= ((sessionvar_enum_t*) var)->typelib;
995
typelib= ((sysvar_enum_t*) var)->typelib;
997
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
999
length= sizeof(buff);
1000
if (!(str= value->val_str(value, buff, &length)))
1002
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1010
if (value->val_int(value, &tmp))
1012
if (tmp >= typelib->count)
1020
*(long*)save= result;
1023
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1028
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1029
void *save, st_mysql_value *value)
1031
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1032
const char *strvalue= "NULL", *str;
1039
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1040
typelib= ((sessionvar_set_t*) var)->typelib;
1042
typelib= ((sysvar_set_t*)var)->typelib;
1044
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1046
length= sizeof(buff);
1047
if (!(str= value->val_str(value, buff, &length)))
1049
result= find_set(typelib, str, length, NULL,
1050
&error, &error_len, ¬_used);
1053
length= min((uint32_t)sizeof(buff), error_len);
1054
strncpy(buff, error, length);
1062
if (value->val_int(value, (int64_t *)&result))
1064
if (unlikely((result >= (1UL << typelib->count)) &&
1065
(typelib->count < sizeof(long)*8)))
1067
llstr(result, buff);
1072
*(uint64_t*)save= result;
1075
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1080
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1081
void *tgt, const void *save)
1083
*(bool *) tgt= *(int *) save ? 1 : 0;
1087
static void update_func_int(Session *, struct st_mysql_sys_var *,
1088
void *tgt, const void *save)
1090
*(int *)tgt= *(int *) save;
1094
static void update_func_long(Session *, struct st_mysql_sys_var *,
1095
void *tgt, const void *save)
1097
*(long *)tgt= *(long *) save;
1101
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1102
void *tgt, const void *save)
1104
*(int64_t *)tgt= *(uint64_t *) save;
1108
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1109
void *tgt, const void *save)
1111
char *old= *(char **) tgt;
1112
*(char **)tgt= *(char **) save;
1113
if (var->flags & PLUGIN_VAR_MEMALLOC)
1115
*(char **)tgt= strdup(*(char **) save);
1118
* There isn't a _really_ good thing to do here until this whole set_var
1119
* mess gets redesigned
1122
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
1128
/****************************************************************************
499
1129
System Variables support
500
1130
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
1133
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
1136
sys_var_pluginvar *pi= NULL;
1137
plugin::Module *module;
1139
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1140
if ((var= intern_find_sys_var(str, length, false)) &&
1141
(pi= var->cast_pluginvar()))
1143
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1144
if (!(module= pi->plugin))
1145
var= NULL; /* failed to lock it, it must be uninstalling */
1146
else if (module->isInited == false)
1152
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1155
If the variable exists but the plugin it is associated with is not ready
1156
then the intern_plugin_lock did not raise an error, so we do it here.
1159
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1165
called by register_var, construct_options and test_plugin_options.
1166
Returns the 'bookmark' for the named variable.
1167
LOCK_system_variables_hash should be at least read locked
1169
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1171
st_bookmark *result= NULL;
1172
uint32_t namelen, length, pluginlen= 0;
1175
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1178
namelen= strlen(name);
1180
pluginlen= strlen(plugin) + 1;
1181
length= namelen + pluginlen + 2;
1182
varname= (char*) malloc(length);
1186
sprintf(varname+1,"%s_%s",plugin,name);
1187
for (p= varname + 1; *p; p++)
1192
memcpy(varname + 1, name, namelen + 1);
1194
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1196
result= (st_bookmark*) hash_search(&bookmark_hash,
1197
(const unsigned char*) varname, length - 1);
1205
returns a bookmark for session-local variables, creating if neccessary.
1206
returns null for non session-local variables.
1207
Requires that a write lock is obtained on LOCK_system_variables_hash
1209
static st_bookmark *register_var(const char *plugin, const char *name,
1212
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1213
st_bookmark *result;
1216
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1219
switch (flags & PLUGIN_VAR_TYPEMASK) {
1220
case PLUGIN_VAR_BOOL:
1221
size= ALIGN_SIZE(sizeof(bool));
1223
case PLUGIN_VAR_INT:
1224
size= ALIGN_SIZE(sizeof(int));
1226
case PLUGIN_VAR_LONG:
1227
case PLUGIN_VAR_ENUM:
1228
size= ALIGN_SIZE(sizeof(long));
1230
case PLUGIN_VAR_LONGLONG:
1231
case PLUGIN_VAR_SET:
1232
size= ALIGN_SIZE(sizeof(uint64_t));
1234
case PLUGIN_VAR_STR:
1235
size= ALIGN_SIZE(sizeof(char*));
1242
varname= ((char*) malloc(length));
1243
sprintf(varname+1, "%s_%s", plugin, name);
1244
for (p= varname + 1; *p; p++)
1248
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1250
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1251
sizeof(struct st_bookmark) + length-1);
1252
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1253
memcpy(result->key, varname, length);
1254
result->name_len= length - 2;
1257
assert(size && !(size & (size-1))); /* must be power of 2 */
1259
offset= global_system_variables.dynamic_variables_size;
1260
offset= (offset + size - 1) & ~(size - 1);
1261
result->offset= (int) offset;
1263
new_size= (offset + size + 63) & ~63;
1265
if (new_size > global_variables_dynamic_size)
1269
(char *)realloc(global_system_variables.dynamic_variables_ptr,
1272
global_system_variables.dynamic_variables_ptr= tmpptr;
1275
(char *)realloc(max_system_variables.dynamic_variables_ptr,
1278
max_system_variables.dynamic_variables_ptr= tmpptr;
1281
Clear the new variable value space. This is required for string
1282
variables. If their value is non-NULL, it must point to a valid
1285
memset(global_system_variables.dynamic_variables_ptr +
1286
global_variables_dynamic_size, 0,
1287
new_size - global_variables_dynamic_size);
1288
memset(max_system_variables.dynamic_variables_ptr +
1289
global_variables_dynamic_size, 0,
1290
new_size - global_variables_dynamic_size);
1291
global_variables_dynamic_size= new_size;
1294
global_system_variables.dynamic_variables_head= offset;
1295
max_system_variables.dynamic_variables_head= offset;
1296
global_system_variables.dynamic_variables_size= offset + size;
1297
max_system_variables.dynamic_variables_size= offset + size;
1298
global_system_variables.dynamic_variables_version++;
1299
max_system_variables.dynamic_variables_version++;
1301
result->version= global_system_variables.dynamic_variables_version;
1303
/* this should succeed because we have already checked if a dup exists */
1304
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1306
fprintf(stderr, "failed to add placeholder to hash");
1316
returns a pointer to the memory which holds the session-local variable or
1317
a pointer to the global variable if session==null.
1318
If required, will sync with global variables if the requested variable
1319
has not yet been allocated in the current thread.
1321
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1323
assert(offset >= 0);
1324
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1327
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1330
dynamic_variables_head points to the largest valid offset
1332
if (!session->variables.dynamic_variables_ptr ||
1333
(uint32_t)offset > session->variables.dynamic_variables_head)
1337
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1340
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1341
global_variables_dynamic_size)))
1343
session->variables.dynamic_variables_ptr= tmpptr;
1346
pthread_mutex_lock(&LOCK_global_system_variables);
1348
safe_mutex_assert_owner(&LOCK_global_system_variables);
1350
memcpy(session->variables.dynamic_variables_ptr +
1351
session->variables.dynamic_variables_size,
1352
global_system_variables.dynamic_variables_ptr +
1353
session->variables.dynamic_variables_size,
1354
global_system_variables.dynamic_variables_size -
1355
session->variables.dynamic_variables_size);
1358
now we need to iterate through any newly copied 'defaults'
1359
and if it is a string type with MEMALLOC flag, we need to strdup
1361
for (idx= 0; idx < bookmark_hash.records; idx++)
1363
sys_var_pluginvar *pi;
1365
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1367
if (v->version <= session->variables.dynamic_variables_version ||
1368
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1369
!(pi= var->cast_pluginvar()) ||
1370
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1373
/* Here we do anything special that may be required of the data types */
1375
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1376
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1378
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1379
*(int*)(pi->plugin_var + 1));
1380
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1381
*(int*)(pi->plugin_var + 1))))
1389
pthread_mutex_unlock(&LOCK_global_system_variables);
1391
session->variables.dynamic_variables_version=
1392
global_system_variables.dynamic_variables_version;
1393
session->variables.dynamic_variables_head=
1394
global_system_variables.dynamic_variables_head;
1395
session->variables.dynamic_variables_size=
1396
global_system_variables.dynamic_variables_size;
1398
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1400
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1403
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1405
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1408
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1410
return (int *)intern_sys_var_ptr(a_session, offset, true);
1413
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1415
return (long *)intern_sys_var_ptr(a_session, offset, true);
1418
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1420
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1423
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1425
return (char **)intern_sys_var_ptr(a_session, offset, true);
1428
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1430
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1433
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1435
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
509
1439
void plugin_sessionvar_init(Session *session)
511
1441
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1442
cleanup_variables(session, &session->variables);
514
1444
session->variables= global_system_variables;
515
1445
session->variables.storage_engine= NULL;
552
1510
void plugin_sessionvar_cleanup(Session *session)
554
1512
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1513
cleanup_variables(session, &session->variables);
1518
@brief Free values of thread variables of a plugin.
1520
This must be called before a plugin is deleted. Otherwise its
1521
variables are no longer accessible and the value space is lost. Note
1522
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1525
@param[in] vars Chain of system variables of a plugin
1528
static void plugin_vars_free_values(sys_var *vars)
1531
for (sys_var *var= vars; var; var= var->getNext())
1533
sys_var_pluginvar *piv= var->cast_pluginvar();
1535
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1536
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1538
/* Free the string from global_system_variables. */
1539
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1548
bool sys_var_pluginvar::check_update_type(Item_result type)
1552
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1553
case PLUGIN_VAR_INT:
1554
case PLUGIN_VAR_LONG:
1555
case PLUGIN_VAR_LONGLONG:
1556
return type != INT_RESULT;
1557
case PLUGIN_VAR_STR:
1558
return type != STRING_RESULT;
1565
SHOW_TYPE sys_var_pluginvar::show_type()
1567
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1568
case PLUGIN_VAR_BOOL:
1569
return SHOW_MY_BOOL;
1570
case PLUGIN_VAR_INT:
1572
case PLUGIN_VAR_LONG:
1574
case PLUGIN_VAR_LONGLONG:
1575
return SHOW_LONGLONG;
1576
case PLUGIN_VAR_STR:
1577
return SHOW_CHAR_PTR;
1578
case PLUGIN_VAR_ENUM:
1579
case PLUGIN_VAR_SET:
1588
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1590
assert(session || (type == OPT_GLOBAL));
1591
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1593
if (type == OPT_GLOBAL)
1596
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1598
return *(unsigned char**) (plugin_var+1);
1602
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1604
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1605
case PLUGIN_VAR_ENUM:
1606
return ((sysvar_enum_t *)plugin_var)->typelib;
1607
case PLUGIN_VAR_SET:
1608
return ((sysvar_set_t *)plugin_var)->typelib;
1609
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1610
return ((sessionvar_enum_t *)plugin_var)->typelib;
1611
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1612
return ((sessionvar_set_t *)plugin_var)->typelib;
1620
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1622
unsigned char* result;
1624
result= real_value_ptr(session, type);
1626
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
1627
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
1628
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
1630
char buffer[STRING_BUFFER_USUAL_SIZE];
1631
String str(buffer, sizeof(buffer), system_charset_info);
1632
TYPELIB *typelib= plugin_var_typelib();
1633
uint64_t mask= 1, value= *(uint64_t*) result;
1637
for (i= 0; i < typelib->count; i++, mask<<=1)
1639
if (!(value & mask))
1641
str.append(typelib->type_names[i], typelib->type_lengths[i]);
1645
result= (unsigned char*) "";
1647
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
1653
bool sys_var_pluginvar::check(Session *session, set_var *var)
1655
st_item_value_holder value;
1656
assert(is_readonly() || plugin_var->check);
1658
value.value_type= item_value_type;
1659
value.val_str= item_val_str;
1660
value.val_int= item_val_int;
1661
value.val_real= item_val_real;
1662
value.item= var->value;
1664
return is_readonly() ||
1665
plugin_var->check(session, plugin_var, &var->save_result, &value);
1669
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1674
assert(is_readonly() || plugin_var->update);
1679
pthread_mutex_lock(&LOCK_global_system_variables);
1680
tgt= real_value_ptr(session, type);
1681
src= ((void **) (plugin_var + 1) + 1);
1683
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1685
if (type != OPT_GLOBAL)
1686
src= real_value_ptr(session, OPT_GLOBAL);
1688
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1689
case PLUGIN_VAR_INT:
1690
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1692
case PLUGIN_VAR_LONG:
1693
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1695
case PLUGIN_VAR_LONGLONG:
1696
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1698
case PLUGIN_VAR_ENUM:
1699
src= &((sessionvar_enum_t*) plugin_var)->def_val;
1701
case PLUGIN_VAR_SET:
1702
src= &((sessionvar_set_t*) plugin_var)->def_val;
1704
case PLUGIN_VAR_BOOL:
1705
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1707
case PLUGIN_VAR_STR:
1708
src= &((sessionvar_str_t*) plugin_var)->def_val;
1715
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1716
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1717
session == current_session);
1719
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1721
plugin_var->update(session, plugin_var, tgt, src);
1722
pthread_mutex_unlock(&LOCK_global_system_variables);
1726
pthread_mutex_unlock(&LOCK_global_system_variables);
1727
plugin_var->update(session, plugin_var, tgt, src);
1732
bool sys_var_pluginvar::update(Session *session, set_var *var)
1736
assert(is_readonly() || plugin_var->update);
1738
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1739
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1740
session == current_session);
1745
pthread_mutex_lock(&LOCK_global_system_variables);
1746
tgt= real_value_ptr(session, var->type);
1748
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1750
/* variable we are updating has global scope, so we unlock after updating */
1751
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1752
pthread_mutex_unlock(&LOCK_global_system_variables);
1756
pthread_mutex_unlock(&LOCK_global_system_variables);
1757
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1763
#define OPTION_SET_LIMITS(type, options, opt) \
1764
options->var_type= type; \
1765
options->def_value= (opt)->def_val; \
1766
options->min_value= (opt)->min_val; \
1767
options->max_value= (opt)->max_val; \
1768
options->block_size= (long) (opt)->blk_sz
1771
static void plugin_opt_set_limits(struct my_option *options,
1772
const struct st_mysql_sys_var *opt)
1774
options->sub_size= 0;
1776
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1777
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1778
/* global system variables */
1779
case PLUGIN_VAR_INT:
1780
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1782
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1783
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1785
case PLUGIN_VAR_LONG:
1786
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1788
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1789
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1791
case PLUGIN_VAR_LONGLONG:
1792
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1794
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1795
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1797
case PLUGIN_VAR_ENUM:
1798
options->var_type= GET_ENUM;
1799
options->typelib= ((sysvar_enum_t*) opt)->typelib;
1800
options->def_value= ((sysvar_enum_t*) opt)->def_val;
1801
options->min_value= options->block_size= 0;
1802
options->max_value= options->typelib->count - 1;
1804
case PLUGIN_VAR_SET:
1805
options->var_type= GET_SET;
1806
options->typelib= ((sysvar_set_t*) opt)->typelib;
1807
options->def_value= ((sysvar_set_t*) opt)->def_val;
1808
options->min_value= options->block_size= 0;
1809
options->max_value= (1UL << options->typelib->count) - 1;
1811
case PLUGIN_VAR_BOOL:
1812
options->var_type= GET_BOOL;
1813
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1815
case PLUGIN_VAR_STR:
1816
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1817
GET_STR_ALLOC : GET_STR);
1818
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1820
/* threadlocal variables */
1821
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1822
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1824
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1825
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1827
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1828
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1830
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1831
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1833
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1834
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1836
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1837
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1839
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1840
options->var_type= GET_ENUM;
1841
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
1842
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
1843
options->min_value= options->block_size= 0;
1844
options->max_value= options->typelib->count - 1;
1846
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1847
options->var_type= GET_SET;
1848
options->typelib= ((sessionvar_set_t*) opt)->typelib;
1849
options->def_value= ((sessionvar_set_t*) opt)->def_val;
1850
options->min_value= options->block_size= 0;
1851
options->max_value= (1UL << options->typelib->count) - 1;
1853
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1854
options->var_type= GET_BOOL;
1855
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1857
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1858
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1859
GET_STR_ALLOC : GET_STR);
1860
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1865
options->arg_type= REQUIRED_ARG;
1866
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1867
options->arg_type= NO_ARG;
1868
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1869
options->arg_type= OPT_ARG;
1872
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
1875
bool get_one_plugin_option(int, const struct my_option *, char *)
1881
static int construct_options(MEM_ROOT *mem_root, plugin::Module *tmp,
1882
my_option *options, bool can_disable)
1884
const char *plugin_name= tmp->getManifest().name;
1885
uint32_t namelen= strlen(plugin_name), optnamelen;
1886
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
1887
char *name= (char*) alloc_root(mem_root, buffer_length);
1888
bool *enabled_value= (bool*) alloc_root(mem_root, sizeof(bool));
1890
int index= 0, offset= 0;
1891
st_mysql_sys_var *opt, **plugin_option;
1894
/* support --skip-plugin-foo syntax */
1895
memcpy(name, plugin_name, namelen + 1);
1896
my_casedn_str(&my_charset_utf8_general_ci, name);
1897
sprintf(name+namelen+1, "plugin-%s", name);
1898
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
1900
for (p= name + namelen*2 + 8; p > name; p--)
1906
sprintf(name+namelen*2+10,
1907
"Enable %s plugin. Disable with --skip-%s (will save memory).",
1910
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
1911
20 + namelen + 20 + 1 == namelen * 4 + 67.
1914
options[0].comment= name + namelen*2 + 10;
1918
This whole code around variables and command line parameters is turd
1921
e.g. the below assignemnt of having the plugin alaways enabled is never
1922
changed so that './drizzled --skip-innodb --help' shows innodb as enabled.
1924
But this is just as broken as it was in MySQL and properly fixing everything
1925
is a decent amount of "future work"
1927
*enabled_value= true; /* by default, plugin enabled */
1929
options[1].name= (options[0].name= name) + namelen + 1;
1930
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
1931
options[0].var_type= options[1].var_type= GET_BOOL;
1932
options[0].arg_type= options[1].arg_type= NO_ARG;
1933
options[0].def_value= options[1].def_value= true;
1934
options[0].value= options[0].u_max_value=
1935
options[1].value= options[1].u_max_value= (char**) enabled_value;
1939
Two passes as the 2nd pass will take pointer addresses for use
1940
by my_getopt and register_var() in the first pass uses realloc
1943
for (plugin_option= tmp->getManifest().system_vars;
1944
plugin_option && *plugin_option; plugin_option++, index++)
1946
opt= *plugin_option;
1947
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1949
if (!(register_var(name, opt->name, opt->flags)))
1951
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1952
case PLUGIN_VAR_BOOL:
1953
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1955
case PLUGIN_VAR_INT:
1956
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1958
case PLUGIN_VAR_LONG:
1959
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1961
case PLUGIN_VAR_LONGLONG:
1962
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1964
case PLUGIN_VAR_STR:
1965
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1967
case PLUGIN_VAR_ENUM:
1968
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
1970
case PLUGIN_VAR_SET:
1971
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1974
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1975
opt->flags, plugin_name);
1980
for (plugin_option= tmp->getManifest().system_vars;
1981
plugin_option && *plugin_option; plugin_option++, index++)
1983
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1984
case PLUGIN_VAR_BOOL:
1986
opt->check= check_func_bool;
1988
opt->update= update_func_bool;
1990
case PLUGIN_VAR_INT:
1992
opt->check= check_func_int;
1994
opt->update= update_func_int;
1996
case PLUGIN_VAR_LONG:
1998
opt->check= check_func_long;
2000
opt->update= update_func_long;
2002
case PLUGIN_VAR_LONGLONG:
2004
opt->check= check_func_int64_t;
2006
opt->update= update_func_int64_t;
2008
case PLUGIN_VAR_STR:
2010
opt->check= check_func_str;
2013
opt->update= update_func_str;
2014
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2016
opt->flags|= PLUGIN_VAR_READONLY;
2017
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2018
"to be read-only: string variable without "
2019
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2020
opt->name, plugin_name);
2024
case PLUGIN_VAR_ENUM:
2026
opt->check= check_func_enum;
2028
opt->update= update_func_long;
2030
case PLUGIN_VAR_SET:
2032
opt->check= check_func_set;
2034
opt->update= update_func_int64_t;
2037
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2038
opt->flags, plugin_name);
2042
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2043
== PLUGIN_VAR_NOCMDOPT)
2048
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2053
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2055
optnamelen= strlen(opt->name);
2056
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2057
sprintf(optname, "%s-%s", name, opt->name);
2058
optnamelen= namelen + optnamelen + 1;
2062
/* this should not fail because register_var should create entry */
2063
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2065
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2066
"in plugin '%s'."), opt->name, plugin_name);
2070
*(int*)(opt + 1)= offset= v->offset;
2072
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2075
optname= (char*) memdup_root(mem_root, v->key + 1,
2076
(optnamelen= v->name_len) + 1);
2079
/* convert '_' to '-' */
2080
for (p= optname; *p; p++)
2084
options->name= optname;
2085
options->comment= opt->comment;
2086
options->app_type= opt;
2087
options->id= (options-1)->id + 1;
2089
plugin_opt_set_limits(options, opt);
2091
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2092
options->value= options->u_max_value= (char**)
2093
(global_system_variables.dynamic_variables_ptr + offset);
2095
options->value= options->u_max_value= *(char***) (opt + 1);
2097
options[1]= options[0];
2098
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2099
options[1].comment= 0; // hidden
2100
sprintf(p,"plugin-%s",optname);
2109
static my_option *construct_help_options(MEM_ROOT *mem_root, plugin::Module *p)
2111
st_mysql_sys_var **opt;
2114
uint32_t count= EXTRA_OPTIONS;
2116
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count+= 2) {};
2118
opts= (my_option*)alloc_root(mem_root, (sizeof(my_option) * count));
2122
memset(opts, 0, sizeof(my_option) * count);
2124
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->getName().c_str(), "MyISAM") == 0))
2126
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->getName().c_str(), "MEMORY") == 0))
2132
if (construct_options(mem_root, p, opts, can_disable))
2138
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
2140
plugin_sysvar_vec.push_back(var);
2143
void drizzle_del_plugin_sysvar()
2145
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
2146
while(iter != plugin_sysvar_vec.end())
2151
plugin_sysvar_vec.clear();
562
2156
test_plugin_options()
563
2157
tmp_root temporary scratch space
564
2158
plugin internal plugin structure
2159
argc user supplied arguments
2160
argv user supplied arguments
565
2161
default_enabled default plugin enable status
567
2163
0 SUCCESS - plugin should be enabled/loaded
569
2165
Requires that a write-lock is held on LOCK_system_variables_hash
571
static int test_plugin_options(memory::Root *,
572
module::Module *test_module,
573
po::options_description &long_options)
2167
static int test_plugin_options(MEM_ROOT *tmp_root, plugin::Module *tmp,
2168
int *argc, char **argv)
576
if (test_module->getManifest().init_options != NULL)
578
string plugin_section_title("Options used by ");
579
plugin_section_title.append(test_module->getName());
580
po::options_description module_options(plugin_section_title);
581
module::option_context opt_ctx(test_module->getName(),
582
module_options.add_options());
583
test_module->getManifest().init_options(opt_ctx);
584
long_options.add(module_options);
2170
struct sys_var_chain chain= { NULL, NULL };
2172
st_mysql_sys_var **opt;
2173
my_option *opts= NULL;
2175
st_mysql_sys_var *o;
2176
struct st_bookmark *var;
2177
uint32_t len, count= EXTRA_OPTIONS;
2179
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
2180
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
2182
if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->getName().c_str(), "MyISAM") == 0))
2184
else if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->getName().c_str(), "MEMORY") == 0))
2189
if (count > EXTRA_OPTIONS || (*argc > 1))
2191
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2193
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
2196
memset(opts, 0, sizeof(my_option) * count);
2198
if (construct_options(tmp_root, tmp, opts, can_disable))
2200
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
2204
error= handle_options(argc, &argv, opts, get_one_plugin_option);
2205
(*argc)++; /* add back one for the program name */
2209
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2210
tmp->getName().c_str());
2218
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
2221
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
2224
if ((var= find_bookmark(tmp->getName().c_str(), o->name, o->flags)))
2225
v= new sys_var_pluginvar(var->key + 1, o);
2228
len= tmp->getName().length() + strlen(o->name) + 2;
2229
string vname(tmp->getName());
2230
vname.push_back('-');
2231
vname.append(o->name);
2232
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
2233
string::iterator p= vname.begin();
2234
while (p != vname.end())
2241
v= new sys_var_pluginvar(vname, o);
2243
assert(v); /* check that an object was actually constructed */
2245
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
2247
Add to the chain of variables.
2248
Done like this for easier debugging so that the
2249
pointer to v is not lost on optimized builds.
2251
v->chain_sys_var(&chain);
2255
chain.last->setNext(NULL);
2256
if (mysql_add_sys_var_chain(chain.first, NULL))
2258
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2259
tmp->getName().c_str());
2262
tmp->system_vars= chain.first;
2269
my_cleanup_options(opts);