95
79
write-lock on LOCK_system_variables_hash is required before modifying
96
80
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
82
static MEM_ROOT plugin_mem_root;
99
83
static uint32_t global_variables_dynamic_size= 0;
84
static HASH bookmark_hash;
103
88
hidden part of opaque value passed to variable check functions.
104
89
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
91
struct st_item_value_holder : public st_mysql_value
98
stored in bookmark_hash, this structure is never removed from the
99
hash and is used to mark a single offset for a session local variable
100
even if plugins have been uninstalled and reinstalled, repeatedly.
101
This structure is allocated from plugin_mem_root.
103
The key format is as follows:
104
1 byte - variable type code
105
name_len bytes - variable name
122
112
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
118
skeleton of a plugin variable - portion of structure common to all.
120
struct st_mysql_sys_var
122
DRIZZLE_PLUGIN_VAR_HEADER;
127
sys_var class for access to all plugin variables visible to the user
129
class sys_var_pluginvar: public sys_var
132
plugin::Handle *plugin;
133
struct st_mysql_sys_var *plugin_var;
135
sys_var_pluginvar(const std::string name_arg,
136
struct st_mysql_sys_var *plugin_var_arg)
137
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
138
sys_var_pluginvar *cast_pluginvar() { return this; }
139
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
140
bool check_type(enum_var_type type)
141
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
142
bool check_update_type(Item_result type);
143
SHOW_TYPE show_type();
144
unsigned char* real_value_ptr(Session *session, enum_var_type type);
145
TYPELIB* plugin_var_typelib(void);
146
unsigned char* value_ptr(Session *session, enum_var_type type,
147
const LEX_STRING *base);
148
bool check(Session *session, set_var *var);
149
bool check_default(enum_var_type)
150
{ return is_readonly(); }
151
void set_default(Session *session, enum_var_type);
152
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);
157
static bool plugin_load_list(plugin::Registry ®istry,
158
MEM_ROOT *tmp_root, int *argc, char **argv,
160
static int test_plugin_options(MEM_ROOT *, plugin::Handle *,
162
static bool register_builtin(plugin::Registry ®istry,
165
static void unlock_variables(Session *session, struct system_variables *vars);
166
static void cleanup_variables(Session *session, struct system_variables *vars);
167
static void plugin_vars_free_values(sys_var *vars);
168
static void plugin_opt_set_limits(struct my_option *options,
169
const struct st_mysql_sys_var *opt);
170
static void reap_plugins(plugin::Registry &plugins);
144
173
/* declared in set_var.cc */
145
174
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
175
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
176
const std::string &name, int64_t val);
178
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
179
const char *name, int64_t val)
181
const std::string name_str(name);
182
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
185
/****************************************************************************
186
Value type thunks, allows the C world to play in the C++ world
187
****************************************************************************/
189
static int item_value_type(struct st_mysql_value *value)
191
switch (((st_item_value_holder*)value)->item->result_type()) {
193
return DRIZZLE_VALUE_TYPE_INT;
195
return DRIZZLE_VALUE_TYPE_REAL;
197
return DRIZZLE_VALUE_TYPE_STRING;
201
static const char *item_val_str(struct st_mysql_value *value,
202
char *buffer, int *length)
204
String str(buffer, *length, system_charset_info), *res;
205
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
207
*length= res->length();
208
if (res->c_ptr_quick() == buffer)
212
Lets be nice and create a temporary string since the
215
return current_session->strmake(res->c_ptr_quick(), res->length());
219
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
221
Item *item= ((st_item_value_holder*)value)->item;
222
*buf= item->val_int();
229
static int item_val_real(struct st_mysql_value *value, double *buf)
231
Item *item= ((st_item_value_holder*)value)->item;
232
*buf= item->val_real();
148
239
/****************************************************************************
149
240
Plugin support code
150
241
****************************************************************************/
243
static plugin::Library *plugin_dl_find(const LEX_STRING *dl)
246
plugin::Library *tmp;
248
for (i= 0; i < plugin_dl_array.elements; i++)
250
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
251
if (! my_strnncoll(files_charset_info,
252
(const unsigned char *)dl->str, dl->length,
253
(const unsigned char *)tmp->dl.str, tmp->dl.length))
259
static plugin::Library *plugin_dl_insert_or_reuse(plugin::Library *plugin_dl)
262
plugin::Library *tmp;
264
for (i= 0; i < plugin_dl_array.elements; i++)
266
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
268
memcpy(tmp, plugin_dl, sizeof(plugin::Library));
272
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
274
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
276
(plugin::Library *) memdup_root(&plugin_mem_root,
277
(unsigned char*)plugin_dl,
278
sizeof(plugin::Library));
282
static inline void free_plugin_mem(plugin::Library *p)
290
static plugin::Library *plugin_dl_add(const LEX_STRING *dl, int report)
293
uint32_t plugin_dir_len;
294
plugin::Library *tmp, plugin_dl;
296
plugin_dir_len= strlen(opt_plugin_dir);
297
dlpath.reserve(FN_REFLEN);
299
Ensure that the dll doesn't have a path.
300
This is done to ensure that only approved libraries from the
301
plugin directory are used (to make this even remotely secure).
303
if (strchr(dl->str, FN_LIBCHAR) ||
304
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
305
system_charset_info, 1) ||
306
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
308
if (report & REPORT_TO_USER)
309
my_error(ER_UDF_NO_PATHS, MYF(0));
310
if (report & REPORT_TO_LOG)
311
errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
314
/* If this dll is already loaded just increase ref_count. */
315
if ((tmp= plugin_dl_find(dl)))
319
memset(&plugin_dl, 0, sizeof(plugin_dl));
320
/* Compile dll path */
321
dlpath.append(opt_plugin_dir);
323
dlpath.append(dl->str);
324
/* Open new dll handle */
325
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
327
const char *errmsg=dlerror();
328
uint32_t dlpathlen= dlpath.length();
329
if (!dlpath.compare(0, dlpathlen, errmsg))
330
{ // if errmsg starts from dlpath, trim this prefix.
332
if (*errmsg == ':') errmsg++;
333
if (*errmsg == ' ') errmsg++;
335
if (report & REPORT_TO_USER)
336
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
337
if (report & REPORT_TO_LOG)
338
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
342
/* Find plugin declarations */
343
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
345
free_plugin_mem(&plugin_dl);
346
if (report & REPORT_TO_USER)
347
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
348
if (report & REPORT_TO_LOG)
349
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
353
plugin_dl.plugins= static_cast<plugin::Manifest *>(sym);
355
/* Duplicate and convert dll name */
356
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
357
if (! (plugin_dl.dl.str= (char*) calloc(plugin_dl.dl.length, sizeof(char))))
359
free_plugin_mem(&plugin_dl);
360
if (report & REPORT_TO_USER)
361
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
362
if (report & REPORT_TO_LOG)
363
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
366
strcpy(plugin_dl.dl.str, dl->str);
367
/* Add this dll to array */
368
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
370
free_plugin_mem(&plugin_dl);
371
if (report & REPORT_TO_USER)
372
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(plugin::Library));
373
if (report & REPORT_TO_LOG)
374
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY),
375
sizeof(plugin::Library));
382
static void plugin_dl_del(const LEX_STRING *dl)
386
for (i= 0; i < plugin_dl_array.elements; i++)
388
plugin::Library *tmp= *dynamic_element(&plugin_dl_array, i,
390
if (! my_strnncoll(files_charset_info,
391
(const unsigned char *)dl->str, dl->length,
392
(const unsigned char *)tmp->dl.str, tmp->dl.length))
394
/* Do not remove this element, unless no other plugin uses this dll. */
396
free_plugin_mem(tmp);
397
memset(tmp, 0, sizeof(plugin::Library));
407
static plugin::Handle *plugin_insert_or_reuse(plugin::Handle *plugin)
409
if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
411
plugin= *dynamic_element(&plugin_array, plugin_array.elements - 1,
157
419
Requires that a write-lock is held on LOCK_system_variables_hash
159
static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
160
module::Library *library,
161
po::options_description &long_options)
421
static bool plugin_add(plugin::Registry ®istry, MEM_ROOT *tmp_root,
422
const LEX_STRING *name, const LEX_STRING *dl,
423
int *argc, char **argv, int report)
425
plugin::Manifest *manifest;
163
426
if (! initialized)
166
if (registry.find(library->getName()))
429
if (registry.find(name))
168
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
169
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);
437
plugin::Library *library= plugin_dl_add(dl, report);
173
module::Module *tmp= NULL;
441
plugin::Handle *tmp= NULL;
174
442
/* Find plugin by name */
175
const module::Manifest *manifest= library->getManifest();
177
if (registry.find(manifest->name))
179
errmsg_printf(ERRMSG_LVL_ERROR,
180
_("Plugin '%s' contains the name '%s' in its manifest, which "
181
"has already been registered.\n"),
182
library->getName().c_str(),
187
tmp= new (std::nothrow) module::Module(manifest, library);
191
if (!test_plugin_options(tmp_root, tmp, long_options))
196
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY),
197
library->getName().c_str());
202
static void reap_plugins(module::Registry ®istry)
204
std::map<std::string, module::Module *>::const_iterator modules=
205
registry.getModulesMap().begin();
207
while (modules != registry.getModulesMap().end())
209
module::Module *module= (*modules).second;
216
static bool plugin_initialize(module::Registry ®istry,
217
module::Module *module)
219
assert(module->isInited == false);
221
module::Context loading_context(registry, module);
222
if (module->getManifest().init)
224
if (module->getManifest().init(loading_context))
443
for (manifest= library->plugins; manifest->name; manifest++)
445
if (! my_strnncoll(system_charset_info,
446
(const unsigned char *)name->str, name->length,
447
(const unsigned char *)manifest->name,
448
strlen(manifest->name)))
450
tmp= new (std::nothrow) plugin::Handle(manifest, library);
454
if (!test_plugin_options(tmp_root, tmp, argc, argv))
456
if ((tmp= plugin_insert_or_reuse(tmp)))
459
init_alloc_root(&tmp->mem_root, 4096, 4096);
462
mysql_del_sys_var_chain(tmp->system_vars);
465
/* plugin was disabled */
470
if (report & REPORT_TO_USER)
471
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
472
if (report & REPORT_TO_LOG)
473
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
480
static void plugin_del(plugin::Registry ®istry, plugin::Handle *plugin)
482
if (plugin->isInited)
484
if (plugin->getManifest().status_vars)
486
remove_status_vars(plugin->getManifest().status_vars);
489
if (plugin->getManifest().deinit)
490
plugin->getManifest().deinit(registry);
493
/* Free allocated strings before deleting the plugin. */
494
plugin_vars_free_values(plugin->system_vars);
495
if (plugin->plugin_dl)
496
plugin_dl_del(&plugin->plugin_dl->dl);
497
plugin->isInited= false;
498
pthread_rwlock_wrlock(&LOCK_system_variables_hash);
499
mysql_del_sys_var_chain(plugin->system_vars);
500
pthread_rwlock_unlock(&LOCK_system_variables_hash);
504
static void reap_plugins(plugin::Registry &plugins)
508
plugin::Handle *plugin;
510
count= plugin_array.elements;
512
for (idx= 0; idx < count; idx++)
514
plugin= *dynamic_element(&plugin_array, idx, plugin::Handle **);
515
plugin_del(plugins, plugin);
517
drizzle_del_plugin_sysvar();
521
static void plugin_initialize_vars(plugin::Handle *plugin)
523
if (plugin->getManifest().status_vars)
525
add_status_vars(plugin->getManifest().status_vars); // add_status_vars makes a copy
529
set the plugin attribute of plugin's sys vars so they are pointing
532
if (plugin->system_vars)
534
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
538
if (! var->getNext())
540
var= var->getNext()->cast_pluginvar();
546
static bool plugin_initialize(plugin::Registry ®istry,
547
plugin::Handle *plugin)
549
assert(plugin->isInited == false);
551
registry.setCurrentHandle(plugin);
552
if (plugin->getManifest().init)
554
if (plugin->getManifest().init(registry))
226
556
errmsg_printf(ERRMSG_LVL_ERROR,
227
557
_("Plugin '%s' init function returned error.\n"),
228
module->getName().c_str());
558
plugin->getName().c_str());
232
module->isInited= true;
562
registry.clearCurrentHandle();
563
plugin->isInited= true;
239
inline static void dashes_to_underscores(std::string &name_in,
240
char from= '-', char to= '_')
242
for (string::iterator p= name_in.begin();
253
inline static void underscores_to_dashes(std::string &name_in)
255
return dashes_to_underscores(name_in, '_', '-');
258
static void compose_plugin_options(vector<string> &target,
259
vector<string> options)
261
for (vector<string>::iterator it= options.begin();
265
tokenize(*it, target, ",", true);
267
for (vector<string>::iterator it= target.begin();
271
dashes_to_underscores(*it);
275
void compose_plugin_add(vector<string> options)
277
compose_plugin_options(opt_plugin_add, options);
280
void compose_plugin_remove(vector<string> options)
282
compose_plugin_options(opt_plugin_remove, options);
285
void notify_plugin_load(string in_plugin_load)
287
tokenize(in_plugin_load, opt_plugin_load, ",", true);
570
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
573
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
575
struct st_bookmark *var= (st_bookmark *)buff;
576
*length= var->name_len + 1;
577
return (unsigned char*) var->key;
291
582
The logic is that we first load and initialize all compiled in plugins.
295
586
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)
588
int plugin_init(plugin::Registry ®istry, int *argc, char **argv, int flags)
300
memory::Root tmp_root(4096);
591
plugin::Manifest **builtins;
592
plugin::Manifest *manifest;
593
plugin::Handle *handle;
599
init_alloc_root(&plugin_mem_root, 4096, 4096);
600
init_alloc_root(&tmp_root, 4096, 4096);
602
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
603
get_bookmark_hash_key, NULL, HASH_UNIQUE))
607
if (my_init_dynamic_array(&plugin_dl_array,
608
sizeof(plugin::Library *),16,16) ||
609
my_init_dynamic_array(&plugin_array,
610
sizeof(plugin::Handle *),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
616
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);
618
for (builtins= drizzled_builtins; *builtins; builtins++)
349
tmp_root.free_root(MYF(0));
620
for (manifest= *builtins; manifest->name; manifest++)
622
handle= new (std::nothrow) plugin::Handle(manifest);
626
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
627
if (test_plugin_options(&tmp_root, handle, argc, argv))
630
if (register_builtin(registry, handle, &handle))
633
plugin_initialize_vars(handle);
635
if (! (flags & PLUGIN_INIT_SKIP_INITIALIZATION))
637
if (plugin_initialize(registry, handle))
353
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
357
644
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
645
if (! (flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
362
tmp_root.free_root(MYF(0));
648
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)
651
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
374
655
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())
657
for (idx= 0; idx < plugin_array.elements; idx++)
381
module::Module *module= (*modules).second;
383
if (module->isInited == false)
659
handle= *dynamic_element(&plugin_array, idx, plugin::Handle **);
660
if (handle->isInited == false)
385
if (plugin_initialize(registry, module))
387
registry.remove(module);
662
plugin_initialize_vars(handle);
664
if (plugin_initialize(registry, handle))
665
plugin_del(registry, handle);
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(),
671
free_root(&tmp_root, MYF(0));
677
free_root(&tmp_root, MYF(0));
682
static bool register_builtin(plugin::Registry ®istry,
684
plugin::Handle **ptr)
687
tmp->isInited= false;
690
if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
693
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
434
703
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,
705
static bool plugin_load_list(plugin::Registry &plugins,
706
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();
709
char buffer[FN_REFLEN];
710
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
711
plugin::Library *plugin_dl;
712
plugin::Manifest *plugin;
448
const string plugin_name(*iter);
450
library= registry.addLibrary(plugin_name, builtin);
716
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());
718
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());
722
switch ((*(p++)= *(list++))) {
724
list= NULL; /* terminate the loop */
726
case ':': /* can't use this as delimiter as it may be drive letter */
728
str->str[str->length]= '\0';
729
if (str == &name) // load all plugins in named module
733
p--; /* reset pointer */
738
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
740
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
742
name.str= (char *) plugin->name;
743
name.length= strlen(name.str);
745
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
746
if (plugin_add(plugins, tmp_root, &name, &dl,
747
argc, argv, REPORT_TO_LOG))
750
plugin_dl_del(&dl); // reduce ref count
755
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
756
if (plugin_add(plugins, tmp_root, &name, &dl,
757
argc, argv, REPORT_TO_LOG))
760
name.length= dl.length= 0;
761
dl.str= NULL; name.str= p= buffer;
768
name.str[name.length]= '\0';
780
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
474
void module_shutdown(module::Registry ®istry)
786
void plugin_shutdown(plugin::Registry ®istry)
789
size_t count= plugin_array.elements;
790
vector<plugin::Handle *> plugins;
791
vector<plugin::Library *> dl;
482
798
unlock_variables(NULL, &global_system_variables);
483
799
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
801
cleanup_variables(NULL, &global_system_variables);
802
cleanup_variables(NULL, &max_system_variables);
491
807
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
809
delete_dynamic(&plugin_array);
811
count= plugin_dl_array.elements;
813
for (idx= 0; idx < count; idx++)
814
dl.push_back(*dynamic_element(&plugin_dl_array, idx,
815
plugin::Library **));
816
for (idx= 0; idx < count; idx++)
817
free_plugin_mem(dl[idx]);
818
delete_dynamic(&plugin_dl_array);
820
hash_free(&bookmark_hash);
821
free_root(&plugin_mem_root, MYF(0));
494
823
global_variables_dynamic_size= 0;
826
/****************************************************************************
827
Internal type declarations for variables support
828
****************************************************************************/
830
#undef DRIZZLE_SYSVAR_NAME
831
#define DRIZZLE_SYSVAR_NAME(name) name
832
#define PLUGIN_VAR_TYPEMASK 0x007f
834
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
836
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
837
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
838
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
839
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
841
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
842
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
843
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
844
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
846
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
847
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
848
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
849
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
850
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
851
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
853
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
854
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
855
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
856
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
857
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
858
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
860
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
863
/****************************************************************************
864
default variable data check and update functions
865
****************************************************************************/
867
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
868
void *save, st_mysql_value *value)
870
char buff[STRING_BUFFER_USUAL_SIZE];
871
const char *strvalue= "NULL", *str;
875
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
877
length= sizeof(buff);
878
if (!(str= value->val_str(value, buff, &length)) ||
879
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
888
if (value->val_int(value, &tmp) < 0)
898
*(int*)save= -result;
901
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
906
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
907
void *save, st_mysql_value *value)
911
struct my_option options;
912
value->val_int(value, &tmp);
913
plugin_opt_set_limits(&options, var);
915
if (var->flags & PLUGIN_VAR_UNSIGNED)
916
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
919
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
921
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
922
var->name, (int64_t) tmp);
926
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
927
void *save, st_mysql_value *value)
931
struct my_option options;
932
value->val_int(value, &tmp);
933
plugin_opt_set_limits(&options, var);
935
if (var->flags & PLUGIN_VAR_UNSIGNED)
936
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
939
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
941
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
942
var->name, (int64_t) tmp);
946
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
947
void *save, st_mysql_value *value)
951
struct my_option options;
952
value->val_int(value, &tmp);
953
plugin_opt_set_limits(&options, var);
955
if (var->flags & PLUGIN_VAR_UNSIGNED)
956
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
959
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
961
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
962
var->name, (int64_t) tmp);
965
static int check_func_str(Session *session, struct st_mysql_sys_var *,
966
void *save, st_mysql_value *value)
968
char buff[STRING_BUFFER_USUAL_SIZE];
972
length= sizeof(buff);
973
if ((str= value->val_str(value, buff, &length)))
974
str= session->strmake(str, length);
975
*(const char**)save= str;
980
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
981
void *save, st_mysql_value *value)
983
char buff[STRING_BUFFER_USUAL_SIZE];
984
const char *strvalue= "NULL", *str;
990
if (var->flags & PLUGIN_VAR_SessionLOCAL)
991
typelib= ((sessionvar_enum_t*) var)->typelib;
993
typelib= ((sysvar_enum_t*) var)->typelib;
995
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
997
length= sizeof(buff);
998
if (!(str= value->val_str(value, buff, &length)))
1000
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1008
if (value->val_int(value, &tmp))
1010
if (tmp >= typelib->count)
1018
*(long*)save= result;
1021
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1026
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1027
void *save, st_mysql_value *value)
1029
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1030
const char *strvalue= "NULL", *str;
1037
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1038
typelib= ((sessionvar_set_t*) var)->typelib;
1040
typelib= ((sysvar_set_t*)var)->typelib;
1042
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1044
length= sizeof(buff);
1045
if (!(str= value->val_str(value, buff, &length)))
1047
result= find_set(typelib, str, length, NULL,
1048
&error, &error_len, ¬_used);
1051
length= min((uint32_t)sizeof(buff), error_len);
1052
strncpy(buff, error, length);
1060
if (value->val_int(value, (int64_t *)&result))
1062
if (unlikely((result >= (1UL << typelib->count)) &&
1063
(typelib->count < sizeof(long)*8)))
1065
llstr(result, buff);
1070
*(uint64_t*)save= result;
1073
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1078
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1079
void *tgt, const void *save)
1081
*(bool *) tgt= *(int *) save ? 1 : 0;
1085
static void update_func_int(Session *, struct st_mysql_sys_var *,
1086
void *tgt, const void *save)
1088
*(int *)tgt= *(int *) save;
1092
static void update_func_long(Session *, struct st_mysql_sys_var *,
1093
void *tgt, const void *save)
1095
*(long *)tgt= *(long *) save;
1099
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1100
void *tgt, const void *save)
1102
*(int64_t *)tgt= *(uint64_t *) save;
1106
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1107
void *tgt, const void *save)
1109
char *old= *(char **) tgt;
1110
*(char **)tgt= *(char **) save;
1111
if (var->flags & PLUGIN_VAR_MEMALLOC)
1113
*(char **)tgt= strdup(*(char **) save);
1116
* There isn't a _really_ good thing to do here until this whole set_var
1117
* mess gets redesigned
1120
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
1126
/****************************************************************************
499
1127
System Variables support
500
1128
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
1131
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
1134
sys_var_pluginvar *pi= NULL;
1135
plugin::Handle *plugin;
1137
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1138
if ((var= intern_find_sys_var(str, length, false)) &&
1139
(pi= var->cast_pluginvar()))
1141
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1142
if (!(plugin= pi->plugin))
1143
var= NULL; /* failed to lock it, it must be uninstalling */
1144
else if (plugin->isInited == false)
1150
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1153
If the variable exists but the plugin it is associated with is not ready
1154
then the intern_plugin_lock did not raise an error, so we do it here.
1157
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1163
called by register_var, construct_options and test_plugin_options.
1164
Returns the 'bookmark' for the named variable.
1165
LOCK_system_variables_hash should be at least read locked
1167
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1169
st_bookmark *result= NULL;
1170
uint32_t namelen, length, pluginlen= 0;
1173
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1176
namelen= strlen(name);
1178
pluginlen= strlen(plugin) + 1;
1179
length= namelen + pluginlen + 2;
1180
varname= (char*) malloc(length);
1184
sprintf(varname+1,"%s_%s",plugin,name);
1185
for (p= varname + 1; *p; p++)
1190
memcpy(varname + 1, name, namelen + 1);
1192
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1194
result= (st_bookmark*) hash_search(&bookmark_hash,
1195
(const unsigned char*) varname, length - 1);
1203
returns a bookmark for session-local variables, creating if neccessary.
1204
returns null for non session-local variables.
1205
Requires that a write lock is obtained on LOCK_system_variables_hash
1207
static st_bookmark *register_var(const char *plugin, const char *name,
1210
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1211
st_bookmark *result;
1214
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1217
switch (flags & PLUGIN_VAR_TYPEMASK) {
1218
case PLUGIN_VAR_BOOL:
1219
size= ALIGN_SIZE(sizeof(bool));
1221
case PLUGIN_VAR_INT:
1222
size= ALIGN_SIZE(sizeof(int));
1224
case PLUGIN_VAR_LONG:
1225
case PLUGIN_VAR_ENUM:
1226
size= ALIGN_SIZE(sizeof(long));
1228
case PLUGIN_VAR_LONGLONG:
1229
case PLUGIN_VAR_SET:
1230
size= ALIGN_SIZE(sizeof(uint64_t));
1232
case PLUGIN_VAR_STR:
1233
size= ALIGN_SIZE(sizeof(char*));
1240
varname= ((char*) malloc(length));
1241
sprintf(varname+1, "%s_%s", plugin, name);
1242
for (p= varname + 1; *p; p++)
1246
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1248
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1249
sizeof(struct st_bookmark) + length-1);
1250
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1251
memcpy(result->key, varname, length);
1252
result->name_len= length - 2;
1255
assert(size && !(size & (size-1))); /* must be power of 2 */
1257
offset= global_system_variables.dynamic_variables_size;
1258
offset= (offset + size - 1) & ~(size - 1);
1259
result->offset= (int) offset;
1261
new_size= (offset + size + 63) & ~63;
1263
if (new_size > global_variables_dynamic_size)
1267
(char *)realloc(global_system_variables.dynamic_variables_ptr,
1270
global_system_variables.dynamic_variables_ptr= tmpptr;
1273
(char *)realloc(max_system_variables.dynamic_variables_ptr,
1276
max_system_variables.dynamic_variables_ptr= tmpptr;
1279
Clear the new variable value space. This is required for string
1280
variables. If their value is non-NULL, it must point to a valid
1283
memset(global_system_variables.dynamic_variables_ptr +
1284
global_variables_dynamic_size, 0,
1285
new_size - global_variables_dynamic_size);
1286
memset(max_system_variables.dynamic_variables_ptr +
1287
global_variables_dynamic_size, 0,
1288
new_size - global_variables_dynamic_size);
1289
global_variables_dynamic_size= new_size;
1292
global_system_variables.dynamic_variables_head= offset;
1293
max_system_variables.dynamic_variables_head= offset;
1294
global_system_variables.dynamic_variables_size= offset + size;
1295
max_system_variables.dynamic_variables_size= offset + size;
1296
global_system_variables.dynamic_variables_version++;
1297
max_system_variables.dynamic_variables_version++;
1299
result->version= global_system_variables.dynamic_variables_version;
1301
/* this should succeed because we have already checked if a dup exists */
1302
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1304
fprintf(stderr, "failed to add placeholder to hash");
1314
returns a pointer to the memory which holds the session-local variable or
1315
a pointer to the global variable if session==null.
1316
If required, will sync with global variables if the requested variable
1317
has not yet been allocated in the current thread.
1319
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1321
assert(offset >= 0);
1322
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1325
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1328
dynamic_variables_head points to the largest valid offset
1330
if (!session->variables.dynamic_variables_ptr ||
1331
(uint32_t)offset > session->variables.dynamic_variables_head)
1335
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1338
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1339
global_variables_dynamic_size)))
1341
session->variables.dynamic_variables_ptr= tmpptr;
1344
pthread_mutex_lock(&LOCK_global_system_variables);
1346
safe_mutex_assert_owner(&LOCK_global_system_variables);
1348
memcpy(session->variables.dynamic_variables_ptr +
1349
session->variables.dynamic_variables_size,
1350
global_system_variables.dynamic_variables_ptr +
1351
session->variables.dynamic_variables_size,
1352
global_system_variables.dynamic_variables_size -
1353
session->variables.dynamic_variables_size);
1356
now we need to iterate through any newly copied 'defaults'
1357
and if it is a string type with MEMALLOC flag, we need to strdup
1359
for (idx= 0; idx < bookmark_hash.records; idx++)
1361
sys_var_pluginvar *pi;
1363
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1365
if (v->version <= session->variables.dynamic_variables_version ||
1366
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1367
!(pi= var->cast_pluginvar()) ||
1368
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1371
/* Here we do anything special that may be required of the data types */
1373
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1374
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1376
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1377
*(int*)(pi->plugin_var + 1));
1378
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1379
*(int*)(pi->plugin_var + 1))))
1387
pthread_mutex_unlock(&LOCK_global_system_variables);
1389
session->variables.dynamic_variables_version=
1390
global_system_variables.dynamic_variables_version;
1391
session->variables.dynamic_variables_head=
1392
global_system_variables.dynamic_variables_head;
1393
session->variables.dynamic_variables_size=
1394
global_system_variables.dynamic_variables_size;
1396
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1398
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1401
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1403
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1406
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1408
return (int *)intern_sys_var_ptr(a_session, offset, true);
1411
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1413
return (long *)intern_sys_var_ptr(a_session, offset, true);
1416
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1418
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1421
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1423
return (char **)intern_sys_var_ptr(a_session, offset, true);
1426
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1428
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1431
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1433
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
509
1437
void plugin_sessionvar_init(Session *session)
511
1439
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1440
cleanup_variables(session, &session->variables);
514
1442
session->variables= global_system_variables;
515
1443
session->variables.storage_engine= NULL;
552
1508
void plugin_sessionvar_cleanup(Session *session)
554
1510
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1511
cleanup_variables(session, &session->variables);
1516
@brief Free values of thread variables of a plugin.
1518
This must be called before a plugin is deleted. Otherwise its
1519
variables are no longer accessible and the value space is lost. Note
1520
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1523
@param[in] vars Chain of system variables of a plugin
1526
static void plugin_vars_free_values(sys_var *vars)
1529
for (sys_var *var= vars; var; var= var->getNext())
1531
sys_var_pluginvar *piv= var->cast_pluginvar();
1533
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1534
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1536
/* Free the string from global_system_variables. */
1537
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1546
bool sys_var_pluginvar::check_update_type(Item_result type)
1550
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1551
case PLUGIN_VAR_INT:
1552
case PLUGIN_VAR_LONG:
1553
case PLUGIN_VAR_LONGLONG:
1554
return type != INT_RESULT;
1555
case PLUGIN_VAR_STR:
1556
return type != STRING_RESULT;
1563
SHOW_TYPE sys_var_pluginvar::show_type()
1565
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1566
case PLUGIN_VAR_BOOL:
1567
return SHOW_MY_BOOL;
1568
case PLUGIN_VAR_INT:
1570
case PLUGIN_VAR_LONG:
1572
case PLUGIN_VAR_LONGLONG:
1573
return SHOW_LONGLONG;
1574
case PLUGIN_VAR_STR:
1575
return SHOW_CHAR_PTR;
1576
case PLUGIN_VAR_ENUM:
1577
case PLUGIN_VAR_SET:
1586
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1588
assert(session || (type == OPT_GLOBAL));
1589
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1591
if (type == OPT_GLOBAL)
1594
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1596
return *(unsigned char**) (plugin_var+1);
1600
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1602
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1603
case PLUGIN_VAR_ENUM:
1604
return ((sysvar_enum_t *)plugin_var)->typelib;
1605
case PLUGIN_VAR_SET:
1606
return ((sysvar_set_t *)plugin_var)->typelib;
1607
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1608
return ((sessionvar_enum_t *)plugin_var)->typelib;
1609
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1610
return ((sessionvar_set_t *)plugin_var)->typelib;
1618
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1620
unsigned char* result;
1622
result= real_value_ptr(session, type);
1624
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
1625
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
1626
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
1628
char buffer[STRING_BUFFER_USUAL_SIZE];
1629
String str(buffer, sizeof(buffer), system_charset_info);
1630
TYPELIB *typelib= plugin_var_typelib();
1631
uint64_t mask= 1, value= *(uint64_t*) result;
1635
for (i= 0; i < typelib->count; i++, mask<<=1)
1637
if (!(value & mask))
1639
str.append(typelib->type_names[i], typelib->type_lengths[i]);
1643
result= (unsigned char*) "";
1645
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
1651
bool sys_var_pluginvar::check(Session *session, set_var *var)
1653
st_item_value_holder value;
1654
assert(is_readonly() || plugin_var->check);
1656
value.value_type= item_value_type;
1657
value.val_str= item_val_str;
1658
value.val_int= item_val_int;
1659
value.val_real= item_val_real;
1660
value.item= var->value;
1662
return is_readonly() ||
1663
plugin_var->check(session, plugin_var, &var->save_result, &value);
1667
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1672
assert(is_readonly() || plugin_var->update);
1677
pthread_mutex_lock(&LOCK_global_system_variables);
1678
tgt= real_value_ptr(session, type);
1679
src= ((void **) (plugin_var + 1) + 1);
1681
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1683
if (type != OPT_GLOBAL)
1684
src= real_value_ptr(session, OPT_GLOBAL);
1686
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1687
case PLUGIN_VAR_INT:
1688
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1690
case PLUGIN_VAR_LONG:
1691
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1693
case PLUGIN_VAR_LONGLONG:
1694
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1696
case PLUGIN_VAR_ENUM:
1697
src= &((sessionvar_enum_t*) plugin_var)->def_val;
1699
case PLUGIN_VAR_SET:
1700
src= &((sessionvar_set_t*) plugin_var)->def_val;
1702
case PLUGIN_VAR_BOOL:
1703
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1705
case PLUGIN_VAR_STR:
1706
src= &((sessionvar_str_t*) plugin_var)->def_val;
1713
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1714
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1715
session == current_session);
1717
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1719
plugin_var->update(session, plugin_var, tgt, src);
1720
pthread_mutex_unlock(&LOCK_global_system_variables);
1724
pthread_mutex_unlock(&LOCK_global_system_variables);
1725
plugin_var->update(session, plugin_var, tgt, src);
1730
bool sys_var_pluginvar::update(Session *session, set_var *var)
1734
assert(is_readonly() || plugin_var->update);
1736
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1737
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1738
session == current_session);
1743
pthread_mutex_lock(&LOCK_global_system_variables);
1744
tgt= real_value_ptr(session, var->type);
1746
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1748
/* variable we are updating has global scope, so we unlock after updating */
1749
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1750
pthread_mutex_unlock(&LOCK_global_system_variables);
1754
pthread_mutex_unlock(&LOCK_global_system_variables);
1755
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1761
#define OPTION_SET_LIMITS(type, options, opt) \
1762
options->var_type= type; \
1763
options->def_value= (opt)->def_val; \
1764
options->min_value= (opt)->min_val; \
1765
options->max_value= (opt)->max_val; \
1766
options->block_size= (long) (opt)->blk_sz
1769
static void plugin_opt_set_limits(struct my_option *options,
1770
const struct st_mysql_sys_var *opt)
1772
options->sub_size= 0;
1774
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1775
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1776
/* global system variables */
1777
case PLUGIN_VAR_INT:
1778
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1780
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1781
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1783
case PLUGIN_VAR_LONG:
1784
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1786
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1787
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1789
case PLUGIN_VAR_LONGLONG:
1790
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1792
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1793
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1795
case PLUGIN_VAR_ENUM:
1796
options->var_type= GET_ENUM;
1797
options->typelib= ((sysvar_enum_t*) opt)->typelib;
1798
options->def_value= ((sysvar_enum_t*) opt)->def_val;
1799
options->min_value= options->block_size= 0;
1800
options->max_value= options->typelib->count - 1;
1802
case PLUGIN_VAR_SET:
1803
options->var_type= GET_SET;
1804
options->typelib= ((sysvar_set_t*) opt)->typelib;
1805
options->def_value= ((sysvar_set_t*) opt)->def_val;
1806
options->min_value= options->block_size= 0;
1807
options->max_value= (1UL << options->typelib->count) - 1;
1809
case PLUGIN_VAR_BOOL:
1810
options->var_type= GET_BOOL;
1811
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1813
case PLUGIN_VAR_STR:
1814
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1815
GET_STR_ALLOC : GET_STR);
1816
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1818
/* threadlocal variables */
1819
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1820
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1822
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1823
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1825
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1826
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1828
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1829
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1831
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1832
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1834
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1835
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1837
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1838
options->var_type= GET_ENUM;
1839
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
1840
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
1841
options->min_value= options->block_size= 0;
1842
options->max_value= options->typelib->count - 1;
1844
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1845
options->var_type= GET_SET;
1846
options->typelib= ((sessionvar_set_t*) opt)->typelib;
1847
options->def_value= ((sessionvar_set_t*) opt)->def_val;
1848
options->min_value= options->block_size= 0;
1849
options->max_value= (1UL << options->typelib->count) - 1;
1851
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1852
options->var_type= GET_BOOL;
1853
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1855
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1856
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1857
GET_STR_ALLOC : GET_STR);
1858
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1863
options->arg_type= REQUIRED_ARG;
1864
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1865
options->arg_type= NO_ARG;
1866
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1867
options->arg_type= OPT_ARG;
1870
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
1873
bool get_one_plugin_option(int, const struct my_option *, char *)
1879
static int construct_options(MEM_ROOT *mem_root, plugin::Handle *tmp,
1880
my_option *options, bool can_disable)
1882
const char *plugin_name= tmp->getManifest().name;
1883
uint32_t namelen= strlen(plugin_name), optnamelen;
1884
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
1885
char *name= (char*) alloc_root(mem_root, buffer_length);
1886
bool *enabled_value= (bool*) alloc_root(mem_root, sizeof(bool));
1888
int index= 0, offset= 0;
1889
st_mysql_sys_var *opt, **plugin_option;
1892
/* support --skip-plugin-foo syntax */
1893
memcpy(name, plugin_name, namelen + 1);
1894
my_casedn_str(&my_charset_utf8_general_ci, name);
1895
sprintf(name+namelen+1, "plugin-%s", name);
1896
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
1898
for (p= name + namelen*2 + 8; p > name; p--)
1904
sprintf(name+namelen*2+10,
1905
"Enable %s plugin. Disable with --skip-%s (will save memory).",
1908
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
1909
20 + namelen + 20 + 1 == namelen * 4 + 67.
1912
options[0].comment= name + namelen*2 + 10;
1916
This whole code around variables and command line parameters is turd
1919
e.g. the below assignemnt of having the plugin alaways enabled is never
1920
changed so that './drizzled --skip-innodb --help' shows innodb as enabled.
1922
But this is just as broken as it was in MySQL and properly fixing everything
1923
is a decent amount of "future work"
1925
*enabled_value= true; /* by default, plugin enabled */
1927
options[1].name= (options[0].name= name) + namelen + 1;
1928
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
1929
options[0].var_type= options[1].var_type= GET_BOOL;
1930
options[0].arg_type= options[1].arg_type= NO_ARG;
1931
options[0].def_value= options[1].def_value= true;
1932
options[0].value= options[0].u_max_value=
1933
options[1].value= options[1].u_max_value= (char**) enabled_value;
1937
Two passes as the 2nd pass will take pointer addresses for use
1938
by my_getopt and register_var() in the first pass uses realloc
1941
for (plugin_option= tmp->getManifest().system_vars;
1942
plugin_option && *plugin_option; plugin_option++, index++)
1944
opt= *plugin_option;
1945
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1947
if (!(register_var(name, opt->name, opt->flags)))
1949
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1950
case PLUGIN_VAR_BOOL:
1951
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1953
case PLUGIN_VAR_INT:
1954
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1956
case PLUGIN_VAR_LONG:
1957
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1959
case PLUGIN_VAR_LONGLONG:
1960
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1962
case PLUGIN_VAR_STR:
1963
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1965
case PLUGIN_VAR_ENUM:
1966
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
1968
case PLUGIN_VAR_SET:
1969
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1972
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1973
opt->flags, plugin_name);
1978
for (plugin_option= tmp->getManifest().system_vars;
1979
plugin_option && *plugin_option; plugin_option++, index++)
1981
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1982
case PLUGIN_VAR_BOOL:
1984
opt->check= check_func_bool;
1986
opt->update= update_func_bool;
1988
case PLUGIN_VAR_INT:
1990
opt->check= check_func_int;
1992
opt->update= update_func_int;
1994
case PLUGIN_VAR_LONG:
1996
opt->check= check_func_long;
1998
opt->update= update_func_long;
2000
case PLUGIN_VAR_LONGLONG:
2002
opt->check= check_func_int64_t;
2004
opt->update= update_func_int64_t;
2006
case PLUGIN_VAR_STR:
2008
opt->check= check_func_str;
2011
opt->update= update_func_str;
2012
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2014
opt->flags|= PLUGIN_VAR_READONLY;
2015
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2016
"to be read-only: string variable without "
2017
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2018
opt->name, plugin_name);
2022
case PLUGIN_VAR_ENUM:
2024
opt->check= check_func_enum;
2026
opt->update= update_func_long;
2028
case PLUGIN_VAR_SET:
2030
opt->check= check_func_set;
2032
opt->update= update_func_int64_t;
2035
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2036
opt->flags, plugin_name);
2040
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2041
== PLUGIN_VAR_NOCMDOPT)
2046
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2051
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2053
optnamelen= strlen(opt->name);
2054
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2055
sprintf(optname, "%s-%s", name, opt->name);
2056
optnamelen= namelen + optnamelen + 1;
2060
/* this should not fail because register_var should create entry */
2061
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2063
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2064
"in plugin '%s'."), opt->name, plugin_name);
2068
*(int*)(opt + 1)= offset= v->offset;
2070
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2073
optname= (char*) memdup_root(mem_root, v->key + 1,
2074
(optnamelen= v->name_len) + 1);
2077
/* convert '_' to '-' */
2078
for (p= optname; *p; p++)
2082
options->name= optname;
2083
options->comment= opt->comment;
2084
options->app_type= opt;
2085
options->id= (options-1)->id + 1;
2087
plugin_opt_set_limits(options, opt);
2089
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2090
options->value= options->u_max_value= (char**)
2091
(global_system_variables.dynamic_variables_ptr + offset);
2093
options->value= options->u_max_value= *(char***) (opt + 1);
2095
options[1]= options[0];
2096
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2097
options[1].comment= 0; // hidden
2098
sprintf(p,"plugin-%s",optname);
2107
static my_option *construct_help_options(MEM_ROOT *mem_root, plugin::Handle *p)
2109
st_mysql_sys_var **opt;
2112
uint32_t count= EXTRA_OPTIONS;
2114
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count+= 2) {};
2116
opts= (my_option*)alloc_root(mem_root, (sizeof(my_option) * count));
2120
memset(opts, 0, sizeof(my_option) * count);
2122
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->getName().c_str(), "MyISAM") == 0))
2124
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->getName().c_str(), "MEMORY") == 0))
2130
if (construct_options(mem_root, p, opts, can_disable))
2136
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
2138
plugin_sysvar_vec.push_back(var);
2141
void drizzle_del_plugin_sysvar()
2143
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
2144
while(iter != plugin_sysvar_vec.end())
2149
plugin_sysvar_vec.clear();
562
2154
test_plugin_options()
563
2155
tmp_root temporary scratch space
564
2156
plugin internal plugin structure
2157
argc user supplied arguments
2158
argv user supplied arguments
565
2159
default_enabled default plugin enable status
567
2161
0 SUCCESS - plugin should be enabled/loaded
569
2163
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)
2165
static int test_plugin_options(MEM_ROOT *tmp_root, plugin::Handle *tmp,
2166
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);
2168
struct sys_var_chain chain= { NULL, NULL };
2170
st_mysql_sys_var **opt;
2171
my_option *opts= NULL;
2173
st_mysql_sys_var *o;
2174
struct st_bookmark *var;
2175
uint32_t len, count= EXTRA_OPTIONS;
2177
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
2178
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
2180
if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->getName().c_str(), "MyISAM") == 0))
2182
else if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->getName().c_str(), "MEMORY") == 0))
2187
if (count > EXTRA_OPTIONS || (*argc > 1))
2189
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2191
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
2194
memset(opts, 0, sizeof(my_option) * count);
2196
if (construct_options(tmp_root, tmp, opts, can_disable))
2198
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
2202
error= handle_options(argc, &argv, opts, get_one_plugin_option);
2203
(*argc)++; /* add back one for the program name */
2207
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2208
tmp->getName().c_str());
2216
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
2219
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
2222
if ((var= find_bookmark(tmp->getName().c_str(), o->name, o->flags)))
2223
v= new sys_var_pluginvar(var->key + 1, o);
2226
len= tmp->getName().length() + strlen(o->name) + 2;
2227
string vname(tmp->getName());
2228
vname.push_back('-');
2229
vname.append(o->name);
2230
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
2231
string::iterator p= vname.begin();
2232
while (p != vname.end())
2239
v= new sys_var_pluginvar(vname, o);
2241
assert(v); /* check that an object was actually constructed */
2243
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
2245
Add to the chain of variables.
2246
Done like this for easier debugging so that the
2247
pointer to v is not lost on optimized builds.
2249
v->chain_sys_var(&chain);
2253
chain.last->setNext(NULL);
2254
if (mysql_add_sys_var_chain(chain.first, NULL))
2256
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2257
tmp->getName().c_str());
2260
tmp->system_vars= chain.first;
2267
my_cleanup_options(opts);