104
stored in bookmark_hash, this structure is never removed from the
105
hash and is used to mark a single offset for a session local variable
106
even if plugins have been uninstalled and reinstalled, repeatedly.
107
This structure is allocated from plugin_mem_root.
109
The key format is as follows:
110
1 byte - variable type code
111
name_len bytes - variable name
122
118
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
124
sys_var class for access to all plugin variables visible to the user
126
class sys_var_pluginvar: public sys_var
129
plugin::Module *plugin;
130
drizzle_sys_var *plugin_var;
132
sys_var_pluginvar(const std::string name_arg,
133
drizzle_sys_var *plugin_var_arg)
134
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
135
sys_var_pluginvar *cast_pluginvar() { return this; }
136
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
137
bool check_type(sql_var_t type)
138
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
139
bool check_update_type(Item_result type);
140
SHOW_TYPE show_type();
141
unsigned char* real_value_ptr(Session *session, sql_var_t type);
142
TYPELIB* plugin_var_typelib(void);
143
unsigned char* value_ptr(Session *session, sql_var_t type,
144
const LEX_STRING *base);
145
bool check(Session *session, set_var *var);
146
bool check_default(sql_var_t)
147
{ return is_readonly(); }
148
void set_default(Session *session, sql_var_t);
149
bool update(Session *session, set_var *var);
132
154
static void plugin_prune_list(vector<string> &plugin_list,
133
155
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);
156
static bool plugin_load_list(plugin::Registry ®istry,
157
memory::Root *tmp_root, int *argc, char **argv,
158
const set<string> &plugin_list);
159
static int test_plugin_options(memory::Root *, plugin::Module *,
161
static void unlock_variables(Session *session, struct system_variables *vars);
162
static void cleanup_variables(Session *session, struct system_variables *vars);
163
static void plugin_vars_free_values(sys_var *vars);
144
165
/* declared in set_var.cc */
145
166
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
167
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
168
const std::string &name, int64_t val);
170
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
171
const char *name, int64_t val)
173
const std::string name_str(name);
174
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
177
/****************************************************************************
178
Value type thunks, allows the C world to play in the C++ world
179
****************************************************************************/
181
static int item_value_type(drizzle_value *value)
183
switch (((st_item_value_holder*)value)->item->result_type()) {
185
return DRIZZLE_VALUE_TYPE_INT;
187
return DRIZZLE_VALUE_TYPE_REAL;
189
return DRIZZLE_VALUE_TYPE_STRING;
193
static const char *item_val_str(drizzle_value *value,
194
char *buffer, int *length)
196
String str(buffer, *length, system_charset_info), *res;
197
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
199
*length= res->length();
200
if (res->c_ptr_quick() == buffer)
204
Lets be nice and create a temporary string since the
207
return current_session->strmake(res->c_ptr_quick(), res->length());
211
static int item_val_int(drizzle_value *value, int64_t *buf)
213
Item *item= ((st_item_value_holder*)value)->item;
214
*buf= item->val_int();
221
static int item_val_real(drizzle_value *value, double *buf)
223
Item *item= ((st_item_value_holder*)value)->item;
224
*buf= item->val_real();
148
231
/****************************************************************************
295
370
Finally we initialize everything, aka the dynamic that have yet to initialize.
297
bool plugin_init(module::Registry ®istry,
298
po::options_description &long_options)
372
bool plugin_init(plugin::Registry ®istry,
373
int *argc, char **argv,
376
plugin::Manifest **builtins;
377
plugin::Manifest *manifest;
378
plugin::Module *module;
300
379
memory::Root tmp_root(4096);
384
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
385
get_bookmark_hash_key, NULL, HASH_UNIQUE))
387
tmp_root.free_root(MYF(0));
307
PluginOptions builtin_load_list;
308
tokenize(builtin_load_plugins, builtin_load_list, ",", true);
310
PluginOptions builtin_list;
311
tokenize(builtin_plugins, builtin_list, ",", true);
395
First we register builtin plugins
397
for (builtins= drizzled_builtins; *builtins; builtins++)
400
if (manifest->name != NULL)
402
module= new (std::nothrow) plugin::Module(manifest);
406
tmp_root.free_root(MYF(memory::MARK_BLOCKS_FREE));
407
if (test_plugin_options(&tmp_root, module, argc, argv))
410
registry.add(module);
412
plugin_initialize_vars(module);
416
if (plugin_initialize(registry, module))
418
tmp_root.free_root(MYF(0));
313
426
bool load_failed= false;
315
if (opt_plugin_add.size() > 0)
317
for (PluginOptions::iterator iter= opt_plugin_add.begin();
318
iter != opt_plugin_add.end();
321
if (find(builtin_list.begin(),
322
builtin_list.end(), *iter) != builtin_list.end())
324
builtin_load_list.push_back(*iter);
328
opt_plugin_load.push_back(*iter);
333
if (opt_plugin_remove.size() > 0)
335
plugin_prune_list(opt_plugin_load, opt_plugin_remove);
336
plugin_prune_list(builtin_load_list, opt_plugin_remove);
341
First we register builtin plugins
343
const set<string> builtin_list_set(builtin_load_list.begin(),
344
builtin_load_list.end());
345
load_failed= plugin_load_list(registry, &tmp_root,
346
builtin_list_set, long_options, true);
349
tmp_root.free_root(MYF(0));
427
vector<string> plugin_list;
430
tokenize(opt_plugin_load, plugin_list, ",", true);
434
tokenize(opt_plugin_load_default, plugin_list, ",", true);
438
tokenize(opt_plugin_add, plugin_list, ",", true);
441
if (opt_plugin_remove)
443
vector<string> plugins_to_remove;
444
tokenize(opt_plugin_remove, plugins_to_remove, ",", true);
445
plugin_prune_list(plugin_list, plugins_to_remove);
353
448
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
449
const set<string> plugin_list_set(plugin_list.begin(), plugin_list.end());
357
451
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
452
load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
362
456
tmp_root.free_root(MYF(0));
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
462
tmp_root.free_root(MYF(0));
374
467
Now we initialize all remaining plugins
376
std::map<std::string, module::Module *>::const_iterator modules=
469
std::map<std::string, plugin::Module *>::const_iterator modules=
377
470
registry.getModulesMap().begin();
379
472
while (modules != registry.getModulesMap().end())
381
module::Module *module= (*modules).second;
474
module= (*modules).second;
383
476
if (module->isInited == false)
478
plugin_initialize_vars(module);
385
480
if (plugin_initialize(registry, module))
387
registry.remove(module);
481
delete_module(module);
394
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
396
value.second->prime();
486
tmp_root.free_root(MYF(0));
482
568
unlock_variables(NULL, &global_system_variables);
483
569
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
571
cleanup_variables(NULL, &global_system_variables);
572
cleanup_variables(NULL, &max_system_variables);
491
577
/* Dispose of the memory */
579
hash_free(&bookmark_hash);
492
580
plugin_mem_root.free_root(MYF(0));
494
582
global_variables_dynamic_size= 0;
585
/****************************************************************************
586
Internal type declarations for variables support
587
****************************************************************************/
589
#undef DRIZZLE_SYSVAR_NAME
590
#define DRIZZLE_SYSVAR_NAME(name) name
591
#define PLUGIN_VAR_TYPEMASK 0x007f
593
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
595
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
596
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
597
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
598
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
600
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
601
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
603
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
604
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
605
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
606
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
607
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
608
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
610
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
611
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
612
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
613
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
614
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
615
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
617
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
620
/****************************************************************************
621
default variable data check and update functions
622
****************************************************************************/
624
static int check_func_bool(Session *, drizzle_sys_var *var,
625
void *save, drizzle_value *value)
627
char buff[STRING_BUFFER_USUAL_SIZE];
628
const char *strvalue= "NULL", *str;
632
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
634
length= sizeof(buff);
635
if (!(str= value->val_str(value, buff, &length)) ||
636
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
645
if (value->val_int(value, &tmp) < 0)
649
internal::llstr(tmp, buff);
655
*(int*)save= -result;
658
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
663
static int check_func_int(Session *session, drizzle_sys_var *var,
664
void *save, drizzle_value *value)
668
struct option options;
669
value->val_int(value, &tmp);
670
plugin_opt_set_limits(&options, var);
672
if (var->flags & PLUGIN_VAR_UNSIGNED)
673
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
676
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
678
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
679
var->name, (int64_t) tmp);
683
static int check_func_long(Session *session, drizzle_sys_var *var,
684
void *save, drizzle_value *value)
688
struct option options;
689
value->val_int(value, &tmp);
690
plugin_opt_set_limits(&options, var);
692
if (var->flags & PLUGIN_VAR_UNSIGNED)
693
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
696
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
698
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
699
var->name, (int64_t) tmp);
703
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
704
void *save, drizzle_value *value)
708
struct option options;
709
value->val_int(value, &tmp);
710
plugin_opt_set_limits(&options, var);
712
if (var->flags & PLUGIN_VAR_UNSIGNED)
713
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
716
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
718
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
719
var->name, (int64_t) tmp);
722
static int check_func_str(Session *session, drizzle_sys_var *,
723
void *save, drizzle_value *value)
725
char buff[STRING_BUFFER_USUAL_SIZE];
729
length= sizeof(buff);
730
if ((str= value->val_str(value, buff, &length)))
731
str= session->strmake(str, length);
732
*(const char**)save= str;
737
static void update_func_bool(Session *, drizzle_sys_var *,
738
void *tgt, const void *save)
740
*(bool *) tgt= *(int *) save ? 1 : 0;
744
static void update_func_int(Session *, drizzle_sys_var *,
745
void *tgt, const void *save)
747
*(int *)tgt= *(int *) save;
751
static void update_func_long(Session *, drizzle_sys_var *,
752
void *tgt, const void *save)
754
*(long *)tgt= *(long *) save;
758
static void update_func_int64_t(Session *, drizzle_sys_var *,
759
void *tgt, const void *save)
761
*(int64_t *)tgt= *(uint64_t *) save;
765
static void update_func_str(Session *, drizzle_sys_var *var,
766
void *tgt, const void *save)
768
char *old= *(char **) tgt;
769
*(char **)tgt= *(char **) save;
770
if (var->flags & PLUGIN_VAR_MEMALLOC)
772
*(char **)tgt= strdup(*(char **) save);
775
* There isn't a _really_ good thing to do here until this whole set_var
776
* mess gets redesigned
779
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
785
/****************************************************************************
499
786
System Variables support
500
787
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
790
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
793
sys_var_pluginvar *pi= NULL;
794
plugin::Module *module;
796
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
797
if ((var= intern_find_sys_var(str, length, false)) &&
798
(pi= var->cast_pluginvar()))
800
pthread_rwlock_unlock(&LOCK_system_variables_hash);
801
if (!(module= pi->plugin))
802
var= NULL; /* failed to lock it, it must be uninstalling */
803
else if (module->isInited == false)
809
pthread_rwlock_unlock(&LOCK_system_variables_hash);
812
If the variable exists but the plugin it is associated with is not ready
813
then the intern_plugin_lock did not raise an error, so we do it here.
816
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
820
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
822
/* Embed the flags into the first char of the string */
823
string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
824
varname.append(plugin);
825
varname.push_back('_');
826
varname.append(name);
828
for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
839
called by register_var, construct_options and test_plugin_options.
840
Returns the 'bookmark' for the named variable.
841
LOCK_system_variables_hash should be at least read locked
843
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
845
st_bookmark *result= NULL;
847
if (!(flags & PLUGIN_VAR_SessionLOCAL))
850
const string varname(make_bookmark_name(plugin, name, flags));
853
result= (st_bookmark*) hash_search(&bookmark_hash,
854
(const unsigned char*) varname.c_str(), varname.size() - 1);
861
returns a bookmark for session-local variables, creating if neccessary.
862
returns null for non session-local variables.
863
Requires that a write lock is obtained on LOCK_system_variables_hash
865
static st_bookmark *register_var(const string &plugin, const char *name,
868
if (!(flags & PLUGIN_VAR_SessionLOCAL))
871
uint32_t size= 0, offset, new_size;
874
switch (flags & PLUGIN_VAR_TYPEMASK) {
875
case PLUGIN_VAR_BOOL:
876
size= ALIGN_SIZE(sizeof(bool));
879
size= ALIGN_SIZE(sizeof(int));
881
case PLUGIN_VAR_LONG:
882
size= ALIGN_SIZE(sizeof(long));
884
case PLUGIN_VAR_LONGLONG:
885
size= ALIGN_SIZE(sizeof(uint64_t));
888
size= ALIGN_SIZE(sizeof(char*));
896
if (!(result= find_bookmark(plugin, name, flags)))
898
const string varname(make_bookmark_name(plugin, name, flags));
900
result= static_cast<st_bookmark*>(plugin_mem_root.alloc_root(sizeof(struct st_bookmark) + varname.size() + 1));
901
memset(result->key, 0, varname.size()+1);
902
memcpy(result->key, varname.c_str(), varname.size());
903
result->name_len= varname.size() - 2;
906
assert(size && !(size & (size-1))); /* must be power of 2 */
908
offset= global_system_variables.dynamic_variables_size;
909
offset= (offset + size - 1) & ~(size - 1);
910
result->offset= (int) offset;
912
new_size= (offset + size + 63) & ~63;
914
if (new_size > global_variables_dynamic_size)
918
(char *)realloc(global_system_variables.dynamic_variables_ptr,
921
global_system_variables.dynamic_variables_ptr= tmpptr;
924
(char *)realloc(max_system_variables.dynamic_variables_ptr,
927
max_system_variables.dynamic_variables_ptr= tmpptr;
930
Clear the new variable value space. This is required for string
931
variables. If their value is non-NULL, it must point to a valid
934
memset(global_system_variables.dynamic_variables_ptr +
935
global_variables_dynamic_size, 0,
936
new_size - global_variables_dynamic_size);
937
memset(max_system_variables.dynamic_variables_ptr +
938
global_variables_dynamic_size, 0,
939
new_size - global_variables_dynamic_size);
940
global_variables_dynamic_size= new_size;
943
global_system_variables.dynamic_variables_head= offset;
944
max_system_variables.dynamic_variables_head= offset;
945
global_system_variables.dynamic_variables_size= offset + size;
946
max_system_variables.dynamic_variables_size= offset + size;
947
global_system_variables.dynamic_variables_version++;
948
max_system_variables.dynamic_variables_version++;
950
result->version= global_system_variables.dynamic_variables_version;
952
/* this should succeed because we have already checked if a dup exists */
953
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
955
fprintf(stderr, "failed to add placeholder to hash");
964
returns a pointer to the memory which holds the session-local variable or
965
a pointer to the global variable if session==null.
966
If required, will sync with global variables if the requested variable
967
has not yet been allocated in the current thread.
969
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
972
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
975
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
978
dynamic_variables_head points to the largest valid offset
980
if (!session->variables.dynamic_variables_ptr ||
981
(uint32_t)offset > session->variables.dynamic_variables_head)
985
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
988
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
989
global_variables_dynamic_size)))
991
session->variables.dynamic_variables_ptr= tmpptr;
994
pthread_mutex_lock(&LOCK_global_system_variables);
996
//safe_mutex_assert_owner(&LOCK_global_system_variables);
998
memcpy(session->variables.dynamic_variables_ptr +
999
session->variables.dynamic_variables_size,
1000
global_system_variables.dynamic_variables_ptr +
1001
session->variables.dynamic_variables_size,
1002
global_system_variables.dynamic_variables_size -
1003
session->variables.dynamic_variables_size);
1006
now we need to iterate through any newly copied 'defaults'
1007
and if it is a string type with MEMALLOC flag, we need to strdup
1009
for (idx= 0; idx < bookmark_hash.records; idx++)
1011
sys_var_pluginvar *pi;
1013
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1015
if (v->version <= session->variables.dynamic_variables_version ||
1016
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1017
!(pi= var->cast_pluginvar()) ||
1018
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1021
/* Here we do anything special that may be required of the data types */
1023
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1024
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1026
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1027
*(int*)(pi->plugin_var + 1));
1028
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1029
*(int*)(pi->plugin_var + 1))))
1037
pthread_mutex_unlock(&LOCK_global_system_variables);
1039
session->variables.dynamic_variables_version=
1040
global_system_variables.dynamic_variables_version;
1041
session->variables.dynamic_variables_head=
1042
global_system_variables.dynamic_variables_head;
1043
session->variables.dynamic_variables_size=
1044
global_system_variables.dynamic_variables_size;
1046
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1048
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1051
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1053
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1056
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1058
return (int *)intern_sys_var_ptr(a_session, offset, true);
1061
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1063
return (long *)intern_sys_var_ptr(a_session, offset, true);
1066
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1068
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1071
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1073
return (char **)intern_sys_var_ptr(a_session, offset, true);
509
1076
void plugin_sessionvar_init(Session *session)
511
1078
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1079
cleanup_variables(session, &session->variables);
514
1081
session->variables= global_system_variables;
515
1082
session->variables.storage_engine= NULL;
552
1147
void plugin_sessionvar_cleanup(Session *session)
554
1149
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1150
cleanup_variables(session, &session->variables);
1155
@brief Free values of thread variables of a plugin.
1157
This must be called before a plugin is deleted. Otherwise its
1158
variables are no longer accessible and the value space is lost. Note
1159
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1162
@param[in] vars Chain of system variables of a plugin
1165
static void plugin_vars_free_values(sys_var *vars)
1168
for (sys_var *var= vars; var; var= var->getNext())
1170
sys_var_pluginvar *piv= var->cast_pluginvar();
1172
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1173
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1175
/* Free the string from global_system_variables. */
1176
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1185
bool sys_var_pluginvar::check_update_type(Item_result type)
1189
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1190
case PLUGIN_VAR_INT:
1191
case PLUGIN_VAR_LONG:
1192
case PLUGIN_VAR_LONGLONG:
1193
return type != INT_RESULT;
1194
case PLUGIN_VAR_STR:
1195
return type != STRING_RESULT;
1202
SHOW_TYPE sys_var_pluginvar::show_type()
1204
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1205
case PLUGIN_VAR_BOOL:
1206
return SHOW_MY_BOOL;
1207
case PLUGIN_VAR_INT:
1209
case PLUGIN_VAR_LONG:
1211
case PLUGIN_VAR_LONGLONG:
1212
return SHOW_LONGLONG;
1213
case PLUGIN_VAR_STR:
1214
return SHOW_CHAR_PTR;
1222
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
1224
assert(session || (type == OPT_GLOBAL));
1225
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1227
if (type == OPT_GLOBAL)
1230
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1232
return *(unsigned char**) (plugin_var+1);
1236
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1238
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1239
case PLUGIN_VAR_SessionLOCAL:
1240
return ((sessionvar_enum_t *)plugin_var)->typelib;
1248
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
1250
unsigned char* result;
1252
result= real_value_ptr(session, type);
1258
bool sys_var_pluginvar::check(Session *session, set_var *var)
1260
st_item_value_holder value;
1261
assert(is_readonly() || plugin_var->check);
1263
value.value_type= item_value_type;
1264
value.val_str= item_val_str;
1265
value.val_int= item_val_int;
1266
value.val_real= item_val_real;
1267
value.item= var->value;
1269
return is_readonly() ||
1270
plugin_var->check(session, plugin_var, &var->save_result, &value);
1274
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
1279
assert(is_readonly() || plugin_var->update);
1284
pthread_mutex_lock(&LOCK_global_system_variables);
1285
tgt= real_value_ptr(session, type);
1286
src= ((void **) (plugin_var + 1) + 1);
1288
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1290
if (type != OPT_GLOBAL)
1291
src= real_value_ptr(session, OPT_GLOBAL);
1293
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1294
case PLUGIN_VAR_INT:
1295
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1297
case PLUGIN_VAR_LONG:
1298
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1300
case PLUGIN_VAR_LONGLONG:
1301
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1303
case PLUGIN_VAR_BOOL:
1304
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1306
case PLUGIN_VAR_STR:
1307
src= &((sessionvar_str_t*) plugin_var)->def_val;
1314
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1315
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1316
session == current_session);
1318
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1320
plugin_var->update(session, plugin_var, tgt, src);
1321
pthread_mutex_unlock(&LOCK_global_system_variables);
1325
pthread_mutex_unlock(&LOCK_global_system_variables);
1326
plugin_var->update(session, plugin_var, tgt, src);
1331
bool sys_var_pluginvar::update(Session *session, set_var *var)
1335
assert(is_readonly() || plugin_var->update);
1337
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1338
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1339
session == current_session);
1344
pthread_mutex_lock(&LOCK_global_system_variables);
1345
tgt= real_value_ptr(session, var->type);
1347
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1349
/* variable we are updating has global scope, so we unlock after updating */
1350
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1351
pthread_mutex_unlock(&LOCK_global_system_variables);
1355
pthread_mutex_unlock(&LOCK_global_system_variables);
1356
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1362
#define OPTION_SET_LIMITS(type, options, opt) \
1363
options->var_type= type; \
1364
options->def_value= (opt)->def_val; \
1365
options->min_value= (opt)->min_val; \
1366
options->max_value= (opt)->max_val; \
1367
options->block_size= (long) (opt)->blk_sz
1370
void plugin_opt_set_limits(struct option *options,
1371
const drizzle_sys_var *opt)
1373
options->sub_size= 0;
1375
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1376
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1377
/* global system variables */
1378
case PLUGIN_VAR_INT:
1379
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1381
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1382
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1384
case PLUGIN_VAR_LONG:
1385
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1387
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1388
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1390
case PLUGIN_VAR_LONGLONG:
1391
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1393
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1394
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1396
case PLUGIN_VAR_BOOL:
1397
options->var_type= GET_BOOL;
1398
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1400
case PLUGIN_VAR_STR:
1401
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1402
GET_STR_ALLOC : GET_STR);
1403
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1405
/* threadlocal variables */
1406
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1407
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1409
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1410
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1412
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1413
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1415
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1416
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1418
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1419
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1421
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1422
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1424
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1425
options->var_type= GET_BOOL;
1426
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1428
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1429
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1430
GET_STR_ALLOC : GET_STR);
1431
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1436
options->arg_type= REQUIRED_ARG;
1437
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1438
options->arg_type= NO_ARG;
1439
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1440
options->arg_type= OPT_ARG;
1443
static int get_one_plugin_option(int, const struct option *, char *)
1449
static int construct_options(memory::Root *mem_root, plugin::Module *tmp,
1453
int localoptionid= 256;
1454
const string plugin_name(tmp->getManifest().name);
1456
size_t namelen= plugin_name.size(), optnamelen;
1459
int index= 0, offset= 0;
1460
drizzle_sys_var *opt, **plugin_option;
1463
string name(plugin_name);
1464
transform(name.begin(), name.end(), name.begin(), ::tolower);
1466
for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
1473
Two passes as the 2nd pass will take pointer addresses for use
1474
by my_getopt and register_var() in the first pass uses realloc
1477
for (plugin_option= tmp->getManifest().system_vars;
1478
plugin_option && *plugin_option; plugin_option++, index++)
1480
opt= *plugin_option;
1481
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1483
if (!(register_var(name, opt->name, opt->flags)))
1485
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1486
case PLUGIN_VAR_BOOL:
1487
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1489
case PLUGIN_VAR_INT:
1490
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1492
case PLUGIN_VAR_LONG:
1493
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1495
case PLUGIN_VAR_LONGLONG:
1496
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1498
case PLUGIN_VAR_STR:
1499
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1502
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1503
opt->flags, plugin_name.c_str());
1508
for (plugin_option= tmp->getManifest().system_vars;
1509
plugin_option && *plugin_option; plugin_option++, index++)
1511
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1512
case PLUGIN_VAR_BOOL:
1514
opt->check= check_func_bool;
1516
opt->update= update_func_bool;
1518
case PLUGIN_VAR_INT:
1520
opt->check= check_func_int;
1522
opt->update= update_func_int;
1524
case PLUGIN_VAR_LONG:
1526
opt->check= check_func_long;
1528
opt->update= update_func_long;
1530
case PLUGIN_VAR_LONGLONG:
1532
opt->check= check_func_int64_t;
1534
opt->update= update_func_int64_t;
1536
case PLUGIN_VAR_STR:
1538
opt->check= check_func_str;
1541
opt->update= update_func_str;
1542
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1544
opt->flags|= PLUGIN_VAR_READONLY;
1545
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1546
"to be read-only: string variable without "
1547
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1548
opt->name, plugin_name.c_str());
1553
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1554
opt->flags, plugin_name.c_str());
1558
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
1559
== PLUGIN_VAR_NOCMDOPT)
1564
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1565
plugin_name.c_str());
1569
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1571
optnamelen= strlen(opt->name);
1572
optname= (char*) mem_root->alloc_root(namelen + optnamelen + 2);
1573
sprintf(optname, "%s-%s", name.c_str(), opt->name);
1574
optnamelen= namelen + optnamelen + 1;
1578
/* this should not fail because register_var should create entry */
1579
if (!(v= find_bookmark(name, opt->name, opt->flags)))
1581
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1582
"in plugin '%s'."), opt->name, plugin_name.c_str());
1586
*(int*)(opt + 1)= offset= v->offset;
1588
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
1591
optname= (char*) mem_root->memdup_root(v->key + 1, (optnamelen= v->name_len) + 1);
1594
/* convert '_' to '-' */
1595
for (p= optname; *p; p++)
1599
options->name= optname;
1600
options->comment= opt->comment;
1601
options->app_type= opt;
1602
options->id= localoptionid++;
1604
plugin_opt_set_limits(options, opt);
1606
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
1607
options->value= options->u_max_value= (char**)
1608
(global_system_variables.dynamic_variables_ptr + offset);
1610
options->value= options->u_max_value= *(char***) (opt + 1);
1619
static option *construct_help_options(memory::Root *mem_root, plugin::Module *p)
1621
drizzle_sys_var **opt;
1623
uint32_t count= EXTRA_OPTIONS;
1625
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1627
opts= (option*)mem_root->alloc_root((sizeof(option) * count));
1631
memset(opts, 0, sizeof(option) * count);
1633
if (construct_options(mem_root, p, opts))
1639
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1641
plugin_sysvar_vec.push_back(var);
1644
void drizzle_del_plugin_sysvar()
1646
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1647
while(iter != plugin_sysvar_vec.end())
1652
plugin_sysvar_vec.clear();
562
1657
test_plugin_options()
563
1658
tmp_root temporary scratch space
564
1659
plugin internal plugin structure
1660
argc user supplied arguments
1661
argv user supplied arguments
565
1662
default_enabled default plugin enable status
567
1664
0 SUCCESS - plugin should be enabled/loaded
569
1666
Requires that a write-lock is held on LOCK_system_variables_hash
571
static int test_plugin_options(memory::Root *,
572
module::Module *test_module,
573
po::options_description &long_options)
1668
static int test_plugin_options(memory::Root *tmp_root, plugin::Module *tmp,
1669
int *argc, char **argv)
576
if (test_module->getManifest().init_options != NULL)
578
string plugin_section_title("Options used by ");
579
plugin_section_title.append(test_module->getName());
580
po::options_description module_options(plugin_section_title);
581
module::option_context opt_ctx(test_module->getName(),
582
module_options.add_options());
583
test_module->getManifest().init_options(opt_ctx);
584
long_options.add(module_options);
1671
struct sys_var_chain chain= { NULL, NULL };
1672
drizzle_sys_var **opt;
1676
struct st_bookmark *var;
1677
uint32_t len, count= EXTRA_OPTIONS;
1679
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1683
if (count > EXTRA_OPTIONS || (*argc > 1))
1685
if (!(opts= (option*) tmp_root->alloc_root(sizeof(option) * count)))
1687
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
1690
memset(opts, 0, sizeof(option) * count);
1692
if (construct_options(tmp_root, tmp, opts))
1694
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
1698
error= handle_options(argc, &argv, opts, get_one_plugin_option);
1699
(*argc)++; /* add back one for the program name */
1703
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
1704
tmp->getName().c_str());
1712
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1715
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1718
if ((var= find_bookmark(tmp->getName(), o->name, o->flags)))
1719
v= new sys_var_pluginvar(var->key + 1, o);
1722
len= tmp->getName().length() + strlen(o->name) + 2;
1723
string vname(tmp->getName());
1724
vname.push_back('-');
1725
vname.append(o->name);
1726
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1727
string::iterator p= vname.begin();
1728
while (p != vname.end())
1735
v= new sys_var_pluginvar(vname, o);
1737
assert(v); /* check that an object was actually constructed */
1739
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1741
Add to the chain of variables.
1742
Done like this for easier debugging so that the
1743
pointer to v is not lost on optimized builds.
1745
v->chain_sys_var(&chain);
1749
chain.last->setNext(NULL);
1750
if (mysql_add_sys_var_chain(chain.first, NULL))
1752
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
1753
tmp->getName().c_str());
1756
tmp->system_vars= chain.first;
1763
my_cleanup_options(opts);