12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
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>
19
#include <drizzled/authentication.h>
20
#include <drizzled/logging.h>
21
#include <drizzled/errmsg.h>
22
#include <drizzled/configvar.h>
23
#include <drizzled/qcache.h>
24
#include <drizzled/parser.h>
25
#include <drizzled/scheduling.h>
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
29
#include <drizzled/error.h>
44
30
#include <drizzled/gettext.h>
45
#include <drizzled/errmsg_print.h>
46
#include <drizzled/strfunc.h>
47
#include <drizzled/pthread_globals.h>
48
#include <drizzled/util/tokenize.h>
50
#include <boost/foreach.hpp>
52
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
32
#define REPORT_TO_LOG 1
33
#define REPORT_TO_USER 2
35
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
36
#define plugin_int_to_ref(A) &(A)
59
38
using namespace std;
61
/** These exist just to prevent symbols from being optimized out */
62
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
drizzled::module::Manifest *drizzled_builtins[]=
67
PANDORA_BUILTIN_SYMBOLS_LIST, NULL
69
drizzled::module::Manifest *drizzled_load_builtins[]=
71
PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
78
typedef vector<string> PluginOptions;
79
static PluginOptions opt_plugin_load;
80
static PluginOptions opt_plugin_add;
81
static PluginOptions opt_plugin_remove;
82
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
40
extern struct st_mysql_plugin *mysqld_builtins[];
42
char *opt_plugin_load= NULL;
43
char *opt_plugin_dir_ptr;
44
char opt_plugin_dir[FN_REFLEN];
46
When you ad a new plugin type, add both a string and make sure that the
47
init and deinit array are correctly updated.
49
const LEX_STRING plugin_type_names[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
51
{ C_STRING_WITH_LEN("DAEMON") },
52
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
53
{ C_STRING_WITH_LEN("INFORMATION SCHEMA") },
54
{ C_STRING_WITH_LEN("UDF") },
55
{ C_STRING_WITH_LEN("UDA") },
56
{ C_STRING_WITH_LEN("AUDIT") },
57
{ C_STRING_WITH_LEN("LOGGER") },
58
{ C_STRING_WITH_LEN("ERRMSG") },
59
{ C_STRING_WITH_LEN("AUTH") },
60
{ C_STRING_WITH_LEN("CONFIGVAR") },
61
{ C_STRING_WITH_LEN("QCACHE") },
62
{ C_STRING_WITH_LEN("PARSER") },
63
{ C_STRING_WITH_LEN("SCHEDULING") }
66
extern int initialize_schema_table(st_plugin_int *plugin);
67
extern int finalize_schema_table(st_plugin_int *plugin);
69
extern int initialize_udf(st_plugin_int *plugin);
70
extern int finalize_udf(st_plugin_int *plugin);
73
The number of elements in both plugin_type_initialize and
74
plugin_type_deinitialize should equal to the number of plugins
77
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
80
ha_initialize_handlerton, /* Storage Engine */
81
initialize_schema_table, /* Information Schema */
82
initialize_udf, /* UDF */
85
logging_initializer, /* Logger */
86
errmsg_initializer, /* Error Messages */
87
authentication_initializer, /* Auth */
88
configvar_initializer,
91
scheduling_initializer
94
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
97
ha_finalize_handlerton, /* Storage Engine */
98
finalize_schema_table, /* Information Schema */
99
finalize_udf, /* UDF */
102
logging_finalizer, /* Logger */
103
errmsg_finalizer, /* Logger */
104
authentication_finalizer, /* Auth */
111
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
85
113
/* Note that 'int version' must be the first field of every plugin
86
114
sub-structure (plugin->info).
89
static bool initialized= false;
117
static bool initialized= 0;
119
static DYNAMIC_ARRAY plugin_dl_array;
120
static DYNAMIC_ARRAY plugin_array;
121
static HASH plugin_hash[DRIZZLE_MAX_PLUGIN_TYPE_NUM];
92
122
static bool reap_needed= false;
123
static int plugin_array_version=0;
95
126
write-lock on LOCK_system_variables_hash is required before modifying
96
127
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
129
static MEM_ROOT plugin_mem_root;
99
130
static uint32_t global_variables_dynamic_size= 0;
131
static HASH bookmark_hash;
103
135
hidden part of opaque value passed to variable check functions.
104
136
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
138
struct st_item_value_holder : public st_mysql_value
145
stored in bookmark_hash, this structure is never removed from the
146
hash and is used to mark a single offset for a session local variable
147
even if plugins have been uninstalled and reinstalled, repeatedly.
148
This structure is allocated from plugin_mem_root.
150
The key format is as follows:
151
1 byte - variable type code
152
name_len bytes - variable name
122
159
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
165
skeleton of a plugin variable - portion of structure common to all.
167
struct st_mysql_sys_var
169
DRIZZLE_PLUGIN_VAR_HEADER;
174
sys_var class for access to all plugin variables visible to the user
176
class sys_var_pluginvar: public sys_var
179
struct st_plugin_int *plugin;
180
struct st_mysql_sys_var *plugin_var;
182
static void *operator new(size_t size, MEM_ROOT *mem_root)
183
{ return (void*) alloc_root(mem_root, (uint) size); }
184
static void operator delete(void *ptr_arg __attribute__((unused)),
185
size_t size __attribute__((unused)))
186
{ TRASH(ptr_arg, size); }
188
sys_var_pluginvar(const char *name_arg,
189
struct st_mysql_sys_var *plugin_var_arg)
190
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
191
sys_var_pluginvar *cast_pluginvar() { return this; }
192
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
193
bool check_type(enum_var_type type)
194
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
195
bool check_update_type(Item_result type);
196
SHOW_TYPE show_type();
197
unsigned char* real_value_ptr(Session *session, enum_var_type type);
198
TYPELIB* plugin_var_typelib(void);
199
unsigned char* value_ptr(Session *session, enum_var_type type, LEX_STRING *base);
200
bool check(Session *session, set_var *var);
201
bool check_default(enum_var_type type __attribute__((unused)))
202
{ return is_readonly(); }
203
void set_default(Session *session,
204
enum_var_type type __attribute__((unused)));
205
bool update(Session *session, set_var *var);
132
static void plugin_prune_list(vector<string> &plugin_list,
133
const vector<string> &plugins_to_remove);
134
static bool plugin_load_list(module::Registry ®istry,
135
memory::Root *tmp_root,
136
const set<string> &plugin_list,
137
po::options_description &long_options,
138
bool builtin= false);
139
static int test_plugin_options(memory::Root *, module::Module *,
140
po::options_description &long_options);
141
static void unlock_variables(Session *session, drizzle_system_variables *vars);
142
static void cleanup_variables(drizzle_system_variables *vars);
210
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
212
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
214
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
215
struct st_plugin_int **);
216
static void unlock_variables(Session *session, struct system_variables *vars);
217
static void cleanup_variables(Session *session, struct system_variables *vars);
218
static void plugin_vars_free_values(sys_var *vars);
219
static void plugin_opt_set_limits(struct my_option *options,
220
const struct st_mysql_sys_var *opt);
221
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
222
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
223
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
225
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
226
static void reap_plugins(void);
229
/* declared in set_var.cc */
230
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
231
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
232
const char *name, int64_t val);
234
/****************************************************************************
235
Value type thunks, allows the C world to play in the C++ world
236
****************************************************************************/
238
static int item_value_type(struct st_mysql_value *value)
240
switch (((st_item_value_holder*)value)->item->result_type()) {
242
return DRIZZLE_VALUE_TYPE_INT;
244
return DRIZZLE_VALUE_TYPE_REAL;
246
return DRIZZLE_VALUE_TYPE_STRING;
250
static const char *item_val_str(struct st_mysql_value *value,
251
char *buffer, int *length)
253
String str(buffer, *length, system_charset_info), *res;
254
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
256
*length= res->length();
257
if (res->c_ptr_quick() == buffer)
261
Lets be nice and create a temporary string since the
264
return current_session->strmake(res->c_ptr_quick(), res->length());
268
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
270
Item *item= ((st_item_value_holder*)value)->item;
271
*buf= item->val_int();
278
static int item_val_real(struct st_mysql_value *value, double *buf)
280
Item *item= ((st_item_value_holder*)value)->item;
281
*buf= item->val_real();
145
288
/****************************************************************************
146
289
Plugin support code
147
290
****************************************************************************/
292
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
295
struct st_plugin_dl *tmp;
296
for (i= 0; i < plugin_dl_array.elements; i++)
298
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
299
if (tmp->ref_count &&
300
! my_strnncoll(files_charset_info,
301
(const unsigned char *)dl->str, dl->length,
302
(const unsigned char *)tmp->dl.str, tmp->dl.length))
308
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
311
struct st_plugin_dl *tmp;
312
for (i= 0; i < plugin_dl_array.elements; i++)
314
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
315
if (! tmp->ref_count)
317
memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
321
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
323
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
324
struct st_plugin_dl **)=
325
(struct st_plugin_dl *) memdup_root(&plugin_mem_root, (unsigned char*)plugin_dl,
326
sizeof(struct st_plugin_dl));
330
static inline void free_plugin_mem(struct st_plugin_dl *p)
338
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
341
uint32_t plugin_dir_len, dummy_errors;
342
struct st_plugin_dl *tmp, plugin_dl;
344
plugin_dir_len= strlen(opt_plugin_dir);
345
dlpath.reserve(FN_REFLEN);
347
Ensure that the dll doesn't have a path.
348
This is done to ensure that only approved libraries from the
349
plugin directory are used (to make this even remotely secure).
351
if (strchr(dl->str, FN_LIBCHAR) ||
352
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
353
system_charset_info, 1) ||
354
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
356
if (report & REPORT_TO_USER)
357
my_error(ER_UDF_NO_PATHS, MYF(0));
358
if (report & REPORT_TO_LOG)
359
sql_print_error("%s",ER(ER_UDF_NO_PATHS));
362
/* If this dll is already loaded just increase ref_count. */
363
if ((tmp= plugin_dl_find(dl)))
368
memset(&plugin_dl, 0, sizeof(plugin_dl));
369
/* Compile dll path */
370
dlpath.append(opt_plugin_dir);
372
dlpath.append(dl->str);
373
plugin_dl.ref_count= 1;
374
/* Open new dll handle */
375
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
377
const char *errmsg=dlerror();
378
uint32_t dlpathlen= dlpath.length();
379
if (!dlpath.compare(0, dlpathlen, errmsg))
380
{ // if errmsg starts from dlpath, trim this prefix.
382
if (*errmsg == ':') errmsg++;
383
if (*errmsg == ' ') errmsg++;
385
if (report & REPORT_TO_USER)
386
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
387
if (report & REPORT_TO_LOG)
388
sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
392
/* Find plugin declarations */
393
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
395
free_plugin_mem(&plugin_dl);
396
if (report & REPORT_TO_USER)
397
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
398
if (report & REPORT_TO_LOG)
399
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
403
plugin_dl.plugins= (struct st_mysql_plugin *)sym;
405
/* Duplicate and convert dll name */
406
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
407
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
409
free_plugin_mem(&plugin_dl);
410
if (report & REPORT_TO_USER)
411
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
412
if (report & REPORT_TO_LOG)
413
sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
416
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
417
files_charset_info, dl->str, dl->length, system_charset_info,
419
plugin_dl.dl.str[plugin_dl.dl.length]= 0;
420
/* Add this dll to array */
421
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
423
free_plugin_mem(&plugin_dl);
424
if (report & REPORT_TO_USER)
425
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
426
if (report & REPORT_TO_LOG)
427
sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
434
static void plugin_dl_del(const LEX_STRING *dl)
438
for (i= 0; i < plugin_dl_array.elements; i++)
440
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
441
struct st_plugin_dl **);
442
if (tmp->ref_count &&
443
! my_strnncoll(files_charset_info,
444
(const unsigned char *)dl->str, dl->length,
445
(const unsigned char *)tmp->dl.str, tmp->dl.length))
447
/* Do not remove this element, unless no other plugin uses this dll. */
448
if (! --tmp->ref_count)
450
free_plugin_mem(tmp);
451
memset(tmp, 0, sizeof(struct st_plugin_dl));
460
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
466
if (type == DRIZZLE_ANY_PLUGIN)
468
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
470
struct st_plugin_int *plugin= (st_plugin_int *)
471
hash_search(&plugin_hash[i], (const unsigned char *)name->str, name->length);
477
return((st_plugin_int *)
478
hash_search(&plugin_hash[type], (const unsigned char *)name->str, name->length));
483
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
485
SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
486
struct st_plugin_int *plugin;
487
if ((plugin= plugin_find_internal(name, type)))
489
rc= SHOW_OPTION_DISABLED;
490
if (plugin->state == PLUGIN_IS_READY)
497
bool plugin_is_ready(const LEX_STRING *name, int type)
500
if (plugin_status(name, type) == SHOW_OPTION_YES)
506
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
508
LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
509
return plugin_status(&plugin_name, plugin_type);
513
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
515
st_plugin_int *pi= plugin_ref_to_int(rc);
517
if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
521
For debugging, we do an additional malloc which allows the
522
memory manager and/or valgrind to track locked references and
523
double unlocks to aid resolving reference counting.problems.
525
if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
532
insert_dynamic(&lex->plugins, (unsigned char*)&plugin);
539
plugin_ref plugin_lock(Session *session, plugin_ref *ptr CALLER_INFO_PROTO)
541
LEX *lex= session ? session->lex : 0;
543
rc= my_intern_plugin_lock_ci(lex, *ptr);
548
plugin_ref plugin_lock_by_name(Session *session, const LEX_STRING *name, int type
551
LEX *lex= session ? session->lex : 0;
553
st_plugin_int *plugin;
554
if ((plugin= plugin_find_internal(name, type)))
555
rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
560
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
563
struct st_plugin_int *tmp;
564
for (i= 0; i < plugin_array.elements; i++)
566
tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
567
if (tmp->state == PLUGIN_IS_FREED)
569
memcpy(tmp, plugin, sizeof(struct st_plugin_int));
573
if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
575
tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
576
struct st_plugin_int **)=
577
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)plugin,
578
sizeof(struct st_plugin_int));
154
585
Requires that a write-lock is held on LOCK_system_variables_hash
156
static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
157
module::Library *library,
158
po::options_description &long_options)
587
static bool plugin_add(MEM_ROOT *tmp_root,
588
const LEX_STRING *name, const LEX_STRING *dl,
589
int *argc, char **argv, int report)
163
if (registry.find(library->getName()))
591
struct st_plugin_int tmp;
592
struct st_mysql_plugin *plugin;
593
if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
165
errmsg_printf(error::WARN, ER(ER_PLUGIN_EXISTS),
166
library->getName().c_str());
595
if (report & REPORT_TO_USER)
596
my_error(ER_UDF_EXISTS, MYF(0), name->str);
597
if (report & REPORT_TO_LOG)
598
sql_print_error(ER(ER_UDF_EXISTS), name->str);
170
module::Module *tmp= NULL;
601
/* Clear the whole struct to catch future extensions. */
602
memset(&tmp, 0, sizeof(tmp));
603
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
171
605
/* Find plugin by name */
172
const module::Manifest *manifest= library->getManifest();
174
if (registry.find(manifest->name))
176
errmsg_printf(error::ERROR,
177
_("Plugin '%s' contains the name '%s' in its manifest, which "
178
"has already been registered.\n"),
179
library->getName().c_str(),
184
tmp= new (std::nothrow) module::Module(manifest, library);
188
if (!test_plugin_options(tmp_root, tmp, long_options))
193
errmsg_printf(error::ERROR, ER(ER_CANT_FIND_DL_ENTRY),
194
library->getName().c_str());
199
static void reap_plugins(module::Registry ®istry)
201
std::map<std::string, module::Module *>::const_iterator modules=
202
registry.getModulesMap().begin();
204
while (modules != registry.getModulesMap().end())
206
module::Module *module= (*modules).second;
213
static bool plugin_initialize(module::Registry ®istry,
214
module::Module *module)
216
assert(module->isInited == false);
218
module::Context loading_context(registry, module);
219
if (module->getManifest().init)
221
if (module->getManifest().init(loading_context))
223
errmsg_printf(error::ERROR,
224
_("Plugin '%s' init function returned error.\n"),
225
module->getName().c_str());
229
module->isInited= true;
236
inline static void dashes_to_underscores(std::string &name_in,
237
char from= '-', char to= '_')
239
for (string::iterator p= name_in.begin();
250
inline static void underscores_to_dashes(std::string &name_in)
252
return dashes_to_underscores(name_in, '_', '-');
255
static void compose_plugin_options(vector<string> &target,
256
vector<string> options)
258
for (vector<string>::iterator it= options.begin();
262
tokenize(*it, target, ",", true);
264
for (vector<string>::iterator it= target.begin();
268
dashes_to_underscores(*it);
272
void compose_plugin_add(vector<string> options)
274
compose_plugin_options(opt_plugin_add, options);
277
void compose_plugin_remove(vector<string> options)
279
compose_plugin_options(opt_plugin_remove, options);
282
void notify_plugin_load(string in_plugin_load)
284
tokenize(in_plugin_load, opt_plugin_load, ",", true);
606
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
608
uint32_t name_len= strlen(plugin->name);
609
if (plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
610
! my_strnncoll(system_charset_info,
611
(const unsigned char *)name->str, name->length,
612
(const unsigned char *)plugin->name,
615
struct st_plugin_int *tmp_plugin_ptr;
618
tmp.name.str= (char *)plugin->name;
619
tmp.name.length= name_len;
621
tmp.state= PLUGIN_IS_UNINITIALIZED;
622
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
624
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
626
plugin_array_version++;
627
if (!my_hash_insert(&plugin_hash[plugin->type], (unsigned char*)tmp_plugin_ptr))
629
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
632
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
634
mysql_del_sys_var_chain(tmp.system_vars);
637
/* plugin was disabled */
642
if (report & REPORT_TO_USER)
643
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
644
if (report & REPORT_TO_LOG)
645
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
652
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
654
if (plugin->plugin->status_vars)
658
We have a problem right now where we can not prepend without
659
breaking backwards compatibility. We will fix this shortly so
660
that engines have "use names" and we wil use those for
661
CREATE TABLE, and use the plugin name then for adding automatic
665
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
668
remove_status_vars(array);
670
remove_status_vars(plugin->plugin->status_vars);
671
#endif /* FIX_LATER */
674
if (plugin_type_deinitialize[plugin->plugin->type])
676
if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
678
sql_print_error(_("Plugin '%s' of type %s failed deinitialization"),
679
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
682
else if (plugin->plugin->deinit)
683
plugin->plugin->deinit(plugin);
685
plugin->state= PLUGIN_IS_UNINITIALIZED;
688
We do the check here because NDB has a worker Session which doesn't
689
exit until NDB is shut down.
691
if (ref_check && plugin->ref_count)
692
sql_print_error(_("Plugin '%s' has ref_count=%d after deinitialization."),
693
plugin->name.str, plugin->ref_count);
697
static void plugin_del(struct st_plugin_int *plugin)
699
/* Free allocated strings before deleting the plugin. */
700
plugin_vars_free_values(plugin->system_vars);
701
hash_delete(&plugin_hash[plugin->plugin->type], (unsigned char*)plugin);
702
if (plugin->plugin_dl)
703
plugin_dl_del(&plugin->plugin_dl->dl);
704
plugin->state= PLUGIN_IS_FREED;
705
plugin_array_version++;
706
rw_wrlock(&LOCK_system_variables_hash);
707
mysql_del_sys_var_chain(plugin->system_vars);
708
rw_unlock(&LOCK_system_variables_hash);
709
free_root(&plugin->mem_root, MYF(0));
713
static void reap_plugins(void)
716
struct st_plugin_int *plugin, **reap, **list;
722
count= plugin_array.elements;
723
reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
726
for (idx= 0; idx < count; idx++)
728
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
729
if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
731
/* change the status flag to prevent reaping by another thread */
732
plugin->state= PLUGIN_IS_DYING;
738
while ((plugin= *(--list)))
739
plugin_deinitialize(plugin, true);
741
while ((plugin= *(--reap)))
747
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
755
pi= plugin_ref_to_int(plugin);
757
free((unsigned char*) plugin);
762
Remove one instance of this plugin from the use list.
763
We are searching backwards so that plugins locked last
764
could be unlocked faster - optimizing for LIFO semantics.
766
for (i= lex->plugins.elements - 1; i >= 0; i--)
767
if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
769
delete_dynamic_element(&lex->plugins, i);
775
assert(pi->ref_count);
778
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
785
void plugin_unlock(Session *session, plugin_ref plugin)
787
LEX *lex= session ? session->lex : 0;
790
intern_plugin_unlock(lex, plugin);
795
void plugin_unlock_list(Session *session, plugin_ref *list, uint32_t count)
797
LEX *lex= session ? session->lex : 0;
800
intern_plugin_unlock(lex, *list++);
805
static int plugin_initialize(struct st_plugin_int *plugin)
808
if (plugin_type_initialize[plugin->plugin->type])
810
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
812
sql_print_error(_("Plugin '%s' registration as a %s failed."),
813
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
817
else if (plugin->plugin->init)
819
if (plugin->plugin->init(plugin))
821
sql_print_error(_("Plugin '%s' init function returned error."),
827
plugin->state= PLUGIN_IS_READY;
829
if (plugin->plugin->status_vars)
833
We have a problem right now where we can not prepend without
834
breaking backwards compatibility. We will fix this shortly so
835
that engines have "use names" and we wil use those for
836
CREATE TABLE, and use the plugin name then for adding automatic
840
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
843
if (add_status_vars(array)) // add_status_vars makes a copy
846
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
847
#endif /* FIX_LATER */
851
set the plugin attribute of plugin's sys vars so they are pointing
854
if (plugin->system_vars)
856
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
862
var= var->next->cast_pluginvar();
872
extern "C" unsigned char *get_plugin_hash_key(const unsigned char *, size_t *, bool);
873
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
876
unsigned char *get_plugin_hash_key(const unsigned char *buff, size_t *length,
877
bool not_used __attribute__((unused)))
879
struct st_plugin_int *plugin= (st_plugin_int *)buff;
880
*length= (uint)plugin->name.length;
881
return((unsigned char *)plugin->name.str);
885
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length,
886
bool not_used __attribute__((unused)))
888
struct st_bookmark *var= (st_bookmark *)buff;
889
*length= var->name_len + 1;
890
return (unsigned char*) var->key;
288
895
The logic is that we first load and initialize all compiled in plugins.
292
899
Finally we initialize everything, aka the dynamic that have yet to initialize.
294
bool plugin_init(module::Registry ®istry,
295
po::options_description &long_options)
901
int plugin_init(int *argc, char **argv, int flags)
297
memory::Root tmp_root(4096);
904
struct st_mysql_plugin **builtins;
905
struct st_mysql_plugin *plugin;
906
struct st_plugin_int tmp, *plugin_ptr, **reap;
912
init_alloc_root(&plugin_mem_root, 4096, 4096);
913
init_alloc_root(&tmp_root, 4096, 4096);
915
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
916
get_bookmark_hash_key, NULL, HASH_UNIQUE))
920
if (my_init_dynamic_array(&plugin_dl_array,
921
sizeof(struct st_plugin_dl *),16,16) ||
922
my_init_dynamic_array(&plugin_array,
923
sizeof(struct st_plugin_int *),16,16))
926
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
928
if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
929
get_plugin_hash_key, NULL, HASH_UNIQUE))
304
PluginOptions builtin_load_list;
305
tokenize(builtin_load_plugins, builtin_load_list, ",", true);
307
PluginOptions builtin_list;
308
tokenize(builtin_plugins, builtin_list, ",", true);
310
bool load_failed= false;
312
if (opt_plugin_add.size() > 0)
314
for (PluginOptions::iterator iter= opt_plugin_add.begin();
315
iter != opt_plugin_add.end();
318
if (find(builtin_list.begin(),
319
builtin_list.end(), *iter) != builtin_list.end())
321
builtin_load_list.push_back(*iter);
325
opt_plugin_load.push_back(*iter);
330
if (opt_plugin_remove.size() > 0)
332
plugin_prune_list(opt_plugin_load, opt_plugin_remove);
333
plugin_prune_list(builtin_load_list, opt_plugin_remove);
338
936
First we register builtin plugins
340
const set<string> builtin_list_set(builtin_load_list.begin(),
341
builtin_load_list.end());
342
load_failed= plugin_load_list(registry, &tmp_root,
343
builtin_list_set, long_options, true);
938
for (builtins= mysqld_builtins; *builtins; builtins++)
346
tmp_root.free_root(MYF(0));
940
for (plugin= *builtins; plugin->name; plugin++)
942
memset(&tmp, 0, sizeof(tmp));
944
tmp.name.str= (char *)plugin->name;
945
tmp.name.length= strlen(plugin->name);
947
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
948
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
951
if (register_builtin(plugin, &tmp, &plugin_ptr))
954
if (plugin_initialize(plugin_ptr))
958
initialize the global default storage engine so that it may
959
not be null in any child thread.
961
if (my_strcasecmp(&my_charset_utf8_general_ci, plugin->name, "MyISAM") == 0)
963
assert(!global_system_variables.table_plugin);
964
global_system_variables.table_plugin=
965
my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
966
assert(plugin_ptr->ref_count == 1);
350
/* Uniquify the list */
351
const set<string> plugin_list_set(opt_plugin_load.begin(),
352
opt_plugin_load.end());
971
/* should now be set to MyISAM storage engine */
972
assert(global_system_variables.table_plugin);
354
974
/* Register all dynamic plugins */
355
load_failed= plugin_load_list(registry, &tmp_root,
356
plugin_list_set, long_options);
975
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
359
tmp_root.free_root(MYF(0));
978
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
363
tmp_root.free_root(MYF(0));
368
bool plugin_finalize(module::Registry ®istry)
981
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
371
985
Now we initialize all remaining plugins
373
module::Registry::ModuleList module_list= registry.getList();
374
module::Registry::ModuleList::iterator modules= module_list.begin();
376
while (modules != module_list.end())
988
reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
991
for (i= 0; i < plugin_array.elements; i++)
378
module::Module *module= *modules;
380
if (module->isInited == false)
993
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
994
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
382
if (plugin_initialize(registry, module))
996
if (plugin_initialize(plugin_ptr))
384
registry.remove(module);
998
plugin_ptr->state= PLUGIN_IS_DYING;
999
*(reap++)= plugin_ptr;
392
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
394
value.second->prime();
401
Window of opportunity for plugins to issue any queries with the database up and running but with no user's connected.
403
void plugin_startup_window(module::Registry ®istry, drizzled::Session &session)
405
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
407
value.second->startup(session);
412
public unary_function<string, bool>
414
const string to_match;
416
PrunePlugin& operator=(const PrunePlugin&);
418
explicit PrunePlugin(const string &match_in) :
422
result_type operator()(const string &match_against)
424
return match_against == to_match;
428
static void plugin_prune_list(vector<string> &plugin_list,
429
const vector<string> &plugins_to_remove)
431
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
432
iter != plugins_to_remove.end();
435
plugin_list.erase(remove_if(plugin_list.begin(),
1005
Check if any plugins have to be reaped
1007
while ((plugin_ptr= *(--reap)))
1009
plugin_deinitialize(plugin_ptr, true);
1010
plugin_del(plugin_ptr);
1016
free_root(&tmp_root, MYF(0));
1022
free_root(&tmp_root, MYF(0));
1027
static bool register_builtin(struct st_mysql_plugin *plugin,
1028
struct st_plugin_int *tmp,
1029
struct st_plugin_int **ptr)
1032
tmp->state= PLUGIN_IS_UNINITIALIZED;
1036
if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
1039
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1040
struct st_plugin_int **)=
1041
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
1042
sizeof(struct st_plugin_int));
1044
if (my_hash_insert(&plugin_hash[plugin->type],(unsigned char*) *ptr))
443
1052
called only by plugin_init()
445
static bool plugin_load_list(module::Registry ®istry,
446
memory::Root *tmp_root,
447
const set<string> &plugin_list,
448
po::options_description &long_options,
1054
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
451
module::Library *library= NULL;
453
for (set<string>::const_iterator iter= plugin_list.begin();
454
iter != plugin_list.end();
1057
char buffer[FN_REFLEN];
1058
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
1059
struct st_plugin_dl *plugin_dl;
1060
struct st_mysql_plugin *plugin;
457
const string plugin_name(*iter);
459
library= registry.addLibrary(plugin_name, builtin);
1064
if (p == buffer + sizeof(buffer) - 1)
462
errmsg_printf(error::ERROR,
463
_("Couldn't load plugin library named '%s'.\n"),
464
plugin_name.c_str());
1066
sql_print_error(_("plugin-load parameter too long"));
468
tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
469
if (plugin_add(registry, tmp_root, library, long_options))
471
registry.removeLibrary(plugin_name);
472
errmsg_printf(error::ERROR,
473
_("Couldn't load plugin named '%s'.\n"),
474
plugin_name.c_str());
1070
switch ((*(p++)= *(list++))) {
1072
list= NULL; /* terminate the loop */
1074
case ':': /* can't use this as delimiter as it may be drive letter */
1076
str->str[str->length]= '\0';
1077
if (str == &name) // load all plugins in named module
1081
p--; /* reset pointer */
1086
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1088
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
1090
name.str= (char *) plugin->name;
1091
name.length= strlen(name.str);
1093
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1094
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1097
plugin_dl_del(&dl); // reduce ref count
1102
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1103
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1106
name.length= dl.length= 0;
1107
dl.str= NULL; name.str= p= buffer;
1114
name.str[name.length]= '\0';
1126
sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
483
void module_shutdown(module::Registry ®istry)
1132
void plugin_shutdown(void)
1134
uint32_t i, count= plugin_array.elements, free_slots= 0;
1135
struct st_plugin_int **plugins, *plugin;
1136
struct st_plugin_dl **dl;
486
1138
if (initialized)
488
1140
reap_needed= true;
490
reap_plugins(registry);
491
unlock_variables(NULL, &global_system_variables);
492
unlock_variables(NULL, &max_system_variables);
494
cleanup_variables(&global_system_variables);
495
cleanup_variables(&max_system_variables);
1143
We want to shut down plugins in a reasonable order, this will
1144
become important when we have plugins which depend upon each other.
1145
Circular references cannot be reaped so they are forced afterwards.
1146
TODO: Have an additional step here to notify all active plugins that
1147
shutdown is requested to allow plugins to deinitialize in parallel.
1149
while (reap_needed && (count= plugin_array.elements))
1152
for (i= free_slots= 0; i < count; i++)
1154
plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1155
switch (plugin->state) {
1156
case PLUGIN_IS_READY:
1157
plugin->state= PLUGIN_IS_DELETED;
1160
case PLUGIN_IS_FREED:
1161
case PLUGIN_IS_UNINITIALIZED:
1169
release any plugin references held.
1171
unlock_variables(NULL, &global_system_variables);
1172
unlock_variables(NULL, &max_system_variables);
1176
if (count > free_slots)
1177
sql_print_warning(_("Forcing shutdown of %d plugins"),
1178
count - free_slots);
1180
plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1183
If we have any plugins which did not die cleanly, we force shutdown
1185
for (i= 0; i < count; i++)
1187
plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1188
/* change the state to ensure no reaping races */
1189
if (plugins[i]->state == PLUGIN_IS_DELETED)
1190
plugins[i]->state= PLUGIN_IS_DYING;
1194
We loop through all plugins and call deinit() if they have one.
1196
for (i= 0; i < count; i++)
1197
if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1199
sql_print_information(_("Plugin '%s' will be forced to shutdown"),
1200
plugins[i]->name.str);
1202
We are forcing deinit on plugins so we don't want to do a ref_count
1203
check until we have processed all the plugins.
1205
plugin_deinitialize(plugins[i], false);
1209
We defer checking ref_counts until after all plugins are deinitialized
1210
as some may have worker threads holding on to plugin references.
1212
for (i= 0; i < count; i++)
1214
if (plugins[i]->ref_count)
1215
sql_print_error(_("Plugin '%s' has ref_count=%d after shutdown."),
1216
plugins[i]->name.str, plugins[i]->ref_count);
1217
if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1218
plugin_del(plugins[i]);
1222
Now we can deallocate all memory.
1225
cleanup_variables(NULL, &global_system_variables);
1226
cleanup_variables(NULL, &max_system_variables);
500
1233
/* Dispose of the memory */
501
plugin_mem_root.free_root(MYF(0));
1235
for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1236
hash_free(&plugin_hash[i]);
1237
delete_dynamic(&plugin_array);
1239
count= plugin_dl_array.elements;
1240
dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1241
for (i= 0; i < count; i++)
1242
dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1243
for (i= 0; i < plugin_dl_array.elements; i++)
1244
free_plugin_mem(dl[i]);
1246
delete_dynamic(&plugin_dl_array);
1248
hash_free(&bookmark_hash);
1249
free_root(&plugin_mem_root, MYF(0));
503
1251
global_variables_dynamic_size= 0;
1257
bool plugin_foreach_with_mask(Session *session, plugin_foreach_func *func,
1258
int type, uint32_t state_mask, void *arg)
1260
uint32_t idx, total;
1261
struct st_plugin_int *plugin, **plugins;
1262
int version=plugin_array_version;
1267
state_mask= ~state_mask; // do it only once
1269
total= type == DRIZZLE_ANY_PLUGIN ? plugin_array.elements
1270
: plugin_hash[type].records;
1272
Do the alloca out here in case we do have a working alloca:
1273
leaving the nested stack frame invalidates alloca allocation.
1275
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1276
if (type == DRIZZLE_ANY_PLUGIN)
1278
for (idx= 0; idx < total; idx++)
1280
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1281
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1286
HASH *hash= plugin_hash + type;
1287
for (idx= 0; idx < total; idx++)
1289
plugin= (struct st_plugin_int *) hash_element(hash, idx);
1290
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1293
for (idx= 0; idx < total; idx++)
1295
if (unlikely(version != plugin_array_version))
1297
for (uint32_t i=idx; i < total; i++)
1298
if (plugins[i] && plugins[i]->state & state_mask)
1301
plugin= plugins[idx];
1302
/* It will stop iterating on first engine error when "func" returns true */
1303
if (plugin && func(session, plugin_int_to_ref(plugin), arg))
1315
/****************************************************************************
1316
Internal type declarations for variables support
1317
****************************************************************************/
1319
#undef DRIZZLE_SYSVAR_NAME
1320
#define DRIZZLE_SYSVAR_NAME(name) name
1321
#define PLUGIN_VAR_TYPEMASK 0x007f
1323
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1325
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1326
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1327
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1328
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1330
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1331
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1332
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1333
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1335
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1336
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1337
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1338
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1339
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1340
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1342
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
1343
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
1344
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
1345
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
1346
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
1347
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1349
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1352
/****************************************************************************
1353
default variable data check and update functions
1354
****************************************************************************/
1356
static int check_func_bool(Session *session __attribute__((unused)),
1357
struct st_mysql_sys_var *var,
1358
void *save, st_mysql_value *value)
1360
char buff[STRING_BUFFER_USUAL_SIZE];
1361
const char *strvalue= "NULL", *str;
1365
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1367
length= sizeof(buff);
1368
if (!(str= value->val_str(value, buff, &length)) ||
1369
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
1378
if (value->val_int(value, &tmp) < 0)
1388
*(int*)save= -result;
1391
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1396
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1397
void *save, st_mysql_value *value)
1401
struct my_option options;
1402
value->val_int(value, &tmp);
1403
plugin_opt_set_limits(&options, var);
1405
if (var->flags & PLUGIN_VAR_UNSIGNED)
1406
*(uint32_t *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
1409
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1411
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1412
var->name, (int64_t) tmp);
1416
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1417
void *save, st_mysql_value *value)
1421
struct my_option options;
1422
value->val_int(value, &tmp);
1423
plugin_opt_set_limits(&options, var);
1425
if (var->flags & PLUGIN_VAR_UNSIGNED)
1426
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
1429
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1431
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1432
var->name, (int64_t) tmp);
1436
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1437
void *save, st_mysql_value *value)
1441
struct my_option options;
1442
value->val_int(value, &tmp);
1443
plugin_opt_set_limits(&options, var);
1445
if (var->flags & PLUGIN_VAR_UNSIGNED)
1446
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
1449
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1451
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1452
var->name, (int64_t) tmp);
1455
static int check_func_str(Session *session,
1456
struct st_mysql_sys_var *var __attribute__((unused)),
1457
void *save, st_mysql_value *value)
1459
char buff[STRING_BUFFER_USUAL_SIZE];
1463
length= sizeof(buff);
1464
if ((str= value->val_str(value, buff, &length)))
1465
str= session->strmake(str, length);
1466
*(const char**)save= str;
1471
static int check_func_enum(Session *session __attribute__((unused)),
1472
struct st_mysql_sys_var *var,
1473
void *save, st_mysql_value *value)
1475
char buff[STRING_BUFFER_USUAL_SIZE];
1476
const char *strvalue= "NULL", *str;
1482
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1483
typelib= ((sessionvar_enum_t*) var)->typelib;
1485
typelib= ((sysvar_enum_t*) var)->typelib;
1487
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1489
length= sizeof(buff);
1490
if (!(str= value->val_str(value, buff, &length)))
1492
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1500
if (value->val_int(value, &tmp))
1502
if (tmp >= typelib->count)
1510
*(long*)save= result;
1513
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1518
static int check_func_set(Session *session __attribute__((unused)),
1519
struct st_mysql_sys_var *var,
1520
void *save, st_mysql_value *value)
1522
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1523
const char *strvalue= "NULL", *str;
1530
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1531
typelib= ((sessionvar_set_t*) var)->typelib;
1533
typelib= ((sysvar_set_t*)var)->typelib;
1535
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1537
length= sizeof(buff);
1538
if (!(str= value->val_str(value, buff, &length)))
1540
result= find_set(typelib, str, length, NULL,
1541
&error, &error_len, ¬_used);
1544
strmake(buff, error, cmin(sizeof(buff), (unsigned long)error_len));
1551
if (value->val_int(value, (int64_t *)&result))
1553
if (unlikely((result >= (1UL << typelib->count)) &&
1554
(typelib->count < sizeof(long)*8)))
1556
llstr(result, buff);
1561
*(uint64_t*)save= result;
1564
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1569
static void update_func_bool(Session *session __attribute__((unused)),
1570
struct st_mysql_sys_var *var __attribute__((unused)),
1571
void *tgt, const void *save)
1573
*(bool *) tgt= *(int *) save ? 1 : 0;
1577
static void update_func_int(Session *session __attribute__((unused)),
1578
struct st_mysql_sys_var *var __attribute__((unused)),
1579
void *tgt, const void *save)
1581
*(int *)tgt= *(int *) save;
1585
static void update_func_long(Session *session __attribute__((unused)),
1586
struct st_mysql_sys_var *var __attribute__((unused)),
1587
void *tgt, const void *save)
1589
*(long *)tgt= *(long *) save;
1593
static void update_func_int64_t(Session *session __attribute__((unused)),
1594
struct st_mysql_sys_var *var __attribute__((unused)),
1595
void *tgt, const void *save)
1597
*(int64_t *)tgt= *(uint64_t *) save;
1601
static void update_func_str(Session *session __attribute__((unused)), struct st_mysql_sys_var *var,
1602
void *tgt, const void *save)
1604
char *old= *(char **) tgt;
1605
*(char **)tgt= *(char **) save;
1606
if (var->flags & PLUGIN_VAR_MEMALLOC)
1608
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
509
1616
****************************************************************************/
1619
sys_var *find_sys_var(Session *session, const char *str, uint32_t length)
1622
sys_var_pluginvar *pi= NULL;
1625
rw_rdlock(&LOCK_system_variables_hash);
1626
if ((var= intern_find_sys_var(str, length, false)) &&
1627
(pi= var->cast_pluginvar()))
1629
rw_unlock(&LOCK_system_variables_hash);
1630
LEX *lex= session ? session->lex : 0;
1631
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1632
var= NULL; /* failed to lock it, it must be uninstalling */
1634
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
1636
/* initialization not completed */
1638
intern_plugin_unlock(lex, plugin);
1642
rw_unlock(&LOCK_system_variables_hash);
1645
If the variable exists but the plugin it is associated with is not ready
1646
then the intern_plugin_lock did not raise an error, so we do it here.
1649
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1655
called by register_var, construct_options and test_plugin_options.
1656
Returns the 'bookmark' for the named variable.
1657
LOCK_system_variables_hash should be at least read locked
1659
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1661
st_bookmark *result= NULL;
1662
uint32_t namelen, length, pluginlen= 0;
1665
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1668
namelen= strlen(name);
1670
pluginlen= strlen(plugin) + 1;
1671
length= namelen + pluginlen + 2;
1672
varname= (char*) my_alloca(length);
1676
strxmov(varname + 1, plugin, "_", name, NULL);
1677
for (p= varname + 1; *p; p++)
1682
memcpy(varname + 1, name, namelen + 1);
1684
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1686
result= (st_bookmark*) hash_search(&bookmark_hash,
1687
(const unsigned char*) varname, length - 1);
1695
returns a bookmark for session-local variables, creating if neccessary.
1696
returns null for non session-local variables.
1697
Requires that a write lock is obtained on LOCK_system_variables_hash
1699
static st_bookmark *register_var(const char *plugin, const char *name,
1702
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1703
st_bookmark *result;
1706
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1709
switch (flags & PLUGIN_VAR_TYPEMASK) {
1710
case PLUGIN_VAR_BOOL:
1713
case PLUGIN_VAR_INT:
1716
case PLUGIN_VAR_LONG:
1717
case PLUGIN_VAR_ENUM:
1720
case PLUGIN_VAR_LONGLONG:
1721
case PLUGIN_VAR_SET:
1722
size= sizeof(uint64_t);
1724
case PLUGIN_VAR_STR:
1725
size= sizeof(char*);
1732
varname= ((char*) my_alloca(length));
1733
strxmov(varname + 1, plugin, "_", name, NULL);
1734
for (p= varname + 1; *p; p++)
1738
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1740
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1741
sizeof(struct st_bookmark) + length-1);
1742
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1743
memcpy(result->key, varname, length);
1744
result->name_len= length - 2;
1747
assert(size && !(size & (size-1))); /* must be power of 2 */
1749
offset= global_system_variables.dynamic_variables_size;
1750
offset= (offset + size - 1) & ~(size - 1);
1751
result->offset= (int) offset;
1753
new_size= (offset + size + 63) & ~63;
1755
if (new_size > global_variables_dynamic_size)
1757
global_system_variables.dynamic_variables_ptr= (char*)
1758
my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1759
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1760
max_system_variables.dynamic_variables_ptr= (char*)
1761
my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1762
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1764
Clear the new variable value space. This is required for string
1765
variables. If their value is non-NULL, it must point to a valid
1768
memset(global_system_variables.dynamic_variables_ptr +
1769
global_variables_dynamic_size, 0,
1770
new_size - global_variables_dynamic_size);
1771
memset(max_system_variables.dynamic_variables_ptr +
1772
global_variables_dynamic_size, 0,
1773
new_size - global_variables_dynamic_size);
1774
global_variables_dynamic_size= new_size;
1777
global_system_variables.dynamic_variables_head= offset;
1778
max_system_variables.dynamic_variables_head= offset;
1779
global_system_variables.dynamic_variables_size= offset + size;
1780
max_system_variables.dynamic_variables_size= offset + size;
1781
global_system_variables.dynamic_variables_version++;
1782
max_system_variables.dynamic_variables_version++;
1784
result->version= global_system_variables.dynamic_variables_version;
1786
/* this should succeed because we have already checked if a dup exists */
1787
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1789
fprintf(stderr, "failed to add placeholder to hash");
1799
returns a pointer to the memory which holds the session-local variable or
1800
a pointer to the global variable if session==null.
1801
If required, will sync with global variables if the requested variable
1802
has not yet been allocated in the current thread.
1804
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1806
assert(offset >= 0);
1807
assert((uint)offset <= global_system_variables.dynamic_variables_head);
1810
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1813
dynamic_variables_head points to the largest valid offset
1815
if (!session->variables.dynamic_variables_ptr ||
1816
(uint)offset > session->variables.dynamic_variables_head)
1820
rw_rdlock(&LOCK_system_variables_hash);
1822
session->variables.dynamic_variables_ptr= (char*)
1823
my_realloc(session->variables.dynamic_variables_ptr,
1824
global_variables_dynamic_size,
1825
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1828
pthread_mutex_lock(&LOCK_global_system_variables);
1830
safe_mutex_assert_owner(&LOCK_global_system_variables);
1832
memcpy(session->variables.dynamic_variables_ptr +
1833
session->variables.dynamic_variables_size,
1834
global_system_variables.dynamic_variables_ptr +
1835
session->variables.dynamic_variables_size,
1836
global_system_variables.dynamic_variables_size -
1837
session->variables.dynamic_variables_size);
1840
now we need to iterate through any newly copied 'defaults'
1841
and if it is a string type with MEMALLOC flag, we need to strdup
1843
for (idx= 0; idx < bookmark_hash.records; idx++)
1845
sys_var_pluginvar *pi;
1847
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1849
if (v->version <= session->variables.dynamic_variables_version ||
1850
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1851
!(pi= var->cast_pluginvar()) ||
1852
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1855
/* Here we do anything special that may be required of the data types */
1857
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1858
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1860
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1861
*(int*)(pi->plugin_var + 1));
1862
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1863
*(int*)(pi->plugin_var + 1))))
1864
*pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
1869
pthread_mutex_unlock(&LOCK_global_system_variables);
1871
session->variables.dynamic_variables_version=
1872
global_system_variables.dynamic_variables_version;
1873
session->variables.dynamic_variables_head=
1874
global_system_variables.dynamic_variables_head;
1875
session->variables.dynamic_variables_size=
1876
global_system_variables.dynamic_variables_size;
1878
rw_unlock(&LOCK_system_variables_hash);
1880
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1883
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1885
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1888
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1890
return (int *)intern_sys_var_ptr(a_session, offset, true);
1893
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1895
return (long *)intern_sys_var_ptr(a_session, offset, true);
1898
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1900
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1903
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1905
return (char **)intern_sys_var_ptr(a_session, offset, true);
1908
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1910
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1913
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1915
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
513
1919
void plugin_sessionvar_init(Session *session)
515
session->variables.storage_engine= NULL;
516
cleanup_variables(&session->variables);
1921
plugin_ref old_table_plugin= session->variables.table_plugin;
1923
session->variables.table_plugin= NULL;
1924
cleanup_variables(session, &session->variables);
518
1926
session->variables= global_system_variables;
519
session->variables.storage_engine= NULL;
1927
session->variables.table_plugin= NULL;
521
1929
/* we are going to allocate these lazily */
522
1930
session->variables.dynamic_variables_version= 0;
523
1931
session->variables.dynamic_variables_size= 0;
524
1932
session->variables.dynamic_variables_ptr= 0;
526
session->variables.storage_engine= global_system_variables.storage_engine;
1934
session->variables.table_plugin=
1935
my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1936
intern_plugin_unlock(NULL, old_table_plugin);
531
1942
Unlocks all system variables which hold a reference
533
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
1944
static void unlock_variables(Session *session __attribute__((unused)),
1945
struct system_variables *vars)
535
vars->storage_engine= NULL;
1947
intern_plugin_unlock(NULL, vars->table_plugin);
1948
vars->table_plugin= NULL;
556
1997
void plugin_sessionvar_cleanup(Session *session)
558
2002
unlock_variables(session, &session->variables);
559
cleanup_variables(&session->variables);
2003
cleanup_variables(session, &session->variables);
2005
if ((idx= session->lex->plugins.elements))
2007
list= ((plugin_ref*) session->lex->plugins.buffer) + idx - 1;
2008
while ((unsigned char*) list >= session->lex->plugins.buffer)
2009
intern_plugin_unlock(NULL, *list--);
2012
reset_dynamic(&session->lex->plugins);
2019
@brief Free values of thread variables of a plugin.
2021
This must be called before a plugin is deleted. Otherwise its
2022
variables are no longer accessible and the value space is lost. Note
2023
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
2026
@param[in] vars Chain of system variables of a plugin
2029
static void plugin_vars_free_values(sys_var *vars)
2032
for (sys_var *var= vars; var; var= var->next)
2034
sys_var_pluginvar *piv= var->cast_pluginvar();
2036
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
2037
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
2039
/* Free the string from global_system_variables. */
2040
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2049
bool sys_var_pluginvar::check_update_type(Item_result type)
2053
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2054
case PLUGIN_VAR_INT:
2055
case PLUGIN_VAR_LONG:
2056
case PLUGIN_VAR_LONGLONG:
2057
return type != INT_RESULT;
2058
case PLUGIN_VAR_STR:
2059
return type != STRING_RESULT;
2066
SHOW_TYPE sys_var_pluginvar::show_type()
2068
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2069
case PLUGIN_VAR_BOOL:
2070
return SHOW_MY_BOOL;
2071
case PLUGIN_VAR_INT:
2073
case PLUGIN_VAR_LONG:
2075
case PLUGIN_VAR_LONGLONG:
2076
return SHOW_LONGLONG;
2077
case PLUGIN_VAR_STR:
2078
return SHOW_CHAR_PTR;
2079
case PLUGIN_VAR_ENUM:
2080
case PLUGIN_VAR_SET:
2089
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2091
assert(session || (type == OPT_GLOBAL));
2092
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2094
if (type == OPT_GLOBAL)
2097
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2099
return *(unsigned char**) (plugin_var+1);
2103
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2105
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2106
case PLUGIN_VAR_ENUM:
2107
return ((sysvar_enum_t *)plugin_var)->typelib;
2108
case PLUGIN_VAR_SET:
2109
return ((sysvar_set_t *)plugin_var)->typelib;
2110
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2111
return ((sessionvar_enum_t *)plugin_var)->typelib;
2112
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2113
return ((sessionvar_set_t *)plugin_var)->typelib;
2121
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type,
2122
LEX_STRING *base __attribute__((unused)))
2124
unsigned char* result;
2126
result= real_value_ptr(session, type);
2128
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2129
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2130
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2132
char buffer[STRING_BUFFER_USUAL_SIZE];
2133
String str(buffer, sizeof(buffer), system_charset_info);
2134
TYPELIB *typelib= plugin_var_typelib();
2135
uint64_t mask= 1, value= *(uint64_t*) result;
2139
for (i= 0; i < typelib->count; i++, mask<<=1)
2141
if (!(value & mask))
2143
str.append(typelib->type_names[i], typelib->type_lengths[i]);
2147
result= (unsigned char*) "";
2149
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2155
bool sys_var_pluginvar::check(Session *session, set_var *var)
2157
st_item_value_holder value;
2158
assert(is_readonly() || plugin_var->check);
2160
value.value_type= item_value_type;
2161
value.val_str= item_val_str;
2162
value.val_int= item_val_int;
2163
value.val_real= item_val_real;
2164
value.item= var->value;
2166
return is_readonly() ||
2167
plugin_var->check(session, plugin_var, &var->save_result, &value);
2171
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2176
assert(is_readonly() || plugin_var->update);
2181
pthread_mutex_lock(&LOCK_global_system_variables);
2182
tgt= real_value_ptr(session, type);
2183
src= ((void **) (plugin_var + 1) + 1);
2185
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2187
if (type != OPT_GLOBAL)
2188
src= real_value_ptr(session, OPT_GLOBAL);
2190
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2191
case PLUGIN_VAR_INT:
2192
src= &((sessionvar_uint_t*) plugin_var)->def_val;
2194
case PLUGIN_VAR_LONG:
2195
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2197
case PLUGIN_VAR_LONGLONG:
2198
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2200
case PLUGIN_VAR_ENUM:
2201
src= &((sessionvar_enum_t*) plugin_var)->def_val;
2203
case PLUGIN_VAR_SET:
2204
src= &((sessionvar_set_t*) plugin_var)->def_val;
2206
case PLUGIN_VAR_BOOL:
2207
src= &((sessionvar_bool_t*) plugin_var)->def_val;
2209
case PLUGIN_VAR_STR:
2210
src= &((sessionvar_str_t*) plugin_var)->def_val;
2217
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
2218
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
2219
session == current_session);
2221
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2223
plugin_var->update(session, plugin_var, tgt, src);
2224
pthread_mutex_unlock(&LOCK_global_system_variables);
2228
pthread_mutex_unlock(&LOCK_global_system_variables);
2229
plugin_var->update(session, plugin_var, tgt, src);
2234
bool sys_var_pluginvar::update(Session *session, set_var *var)
2238
assert(is_readonly() || plugin_var->update);
2240
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
2241
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
2242
session == current_session);
2247
pthread_mutex_lock(&LOCK_global_system_variables);
2248
tgt= real_value_ptr(session, var->type);
2250
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2252
/* variable we are updating has global scope, so we unlock after updating */
2253
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2254
pthread_mutex_unlock(&LOCK_global_system_variables);
2258
pthread_mutex_unlock(&LOCK_global_system_variables);
2259
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2265
#define OPTION_SET_LIMITS(type, options, opt) \
2266
options->var_type= type; \
2267
options->def_value= (opt)->def_val; \
2268
options->min_value= (opt)->min_val; \
2269
options->max_value= (opt)->max_val; \
2270
options->block_size= (long) (opt)->blk_sz
2273
static void plugin_opt_set_limits(struct my_option *options,
2274
const struct st_mysql_sys_var *opt)
2276
options->sub_size= 0;
2278
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2279
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2280
/* global system variables */
2281
case PLUGIN_VAR_INT:
2282
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2284
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
2285
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
2287
case PLUGIN_VAR_LONG:
2288
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2290
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2291
OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
2293
case PLUGIN_VAR_LONGLONG:
2294
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2296
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
2297
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
2299
case PLUGIN_VAR_ENUM:
2300
options->var_type= GET_ENUM;
2301
options->typelib= ((sysvar_enum_t*) opt)->typelib;
2302
options->def_value= ((sysvar_enum_t*) opt)->def_val;
2303
options->min_value= options->block_size= 0;
2304
options->max_value= options->typelib->count - 1;
2306
case PLUGIN_VAR_SET:
2307
options->var_type= GET_SET;
2308
options->typelib= ((sysvar_set_t*) opt)->typelib;
2309
options->def_value= ((sysvar_set_t*) opt)->def_val;
2310
options->min_value= options->block_size= 0;
2311
options->max_value= (1UL << options->typelib->count) - 1;
2313
case PLUGIN_VAR_BOOL:
2314
options->var_type= GET_BOOL;
2315
options->def_value= ((sysvar_bool_t*) opt)->def_val;
2317
case PLUGIN_VAR_STR:
2318
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2319
GET_STR_ALLOC : GET_STR);
2320
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2322
/* threadlocal variables */
2323
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
2324
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
2326
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2327
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
2329
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
2330
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
2332
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2333
OPTION_SET_LIMITS(GET_ULONG, options, (sessionvar_ulong_t*) opt);
2335
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
2336
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
2338
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2339
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
2341
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2342
options->var_type= GET_ENUM;
2343
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
2344
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2345
options->min_value= options->block_size= 0;
2346
options->max_value= options->typelib->count - 1;
2348
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2349
options->var_type= GET_SET;
2350
options->typelib= ((sessionvar_set_t*) opt)->typelib;
2351
options->def_value= ((sessionvar_set_t*) opt)->def_val;
2352
options->min_value= options->block_size= 0;
2353
options->max_value= (1UL << options->typelib->count) - 1;
2355
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2356
options->var_type= GET_BOOL;
2357
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2359
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2360
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2361
GET_STR_ALLOC : GET_STR);
2362
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2367
options->arg_type= REQUIRED_ARG;
2368
if (opt->flags & PLUGIN_VAR_NOCMDARG)
2369
options->arg_type= NO_ARG;
2370
if (opt->flags & PLUGIN_VAR_OPCMDARG)
2371
options->arg_type= OPT_ARG;
2374
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2377
bool get_one_plugin_option(int optid __attribute__((unused)),
2378
const struct my_option *opt __attribute__((unused)),
2379
char *argument __attribute__((unused)))
2385
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
2386
my_option *options, bool can_disable)
2388
const char *plugin_name= tmp->plugin->name;
2389
uint32_t namelen= strlen(plugin_name), optnamelen;
2390
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2391
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2393
int index= 0, offset= 0;
2394
st_mysql_sys_var *opt, **plugin_option;
2397
/* support --skip-plugin-foo syntax */
2398
memcpy(name, plugin_name, namelen + 1);
2399
my_casedn_str(&my_charset_utf8_general_ci, name);
2400
strxmov(name + namelen + 1, "plugin-", name, NULL);
2401
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2403
for (p= name + namelen*2 + 8; p > name; p--)
2409
strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2410
"Disable with --skip-", name," (will save memory).", NULL);
2412
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2413
20 + namelen + 20 + 1 == namelen * 4 + 67.
2416
options[0].comment= name + namelen*2 + 10;
2419
options[1].name= (options[0].name= name) + namelen + 1;
2420
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2421
options[0].var_type= options[1].var_type= GET_BOOL;
2422
options[0].arg_type= options[1].arg_type= NO_ARG;
2423
options[0].def_value= options[1].def_value= true;
2424
options[0].value= options[0].u_max_value=
2425
options[1].value= options[1].u_max_value= (char**) (name - 1);
2429
Two passes as the 2nd pass will take pointer addresses for use
2430
by my_getopt and register_var() in the first pass uses realloc
2433
for (plugin_option= tmp->plugin->system_vars;
2434
plugin_option && *plugin_option; plugin_option++, index++)
2436
opt= *plugin_option;
2437
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2439
if (!(register_var(name, opt->name, opt->flags)))
2441
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2442
case PLUGIN_VAR_BOOL:
2443
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2445
case PLUGIN_VAR_INT:
2446
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2448
case PLUGIN_VAR_LONG:
2449
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2451
case PLUGIN_VAR_LONGLONG:
2452
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2454
case PLUGIN_VAR_STR:
2455
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2457
case PLUGIN_VAR_ENUM:
2458
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2460
case PLUGIN_VAR_SET:
2461
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2464
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2465
opt->flags, plugin_name);
2470
for (plugin_option= tmp->plugin->system_vars;
2471
plugin_option && *plugin_option; plugin_option++, index++)
2473
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
2474
case PLUGIN_VAR_BOOL:
2476
opt->check= check_func_bool;
2478
opt->update= update_func_bool;
2480
case PLUGIN_VAR_INT:
2482
opt->check= check_func_int;
2484
opt->update= update_func_int;
2486
case PLUGIN_VAR_LONG:
2488
opt->check= check_func_long;
2490
opt->update= update_func_long;
2492
case PLUGIN_VAR_LONGLONG:
2494
opt->check= check_func_int64_t;
2496
opt->update= update_func_int64_t;
2498
case PLUGIN_VAR_STR:
2500
opt->check= check_func_str;
2503
opt->update= update_func_str;
2504
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2506
opt->flags|= PLUGIN_VAR_READONLY;
2507
sql_print_warning(_("Server variable %s of plugin %s was forced "
2508
"to be read-only: string variable without "
2509
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2510
opt->name, plugin_name);
2514
case PLUGIN_VAR_ENUM:
2516
opt->check= check_func_enum;
2518
opt->update= update_func_long;
2520
case PLUGIN_VAR_SET:
2522
opt->check= check_func_set;
2524
opt->update= update_func_int64_t;
2527
sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
2528
opt->flags, plugin_name);
2532
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2533
== PLUGIN_VAR_NOCMDOPT)
2538
sql_print_error(_("Missing variable name in plugin '%s'."),
2543
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2545
optnamelen= strlen(opt->name);
2546
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2547
strxmov(optname, name, "-", opt->name, NULL);
2548
optnamelen= namelen + optnamelen + 1;
2552
/* this should not fail because register_var should create entry */
2553
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2555
sql_print_error(_("Thread local variable '%s' not allocated "
2556
"in plugin '%s'."), opt->name, plugin_name);
2560
*(int*)(opt + 1)= offset= v->offset;
2562
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2565
optname= (char*) memdup_root(mem_root, v->key + 1,
2566
(optnamelen= v->name_len) + 1);
2569
/* convert '_' to '-' */
2570
for (p= optname; *p; p++)
2574
options->name= optname;
2575
options->comment= opt->comment;
2576
options->app_type= opt;
2577
options->id= (options-1)->id + 1;
2579
plugin_opt_set_limits(options, opt);
2581
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2582
options->value= options->u_max_value= (char**)
2583
(global_system_variables.dynamic_variables_ptr + offset);
2585
options->value= options->u_max_value= *(char***) (opt + 1);
2587
options[1]= options[0];
2588
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2589
options[1].comment= 0; // hidden
2590
strxmov(p, "plugin-", optname, NULL);
2599
static my_option *construct_help_options(MEM_ROOT *mem_root,
2600
struct st_plugin_int *p)
2602
st_mysql_sys_var **opt;
2605
uint32_t count= EXTRA_OPTIONS;
2607
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2609
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2612
memset(opts, 0, sizeof(my_option) * count);
2614
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2616
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2622
if (construct_options(mem_root, p, opts, can_disable))