12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
#include "config.h"
24
23
#include <algorithm>
27
#include <boost/program_options.hpp>
29
#include "drizzled/option.h"
25
#include "drizzled/my_getopt.h"
26
#include "drizzled/my_hash.h"
30
27
#include "drizzled/internal/m_string.h"
32
29
#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"
30
#include "drizzled/plugin/load_list.h"
37
31
#include "drizzled/sql_parse.h"
38
32
#include "drizzled/show.h"
39
33
#include "drizzled/cursor.h"
40
34
#include "drizzled/set_var.h"
41
35
#include "drizzled/session.h"
42
36
#include "drizzled/item/null.h"
37
#include "drizzled/plugin/registry.h"
43
38
#include "drizzled/error.h"
44
39
#include "drizzled/gettext.h"
45
40
#include "drizzled/errmsg_print.h"
41
#include "drizzled/plugin/library.h"
46
42
#include "drizzled/strfunc.h"
47
43
#include "drizzled/pthread_globals.h"
48
44
#include "drizzled/util/tokenize.h"
50
#include <boost/foreach.hpp>
52
46
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
59
51
using namespace std;
61
/** These exist just to prevent symbols from being optimized out */
62
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
drizzled::module::Manifest *drizzled_builtins[]=
67
PANDORA_BUILTIN_SYMBOLS_LIST, NULL
69
drizzled::module::Manifest *drizzled_load_builtins[]=
71
PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
53
typedef drizzled::plugin::Manifest drizzled_builtin_plugin[];
54
extern drizzled_builtin_plugin PANDORA_BUILTIN_LIST;
55
static drizzled::plugin::Manifest *drizzled_builtins[]=
57
PANDORA_BUILTIN_LIST, NULL
78
typedef vector<string> PluginOptions;
79
static PluginOptions opt_plugin_load;
80
static PluginOptions opt_plugin_add;
81
static PluginOptions opt_plugin_remove;
82
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
64
class sys_var_pluginvar;
65
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
67
char *opt_plugin_add= NULL;
68
char *opt_plugin_remove= NULL;
69
char *opt_plugin_load= NULL;
70
char *opt_plugin_dir_ptr;
71
char opt_plugin_dir[FN_REFLEN];
72
const char *opt_plugin_load_default= PANDORA_PLUGIN_LIST;
85
74
/* Note that 'int version' must be the first field of every plugin
86
75
sub-structure (plugin->info).
103
stored in bookmark_hash, this structure is never removed from the
104
hash and is used to mark a single offset for a session local variable
105
even if plugins have been uninstalled and reinstalled, repeatedly.
106
This structure is allocated from plugin_mem_root.
108
The key format is as follows:
109
1 byte - variable type code
110
name_len bytes - variable name
122
117
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
123
sys_var class for access to all plugin variables visible to the user
125
class sys_var_pluginvar: public sys_var
128
plugin::Module *plugin;
129
drizzle_sys_var *plugin_var;
131
sys_var_pluginvar(const std::string name_arg,
132
drizzle_sys_var *plugin_var_arg)
133
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
134
sys_var_pluginvar *cast_pluginvar() { return this; }
135
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
136
bool check_type(sql_var_t type)
137
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
138
bool check_update_type(Item_result type);
139
SHOW_TYPE show_type();
140
unsigned char* real_value_ptr(Session *session, sql_var_t type);
141
TYPELIB* plugin_var_typelib(void);
142
unsigned char* value_ptr(Session *session, sql_var_t type,
143
const LEX_STRING *base);
144
bool check(Session *session, set_var *var);
145
bool check_default(sql_var_t)
146
{ return is_readonly(); }
147
void set_default(Session *session, sql_var_t);
148
bool update(Session *session, set_var *var);
132
153
static void plugin_prune_list(vector<string> &plugin_list,
133
154
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);
155
static bool plugin_load_list(plugin::Registry ®istry,
156
memory::Root *tmp_root, int *argc, char **argv,
157
const vector<string> &plugin_list);
158
static int test_plugin_options(memory::Root *, plugin::Module *,
160
static void unlock_variables(Session *session, struct system_variables *vars);
161
static void cleanup_variables(Session *session, struct system_variables *vars);
162
static void plugin_vars_free_values(sys_var *vars);
144
164
/* declared in set_var.cc */
145
165
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
166
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
167
const std::string &name, int64_t val);
169
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
170
const char *name, int64_t val)
172
const std::string name_str(name);
173
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
176
/****************************************************************************
177
Value type thunks, allows the C world to play in the C++ world
178
****************************************************************************/
180
static int item_value_type(drizzle_value *value)
182
switch (((st_item_value_holder*)value)->item->result_type()) {
184
return DRIZZLE_VALUE_TYPE_INT;
186
return DRIZZLE_VALUE_TYPE_REAL;
188
return DRIZZLE_VALUE_TYPE_STRING;
192
static const char *item_val_str(drizzle_value *value,
193
char *buffer, int *length)
195
String str(buffer, *length, system_charset_info), *res;
196
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
198
*length= res->length();
199
if (res->c_ptr_quick() == buffer)
203
Lets be nice and create a temporary string since the
206
return current_session->strmake(res->c_ptr_quick(), res->length());
210
static int item_val_int(drizzle_value *value, int64_t *buf)
212
Item *item= ((st_item_value_holder*)value)->item;
213
*buf= item->val_int();
220
static int item_val_real(drizzle_value *value, double *buf)
222
Item *item= ((st_item_value_holder*)value)->item;
223
*buf= item->val_real();
148
230
/****************************************************************************
295
379
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)
381
bool plugin_init(plugin::Registry ®istry,
382
int *argc, char **argv,
300
memory::Root tmp_root(4096);
385
plugin::Manifest **builtins;
386
plugin::Manifest *manifest;
387
plugin::Module *module;
388
memory::Root tmp_root;
393
init_alloc_root(&plugin_mem_root, 4096);
394
init_alloc_root(&tmp_root, 4096);
396
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
397
get_bookmark_hash_key, NULL, HASH_UNIQUE))
399
free_root(&tmp_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);
407
First we register builtin plugins
409
for (builtins= drizzled_builtins; *builtins; builtins++)
412
if (manifest->name != NULL)
414
module= new (std::nothrow) plugin::Module(manifest);
418
free_root(&tmp_root, MYF(memory::MARK_BLOCKS_FREE));
419
if (test_plugin_options(&tmp_root, module, argc, argv))
422
registry.add(module);
424
plugin_initialize_vars(module);
428
if (plugin_initialize(registry, module))
430
free_root(&tmp_root, MYF(0));
313
438
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));
353
/* Uniquify the list */
354
const set<string> plugin_list_set(opt_plugin_load.begin(),
355
opt_plugin_load.end());
439
vector<string> plugin_list;
442
tokenize(opt_plugin_load, plugin_list, ",", true);
446
tokenize(opt_plugin_load_default, plugin_list, ",", true);
450
tokenize(opt_plugin_add, plugin_list, ",", true);
453
if (opt_plugin_remove)
455
vector<string> plugins_to_remove;
456
tokenize(opt_plugin_remove, plugins_to_remove, ",", true);
457
plugin_prune_list(plugin_list, plugins_to_remove);
357
460
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
461
load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
362
tmp_root.free_root(MYF(0));
465
free_root(&tmp_root, MYF(0));
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
471
free_root(&tmp_root, MYF(0));
374
476
Now we initialize all remaining plugins
376
std::map<std::string, module::Module *>::const_iterator modules=
478
std::map<std::string, plugin::Module *>::const_iterator modules=
377
479
registry.getModulesMap().begin();
379
481
while (modules != registry.getModulesMap().end())
381
module::Module *module= (*modules).second;
483
module= (*modules).second;
383
485
if (module->isInited == false)
487
plugin_initialize_vars(module);
385
489
if (plugin_initialize(registry, module))
387
registry.remove(module);
490
delete_module(registry, module);
394
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
396
value.second->prime();
495
free_root(&tmp_root, MYF(0));
482
577
unlock_variables(NULL, &global_system_variables);
483
578
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
580
cleanup_variables(NULL, &global_system_variables);
581
cleanup_variables(NULL, &max_system_variables);
491
586
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
588
hash_free(&bookmark_hash);
589
free_root(&plugin_mem_root, MYF(0));
494
591
global_variables_dynamic_size= 0;
594
/****************************************************************************
595
Internal type declarations for variables support
596
****************************************************************************/
598
#undef DRIZZLE_SYSVAR_NAME
599
#define DRIZZLE_SYSVAR_NAME(name) name
600
#define PLUGIN_VAR_TYPEMASK 0x007f
602
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
604
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
605
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
606
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
607
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
609
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
610
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
612
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
613
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
614
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
615
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
616
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
617
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
619
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
620
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
621
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
622
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
623
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
624
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
626
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
629
/****************************************************************************
630
default variable data check and update functions
631
****************************************************************************/
633
static int check_func_bool(Session *, drizzle_sys_var *var,
634
void *save, drizzle_value *value)
636
char buff[STRING_BUFFER_USUAL_SIZE];
637
const char *strvalue= "NULL", *str;
641
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
643
length= sizeof(buff);
644
if (!(str= value->val_str(value, buff, &length)) ||
645
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
654
if (value->val_int(value, &tmp) < 0)
658
internal::llstr(tmp, buff);
664
*(int*)save= -result;
667
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
672
static int check_func_int(Session *session, drizzle_sys_var *var,
673
void *save, drizzle_value *value)
677
struct my_option options;
678
value->val_int(value, &tmp);
679
plugin_opt_set_limits(&options, var);
681
if (var->flags & PLUGIN_VAR_UNSIGNED)
682
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
685
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
687
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
688
var->name, (int64_t) tmp);
692
static int check_func_long(Session *session, drizzle_sys_var *var,
693
void *save, drizzle_value *value)
697
struct my_option options;
698
value->val_int(value, &tmp);
699
plugin_opt_set_limits(&options, var);
701
if (var->flags & PLUGIN_VAR_UNSIGNED)
702
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
705
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
707
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
708
var->name, (int64_t) tmp);
712
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
713
void *save, drizzle_value *value)
717
struct my_option options;
718
value->val_int(value, &tmp);
719
plugin_opt_set_limits(&options, var);
721
if (var->flags & PLUGIN_VAR_UNSIGNED)
722
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
725
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
727
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
728
var->name, (int64_t) tmp);
731
static int check_func_str(Session *session, drizzle_sys_var *,
732
void *save, drizzle_value *value)
734
char buff[STRING_BUFFER_USUAL_SIZE];
738
length= sizeof(buff);
739
if ((str= value->val_str(value, buff, &length)))
740
str= session->strmake(str, length);
741
*(const char**)save= str;
746
static void update_func_bool(Session *, drizzle_sys_var *,
747
void *tgt, const void *save)
749
*(bool *) tgt= *(int *) save ? 1 : 0;
753
static void update_func_int(Session *, drizzle_sys_var *,
754
void *tgt, const void *save)
756
*(int *)tgt= *(int *) save;
760
static void update_func_long(Session *, drizzle_sys_var *,
761
void *tgt, const void *save)
763
*(long *)tgt= *(long *) save;
767
static void update_func_int64_t(Session *, drizzle_sys_var *,
768
void *tgt, const void *save)
770
*(int64_t *)tgt= *(uint64_t *) save;
774
static void update_func_str(Session *, drizzle_sys_var *var,
775
void *tgt, const void *save)
777
char *old= *(char **) tgt;
778
*(char **)tgt= *(char **) save;
779
if (var->flags & PLUGIN_VAR_MEMALLOC)
781
*(char **)tgt= strdup(*(char **) save);
784
* There isn't a _really_ good thing to do here until this whole set_var
785
* mess gets redesigned
788
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
794
/****************************************************************************
499
795
System Variables support
500
796
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
799
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
802
sys_var_pluginvar *pi= NULL;
803
plugin::Module *module;
805
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
806
if ((var= intern_find_sys_var(str, length, false)) &&
807
(pi= var->cast_pluginvar()))
809
pthread_rwlock_unlock(&LOCK_system_variables_hash);
810
if (!(module= pi->plugin))
811
var= NULL; /* failed to lock it, it must be uninstalling */
812
else if (module->isInited == false)
818
pthread_rwlock_unlock(&LOCK_system_variables_hash);
821
If the variable exists but the plugin it is associated with is not ready
822
then the intern_plugin_lock did not raise an error, so we do it here.
825
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
829
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
831
/* Embed the flags into the first char of the string */
832
string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
833
varname.append(plugin);
834
varname.push_back('_');
835
varname.append(name);
837
for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
848
called by register_var, construct_options and test_plugin_options.
849
Returns the 'bookmark' for the named variable.
850
LOCK_system_variables_hash should be at least read locked
852
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
854
st_bookmark *result= NULL;
856
if (!(flags & PLUGIN_VAR_SessionLOCAL))
859
const string varname(make_bookmark_name(plugin, name, flags));
862
result= (st_bookmark*) hash_search(&bookmark_hash,
863
(const unsigned char*) varname.c_str(), varname.size() - 1);
870
returns a bookmark for session-local variables, creating if neccessary.
871
returns null for non session-local variables.
872
Requires that a write lock is obtained on LOCK_system_variables_hash
874
static st_bookmark *register_var(const string &plugin, const char *name,
877
if (!(flags & PLUGIN_VAR_SessionLOCAL))
880
uint32_t size= 0, offset, new_size;
883
switch (flags & PLUGIN_VAR_TYPEMASK) {
884
case PLUGIN_VAR_BOOL:
885
size= ALIGN_SIZE(sizeof(bool));
888
size= ALIGN_SIZE(sizeof(int));
890
case PLUGIN_VAR_LONG:
891
size= ALIGN_SIZE(sizeof(long));
893
case PLUGIN_VAR_LONGLONG:
894
size= ALIGN_SIZE(sizeof(uint64_t));
897
size= ALIGN_SIZE(sizeof(char*));
905
if (!(result= find_bookmark(plugin, name, flags)))
907
const string varname(make_bookmark_name(plugin, name, flags));
909
result= static_cast<st_bookmark*>(alloc_root(&plugin_mem_root,
910
sizeof(struct st_bookmark) + varname.size() + 1));
911
memset(result->key, 0, varname.size()+1);
912
memcpy(result->key, varname.c_str(), varname.size());
913
result->name_len= varname.size() - 2;
916
assert(size && !(size & (size-1))); /* must be power of 2 */
918
offset= global_system_variables.dynamic_variables_size;
919
offset= (offset + size - 1) & ~(size - 1);
920
result->offset= (int) offset;
922
new_size= (offset + size + 63) & ~63;
924
if (new_size > global_variables_dynamic_size)
928
(char *)realloc(global_system_variables.dynamic_variables_ptr,
931
global_system_variables.dynamic_variables_ptr= tmpptr;
934
(char *)realloc(max_system_variables.dynamic_variables_ptr,
937
max_system_variables.dynamic_variables_ptr= tmpptr;
940
Clear the new variable value space. This is required for string
941
variables. If their value is non-NULL, it must point to a valid
944
memset(global_system_variables.dynamic_variables_ptr +
945
global_variables_dynamic_size, 0,
946
new_size - global_variables_dynamic_size);
947
memset(max_system_variables.dynamic_variables_ptr +
948
global_variables_dynamic_size, 0,
949
new_size - global_variables_dynamic_size);
950
global_variables_dynamic_size= new_size;
953
global_system_variables.dynamic_variables_head= offset;
954
max_system_variables.dynamic_variables_head= offset;
955
global_system_variables.dynamic_variables_size= offset + size;
956
max_system_variables.dynamic_variables_size= offset + size;
957
global_system_variables.dynamic_variables_version++;
958
max_system_variables.dynamic_variables_version++;
960
result->version= global_system_variables.dynamic_variables_version;
962
/* this should succeed because we have already checked if a dup exists */
963
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
965
fprintf(stderr, "failed to add placeholder to hash");
974
returns a pointer to the memory which holds the session-local variable or
975
a pointer to the global variable if session==null.
976
If required, will sync with global variables if the requested variable
977
has not yet been allocated in the current thread.
979
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
982
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
985
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
988
dynamic_variables_head points to the largest valid offset
990
if (!session->variables.dynamic_variables_ptr ||
991
(uint32_t)offset > session->variables.dynamic_variables_head)
995
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
998
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
999
global_variables_dynamic_size)))
1001
session->variables.dynamic_variables_ptr= tmpptr;
1004
pthread_mutex_lock(&LOCK_global_system_variables);
1006
//safe_mutex_assert_owner(&LOCK_global_system_variables);
1008
memcpy(session->variables.dynamic_variables_ptr +
1009
session->variables.dynamic_variables_size,
1010
global_system_variables.dynamic_variables_ptr +
1011
session->variables.dynamic_variables_size,
1012
global_system_variables.dynamic_variables_size -
1013
session->variables.dynamic_variables_size);
1016
now we need to iterate through any newly copied 'defaults'
1017
and if it is a string type with MEMALLOC flag, we need to strdup
1019
for (idx= 0; idx < bookmark_hash.records; idx++)
1021
sys_var_pluginvar *pi;
1023
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1025
if (v->version <= session->variables.dynamic_variables_version ||
1026
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1027
!(pi= var->cast_pluginvar()) ||
1028
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1031
/* Here we do anything special that may be required of the data types */
1033
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1034
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1036
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1037
*(int*)(pi->plugin_var + 1));
1038
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1039
*(int*)(pi->plugin_var + 1))))
1047
pthread_mutex_unlock(&LOCK_global_system_variables);
1049
session->variables.dynamic_variables_version=
1050
global_system_variables.dynamic_variables_version;
1051
session->variables.dynamic_variables_head=
1052
global_system_variables.dynamic_variables_head;
1053
session->variables.dynamic_variables_size=
1054
global_system_variables.dynamic_variables_size;
1056
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1058
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1061
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1063
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1066
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1068
return (int *)intern_sys_var_ptr(a_session, offset, true);
1071
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1073
return (long *)intern_sys_var_ptr(a_session, offset, true);
1076
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1078
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1081
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1083
return (char **)intern_sys_var_ptr(a_session, offset, true);
509
1086
void plugin_sessionvar_init(Session *session)
511
1088
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1089
cleanup_variables(session, &session->variables);
514
1091
session->variables= global_system_variables;
515
1092
session->variables.storage_engine= NULL;
552
1157
void plugin_sessionvar_cleanup(Session *session)
554
1159
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1160
cleanup_variables(session, &session->variables);
1165
@brief Free values of thread variables of a plugin.
1167
This must be called before a plugin is deleted. Otherwise its
1168
variables are no longer accessible and the value space is lost. Note
1169
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1172
@param[in] vars Chain of system variables of a plugin
1175
static void plugin_vars_free_values(sys_var *vars)
1178
for (sys_var *var= vars; var; var= var->getNext())
1180
sys_var_pluginvar *piv= var->cast_pluginvar();
1182
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1183
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1185
/* Free the string from global_system_variables. */
1186
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1195
bool sys_var_pluginvar::check_update_type(Item_result type)
1199
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1200
case PLUGIN_VAR_INT:
1201
case PLUGIN_VAR_LONG:
1202
case PLUGIN_VAR_LONGLONG:
1203
return type != INT_RESULT;
1204
case PLUGIN_VAR_STR:
1205
return type != STRING_RESULT;
1212
SHOW_TYPE sys_var_pluginvar::show_type()
1214
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1215
case PLUGIN_VAR_BOOL:
1216
return SHOW_MY_BOOL;
1217
case PLUGIN_VAR_INT:
1219
case PLUGIN_VAR_LONG:
1221
case PLUGIN_VAR_LONGLONG:
1222
return SHOW_LONGLONG;
1223
case PLUGIN_VAR_STR:
1224
return SHOW_CHAR_PTR;
1232
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
1234
assert(session || (type == OPT_GLOBAL));
1235
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1237
if (type == OPT_GLOBAL)
1240
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1242
return *(unsigned char**) (plugin_var+1);
1246
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1248
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1249
case PLUGIN_VAR_SessionLOCAL:
1250
return ((sessionvar_enum_t *)plugin_var)->typelib;
1258
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
1260
unsigned char* result;
1262
result= real_value_ptr(session, type);
1268
bool sys_var_pluginvar::check(Session *session, set_var *var)
1270
st_item_value_holder value;
1271
assert(is_readonly() || plugin_var->check);
1273
value.value_type= item_value_type;
1274
value.val_str= item_val_str;
1275
value.val_int= item_val_int;
1276
value.val_real= item_val_real;
1277
value.item= var->value;
1279
return is_readonly() ||
1280
plugin_var->check(session, plugin_var, &var->save_result, &value);
1284
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
1289
assert(is_readonly() || plugin_var->update);
1294
pthread_mutex_lock(&LOCK_global_system_variables);
1295
tgt= real_value_ptr(session, type);
1296
src= ((void **) (plugin_var + 1) + 1);
1298
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1300
if (type != OPT_GLOBAL)
1301
src= real_value_ptr(session, OPT_GLOBAL);
1303
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1304
case PLUGIN_VAR_INT:
1305
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1307
case PLUGIN_VAR_LONG:
1308
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1310
case PLUGIN_VAR_LONGLONG:
1311
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1313
case PLUGIN_VAR_BOOL:
1314
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1316
case PLUGIN_VAR_STR:
1317
src= &((sessionvar_str_t*) plugin_var)->def_val;
1324
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1325
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1326
session == current_session);
1328
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1330
plugin_var->update(session, plugin_var, tgt, src);
1331
pthread_mutex_unlock(&LOCK_global_system_variables);
1335
pthread_mutex_unlock(&LOCK_global_system_variables);
1336
plugin_var->update(session, plugin_var, tgt, src);
1341
bool sys_var_pluginvar::update(Session *session, set_var *var)
1345
assert(is_readonly() || plugin_var->update);
1347
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1348
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1349
session == current_session);
1354
pthread_mutex_lock(&LOCK_global_system_variables);
1355
tgt= real_value_ptr(session, var->type);
1357
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1359
/* variable we are updating has global scope, so we unlock after updating */
1360
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1361
pthread_mutex_unlock(&LOCK_global_system_variables);
1365
pthread_mutex_unlock(&LOCK_global_system_variables);
1366
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1372
#define OPTION_SET_LIMITS(type, options, opt) \
1373
options->var_type= type; \
1374
options->def_value= (opt)->def_val; \
1375
options->min_value= (opt)->min_val; \
1376
options->max_value= (opt)->max_val; \
1377
options->block_size= (long) (opt)->blk_sz
1380
void plugin_opt_set_limits(struct my_option *options,
1381
const drizzle_sys_var *opt)
1383
options->sub_size= 0;
1385
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1386
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1387
/* global system variables */
1388
case PLUGIN_VAR_INT:
1389
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1391
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1392
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1394
case PLUGIN_VAR_LONG:
1395
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1397
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1398
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1400
case PLUGIN_VAR_LONGLONG:
1401
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1403
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1404
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1406
case PLUGIN_VAR_BOOL:
1407
options->var_type= GET_BOOL;
1408
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1410
case PLUGIN_VAR_STR:
1411
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1412
GET_STR_ALLOC : GET_STR);
1413
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1415
/* threadlocal variables */
1416
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1417
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1419
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1420
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1422
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1423
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1425
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1426
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1428
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1429
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1431
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1432
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1434
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1435
options->var_type= GET_BOOL;
1436
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1438
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1439
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1440
GET_STR_ALLOC : GET_STR);
1441
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1446
options->arg_type= REQUIRED_ARG;
1447
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1448
options->arg_type= NO_ARG;
1449
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1450
options->arg_type= OPT_ARG;
1453
static bool get_one_plugin_option(int, const struct my_option *, char *)
1459
static int construct_options(memory::Root *mem_root, plugin::Module *tmp,
1463
int localoptionid= 256;
1464
const string plugin_name(tmp->getManifest().name);
1466
size_t namelen= plugin_name.size(), optnamelen;
1469
int index= 0, offset= 0;
1470
drizzle_sys_var *opt, **plugin_option;
1473
string name(plugin_name);
1474
transform(name.begin(), name.end(), name.begin(), ::tolower);
1476
for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
1483
Two passes as the 2nd pass will take pointer addresses for use
1484
by my_getopt and register_var() in the first pass uses realloc
1487
for (plugin_option= tmp->getManifest().system_vars;
1488
plugin_option && *plugin_option; plugin_option++, index++)
1490
opt= *plugin_option;
1491
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1493
if (!(register_var(name, opt->name, opt->flags)))
1495
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1496
case PLUGIN_VAR_BOOL:
1497
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1499
case PLUGIN_VAR_INT:
1500
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1502
case PLUGIN_VAR_LONG:
1503
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1505
case PLUGIN_VAR_LONGLONG:
1506
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1508
case PLUGIN_VAR_STR:
1509
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1512
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1513
opt->flags, plugin_name.c_str());
1518
for (plugin_option= tmp->getManifest().system_vars;
1519
plugin_option && *plugin_option; plugin_option++, index++)
1521
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1522
case PLUGIN_VAR_BOOL:
1524
opt->check= check_func_bool;
1526
opt->update= update_func_bool;
1528
case PLUGIN_VAR_INT:
1530
opt->check= check_func_int;
1532
opt->update= update_func_int;
1534
case PLUGIN_VAR_LONG:
1536
opt->check= check_func_long;
1538
opt->update= update_func_long;
1540
case PLUGIN_VAR_LONGLONG:
1542
opt->check= check_func_int64_t;
1544
opt->update= update_func_int64_t;
1546
case PLUGIN_VAR_STR:
1548
opt->check= check_func_str;
1551
opt->update= update_func_str;
1552
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1554
opt->flags|= PLUGIN_VAR_READONLY;
1555
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1556
"to be read-only: string variable without "
1557
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1558
opt->name, plugin_name.c_str());
1563
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1564
opt->flags, plugin_name.c_str());
1568
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
1569
== PLUGIN_VAR_NOCMDOPT)
1574
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1575
plugin_name.c_str());
1579
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1581
optnamelen= strlen(opt->name);
1582
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
1583
sprintf(optname, "%s-%s", name.c_str(), opt->name);
1584
optnamelen= namelen + optnamelen + 1;
1588
/* this should not fail because register_var should create entry */
1589
if (!(v= find_bookmark(name, opt->name, opt->flags)))
1591
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1592
"in plugin '%s'."), opt->name, plugin_name.c_str());
1596
*(int*)(opt + 1)= offset= v->offset;
1598
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
1601
optname= (char*) memdup_root(mem_root, v->key + 1,
1602
(optnamelen= v->name_len) + 1);
1605
/* convert '_' to '-' */
1606
for (p= optname; *p; p++)
1610
options->name= optname;
1611
options->comment= opt->comment;
1612
options->app_type= opt;
1613
options->id= localoptionid++;
1615
plugin_opt_set_limits(options, opt);
1617
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
1618
options->value= options->u_max_value= (char**)
1619
(global_system_variables.dynamic_variables_ptr + offset);
1621
options->value= options->u_max_value= *(char***) (opt + 1);
1630
static my_option *construct_help_options(memory::Root *mem_root, plugin::Module *p)
1632
drizzle_sys_var **opt;
1634
uint32_t count= EXTRA_OPTIONS;
1636
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1638
opts= (my_option*)alloc_root(mem_root, (sizeof(my_option) * count));
1642
memset(opts, 0, sizeof(my_option) * count);
1644
if (construct_options(mem_root, p, opts))
1650
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1652
plugin_sysvar_vec.push_back(var);
1655
void drizzle_del_plugin_sysvar()
1657
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1658
while(iter != plugin_sysvar_vec.end())
1663
plugin_sysvar_vec.clear();
562
1668
test_plugin_options()
563
1669
tmp_root temporary scratch space
564
1670
plugin internal plugin structure
1671
argc user supplied arguments
1672
argv user supplied arguments
565
1673
default_enabled default plugin enable status
567
1675
0 SUCCESS - plugin should be enabled/loaded
569
1677
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)
1679
static int test_plugin_options(memory::Root *tmp_root, plugin::Module *tmp,
1680
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);
1682
struct sys_var_chain chain= { NULL, NULL };
1683
drizzle_sys_var **opt;
1684
my_option *opts= NULL;
1687
struct st_bookmark *var;
1688
uint32_t len, count= EXTRA_OPTIONS;
1690
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1694
if (count > EXTRA_OPTIONS || (*argc > 1))
1696
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
1698
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
1701
memset(opts, 0, sizeof(my_option) * count);
1703
if (construct_options(tmp_root, tmp, opts))
1705
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
1709
error= handle_options(argc, &argv, opts, get_one_plugin_option);
1710
(*argc)++; /* add back one for the program name */
1714
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
1715
tmp->getName().c_str());
1723
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1726
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1729
if ((var= find_bookmark(tmp->getName(), o->name, o->flags)))
1730
v= new sys_var_pluginvar(var->key + 1, o);
1733
len= tmp->getName().length() + strlen(o->name) + 2;
1734
string vname(tmp->getName());
1735
vname.push_back('-');
1736
vname.append(o->name);
1737
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1738
string::iterator p= vname.begin();
1739
while (p != vname.end())
1746
v= new sys_var_pluginvar(vname, o);
1748
assert(v); /* check that an object was actually constructed */
1750
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1752
Add to the chain of variables.
1753
Done like this for easier debugging so that the
1754
pointer to v is not lost on optimized builds.
1756
v->chain_sys_var(&chain);
1760
chain.last->setNext(NULL);
1761
if (mysql_add_sys_var_chain(chain.first, NULL))
1763
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
1764
tmp->getName().c_str());
1767
tmp->system_vars= chain.first;
1774
my_cleanup_options(opts);