24
24
#include <algorithm>
27
#include <boost/program_options.hpp>
29
#include <drizzled/option.h>
30
#include <drizzled/internal/m_string.h>
32
#include <drizzled/plugin.h>
33
#include <drizzled/module/load_list.h>
34
#include <drizzled/module/library.h>
35
#include <drizzled/module/registry.h>
36
#include <drizzled/module/option_context.h>
37
#include <drizzled/sql_parse.h>
38
#include <drizzled/show.h>
39
#include <drizzled/cursor.h>
40
#include <drizzled/set_var.h>
41
#include <drizzled/session.h>
42
#include <drizzled/item/null.h>
43
#include <drizzled/error.h>
44
#include <drizzled/gettext.h>
45
#include <drizzled/errmsg_print.h>
46
#include <drizzled/strfunc.h>
47
#include <drizzled/pthread_globals.h>
48
#include <drizzled/util/tokenize.h>
50
#include <boost/foreach.hpp>
26
#include "drizzled/option.h"
27
#include "drizzled/my_hash.h"
28
#include "drizzled/internal/m_string.h"
30
#include "drizzled/plugin.h"
31
#include "drizzled/module/load_list.h"
32
#include "drizzled/module/library.h"
33
#include "drizzled/module/registry.h"
34
#include "drizzled/sql_parse.h"
35
#include "drizzled/show.h"
36
#include "drizzled/cursor.h"
37
#include "drizzled/set_var.h"
38
#include "drizzled/session.h"
39
#include "drizzled/item/null.h"
40
#include "drizzled/error.h"
41
#include "drizzled/gettext.h"
42
#include "drizzled/errmsg_print.h"
43
#include "drizzled/strfunc.h"
44
#include "drizzled/pthread_globals.h"
45
#include "drizzled/util/tokenize.h"
52
47
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
59
52
using namespace std;
61
54
/** These exist just to prevent symbols from being optimized out */
62
55
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
56
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
57
drizzled::module::Manifest *drizzled_builtins[]=
67
59
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;
66
class sys_var_pluginvar;
67
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
69
char *opt_plugin_add= NULL;
70
char *opt_plugin_remove= NULL;
71
char *opt_plugin_load= NULL;
72
char *opt_plugin_dir_ptr;
73
char opt_plugin_dir[FN_REFLEN];
74
const char *opt_plugin_load_default= PANDORA_PLUGIN_LIST;
82
75
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
85
77
/* Note that 'int version' must be the first field of every plugin
86
78
sub-structure (plugin->info).
106
stored in bookmark_hash, this structure is never removed from the
107
hash and is used to mark a single offset for a session local variable
108
even if plugins have been uninstalled and reinstalled, repeatedly.
109
This structure is allocated from plugin_mem_root.
111
The key format is as follows:
112
1 byte - variable type code
113
name_len bytes - variable name
122
120
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
126
sys_var class for access to all plugin variables visible to the user
128
class sys_var_pluginvar: public sys_var
131
module::Module *plugin;
132
drizzle_sys_var *plugin_var;
134
sys_var_pluginvar(const std::string name_arg,
135
drizzle_sys_var *plugin_var_arg)
136
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
137
sys_var_pluginvar *cast_pluginvar() { return this; }
138
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
139
bool check_type(sql_var_t type)
140
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
141
bool check_update_type(Item_result type);
142
SHOW_TYPE show_type();
143
unsigned char* real_value_ptr(Session *session, sql_var_t type);
144
TYPELIB* plugin_var_typelib(void);
145
unsigned char* value_ptr(Session *session, sql_var_t type,
146
const LEX_STRING *base);
147
bool check(Session *session, set_var *var);
148
bool check_default(sql_var_t)
149
{ return is_readonly(); }
150
void set_default(Session *session, sql_var_t);
151
bool update(Session *session, set_var *var);
132
156
static void plugin_prune_list(vector<string> &plugin_list,
133
157
const vector<string> &plugins_to_remove);
134
158
static bool plugin_load_list(module::Registry ®istry,
135
memory::Root *tmp_root,
159
memory::Root *tmp_root, int *argc, char **argv,
136
160
const set<string> &plugin_list,
137
po::options_description &long_options,
138
161
bool builtin= false);
139
162
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);
164
static void unlock_variables(Session *session, struct system_variables *vars);
165
static void cleanup_variables(Session *session, struct system_variables *vars);
166
static void plugin_vars_free_values(sys_var *vars);
168
/* declared in set_var.cc */
169
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
170
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
171
const std::string &name, int64_t val);
173
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
174
const char *name, int64_t val)
176
const std::string name_str(name);
177
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
180
/****************************************************************************
181
Value type thunks, allows the C world to play in the C++ world
182
****************************************************************************/
184
static int item_value_type(drizzle_value *value)
186
switch (((st_item_value_holder*)value)->item->result_type()) {
188
return DRIZZLE_VALUE_TYPE_INT;
190
return DRIZZLE_VALUE_TYPE_REAL;
192
return DRIZZLE_VALUE_TYPE_STRING;
196
static const char *item_val_str(drizzle_value *value,
197
char *buffer, int *length)
199
String str(buffer, *length, system_charset_info), *res;
200
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
202
*length= res->length();
203
if (res->c_ptr_quick() == buffer)
207
Lets be nice and create a temporary string since the
210
return current_session->strmake(res->c_ptr_quick(), res->length());
214
static int item_val_int(drizzle_value *value, int64_t *buf)
216
Item *item= ((st_item_value_holder*)value)->item;
217
*buf= item->val_int();
224
static int item_val_real(drizzle_value *value, double *buf)
226
Item *item= ((st_item_value_holder*)value)->item;
227
*buf= item->val_real();
145
234
/****************************************************************************
491
556
unlock_variables(NULL, &global_system_variables);
492
557
unlock_variables(NULL, &max_system_variables);
494
cleanup_variables(&global_system_variables);
495
cleanup_variables(&max_system_variables);
559
cleanup_variables(NULL, &global_system_variables);
560
cleanup_variables(NULL, &max_system_variables);
500
565
/* Dispose of the memory */
567
hash_free(&bookmark_hash);
501
568
plugin_mem_root.free_root(MYF(0));
503
570
global_variables_dynamic_size= 0;
573
/****************************************************************************
574
Internal type declarations for variables support
575
****************************************************************************/
577
#undef DRIZZLE_SYSVAR_NAME
578
#define DRIZZLE_SYSVAR_NAME(name) name
579
#define PLUGIN_VAR_TYPEMASK 0x007f
581
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
583
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
584
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
585
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
586
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
588
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
589
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
591
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
592
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
593
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
594
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
595
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
596
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
598
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
599
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
600
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
601
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
602
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
603
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
605
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
608
/****************************************************************************
609
default variable data check and update functions
610
****************************************************************************/
612
static int check_func_bool(Session *, drizzle_sys_var *var,
613
void *save, drizzle_value *value)
615
char buff[STRING_BUFFER_USUAL_SIZE];
616
const char *strvalue= "NULL", *str;
620
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
622
length= sizeof(buff);
623
if (!(str= value->val_str(value, buff, &length)) ||
624
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
633
if (value->val_int(value, &tmp) < 0)
637
internal::llstr(tmp, buff);
643
*(int*)save= -result;
646
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
651
static int check_func_int(Session *session, drizzle_sys_var *var,
652
void *save, drizzle_value *value)
656
struct option options;
657
value->val_int(value, &tmp);
658
plugin_opt_set_limits(&options, var);
660
if (var->flags & PLUGIN_VAR_UNSIGNED)
661
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
664
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
666
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
667
var->name, (int64_t) tmp);
671
static int check_func_long(Session *session, drizzle_sys_var *var,
672
void *save, drizzle_value *value)
676
struct option options;
677
value->val_int(value, &tmp);
678
plugin_opt_set_limits(&options, var);
680
if (var->flags & PLUGIN_VAR_UNSIGNED)
681
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
684
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
686
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
687
var->name, (int64_t) tmp);
691
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
692
void *save, drizzle_value *value)
696
struct option options;
697
value->val_int(value, &tmp);
698
plugin_opt_set_limits(&options, var);
700
if (var->flags & PLUGIN_VAR_UNSIGNED)
701
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
704
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
706
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
707
var->name, (int64_t) tmp);
710
static int check_func_str(Session *session, drizzle_sys_var *,
711
void *save, drizzle_value *value)
713
char buff[STRING_BUFFER_USUAL_SIZE];
717
length= sizeof(buff);
718
if ((str= value->val_str(value, buff, &length)))
719
str= session->strmake(str, length);
720
*(const char**)save= str;
725
static void update_func_bool(Session *, drizzle_sys_var *,
726
void *tgt, const void *save)
728
*(bool *) tgt= *(int *) save ? 1 : 0;
732
static void update_func_int(Session *, drizzle_sys_var *,
733
void *tgt, const void *save)
735
*(int *)tgt= *(int *) save;
739
static void update_func_long(Session *, drizzle_sys_var *,
740
void *tgt, const void *save)
742
*(long *)tgt= *(long *) save;
746
static void update_func_int64_t(Session *, drizzle_sys_var *,
747
void *tgt, const void *save)
749
*(int64_t *)tgt= *(uint64_t *) save;
753
static void update_func_str(Session *, drizzle_sys_var *var,
754
void *tgt, const void *save)
756
char *old= *(char **) tgt;
757
*(char **)tgt= *(char **) save;
758
if (var->flags & PLUGIN_VAR_MEMALLOC)
760
*(char **)tgt= strdup(*(char **) save);
763
* There isn't a _really_ good thing to do here until this whole set_var
764
* mess gets redesigned
767
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
507
773
/****************************************************************************
508
774
System Variables support
509
775
****************************************************************************/
778
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
781
sys_var_pluginvar *pi= NULL;
782
module::Module *module;
784
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
785
if ((var= intern_find_sys_var(str, length, false)) &&
786
(pi= var->cast_pluginvar()))
788
pthread_rwlock_unlock(&LOCK_system_variables_hash);
789
if (!(module= pi->plugin))
790
var= NULL; /* failed to lock it, it must be uninstalling */
791
else if (module->isInited == false)
797
pthread_rwlock_unlock(&LOCK_system_variables_hash);
800
If the variable exists but the plugin it is associated with is not ready
801
then the intern_plugin_lock did not raise an error, so we do it here.
804
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
808
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
810
/* Embed the flags into the first char of the string */
811
string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
812
varname.append(plugin);
813
varname.push_back('_');
814
varname.append(name);
816
for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
827
called by register_var, construct_options and test_plugin_options.
828
Returns the 'bookmark' for the named variable.
829
LOCK_system_variables_hash should be at least read locked
831
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
833
st_bookmark *result= NULL;
835
if (!(flags & PLUGIN_VAR_SessionLOCAL))
838
const string varname(make_bookmark_name(plugin, name, flags));
841
result= (st_bookmark*) hash_search(&bookmark_hash,
842
(const unsigned char*) varname.c_str(), varname.size() - 1);
849
returns a bookmark for session-local variables, creating if neccessary.
850
returns null for non session-local variables.
851
Requires that a write lock is obtained on LOCK_system_variables_hash
853
static st_bookmark *register_var(const string &plugin, const char *name,
856
if (!(flags & PLUGIN_VAR_SessionLOCAL))
859
uint32_t size= 0, offset, new_size;
862
switch (flags & PLUGIN_VAR_TYPEMASK) {
863
case PLUGIN_VAR_BOOL:
864
size= ALIGN_SIZE(sizeof(bool));
867
size= ALIGN_SIZE(sizeof(int));
869
case PLUGIN_VAR_LONG:
870
size= ALIGN_SIZE(sizeof(long));
872
case PLUGIN_VAR_LONGLONG:
873
size= ALIGN_SIZE(sizeof(uint64_t));
876
size= ALIGN_SIZE(sizeof(char*));
884
if (!(result= find_bookmark(plugin, name, flags)))
886
const string varname(make_bookmark_name(plugin, name, flags));
888
result= static_cast<st_bookmark*>(plugin_mem_root.alloc_root(sizeof(struct st_bookmark) + varname.size() + 1));
889
memset(result->key, 0, varname.size()+1);
890
memcpy(result->key, varname.c_str(), varname.size());
891
result->name_len= varname.size() - 2;
894
assert(size && !(size & (size-1))); /* must be power of 2 */
896
offset= global_system_variables.dynamic_variables_size;
897
offset= (offset + size - 1) & ~(size - 1);
898
result->offset= (int) offset;
900
new_size= (offset + size + 63) & ~63;
902
if (new_size > global_variables_dynamic_size)
906
(char *)realloc(global_system_variables.dynamic_variables_ptr,
909
global_system_variables.dynamic_variables_ptr= tmpptr;
912
(char *)realloc(max_system_variables.dynamic_variables_ptr,
915
max_system_variables.dynamic_variables_ptr= tmpptr;
918
Clear the new variable value space. This is required for string
919
variables. If their value is non-NULL, it must point to a valid
922
memset(global_system_variables.dynamic_variables_ptr +
923
global_variables_dynamic_size, 0,
924
new_size - global_variables_dynamic_size);
925
memset(max_system_variables.dynamic_variables_ptr +
926
global_variables_dynamic_size, 0,
927
new_size - global_variables_dynamic_size);
928
global_variables_dynamic_size= new_size;
931
global_system_variables.dynamic_variables_head= offset;
932
max_system_variables.dynamic_variables_head= offset;
933
global_system_variables.dynamic_variables_size= offset + size;
934
max_system_variables.dynamic_variables_size= offset + size;
935
global_system_variables.dynamic_variables_version++;
936
max_system_variables.dynamic_variables_version++;
938
result->version= global_system_variables.dynamic_variables_version;
940
/* this should succeed because we have already checked if a dup exists */
941
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
943
fprintf(stderr, "failed to add placeholder to hash");
952
returns a pointer to the memory which holds the session-local variable or
953
a pointer to the global variable if session==null.
954
If required, will sync with global variables if the requested variable
955
has not yet been allocated in the current thread.
957
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
960
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
963
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
966
dynamic_variables_head points to the largest valid offset
968
if (!session->variables.dynamic_variables_ptr ||
969
(uint32_t)offset > session->variables.dynamic_variables_head)
973
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
976
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
977
global_variables_dynamic_size)))
979
session->variables.dynamic_variables_ptr= tmpptr;
982
pthread_mutex_lock(&LOCK_global_system_variables);
984
//safe_mutex_assert_owner(&LOCK_global_system_variables);
986
memcpy(session->variables.dynamic_variables_ptr +
987
session->variables.dynamic_variables_size,
988
global_system_variables.dynamic_variables_ptr +
989
session->variables.dynamic_variables_size,
990
global_system_variables.dynamic_variables_size -
991
session->variables.dynamic_variables_size);
994
now we need to iterate through any newly copied 'defaults'
995
and if it is a string type with MEMALLOC flag, we need to strdup
997
for (idx= 0; idx < bookmark_hash.records; idx++)
999
sys_var_pluginvar *pi;
1001
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1003
if (v->version <= session->variables.dynamic_variables_version ||
1004
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1005
!(pi= var->cast_pluginvar()) ||
1006
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1009
/* Here we do anything special that may be required of the data types */
1011
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1012
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1014
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1015
*(int*)(pi->plugin_var + 1));
1016
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1017
*(int*)(pi->plugin_var + 1))))
1025
pthread_mutex_unlock(&LOCK_global_system_variables);
1027
session->variables.dynamic_variables_version=
1028
global_system_variables.dynamic_variables_version;
1029
session->variables.dynamic_variables_head=
1030
global_system_variables.dynamic_variables_head;
1031
session->variables.dynamic_variables_size=
1032
global_system_variables.dynamic_variables_size;
1034
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1036
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1039
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1041
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1044
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1046
return (int *)intern_sys_var_ptr(a_session, offset, true);
1049
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1051
return (long *)intern_sys_var_ptr(a_session, offset, true);
1054
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1056
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1059
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1061
return (char **)intern_sys_var_ptr(a_session, offset, true);
513
1064
void plugin_sessionvar_init(Session *session)
515
1066
session->variables.storage_engine= NULL;
516
cleanup_variables(&session->variables);
1067
cleanup_variables(session, &session->variables);
518
1069
session->variables= global_system_variables;
519
1070
session->variables.storage_engine= NULL;
556
1135
void plugin_sessionvar_cleanup(Session *session)
558
1137
unlock_variables(session, &session->variables);
559
cleanup_variables(&session->variables);
1138
cleanup_variables(session, &session->variables);
1143
@brief Free values of thread variables of a plugin.
1145
This must be called before a plugin is deleted. Otherwise its
1146
variables are no longer accessible and the value space is lost. Note
1147
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1150
@param[in] vars Chain of system variables of a plugin
1153
static void plugin_vars_free_values(sys_var *vars)
1156
for (sys_var *var= vars; var; var= var->getNext())
1158
sys_var_pluginvar *piv= var->cast_pluginvar();
1160
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1161
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1163
/* Free the string from global_system_variables. */
1164
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1173
bool sys_var_pluginvar::check_update_type(Item_result type)
1177
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1178
case PLUGIN_VAR_INT:
1179
case PLUGIN_VAR_LONG:
1180
case PLUGIN_VAR_LONGLONG:
1181
return type != INT_RESULT;
1182
case PLUGIN_VAR_STR:
1183
return type != STRING_RESULT;
1190
SHOW_TYPE sys_var_pluginvar::show_type()
1192
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1193
case PLUGIN_VAR_BOOL:
1194
return SHOW_MY_BOOL;
1195
case PLUGIN_VAR_INT:
1197
case PLUGIN_VAR_LONG:
1199
case PLUGIN_VAR_LONGLONG:
1200
return SHOW_LONGLONG;
1201
case PLUGIN_VAR_STR:
1202
return SHOW_CHAR_PTR;
1210
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
1212
assert(session || (type == OPT_GLOBAL));
1213
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1215
if (type == OPT_GLOBAL)
1218
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1220
return *(unsigned char**) (plugin_var+1);
1224
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1226
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1227
case PLUGIN_VAR_SessionLOCAL:
1228
return ((sessionvar_enum_t *)plugin_var)->typelib;
1236
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
1238
unsigned char* result;
1240
result= real_value_ptr(session, type);
1246
bool sys_var_pluginvar::check(Session *session, set_var *var)
1248
st_item_value_holder value;
1249
assert(is_readonly() || plugin_var->check);
1251
value.value_type= item_value_type;
1252
value.val_str= item_val_str;
1253
value.val_int= item_val_int;
1254
value.val_real= item_val_real;
1255
value.item= var->value;
1257
return is_readonly() ||
1258
plugin_var->check(session, plugin_var, &var->save_result, &value);
1262
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
1267
assert(is_readonly() || plugin_var->update);
1272
pthread_mutex_lock(&LOCK_global_system_variables);
1273
tgt= real_value_ptr(session, type);
1274
src= ((void **) (plugin_var + 1) + 1);
1276
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1278
if (type != OPT_GLOBAL)
1279
src= real_value_ptr(session, OPT_GLOBAL);
1281
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1282
case PLUGIN_VAR_INT:
1283
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1285
case PLUGIN_VAR_LONG:
1286
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1288
case PLUGIN_VAR_LONGLONG:
1289
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1291
case PLUGIN_VAR_BOOL:
1292
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1294
case PLUGIN_VAR_STR:
1295
src= &((sessionvar_str_t*) plugin_var)->def_val;
1302
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1303
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1304
session == current_session);
1306
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1308
plugin_var->update(session, plugin_var, tgt, src);
1309
pthread_mutex_unlock(&LOCK_global_system_variables);
1313
pthread_mutex_unlock(&LOCK_global_system_variables);
1314
plugin_var->update(session, plugin_var, tgt, src);
1319
bool sys_var_pluginvar::update(Session *session, set_var *var)
1323
assert(is_readonly() || plugin_var->update);
1325
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1326
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1327
session == current_session);
1332
pthread_mutex_lock(&LOCK_global_system_variables);
1333
tgt= real_value_ptr(session, var->type);
1335
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1337
/* variable we are updating has global scope, so we unlock after updating */
1338
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1339
pthread_mutex_unlock(&LOCK_global_system_variables);
1343
pthread_mutex_unlock(&LOCK_global_system_variables);
1344
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1350
#define OPTION_SET_LIMITS(type, options, opt) \
1351
options->var_type= type; \
1352
options->def_value= (opt)->def_val; \
1353
options->min_value= (opt)->min_val; \
1354
options->max_value= (opt)->max_val; \
1355
options->block_size= (long) (opt)->blk_sz
1358
void plugin_opt_set_limits(struct option *options,
1359
const drizzle_sys_var *opt)
1361
options->sub_size= 0;
1363
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1364
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1365
/* global system variables */
1366
case PLUGIN_VAR_INT:
1367
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1369
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1370
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1372
case PLUGIN_VAR_LONG:
1373
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1375
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1376
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1378
case PLUGIN_VAR_LONGLONG:
1379
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1381
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1382
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1384
case PLUGIN_VAR_BOOL:
1385
options->var_type= GET_BOOL;
1386
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1388
case PLUGIN_VAR_STR:
1389
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1390
GET_STR_ALLOC : GET_STR);
1391
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1393
/* threadlocal variables */
1394
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1395
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1397
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1398
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1400
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1401
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1403
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1404
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1406
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1407
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1409
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1410
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1412
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1413
options->var_type= GET_BOOL;
1414
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1416
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1417
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1418
GET_STR_ALLOC : GET_STR);
1419
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1424
options->arg_type= REQUIRED_ARG;
1425
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1426
options->arg_type= NO_ARG;
1427
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1428
options->arg_type= OPT_ARG;
1431
static int get_one_plugin_option(int, const struct option *, char *)
1437
static int construct_options(memory::Root *mem_root, module::Module *tmp,
1441
int localoptionid= 256;
1442
const string plugin_name(tmp->getManifest().name);
1444
size_t namelen= plugin_name.size(), optnamelen;
1447
int index= 0, offset= 0;
1448
drizzle_sys_var *opt, **plugin_option;
1451
string name(plugin_name);
1452
transform(name.begin(), name.end(), name.begin(), ::tolower);
1454
for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
1461
Two passes as the 2nd pass will take pointer addresses for use
1462
by my_getopt and register_var() in the first pass uses realloc
1465
for (plugin_option= tmp->getManifest().system_vars;
1466
plugin_option && *plugin_option; plugin_option++, index++)
1468
opt= *plugin_option;
1469
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1471
if (!(register_var(name, opt->name, opt->flags)))
1473
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1474
case PLUGIN_VAR_BOOL:
1475
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1477
case PLUGIN_VAR_INT:
1478
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1480
case PLUGIN_VAR_LONG:
1481
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1483
case PLUGIN_VAR_LONGLONG:
1484
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1486
case PLUGIN_VAR_STR:
1487
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1490
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1491
opt->flags, plugin_name.c_str());
1496
for (plugin_option= tmp->getManifest().system_vars;
1497
plugin_option && *plugin_option; plugin_option++, index++)
1499
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1500
case PLUGIN_VAR_BOOL:
1502
opt->check= check_func_bool;
1504
opt->update= update_func_bool;
1506
case PLUGIN_VAR_INT:
1508
opt->check= check_func_int;
1510
opt->update= update_func_int;
1512
case PLUGIN_VAR_LONG:
1514
opt->check= check_func_long;
1516
opt->update= update_func_long;
1518
case PLUGIN_VAR_LONGLONG:
1520
opt->check= check_func_int64_t;
1522
opt->update= update_func_int64_t;
1524
case PLUGIN_VAR_STR:
1526
opt->check= check_func_str;
1529
opt->update= update_func_str;
1530
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1532
opt->flags|= PLUGIN_VAR_READONLY;
1533
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1534
"to be read-only: string variable without "
1535
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1536
opt->name, plugin_name.c_str());
1541
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1542
opt->flags, plugin_name.c_str());
1546
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
1547
== PLUGIN_VAR_NOCMDOPT)
1552
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1553
plugin_name.c_str());
1557
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1559
optnamelen= strlen(opt->name);
1560
optname= (char*) mem_root->alloc_root(namelen + optnamelen + 2);
1561
sprintf(optname, "%s-%s", name.c_str(), opt->name);
1562
optnamelen= namelen + optnamelen + 1;
1566
/* this should not fail because register_var should create entry */
1567
if (!(v= find_bookmark(name, opt->name, opt->flags)))
1569
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1570
"in plugin '%s'."), opt->name, plugin_name.c_str());
1574
*(int*)(opt + 1)= offset= v->offset;
1576
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
1579
optname= (char*) mem_root->memdup_root(v->key + 1, (optnamelen= v->name_len) + 1);
1582
/* convert '_' to '-' */
1583
for (p= optname; *p; p++)
1587
options->name= optname;
1588
options->comment= opt->comment;
1589
options->app_type= opt;
1590
options->id= localoptionid++;
1592
plugin_opt_set_limits(options, opt);
1594
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
1595
options->value= options->u_max_value= (char**)
1596
(global_system_variables.dynamic_variables_ptr + offset);
1598
options->value= options->u_max_value= *(char***) (opt + 1);
1607
static option *construct_help_options(memory::Root *mem_root, module::Module *p)
1609
drizzle_sys_var **opt;
1611
uint32_t count= EXTRA_OPTIONS;
1613
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1615
opts= (option*)mem_root->alloc_root((sizeof(option) * count));
1619
memset(opts, 0, sizeof(option) * count);
1621
if (construct_options(mem_root, p, opts))
1627
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1629
plugin_sysvar_vec.push_back(var);
1632
void drizzle_del_plugin_sysvar()
1634
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1635
while(iter != plugin_sysvar_vec.end())
1640
plugin_sysvar_vec.clear();
566
1645
test_plugin_options()
567
1646
tmp_root temporary scratch space
568
1647
plugin internal plugin structure
1648
argc user supplied arguments
1649
argv user supplied arguments
569
1650
default_enabled default plugin enable status
571
1652
0 SUCCESS - plugin should be enabled/loaded
573
1654
Requires that a write-lock is held on LOCK_system_variables_hash
575
static int test_plugin_options(memory::Root *,
576
module::Module *test_module,
577
po::options_description &long_options)
1656
static int test_plugin_options(memory::Root *tmp_root, module::Module *tmp,
1657
int *argc, char **argv)
580
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);
585
module::option_context opt_ctx(test_module->getName(),
586
module_options.add_options());
587
test_module->getManifest().init_options(opt_ctx);
588
long_options.add(module_options);
1659
struct sys_var_chain chain= { NULL, NULL };
1660
drizzle_sys_var **opt;
1664
struct st_bookmark *var;
1665
uint32_t len, count= EXTRA_OPTIONS;
1667
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1671
if (count > EXTRA_OPTIONS || (*argc > 1))
1673
if (!(opts= (option*) tmp_root->alloc_root(sizeof(option) * count)))
1675
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
1678
memset(opts, 0, sizeof(option) * count);
1680
if (construct_options(tmp_root, tmp, opts))
1682
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
1686
error= handle_options(argc, &argv, opts, get_one_plugin_option);
1687
(*argc)++; /* add back one for the program name */
1691
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
1692
tmp->getName().c_str());
1700
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1703
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1706
if ((var= find_bookmark(tmp->getName(), o->name, o->flags)))
1707
v= new sys_var_pluginvar(var->key + 1, o);
1710
len= tmp->getName().length() + strlen(o->name) + 2;
1711
string vname(tmp->getName());
1712
vname.push_back('-');
1713
vname.append(o->name);
1714
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1715
string::iterator p= vname.begin();
1716
while (p != vname.end())
1723
v= new sys_var_pluginvar(vname, o);
1725
assert(v); /* check that an object was actually constructed */
1727
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1729
Add to the chain of variables.
1730
Done like this for easier debugging so that the
1731
pointer to v is not lost on optimized builds.
1733
v->chain_sys_var(&chain);
1737
chain.last->setNext(NULL);
1738
if (mysql_add_sys_var_chain(chain.first, NULL))
1740
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
1741
tmp->getName().c_str());
1744
tmp->system_vars= chain.first;
1751
my_cleanup_options(opts);