13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
55
namespace po=boost::program_options;
59
/** These exist just to prevent symbols from being optimized out */
60
typedef drizzled::module::Manifest drizzled_builtin_list[];
61
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
62
drizzled::module::Manifest *drizzled_builtins[]=
64
PANDORA_BUILTIN_SYMBOLS_LIST, NULL
71
class sys_var_pluginvar;
72
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
74
typedef vector<string> PluginOptions;
75
static PluginOptions opt_plugin_load;
76
static PluginOptions opt_plugin_add;
77
static PluginOptions opt_plugin_remove;
16
#include "mysql_priv.h"
17
#include <mysys/my_pthread.h>
18
#include <mysys/my_getopt.h>
19
#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;
78
30
char *opt_plugin_dir_ptr;
79
31
char opt_plugin_dir[FN_REFLEN];
80
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
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[MYSQL_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[MYSQL_MAX_PLUGIN_TYPE_NUM]=
62
ha_initialize_handlerton, /* Storage Engine */
63
initialize_schema_table, /* Information Schema */
64
initialize_udf, /* UDF */
68
authentication_initializer /* Auth */
71
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
74
ha_finalize_handlerton, /* Storage Engine */
75
finalize_schema_table, /* Information Schema */
76
finalize_udf, /* UDF */
80
authentication_finalizer /* Auth */
83
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
82
85
/* Note that 'int version' must be the first field of every plugin
83
86
sub-structure (plugin->info).
86
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[MYSQL_MAX_PLUGIN_TYPE_NUM];
89
94
static bool reap_needed= false;
95
static int plugin_array_version=0;
92
98
write-lock on LOCK_system_variables_hash is required before modifying
93
99
the following variables/structures
95
static memory::Root plugin_mem_root(4096);
96
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;
100
107
hidden part of opaque value passed to variable check functions.
101
108
Used to provide a object-like structure to non C++ consumers.
103
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
123
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
124
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
MYSQL_PLUGIN_VAR_HEADER;
130
148
class sys_var_pluginvar: public sys_var
133
module::Module *plugin;
134
drizzle_sys_var *plugin_var;
136
sys_var_pluginvar(const std::string name_arg,
137
drizzle_sys_var *plugin_var_arg)
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)
138
162
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
139
163
sys_var_pluginvar *cast_pluginvar() { return this; }
140
164
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
141
bool check_type(sql_var_t type)
142
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
165
bool check_type(enum_var_type type)
166
{ return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
143
167
bool check_update_type(Item_result type);
144
168
SHOW_TYPE show_type();
145
unsigned char* real_value_ptr(Session *session, sql_var_t type);
169
uchar* real_value_ptr(THD *thd, enum_var_type type);
146
170
TYPELIB* plugin_var_typelib(void);
147
unsigned char* value_ptr(Session *session, sql_var_t type,
148
const LEX_STRING *base);
149
bool check(Session *session, set_var *var);
150
bool check_default(sql_var_t)
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)))
151
174
{ return is_readonly(); }
152
void set_default(Session *session, sql_var_t);
153
bool update(Session *session, set_var *var);
175
void set_default(THD *thd,
176
enum_var_type type __attribute__((unused)));
177
bool update(THD *thd, set_var *var);
158
static void plugin_prune_list(vector<string> &plugin_list,
159
const vector<string> &plugins_to_remove);
160
static bool plugin_load_list(module::Registry ®istry,
161
memory::Root *tmp_root,
162
const set<string> &plugin_list,
163
po::options_description &long_options,
164
bool builtin= false);
165
static int test_plugin_options(memory::Root *, module::Module *,
166
po::options_description &long_options);
167
static void unlock_variables(Session *session, struct system_variables *vars);
168
static void cleanup_variables(Session *session, struct 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);
169
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);
171
201
/* declared in set_var.cc */
172
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
173
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
174
const std::string &name, int64_t val);
176
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
177
const char *name, int64_t val)
179
const std::string name_str(name);
180
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
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);
183
206
/****************************************************************************
184
207
Value type thunks, allows the C world to play in the C++ world
185
208
****************************************************************************/
187
static int item_value_type(drizzle_value *value)
210
static int item_value_type(struct st_mysql_value *value)
189
212
switch (((st_item_value_holder*)value)->item->result_type()) {
191
return DRIZZLE_VALUE_TYPE_INT;
214
return MYSQL_VALUE_TYPE_INT;
192
215
case REAL_RESULT:
193
return DRIZZLE_VALUE_TYPE_REAL;
216
return MYSQL_VALUE_TYPE_REAL;
195
return DRIZZLE_VALUE_TYPE_STRING;
218
return MYSQL_VALUE_TYPE_STRING;
199
static const char *item_val_str(drizzle_value *value,
222
static const char *item_val_str(struct st_mysql_value *value,
200
223
char *buffer, int *length)
202
225
String str(buffer, *length, system_charset_info), *res;
238
261
Plugin support code
239
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 (my_strchr(files_charset_info, dl->str, dl->str + dl->length, 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 == MYSQL_ANY_PLUGIN)
438
for (i= 0; i < MYSQL_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));
246
555
Requires that a write-lock is held on LOCK_system_variables_hash
248
static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
249
module::Library *library,
250
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)
255
if (registry.find(library->getName()))
561
struct st_plugin_int tmp;
562
struct st_mysql_plugin *plugin;
563
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
257
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
258
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);
262
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)))
263
575
/* Find plugin by name */
264
const module::Manifest *manifest= library->getManifest();
266
if (registry.find(manifest->name))
268
errmsg_printf(ERRMSG_LVL_ERROR,
269
_("Plugin '%s' contains the name '%s' in its manifest, which "
270
"has already been registered.\n"),
271
library->getName().c_str(),
276
tmp= new (std::nothrow) module::Module(manifest, library);
280
if (!test_plugin_options(tmp_root, tmp, long_options))
285
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY),
286
library->getName().c_str());
291
static void delete_module(module::Module *module)
576
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
578
uint name_len= strlen(plugin->name);
579
if (plugin->type >= 0 && plugin->type < MYSQL_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)
293
669
/* Free allocated strings before deleting the plugin. */
294
plugin_vars_free_values(module->system_vars);
295
module->isInited= false;
296
mysql_del_sys_var_chain(module->system_vars);
301
static void reap_plugins(module::Registry ®istry)
303
std::map<std::string, module::Module *>::const_iterator modules=
304
registry.getModulesMap().begin();
306
while (modules != registry.getModulesMap().end())
308
module::Module *module= (*modules).second;
309
delete_module(module);
313
drizzle_del_plugin_sysvar();
317
static void plugin_initialize_vars(module::Module *module)
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 */
320
821
set the plugin attribute of plugin's sys vars so they are pointing
321
822
to the active plugin
323
if (module->system_vars)
824
if (plugin->system_vars)
325
sys_var_pluginvar *var= module->system_vars->cast_pluginvar();
826
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
329
if (! var->getNext())
331
var= var->getNext()->cast_pluginvar();
337
static bool plugin_initialize(module::Registry ®istry,
338
module::Module *module)
340
assert(module->isInited == false);
342
module::Context loading_context(registry, module);
343
if (module->getManifest().init)
345
if (module->getManifest().init(loading_context))
347
errmsg_printf(ERRMSG_LVL_ERROR,
348
_("Plugin '%s' init function returned error.\n"),
349
module->getName().c_str());
353
module->isInited= true;
359
static void compose_plugin_options(vector<string> &target,
360
vector<string> options)
362
for (vector<string>::iterator it= options.begin();
366
tokenize(*it, target, ",", true);
370
void compose_plugin_add(vector<string> options)
372
compose_plugin_options(opt_plugin_add, options);
375
void compose_plugin_remove(vector<string> options)
377
compose_plugin_options(opt_plugin_remove, options);
380
void notify_plugin_load(string in_plugin_load)
382
tokenize(in_plugin_load, opt_plugin_load, ",", true);
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;
386
865
The logic is that we first load and initialize all compiled in plugins.
390
869
Finally we initialize everything, aka the dynamic that have yet to initialize.
392
bool plugin_init(module::Registry ®istry,
393
po::options_description &long_options)
871
int plugin_init(int *argc, char **argv, int flags)
395
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 < MYSQL_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))
402
PluginOptions builtin_list;
403
tokenize(builtin_plugins, builtin_list, ",", true);
405
bool load_failed= false;
407
if (opt_plugin_add.size() > 0)
409
opt_plugin_load.insert(opt_plugin_load.end(),
410
opt_plugin_add.begin(),
411
opt_plugin_add.end());
414
if (opt_plugin_remove.size() > 0)
416
plugin_prune_list(opt_plugin_load, opt_plugin_remove);
417
plugin_prune_list(builtin_list, opt_plugin_remove);
422
906
First we register builtin plugins
424
const set<string> builtin_list_set(builtin_list.begin(), builtin_list.end());
425
load_failed= plugin_load_list(registry, &tmp_root,
426
builtin_list_set, long_options, true);
908
for (builtins= mysqld_builtins; *builtins; builtins++)
429
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);
433
/* Uniquify the list */
434
const set<string> plugin_list_set(opt_plugin_load.begin(),
435
opt_plugin_load.end());
941
/* should now be set to MyISAM storage engine */
942
assert(global_system_variables.table_plugin);
437
944
/* Register all dynamic plugins */
438
load_failed= plugin_load_list(registry, &tmp_root,
439
plugin_list_set, long_options);
945
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
442
tmp_root.free_root(MYF(0));
948
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
446
tmp_root.free_root(MYF(0));
451
void plugin_finalize(module::Registry ®istry)
951
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
455
955
Now we initialize all remaining plugins
457
std::map<std::string, module::Module *>::const_iterator modules=
458
registry.getModulesMap().begin();
460
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++)
462
module::Module *module= (*modules).second;
464
if (module->isInited == false)
963
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
964
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
466
plugin_initialize_vars(module);
468
if (plugin_initialize(registry, module))
966
if (plugin_initialize(plugin_ptr))
470
registry.remove(module);
471
delete_module(module);
968
plugin_ptr->state= PLUGIN_IS_DYING;
969
*(reap++)= plugin_ptr;
478
public unary_function<string, bool>
480
const string to_match;
482
PrunePlugin& operator=(const PrunePlugin&);
484
explicit PrunePlugin(const string &match_in) :
488
result_type operator()(const string &match_against)
490
return match_against == to_match;
494
static void plugin_prune_list(vector<string> &plugin_list,
495
const vector<string> &plugins_to_remove)
497
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
498
iter != plugins_to_remove.end();
501
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))
509
1022
called only by plugin_init()
511
static bool plugin_load_list(module::Registry ®istry,
512
memory::Root *tmp_root,
513
const set<string> &plugin_list,
514
po::options_description &long_options,
1024
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
517
module::Library *library= NULL;
519
for (set<string>::const_iterator iter= plugin_list.begin();
520
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;
523
const string plugin_name(*iter);
525
library= registry.addLibrary(plugin_name, builtin);
1034
if (p == buffer + sizeof(buffer) - 1)
528
errmsg_printf(ERRMSG_LVL_ERROR,
529
_("Couldn't load plugin library named '%s'.\n"),
530
plugin_name.c_str());
1036
sql_print_error("plugin-load parameter too long");
534
tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
535
if (plugin_add(registry, tmp_root, library, long_options))
537
registry.removeLibrary(plugin_name);
538
errmsg_printf(ERRMSG_LVL_ERROR,
539
_("Couldn't load plugin named '%s'.\n"),
540
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'.",
549
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;
552
1108
if (initialized)
554
1110
reap_needed= true;
556
reap_plugins(registry);
557
unlock_variables(NULL, &global_system_variables);
558
unlock_variables(NULL, &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", count - free_slots);
1149
plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1152
If we have any plugins which did not die cleanly, we force shutdown
1154
for (i= 0; i < count; i++)
1156
plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1157
/* change the state to ensure no reaping races */
1158
if (plugins[i]->state == PLUGIN_IS_DELETED)
1159
plugins[i]->state= PLUGIN_IS_DYING;
1163
We loop through all plugins and call deinit() if they have one.
1165
for (i= 0; i < count; i++)
1166
if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1168
sql_print_information("Plugin '%s' will be forced to shutdown",
1169
plugins[i]->name.str);
1171
We are forcing deinit on plugins so we don't want to do a ref_count
1172
check until we have processed all the plugins.
1174
plugin_deinitialize(plugins[i], false);
1178
We defer checking ref_counts until after all plugins are deinitialized
1179
as some may have worker threads holding on to plugin references.
1181
for (i= 0; i < count; i++)
1183
if (plugins[i]->ref_count)
1184
sql_print_error("Plugin '%s' has ref_count=%d after shutdown.",
1185
plugins[i]->name.str, plugins[i]->ref_count);
1186
if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1187
plugin_del(plugins[i]);
1191
Now we can deallocate all memory.
560
1194
cleanup_variables(NULL, &global_system_variables);
561
1195
cleanup_variables(NULL, &max_system_variables);
566
1202
/* Dispose of the memory */
567
plugin_mem_root.free_root(MYF(0));
1204
for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
1205
hash_free(&plugin_hash[i]);
1206
delete_dynamic(&plugin_array);
1208
count= plugin_dl_array.elements;
1209
dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1210
for (i= 0; i < count; i++)
1211
dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1212
for (i= 0; i < plugin_dl_array.elements; i++)
1213
free_plugin_mem(dl[i]);
1215
delete_dynamic(&plugin_dl_array);
1217
hash_free(&bookmark_hash);
1218
free_root(&plugin_mem_root, MYF(0));
569
1220
global_variables_dynamic_size= 0;
1226
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1227
int type, uint state_mask, void *arg)
1230
struct st_plugin_int *plugin, **plugins;
1231
int version=plugin_array_version;
1236
state_mask= ~state_mask; // do it only once
1238
total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements
1239
: plugin_hash[type].records;
1241
Do the alloca out here in case we do have a working alloca:
1242
leaving the nested stack frame invalidates alloca allocation.
1244
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1245
if (type == MYSQL_ANY_PLUGIN)
1247
for (idx= 0; idx < total; idx++)
1249
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1250
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1255
HASH *hash= plugin_hash + type;
1256
for (idx= 0; idx < total; idx++)
1258
plugin= (struct st_plugin_int *) hash_element(hash, idx);
1259
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1262
for (idx= 0; idx < total; idx++)
1264
if (unlikely(version != plugin_array_version))
1266
for (uint i=idx; i < total; i++)
1267
if (plugins[i] && plugins[i]->state & state_mask)
1270
plugin= plugins[idx];
1271
/* It will stop iterating on first engine error when "func" returns true */
1272
if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
572
1284
/****************************************************************************
573
1285
Internal type declarations for variables support
574
1286
****************************************************************************/
576
#undef DRIZZLE_SYSVAR_NAME
577
#define DRIZZLE_SYSVAR_NAME(name) name
1288
#undef MYSQL_SYSVAR_NAME
1289
#define MYSQL_SYSVAR_NAME(name) name
578
1290
#define PLUGIN_VAR_TYPEMASK 0x007f
580
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
582
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
583
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
584
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
585
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
587
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
588
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
590
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
591
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
592
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
593
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
594
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
595
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
597
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
598
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
599
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
600
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
601
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
602
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
604
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1292
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1294
typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_bool_t, bool);
1295
typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_bool_t, bool);
1296
typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_str_t, char *);
1297
typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_str_t, char *);
1299
typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1300
typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
1301
typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1302
typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
1304
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_int_t, int);
1305
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_long_t, long);
1306
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1307
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1308
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1309
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1311
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int_t, int);
1312
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_long_t, long);
1313
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int64_t_t, int64_t);
1314
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint);
1315
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
1316
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint64_t_t, uint64_t);
1318
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
607
1321
/****************************************************************************
608
1322
default variable data check and update functions
609
1323
****************************************************************************/
611
static int check_func_bool(Session *, drizzle_sys_var *var,
612
void *save, drizzle_value *value)
1325
static int check_func_bool(THD *thd __attribute__((unused)),
1326
struct st_mysql_sys_var *var,
1327
void *save, st_mysql_value *value)
614
1329
char buff[STRING_BUFFER_USUAL_SIZE];
615
1330
const char *strvalue= "NULL", *str;
616
1331
int result, length;
619
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1334
if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
621
1336
length= sizeof(buff);
622
1337
if (!(str= value->val_str(value, buff, &length)) ||
716
1432
length= sizeof(buff);
717
1433
if ((str= value->val_str(value, buff, &length)))
718
str= session->strmake(str, length);
1434
str= thd->strmake(str, length);
719
1435
*(const char**)save= str;
724
static void update_func_bool(Session *, drizzle_sys_var *,
1440
static int check_func_enum(THD *thd __attribute__((unused)),
1441
struct st_mysql_sys_var *var,
1442
void *save, st_mysql_value *value)
1444
char buff[STRING_BUFFER_USUAL_SIZE];
1445
const char *strvalue= "NULL", *str;
1451
if (var->flags & PLUGIN_VAR_THDLOCAL)
1452
typelib= ((thdvar_enum_t*) var)->typelib;
1454
typelib= ((sysvar_enum_t*) var)->typelib;
1456
if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
1458
length= sizeof(buff);
1459
if (!(str= value->val_str(value, buff, &length)))
1461
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1469
if (value->val_int(value, &tmp))
1471
if (tmp >= typelib->count)
1479
*(long*)save= result;
1482
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1487
static int check_func_set(THD *thd __attribute__((unused)),
1488
struct st_mysql_sys_var *var,
1489
void *save, st_mysql_value *value)
1491
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1492
const char *strvalue= "NULL", *str;
1499
if (var->flags & PLUGIN_VAR_THDLOCAL)
1500
typelib= ((thdvar_set_t*) var)->typelib;
1502
typelib= ((sysvar_set_t*)var)->typelib;
1504
if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
1506
length= sizeof(buff);
1507
if (!(str= value->val_str(value, buff, &length)))
1509
result= find_set(typelib, str, length, NULL,
1510
&error, &error_len, ¬_used);
1513
strmake(buff, error, min(sizeof(buff), error_len));
1520
if (value->val_int(value, (int64_t *)&result))
1522
if (unlikely((result >= (1ULL << typelib->count)) &&
1523
(typelib->count < sizeof(long)*8)))
1525
llstr(result, buff);
1530
*(uint64_t*)save= result;
1533
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1538
static void update_func_bool(THD *thd __attribute__((unused)),
1539
struct st_mysql_sys_var *var __attribute__((unused)),
725
1540
void *tgt, const void *save)
727
1542
*(bool *) tgt= *(int *) save ? 1 : 0;
731
static void update_func_int(Session *, drizzle_sys_var *,
1546
static void update_func_int(THD *thd __attribute__((unused)),
1547
struct st_mysql_sys_var *var __attribute__((unused)),
732
1548
void *tgt, const void *save)
734
1550
*(int *)tgt= *(int *) save;
738
static void update_func_long(Session *, drizzle_sys_var *,
1554
static void update_func_long(THD *thd __attribute__((unused)),
1555
struct st_mysql_sys_var *var __attribute__((unused)),
739
1556
void *tgt, const void *save)
741
1558
*(long *)tgt= *(long *) save;
745
static void update_func_int64_t(Session *, drizzle_sys_var *,
1562
static void update_func_int64_t(THD *thd __attribute__((unused)),
1563
struct st_mysql_sys_var *var __attribute__((unused)),
746
1564
void *tgt, const void *save)
748
1566
*(int64_t *)tgt= *(uint64_t *) save;
752
static void update_func_str(Session *, drizzle_sys_var *var,
1570
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
753
1571
void *tgt, const void *save)
755
1573
char *old= *(char **) tgt;
756
1574
*(char **)tgt= *(char **) save;
757
1575
if (var->flags & PLUGIN_VAR_MEMALLOC)
759
*(char **)tgt= strdup(*(char **) save);
762
* There isn't a _really_ good thing to do here until this whole set_var
763
* mess gets redesigned
766
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
1577
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
1578
my_free(old, MYF(0));
803
static const string make_bookmark_name(const string &plugin, const char *name)
805
string varname(plugin);
806
varname.push_back('_');
807
varname.append(name);
809
for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
820
1624
called by register_var, construct_options and test_plugin_options.
821
1625
Returns the 'bookmark' for the named variable.
822
1626
LOCK_system_variables_hash should be at least read locked
824
static Bookmark *find_bookmark(const string &plugin, const char *name, int flags)
1628
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
826
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1630
st_bookmark *result= NULL;
1631
uint namelen, length, pluginlen= 0;
1634
if (!(flags & PLUGIN_VAR_THDLOCAL))
829
const string varname(make_bookmark_name(plugin, name));
1637
namelen= strlen(name);
1639
pluginlen= strlen(plugin) + 1;
1640
length= namelen + pluginlen + 2;
1641
varname= (char*) my_alloca(length);
831
bookmark_unordered_map::iterator iter= bookmark_hash.find(varname);
832
if (iter != bookmark_hash.end())
834
return &((*iter).second);
1645
strxmov(varname + 1, plugin, "_", name, NullS);
1646
for (p= varname + 1; *p; p++)
1651
memcpy(varname + 1, name, namelen + 1);
1653
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1655
result= (st_bookmark*) hash_search(&bookmark_hash,
1656
(const uchar*) varname, length - 1);
841
returns a bookmark for session-local variables, creating if neccessary.
842
returns null for non session-local variables.
1664
returns a bookmark for thd-local variables, creating if neccessary.
1665
returns null for non thd-local variables.
843
1666
Requires that a write lock is obtained on LOCK_system_variables_hash
845
static Bookmark *register_var(const string &plugin, const char *name,
1668
static st_bookmark *register_var(const char *plugin, const char *name,
848
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1671
uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1672
st_bookmark *result;
1675
if (!(flags & PLUGIN_VAR_THDLOCAL))
851
uint32_t size= 0, offset, new_size;
852
Bookmark *result= NULL;
854
1678
switch (flags & PLUGIN_VAR_TYPEMASK) {
855
1679
case PLUGIN_VAR_BOOL:
856
size= ALIGN_SIZE(sizeof(bool));
858
1682
case PLUGIN_VAR_INT:
859
size= ALIGN_SIZE(sizeof(int));
861
1685
case PLUGIN_VAR_LONG:
862
size= ALIGN_SIZE(sizeof(long));
1686
case PLUGIN_VAR_ENUM:
864
1689
case PLUGIN_VAR_LONGLONG:
865
size= ALIGN_SIZE(sizeof(uint64_t));
1690
case PLUGIN_VAR_SET:
1691
size= sizeof(uint64_t);
867
1693
case PLUGIN_VAR_STR:
868
size= ALIGN_SIZE(sizeof(char*));
1694
size= sizeof(char*);
1701
varname= ((char*) my_alloca(length));
1702
strxmov(varname + 1, plugin, "_", name, NullS);
1703
for (p= varname + 1; *p; p++)
876
if (!(result= find_bookmark(plugin, name, flags)))
1707
if (!(result= find_bookmark(NULL, varname + 1, flags)))
878
const string varname(make_bookmark_name(plugin, name));
880
Bookmark new_bookmark;
881
new_bookmark.key= varname;
882
new_bookmark.offset= -1;
1709
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1710
sizeof(struct st_bookmark) + length-1);
1711
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1712
memcpy(result->key, varname, length);
1713
result->name_len= length - 2;
884
1716
assert(size && !(size & (size-1))); /* must be power of 2 */
886
1718
offset= global_system_variables.dynamic_variables_size;
887
1719
offset= (offset + size - 1) & ~(size - 1);
888
new_bookmark.offset= (int) offset;
1720
result->offset= (int) offset;
890
1722
new_size= (offset + size + 63) & ~63;
892
1724
if (new_size > global_variables_dynamic_size)
896
(char *)realloc(global_system_variables.dynamic_variables_ptr,
899
global_system_variables.dynamic_variables_ptr= tmpptr;
902
(char *)realloc(max_system_variables.dynamic_variables_ptr,
905
max_system_variables.dynamic_variables_ptr= tmpptr;
1726
global_system_variables.dynamic_variables_ptr= (char*)
1727
my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1728
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1729
max_system_variables.dynamic_variables_ptr= (char*)
1730
my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1731
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
908
1733
Clear the new variable value space. This is required for string
909
1734
variables. If their value is non-NULL, it must point to a valid
925
1750
global_system_variables.dynamic_variables_version++;
926
1751
max_system_variables.dynamic_variables_version++;
928
new_bookmark.version= global_system_variables.dynamic_variables_version;
929
new_bookmark.type_code= flags;
1753
result->version= global_system_variables.dynamic_variables_version;
931
1755
/* this should succeed because we have already checked if a dup exists */
932
bookmark_hash.insert(make_pair(varname, new_bookmark));
933
result= find_bookmark(plugin, name, flags);
1756
if (my_hash_insert(&bookmark_hash, (uchar*) result))
1758
fprintf(stderr, "failed to add placeholder to hash");
940
returns a pointer to the memory which holds the session-local variable or
941
a pointer to the global variable if session==null.
1768
returns a pointer to the memory which holds the thd-local variable or
1769
a pointer to the global variable if thd==null.
942
1770
If required, will sync with global variables if the requested variable
943
1771
has not yet been allocated in the current thread.
945
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1773
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
947
1775
assert(offset >= 0);
948
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1776
assert((uint)offset <= global_system_variables.dynamic_variables_head);
951
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1779
return (uchar*) global_system_variables.dynamic_variables_ptr + offset;
954
1782
dynamic_variables_head points to the largest valid offset
956
if (!session->variables.dynamic_variables_ptr ||
957
(uint32_t)offset > session->variables.dynamic_variables_head)
1784
if (!thd->variables.dynamic_variables_ptr ||
1785
(uint)offset > thd->variables.dynamic_variables_head)
960
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
961
global_variables_dynamic_size)))
963
session->variables.dynamic_variables_ptr= tmpptr;
1789
rw_rdlock(&LOCK_system_variables_hash);
1791
thd->variables.dynamic_variables_ptr= (char*)
1792
my_realloc(thd->variables.dynamic_variables_ptr,
1793
global_variables_dynamic_size,
1794
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
965
1796
if (global_lock)
966
LOCK_global_system_variables.lock();
968
//safe_mutex_assert_owner(&LOCK_global_system_variables);
970
memcpy(session->variables.dynamic_variables_ptr +
971
session->variables.dynamic_variables_size,
1797
pthread_mutex_lock(&LOCK_global_system_variables);
1799
safe_mutex_assert_owner(&LOCK_global_system_variables);
1801
memcpy(thd->variables.dynamic_variables_ptr +
1802
thd->variables.dynamic_variables_size,
972
1803
global_system_variables.dynamic_variables_ptr +
973
session->variables.dynamic_variables_size,
1804
thd->variables.dynamic_variables_size,
974
1805
global_system_variables.dynamic_variables_size -
975
session->variables.dynamic_variables_size);
1806
thd->variables.dynamic_variables_size);
978
1809
now we need to iterate through any newly copied 'defaults'
979
1810
and if it is a string type with MEMALLOC flag, we need to strdup
981
bookmark_unordered_map::iterator iter= bookmark_hash.begin();
982
for (; iter != bookmark_hash.end() ; ++iter)
1812
for (idx= 0; idx < bookmark_hash.records; idx++)
984
1814
sys_var_pluginvar *pi;
986
const Bookmark &v= (*iter).second;
987
const string var_name((*iter).first);
1816
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
989
if (v.version <= session->variables.dynamic_variables_version ||
990
!(var= intern_find_sys_var(var_name.c_str(), var_name.size(), true)) ||
1818
if (v->version <= thd->variables.dynamic_variables_version ||
1819
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
991
1820
!(pi= var->cast_pluginvar()) ||
992
v.type_code != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1821
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
995
1824
/* Here we do anything special that may be required of the data types */
997
1826
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
998
1827
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1000
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1829
char **pp= (char**) (thd->variables.dynamic_variables_ptr +
1001
1830
*(int*)(pi->plugin_var + 1));
1002
1831
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1003
1832
*(int*)(pi->plugin_var + 1))))
1833
*pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
1010
1837
if (global_lock)
1011
LOCK_global_system_variables.unlock();
1838
pthread_mutex_unlock(&LOCK_global_system_variables);
1013
session->variables.dynamic_variables_version=
1840
thd->variables.dynamic_variables_version=
1014
1841
global_system_variables.dynamic_variables_version;
1015
session->variables.dynamic_variables_head=
1842
thd->variables.dynamic_variables_head=
1016
1843
global_system_variables.dynamic_variables_head;
1017
session->variables.dynamic_variables_size=
1844
thd->variables.dynamic_variables_size=
1018
1845
global_system_variables.dynamic_variables_size;
1847
rw_unlock(&LOCK_system_variables_hash);
1020
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1023
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1025
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1028
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1030
return (int *)intern_sys_var_ptr(a_session, offset, true);
1033
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1035
return (long *)intern_sys_var_ptr(a_session, offset, true);
1038
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1040
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1043
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1045
return (char **)intern_sys_var_ptr(a_session, offset, true);
1048
void plugin_sessionvar_init(Session *session)
1050
session->variables.storage_engine= NULL;
1051
cleanup_variables(session, &session->variables);
1053
session->variables= global_system_variables;
1054
session->variables.storage_engine= NULL;
1849
return (uchar*)thd->variables.dynamic_variables_ptr + offset;
1852
static bool *mysql_sys_var_ptr_bool(THD* a_thd, int offset)
1854
return (bool *)intern_sys_var_ptr(a_thd, offset, true);
1857
static int *mysql_sys_var_ptr_int(THD* a_thd, int offset)
1859
return (int *)intern_sys_var_ptr(a_thd, offset, true);
1862
static long *mysql_sys_var_ptr_long(THD* a_thd, int offset)
1864
return (long *)intern_sys_var_ptr(a_thd, offset, true);
1867
static int64_t *mysql_sys_var_ptr_int64_t(THD* a_thd, int offset)
1869
return (int64_t *)intern_sys_var_ptr(a_thd, offset, true);
1872
static char **mysql_sys_var_ptr_str(THD* a_thd, int offset)
1874
return (char **)intern_sys_var_ptr(a_thd, offset, true);
1877
static uint64_t *mysql_sys_var_ptr_set(THD* a_thd, int offset)
1879
return (uint64_t *)intern_sys_var_ptr(a_thd, offset, true);
1882
static unsigned long *mysql_sys_var_ptr_enum(THD* a_thd, int offset)
1884
return (unsigned long *)intern_sys_var_ptr(a_thd, offset, true);
1888
void plugin_thdvar_init(THD *thd)
1890
plugin_ref old_table_plugin= thd->variables.table_plugin;
1892
thd->variables.table_plugin= NULL;
1893
cleanup_variables(thd, &thd->variables);
1895
thd->variables= global_system_variables;
1896
thd->variables.table_plugin= NULL;
1056
1898
/* we are going to allocate these lazily */
1057
session->variables.dynamic_variables_version= 0;
1058
session->variables.dynamic_variables_size= 0;
1059
session->variables.dynamic_variables_ptr= 0;
1899
thd->variables.dynamic_variables_version= 0;
1900
thd->variables.dynamic_variables_size= 0;
1901
thd->variables.dynamic_variables_ptr= 0;
1061
session->variables.storage_engine= global_system_variables.storage_engine;
1903
thd->variables.table_plugin=
1904
my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1905
intern_plugin_unlock(NULL, old_table_plugin);
1066
1911
Unlocks all system variables which hold a reference
1068
static void unlock_variables(Session *, struct system_variables *vars)
1913
static void unlock_variables(THD *thd __attribute__((unused)),
1914
struct system_variables *vars)
1070
vars->storage_engine= NULL;
1916
intern_plugin_unlock(NULL, vars->table_plugin);
1917
vars->table_plugin= NULL;
1251
2147
if (is_readonly())
1254
LOCK_global_system_variables.lock();
1255
tgt= real_value_ptr(session, type);
2150
pthread_mutex_lock(&LOCK_global_system_variables);
2151
tgt= real_value_ptr(thd, type);
1256
2152
src= ((void **) (plugin_var + 1) + 1);
1258
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2154
if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
1260
2156
if (type != OPT_GLOBAL)
1261
src= real_value_ptr(session, OPT_GLOBAL);
2157
src= real_value_ptr(thd, OPT_GLOBAL);
1263
2159
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1264
2160
case PLUGIN_VAR_INT:
1265
src= &((sessionvar_uint_t*) plugin_var)->def_val;
2161
src= &((thdvar_uint_t*) plugin_var)->def_val;
1267
2163
case PLUGIN_VAR_LONG:
1268
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2164
src= &((thdvar_ulong_t*) plugin_var)->def_val;
1270
2166
case PLUGIN_VAR_LONGLONG:
1271
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2167
src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
2169
case PLUGIN_VAR_ENUM:
2170
src= &((thdvar_enum_t*) plugin_var)->def_val;
2172
case PLUGIN_VAR_SET:
2173
src= &((thdvar_set_t*) plugin_var)->def_val;
1273
2175
case PLUGIN_VAR_BOOL:
1274
src= &((sessionvar_bool_t*) plugin_var)->def_val;
2176
src= &((thdvar_bool_t*) plugin_var)->def_val;
1276
2178
case PLUGIN_VAR_STR:
1277
src= &((sessionvar_str_t*) plugin_var)->def_val;
2179
src= &((thdvar_str_t*) plugin_var)->def_val;
1284
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1285
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1286
session == current_session);
2186
/* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2187
assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2188
thd == current_thd);
1288
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2190
if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
1290
plugin_var->update(session, plugin_var, tgt, src);
1291
LOCK_global_system_variables.unlock();
2192
plugin_var->update(thd, plugin_var, tgt, src);
2193
pthread_mutex_unlock(&LOCK_global_system_variables);
1295
LOCK_global_system_variables.unlock();
1296
plugin_var->update(session, plugin_var, tgt, src);
2197
pthread_mutex_unlock(&LOCK_global_system_variables);
2198
plugin_var->update(thd, plugin_var, tgt, src);
1301
bool sys_var_pluginvar::update(Session *session, set_var *var)
2203
bool sys_var_pluginvar::update(THD *thd, set_var *var)
1305
2207
assert(is_readonly() || plugin_var->update);
1307
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1308
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1309
session == current_session);
2209
/* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2210
assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2211
thd == current_thd);
1311
2213
if (is_readonly())
1314
LOCK_global_system_variables.lock();
1315
tgt= real_value_ptr(session, var->type);
2216
pthread_mutex_lock(&LOCK_global_system_variables);
2217
tgt= real_value_ptr(thd, var->type);
1317
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2219
if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
1319
2221
/* variable we are updating has global scope, so we unlock after updating */
1320
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1321
LOCK_global_system_variables.unlock();
2222
plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2223
pthread_mutex_unlock(&LOCK_global_system_variables);
1325
LOCK_global_system_variables.unlock();
1326
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2227
pthread_mutex_unlock(&LOCK_global_system_variables);
2228
plugin_var->update(thd, plugin_var, tgt, &var->save_result);
1332
2234
#define OPTION_SET_LIMITS(type, options, opt) \
1333
options->var_type= type; \
1334
options->def_value= (opt)->def_val; \
1335
options->min_value= (opt)->min_val; \
1336
options->max_value= (opt)->max_val; \
2235
options->var_type= type; \
2236
options->def_value= (opt)->def_val; \
2237
options->min_value= (opt)->min_val; \
2238
options->max_value= (opt)->max_val; \
1337
2239
options->block_size= (long) (opt)->blk_sz
1340
void plugin_opt_set_limits(struct option *options,
1341
const drizzle_sys_var *opt)
2242
static void plugin_opt_set_limits(struct my_option *options,
2243
const struct st_mysql_sys_var *opt)
1343
2245
options->sub_size= 0;
1345
2247
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1346
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2248
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
1347
2249
/* global system variables */
1348
2250
case PLUGIN_VAR_INT:
1349
2251
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1410
2340
options->arg_type= OPT_ARG;
1413
static int construct_options(memory::Root *mem_root, module::Module *tmp,
1417
int localoptionid= 256;
1418
const string plugin_name(tmp->getManifest().name);
1420
size_t namelen= plugin_name.size(), optnamelen;
2343
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2346
bool get_one_plugin_option(int optid __attribute__((unused)),
2347
const struct my_option *opt __attribute__((unused)),
2348
char *argument __attribute__((unused)))
2354
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
2355
my_option *options, bool can_disable)
2357
const char *plugin_name= tmp->plugin->name;
2358
uint namelen= strlen(plugin_name), optnamelen;
2359
uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2360
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
1422
2361
char *optname, *p;
1423
2362
int index= 0, offset= 0;
1424
drizzle_sys_var *opt, **plugin_option;
1427
string name(plugin_name);
1428
transform(name.begin(), name.end(), name.begin(), ::tolower);
1430
for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
2363
st_mysql_sys_var *opt, **plugin_option;
2366
/* support --skip-plugin-foo syntax */
2367
memcpy(name, plugin_name, namelen + 1);
2368
my_casedn_str(&my_charset_latin1, name);
2369
strxmov(name + namelen + 1, "plugin-", name, NullS);
2370
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2372
for (p= name + namelen*2 + 8; p > name; p--)
2378
strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2379
"Disable with --skip-", name," (will save memory).", NullS);
2381
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2382
20 + namelen + 20 + 1 == namelen * 4 + 67.
2385
options[0].comment= name + namelen*2 + 10;
2388
options[1].name= (options[0].name= name) + namelen + 1;
2389
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2390
options[0].var_type= options[1].var_type= GET_BOOL;
2391
options[0].arg_type= options[1].arg_type= NO_ARG;
2392
options[0].def_value= options[1].def_value= true;
2393
options[0].value= options[0].u_max_value=
2394
options[1].value= options[1].u_max_value= (char**) (name - 1);
1437
2398
Two passes as the 2nd pass will take pointer addresses for use
1438
2399
by my_getopt and register_var() in the first pass uses realloc
1441
for (plugin_option= tmp->getManifest().system_vars;
2402
for (plugin_option= tmp->plugin->system_vars;
1442
2403
plugin_option && *plugin_option; plugin_option++, index++)
1444
2405
opt= *plugin_option;
1445
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2406
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
1447
2408
if (!(register_var(name, opt->name, opt->flags)))
1449
2410
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1450
2411
case PLUGIN_VAR_BOOL:
1451
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2412
(((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1453
2414
case PLUGIN_VAR_INT:
1454
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2415
(((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1456
2417
case PLUGIN_VAR_LONG:
1457
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2418
(((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1459
2420
case PLUGIN_VAR_LONGLONG:
1460
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2421
(((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1462
2423
case PLUGIN_VAR_STR:
1463
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2424
(((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2426
case PLUGIN_VAR_ENUM:
2427
(((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2429
case PLUGIN_VAR_SET:
2430
(((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1466
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1467
opt->flags, plugin_name.c_str());
2433
sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
2434
opt->flags, plugin_name);
1472
for (plugin_option= tmp->getManifest().system_vars;
2439
for (plugin_option= tmp->plugin->system_vars;
1473
2440
plugin_option && *plugin_option; plugin_option++, index++)
1475
2442
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1563
2543
options->name= optname;
1564
2544
options->comment= opt->comment;
1565
2545
options->app_type= opt;
1566
options->id= localoptionid++;
2546
options->id= (options-1)->id + 1;
1568
2548
plugin_opt_set_limits(options, opt);
1570
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2550
if (opt->flags & PLUGIN_VAR_THDLOCAL)
1571
2551
options->value= options->u_max_value= (char**)
1572
2552
(global_system_variables.dynamic_variables_ptr + offset);
1574
2554
options->value= options->u_max_value= *(char***) (opt + 1);
2556
options[1]= options[0];
2557
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2558
options[1].comment= 0; // hidden
2559
strxmov(p, "plugin-", optname, NullS);
1583
static option *construct_help_options(memory::Root *mem_root, module::Module *p)
2568
static my_option *construct_help_options(MEM_ROOT *mem_root,
2569
struct st_plugin_int *p)
1585
drizzle_sys_var **opt;
1587
uint32_t count= EXTRA_OPTIONS;
1589
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1591
opts= (option*)mem_root->alloc_root((sizeof(option) * count));
1595
memset(opts, 0, sizeof(option) * count);
1597
if (construct_options(mem_root, p, opts))
2571
st_mysql_sys_var **opt;
2574
uint count= EXTRA_OPTIONS;
2576
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2578
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2581
memset(opts, 0, sizeof(my_option) * count);
2583
if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") == 0))
2585
else if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY") == 0))
2591
if (construct_options(mem_root, p, opts, can_disable))
1603
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1605
plugin_sysvar_vec.push_back(var);
1608
void drizzle_del_plugin_sysvar()
1610
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1611
while(iter != plugin_sysvar_vec.end())
1616
plugin_sysvar_vec.clear();
1621
2600
test_plugin_options()
1622
2601
tmp_root temporary scratch space
1623
2602
plugin internal plugin structure
2603
argc user supplied arguments
2604
argv user supplied arguments
1624
2605
default_enabled default plugin enable status
1626
2607
0 SUCCESS - plugin should be enabled/loaded
1628
2609
Requires that a write-lock is held on LOCK_system_variables_hash
1630
static int test_plugin_options(memory::Root *module_root,
1631
module::Module *test_module,
1632
po::options_description &long_options)
2611
static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
2612
int *argc, char **argv)
1634
2614
struct sys_var_chain chain= { NULL, NULL };
1635
drizzle_sys_var **opt;
2615
bool enabled_saved= true;
2617
MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
2618
&tmp->mem_root : &plugin_mem_root;
2619
st_mysql_sys_var **opt;
2620
my_option *opts= NULL;
1640
uint32_t len, count= EXTRA_OPTIONS;
1642
if (test_module->getManifest().init_options != NULL)
1644
string plugin_section_title("Options used by ");
1645
plugin_section_title.append(test_module->getName());
1646
po::options_description module_options(plugin_section_title);
1647
module::option_context opt_ctx(test_module->getName(),
1648
module_options.add_options());
1649
test_module->getManifest().init_options(opt_ctx);
1650
long_options.add(module_options);
1654
for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
1659
if (count > EXTRA_OPTIONS)
1661
if (!(opts= (option*) module_root->alloc_root(sizeof(option) * count)))
1663
errmsg_printf(ERRMSG_LVL_ERROR,
1664
_("Out of memory for plugin '%s'."),
1665
test_module->getName().c_str());
1668
memset(opts, 0, sizeof(option) * count);
1670
if (construct_options(module_root, test_module, opts))
1672
errmsg_printf(ERRMSG_LVL_ERROR,
1673
_("Bad options for plugin '%s'."),
1674
test_module->getName().c_str());
2623
st_mysql_sys_var *o;
2625
struct st_bookmark *var;
2626
uint len, count= EXTRA_OPTIONS;
2627
assert(tmp->plugin && tmp->name.str);
2629
for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
2630
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
2632
if ((my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") == 0))
2634
else if ((my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY") == 0))
2639
if (count > EXTRA_OPTIONS || (*argc > 1))
2641
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2643
sql_print_error("Out of memory for plugin '%s'.", tmp->name.str);
2646
memset(opts, 0, sizeof(my_option) * count);
2648
if (construct_options(tmp_root, tmp, opts, can_disable))
2650
sql_print_error("Bad options for plugin '%s'.", tmp->name.str);
2654
error= handle_options(argc, &argv, opts, get_one_plugin_option);
2655
(*argc)++; /* add back one for the program name */
2659
sql_print_error("Parsing options for plugin '%s' failed.",
1683
for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
2668
for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
1686
2670
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1689
if ((var= find_bookmark(test_module->getName(), o->name, o->flags)))
1691
v= new sys_var_pluginvar(var->key.c_str(), o);
2673
if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
2674
v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
1695
len= test_module->getName().length() + strlen(o->name) + 2;
1696
string vname(test_module->getName());
1697
vname.push_back('-');
1698
vname.append(o->name);
1699
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1700
string::iterator p= vname.begin();
1701
while (p != vname.end())
2677
len= tmp->name.length + strlen(o->name) + 2;
2678
varname= (char*) alloc_root(mem_root, len);
2679
strxmov(varname, tmp->name.str, "-", o->name, NullS);
2680
my_casedn_str(&my_charset_latin1, varname);
2682
for (p= varname; *p; p++)
1708
v= new sys_var_pluginvar(vname, o);
2686
v= new (mem_root) sys_var_pluginvar(varname, o);
1710
2688
assert(v); /* check that an object was actually constructed */
1712
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1714
2691
Add to the chain of variables.
1715
2692
Done like this for easier debugging so that the