95
78
write-lock on LOCK_system_variables_hash is required before modifying
96
79
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
81
static MEM_ROOT plugin_mem_root;
99
82
static uint32_t global_variables_dynamic_size= 0;
83
static HASH bookmark_hash;
103
87
hidden part of opaque value passed to variable check functions.
104
88
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
90
struct st_item_value_holder : public st_mysql_value
97
stored in bookmark_hash, this structure is never removed from the
98
hash and is used to mark a single offset for a session local variable
99
even if plugins have been uninstalled and reinstalled, repeatedly.
100
This structure is allocated from plugin_mem_root.
102
The key format is as follows:
103
1 byte - variable type code
104
name_len bytes - variable name
122
111
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
117
skeleton of a plugin variable - portion of structure common to all.
119
struct st_mysql_sys_var
121
DRIZZLE_PLUGIN_VAR_HEADER;
126
sys_var class for access to all plugin variables visible to the user
128
class sys_var_pluginvar: public sys_var
131
plugin::Module *plugin;
132
struct st_mysql_sys_var *plugin_var;
134
sys_var_pluginvar(const std::string name_arg,
135
struct st_mysql_sys_var *plugin_var_arg)
136
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
137
sys_var_pluginvar *cast_pluginvar() { return this; }
138
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
139
bool check_type(enum_var_type type)
140
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
141
bool check_update_type(Item_result type);
142
SHOW_TYPE show_type();
143
unsigned char* real_value_ptr(Session *session, enum_var_type type);
144
TYPELIB* plugin_var_typelib(void);
145
unsigned char* value_ptr(Session *session, enum_var_type type,
146
const LEX_STRING *base);
147
bool check(Session *session, set_var *var);
148
bool check_default(enum_var_type)
149
{ return is_readonly(); }
150
void set_default(Session *session, enum_var_type);
151
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);
156
static bool plugin_load_list(plugin::Registry ®istry,
157
MEM_ROOT *tmp_root, int *argc, char **argv,
159
static int test_plugin_options(MEM_ROOT *, plugin::Module *,
161
static bool register_builtin(plugin::Registry ®istry,
164
static void unlock_variables(Session *session, struct system_variables *vars);
165
static void cleanup_variables(Session *session, struct system_variables *vars);
166
static void plugin_vars_free_values(sys_var *vars);
167
static void plugin_opt_set_limits(struct my_option *options,
168
const struct st_mysql_sys_var *opt);
169
static void reap_plugins(plugin::Registry &plugins);
144
172
/* declared in set_var.cc */
145
173
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
174
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
175
const std::string &name, int64_t val);
177
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
178
const char *name, int64_t val)
180
const std::string name_str(name);
181
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
184
/****************************************************************************
185
Value type thunks, allows the C world to play in the C++ world
186
****************************************************************************/
188
static int item_value_type(struct st_mysql_value *value)
190
switch (((st_item_value_holder*)value)->item->result_type()) {
192
return DRIZZLE_VALUE_TYPE_INT;
194
return DRIZZLE_VALUE_TYPE_REAL;
196
return DRIZZLE_VALUE_TYPE_STRING;
200
static const char *item_val_str(struct st_mysql_value *value,
201
char *buffer, int *length)
203
String str(buffer, *length, system_charset_info), *res;
204
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
206
*length= res->length();
207
if (res->c_ptr_quick() == buffer)
211
Lets be nice and create a temporary string since the
214
return current_session->strmake(res->c_ptr_quick(), res->length());
218
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
220
Item *item= ((st_item_value_holder*)value)->item;
221
*buf= item->val_int();
228
static int item_val_real(struct st_mysql_value *value, double *buf)
230
Item *item= ((st_item_value_holder*)value)->item;
231
*buf= item->val_real();
148
238
/****************************************************************************
149
239
Plugin support code
150
240
****************************************************************************/
242
static plugin::Library *plugin_dl_find(const LEX_STRING *dl)
245
plugin::Library *tmp;
247
for (i= 0; i < plugin_dl_array.elements; i++)
249
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
250
if (! my_strnncoll(files_charset_info,
251
(const unsigned char *)dl->str, dl->length,
252
(const unsigned char *)tmp->dl.str, tmp->dl.length))
258
static plugin::Library *plugin_dl_insert_or_reuse(plugin::Library *plugin_dl)
261
plugin::Library *tmp;
263
for (i= 0; i < plugin_dl_array.elements; i++)
265
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
267
memcpy(tmp, plugin_dl, sizeof(plugin::Library));
271
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
273
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
275
(plugin::Library *) memdup_root(&plugin_mem_root,
276
(unsigned char*)plugin_dl,
277
sizeof(plugin::Library));
281
static inline void free_plugin_mem(plugin::Library *p)
289
static plugin::Library *plugin_dl_add(const LEX_STRING *dl)
292
uint32_t plugin_dir_len;
293
plugin::Library *tmp, plugin_dl;
295
plugin_dir_len= strlen(opt_plugin_dir);
296
dlpath.reserve(FN_REFLEN);
298
Ensure that the dll doesn't have a path.
299
This is done to ensure that only approved libraries from the
300
plugin directory are used (to make this even remotely secure).
302
if (strchr(dl->str, FN_LIBCHAR) ||
303
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
304
system_charset_info, 1) ||
305
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
307
errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
310
/* If this dll is already loaded just increase ref_count. */
311
if ((tmp= plugin_dl_find(dl)))
315
memset(&plugin_dl, 0, sizeof(plugin_dl));
316
/* Compile dll path */
317
dlpath.append(opt_plugin_dir);
319
dlpath.append("lib");
320
dlpath.append(dl->str);
321
dlpath.append("_plugin.so");
322
/* Open new dll handle */
323
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_NOW|RTLD_GLOBAL)))
325
const char *errmsg=dlerror();
326
uint32_t dlpathlen= dlpath.length();
327
if (!dlpath.compare(0, dlpathlen, errmsg))
328
{ // if errmsg starts from dlpath, trim this prefix.
330
if (*errmsg == ':') errmsg++;
331
if (*errmsg == ' ') errmsg++;
333
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
337
/* Find plugin declarations */
338
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
340
free_plugin_mem(&plugin_dl);
341
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
345
plugin_dl.plugins= static_cast<plugin::Manifest *>(sym);
347
/* Duplicate and convert dll name */
348
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
349
if (! (plugin_dl.dl.str= (char*) calloc(plugin_dl.dl.length, sizeof(char))))
351
free_plugin_mem(&plugin_dl);
352
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
355
strcpy(plugin_dl.dl.str, dl->str);
356
/* Add this dll to array */
357
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
359
free_plugin_mem(&plugin_dl);
360
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY),
361
sizeof(plugin::Library));
368
static void plugin_dl_del(const LEX_STRING *dl)
372
for (i= 0; i < plugin_dl_array.elements; i++)
374
plugin::Library *tmp= *dynamic_element(&plugin_dl_array, i,
376
if (! my_strnncoll(files_charset_info,
377
(const unsigned char *)dl->str, dl->length,
378
(const unsigned char *)tmp->dl.str, tmp->dl.length))
380
/* Do not remove this element, unless no other plugin uses this dll. */
382
free_plugin_mem(tmp);
383
memset(tmp, 0, sizeof(plugin::Library));
393
static plugin::Module *plugin_insert_or_reuse(plugin::Module *module)
395
if (insert_dynamic(&module_array, (unsigned char*)&module))
397
module= *dynamic_element(&module_array, module_array.elements - 1,
157
405
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)
407
static bool plugin_add(plugin::Registry ®istry, MEM_ROOT *tmp_root,
408
const LEX_STRING *name, const LEX_STRING *dl,
409
int *argc, char **argv)
411
plugin::Manifest *manifest;
163
412
if (! initialized)
166
if (registry.find(library->getName()))
415
if (registry.find(name))
168
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
169
library->getName().c_str());
417
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
420
plugin::Library *library= plugin_dl_add(dl);
173
module::Module *tmp= NULL;
424
plugin::Module *tmp= NULL;
174
425
/* 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)
426
for (manifest= library->plugins; manifest->name; manifest++)
428
if (! my_strnncoll(system_charset_info,
429
(const unsigned char *)name->str, name->length,
430
(const unsigned char *)manifest->name,
431
strlen(manifest->name)))
433
tmp= new (std::nothrow) plugin::Module(manifest, library);
437
if (!test_plugin_options(tmp_root, tmp, argc, argv))
439
if ((tmp= plugin_insert_or_reuse(tmp)))
442
init_alloc_root(&tmp->mem_root, 4096, 4096);
445
mysql_del_sys_var_chain(tmp->system_vars);
448
/* plugin was disabled */
453
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
460
static void delete_module(plugin::Registry ®istry, plugin::Module *module)
462
plugin::Manifest manifest= module->getManifest();
464
if (module->isInited)
466
if (manifest.status_vars)
468
remove_status_vars(manifest.status_vars);
472
manifest.deinit(registry);
475
/* Free allocated strings before deleting the plugin. */
476
plugin_vars_free_values(module->system_vars);
477
if (module->plugin_dl)
478
plugin_dl_del(&module->plugin_dl->dl);
479
module->isInited= false;
480
pthread_rwlock_wrlock(&LOCK_system_variables_hash);
481
mysql_del_sys_var_chain(module->system_vars);
482
pthread_rwlock_unlock(&LOCK_system_variables_hash);
486
static void reap_plugins(plugin::Registry &plugins)
490
plugin::Module *module;
492
count= module_array.elements;
494
for (idx= 0; idx < count; idx++)
496
module= *dynamic_element(&module_array, idx, plugin::Module **);
497
delete_module(plugins, module);
499
drizzle_del_plugin_sysvar();
503
static void plugin_initialize_vars(plugin::Module *module)
505
if (module->getManifest().status_vars)
507
add_status_vars(module->getManifest().status_vars); // add_status_vars makes a copy
511
set the plugin attribute of plugin's sys vars so they are pointing
514
if (module->system_vars)
516
sys_var_pluginvar *var= module->system_vars->cast_pluginvar();
520
if (! var->getNext())
522
var= var->getNext()->cast_pluginvar();
528
static bool plugin_initialize(plugin::Registry ®istry,
529
plugin::Module *module)
219
531
assert(module->isInited == false);
221
module::Context loading_context(registry, module);
533
registry.setCurrentModule(module);
222
534
if (module->getManifest().init)
224
if (module->getManifest().init(loading_context))
536
if (module->getManifest().init(registry))
226
538
errmsg_printf(ERRMSG_LVL_ERROR,
227
539
_("Plugin '%s' init function returned error.\n"),
295
568
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)
570
int plugin_init(plugin::Registry ®istry, int *argc, char **argv, int flags)
300
memory::Root tmp_root(4096);
573
plugin::Manifest **builtins;
574
plugin::Manifest *manifest;
575
plugin::Module *module;
581
init_alloc_root(&plugin_mem_root, 4096, 4096);
582
init_alloc_root(&tmp_root, 4096, 4096);
584
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
585
get_bookmark_hash_key, NULL, HASH_UNIQUE))
589
if (my_init_dynamic_array(&plugin_dl_array,
590
sizeof(plugin::Library *),16,16) ||
591
my_init_dynamic_array(&module_array,
592
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
598
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);
600
for (builtins= drizzled_builtins; *builtins; builtins++)
349
tmp_root.free_root(MYF(0));
602
for (manifest= *builtins; manifest->name; manifest++)
604
module= new (std::nothrow) plugin::Module(manifest);
608
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
609
if (test_plugin_options(&tmp_root, module, argc, argv))
612
if (register_builtin(registry, module, &module))
615
plugin_initialize_vars(module);
617
if (! (flags & PLUGIN_INIT_SKIP_INITIALIZATION))
619
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
626
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
627
if (! (flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
362
tmp_root.free_root(MYF(0));
631
plugin_load_list(registry, &tmp_root, argc, argv, opt_plugin_load);
635
string tmp_plugin_list(opt_plugin_load_default);
638
tmp_plugin_list.push_back(',');
639
tmp_plugin_list.append(opt_plugin_add);
641
plugin_load_list(registry, &tmp_root, argc, argv, tmp_plugin_list.c_str());
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
645
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
374
649
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())
651
for (idx= 0; idx < module_array.elements; idx++)
381
module::Module *module= (*modules).second;
653
module= *dynamic_element(&module_array, idx, plugin::Module **);
383
654
if (module->isInited == false)
656
plugin_initialize_vars(module);
385
658
if (plugin_initialize(registry, module))
387
registry.remove(module);
659
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(),
665
free_root(&tmp_root, MYF(0));
671
free_root(&tmp_root, MYF(0));
676
static bool register_builtin(plugin::Registry ®istry,
678
plugin::Module **ptr)
681
tmp->isInited= false;
684
if (insert_dynamic(&module_array, (unsigned char*)&tmp))
687
*ptr= *dynamic_element(&module_array, module_array.elements - 1,
434
697
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,
699
static bool plugin_load_list(plugin::Registry &plugins,
700
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();
703
char buffer[FN_REFLEN];
704
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
705
plugin::Library *plugin_dl;
706
plugin::Manifest *plugin;
448
const string plugin_name(*iter);
450
library= registry.addLibrary(plugin_name, builtin);
710
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());
712
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());
716
switch ((*(p++)= *(list++))) {
718
list= NULL; /* terminate the loop */
720
case ':': /* can't use this as delimiter as it may be drive letter */
722
str->str[str->length]= '\0';
723
if (str == &name) // load all plugins in named module
727
p--; /* reset pointer */
732
if ((plugin_dl= plugin_dl_add(&dl)))
734
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
736
name.str= (char *) plugin->name;
737
name.length= strlen(name.str);
739
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
740
if (plugin_add(plugins, tmp_root, &name, &dl, argc, argv))
743
plugin_dl_del(&dl); // reduce ref count
748
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
749
if (plugin_add(plugins, tmp_root, &name, &dl, argc, argv))
752
name.length= dl.length= 0;
753
dl.str= NULL; name.str= p= buffer;
760
name.str[name.length]= '\0';
772
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
474
void module_shutdown(module::Registry ®istry)
778
void plugin_shutdown(plugin::Registry ®istry)
781
size_t count= module_array.elements;
782
vector<plugin::Library *> dl;
482
789
unlock_variables(NULL, &global_system_variables);
483
790
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
792
cleanup_variables(NULL, &global_system_variables);
793
cleanup_variables(NULL, &max_system_variables);
491
798
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
800
delete_dynamic(&module_array);
802
count= plugin_dl_array.elements;
804
for (idx= 0; idx < count; idx++)
805
dl.push_back(*dynamic_element(&plugin_dl_array, idx,
806
plugin::Library **));
807
for (idx= 0; idx < count; idx++)
808
free_plugin_mem(dl[idx]);
809
delete_dynamic(&plugin_dl_array);
811
hash_free(&bookmark_hash);
812
free_root(&plugin_mem_root, MYF(0));
494
814
global_variables_dynamic_size= 0;
817
/****************************************************************************
818
Internal type declarations for variables support
819
****************************************************************************/
821
#undef DRIZZLE_SYSVAR_NAME
822
#define DRIZZLE_SYSVAR_NAME(name) name
823
#define PLUGIN_VAR_TYPEMASK 0x007f
825
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
827
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
828
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
829
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
830
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
832
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
833
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
834
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
835
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
837
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
838
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
839
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
840
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
841
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
842
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
844
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
845
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
846
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
847
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
848
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
849
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
851
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
854
/****************************************************************************
855
default variable data check and update functions
856
****************************************************************************/
858
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
859
void *save, st_mysql_value *value)
861
char buff[STRING_BUFFER_USUAL_SIZE];
862
const char *strvalue= "NULL", *str;
866
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
868
length= sizeof(buff);
869
if (!(str= value->val_str(value, buff, &length)) ||
870
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
879
if (value->val_int(value, &tmp) < 0)
889
*(int*)save= -result;
892
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
897
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
898
void *save, st_mysql_value *value)
902
struct my_option options;
903
value->val_int(value, &tmp);
904
plugin_opt_set_limits(&options, var);
906
if (var->flags & PLUGIN_VAR_UNSIGNED)
907
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
910
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
912
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
913
var->name, (int64_t) tmp);
917
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
918
void *save, st_mysql_value *value)
922
struct my_option options;
923
value->val_int(value, &tmp);
924
plugin_opt_set_limits(&options, var);
926
if (var->flags & PLUGIN_VAR_UNSIGNED)
927
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
930
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
932
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
933
var->name, (int64_t) tmp);
937
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
938
void *save, st_mysql_value *value)
942
struct my_option options;
943
value->val_int(value, &tmp);
944
plugin_opt_set_limits(&options, var);
946
if (var->flags & PLUGIN_VAR_UNSIGNED)
947
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
950
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
952
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
953
var->name, (int64_t) tmp);
956
static int check_func_str(Session *session, struct st_mysql_sys_var *,
957
void *save, st_mysql_value *value)
959
char buff[STRING_BUFFER_USUAL_SIZE];
963
length= sizeof(buff);
964
if ((str= value->val_str(value, buff, &length)))
965
str= session->strmake(str, length);
966
*(const char**)save= str;
971
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
972
void *save, st_mysql_value *value)
974
char buff[STRING_BUFFER_USUAL_SIZE];
975
const char *strvalue= "NULL", *str;
981
if (var->flags & PLUGIN_VAR_SessionLOCAL)
982
typelib= ((sessionvar_enum_t*) var)->typelib;
984
typelib= ((sysvar_enum_t*) var)->typelib;
986
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
988
length= sizeof(buff);
989
if (!(str= value->val_str(value, buff, &length)))
991
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
999
if (value->val_int(value, &tmp))
1001
if (tmp >= typelib->count)
1009
*(long*)save= result;
1012
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1017
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1018
void *save, st_mysql_value *value)
1020
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1021
const char *strvalue= "NULL", *str;
1028
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1029
typelib= ((sessionvar_set_t*) var)->typelib;
1031
typelib= ((sysvar_set_t*)var)->typelib;
1033
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1035
length= sizeof(buff);
1036
if (!(str= value->val_str(value, buff, &length)))
1038
result= find_set(typelib, str, length, NULL,
1039
&error, &error_len, ¬_used);
1042
length= min((uint32_t)sizeof(buff), error_len);
1043
strncpy(buff, error, length);
1051
if (value->val_int(value, (int64_t *)&result))
1053
if (unlikely((result >= (1UL << typelib->count)) &&
1054
(typelib->count < sizeof(long)*8)))
1056
llstr(result, buff);
1061
*(uint64_t*)save= result;
1064
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1069
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1070
void *tgt, const void *save)
1072
*(bool *) tgt= *(int *) save ? 1 : 0;
1076
static void update_func_int(Session *, struct st_mysql_sys_var *,
1077
void *tgt, const void *save)
1079
*(int *)tgt= *(int *) save;
1083
static void update_func_long(Session *, struct st_mysql_sys_var *,
1084
void *tgt, const void *save)
1086
*(long *)tgt= *(long *) save;
1090
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1091
void *tgt, const void *save)
1093
*(int64_t *)tgt= *(uint64_t *) save;
1097
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1098
void *tgt, const void *save)
1100
char *old= *(char **) tgt;
1101
*(char **)tgt= *(char **) save;
1102
if (var->flags & PLUGIN_VAR_MEMALLOC)
1104
*(char **)tgt= strdup(*(char **) save);
1107
* There isn't a _really_ good thing to do here until this whole set_var
1108
* mess gets redesigned
1111
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
1117
/****************************************************************************
499
1118
System Variables support
500
1119
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
1122
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
1125
sys_var_pluginvar *pi= NULL;
1126
plugin::Module *module;
1128
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1129
if ((var= intern_find_sys_var(str, length, false)) &&
1130
(pi= var->cast_pluginvar()))
1132
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1133
if (!(module= pi->plugin))
1134
var= NULL; /* failed to lock it, it must be uninstalling */
1135
else if (module->isInited == false)
1141
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1144
If the variable exists but the plugin it is associated with is not ready
1145
then the intern_plugin_lock did not raise an error, so we do it here.
1148
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1154
called by register_var, construct_options and test_plugin_options.
1155
Returns the 'bookmark' for the named variable.
1156
LOCK_system_variables_hash should be at least read locked
1158
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1160
st_bookmark *result= NULL;
1161
uint32_t namelen, length, pluginlen= 0;
1164
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1167
namelen= strlen(name);
1169
pluginlen= strlen(plugin) + 1;
1170
length= namelen + pluginlen + 2;
1171
varname= (char*) malloc(length);
1175
sprintf(varname+1,"%s_%s",plugin,name);
1176
for (p= varname + 1; *p; p++)
1181
memcpy(varname + 1, name, namelen + 1);
1183
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1185
result= (st_bookmark*) hash_search(&bookmark_hash,
1186
(const unsigned char*) varname, length - 1);
1194
returns a bookmark for session-local variables, creating if neccessary.
1195
returns null for non session-local variables.
1196
Requires that a write lock is obtained on LOCK_system_variables_hash
1198
static st_bookmark *register_var(const char *plugin, const char *name,
1201
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1202
st_bookmark *result;
1205
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1208
switch (flags & PLUGIN_VAR_TYPEMASK) {
1209
case PLUGIN_VAR_BOOL:
1210
size= ALIGN_SIZE(sizeof(bool));
1212
case PLUGIN_VAR_INT:
1213
size= ALIGN_SIZE(sizeof(int));
1215
case PLUGIN_VAR_LONG:
1216
case PLUGIN_VAR_ENUM:
1217
size= ALIGN_SIZE(sizeof(long));
1219
case PLUGIN_VAR_LONGLONG:
1220
case PLUGIN_VAR_SET:
1221
size= ALIGN_SIZE(sizeof(uint64_t));
1223
case PLUGIN_VAR_STR:
1224
size= ALIGN_SIZE(sizeof(char*));
1231
varname= ((char*) malloc(length));
1232
sprintf(varname+1, "%s_%s", plugin, name);
1233
for (p= varname + 1; *p; p++)
1237
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1239
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1240
sizeof(struct st_bookmark) + length-1);
1241
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1242
memcpy(result->key, varname, length);
1243
result->name_len= length - 2;
1246
assert(size && !(size & (size-1))); /* must be power of 2 */
1248
offset= global_system_variables.dynamic_variables_size;
1249
offset= (offset + size - 1) & ~(size - 1);
1250
result->offset= (int) offset;
1252
new_size= (offset + size + 63) & ~63;
1254
if (new_size > global_variables_dynamic_size)
1258
(char *)realloc(global_system_variables.dynamic_variables_ptr,
1261
global_system_variables.dynamic_variables_ptr= tmpptr;
1264
(char *)realloc(max_system_variables.dynamic_variables_ptr,
1267
max_system_variables.dynamic_variables_ptr= tmpptr;
1270
Clear the new variable value space. This is required for string
1271
variables. If their value is non-NULL, it must point to a valid
1274
memset(global_system_variables.dynamic_variables_ptr +
1275
global_variables_dynamic_size, 0,
1276
new_size - global_variables_dynamic_size);
1277
memset(max_system_variables.dynamic_variables_ptr +
1278
global_variables_dynamic_size, 0,
1279
new_size - global_variables_dynamic_size);
1280
global_variables_dynamic_size= new_size;
1283
global_system_variables.dynamic_variables_head= offset;
1284
max_system_variables.dynamic_variables_head= offset;
1285
global_system_variables.dynamic_variables_size= offset + size;
1286
max_system_variables.dynamic_variables_size= offset + size;
1287
global_system_variables.dynamic_variables_version++;
1288
max_system_variables.dynamic_variables_version++;
1290
result->version= global_system_variables.dynamic_variables_version;
1292
/* this should succeed because we have already checked if a dup exists */
1293
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1295
fprintf(stderr, "failed to add placeholder to hash");
1305
returns a pointer to the memory which holds the session-local variable or
1306
a pointer to the global variable if session==null.
1307
If required, will sync with global variables if the requested variable
1308
has not yet been allocated in the current thread.
1310
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1312
assert(offset >= 0);
1313
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1316
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1319
dynamic_variables_head points to the largest valid offset
1321
if (!session->variables.dynamic_variables_ptr ||
1322
(uint32_t)offset > session->variables.dynamic_variables_head)
1326
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1329
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1330
global_variables_dynamic_size)))
1332
session->variables.dynamic_variables_ptr= tmpptr;
1335
pthread_mutex_lock(&LOCK_global_system_variables);
1337
safe_mutex_assert_owner(&LOCK_global_system_variables);
1339
memcpy(session->variables.dynamic_variables_ptr +
1340
session->variables.dynamic_variables_size,
1341
global_system_variables.dynamic_variables_ptr +
1342
session->variables.dynamic_variables_size,
1343
global_system_variables.dynamic_variables_size -
1344
session->variables.dynamic_variables_size);
1347
now we need to iterate through any newly copied 'defaults'
1348
and if it is a string type with MEMALLOC flag, we need to strdup
1350
for (idx= 0; idx < bookmark_hash.records; idx++)
1352
sys_var_pluginvar *pi;
1354
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1356
if (v->version <= session->variables.dynamic_variables_version ||
1357
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1358
!(pi= var->cast_pluginvar()) ||
1359
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1362
/* Here we do anything special that may be required of the data types */
1364
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1365
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1367
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1368
*(int*)(pi->plugin_var + 1));
1369
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1370
*(int*)(pi->plugin_var + 1))))
1378
pthread_mutex_unlock(&LOCK_global_system_variables);
1380
session->variables.dynamic_variables_version=
1381
global_system_variables.dynamic_variables_version;
1382
session->variables.dynamic_variables_head=
1383
global_system_variables.dynamic_variables_head;
1384
session->variables.dynamic_variables_size=
1385
global_system_variables.dynamic_variables_size;
1387
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1389
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1392
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1394
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1397
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1399
return (int *)intern_sys_var_ptr(a_session, offset, true);
1402
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1404
return (long *)intern_sys_var_ptr(a_session, offset, true);
1407
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1409
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1412
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1414
return (char **)intern_sys_var_ptr(a_session, offset, true);
1417
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1419
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1422
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1424
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
509
1428
void plugin_sessionvar_init(Session *session)
511
1430
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1431
cleanup_variables(session, &session->variables);
514
1433
session->variables= global_system_variables;
515
1434
session->variables.storage_engine= NULL;
552
1499
void plugin_sessionvar_cleanup(Session *session)
554
1501
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1502
cleanup_variables(session, &session->variables);
1507
@brief Free values of thread variables of a plugin.
1509
This must be called before a plugin is deleted. Otherwise its
1510
variables are no longer accessible and the value space is lost. Note
1511
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1514
@param[in] vars Chain of system variables of a plugin
1517
static void plugin_vars_free_values(sys_var *vars)
1520
for (sys_var *var= vars; var; var= var->getNext())
1522
sys_var_pluginvar *piv= var->cast_pluginvar();
1524
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1525
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1527
/* Free the string from global_system_variables. */
1528
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1537
bool sys_var_pluginvar::check_update_type(Item_result type)
1541
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1542
case PLUGIN_VAR_INT:
1543
case PLUGIN_VAR_LONG:
1544
case PLUGIN_VAR_LONGLONG:
1545
return type != INT_RESULT;
1546
case PLUGIN_VAR_STR:
1547
return type != STRING_RESULT;
1554
SHOW_TYPE sys_var_pluginvar::show_type()
1556
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1557
case PLUGIN_VAR_BOOL:
1558
return SHOW_MY_BOOL;
1559
case PLUGIN_VAR_INT:
1561
case PLUGIN_VAR_LONG:
1563
case PLUGIN_VAR_LONGLONG:
1564
return SHOW_LONGLONG;
1565
case PLUGIN_VAR_STR:
1566
return SHOW_CHAR_PTR;
1567
case PLUGIN_VAR_ENUM:
1568
case PLUGIN_VAR_SET:
1577
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1579
assert(session || (type == OPT_GLOBAL));
1580
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1582
if (type == OPT_GLOBAL)
1585
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1587
return *(unsigned char**) (plugin_var+1);
1591
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1593
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1594
case PLUGIN_VAR_ENUM:
1595
return ((sysvar_enum_t *)plugin_var)->typelib;
1596
case PLUGIN_VAR_SET:
1597
return ((sysvar_set_t *)plugin_var)->typelib;
1598
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1599
return ((sessionvar_enum_t *)plugin_var)->typelib;
1600
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1601
return ((sessionvar_set_t *)plugin_var)->typelib;
1609
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1611
unsigned char* result;
1613
result= real_value_ptr(session, type);
1615
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
1616
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
1617
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
1619
char buffer[STRING_BUFFER_USUAL_SIZE];
1620
String str(buffer, sizeof(buffer), system_charset_info);
1621
TYPELIB *typelib= plugin_var_typelib();
1622
uint64_t mask= 1, value= *(uint64_t*) result;
1626
for (i= 0; i < typelib->count; i++, mask<<=1)
1628
if (!(value & mask))
1630
str.append(typelib->type_names[i], typelib->type_lengths[i]);
1634
result= (unsigned char*) "";
1636
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
1642
bool sys_var_pluginvar::check(Session *session, set_var *var)
1644
st_item_value_holder value;
1645
assert(is_readonly() || plugin_var->check);
1647
value.value_type= item_value_type;
1648
value.val_str= item_val_str;
1649
value.val_int= item_val_int;
1650
value.val_real= item_val_real;
1651
value.item= var->value;
1653
return is_readonly() ||
1654
plugin_var->check(session, plugin_var, &var->save_result, &value);
1658
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1663
assert(is_readonly() || plugin_var->update);
1668
pthread_mutex_lock(&LOCK_global_system_variables);
1669
tgt= real_value_ptr(session, type);
1670
src= ((void **) (plugin_var + 1) + 1);
1672
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1674
if (type != OPT_GLOBAL)
1675
src= real_value_ptr(session, OPT_GLOBAL);
1677
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1678
case PLUGIN_VAR_INT:
1679
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1681
case PLUGIN_VAR_LONG:
1682
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1684
case PLUGIN_VAR_LONGLONG:
1685
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1687
case PLUGIN_VAR_ENUM:
1688
src= &((sessionvar_enum_t*) plugin_var)->def_val;
1690
case PLUGIN_VAR_SET:
1691
src= &((sessionvar_set_t*) plugin_var)->def_val;
1693
case PLUGIN_VAR_BOOL:
1694
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1696
case PLUGIN_VAR_STR:
1697
src= &((sessionvar_str_t*) plugin_var)->def_val;
1704
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1705
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1706
session == current_session);
1708
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1710
plugin_var->update(session, plugin_var, tgt, src);
1711
pthread_mutex_unlock(&LOCK_global_system_variables);
1715
pthread_mutex_unlock(&LOCK_global_system_variables);
1716
plugin_var->update(session, plugin_var, tgt, src);
1721
bool sys_var_pluginvar::update(Session *session, set_var *var)
1725
assert(is_readonly() || plugin_var->update);
1727
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1728
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1729
session == current_session);
1734
pthread_mutex_lock(&LOCK_global_system_variables);
1735
tgt= real_value_ptr(session, var->type);
1737
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1739
/* variable we are updating has global scope, so we unlock after updating */
1740
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1741
pthread_mutex_unlock(&LOCK_global_system_variables);
1745
pthread_mutex_unlock(&LOCK_global_system_variables);
1746
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1752
#define OPTION_SET_LIMITS(type, options, opt) \
1753
options->var_type= type; \
1754
options->def_value= (opt)->def_val; \
1755
options->min_value= (opt)->min_val; \
1756
options->max_value= (opt)->max_val; \
1757
options->block_size= (long) (opt)->blk_sz
1760
static void plugin_opt_set_limits(struct my_option *options,
1761
const struct st_mysql_sys_var *opt)
1763
options->sub_size= 0;
1765
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1766
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1767
/* global system variables */
1768
case PLUGIN_VAR_INT:
1769
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1771
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1772
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1774
case PLUGIN_VAR_LONG:
1775
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1777
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1778
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1780
case PLUGIN_VAR_LONGLONG:
1781
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1783
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1784
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1786
case PLUGIN_VAR_ENUM:
1787
options->var_type= GET_ENUM;
1788
options->typelib= ((sysvar_enum_t*) opt)->typelib;
1789
options->def_value= ((sysvar_enum_t*) opt)->def_val;
1790
options->min_value= options->block_size= 0;
1791
options->max_value= options->typelib->count - 1;
1793
case PLUGIN_VAR_SET:
1794
options->var_type= GET_SET;
1795
options->typelib= ((sysvar_set_t*) opt)->typelib;
1796
options->def_value= ((sysvar_set_t*) opt)->def_val;
1797
options->min_value= options->block_size= 0;
1798
options->max_value= (1UL << options->typelib->count) - 1;
1800
case PLUGIN_VAR_BOOL:
1801
options->var_type= GET_BOOL;
1802
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1804
case PLUGIN_VAR_STR:
1805
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1806
GET_STR_ALLOC : GET_STR);
1807
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1809
/* threadlocal variables */
1810
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1811
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1813
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1814
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1816
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1817
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1819
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1820
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1822
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1823
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1825
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1826
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1828
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1829
options->var_type= GET_ENUM;
1830
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
1831
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
1832
options->min_value= options->block_size= 0;
1833
options->max_value= options->typelib->count - 1;
1835
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
1836
options->var_type= GET_SET;
1837
options->typelib= ((sessionvar_set_t*) opt)->typelib;
1838
options->def_value= ((sessionvar_set_t*) opt)->def_val;
1839
options->min_value= options->block_size= 0;
1840
options->max_value= (1UL << options->typelib->count) - 1;
1842
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1843
options->var_type= GET_BOOL;
1844
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1846
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1847
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1848
GET_STR_ALLOC : GET_STR);
1849
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1854
options->arg_type= REQUIRED_ARG;
1855
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1856
options->arg_type= NO_ARG;
1857
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1858
options->arg_type= OPT_ARG;
1861
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
1864
bool get_one_plugin_option(int, const struct my_option *, char *)
1870
static int construct_options(MEM_ROOT *mem_root, plugin::Module *tmp,
1871
my_option *options, bool can_disable)
1873
const char *plugin_name= tmp->getManifest().name;
1874
uint32_t namelen= strlen(plugin_name), optnamelen;
1875
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
1876
char *name= (char*) alloc_root(mem_root, buffer_length);
1877
bool *enabled_value= (bool*) alloc_root(mem_root, sizeof(bool));
1879
int index= 0, offset= 0;
1880
st_mysql_sys_var *opt, **plugin_option;
1883
/* support --skip-plugin-foo syntax */
1884
memcpy(name, plugin_name, namelen + 1);
1885
my_casedn_str(&my_charset_utf8_general_ci, name);
1886
sprintf(name+namelen+1, "plugin-%s", name);
1887
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
1889
for (p= name + namelen*2 + 8; p > name; p--)
1895
sprintf(name+namelen*2+10,
1896
"Enable %s plugin. Disable with --skip-%s (will save memory).",
1899
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
1900
20 + namelen + 20 + 1 == namelen * 4 + 67.
1903
options[0].comment= name + namelen*2 + 10;
1907
This whole code around variables and command line parameters is turd
1910
e.g. the below assignemnt of having the plugin alaways enabled is never
1911
changed so that './drizzled --skip-innodb --help' shows innodb as enabled.
1913
But this is just as broken as it was in MySQL and properly fixing everything
1914
is a decent amount of "future work"
1916
*enabled_value= true; /* by default, plugin enabled */
1918
options[1].name= (options[0].name= name) + namelen + 1;
1919
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
1920
options[0].var_type= options[1].var_type= GET_BOOL;
1921
options[0].arg_type= options[1].arg_type= NO_ARG;
1922
options[0].def_value= options[1].def_value= true;
1923
options[0].value= options[0].u_max_value=
1924
options[1].value= options[1].u_max_value= (char**) enabled_value;
1928
Two passes as the 2nd pass will take pointer addresses for use
1929
by my_getopt and register_var() in the first pass uses realloc
1932
for (plugin_option= tmp->getManifest().system_vars;
1933
plugin_option && *plugin_option; plugin_option++, index++)
1935
opt= *plugin_option;
1936
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1938
if (!(register_var(name, opt->name, opt->flags)))
1940
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1941
case PLUGIN_VAR_BOOL:
1942
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1944
case PLUGIN_VAR_INT:
1945
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1947
case PLUGIN_VAR_LONG:
1948
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1950
case PLUGIN_VAR_LONGLONG:
1951
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1953
case PLUGIN_VAR_STR:
1954
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1956
case PLUGIN_VAR_ENUM:
1957
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
1959
case PLUGIN_VAR_SET:
1960
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1963
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1964
opt->flags, plugin_name);
1969
for (plugin_option= tmp->getManifest().system_vars;
1970
plugin_option && *plugin_option; plugin_option++, index++)
1972
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1973
case PLUGIN_VAR_BOOL:
1975
opt->check= check_func_bool;
1977
opt->update= update_func_bool;
1979
case PLUGIN_VAR_INT:
1981
opt->check= check_func_int;
1983
opt->update= update_func_int;
1985
case PLUGIN_VAR_LONG:
1987
opt->check= check_func_long;
1989
opt->update= update_func_long;
1991
case PLUGIN_VAR_LONGLONG:
1993
opt->check= check_func_int64_t;
1995
opt->update= update_func_int64_t;
1997
case PLUGIN_VAR_STR:
1999
opt->check= check_func_str;
2002
opt->update= update_func_str;
2003
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2005
opt->flags|= PLUGIN_VAR_READONLY;
2006
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2007
"to be read-only: string variable without "
2008
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2009
opt->name, plugin_name);
2013
case PLUGIN_VAR_ENUM:
2015
opt->check= check_func_enum;
2017
opt->update= update_func_long;
2019
case PLUGIN_VAR_SET:
2021
opt->check= check_func_set;
2023
opt->update= update_func_int64_t;
2026
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2027
opt->flags, plugin_name);
2031
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2032
== PLUGIN_VAR_NOCMDOPT)
2037
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2042
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2044
optnamelen= strlen(opt->name);
2045
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2046
sprintf(optname, "%s-%s", name, opt->name);
2047
optnamelen= namelen + optnamelen + 1;
2051
/* this should not fail because register_var should create entry */
2052
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2054
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2055
"in plugin '%s'."), opt->name, plugin_name);
2059
*(int*)(opt + 1)= offset= v->offset;
2061
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2064
optname= (char*) memdup_root(mem_root, v->key + 1,
2065
(optnamelen= v->name_len) + 1);
2068
/* convert '_' to '-' */
2069
for (p= optname; *p; p++)
2073
options->name= optname;
2074
options->comment= opt->comment;
2075
options->app_type= opt;
2076
options->id= (options-1)->id + 1;
2078
plugin_opt_set_limits(options, opt);
2080
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2081
options->value= options->u_max_value= (char**)
2082
(global_system_variables.dynamic_variables_ptr + offset);
2084
options->value= options->u_max_value= *(char***) (opt + 1);
2086
options[1]= options[0];
2087
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2088
options[1].comment= 0; // hidden
2089
sprintf(p,"plugin-%s",optname);
2098
static my_option *construct_help_options(MEM_ROOT *mem_root, plugin::Module *p)
2100
st_mysql_sys_var **opt;
2103
uint32_t count= EXTRA_OPTIONS;
2105
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count+= 2) {};
2107
opts= (my_option*)alloc_root(mem_root, (sizeof(my_option) * count));
2111
memset(opts, 0, sizeof(my_option) * count);
2113
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->getName().c_str(), "MyISAM") == 0))
2115
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->getName().c_str(), "MEMORY") == 0))
2121
if (construct_options(mem_root, p, opts, can_disable))
2127
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
2129
plugin_sysvar_vec.push_back(var);
2132
void drizzle_del_plugin_sysvar()
2134
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
2135
while(iter != plugin_sysvar_vec.end())
2140
plugin_sysvar_vec.clear();
562
2145
test_plugin_options()
563
2146
tmp_root temporary scratch space
564
2147
plugin internal plugin structure
2148
argc user supplied arguments
2149
argv user supplied arguments
565
2150
default_enabled default plugin enable status
567
2152
0 SUCCESS - plugin should be enabled/loaded
569
2154
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)
2156
static int test_plugin_options(MEM_ROOT *tmp_root, plugin::Module *tmp,
2157
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);
2159
struct sys_var_chain chain= { NULL, NULL };
2161
st_mysql_sys_var **opt;
2162
my_option *opts= NULL;
2164
st_mysql_sys_var *o;
2165
struct st_bookmark *var;
2166
uint32_t len, count= EXTRA_OPTIONS;
2168
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
2169
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
2171
if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->getName().c_str(), "MyISAM") == 0))
2173
else if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->getName().c_str(), "MEMORY") == 0))
2178
if (count > EXTRA_OPTIONS || (*argc > 1))
2180
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2182
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
2185
memset(opts, 0, sizeof(my_option) * count);
2187
if (construct_options(tmp_root, tmp, opts, can_disable))
2189
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
2193
error= handle_options(argc, &argv, opts, get_one_plugin_option);
2194
(*argc)++; /* add back one for the program name */
2198
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2199
tmp->getName().c_str());
2207
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
2210
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
2213
if ((var= find_bookmark(tmp->getName().c_str(), o->name, o->flags)))
2214
v= new sys_var_pluginvar(var->key + 1, o);
2217
len= tmp->getName().length() + strlen(o->name) + 2;
2218
string vname(tmp->getName());
2219
vname.push_back('-');
2220
vname.append(o->name);
2221
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
2222
string::iterator p= vname.begin();
2223
while (p != vname.end())
2230
v= new sys_var_pluginvar(vname, o);
2232
assert(v); /* check that an object was actually constructed */
2234
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
2236
Add to the chain of variables.
2237
Done like this for easier debugging so that the
2238
pointer to v is not lost on optimized builds.
2240
v->chain_sys_var(&chain);
2244
chain.last->setNext(NULL);
2245
if (mysql_add_sys_var_chain(chain.first, NULL))
2247
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2248
tmp->getName().c_str());
2251
tmp->system_vars= chain.first;
2258
my_cleanup_options(opts);