12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
27
#include <boost/program_options.hpp>
29
#include <drizzled/option.h>
30
#include <drizzled/internal/m_string.h>
32
#include <drizzled/plugin.h>
33
#include <drizzled/module/load_list.h>
34
#include <drizzled/module/library.h>
35
#include <drizzled/module/registry.h>
36
#include <drizzled/module/option_context.h>
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <drizzled/server_includes.h>
17
#include <mysys/my_getopt.h>
18
#include <mysys/hash.h>
20
#include <drizzled/authentication.h>
21
#include <drizzled/logging.h>
22
#include <drizzled/errmsg.h>
23
#include <drizzled/configvar.h>
24
#include <drizzled/qcache.h>
25
#include <drizzled/parser.h>
37
26
#include <drizzled/sql_parse.h>
27
#include <drizzled/scheduling.h>
28
#include <drizzled/replicator.h>
38
29
#include <drizzled/show.h>
39
#include <drizzled/cursor.h>
30
#include <drizzled/handler.h>
40
31
#include <drizzled/set_var.h>
41
32
#include <drizzled/session.h>
42
33
#include <drizzled/item/null.h>
34
#include <drizzled/plugin_registry.h>
43
40
#include <drizzled/error.h>
44
41
#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;
43
#define REPORT_TO_LOG 1
44
#define REPORT_TO_USER 2
46
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
47
#define plugin_int_to_ref(A) &(A)
59
49
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;
51
extern struct st_mysql_plugin *mysqld_builtins[];
53
char *opt_plugin_load= NULL;
54
char *opt_plugin_dir_ptr;
55
char opt_plugin_dir[FN_REFLEN];
57
When you ad a new plugin type, add both a string and make sure that the
58
init and deinit array are correctly updated.
60
const LEX_STRING plugin_type_names[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
62
{ C_STRING_WITH_LEN("DAEMON") },
63
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
64
{ C_STRING_WITH_LEN("INFORMATION SCHEMA") },
65
{ C_STRING_WITH_LEN("UDF") },
66
{ C_STRING_WITH_LEN("UDA") },
67
{ C_STRING_WITH_LEN("AUDIT") },
68
{ C_STRING_WITH_LEN("LOGGER") },
69
{ C_STRING_WITH_LEN("ERRMSG") },
70
{ C_STRING_WITH_LEN("AUTH") },
71
{ C_STRING_WITH_LEN("CONFIGVAR") },
72
{ C_STRING_WITH_LEN("QCACHE") },
73
{ C_STRING_WITH_LEN("PARSER") },
74
{ C_STRING_WITH_LEN("SCHEDULING") },
75
{ C_STRING_WITH_LEN("REPLICATOR") }
78
extern int initialize_schema_table(st_plugin_int *plugin);
79
extern int finalize_schema_table(st_plugin_int *plugin);
81
extern int initialize_udf(st_plugin_int *plugin);
82
extern int finalize_udf(st_plugin_int *plugin);
85
The number of elements in both plugin_type_initialize and
86
plugin_type_deinitialize should equal to the number of plugins
89
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
92
ha_initialize_handlerton, /* Storage Engine */
93
initialize_schema_table, /* Information Schema */
94
initialize_udf, /* UDF */
97
logging_initializer, /* Logger */
98
errmsg_initializer, /* Error Messages */
99
authentication_initializer, /* Auth */
100
configvar_initializer,
103
scheduling_initializer,
104
replicator_initializer
107
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
110
ha_finalize_handlerton, /* Storage Engine */
111
finalize_schema_table, /* Information Schema */
112
finalize_udf, /* UDF */
115
logging_finalizer, /* Logger */
116
errmsg_finalizer, /* Logger */
117
authentication_finalizer, /* Auth */
121
scheduling_finalizer,
125
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
85
127
/* Note that 'int version' must be the first field of every plugin
86
128
sub-structure (plugin->info).
89
static bool initialized= false;
131
static bool initialized= 0;
133
static DYNAMIC_ARRAY plugin_dl_array;
134
static DYNAMIC_ARRAY plugin_array;
92
136
static bool reap_needed= false;
137
static int plugin_array_version=0;
95
140
write-lock on LOCK_system_variables_hash is required before modifying
96
141
the following variables/structures
98
static memory::Root plugin_mem_root(4096);
143
static MEM_ROOT plugin_mem_root;
99
144
static uint32_t global_variables_dynamic_size= 0;
145
static HASH bookmark_hash;
103
149
hidden part of opaque value passed to variable check functions.
104
150
Used to provide a object-like structure to non C++ consumers.
106
struct st_item_value_holder : public drizzle_value
152
struct st_item_value_holder : public st_mysql_value
159
stored in bookmark_hash, this structure is never removed from the
160
hash and is used to mark a single offset for a session local variable
161
even if plugins have been uninstalled and reinstalled, repeatedly.
162
This structure is allocated from plugin_mem_root.
164
The key format is as follows:
165
1 byte - variable type code
166
name_len bytes - variable name
122
173
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
179
skeleton of a plugin variable - portion of structure common to all.
181
struct st_mysql_sys_var
183
DRIZZLE_PLUGIN_VAR_HEADER;
188
sys_var class for access to all plugin variables visible to the user
190
class sys_var_pluginvar: public sys_var
193
struct st_plugin_int *plugin;
194
struct st_mysql_sys_var *plugin_var;
196
static void *operator new(size_t size, MEM_ROOT *mem_root)
197
{ return (void*) alloc_root(mem_root, (uint32_t) size); }
198
static void operator delete(void *, size_t)
199
{ TRASH(ptr_arg, size); }
201
sys_var_pluginvar(const char *name_arg,
202
struct st_mysql_sys_var *plugin_var_arg)
203
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
204
sys_var_pluginvar *cast_pluginvar() { return this; }
205
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
206
bool check_type(enum_var_type type)
207
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
208
bool check_update_type(Item_result type);
209
SHOW_TYPE show_type();
210
unsigned char* real_value_ptr(Session *session, enum_var_type type);
211
TYPELIB* plugin_var_typelib(void);
212
unsigned char* value_ptr(Session *session, enum_var_type type,
213
const LEX_STRING *base);
214
bool check(Session *session, set_var *var);
215
bool check_default(enum_var_type)
216
{ return is_readonly(); }
217
void set_default(Session *session, enum_var_type);
218
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);
223
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
225
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
227
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
228
struct st_plugin_int **);
229
static void unlock_variables(Session *session, struct system_variables *vars);
230
static void cleanup_variables(Session *session, struct system_variables *vars);
231
static void plugin_vars_free_values(sys_var *vars);
232
static void plugin_opt_set_limits(struct my_option *options,
233
const struct st_mysql_sys_var *opt);
234
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
235
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
236
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
237
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
238
static void reap_plugins(void);
241
/* declared in set_var.cc */
242
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
243
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
244
const char *name, int64_t val);
246
/****************************************************************************
247
Value type thunks, allows the C world to play in the C++ world
248
****************************************************************************/
250
static int item_value_type(struct st_mysql_value *value)
252
switch (((st_item_value_holder*)value)->item->result_type()) {
254
return DRIZZLE_VALUE_TYPE_INT;
256
return DRIZZLE_VALUE_TYPE_REAL;
258
return DRIZZLE_VALUE_TYPE_STRING;
262
static const char *item_val_str(struct st_mysql_value *value,
263
char *buffer, int *length)
265
String str(buffer, *length, system_charset_info), *res;
266
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
268
*length= res->length();
269
if (res->c_ptr_quick() == buffer)
273
Lets be nice and create a temporary string since the
276
return current_session->strmake(res->c_ptr_quick(), res->length());
280
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
282
Item *item= ((st_item_value_holder*)value)->item;
283
*buf= item->val_int();
290
static int item_val_real(struct st_mysql_value *value, double *buf)
292
Item *item= ((st_item_value_holder*)value)->item;
293
*buf= item->val_real();
145
300
/****************************************************************************
146
301
Plugin support code
147
302
****************************************************************************/
304
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
307
struct st_plugin_dl *tmp;
309
for (i= 0; i < plugin_dl_array.elements; i++)
311
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
312
if (tmp->ref_count &&
313
! my_strnncoll(files_charset_info,
314
(const unsigned char *)dl->str, dl->length,
315
(const unsigned char *)tmp->dl.str, tmp->dl.length))
321
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
324
struct st_plugin_dl *tmp;
326
for (i= 0; i < plugin_dl_array.elements; i++)
328
tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
329
if (! tmp->ref_count)
331
memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
335
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
337
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
338
struct st_plugin_dl **)=
339
(struct st_plugin_dl *) memdup_root(&plugin_mem_root, (unsigned char*)plugin_dl,
340
sizeof(struct st_plugin_dl));
344
static inline void free_plugin_mem(struct st_plugin_dl *p)
352
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
355
uint32_t plugin_dir_len, dummy_errors;
356
struct st_plugin_dl *tmp, plugin_dl;
358
plugin_dir_len= strlen(opt_plugin_dir);
359
dlpath.reserve(FN_REFLEN);
361
Ensure that the dll doesn't have a path.
362
This is done to ensure that only approved libraries from the
363
plugin directory are used (to make this even remotely secure).
365
if (strchr(dl->str, FN_LIBCHAR) ||
366
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
367
system_charset_info, 1) ||
368
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
370
if (report & REPORT_TO_USER)
371
my_error(ER_UDF_NO_PATHS, MYF(0));
372
if (report & REPORT_TO_LOG)
373
errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
376
/* If this dll is already loaded just increase ref_count. */
377
if ((tmp= plugin_dl_find(dl)))
382
memset(&plugin_dl, 0, sizeof(plugin_dl));
383
/* Compile dll path */
384
dlpath.append(opt_plugin_dir);
386
dlpath.append(dl->str);
387
plugin_dl.ref_count= 1;
388
/* Open new dll handle */
389
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
391
const char *errmsg=dlerror();
392
uint32_t dlpathlen= dlpath.length();
393
if (!dlpath.compare(0, dlpathlen, errmsg))
394
{ // if errmsg starts from dlpath, trim this prefix.
396
if (*errmsg == ':') errmsg++;
397
if (*errmsg == ' ') errmsg++;
399
if (report & REPORT_TO_USER)
400
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
401
if (report & REPORT_TO_LOG)
402
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
406
/* Find plugin declarations */
407
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
409
free_plugin_mem(&plugin_dl);
410
if (report & REPORT_TO_USER)
411
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
412
if (report & REPORT_TO_LOG)
413
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
417
plugin_dl.plugins= (struct st_mysql_plugin *)sym;
419
/* Duplicate and convert dll name */
420
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
421
if (! (plugin_dl.dl.str= (char*) malloc(plugin_dl.dl.length)))
423
free_plugin_mem(&plugin_dl);
424
if (report & REPORT_TO_USER)
425
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
426
if (report & REPORT_TO_LOG)
427
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
430
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
431
files_charset_info, dl->str, dl->length, system_charset_info,
433
plugin_dl.dl.str[plugin_dl.dl.length]= 0;
434
/* Add this dll to array */
435
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
437
free_plugin_mem(&plugin_dl);
438
if (report & REPORT_TO_USER)
439
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
440
if (report & REPORT_TO_LOG)
441
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
448
static void plugin_dl_del(const LEX_STRING *dl)
452
for (i= 0; i < plugin_dl_array.elements; i++)
454
struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
455
struct st_plugin_dl **);
456
if (tmp->ref_count &&
457
! my_strnncoll(files_charset_info,
458
(const unsigned char *)dl->str, dl->length,
459
(const unsigned char *)tmp->dl.str, tmp->dl.length))
461
/* Do not remove this element, unless no other plugin uses this dll. */
462
if (! --tmp->ref_count)
464
free_plugin_mem(tmp);
465
memset(tmp, 0, sizeof(struct st_plugin_dl));
475
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
477
Plugin_registry registry= Plugin_registry::get_plugin_registry();
479
SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
480
struct st_plugin_int *plugin;
485
if ((plugin= registry.find(name, type)))
487
rc= SHOW_OPTION_DISABLED;
488
if (plugin->state == PLUGIN_IS_READY)
495
bool plugin_is_ready(const LEX_STRING *name, int type)
498
if (plugin_status(name, type) == SHOW_OPTION_YES)
504
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
506
LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
507
return plugin_status(&plugin_name, plugin_type);
511
static plugin_ref intern_plugin_lock(LEX *, plugin_ref rc)
513
st_plugin_int *pi= plugin_ref_to_int(rc);
515
if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
519
For debugging, we do an additional malloc which allows the
520
memory manager and/or valgrind to track locked references and
521
double unlocks to aid resolving reference counting.problems.
523
if (!(plugin= (plugin_ref) malloc(sizeof(pi))))
535
plugin_ref plugin_lock(Session *session, plugin_ref *ptr)
537
LEX *lex= session ? session->lex : 0;
539
rc= my_intern_plugin_lock_ci(lex, *ptr);
544
plugin_ref plugin_lock_by_name(Session *session, const LEX_STRING *name, int type)
546
Plugin_registry registry= Plugin_registry::get_plugin_registry();
548
LEX *lex= session ? session->lex : 0;
550
st_plugin_int *plugin;
554
if ((plugin= registry.find(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)
591
Plugin_registry registry= Plugin_registry::get_plugin_registry();
593
struct st_plugin_int tmp;
594
struct st_mysql_plugin *plugin;
160
595
if (! initialized)
163
if (registry.find(library->getName()))
598
if (registry.find(name, DRIZZLE_ANY_PLUGIN))
165
errmsg_printf(error::WARN, ER(ER_PLUGIN_EXISTS),
166
library->getName().c_str());
600
if (report & REPORT_TO_USER)
601
my_error(ER_UDF_EXISTS, MYF(0), name->str);
602
if (report & REPORT_TO_LOG)
603
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
170
module::Module *tmp= NULL;
606
/* Clear the whole struct to catch future extensions. */
607
memset(&tmp, 0, sizeof(tmp));
608
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
171
610
/* 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);
611
for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
613
uint32_t name_len= strlen(plugin->name);
614
if (plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
615
! my_strnncoll(system_charset_info,
616
(const unsigned char *)name->str, name->length,
617
(const unsigned char *)plugin->name,
620
struct st_plugin_int *tmp_plugin_ptr;
623
tmp.name.str= (char *)plugin->name;
624
tmp.name.length= name_len;
626
tmp.state= PLUGIN_IS_UNINITIALIZED;
627
if (!test_plugin_options(tmp_root, &tmp, argc, argv))
629
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
631
plugin_array_version++;
632
registry.add(plugin, tmp_plugin_ptr);
633
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
636
mysql_del_sys_var_chain(tmp.system_vars);
639
/* plugin was disabled */
644
if (report & REPORT_TO_USER)
645
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
646
if (report & REPORT_TO_LOG)
647
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
654
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
656
if (plugin->plugin->status_vars)
660
We have a problem right now where we can not prepend without
661
breaking backwards compatibility. We will fix this shortly so
662
that engines have "use names" and we wil use those for
663
CREATE TABLE, and use the plugin name then for adding automatic
667
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
670
remove_status_vars(array);
672
remove_status_vars(plugin->plugin->status_vars);
673
#endif /* FIX_LATER */
676
if (plugin_type_deinitialize[plugin->plugin->type])
678
if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
680
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' of type %s failed deinitialization"),
681
plugin->name.str, plugin_type_names[plugin->plugin->type].str);
684
else if (plugin->plugin->deinit)
685
plugin->plugin->deinit(plugin);
687
plugin->state= PLUGIN_IS_UNINITIALIZED;
690
We do the check here because NDB has a worker Session which doesn't
691
exit until NDB is shut down.
693
if (ref_check && plugin->ref_count)
694
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has ref_count=%d after deinitialization."),
695
plugin->name.str, plugin->ref_count);
699
static void plugin_del(struct st_plugin_int *plugin)
701
/* Free allocated strings before deleting the plugin. */
702
plugin_vars_free_values(plugin->system_vars);
703
if (plugin->plugin_dl)
704
plugin_dl_del(&plugin->plugin_dl->dl);
705
plugin->state= PLUGIN_IS_FREED;
706
plugin_array_version++;
707
pthread_rwlock_wrlock(&LOCK_system_variables_hash);
708
mysql_del_sys_var_chain(plugin->system_vars);
709
pthread_rwlock_unlock(&LOCK_system_variables_hash);
710
free_root(&plugin->mem_root, MYF(0));
714
static void reap_plugins(void)
718
struct st_plugin_int *plugin;
721
count= plugin_array.elements;
723
for (idx= 0; idx < count; idx++)
725
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
726
plugin->state= PLUGIN_IS_DYING;
727
plugin_deinitialize(plugin, true);
732
static void intern_plugin_unlock(LEX *, plugin_ref plugin)
739
pi= plugin_ref_to_int(plugin);
741
free((void *) plugin);
743
//assert(pi->ref_count);
744
if (pi->ref_count > 0)
747
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
754
void plugin_unlock(Session *session, plugin_ref plugin)
756
LEX *lex= session ? session->lex : 0;
759
intern_plugin_unlock(lex, plugin);
764
void plugin_unlock_list(Session *session, plugin_ref *list, uint32_t count)
766
LEX *lex= session ? session->lex : 0;
769
intern_plugin_unlock(lex, *list++);
774
static int plugin_initialize(struct st_plugin_int *plugin)
776
plugin->state= PLUGIN_IS_UNINITIALIZED;
778
if (plugin_type_initialize[plugin->plugin->type])
780
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
782
errmsg_printf(ERRMSG_LVL_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
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' init function returned error."),
795
plugin->state= PLUGIN_IS_READY;
798
if (plugin->plugin->status_vars)
802
We have a problem right now where we can not prepend without
803
breaking backwards compatibility. We will fix this shortly so
804
that engines have "use names" and we wil use those for
805
CREATE TABLE, and use the plugin name then for adding automatic
809
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
812
if (add_status_vars(array)) // add_status_vars makes a copy
815
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
816
#endif /* FIX_LATER */
820
set the plugin attribute of plugin's sys vars so they are pointing
823
if (plugin->system_vars)
825
sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
831
var= var->next->cast_pluginvar();
841
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
844
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
846
struct st_bookmark *var= (st_bookmark *)buff;
847
*length= var->name_len + 1;
848
return (unsigned char*) var->key;
288
853
The logic is that we first load and initialize all compiled in plugins.
292
857
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)
859
int plugin_init(int *argc, char **argv, int flags)
297
memory::Root tmp_root(4096);
862
struct st_mysql_plugin **builtins;
863
struct st_mysql_plugin *plugin;
864
struct st_plugin_int tmp, *plugin_ptr;
870
init_alloc_root(&plugin_mem_root, 4096, 4096);
871
init_alloc_root(&tmp_root, 4096, 4096);
873
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
874
get_bookmark_hash_key, NULL, HASH_UNIQUE))
878
if (my_init_dynamic_array(&plugin_dl_array,
879
sizeof(struct st_plugin_dl *),16,16) ||
880
my_init_dynamic_array(&plugin_array,
881
sizeof(struct st_plugin_int *),16,16))
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
887
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);
889
for (builtins= mysqld_builtins; *builtins; builtins++)
346
tmp_root.free_root(MYF(0));
891
for (plugin= *builtins; plugin->name; plugin++)
893
memset(&tmp, 0, sizeof(tmp));
895
tmp.name.str= (char *)plugin->name;
896
tmp.name.length= strlen(plugin->name);
898
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
899
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
902
if (register_builtin(plugin, &tmp, &plugin_ptr))
905
if (plugin_initialize(plugin_ptr))
909
initialize the global default storage engine so that it may
910
not be null in any child thread.
912
if (my_strcasecmp(&my_charset_utf8_general_ci, plugin->name, "MyISAM") == 0)
914
assert(!global_system_variables.table_plugin);
915
global_system_variables.table_plugin=
916
my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
917
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());
922
/* should now be set to MyISAM storage engine */
923
assert(global_system_variables.table_plugin);
354
925
/* Register all dynamic plugins */
355
load_failed= plugin_load_list(registry, &tmp_root,
356
plugin_list_set, long_options);
926
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
359
tmp_root.free_root(MYF(0));
929
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
363
tmp_root.free_root(MYF(0));
368
bool plugin_finalize(module::Registry ®istry)
932
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
371
936
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())
938
for (idx= 0; idx < plugin_array.elements; idx++)
378
module::Module *module= *modules;
380
if (module->isInited == false)
940
plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
941
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
382
if (plugin_initialize(registry, module))
943
if (plugin_initialize(plugin_ptr))
384
registry.remove(module);
945
plugin_ptr->state= PLUGIN_IS_DYING;
946
plugin_deinitialize(plugin_ptr, true);
947
plugin_del(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(),
954
free_root(&tmp_root, MYF(0));
960
free_root(&tmp_root, MYF(0));
965
static bool register_builtin(struct st_mysql_plugin *plugin,
966
struct st_plugin_int *tmp,
967
struct st_plugin_int **ptr)
970
Plugin_registry registry= Plugin_registry::get_plugin_registry();
972
tmp->state= PLUGIN_IS_UNINITIALIZED;
976
if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
979
*ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
980
struct st_plugin_int **)=
981
(struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
982
sizeof(struct st_plugin_int));
984
registry.add(plugin, *ptr);
443
991
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,
993
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();
996
char buffer[FN_REFLEN];
997
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
998
struct st_plugin_dl *plugin_dl;
999
struct st_mysql_plugin *plugin;
457
const string plugin_name(*iter);
459
library= registry.addLibrary(plugin_name, builtin);
1003
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());
1005
errmsg_printf(ERRMSG_LVL_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());
1009
switch ((*(p++)= *(list++))) {
1011
list= NULL; /* terminate the loop */
1013
case ':': /* can't use this as delimiter as it may be drive letter */
1015
str->str[str->length]= '\0';
1016
if (str == &name) // load all plugins in named module
1020
p--; /* reset pointer */
1025
if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1027
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
1029
name.str= (char *) plugin->name;
1030
name.length= strlen(name.str);
1032
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1033
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1036
plugin_dl_del(&dl); // reduce ref count
1041
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1042
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1045
name.length= dl.length= 0;
1046
dl.str= NULL; name.str= p= buffer;
1053
name.str[name.length]= '\0';
1065
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
483
void module_shutdown(module::Registry ®istry)
1071
void plugin_shutdown(void)
1073
uint32_t idx, free_slots= 0;
1074
size_t count= plugin_array.elements;
1075
struct st_plugin_int *plugin;
1076
vector<st_plugin_int *> plugins;
1077
vector<st_plugin_dl *> dl;
486
1079
if (initialized)
488
1081
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);
1084
We want to shut down plugins in a reasonable order, this will
1085
become important when we have plugins which depend upon each other.
1086
Circular references cannot be reaped so they are forced afterwards.
1087
TODO: Have an additional step here to notify all active plugins that
1088
shutdown is requested to allow plugins to deinitialize in parallel.
1090
while (reap_needed && (count= plugin_array.elements))
1093
for (idx= free_slots= 0; idx < count; idx++)
1095
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1096
switch (plugin->state) {
1097
case PLUGIN_IS_READY:
1098
plugin->state= PLUGIN_IS_DELETED;
1101
case PLUGIN_IS_FREED:
1102
case PLUGIN_IS_UNINITIALIZED:
1110
release any plugin references held.
1112
unlock_variables(NULL, &global_system_variables);
1113
unlock_variables(NULL, &max_system_variables);
1117
if (count > free_slots)
1118
errmsg_printf(ERRMSG_LVL_WARN, _("Forcing shutdown of %"PRIu64" plugins"),
1119
(uint64_t)count - free_slots);
1121
plugins.reserve(count);
1124
If we have any plugins which did not die cleanly, we force shutdown
1126
for (idx= 0; idx < count; idx++)
1128
plugins.push_back(*dynamic_element(&plugin_array, idx,
1129
struct st_plugin_int **));
1130
/* change the state to ensure no reaping races */
1131
if (plugins[idx]->state == PLUGIN_IS_DELETED)
1132
plugins[idx]->state= PLUGIN_IS_DYING;
1136
We loop through all plugins and call deinit() if they have one.
1138
for (idx= 0; idx < count; idx++)
1139
if (!(plugins[idx]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1141
errmsg_printf(ERRMSG_LVL_INFO, _("Plugin '%s' will be forced to shutdown"),
1142
plugins[idx]->name.str);
1144
We are forcing deinit on plugins so we don't want to do a ref_count
1145
check until we have processed all the plugins.
1147
plugin_deinitialize(plugins[idx], false);
1151
We defer checking ref_counts until after all plugins are deinitialized
1152
as some may have worker threads holding on to plugin references.
1154
for (idx= 0; idx < count; idx++)
1156
if (plugins[idx]->ref_count)
1157
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has ref_count=%d after shutdown."),
1158
plugins[idx]->name.str, plugins[idx]->ref_count);
1159
if (plugins[idx]->state & PLUGIN_IS_UNINITIALIZED)
1160
plugin_del(plugins[idx]);
1164
Now we can deallocate all memory.
1167
cleanup_variables(NULL, &global_system_variables);
1168
cleanup_variables(NULL, &max_system_variables);
500
1174
/* Dispose of the memory */
501
plugin_mem_root.free_root(MYF(0));
1176
delete_dynamic(&plugin_array);
1178
count= plugin_dl_array.elements;
1180
for (idx= 0; idx < count; idx++)
1181
dl.push_back(*dynamic_element(&plugin_dl_array, idx,
1182
struct st_plugin_dl **));
1183
for (idx= 0; idx < count; idx++)
1184
free_plugin_mem(dl[idx]);
1185
delete_dynamic(&plugin_dl_array);
1187
hash_free(&bookmark_hash);
1188
free_root(&plugin_mem_root, MYF(0));
503
1190
global_variables_dynamic_size= 0;
1196
bool plugin_foreach_with_mask(Session *session, plugin_foreach_func *func,
1197
int type, uint32_t state_mask, void *arg)
1200
struct st_plugin_int *plugin;
1201
vector<st_plugin_int *> plugins;
1202
int version=plugin_array_version;
1207
state_mask= ~state_mask; // do it only once
1210
if (type == DRIZZLE_ANY_PLUGIN)
1212
plugins.reserve(plugin_array.elements);
1213
for (idx= 0; idx < plugin_array.elements; idx++)
1215
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1216
plugins.push_back(!(plugin->state & state_mask) ? plugin : NULL);
1221
Plugin_registry registry= Plugin_registry::get_plugin_registry();
1222
registry.get_mask_list(type, plugins, state_mask);
1225
vector<st_plugin_int *>::iterator plugin_iter;
1226
for (plugin_iter= plugins.begin();
1227
plugin_iter != plugins.end();
1230
if (unlikely(version != plugin_array_version))
1232
vector<st_plugin_int *>::iterator reset_iter;
1233
for (reset_iter= plugin_iter;
1234
reset_iter != plugins.end();
1236
if (*reset_iter && (*reset_iter)->state & state_mask)
1239
plugin= *plugin_iter;
1240
/* It will stop iterating on first engine error when "func" returns true */
1241
if (plugin && func(session, plugin_int_to_ref(plugin), arg))
1251
/****************************************************************************
1252
Internal type declarations for variables support
1253
****************************************************************************/
1255
#undef DRIZZLE_SYSVAR_NAME
1256
#define DRIZZLE_SYSVAR_NAME(name) name
1257
#define PLUGIN_VAR_TYPEMASK 0x007f
1259
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1261
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1262
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1263
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1264
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1266
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1267
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1268
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1269
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1271
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1272
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1273
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1274
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1275
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1276
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1278
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
1279
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
1280
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
1281
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
1282
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
1283
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1285
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1288
/****************************************************************************
1289
default variable data check and update functions
1290
****************************************************************************/
1292
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
1293
void *save, st_mysql_value *value)
1295
char buff[STRING_BUFFER_USUAL_SIZE];
1296
const char *strvalue= "NULL", *str;
1300
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1302
length= sizeof(buff);
1303
if (!(str= value->val_str(value, buff, &length)) ||
1304
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
1313
if (value->val_int(value, &tmp) < 0)
1323
*(int*)save= -result;
1326
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1331
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1332
void *save, st_mysql_value *value)
1336
struct my_option options;
1337
value->val_int(value, &tmp);
1338
plugin_opt_set_limits(&options, var);
1340
if (var->flags & PLUGIN_VAR_UNSIGNED)
1341
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
1344
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1346
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1347
var->name, (int64_t) tmp);
1351
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1352
void *save, st_mysql_value *value)
1356
struct my_option options;
1357
value->val_int(value, &tmp);
1358
plugin_opt_set_limits(&options, var);
1360
if (var->flags & PLUGIN_VAR_UNSIGNED)
1361
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
1364
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1366
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1367
var->name, (int64_t) tmp);
1371
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1372
void *save, st_mysql_value *value)
1376
struct my_option options;
1377
value->val_int(value, &tmp);
1378
plugin_opt_set_limits(&options, var);
1380
if (var->flags & PLUGIN_VAR_UNSIGNED)
1381
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
1384
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1386
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1387
var->name, (int64_t) tmp);
1390
static int check_func_str(Session *session, struct st_mysql_sys_var *,
1391
void *save, st_mysql_value *value)
1393
char buff[STRING_BUFFER_USUAL_SIZE];
1397
length= sizeof(buff);
1398
if ((str= value->val_str(value, buff, &length)))
1399
str= session->strmake(str, length);
1400
*(const char**)save= str;
1405
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
1406
void *save, st_mysql_value *value)
1408
char buff[STRING_BUFFER_USUAL_SIZE];
1409
const char *strvalue= "NULL", *str;
1415
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1416
typelib= ((sessionvar_enum_t*) var)->typelib;
1418
typelib= ((sysvar_enum_t*) var)->typelib;
1420
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1422
length= sizeof(buff);
1423
if (!(str= value->val_str(value, buff, &length)))
1425
if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1433
if (value->val_int(value, &tmp))
1435
if (tmp >= typelib->count)
1443
*(long*)save= result;
1446
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1451
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1452
void *save, st_mysql_value *value)
1454
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1455
const char *strvalue= "NULL", *str;
1462
if (var->flags & PLUGIN_VAR_SessionLOCAL)
1463
typelib= ((sessionvar_set_t*) var)->typelib;
1465
typelib= ((sysvar_set_t*)var)->typelib;
1467
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
1469
length= sizeof(buff);
1470
if (!(str= value->val_str(value, buff, &length)))
1472
result= find_set(typelib, str, length, NULL,
1473
&error, &error_len, ¬_used);
1476
length= cmin(sizeof(buff), (unsigned long)error_len);
1477
strncpy(buff, error, length);
1485
if (value->val_int(value, (int64_t *)&result))
1487
if (unlikely((result >= (1UL << typelib->count)) &&
1488
(typelib->count < sizeof(long)*8)))
1490
llstr(result, buff);
1495
*(uint64_t*)save= result;
1498
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1503
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1504
void *tgt, const void *save)
1506
*(bool *) tgt= *(int *) save ? 1 : 0;
1510
static void update_func_int(Session *, struct st_mysql_sys_var *,
1511
void *tgt, const void *save)
1513
*(int *)tgt= *(int *) save;
1517
static void update_func_long(Session *, struct st_mysql_sys_var *,
1518
void *tgt, const void *save)
1520
*(long *)tgt= *(long *) save;
1524
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1525
void *tgt, const void *save)
1527
*(int64_t *)tgt= *(uint64_t *) save;
1531
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1532
void *tgt, const void *save)
1534
char *old= *(char **) tgt;
1535
*(char **)tgt= *(char **) save;
1536
if (var->flags & PLUGIN_VAR_MEMALLOC)
1538
*(char **)tgt= strdup(*(char **) save);
1541
* There isn't a _really_ good thing to do here until this whole set_var
1542
* mess gets redesigned
1545
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
509
1553
****************************************************************************/
1556
sys_var *find_sys_var(Session *session, const char *str, uint32_t length)
1559
sys_var_pluginvar *pi= NULL;
1562
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1563
if ((var= intern_find_sys_var(str, length, false)) &&
1564
(pi= var->cast_pluginvar()))
1566
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1567
LEX *lex= session ? session->lex : 0;
1568
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1569
var= NULL; /* failed to lock it, it must be uninstalling */
1571
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
1573
/* initialization not completed */
1575
intern_plugin_unlock(lex, plugin);
1579
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1582
If the variable exists but the plugin it is associated with is not ready
1583
then the intern_plugin_lock did not raise an error, so we do it here.
1586
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
1592
called by register_var, construct_options and test_plugin_options.
1593
Returns the 'bookmark' for the named variable.
1594
LOCK_system_variables_hash should be at least read locked
1596
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1598
st_bookmark *result= NULL;
1599
uint32_t namelen, length, pluginlen= 0;
1602
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1605
namelen= strlen(name);
1607
pluginlen= strlen(plugin) + 1;
1608
length= namelen + pluginlen + 2;
1609
varname= (char*) malloc(length);
1613
sprintf(varname+1,"%s_%s",plugin,name);
1614
for (p= varname + 1; *p; p++)
1619
memcpy(varname + 1, name, namelen + 1);
1621
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1623
result= (st_bookmark*) hash_search(&bookmark_hash,
1624
(const unsigned char*) varname, length - 1);
1632
returns a bookmark for session-local variables, creating if neccessary.
1633
returns null for non session-local variables.
1634
Requires that a write lock is obtained on LOCK_system_variables_hash
1636
static st_bookmark *register_var(const char *plugin, const char *name,
1639
uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1640
st_bookmark *result;
1643
if (!(flags & PLUGIN_VAR_SessionLOCAL))
1646
switch (flags & PLUGIN_VAR_TYPEMASK) {
1647
case PLUGIN_VAR_BOOL:
1650
case PLUGIN_VAR_INT:
1653
case PLUGIN_VAR_LONG:
1654
case PLUGIN_VAR_ENUM:
1657
case PLUGIN_VAR_LONGLONG:
1658
case PLUGIN_VAR_SET:
1659
size= sizeof(uint64_t);
1661
case PLUGIN_VAR_STR:
1662
size= sizeof(char*);
1669
varname= ((char*) malloc(length));
1670
sprintf(varname+1, "%s_%s", plugin, name);
1671
for (p= varname + 1; *p; p++)
1675
if (!(result= find_bookmark(NULL, varname + 1, flags)))
1677
result= (st_bookmark*) alloc_root(&plugin_mem_root,
1678
sizeof(struct st_bookmark) + length-1);
1679
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1680
memcpy(result->key, varname, length);
1681
result->name_len= length - 2;
1684
assert(size && !(size & (size-1))); /* must be power of 2 */
1686
offset= global_system_variables.dynamic_variables_size;
1687
offset= (offset + size - 1) & ~(size - 1);
1688
result->offset= (int) offset;
1690
new_size= (offset + size + 63) & ~63;
1692
if (new_size > global_variables_dynamic_size)
1696
(char *)realloc(global_system_variables.dynamic_variables_ptr,
1699
global_system_variables.dynamic_variables_ptr= tmpptr;
1702
(char *)realloc(max_system_variables.dynamic_variables_ptr,
1705
max_system_variables.dynamic_variables_ptr= tmpptr;
1708
Clear the new variable value space. This is required for string
1709
variables. If their value is non-NULL, it must point to a valid
1712
memset(global_system_variables.dynamic_variables_ptr +
1713
global_variables_dynamic_size, 0,
1714
new_size - global_variables_dynamic_size);
1715
memset(max_system_variables.dynamic_variables_ptr +
1716
global_variables_dynamic_size, 0,
1717
new_size - global_variables_dynamic_size);
1718
global_variables_dynamic_size= new_size;
1721
global_system_variables.dynamic_variables_head= offset;
1722
max_system_variables.dynamic_variables_head= offset;
1723
global_system_variables.dynamic_variables_size= offset + size;
1724
max_system_variables.dynamic_variables_size= offset + size;
1725
global_system_variables.dynamic_variables_version++;
1726
max_system_variables.dynamic_variables_version++;
1728
result->version= global_system_variables.dynamic_variables_version;
1730
/* this should succeed because we have already checked if a dup exists */
1731
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1733
fprintf(stderr, "failed to add placeholder to hash");
1743
returns a pointer to the memory which holds the session-local variable or
1744
a pointer to the global variable if session==null.
1745
If required, will sync with global variables if the requested variable
1746
has not yet been allocated in the current thread.
1748
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1750
assert(offset >= 0);
1751
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1754
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1757
dynamic_variables_head points to the largest valid offset
1759
if (!session->variables.dynamic_variables_ptr ||
1760
(uint32_t)offset > session->variables.dynamic_variables_head)
1764
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1767
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
1768
global_variables_dynamic_size)))
1770
session->variables.dynamic_variables_ptr= tmpptr;
1773
pthread_mutex_lock(&LOCK_global_system_variables);
1775
safe_mutex_assert_owner(&LOCK_global_system_variables);
1777
memcpy(session->variables.dynamic_variables_ptr +
1778
session->variables.dynamic_variables_size,
1779
global_system_variables.dynamic_variables_ptr +
1780
session->variables.dynamic_variables_size,
1781
global_system_variables.dynamic_variables_size -
1782
session->variables.dynamic_variables_size);
1785
now we need to iterate through any newly copied 'defaults'
1786
and if it is a string type with MEMALLOC flag, we need to strdup
1788
for (idx= 0; idx < bookmark_hash.records; idx++)
1790
sys_var_pluginvar *pi;
1792
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1794
if (v->version <= session->variables.dynamic_variables_version ||
1795
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1796
!(pi= var->cast_pluginvar()) ||
1797
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1800
/* Here we do anything special that may be required of the data types */
1802
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1803
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1805
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1806
*(int*)(pi->plugin_var + 1));
1807
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1808
*(int*)(pi->plugin_var + 1))))
1816
pthread_mutex_unlock(&LOCK_global_system_variables);
1818
session->variables.dynamic_variables_version=
1819
global_system_variables.dynamic_variables_version;
1820
session->variables.dynamic_variables_head=
1821
global_system_variables.dynamic_variables_head;
1822
session->variables.dynamic_variables_size=
1823
global_system_variables.dynamic_variables_size;
1825
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1827
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1830
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1832
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1835
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1837
return (int *)intern_sys_var_ptr(a_session, offset, true);
1840
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1842
return (long *)intern_sys_var_ptr(a_session, offset, true);
1845
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1847
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1850
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1852
return (char **)intern_sys_var_ptr(a_session, offset, true);
1855
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
1857
return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
1860
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
1862
return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
513
1866
void plugin_sessionvar_init(Session *session)
515
session->variables.storage_engine= NULL;
516
cleanup_variables(&session->variables);
1868
plugin_ref old_table_plugin= session->variables.table_plugin;
1870
session->variables.table_plugin= NULL;
1871
cleanup_variables(session, &session->variables);
518
1873
session->variables= global_system_variables;
519
session->variables.storage_engine= NULL;
1874
session->variables.table_plugin= NULL;
521
1876
/* we are going to allocate these lazily */
522
1877
session->variables.dynamic_variables_version= 0;
523
1878
session->variables.dynamic_variables_size= 0;
524
1879
session->variables.dynamic_variables_ptr= 0;
526
session->variables.storage_engine= global_system_variables.storage_engine;
1881
session->variables.table_plugin=
1882
my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1883
intern_plugin_unlock(NULL, old_table_plugin);
531
1889
Unlocks all system variables which hold a reference
533
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
1891
static void unlock_variables(Session *, struct system_variables *vars)
535
vars->storage_engine= NULL;
1893
intern_plugin_unlock(NULL, vars->table_plugin);
1894
vars->table_plugin= NULL;
556
1943
void plugin_sessionvar_cleanup(Session *session)
558
1945
unlock_variables(session, &session->variables);
559
cleanup_variables(&session->variables);
1946
cleanup_variables(session, &session->variables);
1951
@brief Free values of thread variables of a plugin.
1953
This must be called before a plugin is deleted. Otherwise its
1954
variables are no longer accessible and the value space is lost. Note
1955
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1958
@param[in] vars Chain of system variables of a plugin
1961
static void plugin_vars_free_values(sys_var *vars)
1964
for (sys_var *var= vars; var; var= var->next)
1966
sys_var_pluginvar *piv= var->cast_pluginvar();
1968
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1969
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1971
/* Free the string from global_system_variables. */
1972
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1981
bool sys_var_pluginvar::check_update_type(Item_result type)
1985
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1986
case PLUGIN_VAR_INT:
1987
case PLUGIN_VAR_LONG:
1988
case PLUGIN_VAR_LONGLONG:
1989
return type != INT_RESULT;
1990
case PLUGIN_VAR_STR:
1991
return type != STRING_RESULT;
1998
SHOW_TYPE sys_var_pluginvar::show_type()
2000
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2001
case PLUGIN_VAR_BOOL:
2002
return SHOW_MY_BOOL;
2003
case PLUGIN_VAR_INT:
2005
case PLUGIN_VAR_LONG:
2007
case PLUGIN_VAR_LONGLONG:
2008
return SHOW_LONGLONG;
2009
case PLUGIN_VAR_STR:
2010
return SHOW_CHAR_PTR;
2011
case PLUGIN_VAR_ENUM:
2012
case PLUGIN_VAR_SET:
2021
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2023
assert(session || (type == OPT_GLOBAL));
2024
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2026
if (type == OPT_GLOBAL)
2029
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2031
return *(unsigned char**) (plugin_var+1);
2035
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2037
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2038
case PLUGIN_VAR_ENUM:
2039
return ((sysvar_enum_t *)plugin_var)->typelib;
2040
case PLUGIN_VAR_SET:
2041
return ((sysvar_set_t *)plugin_var)->typelib;
2042
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2043
return ((sessionvar_enum_t *)plugin_var)->typelib;
2044
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2045
return ((sessionvar_set_t *)plugin_var)->typelib;
2053
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
2055
unsigned char* result;
2057
result= real_value_ptr(session, type);
2059
if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2060
result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2061
else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2063
char buffer[STRING_BUFFER_USUAL_SIZE];
2064
String str(buffer, sizeof(buffer), system_charset_info);
2065
TYPELIB *typelib= plugin_var_typelib();
2066
uint64_t mask= 1, value= *(uint64_t*) result;
2070
for (i= 0; i < typelib->count; i++, mask<<=1)
2072
if (!(value & mask))
2074
str.append(typelib->type_names[i], typelib->type_lengths[i]);
2078
result= (unsigned char*) "";
2080
result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2086
bool sys_var_pluginvar::check(Session *session, set_var *var)
2088
st_item_value_holder value;
2089
assert(is_readonly() || plugin_var->check);
2091
value.value_type= item_value_type;
2092
value.val_str= item_val_str;
2093
value.val_int= item_val_int;
2094
value.val_real= item_val_real;
2095
value.item= var->value;
2097
return is_readonly() ||
2098
plugin_var->check(session, plugin_var, &var->save_result, &value);
2102
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2107
assert(is_readonly() || plugin_var->update);
2112
pthread_mutex_lock(&LOCK_global_system_variables);
2113
tgt= real_value_ptr(session, type);
2114
src= ((void **) (plugin_var + 1) + 1);
2116
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2118
if (type != OPT_GLOBAL)
2119
src= real_value_ptr(session, OPT_GLOBAL);
2121
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2122
case PLUGIN_VAR_INT:
2123
src= &((sessionvar_uint_t*) plugin_var)->def_val;
2125
case PLUGIN_VAR_LONG:
2126
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2128
case PLUGIN_VAR_LONGLONG:
2129
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2131
case PLUGIN_VAR_ENUM:
2132
src= &((sessionvar_enum_t*) plugin_var)->def_val;
2134
case PLUGIN_VAR_SET:
2135
src= &((sessionvar_set_t*) plugin_var)->def_val;
2137
case PLUGIN_VAR_BOOL:
2138
src= &((sessionvar_bool_t*) plugin_var)->def_val;
2140
case PLUGIN_VAR_STR:
2141
src= &((sessionvar_str_t*) plugin_var)->def_val;
2148
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
2149
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
2150
session == current_session);
2152
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2154
plugin_var->update(session, plugin_var, tgt, src);
2155
pthread_mutex_unlock(&LOCK_global_system_variables);
2159
pthread_mutex_unlock(&LOCK_global_system_variables);
2160
plugin_var->update(session, plugin_var, tgt, src);
2165
bool sys_var_pluginvar::update(Session *session, set_var *var)
2169
assert(is_readonly() || plugin_var->update);
2171
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
2172
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
2173
session == current_session);
2178
pthread_mutex_lock(&LOCK_global_system_variables);
2179
tgt= real_value_ptr(session, var->type);
2181
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2183
/* variable we are updating has global scope, so we unlock after updating */
2184
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2185
pthread_mutex_unlock(&LOCK_global_system_variables);
2189
pthread_mutex_unlock(&LOCK_global_system_variables);
2190
plugin_var->update(session, plugin_var, tgt, &var->save_result);
2196
#define OPTION_SET_LIMITS(type, options, opt) \
2197
options->var_type= type; \
2198
options->def_value= (opt)->def_val; \
2199
options->min_value= (opt)->min_val; \
2200
options->max_value= (opt)->max_val; \
2201
options->block_size= (long) (opt)->blk_sz
2204
static void plugin_opt_set_limits(struct my_option *options,
2205
const struct st_mysql_sys_var *opt)
2207
options->sub_size= 0;
2209
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2210
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2211
/* global system variables */
2212
case PLUGIN_VAR_INT:
2213
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2215
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
2216
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
2218
case PLUGIN_VAR_LONG:
2219
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2221
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2222
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
2224
case PLUGIN_VAR_LONGLONG:
2225
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2227
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
2228
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
2230
case PLUGIN_VAR_ENUM:
2231
options->var_type= GET_ENUM;
2232
options->typelib= ((sysvar_enum_t*) opt)->typelib;
2233
options->def_value= ((sysvar_enum_t*) opt)->def_val;
2234
options->min_value= options->block_size= 0;
2235
options->max_value= options->typelib->count - 1;
2237
case PLUGIN_VAR_SET:
2238
options->var_type= GET_SET;
2239
options->typelib= ((sysvar_set_t*) opt)->typelib;
2240
options->def_value= ((sysvar_set_t*) opt)->def_val;
2241
options->min_value= options->block_size= 0;
2242
options->max_value= (1UL << options->typelib->count) - 1;
2244
case PLUGIN_VAR_BOOL:
2245
options->var_type= GET_BOOL;
2246
options->def_value= ((sysvar_bool_t*) opt)->def_val;
2248
case PLUGIN_VAR_STR:
2249
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2250
GET_STR_ALLOC : GET_STR);
2251
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2253
/* threadlocal variables */
2254
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
2255
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
2257
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2258
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
2260
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
2261
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
2263
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2264
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
2266
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
2267
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
2269
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
2270
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
2272
case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2273
options->var_type= GET_ENUM;
2274
options->typelib= ((sessionvar_enum_t*) opt)->typelib;
2275
options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2276
options->min_value= options->block_size= 0;
2277
options->max_value= options->typelib->count - 1;
2279
case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2280
options->var_type= GET_SET;
2281
options->typelib= ((sessionvar_set_t*) opt)->typelib;
2282
options->def_value= ((sessionvar_set_t*) opt)->def_val;
2283
options->min_value= options->block_size= 0;
2284
options->max_value= (1UL << options->typelib->count) - 1;
2286
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2287
options->var_type= GET_BOOL;
2288
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2290
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2291
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2292
GET_STR_ALLOC : GET_STR);
2293
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2298
options->arg_type= REQUIRED_ARG;
2299
if (opt->flags & PLUGIN_VAR_NOCMDARG)
2300
options->arg_type= NO_ARG;
2301
if (opt->flags & PLUGIN_VAR_OPCMDARG)
2302
options->arg_type= OPT_ARG;
2305
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2308
bool get_one_plugin_option(int, const struct my_option *, char *)
2314
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
2315
my_option *options, bool can_disable)
2317
const char *plugin_name= tmp->plugin->name;
2318
uint32_t namelen= strlen(plugin_name), optnamelen;
2319
uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2320
char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2322
int index= 0, offset= 0;
2323
st_mysql_sys_var *opt, **plugin_option;
2326
/* support --skip-plugin-foo syntax */
2327
memcpy(name, plugin_name, namelen + 1);
2328
my_casedn_str(&my_charset_utf8_general_ci, name);
2329
sprintf(name+namelen+1, "plugin-%s", name);
2330
/* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2332
for (p= name + namelen*2 + 8; p > name; p--)
2338
sprintf(name+namelen*2+10,
2339
"Enable %s plugin. Disable with --skip-%s (will save memory).",
2342
Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2343
20 + namelen + 20 + 1 == namelen * 4 + 67.
2346
options[0].comment= name + namelen*2 + 10;
2349
options[1].name= (options[0].name= name) + namelen + 1;
2350
options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2351
options[0].var_type= options[1].var_type= GET_BOOL;
2352
options[0].arg_type= options[1].arg_type= NO_ARG;
2353
options[0].def_value= options[1].def_value= true;
2354
options[0].value= options[0].u_max_value=
2355
options[1].value= options[1].u_max_value= (char**) (name - 1);
2359
Two passes as the 2nd pass will take pointer addresses for use
2360
by my_getopt and register_var() in the first pass uses realloc
2363
for (plugin_option= tmp->plugin->system_vars;
2364
plugin_option && *plugin_option; plugin_option++, index++)
2366
opt= *plugin_option;
2367
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2369
if (!(register_var(name, opt->name, opt->flags)))
2371
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2372
case PLUGIN_VAR_BOOL:
2373
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2375
case PLUGIN_VAR_INT:
2376
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2378
case PLUGIN_VAR_LONG:
2379
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2381
case PLUGIN_VAR_LONGLONG:
2382
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2384
case PLUGIN_VAR_STR:
2385
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2387
case PLUGIN_VAR_ENUM:
2388
(((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2390
case PLUGIN_VAR_SET:
2391
(((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2394
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2395
opt->flags, plugin_name);
2400
for (plugin_option= tmp->plugin->system_vars;
2401
plugin_option && *plugin_option; plugin_option++, index++)
2403
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
2404
case PLUGIN_VAR_BOOL:
2406
opt->check= check_func_bool;
2408
opt->update= update_func_bool;
2410
case PLUGIN_VAR_INT:
2412
opt->check= check_func_int;
2414
opt->update= update_func_int;
2416
case PLUGIN_VAR_LONG:
2418
opt->check= check_func_long;
2420
opt->update= update_func_long;
2422
case PLUGIN_VAR_LONGLONG:
2424
opt->check= check_func_int64_t;
2426
opt->update= update_func_int64_t;
2428
case PLUGIN_VAR_STR:
2430
opt->check= check_func_str;
2433
opt->update= update_func_str;
2434
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2436
opt->flags|= PLUGIN_VAR_READONLY;
2437
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2438
"to be read-only: string variable without "
2439
"update_func and PLUGIN_VAR_MEMALLOC flag"),
2440
opt->name, plugin_name);
2444
case PLUGIN_VAR_ENUM:
2446
opt->check= check_func_enum;
2448
opt->update= update_func_long;
2450
case PLUGIN_VAR_SET:
2452
opt->check= check_func_set;
2454
opt->update= update_func_int64_t;
2457
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2458
opt->flags, plugin_name);
2462
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2463
== PLUGIN_VAR_NOCMDOPT)
2468
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2473
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2475
optnamelen= strlen(opt->name);
2476
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2477
sprintf(optname, "%s-%s", name, opt->name);
2478
optnamelen= namelen + optnamelen + 1;
2482
/* this should not fail because register_var should create entry */
2483
if (!(v= find_bookmark(name, opt->name, opt->flags)))
2485
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2486
"in plugin '%s'."), opt->name, plugin_name);
2490
*(int*)(opt + 1)= offset= v->offset;
2492
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2495
optname= (char*) memdup_root(mem_root, v->key + 1,
2496
(optnamelen= v->name_len) + 1);
2499
/* convert '_' to '-' */
2500
for (p= optname; *p; p++)
2504
options->name= optname;
2505
options->comment= opt->comment;
2506
options->app_type= opt;
2507
options->id= (options-1)->id + 1;
2509
plugin_opt_set_limits(options, opt);
2511
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2512
options->value= options->u_max_value= (char**)
2513
(global_system_variables.dynamic_variables_ptr + offset);
2515
options->value= options->u_max_value= *(char***) (opt + 1);
2517
options[1]= options[0];
2518
options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2519
options[1].comment= 0; // hidden
2520
sprintf(p,"plugin-%s",optname);
2529
static my_option *construct_help_options(MEM_ROOT *mem_root,
2530
struct st_plugin_int *p)
2532
st_mysql_sys_var **opt;
2535
uint32_t count= EXTRA_OPTIONS;
2537
for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2539
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2542
memset(opts, 0, sizeof(my_option) * count);
2544
if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2546
else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2552
if (construct_options(mem_root, p, opts, can_disable))