12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
27
#include <boost/program_options.hpp>
29
#include "drizzled/option.h"
30
#include "drizzled/internal/m_string.h"
32
#include "drizzled/plugin.h"
33
#include "drizzled/module/load_list.h"
34
#include "drizzled/module/library.h"
35
#include "drizzled/module/registry.h"
36
#include "drizzled/module/option_context.h"
37
#include "drizzled/sql_parse.h"
38
#include "drizzled/show.h"
39
#include "drizzled/cursor.h"
40
#include "drizzled/set_var.h"
41
#include "drizzled/session.h"
42
#include "drizzled/item/null.h"
43
#include "drizzled/error.h"
44
#include "drizzled/gettext.h"
45
#include "drizzled/errmsg_print.h"
46
#include "drizzled/strfunc.h"
47
#include "drizzled/pthread_globals.h"
48
#include "drizzled/util/tokenize.h"
50
#include <boost/foreach.hpp>
52
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
61
/** These exist just to prevent symbols from being optimized out */
62
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
drizzled::module::Manifest *drizzled_builtins[]=
67
PANDORA_BUILTIN_SYMBOLS_LIST, NULL
69
drizzled::module::Manifest *drizzled_load_builtins[]=
71
PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
78
typedef vector<string> PluginOptions;
79
static PluginOptions opt_plugin_load;
80
static PluginOptions opt_plugin_add;
81
static PluginOptions opt_plugin_remove;
82
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <drizzled/server_includes.h>
17
#include <mysys/my_getopt.h>
18
#include <authentication.h>
20
#include <drizzled/drizzled_error_messages.h>
21
#define REPORT_TO_LOG 1
22
#define REPORT_TO_USER 2
24
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
25
#define plugin_int_to_ref(A) &(A)
27
extern struct st_mysql_plugin *mysqld_builtins[];
29
char *opt_plugin_load= NULL;
30
char *opt_plugin_dir_ptr;
31
char opt_plugin_dir[FN_REFLEN];
33
When you ad a new plugin type, add both a string and make sure that the
34
init and deinit array are correctly updated.
36
const LEX_STRING plugin_type_names[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
38
{ C_STRING_WITH_LEN("DAEMON") },
39
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
40
{ C_STRING_WITH_LEN("INFORMATION SCHEMA") },
41
{ C_STRING_WITH_LEN("UDF") },
42
{ C_STRING_WITH_LEN("UDA") },
43
{ C_STRING_WITH_LEN("AUDIT") },
44
{ C_STRING_WITH_LEN("LOGGER") },
45
{ C_STRING_WITH_LEN("AUTH") }
48
extern int initialize_schema_table(st_plugin_int *plugin);
49
extern int finalize_schema_table(st_plugin_int *plugin);
51
extern int initialize_udf(st_plugin_int *plugin);
52
extern int finalize_udf(st_plugin_int *plugin);
55
The number of elements in both plugin_type_initialize and
56
plugin_type_deinitialize should equal to the number of plugins
59
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
62
ha_initialize_handlerton, /* Storage Engine */
63
initialize_schema_table, /* Information Schema */
64
initialize_udf, /* UDF */
67
logging_initializer, /* Logger */
68
authentication_initializer /* Auth */
71
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
74
ha_finalize_handlerton, /* Storage Engine */
75
finalize_schema_table, /* Information Schema */
76
finalize_udf, /* UDF */
79
logging_finalizer, /* Logger */
80
authentication_finalizer /* Auth */
83
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
85
85
/* Note that 'int version' must be the first field of every plugin
86
86
sub-structure (plugin->info).
89
static bool initialized= false;
89
static bool initialized= 0;
91
static DYNAMIC_ARRAY plugin_dl_array;
92
static DYNAMIC_ARRAY plugin_array;
93
static HASH plugin_hash[DRIZZLE_MAX_PLUGIN_TYPE_NUM];
92
94
static bool reap_needed= false;
95
static int plugin_array_version=0;
95
98
write-lock on LOCK_system_variables_hash is required before modifying
96
99
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
99
static uint32_t global_variables_dynamic_size= 0;
101
static MEM_ROOT plugin_mem_root;
102
static uint global_variables_dynamic_size= 0;
103
static HASH bookmark_hash;
103
107
hidden part of opaque value passed to variable check functions.
104
108
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
110
struct st_item_value_holder : public st_mysql_value
117
stored in bookmark_hash, this structure is never removed from the
118
hash and is used to mark a single offset for a thd local variable
119
even if plugins have been uninstalled and reinstalled, repeatedly.
120
This structure is allocated from plugin_mem_root.
122
The key format is as follows:
123
1 byte - variable type code
124
name_len bytes - variable name
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
137
skeleton of a plugin variable - portion of structure common to all.
139
struct st_mysql_sys_var
141
DRIZZLE_PLUGIN_VAR_HEADER;
146
sys_var class for access to all plugin variables visible to the user
148
class sys_var_pluginvar: public sys_var
151
struct st_plugin_int *plugin;
152
struct st_mysql_sys_var *plugin_var;
154
static void *operator new(size_t size, MEM_ROOT *mem_root)
155
{ return (void*) alloc_root(mem_root, (uint) size); }
156
static void operator delete(void *ptr_arg __attribute__((unused)),
157
size_t size __attribute__((unused)))
158
{ TRASH(ptr_arg, size); }
160
sys_var_pluginvar(const char *name_arg,
161
struct st_mysql_sys_var *plugin_var_arg)
162
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
163
sys_var_pluginvar *cast_pluginvar() { return this; }
164
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
165
bool check_type(enum_var_type type)
166
{ return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
167
bool check_update_type(Item_result type);
168
SHOW_TYPE show_type();
169
uchar* real_value_ptr(THD *thd, enum_var_type type);
170
TYPELIB* plugin_var_typelib(void);
171
uchar* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
172
bool check(THD *thd, set_var *var);
173
bool check_default(enum_var_type type __attribute__((unused)))
174
{ return is_readonly(); }
175
void set_default(THD *thd,
176
enum_var_type type __attribute__((unused)));
177
bool update(THD *thd, 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);
182
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
184
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
186
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
187
struct st_plugin_int **);
188
static void unlock_variables(THD *thd, struct system_variables *vars);
189
static void cleanup_variables(THD *thd, struct system_variables *vars);
190
static void plugin_vars_free_values(sys_var *vars);
191
static void plugin_opt_set_limits(struct my_option *options,
192
const struct st_mysql_sys_var *opt);
193
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
194
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
195
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
197
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
198
static void reap_plugins(void);
144
201
/* declared in set_var.cc */
145
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
202
extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
203
extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
204
const char *name, int64_t val);
206
/****************************************************************************
207
Value type thunks, allows the C world to play in the C++ world
208
****************************************************************************/
210
static int item_value_type(struct st_mysql_value *value)
212
switch (((st_item_value_holder*)value)->item->result_type()) {
214
return DRIZZLE_VALUE_TYPE_INT;
216
return DRIZZLE_VALUE_TYPE_REAL;
218
return DRIZZLE_VALUE_TYPE_STRING;
222
static const char *item_val_str(struct st_mysql_value *value,
223
char *buffer, int *length)
225
String str(buffer, *length, system_charset_info), *res;
226
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
228
*length= res->length();
229
if (res->c_ptr_quick() == buffer)
233
Lets be nice and create a temporary string since the
236
return current_thd->strmake(res->c_ptr_quick(), res->length());
240
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
242
Item *item= ((st_item_value_holder*)value)->item;
243
*buf= item->val_int();
250
static int item_val_real(struct st_mysql_value *value, double *buf)
252
Item *item= ((st_item_value_holder*)value)->item;
253
*buf= item->val_real();
148
260
/****************************************************************************
149
261
Plugin support code
150
262
****************************************************************************/
264
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
267
struct st_plugin_dl *tmp;
268
for (i= 0; i < plugin_dl_array.elements; i++)
270
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
271
if (tmp->ref_count &&
272
! my_strnncoll(files_charset_info,
273
(const uchar *)dl->str, dl->length,
274
(const uchar *)tmp->dl.str, tmp->dl.length))
280
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
283
struct st_plugin_dl *tmp;
284
for (i= 0; i < plugin_dl_array.elements; i++)
286
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
287
if (! tmp->ref_count)
289
memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
293
if (insert_dynamic(&plugin_dl_array, (uchar*)&plugin_dl))
295
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
296
struct st_plugin_dl **)=
297
(struct st_plugin_dl *) memdup_root(&plugin_mem_root, (uchar*)plugin_dl,
298
sizeof(struct st_plugin_dl));
302
static inline void free_plugin_mem(struct st_plugin_dl *p)
306
my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR));
310
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
312
char dlpath[FN_REFLEN];
313
uint plugin_dir_len, dummy_errors, dlpathlen;
314
struct st_plugin_dl *tmp, plugin_dl;
316
plugin_dir_len= strlen(opt_plugin_dir);
318
Ensure that the dll doesn't have a path.
319
This is done to ensure that only approved libraries from the
320
plugin directory are used (to make this even remotely secure).
322
if (strchr(dl->str, FN_LIBCHAR) ||
323
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
324
system_charset_info, 1) ||
325
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
327
if (report & REPORT_TO_USER)
328
my_error(ER_UDF_NO_PATHS, MYF(0));
329
if (report & REPORT_TO_LOG)
330
sql_print_error(ER(ER_UDF_NO_PATHS));
333
/* If this dll is already loaded just increase ref_count. */
334
if ((tmp= plugin_dl_find(dl)))
339
memset(&plugin_dl, 0, sizeof(plugin_dl));
340
/* Compile dll path */
342
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS) -
344
plugin_dl.ref_count= 1;
345
/* Open new dll handle */
346
if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
348
const char *errmsg=dlerror();
349
if (!strncmp(dlpath, errmsg, dlpathlen))
350
{ // if errmsg starts from dlpath, trim this prefix.
352
if (*errmsg == ':') errmsg++;
353
if (*errmsg == ' ') errmsg++;
355
if (report & REPORT_TO_USER)
356
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
357
if (report & REPORT_TO_LOG)
358
sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
362
/* Find plugin declarations */
363
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
365
free_plugin_mem(&plugin_dl);
366
if (report & REPORT_TO_USER)
367
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
368
if (report & REPORT_TO_LOG)
369
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
373
plugin_dl.plugins= (struct st_mysql_plugin *)sym;
375
/* Duplicate and convert dll name */
376
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
377
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
379
free_plugin_mem(&plugin_dl);
380
if (report & REPORT_TO_USER)
381
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
382
if (report & REPORT_TO_LOG)
383
sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
386
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
387
files_charset_info, dl->str, dl->length, system_charset_info,
389
plugin_dl.dl.str[plugin_dl.dl.length]= 0;
390
/* Add this dll to array */
391
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
393
free_plugin_mem(&plugin_dl);
394
if (report & REPORT_TO_USER)
395
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
396
if (report & REPORT_TO_LOG)
397
sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
404
static void plugin_dl_del(const LEX_STRING *dl)
408
for (i= 0; i < plugin_dl_array.elements; i++)
410
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
411
struct st_plugin_dl **);
412
if (tmp->ref_count &&
413
! my_strnncoll(files_charset_info,
414
(const uchar *)dl->str, dl->length,
415
(const uchar *)tmp->dl.str, tmp->dl.length))
417
/* Do not remove this element, unless no other plugin uses this dll. */
418
if (! --tmp->ref_count)
420
free_plugin_mem(tmp);
421
memset(tmp, 0, sizeof(struct st_plugin_dl));
430
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
436
if (type == DRIZZLE_ANY_PLUGIN)
438
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
440
struct st_plugin_int *plugin= (st_plugin_int *)
441
hash_search(&plugin_hash[i], (const uchar *)name->str, name->length);
447
return((st_plugin_int *)
448
hash_search(&plugin_hash[type], (const uchar *)name->str, name->length));
453
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
455
SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
456
struct st_plugin_int *plugin;
457
if ((plugin= plugin_find_internal(name, type)))
459
rc= SHOW_OPTION_DISABLED;
460
if (plugin->state == PLUGIN_IS_READY)
467
bool plugin_is_ready(const LEX_STRING *name, int type)
470
if (plugin_status(name, type) == SHOW_OPTION_YES)
476
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
478
LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
479
return plugin_status(&plugin_name, plugin_type);
483
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
485
st_plugin_int *pi= plugin_ref_to_int(rc);
487
if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
491
For debugging, we do an additional malloc which allows the
492
memory manager and/or valgrind to track locked references and
493
double unlocks to aid resolving reference counting.problems.
495
if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
502
insert_dynamic(&lex->plugins, (uchar*)&plugin);
509
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
511
LEX *lex= thd ? thd->lex : 0;
513
rc= my_intern_plugin_lock_ci(lex, *ptr);
518
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
521
LEX *lex= thd ? thd->lex : 0;
523
st_plugin_int *plugin;
524
if ((plugin= plugin_find_internal(name, type)))
525
rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
530
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
533
struct st_plugin_int *tmp;
534
for (i= 0; i < plugin_array.elements; i++)
536
tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
537
if (tmp->state == PLUGIN_IS_FREED)
539
memcpy(tmp, plugin, sizeof(struct st_plugin_int));
543
if (insert_dynamic(&plugin_array, (uchar*)&plugin))
545
tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
546
struct st_plugin_int **)=
547
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)plugin,
548
sizeof(struct st_plugin_int));
157
555
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)
557
static bool plugin_add(MEM_ROOT *tmp_root,
558
const LEX_STRING *name, const LEX_STRING *dl,
559
int *argc, char **argv, int report)
166
if (registry.find(library->getName()))
561
struct st_plugin_int tmp;
562
struct st_mysql_plugin *plugin;
563
if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
168
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
169
library->getName().c_str());
565
if (report & REPORT_TO_USER)
566
my_error(ER_UDF_EXISTS, MYF(0), name->str);
567
if (report & REPORT_TO_LOG)
568
sql_print_error(ER(ER_UDF_EXISTS), name->str);
173
module::Module *tmp= NULL;
571
/* Clear the whole struct to catch future extensions. */
572
memset(&tmp, 0, sizeof(tmp));
573
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
174
575
/* 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))
226
errmsg_printf(ERRMSG_LVL_ERROR,
227
_("Plugin '%s' init function returned error.\n"),
228
module->getName().c_str());
232
module->isInited= true;
239
inline static void dashes_to_underscores(std::string &name_in,
240
char from= '-', char to= '_')
242
for (string::iterator p= name_in.begin();
253
inline static void underscores_to_dashes(std::string &name_in)
255
return dashes_to_underscores(name_in, '_', '-');
258
static void compose_plugin_options(vector<string> &target,
259
vector<string> options)
261
for (vector<string>::iterator it= options.begin();
265
tokenize(*it, target, ",", true);
267
for (vector<string>::iterator it= target.begin();
271
dashes_to_underscores(*it);
275
void compose_plugin_add(vector<string> options)
277
compose_plugin_options(opt_plugin_add, options);
280
void compose_plugin_remove(vector<string> options)
282
compose_plugin_options(opt_plugin_remove, options);
285
void notify_plugin_load(string in_plugin_load)
287
tokenize(in_plugin_load, opt_plugin_load, ",", true);
576
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
578
uint name_len= strlen(plugin->name);
579
if (plugin->type >= 0 && plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
580
! my_strnncoll(system_charset_info,
581
(const uchar *)name->str, name->length,
582
(const uchar *)plugin->name,
585
struct st_plugin_int *tmp_plugin_ptr;
588
tmp.name.str= (char *)plugin->name;
589
tmp.name.length= name_len;
591
tmp.state= PLUGIN_IS_UNINITIALIZED;
592
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
594
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
596
plugin_array_version++;
597
if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
599
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
602
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
604
mysql_del_sys_var_chain(tmp.system_vars);
607
/* plugin was disabled */
612
if (report & REPORT_TO_USER)
613
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
614
if (report & REPORT_TO_LOG)
615
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
622
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
624
if (plugin->plugin->status_vars)
628
We have a problem right now where we can not prepend without
629
breaking backwards compatibility. We will fix this shortly so
630
that engines have "use names" and we wil use those for
631
CREATE TABLE, and use the plugin name then for adding automatic
635
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
638
remove_status_vars(array);
640
remove_status_vars(plugin->plugin->status_vars);
641
#endif /* FIX_LATER */
644
if (plugin_type_deinitialize[plugin->plugin->type])
646
if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
648
sql_print_error(_("Plugin '%s' of type %s failed deinitialization"),
649
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
652
else if (plugin->plugin->deinit)
653
plugin->plugin->deinit(plugin);
655
plugin->state= PLUGIN_IS_UNINITIALIZED;
658
We do the check here because NDB has a worker THD which doesn't
659
exit until NDB is shut down.
661
if (ref_check && plugin->ref_count)
662
sql_print_error(_("Plugin '%s' has ref_count=%d after deinitialization."),
663
plugin->name.str, plugin->ref_count);
667
static void plugin_del(struct st_plugin_int *plugin)
669
/* Free allocated strings before deleting the plugin. */
670
plugin_vars_free_values(plugin->system_vars);
671
hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
672
if (plugin->plugin_dl)
673
plugin_dl_del(&plugin->plugin_dl->dl);
674
plugin->state= PLUGIN_IS_FREED;
675
plugin_array_version++;
676
rw_wrlock(&LOCK_system_variables_hash);
677
mysql_del_sys_var_chain(plugin->system_vars);
678
rw_unlock(&LOCK_system_variables_hash);
679
free_root(&plugin->mem_root, MYF(0));
683
static void reap_plugins(void)
686
struct st_plugin_int *plugin, **reap, **list;
692
count= plugin_array.elements;
693
reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
696
for (idx= 0; idx < count; idx++)
698
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
699
if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
701
/* change the status flag to prevent reaping by another thread */
702
plugin->state= PLUGIN_IS_DYING;
708
while ((plugin= *(--list)))
709
plugin_deinitialize(plugin, true);
711
while ((plugin= *(--reap)))
717
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
725
pi= plugin_ref_to_int(plugin);
727
my_free((uchar*) plugin, MYF(MY_WME));
732
Remove one instance of this plugin from the use list.
733
We are searching backwards so that plugins locked last
734
could be unlocked faster - optimizing for LIFO semantics.
736
for (i= lex->plugins.elements - 1; i >= 0; i--)
737
if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
739
delete_dynamic_element(&lex->plugins, i);
745
assert(pi->ref_count);
748
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
755
void plugin_unlock(THD *thd, plugin_ref plugin)
757
LEX *lex= thd ? thd->lex : 0;
760
intern_plugin_unlock(lex, plugin);
765
void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
767
LEX *lex= thd ? thd->lex : 0;
770
intern_plugin_unlock(lex, *list++);
775
static int plugin_initialize(struct st_plugin_int *plugin)
778
if (plugin_type_initialize[plugin->plugin->type])
780
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
782
sql_print_error(_("Plugin '%s' registration as a %s failed."),
783
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
787
else if (plugin->plugin->init)
789
if (plugin->plugin->init(plugin))
791
sql_print_error(_("Plugin '%s' init function returned error."),
797
plugin->state= PLUGIN_IS_READY;
799
if (plugin->plugin->status_vars)
803
We have a problem right now where we can not prepend without
804
breaking backwards compatibility. We will fix this shortly so
805
that engines have "use names" and we wil use those for
806
CREATE TABLE, and use the plugin name then for adding automatic
810
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
813
if (add_status_vars(array)) // add_status_vars makes a copy
816
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
817
#endif /* FIX_LATER */
821
set the plugin attribute of plugin's sys vars so they are pointing
824
if (plugin->system_vars)
826
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
832
var= var->next->cast_pluginvar();
842
extern "C" uchar *get_plugin_hash_key(const uchar *, size_t *, bool);
843
extern "C" uchar *get_bookmark_hash_key(const uchar *, size_t *, bool);
846
uchar *get_plugin_hash_key(const uchar *buff, size_t *length,
847
bool not_used __attribute__((unused)))
849
struct st_plugin_int *plugin= (st_plugin_int *)buff;
850
*length= (uint)plugin->name.length;
851
return((uchar *)plugin->name.str);
855
uchar *get_bookmark_hash_key(const uchar *buff, size_t *length,
856
bool not_used __attribute__((unused)))
858
struct st_bookmark *var= (st_bookmark *)buff;
859
*length= var->name_len + 1;
860
return (uchar*) var->key;
291
865
The logic is that we first load and initialize all compiled in plugins.
295
869
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)
871
int plugin_init(int *argc, char **argv, int flags)
300
memory::Root tmp_root(4096);
874
struct st_mysql_plugin **builtins;
875
struct st_mysql_plugin *plugin;
876
struct st_plugin_int tmp, *plugin_ptr, **reap;
882
init_alloc_root(&plugin_mem_root, 4096, 4096);
883
init_alloc_root(&tmp_root, 4096, 4096);
885
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
886
get_bookmark_hash_key, NULL, HASH_UNIQUE))
890
if (my_init_dynamic_array(&plugin_dl_array,
891
sizeof(struct st_plugin_dl *),16,16) ||
892
my_init_dynamic_array(&plugin_array,
893
sizeof(struct st_plugin_int *),16,16))
896
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
898
if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
899
get_plugin_hash_key, NULL, HASH_UNIQUE))
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
906
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);
908
for (builtins= mysqld_builtins; *builtins; builtins++)
349
tmp_root.free_root(MYF(0));
910
for (plugin= *builtins; plugin->name; plugin++)
912
memset(&tmp, 0, sizeof(tmp));
914
tmp.name.str= (char *)plugin->name;
915
tmp.name.length= strlen(plugin->name);
917
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
918
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
921
if (register_builtin(plugin, &tmp, &plugin_ptr))
924
if (plugin_initialize(plugin_ptr))
928
initialize the global default storage engine so that it may
929
not be null in any child thread.
931
if (my_strcasecmp(&my_charset_latin1, plugin->name, "MyISAM") == 0)
933
assert(!global_system_variables.table_plugin);
934
global_system_variables.table_plugin=
935
my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
936
assert(plugin_ptr->ref_count == 1);
353
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
941
/* should now be set to MyISAM storage engine */
942
assert(global_system_variables.table_plugin);
357
944
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
945
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
362
tmp_root.free_root(MYF(0));
948
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
951
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
374
955
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())
958
reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
961
for (i= 0; i < plugin_array.elements; i++)
381
module::Module *module= (*modules).second;
383
if (module->isInited == false)
963
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
964
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
385
if (plugin_initialize(registry, module))
966
if (plugin_initialize(plugin_ptr))
387
registry.remove(module);
968
plugin_ptr->state= PLUGIN_IS_DYING;
969
*(reap++)= plugin_ptr;
394
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
396
value.second->prime();
403
public unary_function<string, bool>
405
const string to_match;
407
PrunePlugin& operator=(const PrunePlugin&);
409
explicit PrunePlugin(const string &match_in) :
413
result_type operator()(const string &match_against)
415
return match_against == to_match;
419
static void plugin_prune_list(vector<string> &plugin_list,
420
const vector<string> &plugins_to_remove)
422
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
423
iter != plugins_to_remove.end();
426
plugin_list.erase(remove_if(plugin_list.begin(),
975
Check if any plugins have to be reaped
977
while ((plugin_ptr= *(--reap)))
979
plugin_deinitialize(plugin_ptr, true);
980
plugin_del(plugin_ptr);
986
free_root(&tmp_root, MYF(0));
992
free_root(&tmp_root, MYF(0));
997
static bool register_builtin(struct st_mysql_plugin *plugin,
998
struct st_plugin_int *tmp,
999
struct st_plugin_int **ptr)
1002
tmp->state= PLUGIN_IS_UNINITIALIZED;
1006
if (insert_dynamic(&plugin_array, (uchar*)&tmp))
1009
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1010
struct st_plugin_int **)=
1011
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)tmp,
1012
sizeof(struct st_plugin_int));
1014
if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr))
434
1022
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,
1024
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
442
module::Library *library= NULL;
444
for (set<string>::const_iterator iter= plugin_list.begin();
445
iter != plugin_list.end();
1027
char buffer[FN_REFLEN];
1028
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
1029
struct st_plugin_dl *plugin_dl;
1030
struct st_mysql_plugin *plugin;
448
const string plugin_name(*iter);
450
library= registry.addLibrary(plugin_name, builtin);
1034
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());
1036
sql_print_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());
1040
switch ((*(p++)= *(list++))) {
1042
list= NULL; /* terminate the loop */
1044
case ':': /* can't use this as delimiter as it may be drive letter */
1046
str->str[str->length]= '\0';
1047
if (str == &name) // load all plugins in named module
1051
p--; /* reset pointer */
1056
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1058
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
1060
name.str= (char *) plugin->name;
1061
name.length= strlen(name.str);
1063
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1064
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1067
plugin_dl_del(&dl); // reduce ref count
1072
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1073
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1076
name.length= dl.length= 0;
1077
dl.str= NULL; name.str= p= buffer;
1084
name.str[name.length]= '\0';
1096
sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
474
void module_shutdown(module::Registry ®istry)
1102
void plugin_shutdown(void)
1104
uint i, count= plugin_array.elements, free_slots= 0;
1105
struct st_plugin_int **plugins, *plugin;
1106
struct st_plugin_dl **dl;
477
1108
if (initialized)
479
1110
reap_needed= true;
481
reap_plugins(registry);
482
unlock_variables(NULL, &global_system_variables);
483
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
1113
We want to shut down plugins in a reasonable order, this will
1114
become important when we have plugins which depend upon each other.
1115
Circular references cannot be reaped so they are forced afterwards.
1116
TODO: Have an additional step here to notify all active plugins that
1117
shutdown is requested to allow plugins to deinitialize in parallel.
1119
while (reap_needed && (count= plugin_array.elements))
1122
for (i= free_slots= 0; i < count; i++)
1124
plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1125
switch (plugin->state) {
1126
case PLUGIN_IS_READY:
1127
plugin->state= PLUGIN_IS_DELETED;
1130
case PLUGIN_IS_FREED:
1131
case PLUGIN_IS_UNINITIALIZED:
1139
release any plugin references held.
1141
unlock_variables(NULL, &global_system_variables);
1142
unlock_variables(NULL, &max_system_variables);
1146
if (count > free_slots)
1147
sql_print_warning(_("Forcing shutdown of %d plugins"),
1148
count - free_slots);
1150
plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1153
If we have any plugins which did not die cleanly, we force shutdown
1155
for (i= 0; i < count; i++)
1157
plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1158
/* change the state to ensure no reaping races */
1159
if (plugins[i]->state == PLUGIN_IS_DELETED)
1160
plugins[i]->state= PLUGIN_IS_DYING;
1164
We loop through all plugins and call deinit() if they have one.
1166
for (i= 0; i < count; i++)
1167
if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1169
sql_print_information(_("Plugin '%s' will be forced to shutdown"),
1170
plugins[i]->name.str);
1172
We are forcing deinit on plugins so we don't want to do a ref_count
1173
check until we have processed all the plugins.
1175
plugin_deinitialize(plugins[i], false);
1179
We defer checking ref_counts until after all plugins are deinitialized
1180
as some may have worker threads holding on to plugin references.
1182
for (i= 0; i < count; i++)
1184
if (plugins[i]->ref_count)
1185
sql_print_error(_("Plugin '%s' has ref_count=%d after shutdown."),
1186
plugins[i]->name.str, plugins[i]->ref_count);
1187
if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1188
plugin_del(plugins[i]);
1192
Now we can deallocate all memory.
1195
cleanup_variables(NULL, &global_system_variables);
1196
cleanup_variables(NULL, &max_system_variables);
491
1203
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
1205
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1206
hash_free(&plugin_hash[i]);
1207
delete_dynamic(&plugin_array);
1209
count= plugin_dl_array.elements;
1210
dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1211
for (i= 0; i < count; i++)
1212
dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1213
for (i= 0; i < plugin_dl_array.elements; i++)
1214
free_plugin_mem(dl[i]);
1216
delete_dynamic(&plugin_dl_array);
1218
hash_free(&bookmark_hash);
1219
free_root(&plugin_mem_root, MYF(0));
494
1221
global_variables_dynamic_size= 0;
1227
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1228
int type, uint state_mask, void *arg)
1231
struct st_plugin_int *plugin, **plugins;
1232
int version=plugin_array_version;
1237
state_mask= ~state_mask; // do it only once
1239
total= type == DRIZZLE_ANY_PLUGIN ? plugin_array.elements
1240
: plugin_hash[type].records;
1242
Do the alloca out here in case we do have a working alloca:
1243
leaving the nested stack frame invalidates alloca allocation.
1245
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1246
if (type == DRIZZLE_ANY_PLUGIN)
1248
for (idx= 0; idx < total; idx++)
1250
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1251
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1256
HASH *hash= plugin_hash + type;
1257
for (idx= 0; idx < total; idx++)
1259
plugin= (struct st_plugin_int *) hash_element(hash, idx);
1260
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1263
for (idx= 0; idx < total; idx++)
1265
if (unlikely(version != plugin_array_version))
1267
for (uint i=idx; i < total; i++)
1268
if (plugins[i] && plugins[i]->state & state_mask)
1271
plugin= plugins[idx];
1272
/* It will stop iterating on first engine error when "func" returns true */
1273
if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
1285
/****************************************************************************
1286
Internal type declarations for variables support
1287
****************************************************************************/
1289
#undef DRIZZLE_SYSVAR_NAME
1290
#define DRIZZLE_SYSVAR_NAME(name) name
1291
#define PLUGIN_VAR_TYPEMASK 0x007f
1293
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1295
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1296
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_bool_t, bool);
1297
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1298
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_str_t, char *);
1300
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1301
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
1302
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1303
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
1305
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1306
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1307
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1308
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1309
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1310
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1312
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int_t, int);
1313
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_long_t, long);
1314
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int64_t_t, int64_t);
1315
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint_t, uint);
1316
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
1317
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint64_t_t, uint64_t);
1319
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
1322
/****************************************************************************
1323
default variable data check and update functions
1324
****************************************************************************/
1326
static int check_func_bool(THD *thd __attribute__((unused)),
1327
struct st_mysql_sys_var *var,
1328
void *save, st_mysql_value *value)
1330
char buff[STRING_BUFFER_USUAL_SIZE];
1331
const char *strvalue= "NULL", *str;
1335
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1337
length= sizeof(buff);
1338
if (!(str= value->val_str(value, buff, &length)) ||
1339
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
1348
if (value->val_int(value, &tmp) < 0)
1358
*(int*)save= -result;
1361
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1366
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
1367
void *save, st_mysql_value *value)
1371
struct my_option options;
1372
value->val_int(value, &tmp);
1373
plugin_opt_set_limits(&options, var);
1375
if (var->flags & PLUGIN_VAR_UNSIGNED)
1376
*(uint *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
1379
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1381
return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1382
var->name, (int64_t) tmp);
1386
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
1387
void *save, st_mysql_value *value)
1391
struct my_option options;
1392
value->val_int(value, &tmp);
1393
plugin_opt_set_limits(&options, var);
1395
if (var->flags & PLUGIN_VAR_UNSIGNED)
1396
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
1399
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1401
return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1402
var->name, (int64_t) tmp);
1406
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
1407
void *save, st_mysql_value *value)
1411
struct my_option options;
1412
value->val_int(value, &tmp);
1413
plugin_opt_set_limits(&options, var);
1415
if (var->flags & PLUGIN_VAR_UNSIGNED)
1416
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
1419
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1421
return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1422
var->name, (int64_t) tmp);
1425
static int check_func_str(THD *thd,
1426
struct st_mysql_sys_var *var __attribute__((unused)),
1427
void *save, st_mysql_value *value)
1429
char buff[STRING_BUFFER_USUAL_SIZE];
1433
length= sizeof(buff);
1434
if ((str= value->val_str(value, buff, &length)))
1435
str= thd->strmake(str, length);
1436
*(const char**)save= str;
1441
static int check_func_enum(THD *thd __attribute__((unused)),
1442
struct st_mysql_sys_var *var,
1443
void *save, st_mysql_value *value)
1445
char buff[STRING_BUFFER_USUAL_SIZE];
1446
const char *strvalue= "NULL", *str;
1452
if (var->flags & PLUGIN_VAR_THDLOCAL)
1453
typelib= ((thdvar_enum_t*) var)->typelib;
1455
typelib= ((sysvar_enum_t*) var)->typelib;
1457
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1459
length= sizeof(buff);
1460
if (!(str= value->val_str(value, buff, &length)))
1462
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1470
if (value->val_int(value, &tmp))
1472
if (tmp >= typelib->count)
1480
*(long*)save= result;
1483
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1488
static int check_func_set(THD *thd __attribute__((unused)),
1489
struct st_mysql_sys_var *var,
1490
void *save, st_mysql_value *value)
1492
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1493
const char *strvalue= "NULL", *str;
1500
if (var->flags & PLUGIN_VAR_THDLOCAL)
1501
typelib= ((thdvar_set_t*) var)->typelib;
1503
typelib= ((sysvar_set_t*)var)->typelib;
1505
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1507
length= sizeof(buff);
1508
if (!(str= value->val_str(value, buff, &length)))
1510
result= find_set(typelib, str, length, NULL,
1511
&error, &error_len, ¬_used);
1514
strmake(buff, error, min(sizeof(buff), (unsigned long)error_len));
1521
if (value->val_int(value, (int64_t *)&result))
1523
if (unlikely((result >= (1ULL << typelib->count)) &&
1524
(typelib->count < sizeof(long)*8)))
1526
llstr(result, buff);
1531
*(uint64_t*)save= result;
1534
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1539
static void update_func_bool(THD *thd __attribute__((unused)),
1540
struct st_mysql_sys_var *var __attribute__((unused)),
1541
void *tgt, const void *save)
1543
*(bool *) tgt= *(int *) save ? 1 : 0;
1547
static void update_func_int(THD *thd __attribute__((unused)),
1548
struct st_mysql_sys_var *var __attribute__((unused)),
1549
void *tgt, const void *save)
1551
*(int *)tgt= *(int *) save;
1555
static void update_func_long(THD *thd __attribute__((unused)),
1556
struct st_mysql_sys_var *var __attribute__((unused)),
1557
void *tgt, const void *save)
1559
*(long *)tgt= *(long *) save;
1563
static void update_func_int64_t(THD *thd __attribute__((unused)),
1564
struct st_mysql_sys_var *var __attribute__((unused)),
1565
void *tgt, const void *save)
1567
*(int64_t *)tgt= *(uint64_t *) save;
1571
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
1572
void *tgt, const void *save)
1574
char *old= *(char **) tgt;
1575
*(char **)tgt= *(char **) save;
1576
if (var->flags & PLUGIN_VAR_MEMALLOC)
1578
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
1579
my_free(old, MYF(0));
500
1586
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
509
void plugin_sessionvar_init(Session *session)
511
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
514
session->variables= global_system_variables;
515
session->variables.storage_engine= NULL;
1589
sys_var *find_sys_var(THD *thd, const char *str, uint length)
1592
sys_var_pluginvar *pi= NULL;
1595
rw_rdlock(&LOCK_system_variables_hash);
1596
if ((var= intern_find_sys_var(str, length, false)) &&
1597
(pi= var->cast_pluginvar()))
1599
rw_unlock(&LOCK_system_variables_hash);
1600
LEX *lex= thd ? thd->lex : 0;
1601
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1602
var= NULL; /* failed to lock it, it must be uninstalling */
1604
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
1606
/* initialization not completed */
1608
intern_plugin_unlock(lex, plugin);
1612
rw_unlock(&LOCK_system_variables_hash);
1615
If the variable exists but the plugin it is associated with is not ready
1616
then the intern_plugin_lock did not raise an error, so we do it here.
1619
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1625
called by register_var, construct_options and test_plugin_options.
1626
Returns the 'bookmark' for the named variable.
1627
LOCK_system_variables_hash should be at least read locked
1629
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1631
st_bookmark *result= NULL;
1632
uint namelen, length, pluginlen= 0;
1635
if (!(flags & PLUGIN_VAR_THDLOCAL))
1638
namelen= strlen(name);
1640
pluginlen= strlen(plugin) + 1;
1641
length= namelen + pluginlen + 2;
1642
varname= (char*) my_alloca(length);
1646
strxmov(varname + 1, plugin, "_", name, NullS);
1647
for (p= varname + 1; *p; p++)
1652
memcpy(varname + 1, name, namelen + 1);
1654
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1656
result= (st_bookmark*) hash_search(&bookmark_hash,
1657
(const uchar*) varname, length - 1);
1665
returns a bookmark for thd-local variables, creating if neccessary.
1666
returns null for non thd-local variables.
1667
Requires that a write lock is obtained on LOCK_system_variables_hash
1669
static st_bookmark *register_var(const char *plugin, const char *name,
1672
uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1673
st_bookmark *result;
1676
if (!(flags & PLUGIN_VAR_THDLOCAL))
1679
switch (flags & PLUGIN_VAR_TYPEMASK) {
1680
case PLUGIN_VAR_BOOL:
1683
case PLUGIN_VAR_INT:
1686
case PLUGIN_VAR_LONG:
1687
case PLUGIN_VAR_ENUM:
1690
case PLUGIN_VAR_LONGLONG:
1691
case PLUGIN_VAR_SET:
1692
size= sizeof(uint64_t);
1694
case PLUGIN_VAR_STR:
1695
size= sizeof(char*);
1702
varname= ((char*) my_alloca(length));
1703
strxmov(varname + 1, plugin, "_", name, NullS);
1704
for (p= varname + 1; *p; p++)
1708
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1710
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1711
sizeof(struct st_bookmark) + length-1);
1712
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1713
memcpy(result->key, varname, length);
1714
result->name_len= length - 2;
1717
assert(size && !(size & (size-1))); /* must be power of 2 */
1719
offset= global_system_variables.dynamic_variables_size;
1720
offset= (offset + size - 1) & ~(size - 1);
1721
result->offset= (int) offset;
1723
new_size= (offset + size + 63) & ~63;
1725
if (new_size > global_variables_dynamic_size)
1727
global_system_variables.dynamic_variables_ptr= (char*)
1728
my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1729
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1730
max_system_variables.dynamic_variables_ptr= (char*)
1731
my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1732
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1734
Clear the new variable value space. This is required for string
1735
variables. If their value is non-NULL, it must point to a valid
1738
memset(global_system_variables.dynamic_variables_ptr +
1739
global_variables_dynamic_size, 0,
1740
new_size - global_variables_dynamic_size);
1741
memset(max_system_variables.dynamic_variables_ptr +
1742
global_variables_dynamic_size, 0,
1743
new_size - global_variables_dynamic_size);
1744
global_variables_dynamic_size= new_size;
1747
global_system_variables.dynamic_variables_head= offset;
1748
max_system_variables.dynamic_variables_head= offset;
1749
global_system_variables.dynamic_variables_size= offset + size;
1750
max_system_variables.dynamic_variables_size= offset + size;
1751
global_system_variables.dynamic_variables_version++;
1752
max_system_variables.dynamic_variables_version++;
1754
result->version= global_system_variables.dynamic_variables_version;
1756
/* this should succeed because we have already checked if a dup exists */
1757
if (my_hash_insert(&bookmark_hash, (uchar*) result))
1759
fprintf(stderr, "failed to add placeholder to hash");
1769
returns a pointer to the memory which holds the thd-local variable or
1770
a pointer to the global variable if thd==null.
1771
If required, will sync with global variables if the requested variable
1772
has not yet been allocated in the current thread.
1774
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
1776
assert(offset >= 0);
1777
assert((uint)offset <= global_system_variables.dynamic_variables_head);
1780
return (uchar*) global_system_variables.dynamic_variables_ptr + offset;
1783
dynamic_variables_head points to the largest valid offset
1785
if (!thd->variables.dynamic_variables_ptr ||
1786
(uint)offset > thd->variables.dynamic_variables_head)
1790
rw_rdlock(&LOCK_system_variables_hash);
1792
thd->variables.dynamic_variables_ptr= (char*)
1793
my_realloc(thd->variables.dynamic_variables_ptr,
1794
global_variables_dynamic_size,
1795
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1798
pthread_mutex_lock(&LOCK_global_system_variables);
1800
safe_mutex_assert_owner(&LOCK_global_system_variables);
1802
memcpy(thd->variables.dynamic_variables_ptr +
1803
thd->variables.dynamic_variables_size,
1804
global_system_variables.dynamic_variables_ptr +
1805
thd->variables.dynamic_variables_size,
1806
global_system_variables.dynamic_variables_size -
1807
thd->variables.dynamic_variables_size);
1810
now we need to iterate through any newly copied 'defaults'
1811
and if it is a string type with MEMALLOC flag, we need to strdup
1813
for (idx= 0; idx < bookmark_hash.records; idx++)
1815
sys_var_pluginvar *pi;
1817
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1819
if (v->version <= thd->variables.dynamic_variables_version ||
1820
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1821
!(pi= var->cast_pluginvar()) ||
1822
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1825
/* Here we do anything special that may be required of the data types */
1827
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1828
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1830
char **pp= (char**) (thd->variables.dynamic_variables_ptr +
1831
*(int*)(pi->plugin_var + 1));
1832
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1833
*(int*)(pi->plugin_var + 1))))
1834
*pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
1839
pthread_mutex_unlock(&LOCK_global_system_variables);
1841
thd->variables.dynamic_variables_version=
1842
global_system_variables.dynamic_variables_version;
1843
thd->variables.dynamic_variables_head=
1844
global_system_variables.dynamic_variables_head;
1845
thd->variables.dynamic_variables_size=
1846
global_system_variables.dynamic_variables_size;
1848
rw_unlock(&LOCK_system_variables_hash);
1850
return (uchar*)thd->variables.dynamic_variables_ptr + offset;
1853
static bool *mysql_sys_var_ptr_bool(THD* a_thd, int offset)
1855
return (bool *)intern_sys_var_ptr(a_thd, offset, true);
1858
static int *mysql_sys_var_ptr_int(THD* a_thd, int offset)
1860
return (int *)intern_sys_var_ptr(a_thd, offset, true);
1863
static long *mysql_sys_var_ptr_long(THD* a_thd, int offset)
1865
return (long *)intern_sys_var_ptr(a_thd, offset, true);
1868
static int64_t *mysql_sys_var_ptr_int64_t(THD* a_thd, int offset)
1870
return (int64_t *)intern_sys_var_ptr(a_thd, offset, true);
1873
static char **mysql_sys_var_ptr_str(THD* a_thd, int offset)
1875
return (char **)intern_sys_var_ptr(a_thd, offset, true);
1878
static uint64_t *mysql_sys_var_ptr_set(THD* a_thd, int offset)
1880
return (uint64_t *)intern_sys_var_ptr(a_thd, offset, true);
1883
static unsigned long *mysql_sys_var_ptr_enum(THD* a_thd, int offset)
1885
return (unsigned long *)intern_sys_var_ptr(a_thd, offset, true);
1889
void plugin_thdvar_init(THD *thd)
1891
plugin_ref old_table_plugin= thd->variables.table_plugin;
1893
thd->variables.table_plugin= NULL;
1894
cleanup_variables(thd, &thd->variables);
1896
thd->variables= global_system_variables;
1897
thd->variables.table_plugin= NULL;
517
1899
/* we are going to allocate these lazily */
518
session->variables.dynamic_variables_version= 0;
519
session->variables.dynamic_variables_size= 0;
520
session->variables.dynamic_variables_ptr= 0;
1900
thd->variables.dynamic_variables_version= 0;
1901
thd->variables.dynamic_variables_size= 0;
1902
thd->variables.dynamic_variables_ptr= 0;
522
session->variables.storage_engine= global_system_variables.storage_engine;
1904
thd->variables.table_plugin=
1905
my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1906
intern_plugin_unlock(NULL, old_table_plugin);
527
1912
Unlocks all system variables which hold a reference
529
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
1914
static void unlock_variables(THD *thd __attribute__((unused)),
1915
struct system_variables *vars)
531
vars->storage_engine= NULL;
1917
intern_plugin_unlock(NULL, vars->table_plugin);
1918
vars->table_plugin= NULL;
538
1925
Unlike plugin_vars_free_values() it frees all variables of all plugins,
539
1926
it's used on shutdown.
541
static void cleanup_variables(drizzle_system_variables *vars)
1928
static void cleanup_variables(THD *thd, struct system_variables *vars)
543
assert(vars->storage_engine == NULL);
545
free(vars->dynamic_variables_ptr);
1931
sys_var_pluginvar *pivar;
1936
rw_rdlock(&LOCK_system_variables_hash);
1937
for (idx= 0; idx < bookmark_hash.records; idx++)
1939
v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1940
if (v->version > vars->dynamic_variables_version ||
1941
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1942
!(pivar= var->cast_pluginvar()) ||
1943
v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1946
flags= pivar->plugin_var->flags;
1948
if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1949
flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1951
char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
1952
my_free(*ptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1956
rw_unlock(&LOCK_system_variables_hash);
1958
assert(vars->table_plugin == NULL);
1960
my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR));
546
1961
vars->dynamic_variables_ptr= NULL;
547
1962
vars->dynamic_variables_size= 0;
548
1963
vars->dynamic_variables_version= 0;
552
void plugin_sessionvar_cleanup(Session *session)
554
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1967
void plugin_thdvar_cleanup(THD *thd)
1972
unlock_variables(thd, &thd->variables);
1973
cleanup_variables(thd, &thd->variables);
1975
if ((idx= thd->lex->plugins.elements))
1977
list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
1978
while ((uchar*) list >= thd->lex->plugins.buffer)
1979
intern_plugin_unlock(NULL, *list--);
1982
reset_dynamic(&thd->lex->plugins);
1989
@brief Free values of thread variables of a plugin.
1991
This must be called before a plugin is deleted. Otherwise its
1992
variables are no longer accessible and the value space is lost. Note
1993
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1996
@param[in] vars Chain of system variables of a plugin
1999
static void plugin_vars_free_values(sys_var *vars)
2002
for (sys_var *var= vars; var; var= var->next)
2004
sys_var_pluginvar *piv= var->cast_pluginvar();
2006
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
2007
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
2009
/* Free the string from global_system_variables. */
2010
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2011
my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
2019
bool sys_var_pluginvar::check_update_type(Item_result type)
2023
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2024
case PLUGIN_VAR_INT:
2025
case PLUGIN_VAR_LONG:
2026
case PLUGIN_VAR_LONGLONG:
2027
return type != INT_RESULT;
2028
case PLUGIN_VAR_STR:
2029
return type != STRING_RESULT;
2036
SHOW_TYPE sys_var_pluginvar::show_type()
2038
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2039
case PLUGIN_VAR_BOOL:
2040
return SHOW_MY_BOOL;
2041
case PLUGIN_VAR_INT:
2043
case PLUGIN_VAR_LONG:
2045
case PLUGIN_VAR_LONGLONG:
2046
return SHOW_LONGLONG;
2047
case PLUGIN_VAR_STR:
2048
return SHOW_CHAR_PTR;
2049
case PLUGIN_VAR_ENUM:
2050
case PLUGIN_VAR_SET:
2059
uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
2061
assert(thd || (type == OPT_GLOBAL));
2062
if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
2064
if (type == OPT_GLOBAL)
2067
return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
2069
return *(uchar**) (plugin_var+1);
2073
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2075
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
2076
case PLUGIN_VAR_ENUM:
2077
return ((sysvar_enum_t *)plugin_var)->typelib;
2078
case PLUGIN_VAR_SET:
2079
return ((sysvar_set_t *)plugin_var)->typelib;
2080
case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2081
return ((thdvar_enum_t *)plugin_var)->typelib;
2082
case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2083
return ((thdvar_set_t *)plugin_var)->typelib;
2091
uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
2092
LEX_STRING *base __attribute__((unused)))
2096
result= real_value_ptr(thd, type);
2098
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2099
result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result);
2100
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2102
char buffer[STRING_BUFFER_USUAL_SIZE];
2103
String str(buffer, sizeof(buffer), system_charset_info);
2104
TYPELIB *typelib= plugin_var_typelib();
2105
uint64_t mask= 1, value= *(uint64_t*) result;
2109
for (i= 0; i < typelib->count; i++, mask<<=1)
2111
if (!(value & mask))
2113
str.append(typelib->type_names[i], typelib->type_lengths[i]);
2117
result= (uchar*) "";
2119
result= (uchar*) thd->strmake(str.ptr(), str.length()-1);
2125
bool sys_var_pluginvar::check(THD *thd, set_var *var)
2127
st_item_value_holder value;
2128
assert(is_readonly() || plugin_var->check);
2130
value.value_type= item_value_type;
2131
value.val_str= item_val_str;
2132
value.val_int= item_val_int;
2133
value.val_real= item_val_real;
2134
value.item= var->value;
2136
return is_readonly() ||
2137
plugin_var->check(thd, plugin_var, &var->save_result, &value);
2141
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
2146
assert(is_readonly() || plugin_var->update);
2151
pthread_mutex_lock(&LOCK_global_system_variables);
2152
tgt= real_value_ptr(thd, type);
2153
src= ((void **) (plugin_var + 1) + 1);
2155
if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
2157
if (type != OPT_GLOBAL)
2158
src= real_value_ptr(thd, OPT_GLOBAL);
2160
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2161
case PLUGIN_VAR_INT:
2162
src= &((thdvar_uint_t*) plugin_var)->def_val;
2164
case PLUGIN_VAR_LONG:
2165
src= &((thdvar_ulong_t*) plugin_var)->def_val;
2167
case PLUGIN_VAR_LONGLONG:
2168
src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
2170
case PLUGIN_VAR_ENUM:
2171
src= &((thdvar_enum_t*) plugin_var)->def_val;
2173
case PLUGIN_VAR_SET:
2174
src= &((thdvar_set_t*) plugin_var)->def_val;
2176
case PLUGIN_VAR_BOOL:
2177
src= &((thdvar_bool_t*) plugin_var)->def_val;
2179
case PLUGIN_VAR_STR:
2180
src= &((thdvar_str_t*) plugin_var)->def_val;
2187
/* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2188
assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2189
thd == current_thd);
2191
if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
2193
plugin_var->update(thd, plugin_var, tgt, src);
2194
pthread_mutex_unlock(&LOCK_global_system_variables);
2198
pthread_mutex_unlock(&LOCK_global_system_variables);
2199
plugin_var->update(thd, plugin_var, tgt, src);
2204
bool sys_var_pluginvar::update(THD *thd, set_var *var)
2208
assert(is_readonly() || plugin_var->update);
2210
/* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2211
assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2212
thd == current_thd);
2217
pthread_mutex_lock(&LOCK_global_system_variables);
2218
tgt= real_value_ptr(thd, var->type);
2220
if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
2222
/* variable we are updating has global scope, so we unlock after updating */
2223
plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2224
pthread_mutex_unlock(&LOCK_global_system_variables);
2228
pthread_mutex_unlock(&LOCK_global_system_variables);
2229
plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2235
#define OPTION_SET_LIMITS(type, options, opt) \
2236
options->var_type= type; \
2237
options->def_value= (opt)->def_val; \
2238
options->min_value= (opt)->min_val; \
2239
options->max_value= (opt)->max_val; \
2240
options->block_size= (long) (opt)->blk_sz
2243
static void plugin_opt_set_limits(struct my_option *options,
2244
const struct st_mysql_sys_var *opt)
2246
options->sub_size= 0;
2248
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2249
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
2250
/* global system variables */
2251
case PLUGIN_VAR_INT:
2252
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2254
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
2255
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
2257
case PLUGIN_VAR_LONG:
2258
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2260
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2261
OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
2263
case PLUGIN_VAR_LONGLONG:
2264
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2266
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
2267
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
2269
case PLUGIN_VAR_ENUM:
2270
options->var_type= GET_ENUM;
2271
options->typelib= ((sysvar_enum_t*) opt)->typelib;
2272
options->def_value= ((sysvar_enum_t*) opt)->def_val;
2273
options->min_value= options->block_size= 0;
2274
options->max_value= options->typelib->count - 1;
2276
case PLUGIN_VAR_SET:
2277
options->var_type= GET_SET;
2278
options->typelib= ((sysvar_set_t*) opt)->typelib;
2279
options->def_value= ((sysvar_set_t*) opt)->def_val;
2280
options->min_value= options->block_size= 0;
2281
options->max_value= (1ULL << options->typelib->count) - 1;
2283
case PLUGIN_VAR_BOOL:
2284
options->var_type= GET_BOOL;
2285
options->def_value= ((sysvar_bool_t*) opt)->def_val;
2287
case PLUGIN_VAR_STR:
2288
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2289
GET_STR_ALLOC : GET_STR);
2290
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2292
/* threadlocal variables */
2293
case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
2294
OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
2296
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2297
OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
2299
case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
2300
OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
2302
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2303
OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
2305
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
2306
OPTION_SET_LIMITS(GET_LL, options, (thdvar_int64_t_t*) opt);
2308
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2309
OPTION_SET_LIMITS(GET_ULL, options, (thdvar_uint64_t_t*) opt);
2311
case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2312
options->var_type= GET_ENUM;
2313
options->typelib= ((thdvar_enum_t*) opt)->typelib;
2314
options->def_value= ((thdvar_enum_t*) opt)->def_val;
2315
options->min_value= options->block_size= 0;
2316
options->max_value= options->typelib->count - 1;
2318
case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2319
options->var_type= GET_SET;
2320
options->typelib= ((thdvar_set_t*) opt)->typelib;
2321
options->def_value= ((thdvar_set_t*) opt)->def_val;
2322
options->min_value= options->block_size= 0;
2323
options->max_value= (1ULL << options->typelib->count) - 1;
2325
case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
2326
options->var_type= GET_BOOL;
2327
options->def_value= ((thdvar_bool_t*) opt)->def_val;
2329
case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
2330
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2331
GET_STR_ALLOC : GET_STR);
2332
options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
2337
options->arg_type= REQUIRED_ARG;
2338
if (opt->flags & PLUGIN_VAR_NOCMDARG)
2339
options->arg_type= NO_ARG;
2340
if (opt->flags & PLUGIN_VAR_OPCMDARG)
2341
options->arg_type= OPT_ARG;
2344
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2347
bool get_one_plugin_option(int optid __attribute__((unused)),
2348
const struct my_option *opt __attribute__((unused)),
2349
char *argument __attribute__((unused)))
2355
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
2356
my_option *options, bool can_disable)
2358
const char *plugin_name= tmp->plugin->name;
2359
uint namelen= strlen(plugin_name), optnamelen;
2360
uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2361
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2363
int index= 0, offset= 0;
2364
st_mysql_sys_var *opt, **plugin_option;
2367
/* support --skip-plugin-foo syntax */
2368
memcpy(name, plugin_name, namelen + 1);
2369
my_casedn_str(&my_charset_latin1, name);
2370
strxmov(name + namelen + 1, "plugin-", name, NullS);
2371
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2373
for (p= name + namelen*2 + 8; p > name; p--)
2379
strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2380
"Disable with --skip-", name," (will save memory).", NullS);
2382
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2383
20 + namelen + 20 + 1 == namelen * 4 + 67.
2386
options[0].comment= name + namelen*2 + 10;
2389
options[1].name= (options[0].name= name) + namelen + 1;
2390
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2391
options[0].var_type= options[1].var_type= GET_BOOL;
2392
options[0].arg_type= options[1].arg_type= NO_ARG;
2393
options[0].def_value= options[1].def_value= true;
2394
options[0].value= options[0].u_max_value=
2395
options[1].value= options[1].u_max_value= (char**) (name - 1);
2399
Two passes as the 2nd pass will take pointer addresses for use
2400
by my_getopt and register_var() in the first pass uses realloc
2403
for (plugin_option= tmp->plugin->system_vars;
2404
plugin_option && *plugin_option; plugin_option++, index++)
2406
opt= *plugin_option;
2407
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
2409
if (!(register_var(name, opt->name, opt->flags)))
2411
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2412
case PLUGIN_VAR_BOOL:
2413
(((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2415
case PLUGIN_VAR_INT:
2416
(((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2418
case PLUGIN_VAR_LONG:
2419
(((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2421
case PLUGIN_VAR_LONGLONG:
2422
(((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2424
case PLUGIN_VAR_STR:
2425
(((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2427
case PLUGIN_VAR_ENUM:
2428
(((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2430
case PLUGIN_VAR_SET:
2431
(((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2434
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2435
opt->flags, plugin_name);
2440
for (plugin_option= tmp->plugin->system_vars;
2441
plugin_option && *plugin_option; plugin_option++, index++)
2443
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
2444
case PLUGIN_VAR_BOOL:
2446
opt->check= check_func_bool;
2448
opt->update= update_func_bool;
2450
case PLUGIN_VAR_INT:
2452
opt->check= check_func_int;
2454
opt->update= update_func_int;
2456
case PLUGIN_VAR_LONG:
2458
opt->check= check_func_long;
2460
opt->update= update_func_long;
2462
case PLUGIN_VAR_LONGLONG:
2464
opt->check= check_func_int64_t;
2466
opt->update= update_func_int64_t;
2468
case PLUGIN_VAR_STR:
2470
opt->check= check_func_str;
2473
opt->update= update_func_str;
2474
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2476
opt->flags|= PLUGIN_VAR_READONLY;
2477
sql_print_warning(_("Server variable %s of plugin %s was forced "
2478
"to be read-only: string variable without "
2479
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2480
opt->name, plugin_name);
2484
case PLUGIN_VAR_ENUM:
2486
opt->check= check_func_enum;
2488
opt->update= update_func_long;
2490
case PLUGIN_VAR_SET:
2492
opt->check= check_func_set;
2494
opt->update= update_func_int64_t;
2497
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2498
opt->flags, plugin_name);
2502
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
2503
== PLUGIN_VAR_NOCMDOPT)
2508
sql_print_error(_("Missing variable name in plugin '%s'."),
2513
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
2515
optnamelen= strlen(opt->name);
2516
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2517
strxmov(optname, name, "-", opt->name, NullS);
2518
optnamelen= namelen + optnamelen + 1;
2522
/* this should not fail because register_var should create entry */
2523
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2525
sql_print_error(_("Thread local variable '%s' not allocated "
2526
"in plugin '%s'."), opt->name, plugin_name);
2530
*(int*)(opt + 1)= offset= v->offset;
2532
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2535
optname= (char*) memdup_root(mem_root, v->key + 1,
2536
(optnamelen= v->name_len) + 1);
2539
/* convert '_' to '-' */
2540
for (p= optname; *p; p++)
2544
options->name= optname;
2545
options->comment= opt->comment;
2546
options->app_type= opt;
2547
options->id= (options-1)->id + 1;
2549
plugin_opt_set_limits(options, opt);
2551
if (opt->flags & PLUGIN_VAR_THDLOCAL)
2552
options->value= options->u_max_value= (char**)
2553
(global_system_variables.dynamic_variables_ptr + offset);
2555
options->value= options->u_max_value= *(char***) (opt + 1);
2557
options[1]= options[0];
2558
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2559
options[1].comment= 0; // hidden
2560
strxmov(p, "plugin-", optname, NullS);
2569
static my_option *construct_help_options(MEM_ROOT *mem_root,
2570
struct st_plugin_int *p)
2572
st_mysql_sys_var **opt;
2575
uint count= EXTRA_OPTIONS;
2577
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2579
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2582
memset(opts, 0, sizeof(my_option) * count);
2584
if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") == 0))
2586
else if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY") == 0))
2592
if (construct_options(mem_root, p, opts, can_disable))