112
stored in bookmark_hash, this structure is never removed from the
113
hash and is used to mark a single offset for a session local variable
114
even if plugins have been uninstalled and reinstalled, repeatedly.
115
This structure is allocated from plugin_mem_root.
117
The key format is as follows:
118
1 byte - variable type code
119
name_len bytes - variable name
122
126
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
132
sys_var class for access to all plugin variables visible to the user
134
class sys_var_pluginvar: public sys_var
137
module::Module *plugin;
138
drizzle_sys_var *plugin_var;
140
sys_var_pluginvar(const std::string name_arg,
141
drizzle_sys_var *plugin_var_arg)
142
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
143
sys_var_pluginvar *cast_pluginvar() { return this; }
144
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
145
bool check_type(sql_var_t type)
146
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
147
bool check_update_type(Item_result type);
148
SHOW_TYPE show_type();
149
unsigned char* real_value_ptr(Session *session, sql_var_t type);
150
TYPELIB* plugin_var_typelib(void);
151
unsigned char* value_ptr(Session *session, sql_var_t type,
152
const LEX_STRING *base);
153
bool check(Session *session, set_var *var);
154
bool check_default(sql_var_t)
155
{ return is_readonly(); }
156
void set_default(Session *session, sql_var_t);
157
bool update(Session *session, set_var *var);
132
162
static void plugin_prune_list(vector<string> &plugin_list,
133
163
const vector<string> &plugins_to_remove);
134
164
static bool plugin_load_list(module::Registry ®istry,
135
memory::Root *tmp_root,
165
memory::Root *tmp_root, int *argc, char **argv,
136
166
const set<string> &plugin_list,
137
167
po::options_description &long_options,
138
168
bool builtin= false);
139
169
static int test_plugin_options(memory::Root *, module::Module *,
140
171
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);
172
static void unlock_variables(Session *session, struct system_variables *vars);
173
static void cleanup_variables(Session *session, struct system_variables *vars);
174
static void plugin_vars_free_values(sys_var *vars);
176
/* declared in set_var.cc */
177
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
178
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
179
const std::string &name, int64_t val);
181
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
182
const char *name, int64_t val)
184
const std::string name_str(name);
185
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
188
/****************************************************************************
189
Value type thunks, allows the C world to play in the C++ world
190
****************************************************************************/
192
static int item_value_type(drizzle_value *value)
194
switch (((st_item_value_holder*)value)->item->result_type()) {
196
return DRIZZLE_VALUE_TYPE_INT;
198
return DRIZZLE_VALUE_TYPE_REAL;
200
return DRIZZLE_VALUE_TYPE_STRING;
204
static const char *item_val_str(drizzle_value *value,
205
char *buffer, int *length)
207
String str(buffer, *length, system_charset_info), *res;
208
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
210
*length= res->length();
211
if (res->c_ptr_quick() == buffer)
215
Lets be nice and create a temporary string since the
218
return current_session->strmake(res->c_ptr_quick(), res->length());
222
static int item_val_int(drizzle_value *value, int64_t *buf)
224
Item *item= ((st_item_value_holder*)value)->item;
225
*buf= item->val_int();
232
static int item_val_real(drizzle_value *value, double *buf)
234
Item *item= ((st_item_value_holder*)value)->item;
235
*buf= item->val_real();
145
242
/****************************************************************************
491
567
unlock_variables(NULL, &global_system_variables);
492
568
unlock_variables(NULL, &max_system_variables);
494
cleanup_variables(&global_system_variables);
495
cleanup_variables(&max_system_variables);
570
cleanup_variables(NULL, &global_system_variables);
571
cleanup_variables(NULL, &max_system_variables);
500
576
/* Dispose of the memory */
578
hash_free(&bookmark_hash);
501
579
plugin_mem_root.free_root(MYF(0));
503
581
global_variables_dynamic_size= 0;
584
/****************************************************************************
585
Internal type declarations for variables support
586
****************************************************************************/
588
#undef DRIZZLE_SYSVAR_NAME
589
#define DRIZZLE_SYSVAR_NAME(name) name
590
#define PLUGIN_VAR_TYPEMASK 0x007f
592
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
594
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
595
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
596
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
597
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
599
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
600
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
602
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
603
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
604
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
605
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
606
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
607
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
609
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
610
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
611
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
612
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
613
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
614
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
616
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
619
/****************************************************************************
620
default variable data check and update functions
621
****************************************************************************/
623
static int check_func_bool(Session *, drizzle_sys_var *var,
624
void *save, drizzle_value *value)
626
char buff[STRING_BUFFER_USUAL_SIZE];
627
const char *strvalue= "NULL", *str;
631
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
633
length= sizeof(buff);
634
if (!(str= value->val_str(value, buff, &length)) ||
635
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
644
if (value->val_int(value, &tmp) < 0)
648
internal::llstr(tmp, buff);
654
*(int*)save= -result;
657
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
662
static int check_func_int(Session *session, drizzle_sys_var *var,
663
void *save, drizzle_value *value)
667
struct option options;
668
value->val_int(value, &tmp);
669
plugin_opt_set_limits(&options, var);
671
if (var->flags & PLUGIN_VAR_UNSIGNED)
672
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
675
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
677
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
678
var->name, (int64_t) tmp);
682
static int check_func_long(Session *session, drizzle_sys_var *var,
683
void *save, drizzle_value *value)
687
struct option options;
688
value->val_int(value, &tmp);
689
plugin_opt_set_limits(&options, var);
691
if (var->flags & PLUGIN_VAR_UNSIGNED)
692
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
695
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
697
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
698
var->name, (int64_t) tmp);
702
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
703
void *save, drizzle_value *value)
707
struct option options;
708
value->val_int(value, &tmp);
709
plugin_opt_set_limits(&options, var);
711
if (var->flags & PLUGIN_VAR_UNSIGNED)
712
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
715
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
717
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
718
var->name, (int64_t) tmp);
721
static int check_func_str(Session *session, drizzle_sys_var *,
722
void *save, drizzle_value *value)
724
char buff[STRING_BUFFER_USUAL_SIZE];
728
length= sizeof(buff);
729
if ((str= value->val_str(value, buff, &length)))
730
str= session->strmake(str, length);
731
*(const char**)save= str;
736
static void update_func_bool(Session *, drizzle_sys_var *,
737
void *tgt, const void *save)
739
*(bool *) tgt= *(int *) save ? 1 : 0;
743
static void update_func_int(Session *, drizzle_sys_var *,
744
void *tgt, const void *save)
746
*(int *)tgt= *(int *) save;
750
static void update_func_long(Session *, drizzle_sys_var *,
751
void *tgt, const void *save)
753
*(long *)tgt= *(long *) save;
757
static void update_func_int64_t(Session *, drizzle_sys_var *,
758
void *tgt, const void *save)
760
*(int64_t *)tgt= *(uint64_t *) save;
764
static void update_func_str(Session *, drizzle_sys_var *var,
765
void *tgt, const void *save)
767
char *old= *(char **) tgt;
768
*(char **)tgt= *(char **) save;
769
if (var->flags & PLUGIN_VAR_MEMALLOC)
771
*(char **)tgt= strdup(*(char **) save);
774
* There isn't a _really_ good thing to do here until this whole set_var
775
* mess gets redesigned
778
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
507
784
/****************************************************************************
508
785
System Variables support
509
786
****************************************************************************/
789
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
792
sys_var_pluginvar *pi= NULL;
793
module::Module *module;
795
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
796
if ((var= intern_find_sys_var(str, length, false)) &&
797
(pi= var->cast_pluginvar()))
799
pthread_rwlock_unlock(&LOCK_system_variables_hash);
800
if (!(module= pi->plugin))
801
var= NULL; /* failed to lock it, it must be uninstalling */
802
else if (module->isInited == false)
808
pthread_rwlock_unlock(&LOCK_system_variables_hash);
811
If the variable exists but the plugin it is associated with is not ready
812
then the intern_plugin_lock did not raise an error, so we do it here.
815
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
819
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
821
/* Embed the flags into the first char of the string */
822
string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
823
varname.append(plugin);
824
varname.push_back('_');
825
varname.append(name);
827
for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
838
called by register_var, construct_options and test_plugin_options.
839
Returns the 'bookmark' for the named variable.
840
LOCK_system_variables_hash should be at least read locked
842
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
844
st_bookmark *result= NULL;
846
if (!(flags & PLUGIN_VAR_SessionLOCAL))
849
const string varname(make_bookmark_name(plugin, name, flags));
852
result= (st_bookmark*) hash_search(&bookmark_hash,
853
(const unsigned char*) varname.c_str(), varname.size() - 1);
860
returns a bookmark for session-local variables, creating if neccessary.
861
returns null for non session-local variables.
862
Requires that a write lock is obtained on LOCK_system_variables_hash
864
static st_bookmark *register_var(const string &plugin, const char *name,
867
if (!(flags & PLUGIN_VAR_SessionLOCAL))
870
uint32_t size= 0, offset, new_size;
873
switch (flags & PLUGIN_VAR_TYPEMASK) {
874
case PLUGIN_VAR_BOOL:
875
size= ALIGN_SIZE(sizeof(bool));
878
size= ALIGN_SIZE(sizeof(int));
880
case PLUGIN_VAR_LONG:
881
size= ALIGN_SIZE(sizeof(long));
883
case PLUGIN_VAR_LONGLONG:
884
size= ALIGN_SIZE(sizeof(uint64_t));
887
size= ALIGN_SIZE(sizeof(char*));
895
if (!(result= find_bookmark(plugin, name, flags)))
897
const string varname(make_bookmark_name(plugin, name, flags));
899
result= static_cast<st_bookmark*>(plugin_mem_root.alloc_root(sizeof(struct st_bookmark) + varname.size() + 1));
900
memset(result->key, 0, varname.size()+1);
901
memcpy(result->key, varname.c_str(), varname.size());
902
result->name_len= varname.size() - 2;
905
assert(size && !(size & (size-1))); /* must be power of 2 */
907
offset= global_system_variables.dynamic_variables_size;
908
offset= (offset + size - 1) & ~(size - 1);
909
result->offset= (int) offset;
911
new_size= (offset + size + 63) & ~63;
913
if (new_size > global_variables_dynamic_size)
917
(char *)realloc(global_system_variables.dynamic_variables_ptr,
920
global_system_variables.dynamic_variables_ptr= tmpptr;
923
(char *)realloc(max_system_variables.dynamic_variables_ptr,
926
max_system_variables.dynamic_variables_ptr= tmpptr;
929
Clear the new variable value space. This is required for string
930
variables. If their value is non-NULL, it must point to a valid
933
memset(global_system_variables.dynamic_variables_ptr +
934
global_variables_dynamic_size, 0,
935
new_size - global_variables_dynamic_size);
936
memset(max_system_variables.dynamic_variables_ptr +
937
global_variables_dynamic_size, 0,
938
new_size - global_variables_dynamic_size);
939
global_variables_dynamic_size= new_size;
942
global_system_variables.dynamic_variables_head= offset;
943
max_system_variables.dynamic_variables_head= offset;
944
global_system_variables.dynamic_variables_size= offset + size;
945
max_system_variables.dynamic_variables_size= offset + size;
946
global_system_variables.dynamic_variables_version++;
947
max_system_variables.dynamic_variables_version++;
949
result->version= global_system_variables.dynamic_variables_version;
951
/* this should succeed because we have already checked if a dup exists */
952
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
954
fprintf(stderr, "failed to add placeholder to hash");
963
returns a pointer to the memory which holds the session-local variable or
964
a pointer to the global variable if session==null.
965
If required, will sync with global variables if the requested variable
966
has not yet been allocated in the current thread.
968
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
971
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
974
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
977
dynamic_variables_head points to the largest valid offset
979
if (!session->variables.dynamic_variables_ptr ||
980
(uint32_t)offset > session->variables.dynamic_variables_head)
984
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
987
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
988
global_variables_dynamic_size)))
990
session->variables.dynamic_variables_ptr= tmpptr;
993
pthread_mutex_lock(&LOCK_global_system_variables);
995
//safe_mutex_assert_owner(&LOCK_global_system_variables);
997
memcpy(session->variables.dynamic_variables_ptr +
998
session->variables.dynamic_variables_size,
999
global_system_variables.dynamic_variables_ptr +
1000
session->variables.dynamic_variables_size,
1001
global_system_variables.dynamic_variables_size -
1002
session->variables.dynamic_variables_size);
1005
now we need to iterate through any newly copied 'defaults'
1006
and if it is a string type with MEMALLOC flag, we need to strdup
1008
for (idx= 0; idx < bookmark_hash.records; idx++)
1010
sys_var_pluginvar *pi;
1012
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1014
if (v->version <= session->variables.dynamic_variables_version ||
1015
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1016
!(pi= var->cast_pluginvar()) ||
1017
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1020
/* Here we do anything special that may be required of the data types */
1022
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1023
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1025
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1026
*(int*)(pi->plugin_var + 1));
1027
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1028
*(int*)(pi->plugin_var + 1))))
1036
pthread_mutex_unlock(&LOCK_global_system_variables);
1038
session->variables.dynamic_variables_version=
1039
global_system_variables.dynamic_variables_version;
1040
session->variables.dynamic_variables_head=
1041
global_system_variables.dynamic_variables_head;
1042
session->variables.dynamic_variables_size=
1043
global_system_variables.dynamic_variables_size;
1045
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1047
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1050
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1052
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1055
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1057
return (int *)intern_sys_var_ptr(a_session, offset, true);
1060
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1062
return (long *)intern_sys_var_ptr(a_session, offset, true);
1065
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1067
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1070
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1072
return (char **)intern_sys_var_ptr(a_session, offset, true);
513
1075
void plugin_sessionvar_init(Session *session)
515
1077
session->variables.storage_engine= NULL;
516
cleanup_variables(&session->variables);
1078
cleanup_variables(session, &session->variables);
518
1080
session->variables= global_system_variables;
519
1081
session->variables.storage_engine= NULL;
556
1146
void plugin_sessionvar_cleanup(Session *session)
558
1148
unlock_variables(session, &session->variables);
559
cleanup_variables(&session->variables);
1149
cleanup_variables(session, &session->variables);
1154
@brief Free values of thread variables of a plugin.
1156
This must be called before a plugin is deleted. Otherwise its
1157
variables are no longer accessible and the value space is lost. Note
1158
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1161
@param[in] vars Chain of system variables of a plugin
1164
static void plugin_vars_free_values(sys_var *vars)
1167
for (sys_var *var= vars; var; var= var->getNext())
1169
sys_var_pluginvar *piv= var->cast_pluginvar();
1171
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1172
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1174
/* Free the string from global_system_variables. */
1175
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1184
bool sys_var_pluginvar::check_update_type(Item_result type)
1188
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1189
case PLUGIN_VAR_INT:
1190
case PLUGIN_VAR_LONG:
1191
case PLUGIN_VAR_LONGLONG:
1192
return type != INT_RESULT;
1193
case PLUGIN_VAR_STR:
1194
return type != STRING_RESULT;
1201
SHOW_TYPE sys_var_pluginvar::show_type()
1203
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1204
case PLUGIN_VAR_BOOL:
1205
return SHOW_MY_BOOL;
1206
case PLUGIN_VAR_INT:
1208
case PLUGIN_VAR_LONG:
1210
case PLUGIN_VAR_LONGLONG:
1211
return SHOW_LONGLONG;
1212
case PLUGIN_VAR_STR:
1213
return SHOW_CHAR_PTR;
1221
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
1223
assert(session || (type == OPT_GLOBAL));
1224
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1226
if (type == OPT_GLOBAL)
1229
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1231
return *(unsigned char**) (plugin_var+1);
1235
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1237
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1238
case PLUGIN_VAR_SessionLOCAL:
1239
return ((sessionvar_enum_t *)plugin_var)->typelib;
1247
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
1249
unsigned char* result;
1251
result= real_value_ptr(session, type);
1257
bool sys_var_pluginvar::check(Session *session, set_var *var)
1259
st_item_value_holder value;
1260
assert(is_readonly() || plugin_var->check);
1262
value.value_type= item_value_type;
1263
value.val_str= item_val_str;
1264
value.val_int= item_val_int;
1265
value.val_real= item_val_real;
1266
value.item= var->value;
1268
return is_readonly() ||
1269
plugin_var->check(session, plugin_var, &var->save_result, &value);
1273
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
1278
assert(is_readonly() || plugin_var->update);
1283
pthread_mutex_lock(&LOCK_global_system_variables);
1284
tgt= real_value_ptr(session, type);
1285
src= ((void **) (plugin_var + 1) + 1);
1287
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1289
if (type != OPT_GLOBAL)
1290
src= real_value_ptr(session, OPT_GLOBAL);
1292
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1293
case PLUGIN_VAR_INT:
1294
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1296
case PLUGIN_VAR_LONG:
1297
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1299
case PLUGIN_VAR_LONGLONG:
1300
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1302
case PLUGIN_VAR_BOOL:
1303
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1305
case PLUGIN_VAR_STR:
1306
src= &((sessionvar_str_t*) plugin_var)->def_val;
1313
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1314
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1315
session == current_session);
1317
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1319
plugin_var->update(session, plugin_var, tgt, src);
1320
pthread_mutex_unlock(&LOCK_global_system_variables);
1324
pthread_mutex_unlock(&LOCK_global_system_variables);
1325
plugin_var->update(session, plugin_var, tgt, src);
1330
bool sys_var_pluginvar::update(Session *session, set_var *var)
1334
assert(is_readonly() || plugin_var->update);
1336
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1337
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1338
session == current_session);
1343
pthread_mutex_lock(&LOCK_global_system_variables);
1344
tgt= real_value_ptr(session, var->type);
1346
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1348
/* variable we are updating has global scope, so we unlock after updating */
1349
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1350
pthread_mutex_unlock(&LOCK_global_system_variables);
1354
pthread_mutex_unlock(&LOCK_global_system_variables);
1355
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1361
#define OPTION_SET_LIMITS(type, options, opt) \
1362
options->var_type= type; \
1363
options->def_value= (opt)->def_val; \
1364
options->min_value= (opt)->min_val; \
1365
options->max_value= (opt)->max_val; \
1366
options->block_size= (long) (opt)->blk_sz
1369
void plugin_opt_set_limits(struct option *options,
1370
const drizzle_sys_var *opt)
1372
options->sub_size= 0;
1374
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1375
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1376
/* global system variables */
1377
case PLUGIN_VAR_INT:
1378
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1380
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1381
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1383
case PLUGIN_VAR_LONG:
1384
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1386
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1387
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1389
case PLUGIN_VAR_LONGLONG:
1390
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1392
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1393
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1395
case PLUGIN_VAR_BOOL:
1396
options->var_type= GET_BOOL;
1397
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1399
case PLUGIN_VAR_STR:
1400
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1401
GET_STR_ALLOC : GET_STR);
1402
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1404
/* threadlocal variables */
1405
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1406
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1408
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1409
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1411
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1412
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1414
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1415
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1417
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1418
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1420
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1421
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1423
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1424
options->var_type= GET_BOOL;
1425
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1427
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1428
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1429
GET_STR_ALLOC : GET_STR);
1430
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1435
options->arg_type= REQUIRED_ARG;
1436
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1437
options->arg_type= NO_ARG;
1438
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1439
options->arg_type= OPT_ARG;
1442
static int get_one_plugin_option(int, const struct option *, char *)
1448
static int construct_options(memory::Root *mem_root, module::Module *tmp,
1452
int localoptionid= 256;
1453
const string plugin_name(tmp->getManifest().name);
1455
size_t namelen= plugin_name.size(), optnamelen;
1458
int index= 0, offset= 0;
1459
drizzle_sys_var *opt, **plugin_option;
1462
string name(plugin_name);
1463
transform(name.begin(), name.end(), name.begin(), ::tolower);
1465
for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
1472
Two passes as the 2nd pass will take pointer addresses for use
1473
by my_getopt and register_var() in the first pass uses realloc
1476
for (plugin_option= tmp->getManifest().system_vars;
1477
plugin_option && *plugin_option; plugin_option++, index++)
1479
opt= *plugin_option;
1480
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1482
if (!(register_var(name, opt->name, opt->flags)))
1484
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1485
case PLUGIN_VAR_BOOL:
1486
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1488
case PLUGIN_VAR_INT:
1489
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1491
case PLUGIN_VAR_LONG:
1492
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1494
case PLUGIN_VAR_LONGLONG:
1495
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1497
case PLUGIN_VAR_STR:
1498
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1501
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1502
opt->flags, plugin_name.c_str());
1507
for (plugin_option= tmp->getManifest().system_vars;
1508
plugin_option && *plugin_option; plugin_option++, index++)
1510
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1511
case PLUGIN_VAR_BOOL:
1513
opt->check= check_func_bool;
1515
opt->update= update_func_bool;
1517
case PLUGIN_VAR_INT:
1519
opt->check= check_func_int;
1521
opt->update= update_func_int;
1523
case PLUGIN_VAR_LONG:
1525
opt->check= check_func_long;
1527
opt->update= update_func_long;
1529
case PLUGIN_VAR_LONGLONG:
1531
opt->check= check_func_int64_t;
1533
opt->update= update_func_int64_t;
1535
case PLUGIN_VAR_STR:
1537
opt->check= check_func_str;
1540
opt->update= update_func_str;
1541
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1543
opt->flags|= PLUGIN_VAR_READONLY;
1544
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1545
"to be read-only: string variable without "
1546
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1547
opt->name, plugin_name.c_str());
1552
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1553
opt->flags, plugin_name.c_str());
1557
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
1558
== PLUGIN_VAR_NOCMDOPT)
1563
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1564
plugin_name.c_str());
1568
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1570
optnamelen= strlen(opt->name);
1571
optname= (char*) mem_root->alloc_root(namelen + optnamelen + 2);
1572
sprintf(optname, "%s-%s", name.c_str(), opt->name);
1573
optnamelen= namelen + optnamelen + 1;
1577
/* this should not fail because register_var should create entry */
1578
if (!(v= find_bookmark(name, opt->name, opt->flags)))
1580
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1581
"in plugin '%s'."), opt->name, plugin_name.c_str());
1585
*(int*)(opt + 1)= offset= v->offset;
1587
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
1590
optname= (char*) mem_root->memdup_root(v->key + 1, (optnamelen= v->name_len) + 1);
1593
/* convert '_' to '-' */
1594
for (p= optname; *p; p++)
1598
options->name= optname;
1599
options->comment= opt->comment;
1600
options->app_type= opt;
1601
options->id= localoptionid++;
1603
plugin_opt_set_limits(options, opt);
1605
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
1606
options->value= options->u_max_value= (char**)
1607
(global_system_variables.dynamic_variables_ptr + offset);
1609
options->value= options->u_max_value= *(char***) (opt + 1);
1618
static option *construct_help_options(memory::Root *mem_root, module::Module *p)
1620
drizzle_sys_var **opt;
1622
uint32_t count= EXTRA_OPTIONS;
1624
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1626
opts= (option*)mem_root->alloc_root((sizeof(option) * count));
1630
memset(opts, 0, sizeof(option) * count);
1632
if (construct_options(mem_root, p, opts))
1638
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1640
plugin_sysvar_vec.push_back(var);
1643
void drizzle_del_plugin_sysvar()
1645
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1646
while(iter != plugin_sysvar_vec.end())
1651
plugin_sysvar_vec.clear();
566
1656
test_plugin_options()
567
1657
tmp_root temporary scratch space
568
1658
plugin internal plugin structure
1659
argc user supplied arguments
1660
argv user supplied arguments
569
1661
default_enabled default plugin enable status
571
1663
0 SUCCESS - plugin should be enabled/loaded
573
1665
Requires that a write-lock is held on LOCK_system_variables_hash
575
static int test_plugin_options(memory::Root *,
1667
static int test_plugin_options(memory::Root *module_root,
576
1668
module::Module *test_module,
1669
int *argc, char **argv,
577
1670
po::options_description &long_options)
1672
struct sys_var_chain chain= { NULL, NULL };
1673
drizzle_sys_var **opt;
1677
struct st_bookmark *var;
1678
uint32_t len, count= EXTRA_OPTIONS;
580
1680
if (test_module->getManifest().init_options != NULL)
582
string plugin_section_title("Options used by ");
583
plugin_section_title.append(test_module->getName());
584
po::options_description module_options(plugin_section_title);
1682
po::options_description module_options("Options used by plugins");
585
1683
module::option_context opt_ctx(test_module->getName(),
586
1684
module_options.add_options());
587
1685
test_module->getManifest().init_options(opt_ctx);
588
1686
long_options.add(module_options);
1692
for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
1697
if (count > EXTRA_OPTIONS || (*argc > 1))
1699
if (!(opts= (option*) module_root->alloc_root(sizeof(option) * count)))
1701
errmsg_printf(ERRMSG_LVL_ERROR,
1702
_("Out of memory for plugin '%s'."),
1703
test_module->getName().c_str());
1706
memset(opts, 0, sizeof(option) * count);
1708
if (construct_options(module_root, test_module, opts))
1710
errmsg_printf(ERRMSG_LVL_ERROR,
1711
_("Bad options for plugin '%s'."),
1712
test_module->getName().c_str());
1716
error= handle_options(argc, &argv, opts, get_one_plugin_option);
1717
(*argc)++; /* add back one for the program name */
1721
errmsg_printf(ERRMSG_LVL_ERROR,
1722
_("Parsing options for plugin '%s' failed."),
1723
test_module->getName().c_str());
1732
for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
1735
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1738
if ((var= find_bookmark(test_module->getName(), o->name, o->flags)))
1740
v= new sys_var_pluginvar(var->key + 1, o);
1744
len= test_module->getName().length() + strlen(o->name) + 2;
1745
string vname(test_module->getName());
1746
vname.push_back('-');
1747
vname.append(o->name);
1748
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1749
string::iterator p= vname.begin();
1750
while (p != vname.end())
1757
v= new sys_var_pluginvar(vname, o);
1759
assert(v); /* check that an object was actually constructed */
1761
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1763
Add to the chain of variables.
1764
Done like this for easier debugging so that the
1765
pointer to v is not lost on optimized builds.
1767
v->chain_sys_var(&chain);
1771
chain.last->setNext(NULL);
1772
if (mysql_add_sys_var_chain(chain.first, NULL))
1774
errmsg_printf(ERRMSG_LVL_ERROR,
1775
_("Plugin '%s' has conflicting system variables"),
1776
test_module->getName().c_str());
1779
test_module->system_vars= chain.first;
1786
my_cleanup_options(opts);