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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <drizzled/server_includes.h>
17
#include <mysys/my_getopt.h>
18
#include <mysys/hash.h>
20
#include <drizzled/authentication.h>
21
#include <drizzled/logging.h>
22
#include <drizzled/errmsg.h>
23
#include <drizzled/configvar.h>
24
#include <drizzled/qcache.h>
25
#include <drizzled/parser.h>
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>
26
37
#include <drizzled/sql_parse.h>
27
#include <drizzled/scheduling.h>
28
38
#include <drizzled/show.h>
29
#include <drizzled/handler.h>
39
#include <drizzled/cursor.h>
30
40
#include <drizzled/set_var.h>
31
41
#include <drizzled/session.h>
42
#include <drizzled/item/null.h>
35
43
#include <drizzled/error.h>
36
44
#include <drizzled/gettext.h>
38
#define REPORT_TO_LOG 1
39
#define REPORT_TO_USER 2
41
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
42
#define plugin_int_to_ref(A) &(A)
45
#include <drizzled/errmsg_print.h>
46
#include <drizzled/pthread_globals.h>
47
#include <drizzled/util/tokenize.h>
48
#include <drizzled/system_variables.h>
50
#include <boost/foreach.hpp>
52
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
44
59
using namespace std;
46
extern struct st_mysql_plugin *mysqld_builtins[];
48
char *opt_plugin_load= NULL;
49
char *opt_plugin_dir_ptr;
50
char opt_plugin_dir[FN_REFLEN];
52
When you ad a new plugin type, add both a string and make sure that the
53
init and deinit array are correctly updated.
55
const LEX_STRING plugin_type_names[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
57
{ C_STRING_WITH_LEN("DAEMON") },
58
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
59
{ C_STRING_WITH_LEN("INFORMATION SCHEMA") },
60
{ C_STRING_WITH_LEN("UDF") },
61
{ C_STRING_WITH_LEN("UDA") },
62
{ C_STRING_WITH_LEN("AUDIT") },
63
{ C_STRING_WITH_LEN("LOGGER") },
64
{ C_STRING_WITH_LEN("ERRMSG") },
65
{ C_STRING_WITH_LEN("AUTH") },
66
{ C_STRING_WITH_LEN("CONFIGVAR") },
67
{ C_STRING_WITH_LEN("QCACHE") },
68
{ C_STRING_WITH_LEN("PARSER") },
69
{ C_STRING_WITH_LEN("SCHEDULING") }
72
extern int initialize_schema_table(st_plugin_int *plugin);
73
extern int finalize_schema_table(st_plugin_int *plugin);
75
extern int initialize_udf(st_plugin_int *plugin);
76
extern int finalize_udf(st_plugin_int *plugin);
79
The number of elements in both plugin_type_initialize and
80
plugin_type_deinitialize should equal to the number of plugins
83
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
86
ha_initialize_handlerton, /* Storage Engine */
87
initialize_schema_table, /* Information Schema */
88
initialize_udf, /* UDF */
91
logging_initializer, /* Logger */
92
errmsg_initializer, /* Error Messages */
93
authentication_initializer, /* Auth */
94
configvar_initializer,
97
scheduling_initializer
100
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
103
ha_finalize_handlerton, /* Storage Engine */
104
finalize_schema_table, /* Information Schema */
105
finalize_udf, /* UDF */
108
logging_finalizer, /* Logger */
109
errmsg_finalizer, /* Logger */
110
authentication_finalizer, /* Auth */
117
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
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
77
typedef vector<string> PluginOptions;
78
static PluginOptions opt_plugin_load;
79
static PluginOptions opt_plugin_add;
80
static PluginOptions opt_plugin_remove;
81
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
82
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
119
84
/* Note that 'int version' must be the first field of every plugin
120
85
sub-structure (plugin->info).
123
static bool initialized= 0;
125
static DYNAMIC_ARRAY plugin_dl_array;
126
static DYNAMIC_ARRAY plugin_array;
127
static HASH plugin_hash[DRIZZLE_MAX_PLUGIN_TYPE_NUM];
88
static bool initialized= false;
128
91
static bool reap_needed= false;
129
static int plugin_array_version=0;
132
94
write-lock on LOCK_system_variables_hash is required before modifying
133
95
the following variables/structures
135
static MEM_ROOT plugin_mem_root;
97
static memory::Root plugin_mem_root(4096);
136
98
static uint32_t global_variables_dynamic_size= 0;
137
static HASH bookmark_hash;
141
102
hidden part of opaque value passed to variable check functions.
142
103
Used to provide a object-like structure to non C++ consumers.
144
struct st_item_value_holder : public st_mysql_value
105
struct st_item_value_holder : public drizzle_value
151
stored in bookmark_hash, this structure is never removed from the
152
hash and is used to mark a single offset for a session local variable
153
even if plugins have been uninstalled and reinstalled, repeatedly.
154
This structure is allocated from plugin_mem_root.
156
The key format is as follows:
157
1 byte - variable type code
158
name_len bytes - variable name
171
skeleton of a plugin variable - portion of structure common to all.
173
struct st_mysql_sys_var
175
DRIZZLE_PLUGIN_VAR_HEADER;
180
sys_var class for access to all plugin variables visible to the user
182
class sys_var_pluginvar: public sys_var
185
struct st_plugin_int *plugin;
186
struct st_mysql_sys_var *plugin_var;
188
static void *operator new(size_t size, MEM_ROOT *mem_root)
189
{ return (void*) alloc_root(mem_root, (uint) size); }
190
static void operator delete(void *ptr_arg __attribute__((unused)),
191
size_t size __attribute__((unused)))
192
{ TRASH(ptr_arg, size); }
194
sys_var_pluginvar(const char *name_arg,
195
struct st_mysql_sys_var *plugin_var_arg)
196
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
197
sys_var_pluginvar *cast_pluginvar() { return this; }
198
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
199
bool check_type(enum_var_type type)
200
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
201
bool check_update_type(Item_result type);
202
SHOW_TYPE show_type();
203
unsigned char* real_value_ptr(Session *session, enum_var_type type);
204
TYPELIB* plugin_var_typelib(void);
205
unsigned char* value_ptr(Session *session, enum_var_type type, LEX_STRING *base);
206
bool check(Session *session, set_var *var);
207
bool check_default(enum_var_type type __attribute__((unused)))
208
{ return is_readonly(); }
209
void set_default(Session *session,
210
enum_var_type type __attribute__((unused)));
211
bool update(Session *session, set_var *var);
216
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
218
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
220
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
221
struct st_plugin_int **);
222
static void unlock_variables(Session *session, struct system_variables *vars);
223
static void cleanup_variables(Session *session, struct system_variables *vars);
224
static void plugin_vars_free_values(sys_var *vars);
225
static void plugin_opt_set_limits(struct my_option *options,
226
const struct st_mysql_sys_var *opt);
227
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
228
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
229
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
230
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
231
static void reap_plugins(void);
234
/* declared in set_var.cc */
235
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
236
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
237
const char *name, int64_t val);
239
/****************************************************************************
240
Value type thunks, allows the C world to play in the C++ world
241
****************************************************************************/
243
static int item_value_type(struct st_mysql_value *value)
245
switch (((st_item_value_holder*)value)->item->result_type()) {
247
return DRIZZLE_VALUE_TYPE_INT;
249
return DRIZZLE_VALUE_TYPE_REAL;
251
return DRIZZLE_VALUE_TYPE_STRING;
255
static const char *item_val_str(struct st_mysql_value *value,
256
char *buffer, int *length)
258
String str(buffer, *length, system_charset_info), *res;
259
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
261
*length= res->length();
262
if (res->c_ptr_quick() == buffer)
266
Lets be nice and create a temporary string since the
269
return current_session->strmake(res->c_ptr_quick(), res->length());
273
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
275
Item *item= ((st_item_value_holder*)value)->item;
276
*buf= item->val_int();
283
static int item_val_real(struct st_mysql_value *value, double *buf)
285
Item *item= ((st_item_value_holder*)value)->item;
286
*buf= item->val_real();
111
static void plugin_prune_list(vector<string> &plugin_list, const vector<string> &plugins_to_remove);
112
static bool plugin_load_list(module::Registry ®istry,
113
memory::Root *tmp_root,
114
const set<string> &plugin_list,
115
po::options_description &long_options,
116
bool builtin= false);
117
static int test_plugin_options(memory::Root*, module::Module*, po::options_description&long_options);
118
static void unlock_variables(Session *session, drizzle_system_variables *vars);
119
static void cleanup_variables(drizzle_system_variables *vars);
293
122
/****************************************************************************
294
123
Plugin support code
295
124
****************************************************************************/
297
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
300
struct st_plugin_dl *tmp;
301
for (i= 0; i < plugin_dl_array.elements; i++)
303
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
304
if (tmp->ref_count &&
305
! my_strnncoll(files_charset_info,
306
(const unsigned char *)dl->str, dl->length,
307
(const unsigned char *)tmp->dl.str, tmp->dl.length))
313
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
316
struct st_plugin_dl *tmp;
317
for (i= 0; i < plugin_dl_array.elements; i++)
319
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
320
if (! tmp->ref_count)
322
memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
326
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
328
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
329
struct st_plugin_dl **)=
330
(struct st_plugin_dl *) memdup_root(&plugin_mem_root, (unsigned char*)plugin_dl,
331
sizeof(struct st_plugin_dl));
335
static inline void free_plugin_mem(struct st_plugin_dl *p)
343
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
346
uint32_t plugin_dir_len, dummy_errors;
347
struct st_plugin_dl *tmp, plugin_dl;
349
plugin_dir_len= strlen(opt_plugin_dir);
350
dlpath.reserve(FN_REFLEN);
352
Ensure that the dll doesn't have a path.
353
This is done to ensure that only approved libraries from the
354
plugin directory are used (to make this even remotely secure).
356
if (strchr(dl->str, FN_LIBCHAR) ||
357
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
358
system_charset_info, 1) ||
359
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
361
if (report & REPORT_TO_USER)
362
my_error(ER_UDF_NO_PATHS, MYF(0));
363
if (report & REPORT_TO_LOG)
364
sql_print_error("%s",ER(ER_UDF_NO_PATHS));
367
/* If this dll is already loaded just increase ref_count. */
368
if ((tmp= plugin_dl_find(dl)))
373
memset(&plugin_dl, 0, sizeof(plugin_dl));
374
/* Compile dll path */
375
dlpath.append(opt_plugin_dir);
377
dlpath.append(dl->str);
378
plugin_dl.ref_count= 1;
379
/* Open new dll handle */
380
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
382
const char *errmsg=dlerror();
383
uint32_t dlpathlen= dlpath.length();
384
if (!dlpath.compare(0, dlpathlen, errmsg))
385
{ // if errmsg starts from dlpath, trim this prefix.
387
if (*errmsg == ':') errmsg++;
388
if (*errmsg == ' ') errmsg++;
390
if (report & REPORT_TO_USER)
391
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
392
if (report & REPORT_TO_LOG)
393
sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
397
/* Find plugin declarations */
398
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
400
free_plugin_mem(&plugin_dl);
401
if (report & REPORT_TO_USER)
402
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
403
if (report & REPORT_TO_LOG)
404
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
408
plugin_dl.plugins= (struct st_mysql_plugin *)sym;
410
/* Duplicate and convert dll name */
411
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
412
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
414
free_plugin_mem(&plugin_dl);
415
if (report & REPORT_TO_USER)
416
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
417
if (report & REPORT_TO_LOG)
418
sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
421
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
422
files_charset_info, dl->str, dl->length, system_charset_info,
424
plugin_dl.dl.str[plugin_dl.dl.length]= 0;
425
/* Add this dll to array */
426
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
428
free_plugin_mem(&plugin_dl);
429
if (report & REPORT_TO_USER)
430
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
431
if (report & REPORT_TO_LOG)
432
sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
439
static void plugin_dl_del(const LEX_STRING *dl)
443
for (i= 0; i < plugin_dl_array.elements; i++)
445
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
446
struct st_plugin_dl **);
447
if (tmp->ref_count &&
448
! my_strnncoll(files_charset_info,
449
(const unsigned char *)dl->str, dl->length,
450
(const unsigned char *)tmp->dl.str, tmp->dl.length))
452
/* Do not remove this element, unless no other plugin uses this dll. */
453
if (! --tmp->ref_count)
455
free_plugin_mem(tmp);
456
memset(tmp, 0, sizeof(struct st_plugin_dl));
465
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
131
Requires that a write-lock is held on LOCK_system_variables_hash
133
static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
134
module::Library *library,
135
po::options_description &long_options)
468
137
if (! initialized)
471
if (type == DRIZZLE_ANY_PLUGIN)
473
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
475
struct st_plugin_int *plugin= (st_plugin_int *)
476
hash_search(&plugin_hash[i], (const unsigned char *)name->str, name->length);
482
return((st_plugin_int *)
483
hash_search(&plugin_hash[type], (const unsigned char *)name->str, name->length));
488
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
490
SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
491
struct st_plugin_int *plugin;
492
if ((plugin= plugin_find_internal(name, type)))
494
rc= SHOW_OPTION_DISABLED;
495
if (plugin->state == PLUGIN_IS_READY)
502
bool plugin_is_ready(const LEX_STRING *name, int type)
505
if (plugin_status(name, type) == SHOW_OPTION_YES)
511
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
513
LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
514
return plugin_status(&plugin_name, plugin_type);
518
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc)
520
st_plugin_int *pi= plugin_ref_to_int(rc);
522
if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
526
For debugging, we do an additional malloc which allows the
527
memory manager and/or valgrind to track locked references and
528
double unlocks to aid resolving reference counting.problems.
530
if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
537
insert_dynamic(&lex->plugins, (unsigned char*)&plugin);
544
plugin_ref plugin_lock(Session *session, plugin_ref *ptr)
546
LEX *lex= session ? session->lex : 0;
548
rc= my_intern_plugin_lock_ci(lex, *ptr);
553
plugin_ref plugin_lock_by_name(Session *session, const LEX_STRING *name, int type)
555
LEX *lex= session ? session->lex : 0;
557
st_plugin_int *plugin;
558
if ((plugin= plugin_find_internal(name, type)))
559
rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
564
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
567
struct st_plugin_int *tmp;
568
for (i= 0; i < plugin_array.elements; i++)
570
tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
571
if (tmp->state == PLUGIN_IS_FREED)
573
memcpy(tmp, plugin, sizeof(struct st_plugin_int));
577
if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
579
tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
580
struct st_plugin_int **)=
581
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)plugin,
582
sizeof(struct st_plugin_int));
589
Requires that a write-lock is held on LOCK_system_variables_hash
591
static bool plugin_add(MEM_ROOT *tmp_root,
592
const LEX_STRING *name, const LEX_STRING *dl,
593
int *argc, char **argv, int report)
595
struct st_plugin_int tmp;
596
struct st_mysql_plugin *plugin;
597
if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
599
if (report & REPORT_TO_USER)
600
my_error(ER_UDF_EXISTS, MYF(0), name->str);
601
if (report & REPORT_TO_LOG)
602
sql_print_error(ER(ER_UDF_EXISTS), name->str);
605
/* Clear the whole struct to catch future extensions. */
606
memset(&tmp, 0, sizeof(tmp));
607
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
140
if (registry.find(library->getName()))
142
errmsg_printf(error::WARN, ER(ER_PLUGIN_EXISTS),
143
library->getName().c_str());
609
147
/* Find plugin by name */
610
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
612
uint32_t name_len= strlen(plugin->name);
613
if (plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
614
! my_strnncoll(system_charset_info,
615
(const unsigned char *)name->str, name->length,
616
(const unsigned char *)plugin->name,
619
struct st_plugin_int *tmp_plugin_ptr;
622
tmp.name.str= (char *)plugin->name;
623
tmp.name.length= name_len;
625
tmp.state= PLUGIN_IS_UNINITIALIZED;
626
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
628
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
630
plugin_array_version++;
631
if (!my_hash_insert(&plugin_hash[plugin->type], (unsigned char*)tmp_plugin_ptr))
633
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
636
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
638
mysql_del_sys_var_chain(tmp.system_vars);
641
/* plugin was disabled */
646
if (report & REPORT_TO_USER)
647
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
648
if (report & REPORT_TO_LOG)
649
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
656
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
658
if (plugin->plugin->status_vars)
662
We have a problem right now where we can not prepend without
663
breaking backwards compatibility. We will fix this shortly so
664
that engines have "use names" and we wil use those for
665
CREATE TABLE, and use the plugin name then for adding automatic
669
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
672
remove_status_vars(array);
674
remove_status_vars(plugin->plugin->status_vars);
675
#endif /* FIX_LATER */
678
if (plugin_type_deinitialize[plugin->plugin->type])
680
if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
682
sql_print_error(_("Plugin '%s' of type %s failed deinitialization"),
683
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
686
else if (plugin->plugin->deinit)
687
plugin->plugin->deinit(plugin);
689
plugin->state= PLUGIN_IS_UNINITIALIZED;
692
We do the check here because NDB has a worker Session which doesn't
693
exit until NDB is shut down.
695
if (ref_check && plugin->ref_count)
696
sql_print_error(_("Plugin '%s' has ref_count=%d after deinitialization."),
697
plugin->name.str, plugin->ref_count);
701
static void plugin_del(struct st_plugin_int *plugin)
703
/* Free allocated strings before deleting the plugin. */
704
plugin_vars_free_values(plugin->system_vars);
705
hash_delete(&plugin_hash[plugin->plugin->type], (unsigned char*)plugin);
706
if (plugin->plugin_dl)
707
plugin_dl_del(&plugin->plugin_dl->dl);
708
plugin->state= PLUGIN_IS_FREED;
709
plugin_array_version++;
710
rw_wrlock(&LOCK_system_variables_hash);
711
mysql_del_sys_var_chain(plugin->system_vars);
712
rw_unlock(&LOCK_system_variables_hash);
713
free_root(&plugin->mem_root, MYF(0));
717
static void reap_plugins(void)
720
struct st_plugin_int *plugin, **reap, **list;
726
count= plugin_array.elements;
727
reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
730
for (idx= 0; idx < count; idx++)
732
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
733
if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
735
/* change the status flag to prevent reaping by another thread */
736
plugin->state= PLUGIN_IS_DYING;
742
while ((plugin= *(--list)))
743
plugin_deinitialize(plugin, true);
745
while ((plugin= *(--reap)))
751
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
759
pi= plugin_ref_to_int(plugin);
761
free((void *) plugin);
766
Remove one instance of this plugin from the use list.
767
We are searching backwards so that plugins locked last
768
could be unlocked faster - optimizing for LIFO semantics.
770
for (i= lex->plugins.elements - 1; i >= 0; i--)
771
if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
773
delete_dynamic_element(&lex->plugins, i);
779
assert(pi->ref_count);
782
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
789
void plugin_unlock(Session *session, plugin_ref plugin)
791
LEX *lex= session ? session->lex : 0;
794
intern_plugin_unlock(lex, plugin);
799
void plugin_unlock_list(Session *session, plugin_ref *list, uint32_t count)
801
LEX *lex= session ? session->lex : 0;
804
intern_plugin_unlock(lex, *list++);
809
static int plugin_initialize(struct st_plugin_int *plugin)
812
if (plugin_type_initialize[plugin->plugin->type])
814
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
816
sql_print_error(_("Plugin '%s' registration as a %s failed."),
817
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
821
else if (plugin->plugin->init)
823
if (plugin->plugin->init(plugin))
825
sql_print_error(_("Plugin '%s' init function returned error."),
831
plugin->state= PLUGIN_IS_READY;
833
if (plugin->plugin->status_vars)
837
We have a problem right now where we can not prepend without
838
breaking backwards compatibility. We will fix this shortly so
839
that engines have "use names" and we wil use those for
840
CREATE TABLE, and use the plugin name then for adding automatic
844
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
847
if (add_status_vars(array)) // add_status_vars makes a copy
850
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
851
#endif /* FIX_LATER */
855
set the plugin attribute of plugin's sys vars so they are pointing
858
if (plugin->system_vars)
860
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
866
var= var->next->cast_pluginvar();
876
extern "C" unsigned char *get_plugin_hash_key(const unsigned char *, size_t *, bool);
877
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
880
unsigned char *get_plugin_hash_key(const unsigned char *buff, size_t *length,
881
bool not_used __attribute__((unused)))
883
struct st_plugin_int *plugin= (st_plugin_int *)buff;
884
*length= (uint)plugin->name.length;
885
return((unsigned char *)plugin->name.str);
889
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length,
890
bool not_used __attribute__((unused)))
892
struct st_bookmark *var= (st_bookmark *)buff;
893
*length= var->name_len + 1;
894
return (unsigned char*) var->key;
148
const module::Manifest *manifest= library->getManifest();
150
if (registry.find(manifest->name))
152
errmsg_printf(error::ERROR,
153
_("Plugin '%s' contains the name '%s' in its manifest, which "
154
"has already been registered.\n"),
155
library->getName().c_str(),
160
module::Module* tmp= new module::Module(manifest, library);
162
if (!test_plugin_options(tmp_root, tmp, long_options))
167
errmsg_printf(error::ERROR, ER(ER_CANT_FIND_DL_ENTRY),
168
library->getName().c_str());
173
static void reap_plugins(module::Registry ®istry)
175
BOOST_FOREACH(module::Registry::ModuleMap::const_reference module, registry.getModulesMap())
176
delete module.second;
180
static bool plugin_initialize(module::Registry ®istry,
181
module::Module *module)
183
assert(module->isInited == false);
185
module::Context loading_context(registry, module);
186
if (module->getManifest().init)
188
if (module->getManifest().init(loading_context))
190
errmsg_printf(error::ERROR,
191
_("Plugin '%s' init function returned error.\n"),
192
module->getName().c_str());
196
module->isInited= true;
200
static void compose_plugin_options(vector<string> &target,
201
vector<string> options)
203
BOOST_FOREACH(vector<string>::reference it, options)
204
tokenize(it, target, ",", true);
205
BOOST_FOREACH(vector<string>::reference it, target)
206
std::replace(it.begin(), it.end(), '-', '_');
209
void compose_plugin_add(const vector<string>& options)
211
compose_plugin_options(opt_plugin_add, options);
214
void compose_plugin_remove(const vector<string>& options)
216
compose_plugin_options(opt_plugin_remove, options);
219
void notify_plugin_load(const string& in_plugin_load)
221
tokenize(in_plugin_load, opt_plugin_load, ",", true);
899
225
The logic is that we first load and initialize all compiled in plugins.
903
229
Finally we initialize everything, aka the dynamic that have yet to initialize.
905
int plugin_init(int *argc, char **argv, int flags)
231
bool plugin_init(module::Registry ®istry,
232
po::options_description &long_options)
908
struct st_mysql_plugin **builtins;
909
struct st_mysql_plugin *plugin;
910
struct st_plugin_int tmp, *plugin_ptr, **reap;
916
init_alloc_root(&plugin_mem_root, 4096, 4096);
917
init_alloc_root(&tmp_root, 4096, 4096);
919
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
920
get_bookmark_hash_key, NULL, HASH_UNIQUE))
924
if (my_init_dynamic_array(&plugin_dl_array,
925
sizeof(struct st_plugin_dl *),16,16) ||
926
my_init_dynamic_array(&plugin_array,
927
sizeof(struct st_plugin_int *),16,16))
930
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
932
if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
933
get_plugin_hash_key, NULL, HASH_UNIQUE))
239
PluginOptions builtin_load_list;
240
tokenize(builtin_load_plugins, builtin_load_list, ",", true);
242
PluginOptions builtin_list;
243
tokenize(builtin_plugins, builtin_list, ",", true);
245
bool load_failed= false;
247
if (opt_plugin_add.size() > 0)
249
for (PluginOptions::iterator iter= opt_plugin_add.begin();
250
iter != opt_plugin_add.end();
253
if (find(builtin_list.begin(),
254
builtin_list.end(), *iter) != builtin_list.end())
256
builtin_load_list.push_back(*iter);
260
opt_plugin_load.push_back(*iter);
265
if (opt_plugin_remove.size() > 0)
267
plugin_prune_list(opt_plugin_load, opt_plugin_remove);
268
plugin_prune_list(builtin_load_list, opt_plugin_remove);
271
memory::Root tmp_root(4096);
940
273
First we register builtin plugins
942
for (builtins= mysqld_builtins; *builtins; builtins++)
275
const set<string> builtin_list_set(builtin_load_list.begin(),
276
builtin_load_list.end());
277
load_failed= plugin_load_list(registry, &tmp_root,
278
builtin_list_set, long_options, true);
944
for (plugin= *builtins; plugin->name; plugin++)
946
memset(&tmp, 0, sizeof(tmp));
948
tmp.name.str= (char *)plugin->name;
949
tmp.name.length= strlen(plugin->name);
951
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
952
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
955
if (register_builtin(plugin, &tmp, &plugin_ptr))
958
if (plugin_initialize(plugin_ptr))
962
initialize the global default storage engine so that it may
963
not be null in any child thread.
965
if (my_strcasecmp(&my_charset_utf8_general_ci, plugin->name, "MyISAM") == 0)
967
assert(!global_system_variables.table_plugin);
968
global_system_variables.table_plugin=
969
my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
970
assert(plugin_ptr->ref_count == 1);
281
tmp_root.free_root(MYF(0));
975
/* should now be set to MyISAM storage engine */
976
assert(global_system_variables.table_plugin);
285
/* Uniquify the list */
286
const set<string> plugin_list_set(opt_plugin_load.begin(),
287
opt_plugin_load.end());
978
289
/* Register all dynamic plugins */
979
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
290
load_failed= plugin_load_list(registry, &tmp_root,
291
plugin_list_set, long_options);
982
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
294
tmp_root.free_root(MYF(0));
985
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
298
tmp_root.free_root(MYF(0));
303
bool plugin_finalize(module::Registry ®istry)
989
306
Now we initialize all remaining plugins
992
reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
995
for (i= 0; i < plugin_array.elements; i++)
308
BOOST_FOREACH(module::Registry::ModuleList::const_reference module, registry.getList())
997
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
998
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
310
if (not module->isInited && plugin_initialize(registry, module))
1000
if (plugin_initialize(plugin_ptr))
1002
plugin_ptr->state= PLUGIN_IS_DYING;
1003
*(reap++)= plugin_ptr;
312
registry.remove(module);
1009
Check if any plugins have to be reaped
1011
while ((plugin_ptr= *(--reap)))
1013
plugin_deinitialize(plugin_ptr, true);
1014
plugin_del(plugin_ptr);
1020
free_root(&tmp_root, MYF(0));
1026
free_root(&tmp_root, MYF(0));
1031
static bool register_builtin(struct st_mysql_plugin *plugin,
1032
struct st_plugin_int *tmp,
1033
struct st_plugin_int **ptr)
1036
tmp->state= PLUGIN_IS_UNINITIALIZED;
1040
if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
1043
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1044
struct st_plugin_int **)=
1045
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
1046
sizeof(struct st_plugin_int));
1048
if (my_hash_insert(&plugin_hash[plugin->type],(unsigned char*) *ptr))
317
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
319
value.second->prime();
325
Window of opportunity for plugins to issue any queries with the database up and running but with no user's connected.
327
void plugin_startup_window(module::Registry ®istry, drizzled::Session &session)
329
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
331
value.second->startup(session);
336
public unary_function<string, bool>
338
const string to_match;
340
explicit PrunePlugin(const string &match_in) :
344
result_type operator()(const string &match_against)
346
return match_against == to_match;
350
static void plugin_prune_list(vector<string> &plugin_list,
351
const vector<string> &plugins_to_remove)
353
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
354
iter != plugins_to_remove.end();
357
plugin_list.erase(remove_if(plugin_list.begin(),
1056
365
called only by plugin_init()
1058
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
367
static bool plugin_load_list(module::Registry ®istry,
368
memory::Root *tmp_root,
369
const set<string> &plugin_list,
370
po::options_description &long_options,
1061
char buffer[FN_REFLEN];
1062
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
1063
struct st_plugin_dl *plugin_dl;
1064
struct st_mysql_plugin *plugin;
373
BOOST_FOREACH(const string& plugin_name, plugin_list)
1068
if (p == buffer + sizeof(buffer) - 1)
375
module::Library* library= registry.addLibrary(plugin_name, builtin);
1070
sql_print_error(_("plugin-load parameter too long"));
378
errmsg_printf(error::ERROR,
379
_("Couldn't load plugin library named '%s'.\n"),
380
plugin_name.c_str());
1074
switch ((*(p++)= *(list++))) {
1076
list= NULL; /* terminate the loop */
1078
case ':': /* can't use this as delimiter as it may be drive letter */
1080
str->str[str->length]= '\0';
1081
if (str == &name) // load all plugins in named module
1085
p--; /* reset pointer */
1090
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1092
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
1094
name.str= (char *) plugin->name;
1095
name.length= strlen(name.str);
1097
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1098
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1101
plugin_dl_del(&dl); // reduce ref count
1106
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1107
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1110
name.length= dl.length= 0;
1111
dl.str= NULL; name.str= p= buffer;
1118
name.str[name.length]= '\0';
384
tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
385
if (plugin_add(registry, tmp_root, library, long_options))
387
registry.removeLibrary(plugin_name);
388
errmsg_printf(error::ERROR,
389
_("Couldn't load plugin named '%s'.\n"),
390
plugin_name.c_str());
1130
sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
1136
void plugin_shutdown(void)
397
void module_shutdown(module::Registry ®istry)
1138
uint32_t i, count= plugin_array.elements, free_slots= 0;
1139
struct st_plugin_int **plugins, *plugin;
1140
struct st_plugin_dl **dl;
1142
399
if (initialized)
1144
401
reap_needed= true;
1147
We want to shut down plugins in a reasonable order, this will
1148
become important when we have plugins which depend upon each other.
1149
Circular references cannot be reaped so they are forced afterwards.
1150
TODO: Have an additional step here to notify all active plugins that
1151
shutdown is requested to allow plugins to deinitialize in parallel.
1153
while (reap_needed && (count= plugin_array.elements))
1156
for (i= free_slots= 0; i < count; i++)
1158
plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1159
switch (plugin->state) {
1160
case PLUGIN_IS_READY:
1161
plugin->state= PLUGIN_IS_DELETED;
1164
case PLUGIN_IS_FREED:
1165
case PLUGIN_IS_UNINITIALIZED:
1173
release any plugin references held.
1175
unlock_variables(NULL, &global_system_variables);
1176
unlock_variables(NULL, &max_system_variables);
1180
if (count > free_slots)
1181
sql_print_warning(_("Forcing shutdown of %d plugins"),
1182
count - free_slots);
1184
plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1187
If we have any plugins which did not die cleanly, we force shutdown
1189
for (i= 0; i < count; i++)
1191
plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1192
/* change the state to ensure no reaping races */
1193
if (plugins[i]->state == PLUGIN_IS_DELETED)
1194
plugins[i]->state= PLUGIN_IS_DYING;
1198
We loop through all plugins and call deinit() if they have one.
1200
for (i= 0; i < count; i++)
1201
if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1203
sql_print_information(_("Plugin '%s' will be forced to shutdown"),
1204
plugins[i]->name.str);
1206
We are forcing deinit on plugins so we don't want to do a ref_count
1207
check until we have processed all the plugins.
1209
plugin_deinitialize(plugins[i], false);
1213
We defer checking ref_counts until after all plugins are deinitialized
1214
as some may have worker threads holding on to plugin references.
1216
for (i= 0; i < count; i++)
1218
if (plugins[i]->ref_count)
1219
sql_print_error(_("Plugin '%s' has ref_count=%d after shutdown."),
1220
plugins[i]->name.str, plugins[i]->ref_count);
1221
if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1222
plugin_del(plugins[i]);
1226
Now we can deallocate all memory.
1229
cleanup_variables(NULL, &global_system_variables);
1230
cleanup_variables(NULL, &max_system_variables);
403
reap_plugins(registry);
404
unlock_variables(NULL, &global_system_variables);
405
unlock_variables(NULL, &max_system_variables);
407
cleanup_variables(&global_system_variables);
408
cleanup_variables(&max_system_variables);
1237
413
/* Dispose of the memory */
1239
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1240
hash_free(&plugin_hash[i]);
1241
delete_dynamic(&plugin_array);
1243
count= plugin_dl_array.elements;
1244
dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1245
for (i= 0; i < count; i++)
1246
dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1247
for (i= 0; i < plugin_dl_array.elements; i++)
1248
free_plugin_mem(dl[i]);
1250
delete_dynamic(&plugin_dl_array);
1252
hash_free(&bookmark_hash);
1253
free_root(&plugin_mem_root, MYF(0));
414
plugin_mem_root.free_root(MYF(0));
1255
416
global_variables_dynamic_size= 0;
1261
bool plugin_foreach_with_mask(Session *session, plugin_foreach_func *func,
1262
int type, uint32_t state_mask, void *arg)
1264
uint32_t idx, total;
1265
struct st_plugin_int *plugin, **plugins;
1266
int version=plugin_array_version;
1271
state_mask= ~state_mask; // do it only once
1273
total= type == DRIZZLE_ANY_PLUGIN ? plugin_array.elements
1274
: plugin_hash[type].records;
1276
Do the alloca out here in case we do have a working alloca:
1277
leaving the nested stack frame invalidates alloca allocation.
1279
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1280
if (type == DRIZZLE_ANY_PLUGIN)
1282
for (idx= 0; idx < total; idx++)
1284
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1285
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1290
HASH *hash= plugin_hash + type;
1291
for (idx= 0; idx < total; idx++)
1293
plugin= (struct st_plugin_int *) hash_element(hash, idx);
1294
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1297
for (idx= 0; idx < total; idx++)
1299
if (unlikely(version != plugin_array_version))
1301
for (uint32_t i=idx; i < total; i++)
1302
if (plugins[i] && plugins[i]->state & state_mask)
1305
plugin= plugins[idx];
1306
/* It will stop iterating on first engine error when "func" returns true */
1307
if (plugin && func(session, plugin_int_to_ref(plugin), arg))
1319
/****************************************************************************
1320
Internal type declarations for variables support
1321
****************************************************************************/
1323
#undef DRIZZLE_SYSVAR_NAME
1324
#define DRIZZLE_SYSVAR_NAME(name) name
1325
#define PLUGIN_VAR_TYPEMASK 0x007f
1327
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1329
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1330
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1331
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1332
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1334
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1335
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1336
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1337
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1339
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1340
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1341
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1342
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1343
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1344
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1346
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
1347
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
1348
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
1349
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
1350
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
1351
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1353
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1356
/****************************************************************************
1357
default variable data check and update functions
1358
****************************************************************************/
1360
static int check_func_bool(Session *session __attribute__((unused)),
1361
struct st_mysql_sys_var *var,
1362
void *save, st_mysql_value *value)
1364
char buff[STRING_BUFFER_USUAL_SIZE];
1365
const char *strvalue= "NULL", *str;
1369
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1371
length= sizeof(buff);
1372
if (!(str= value->val_str(value, buff, &length)) ||
1373
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
1382
if (value->val_int(value, &tmp) < 0)
1392
*(int*)save= -result;
1395
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1400
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1401
void *save, st_mysql_value *value)
1405
struct my_option options;
1406
value->val_int(value, &tmp);
1407
plugin_opt_set_limits(&options, var);
1409
if (var->flags & PLUGIN_VAR_UNSIGNED)
1410
*(uint32_t *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
1413
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1415
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1416
var->name, (int64_t) tmp);
1420
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1421
void *save, st_mysql_value *value)
1425
struct my_option options;
1426
value->val_int(value, &tmp);
1427
plugin_opt_set_limits(&options, var);
1429
if (var->flags & PLUGIN_VAR_UNSIGNED)
1430
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
1433
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1435
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1436
var->name, (int64_t) tmp);
1440
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1441
void *save, st_mysql_value *value)
1445
struct my_option options;
1446
value->val_int(value, &tmp);
1447
plugin_opt_set_limits(&options, var);
1449
if (var->flags & PLUGIN_VAR_UNSIGNED)
1450
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
1453
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1455
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1456
var->name, (int64_t) tmp);
1459
static int check_func_str(Session *session,
1460
struct st_mysql_sys_var *var __attribute__((unused)),
1461
void *save, st_mysql_value *value)
1463
char buff[STRING_BUFFER_USUAL_SIZE];
1467
length= sizeof(buff);
1468
if ((str= value->val_str(value, buff, &length)))
1469
str= session->strmake(str, length);
1470
*(const char**)save= str;
1475
static int check_func_enum(Session *session __attribute__((unused)),
1476
struct st_mysql_sys_var *var,
1477
void *save, st_mysql_value *value)
1479
char buff[STRING_BUFFER_USUAL_SIZE];
1480
const char *strvalue= "NULL", *str;
1486
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1487
typelib= ((sessionvar_enum_t*) var)->typelib;
1489
typelib= ((sysvar_enum_t*) var)->typelib;
1491
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1493
length= sizeof(buff);
1494
if (!(str= value->val_str(value, buff, &length)))
1496
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1504
if (value->val_int(value, &tmp))
1506
if (tmp >= typelib->count)
1514
*(long*)save= result;
1517
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1522
static int check_func_set(Session *session __attribute__((unused)),
1523
struct st_mysql_sys_var *var,
1524
void *save, st_mysql_value *value)
1526
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1527
const char *strvalue= "NULL", *str;
1534
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1535
typelib= ((sessionvar_set_t*) var)->typelib;
1537
typelib= ((sysvar_set_t*)var)->typelib;
1539
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1541
length= sizeof(buff);
1542
if (!(str= value->val_str(value, buff, &length)))
1544
result= find_set(typelib, str, length, NULL,
1545
&error, &error_len, ¬_used);
1548
strmake(buff, error, cmin(sizeof(buff), (unsigned long)error_len));
1555
if (value->val_int(value, (int64_t *)&result))
1557
if (unlikely((result >= (1UL << typelib->count)) &&
1558
(typelib->count < sizeof(long)*8)))
1560
llstr(result, buff);
1565
*(uint64_t*)save= result;
1568
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1573
static void update_func_bool(Session *session __attribute__((unused)),
1574
struct st_mysql_sys_var *var __attribute__((unused)),
1575
void *tgt, const void *save)
1577
*(bool *) tgt= *(int *) save ? 1 : 0;
1581
static void update_func_int(Session *session __attribute__((unused)),
1582
struct st_mysql_sys_var *var __attribute__((unused)),
1583
void *tgt, const void *save)
1585
*(int *)tgt= *(int *) save;
1589
static void update_func_long(Session *session __attribute__((unused)),
1590
struct st_mysql_sys_var *var __attribute__((unused)),
1591
void *tgt, const void *save)
1593
*(long *)tgt= *(long *) save;
1597
static void update_func_int64_t(Session *session __attribute__((unused)),
1598
struct st_mysql_sys_var *var __attribute__((unused)),
1599
void *tgt, const void *save)
1601
*(int64_t *)tgt= *(uint64_t *) save;
1605
static void update_func_str(Session *session __attribute__((unused)), struct st_mysql_sys_var *var,
1606
void *tgt, const void *save)
1608
char *old= *(char **) tgt;
1609
*(char **)tgt= *(char **) save;
1610
if (var->flags & PLUGIN_VAR_MEMALLOC)
1612
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
1620
422
****************************************************************************/
1623
sys_var *find_sys_var(Session *session, const char *str, uint32_t length)
1626
sys_var_pluginvar *pi= NULL;
1629
rw_rdlock(&LOCK_system_variables_hash);
1630
if ((var= intern_find_sys_var(str, length, false)) &&
1631
(pi= var->cast_pluginvar()))
1633
rw_unlock(&LOCK_system_variables_hash);
1634
LEX *lex= session ? session->lex : 0;
1635
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1636
var= NULL; /* failed to lock it, it must be uninstalling */
1638
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
1640
/* initialization not completed */
1642
intern_plugin_unlock(lex, plugin);
1646
rw_unlock(&LOCK_system_variables_hash);
1649
If the variable exists but the plugin it is associated with is not ready
1650
then the intern_plugin_lock did not raise an error, so we do it here.
1653
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1659
called by register_var, construct_options and test_plugin_options.
1660
Returns the 'bookmark' for the named variable.
1661
LOCK_system_variables_hash should be at least read locked
1663
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1665
st_bookmark *result= NULL;
1666
uint32_t namelen, length, pluginlen= 0;
1669
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1672
namelen= strlen(name);
1674
pluginlen= strlen(plugin) + 1;
1675
length= namelen + pluginlen + 2;
1676
varname= (char*) my_alloca(length);
1680
strxmov(varname + 1, plugin, "_", name, NULL);
1681
for (p= varname + 1; *p; p++)
1686
memcpy(varname + 1, name, namelen + 1);
1688
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1690
result= (st_bookmark*) hash_search(&bookmark_hash,
1691
(const unsigned char*) varname, length - 1);
1699
returns a bookmark for session-local variables, creating if neccessary.
1700
returns null for non session-local variables.
1701
Requires that a write lock is obtained on LOCK_system_variables_hash
1703
static st_bookmark *register_var(const char *plugin, const char *name,
1706
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1707
st_bookmark *result;
1710
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1713
switch (flags & PLUGIN_VAR_TYPEMASK) {
1714
case PLUGIN_VAR_BOOL:
1717
case PLUGIN_VAR_INT:
1720
case PLUGIN_VAR_LONG:
1721
case PLUGIN_VAR_ENUM:
1724
case PLUGIN_VAR_LONGLONG:
1725
case PLUGIN_VAR_SET:
1726
size= sizeof(uint64_t);
1728
case PLUGIN_VAR_STR:
1729
size= sizeof(char*);
1736
varname= ((char*) my_alloca(length));
1737
strxmov(varname + 1, plugin, "_", name, NULL);
1738
for (p= varname + 1; *p; p++)
1742
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1744
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1745
sizeof(struct st_bookmark) + length-1);
1746
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1747
memcpy(result->key, varname, length);
1748
result->name_len= length - 2;
1751
assert(size && !(size & (size-1))); /* must be power of 2 */
1753
offset= global_system_variables.dynamic_variables_size;
1754
offset= (offset + size - 1) & ~(size - 1);
1755
result->offset= (int) offset;
1757
new_size= (offset + size + 63) & ~63;
1759
if (new_size > global_variables_dynamic_size)
1761
global_system_variables.dynamic_variables_ptr= (char*)
1762
my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1763
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1764
max_system_variables.dynamic_variables_ptr= (char*)
1765
my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1766
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1768
Clear the new variable value space. This is required for string
1769
variables. If their value is non-NULL, it must point to a valid
1772
memset(global_system_variables.dynamic_variables_ptr +
1773
global_variables_dynamic_size, 0,
1774
new_size - global_variables_dynamic_size);
1775
memset(max_system_variables.dynamic_variables_ptr +
1776
global_variables_dynamic_size, 0,
1777
new_size - global_variables_dynamic_size);
1778
global_variables_dynamic_size= new_size;
1781
global_system_variables.dynamic_variables_head= offset;
1782
max_system_variables.dynamic_variables_head= offset;
1783
global_system_variables.dynamic_variables_size= offset + size;
1784
max_system_variables.dynamic_variables_size= offset + size;
1785
global_system_variables.dynamic_variables_version++;
1786
max_system_variables.dynamic_variables_version++;
1788
result->version= global_system_variables.dynamic_variables_version;
1790
/* this should succeed because we have already checked if a dup exists */
1791
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1793
fprintf(stderr, "failed to add placeholder to hash");
1803
returns a pointer to the memory which holds the session-local variable or
1804
a pointer to the global variable if session==null.
1805
If required, will sync with global variables if the requested variable
1806
has not yet been allocated in the current thread.
1808
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1810
assert(offset >= 0);
1811
assert((uint)offset <= global_system_variables.dynamic_variables_head);
1814
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1817
dynamic_variables_head points to the largest valid offset
1819
if (!session->variables.dynamic_variables_ptr ||
1820
(uint)offset > session->variables.dynamic_variables_head)
1824
rw_rdlock(&LOCK_system_variables_hash);
1826
session->variables.dynamic_variables_ptr= (char*)
1827
my_realloc(session->variables.dynamic_variables_ptr,
1828
global_variables_dynamic_size,
1829
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1832
pthread_mutex_lock(&LOCK_global_system_variables);
1834
safe_mutex_assert_owner(&LOCK_global_system_variables);
1836
memcpy(session->variables.dynamic_variables_ptr +
1837
session->variables.dynamic_variables_size,
1838
global_system_variables.dynamic_variables_ptr +
1839
session->variables.dynamic_variables_size,
1840
global_system_variables.dynamic_variables_size -
1841
session->variables.dynamic_variables_size);
1844
now we need to iterate through any newly copied 'defaults'
1845
and if it is a string type with MEMALLOC flag, we need to strdup
1847
for (idx= 0; idx < bookmark_hash.records; idx++)
1849
sys_var_pluginvar *pi;
1851
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1853
if (v->version <= session->variables.dynamic_variables_version ||
1854
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1855
!(pi= var->cast_pluginvar()) ||
1856
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1859
/* Here we do anything special that may be required of the data types */
1861
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1862
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1864
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1865
*(int*)(pi->plugin_var + 1));
1866
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1867
*(int*)(pi->plugin_var + 1))))
1868
*pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
1873
pthread_mutex_unlock(&LOCK_global_system_variables);
1875
session->variables.dynamic_variables_version=
1876
global_system_variables.dynamic_variables_version;
1877
session->variables.dynamic_variables_head=
1878
global_system_variables.dynamic_variables_head;
1879
session->variables.dynamic_variables_size=
1880
global_system_variables.dynamic_variables_size;
1882
rw_unlock(&LOCK_system_variables_hash);
1884
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1887
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1889
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1892
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1894
return (int *)intern_sys_var_ptr(a_session, offset, true);
1897
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1899
return (long *)intern_sys_var_ptr(a_session, offset, true);
1902
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1904
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1907
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1909
return (char **)intern_sys_var_ptr(a_session, offset, true);
1912
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1914
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1917
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1919
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
1923
426
void plugin_sessionvar_init(Session *session)
1925
plugin_ref old_table_plugin= session->variables.table_plugin;
1927
session->variables.table_plugin= NULL;
1928
cleanup_variables(session, &session->variables);
428
session->variables.storage_engine= NULL;
429
cleanup_variables(&session->variables);
1930
431
session->variables= global_system_variables;
1931
session->variables.table_plugin= NULL;
432
session->variables.storage_engine= NULL;
1933
434
/* we are going to allocate these lazily */
1934
435
session->variables.dynamic_variables_version= 0;
1935
436
session->variables.dynamic_variables_size= 0;
1936
437
session->variables.dynamic_variables_ptr= 0;
1938
session->variables.table_plugin=
1939
my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1940
intern_plugin_unlock(NULL, old_table_plugin);
439
session->variables.storage_engine= global_system_variables.storage_engine;
1946
444
Unlocks all system variables which hold a reference
1948
static void unlock_variables(Session *session __attribute__((unused)),
1949
struct system_variables *vars)
446
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
1951
intern_plugin_unlock(NULL, vars->table_plugin);
1952
vars->table_plugin= NULL;
448
vars->storage_engine= NULL;
2001
469
void plugin_sessionvar_cleanup(Session *session)
2006
471
unlock_variables(session, &session->variables);
2007
cleanup_variables(session, &session->variables);
2009
if ((idx= session->lex->plugins.elements))
2011
list= ((plugin_ref*) session->lex->plugins.buffer) + idx - 1;
2012
while ((unsigned char*) list >= session->lex->plugins.buffer)
2013
intern_plugin_unlock(NULL, *list--);
2016
reset_dynamic(&session->lex->plugins);
2023
@brief Free values of thread variables of a plugin.
2025
This must be called before a plugin is deleted. Otherwise its
2026
variables are no longer accessible and the value space is lost. Note
2027
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
2030
@param[in] vars Chain of system variables of a plugin
2033
static void plugin_vars_free_values(sys_var *vars)
2036
for (sys_var *var= vars; var; var= var->next)
2038
sys_var_pluginvar *piv= var->cast_pluginvar();
2040
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
2041
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
2043
/* Free the string from global_system_variables. */
2044
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2053
bool sys_var_pluginvar::check_update_type(Item_result type)
2057
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2058
case PLUGIN_VAR_INT:
2059
case PLUGIN_VAR_LONG:
2060
case PLUGIN_VAR_LONGLONG:
2061
return type != INT_RESULT;
2062
case PLUGIN_VAR_STR:
2063
return type != STRING_RESULT;
2070
SHOW_TYPE sys_var_pluginvar::show_type()
2072
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2073
case PLUGIN_VAR_BOOL:
2074
return SHOW_MY_BOOL;
2075
case PLUGIN_VAR_INT:
2077
case PLUGIN_VAR_LONG:
2079
case PLUGIN_VAR_LONGLONG:
2080
return SHOW_LONGLONG;
2081
case PLUGIN_VAR_STR:
2082
return SHOW_CHAR_PTR;
2083
case PLUGIN_VAR_ENUM:
2084
case PLUGIN_VAR_SET:
2093
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2095
assert(session || (type == OPT_GLOBAL));
2096
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2098
if (type == OPT_GLOBAL)
2101
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2103
return *(unsigned char**) (plugin_var+1);
2107
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2109
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2110
case PLUGIN_VAR_ENUM:
2111
return ((sysvar_enum_t *)plugin_var)->typelib;
2112
case PLUGIN_VAR_SET:
2113
return ((sysvar_set_t *)plugin_var)->typelib;
2114
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2115
return ((sessionvar_enum_t *)plugin_var)->typelib;
2116
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2117
return ((sessionvar_set_t *)plugin_var)->typelib;
2125
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type,
2126
LEX_STRING *base __attribute__((unused)))
2128
unsigned char* result;
2130
result= real_value_ptr(session, type);
2132
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2133
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2134
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2136
char buffer[STRING_BUFFER_USUAL_SIZE];
2137
String str(buffer, sizeof(buffer), system_charset_info);
2138
TYPELIB *typelib= plugin_var_typelib();
2139
uint64_t mask= 1, value= *(uint64_t*) result;
2143
for (i= 0; i < typelib->count; i++, mask<<=1)
2145
if (!(value & mask))
2147
str.append(typelib->type_names[i], typelib->type_lengths[i]);
2151
result= (unsigned char*) "";
2153
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2159
bool sys_var_pluginvar::check(Session *session, set_var *var)
2161
st_item_value_holder value;
2162
assert(is_readonly() || plugin_var->check);
2164
value.value_type= item_value_type;
2165
value.val_str= item_val_str;
2166
value.val_int= item_val_int;
2167
value.val_real= item_val_real;
2168
value.item= var->value;
2170
return is_readonly() ||
2171
plugin_var->check(session, plugin_var, &var->save_result, &value);
2175
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2180
assert(is_readonly() || plugin_var->update);
2185
pthread_mutex_lock(&LOCK_global_system_variables);
2186
tgt= real_value_ptr(session, type);
2187
src= ((void **) (plugin_var + 1) + 1);
2189
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2191
if (type != OPT_GLOBAL)
2192
src= real_value_ptr(session, OPT_GLOBAL);
2194
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2195
case PLUGIN_VAR_INT:
2196
src= &((sessionvar_uint_t*) plugin_var)->def_val;
2198
case PLUGIN_VAR_LONG:
2199
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2201
case PLUGIN_VAR_LONGLONG:
2202
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2204
case PLUGIN_VAR_ENUM:
2205
src= &((sessionvar_enum_t*) plugin_var)->def_val;
2207
case PLUGIN_VAR_SET:
2208
src= &((sessionvar_set_t*) plugin_var)->def_val;
2210
case PLUGIN_VAR_BOOL:
2211
src= &((sessionvar_bool_t*) plugin_var)->def_val;
2213
case PLUGIN_VAR_STR:
2214
src= &((sessionvar_str_t*) plugin_var)->def_val;
2221
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
2222
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
2223
session == current_session);
2225
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2227
plugin_var->update(session, plugin_var, tgt, src);
2228
pthread_mutex_unlock(&LOCK_global_system_variables);
2232
pthread_mutex_unlock(&LOCK_global_system_variables);
2233
plugin_var->update(session, plugin_var, tgt, src);
2238
bool sys_var_pluginvar::update(Session *session, set_var *var)
2242
assert(is_readonly() || plugin_var->update);
2244
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
2245
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
2246
session == current_session);
2251
pthread_mutex_lock(&LOCK_global_system_variables);
2252
tgt= real_value_ptr(session, var->type);
2254
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2256
/* variable we are updating has global scope, so we unlock after updating */
2257
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2258
pthread_mutex_unlock(&LOCK_global_system_variables);
2262
pthread_mutex_unlock(&LOCK_global_system_variables);
2263
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2269
#define OPTION_SET_LIMITS(type, options, opt) \
2270
options->var_type= type; \
2271
options->def_value= (opt)->def_val; \
2272
options->min_value= (opt)->min_val; \
2273
options->max_value= (opt)->max_val; \
2274
options->block_size= (long) (opt)->blk_sz
2277
static void plugin_opt_set_limits(struct my_option *options,
2278
const struct st_mysql_sys_var *opt)
2280
options->sub_size= 0;
2282
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2283
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2284
/* global system variables */
2285
case PLUGIN_VAR_INT:
2286
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2288
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
2289
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
2291
case PLUGIN_VAR_LONG:
2292
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2294
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2295
OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
2297
case PLUGIN_VAR_LONGLONG:
2298
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2300
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
2301
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
2303
case PLUGIN_VAR_ENUM:
2304
options->var_type= GET_ENUM;
2305
options->typelib= ((sysvar_enum_t*) opt)->typelib;
2306
options->def_value= ((sysvar_enum_t*) opt)->def_val;
2307
options->min_value= options->block_size= 0;
2308
options->max_value= options->typelib->count - 1;
2310
case PLUGIN_VAR_SET:
2311
options->var_type= GET_SET;
2312
options->typelib= ((sysvar_set_t*) opt)->typelib;
2313
options->def_value= ((sysvar_set_t*) opt)->def_val;
2314
options->min_value= options->block_size= 0;
2315
options->max_value= (1UL << options->typelib->count) - 1;
2317
case PLUGIN_VAR_BOOL:
2318
options->var_type= GET_BOOL;
2319
options->def_value= ((sysvar_bool_t*) opt)->def_val;
2321
case PLUGIN_VAR_STR:
2322
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2323
GET_STR_ALLOC : GET_STR);
2324
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2326
/* threadlocal variables */
2327
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
2328
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
2330
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2331
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
2333
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
2334
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
2336
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2337
OPTION_SET_LIMITS(GET_ULONG, options, (sessionvar_ulong_t*) opt);
2339
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
2340
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
2342
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2343
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
2345
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2346
options->var_type= GET_ENUM;
2347
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
2348
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2349
options->min_value= options->block_size= 0;
2350
options->max_value= options->typelib->count - 1;
2352
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2353
options->var_type= GET_SET;
2354
options->typelib= ((sessionvar_set_t*) opt)->typelib;
2355
options->def_value= ((sessionvar_set_t*) opt)->def_val;
2356
options->min_value= options->block_size= 0;
2357
options->max_value= (1UL << options->typelib->count) - 1;
2359
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2360
options->var_type= GET_BOOL;
2361
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2363
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2364
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2365
GET_STR_ALLOC : GET_STR);
2366
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2371
options->arg_type= REQUIRED_ARG;
2372
if (opt->flags & PLUGIN_VAR_NOCMDARG)
2373
options->arg_type= NO_ARG;
2374
if (opt->flags & PLUGIN_VAR_OPCMDARG)
2375
options->arg_type= OPT_ARG;
2378
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2381
bool get_one_plugin_option(int optid __attribute__((unused)),
2382
const struct my_option *opt __attribute__((unused)),
2383
char *argument __attribute__((unused)))
2389
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
2390
my_option *options, bool can_disable)
2392
const char *plugin_name= tmp->plugin->name;
2393
uint32_t namelen= strlen(plugin_name), optnamelen;
2394
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2395
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2397
int index= 0, offset= 0;
2398
st_mysql_sys_var *opt, **plugin_option;
2401
/* support --skip-plugin-foo syntax */
2402
memcpy(name, plugin_name, namelen + 1);
2403
my_casedn_str(&my_charset_utf8_general_ci, name);
2404
strxmov(name + namelen + 1, "plugin-", name, NULL);
2405
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2407
for (p= name + namelen*2 + 8; p > name; p--)
2413
strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2414
"Disable with --skip-", name," (will save memory).", NULL);
2416
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2417
20 + namelen + 20 + 1 == namelen * 4 + 67.
2420
options[0].comment= name + namelen*2 + 10;
2423
options[1].name= (options[0].name= name) + namelen + 1;
2424
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2425
options[0].var_type= options[1].var_type= GET_BOOL;
2426
options[0].arg_type= options[1].arg_type= NO_ARG;
2427
options[0].def_value= options[1].def_value= true;
2428
options[0].value= options[0].u_max_value=
2429
options[1].value= options[1].u_max_value= (char**) (name - 1);
2433
Two passes as the 2nd pass will take pointer addresses for use
2434
by my_getopt and register_var() in the first pass uses realloc
2437
for (plugin_option= tmp->plugin->system_vars;
2438
plugin_option && *plugin_option; plugin_option++, index++)
2440
opt= *plugin_option;
2441
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2443
if (!(register_var(name, opt->name, opt->flags)))
2445
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2446
case PLUGIN_VAR_BOOL:
2447
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2449
case PLUGIN_VAR_INT:
2450
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2452
case PLUGIN_VAR_LONG:
2453
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2455
case PLUGIN_VAR_LONGLONG:
2456
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2458
case PLUGIN_VAR_STR:
2459
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2461
case PLUGIN_VAR_ENUM:
2462
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2464
case PLUGIN_VAR_SET:
2465
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2468
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2469
opt->flags, plugin_name);
2474
for (plugin_option= tmp->plugin->system_vars;
2475
plugin_option && *plugin_option; plugin_option++, index++)
2477
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
2478
case PLUGIN_VAR_BOOL:
2480
opt->check= check_func_bool;
2482
opt->update= update_func_bool;
2484
case PLUGIN_VAR_INT:
2486
opt->check= check_func_int;
2488
opt->update= update_func_int;
2490
case PLUGIN_VAR_LONG:
2492
opt->check= check_func_long;
2494
opt->update= update_func_long;
2496
case PLUGIN_VAR_LONGLONG:
2498
opt->check= check_func_int64_t;
2500
opt->update= update_func_int64_t;
2502
case PLUGIN_VAR_STR:
2504
opt->check= check_func_str;
2507
opt->update= update_func_str;
2508
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2510
opt->flags|= PLUGIN_VAR_READONLY;
2511
sql_print_warning(_("Server variable %s of plugin %s was forced "
2512
"to be read-only: string variable without "
2513
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2514
opt->name, plugin_name);
2518
case PLUGIN_VAR_ENUM:
2520
opt->check= check_func_enum;
2522
opt->update= update_func_long;
2524
case PLUGIN_VAR_SET:
2526
opt->check= check_func_set;
2528
opt->update= update_func_int64_t;
2531
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2532
opt->flags, plugin_name);
2536
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2537
== PLUGIN_VAR_NOCMDOPT)
2542
sql_print_error(_("Missing variable name in plugin '%s'."),
2547
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2549
optnamelen= strlen(opt->name);
2550
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2551
strxmov(optname, name, "-", opt->name, NULL);
2552
optnamelen= namelen + optnamelen + 1;
2556
/* this should not fail because register_var should create entry */
2557
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2559
sql_print_error(_("Thread local variable '%s' not allocated "
2560
"in plugin '%s'."), opt->name, plugin_name);
2564
*(int*)(opt + 1)= offset= v->offset;
2566
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2569
optname= (char*) memdup_root(mem_root, v->key + 1,
2570
(optnamelen= v->name_len) + 1);
2573
/* convert '_' to '-' */
2574
for (p= optname; *p; p++)
2578
options->name= optname;
2579
options->comment= opt->comment;
2580
options->app_type= opt;
2581
options->id= (options-1)->id + 1;
2583
plugin_opt_set_limits(options, opt);
2585
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2586
options->value= options->u_max_value= (char**)
2587
(global_system_variables.dynamic_variables_ptr + offset);
2589
options->value= options->u_max_value= *(char***) (opt + 1);
2591
options[1]= options[0];
2592
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2593
options[1].comment= 0; // hidden
2594
strxmov(p, "plugin-", optname, NULL);
2603
static my_option *construct_help_options(MEM_ROOT *mem_root,
2604
struct st_plugin_int *p)
2606
st_mysql_sys_var **opt;
2609
uint32_t count= EXTRA_OPTIONS;
2611
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2613
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2616
memset(opts, 0, sizeof(my_option) * count);
2618
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2620
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2626
if (construct_options(mem_root, p, opts, can_disable))
472
cleanup_variables(&session->variables);