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
#include "drizzled/util/tokenize.h"
50
#include <boost/foreach.hpp>
52
45
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
57
namespace po=boost::program_options;
59
50
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
52
typedef drizzled::plugin::Manifest drizzled_builtin_plugin[];
53
extern drizzled_builtin_plugin PANDORA_BUILTIN_LIST;
54
static drizzled::plugin::Manifest *drizzled_builtins[]=
56
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;
63
class sys_var_pluginvar;
64
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
66
char *opt_plugin_add= NULL;
67
char *opt_plugin_load= NULL;
68
char *opt_plugin_dir_ptr;
69
char opt_plugin_dir[FN_REFLEN];
70
const char *opt_plugin_load_default= PANDORA_PLUGIN_LIST;
85
72
/* Note that 'int version' must be the first field of every plugin
86
73
sub-structure (plugin->info).
101
stored in bookmark_hash, this structure is never removed from the
102
hash and is used to mark a single offset for a session local variable
103
even if plugins have been uninstalled and reinstalled, repeatedly.
104
This structure is allocated from plugin_mem_root.
106
The key format is as follows:
107
1 byte - variable type code
108
name_len bytes - variable name
122
115
uint32_t version;
126
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
static bookmark_unordered_map bookmark_hash;
121
sys_var class for access to all plugin variables visible to the user
123
class sys_var_pluginvar: public sys_var
126
plugin::Module *plugin;
127
drizzle_sys_var *plugin_var;
129
sys_var_pluginvar(const std::string name_arg,
130
drizzle_sys_var *plugin_var_arg)
131
:sys_var(name_arg), plugin_var(plugin_var_arg) {}
132
sys_var_pluginvar *cast_pluginvar() { return this; }
133
bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
134
bool check_type(enum_var_type type)
135
{ return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
136
bool check_update_type(Item_result type);
137
SHOW_TYPE show_type();
138
unsigned char* real_value_ptr(Session *session, enum_var_type type);
139
TYPELIB* plugin_var_typelib(void);
140
unsigned char* value_ptr(Session *session, enum_var_type type,
141
const LEX_STRING *base);
142
bool check(Session *session, set_var *var);
143
bool check_default(enum_var_type)
144
{ return is_readonly(); }
145
void set_default(Session *session, enum_var_type);
146
bool update(Session *session, set_var *var);
132
static void plugin_prune_list(vector<string> &plugin_list,
133
const vector<string> &plugins_to_remove);
134
static bool plugin_load_list(module::Registry ®istry,
135
memory::Root *tmp_root,
136
const set<string> &plugin_list,
137
po::options_description &long_options,
138
bool builtin= false);
139
static int test_plugin_options(memory::Root *, module::Module *,
140
po::options_description &long_options);
141
static void unlock_variables(Session *session, drizzle_system_variables *vars);
142
static void cleanup_variables(drizzle_system_variables *vars);
151
static bool plugin_load_list(plugin::Registry ®istry,
152
memory::Root *tmp_root, int *argc, char **argv,
154
static int test_plugin_options(memory::Root *, plugin::Module *,
156
static void unlock_variables(Session *session, struct system_variables *vars);
157
static void cleanup_variables(Session *session, struct system_variables *vars);
158
static void plugin_vars_free_values(sys_var *vars);
144
160
/* declared in set_var.cc */
145
161
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
162
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
163
const std::string &name, int64_t val);
165
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
166
const char *name, int64_t val)
168
const std::string name_str(name);
169
return throw_bounds_warning(session, fixed, unsignd, name_str, val);
172
/****************************************************************************
173
Value type thunks, allows the C world to play in the C++ world
174
****************************************************************************/
176
static int item_value_type(drizzle_value *value)
178
switch (((st_item_value_holder*)value)->item->result_type()) {
180
return DRIZZLE_VALUE_TYPE_INT;
182
return DRIZZLE_VALUE_TYPE_REAL;
184
return DRIZZLE_VALUE_TYPE_STRING;
188
static const char *item_val_str(drizzle_value *value,
189
char *buffer, int *length)
191
String str(buffer, *length, system_charset_info), *res;
192
if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
194
*length= res->length();
195
if (res->c_ptr_quick() == buffer)
199
Lets be nice and create a temporary string since the
202
return current_session->strmake(res->c_ptr_quick(), res->length());
206
static int item_val_int(drizzle_value *value, int64_t *buf)
208
Item *item= ((st_item_value_holder*)value)->item;
209
*buf= item->val_int();
216
static int item_val_real(drizzle_value *value, double *buf)
218
Item *item= ((st_item_value_holder*)value)->item;
219
*buf= item->val_real();
148
226
/****************************************************************************
295
375
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)
377
bool plugin_init(plugin::Registry ®istry,
378
int *argc, char **argv,
300
memory::Root tmp_root(4096);
381
plugin::Manifest **builtins;
382
plugin::Manifest *manifest;
383
plugin::Module *module;
384
memory::Root tmp_root;
389
init_alloc_root(&plugin_mem_root, 4096);
390
init_alloc_root(&tmp_root, 4096);
392
if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
393
get_bookmark_hash_key, NULL, HASH_UNIQUE))
395
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);
403
First we register builtin plugins
405
for (builtins= drizzled_builtins; *builtins; builtins++)
408
if (manifest->name != NULL)
410
module= new (std::nothrow) plugin::Module(manifest);
414
free_root(&tmp_root, MYF(memory::MARK_BLOCKS_FREE));
415
if (test_plugin_options(&tmp_root, module, argc, argv))
418
registry.add(module);
420
plugin_initialize_vars(module);
424
if (plugin_initialize(registry, module))
426
free_root(&tmp_root, MYF(0));
313
434
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());
357
435
/* Register all dynamic plugins */
358
load_failed= plugin_load_list(registry, &tmp_root,
359
plugin_list_set, long_options);
438
load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
443
string tmp_plugin_list(opt_plugin_load_default);
446
tmp_plugin_list.push_back(',');
447
tmp_plugin_list.append(opt_plugin_add);
449
load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
362
tmp_root.free_root(MYF(0));
454
free_root(&tmp_root, MYF(0));
366
tmp_root.free_root(MYF(0));
371
bool plugin_finalize(module::Registry ®istry)
460
free_root(&tmp_root, MYF(0));
374
465
Now we initialize all remaining plugins
376
std::map<std::string, module::Module *>::const_iterator modules=
467
std::map<std::string, plugin::Module *>::const_iterator modules=
377
468
registry.getModulesMap().begin();
379
470
while (modules != registry.getModulesMap().end())
381
module::Module *module= (*modules).second;
472
module= (*modules).second;
383
474
if (module->isInited == false)
476
plugin_initialize_vars(module);
385
478
if (plugin_initialize(registry, module))
387
registry.remove(module);
479
delete_module(registry, module);
394
BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
396
value.second->prime();
484
free_root(&tmp_root, MYF(0));
403
public unary_function<string, bool>
405
const string to_match;
407
PrunePlugin& operator=(const PrunePlugin&);
409
explicit PrunePlugin(const string &match_in) :
413
result_type operator()(const string &match_against)
415
return match_against == to_match;
419
static void plugin_prune_list(vector<string> &plugin_list,
420
const vector<string> &plugins_to_remove)
422
for (vector<string>::const_iterator iter= plugins_to_remove.begin();
423
iter != plugins_to_remove.end();
426
plugin_list.erase(remove_if(plugin_list.begin(),
434
492
called only by plugin_init()
436
static bool plugin_load_list(module::Registry ®istry,
437
memory::Root *tmp_root,
438
const set<string> &plugin_list,
439
po::options_description &long_options,
494
static bool plugin_load_list(plugin::Registry ®istry,
495
memory::Root *tmp_root, int *argc, char **argv,
442
module::Library *library= NULL;
498
plugin::Library *library= NULL;
444
for (set<string>::const_iterator iter= plugin_list.begin();
445
iter != plugin_list.end();
500
const string DELIMITER(",");
501
string::size_type last_pos= plugin_list.find_first_not_of(DELIMITER);
502
string::size_type pos= plugin_list.find_first_of(DELIMITER, last_pos);
503
while (string::npos != pos || string::npos != last_pos)
448
const string plugin_name(*iter);
505
const string plugin_name(plugin_list.substr(last_pos, pos - last_pos));
450
library= registry.addLibrary(plugin_name, builtin);
507
library= registry.addLibrary(plugin_name);
451
508
if (library == NULL)
453
510
errmsg_printf(ERRMSG_LVL_ERROR,
454
_("Couldn't load plugin library named '%s'.\n"),
511
_("Couldn't load plugin library named '%s'."),
455
512
plugin_name.c_str());
459
tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
460
if (plugin_add(registry, tmp_root, library, long_options))
516
free_root(tmp_root, MYF(memory::MARK_BLOCKS_FREE));
517
if (plugin_add(registry, tmp_root, library, argc, argv))
462
519
registry.removeLibrary(plugin_name);
463
520
errmsg_printf(ERRMSG_LVL_ERROR,
464
_("Couldn't load plugin named '%s'.\n"),
521
_("Couldn't load plugin named '%s'."),
465
522
plugin_name.c_str());
526
last_pos= plugin_list.find_first_not_of(DELIMITER, pos);
527
pos= plugin_list.find_first_of(DELIMITER, last_pos);
474
void module_shutdown(module::Registry ®istry)
533
void plugin_shutdown(plugin::Registry ®istry)
482
541
unlock_variables(NULL, &global_system_variables);
483
542
unlock_variables(NULL, &max_system_variables);
485
cleanup_variables(&global_system_variables);
486
cleanup_variables(&max_system_variables);
544
cleanup_variables(NULL, &global_system_variables);
545
cleanup_variables(NULL, &max_system_variables);
491
550
/* Dispose of the memory */
492
plugin_mem_root.free_root(MYF(0));
552
hash_free(&bookmark_hash);
553
free_root(&plugin_mem_root, MYF(0));
494
555
global_variables_dynamic_size= 0;
558
/****************************************************************************
559
Internal type declarations for variables support
560
****************************************************************************/
562
#undef DRIZZLE_SYSVAR_NAME
563
#define DRIZZLE_SYSVAR_NAME(name) name
564
#define PLUGIN_VAR_TYPEMASK 0x007f
566
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
568
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
569
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
570
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
571
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
573
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
574
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
576
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
577
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
578
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
579
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
580
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
581
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
583
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
584
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
585
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
586
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
587
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
588
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
590
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
593
/****************************************************************************
594
default variable data check and update functions
595
****************************************************************************/
597
static int check_func_bool(Session *, drizzle_sys_var *var,
598
void *save, drizzle_value *value)
600
char buff[STRING_BUFFER_USUAL_SIZE];
601
const char *strvalue= "NULL", *str;
605
if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
607
length= sizeof(buff);
608
if (!(str= value->val_str(value, buff, &length)) ||
609
(result= find_type(&bool_typelib, str, length, 1)-1) < 0)
618
if (value->val_int(value, &tmp) < 0)
622
internal::llstr(tmp, buff);
628
*(int*)save= -result;
631
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
636
static int check_func_int(Session *session, drizzle_sys_var *var,
637
void *save, drizzle_value *value)
641
struct my_option options;
642
value->val_int(value, &tmp);
643
plugin_opt_set_limits(&options, var);
645
if (var->flags & PLUGIN_VAR_UNSIGNED)
646
*(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
649
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
651
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
652
var->name, (int64_t) tmp);
656
static int check_func_long(Session *session, drizzle_sys_var *var,
657
void *save, drizzle_value *value)
661
struct my_option options;
662
value->val_int(value, &tmp);
663
plugin_opt_set_limits(&options, var);
665
if (var->flags & PLUGIN_VAR_UNSIGNED)
666
*(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
669
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
671
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
672
var->name, (int64_t) tmp);
676
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
677
void *save, drizzle_value *value)
681
struct my_option options;
682
value->val_int(value, &tmp);
683
plugin_opt_set_limits(&options, var);
685
if (var->flags & PLUGIN_VAR_UNSIGNED)
686
*(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
689
*(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
691
return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
692
var->name, (int64_t) tmp);
695
static int check_func_str(Session *session, drizzle_sys_var *,
696
void *save, drizzle_value *value)
698
char buff[STRING_BUFFER_USUAL_SIZE];
702
length= sizeof(buff);
703
if ((str= value->val_str(value, buff, &length)))
704
str= session->strmake(str, length);
705
*(const char**)save= str;
710
static void update_func_bool(Session *, drizzle_sys_var *,
711
void *tgt, const void *save)
713
*(bool *) tgt= *(int *) save ? 1 : 0;
717
static void update_func_int(Session *, drizzle_sys_var *,
718
void *tgt, const void *save)
720
*(int *)tgt= *(int *) save;
724
static void update_func_long(Session *, drizzle_sys_var *,
725
void *tgt, const void *save)
727
*(long *)tgt= *(long *) save;
731
static void update_func_int64_t(Session *, drizzle_sys_var *,
732
void *tgt, const void *save)
734
*(int64_t *)tgt= *(uint64_t *) save;
738
static void update_func_str(Session *, drizzle_sys_var *var,
739
void *tgt, const void *save)
741
char *old= *(char **) tgt;
742
*(char **)tgt= *(char **) save;
743
if (var->flags & PLUGIN_VAR_MEMALLOC)
745
*(char **)tgt= strdup(*(char **) save);
748
* There isn't a _really_ good thing to do here until this whole set_var
749
* mess gets redesigned
752
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
498
758
/****************************************************************************
499
759
System Variables support
500
760
****************************************************************************/
503
sys_var *find_sys_var(const char *str, uint32_t length)
505
return intern_find_sys_var(str, length, false);
763
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
766
sys_var_pluginvar *pi= NULL;
767
plugin::Module *module;
769
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
770
if ((var= intern_find_sys_var(str, length, false)) &&
771
(pi= var->cast_pluginvar()))
773
pthread_rwlock_unlock(&LOCK_system_variables_hash);
774
if (!(module= pi->plugin))
775
var= NULL; /* failed to lock it, it must be uninstalling */
776
else if (module->isInited == false)
782
pthread_rwlock_unlock(&LOCK_system_variables_hash);
785
If the variable exists but the plugin it is associated with is not ready
786
then the intern_plugin_lock did not raise an error, so we do it here.
789
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
793
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
795
/* Embed the flags into the first char of the string */
796
string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
797
varname.append(plugin);
798
varname.push_back('_');
799
varname.append(name);
801
for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
812
called by register_var, construct_options and test_plugin_options.
813
Returns the 'bookmark' for the named variable.
814
LOCK_system_variables_hash should be at least read locked
816
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
818
st_bookmark *result= NULL;
820
if (!(flags & PLUGIN_VAR_SessionLOCAL))
823
const string varname(make_bookmark_name(plugin, name, flags));
826
result= (st_bookmark*) hash_search(&bookmark_hash,
827
(const unsigned char*) varname.c_str(), varname.size() - 1);
834
returns a bookmark for session-local variables, creating if neccessary.
835
returns null for non session-local variables.
836
Requires that a write lock is obtained on LOCK_system_variables_hash
838
static st_bookmark *register_var(const string &plugin, const char *name,
841
if (!(flags & PLUGIN_VAR_SessionLOCAL))
844
uint32_t size= 0, offset, new_size;
847
switch (flags & PLUGIN_VAR_TYPEMASK) {
848
case PLUGIN_VAR_BOOL:
849
size= ALIGN_SIZE(sizeof(bool));
852
size= ALIGN_SIZE(sizeof(int));
854
case PLUGIN_VAR_LONG:
855
size= ALIGN_SIZE(sizeof(long));
857
case PLUGIN_VAR_LONGLONG:
858
size= ALIGN_SIZE(sizeof(uint64_t));
861
size= ALIGN_SIZE(sizeof(char*));
869
if (!(result= find_bookmark(plugin, name, flags)))
871
const string varname(make_bookmark_name(plugin, name, flags));
873
result= static_cast<st_bookmark*>(alloc_root(&plugin_mem_root,
874
sizeof(struct st_bookmark) + varname.size() + 1));
875
memset(result->key, 0, varname.size()+1);
876
memcpy(result->key, varname.c_str(), varname.size());
877
result->name_len= varname.size() - 2;
880
assert(size && !(size & (size-1))); /* must be power of 2 */
882
offset= global_system_variables.dynamic_variables_size;
883
offset= (offset + size - 1) & ~(size - 1);
884
result->offset= (int) offset;
886
new_size= (offset + size + 63) & ~63;
888
if (new_size > global_variables_dynamic_size)
892
(char *)realloc(global_system_variables.dynamic_variables_ptr,
895
global_system_variables.dynamic_variables_ptr= tmpptr;
898
(char *)realloc(max_system_variables.dynamic_variables_ptr,
901
max_system_variables.dynamic_variables_ptr= tmpptr;
904
Clear the new variable value space. This is required for string
905
variables. If their value is non-NULL, it must point to a valid
908
memset(global_system_variables.dynamic_variables_ptr +
909
global_variables_dynamic_size, 0,
910
new_size - global_variables_dynamic_size);
911
memset(max_system_variables.dynamic_variables_ptr +
912
global_variables_dynamic_size, 0,
913
new_size - global_variables_dynamic_size);
914
global_variables_dynamic_size= new_size;
917
global_system_variables.dynamic_variables_head= offset;
918
max_system_variables.dynamic_variables_head= offset;
919
global_system_variables.dynamic_variables_size= offset + size;
920
max_system_variables.dynamic_variables_size= offset + size;
921
global_system_variables.dynamic_variables_version++;
922
max_system_variables.dynamic_variables_version++;
924
result->version= global_system_variables.dynamic_variables_version;
926
/* this should succeed because we have already checked if a dup exists */
927
if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
929
fprintf(stderr, "failed to add placeholder to hash");
938
returns a pointer to the memory which holds the session-local variable or
939
a pointer to the global variable if session==null.
940
If required, will sync with global variables if the requested variable
941
has not yet been allocated in the current thread.
943
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
946
assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
949
return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
952
dynamic_variables_head points to the largest valid offset
954
if (!session->variables.dynamic_variables_ptr ||
955
(uint32_t)offset > session->variables.dynamic_variables_head)
959
pthread_rwlock_rdlock(&LOCK_system_variables_hash);
962
if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
963
global_variables_dynamic_size)))
965
session->variables.dynamic_variables_ptr= tmpptr;
968
pthread_mutex_lock(&LOCK_global_system_variables);
970
//safe_mutex_assert_owner(&LOCK_global_system_variables);
972
memcpy(session->variables.dynamic_variables_ptr +
973
session->variables.dynamic_variables_size,
974
global_system_variables.dynamic_variables_ptr +
975
session->variables.dynamic_variables_size,
976
global_system_variables.dynamic_variables_size -
977
session->variables.dynamic_variables_size);
980
now we need to iterate through any newly copied 'defaults'
981
and if it is a string type with MEMALLOC flag, we need to strdup
983
for (idx= 0; idx < bookmark_hash.records; idx++)
985
sys_var_pluginvar *pi;
987
st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
989
if (v->version <= session->variables.dynamic_variables_version ||
990
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
991
!(pi= var->cast_pluginvar()) ||
992
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
995
/* Here we do anything special that may be required of the data types */
997
if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
998
pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1000
char **pp= (char**) (session->variables.dynamic_variables_ptr +
1001
*(int*)(pi->plugin_var + 1));
1002
if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1003
*(int*)(pi->plugin_var + 1))))
1011
pthread_mutex_unlock(&LOCK_global_system_variables);
1013
session->variables.dynamic_variables_version=
1014
global_system_variables.dynamic_variables_version;
1015
session->variables.dynamic_variables_head=
1016
global_system_variables.dynamic_variables_head;
1017
session->variables.dynamic_variables_size=
1018
global_system_variables.dynamic_variables_size;
1020
pthread_rwlock_unlock(&LOCK_system_variables_hash);
1022
return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
1025
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
1027
return (bool *)intern_sys_var_ptr(a_session, offset, true);
1030
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
1032
return (int *)intern_sys_var_ptr(a_session, offset, true);
1035
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
1037
return (long *)intern_sys_var_ptr(a_session, offset, true);
1040
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
1042
return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
1045
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
1047
return (char **)intern_sys_var_ptr(a_session, offset, true);
509
1050
void plugin_sessionvar_init(Session *session)
511
1052
session->variables.storage_engine= NULL;
512
cleanup_variables(&session->variables);
1053
cleanup_variables(session, &session->variables);
514
1055
session->variables= global_system_variables;
515
1056
session->variables.storage_engine= NULL;
552
1121
void plugin_sessionvar_cleanup(Session *session)
554
1123
unlock_variables(session, &session->variables);
555
cleanup_variables(&session->variables);
1124
cleanup_variables(session, &session->variables);
1129
@brief Free values of thread variables of a plugin.
1131
This must be called before a plugin is deleted. Otherwise its
1132
variables are no longer accessible and the value space is lost. Note
1133
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1136
@param[in] vars Chain of system variables of a plugin
1139
static void plugin_vars_free_values(sys_var *vars)
1142
for (sys_var *var= vars; var; var= var->getNext())
1144
sys_var_pluginvar *piv= var->cast_pluginvar();
1146
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
1147
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
1149
/* Free the string from global_system_variables. */
1150
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
1159
bool sys_var_pluginvar::check_update_type(Item_result type)
1163
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1164
case PLUGIN_VAR_INT:
1165
case PLUGIN_VAR_LONG:
1166
case PLUGIN_VAR_LONGLONG:
1167
return type != INT_RESULT;
1168
case PLUGIN_VAR_STR:
1169
return type != STRING_RESULT;
1176
SHOW_TYPE sys_var_pluginvar::show_type()
1178
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1179
case PLUGIN_VAR_BOOL:
1180
return SHOW_MY_BOOL;
1181
case PLUGIN_VAR_INT:
1183
case PLUGIN_VAR_LONG:
1185
case PLUGIN_VAR_LONGLONG:
1186
return SHOW_LONGLONG;
1187
case PLUGIN_VAR_STR:
1188
return SHOW_CHAR_PTR;
1196
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1198
assert(session || (type == OPT_GLOBAL));
1199
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1201
if (type == OPT_GLOBAL)
1204
return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
1206
return *(unsigned char**) (plugin_var+1);
1210
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1212
switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1213
case PLUGIN_VAR_SessionLOCAL:
1214
return ((sessionvar_enum_t *)plugin_var)->typelib;
1222
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1224
unsigned char* result;
1226
result= real_value_ptr(session, type);
1232
bool sys_var_pluginvar::check(Session *session, set_var *var)
1234
st_item_value_holder value;
1235
assert(is_readonly() || plugin_var->check);
1237
value.value_type= item_value_type;
1238
value.val_str= item_val_str;
1239
value.val_int= item_val_int;
1240
value.val_real= item_val_real;
1241
value.item= var->value;
1243
return is_readonly() ||
1244
plugin_var->check(session, plugin_var, &var->save_result, &value);
1248
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1253
assert(is_readonly() || plugin_var->update);
1258
pthread_mutex_lock(&LOCK_global_system_variables);
1259
tgt= real_value_ptr(session, type);
1260
src= ((void **) (plugin_var + 1) + 1);
1262
if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1264
if (type != OPT_GLOBAL)
1265
src= real_value_ptr(session, OPT_GLOBAL);
1267
switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
1268
case PLUGIN_VAR_INT:
1269
src= &((sessionvar_uint_t*) plugin_var)->def_val;
1271
case PLUGIN_VAR_LONG:
1272
src= &((sessionvar_ulong_t*) plugin_var)->def_val;
1274
case PLUGIN_VAR_LONGLONG:
1275
src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1277
case PLUGIN_VAR_BOOL:
1278
src= &((sessionvar_bool_t*) plugin_var)->def_val;
1280
case PLUGIN_VAR_STR:
1281
src= &((sessionvar_str_t*) plugin_var)->def_val;
1288
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1289
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1290
session == current_session);
1292
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
1294
plugin_var->update(session, plugin_var, tgt, src);
1295
pthread_mutex_unlock(&LOCK_global_system_variables);
1299
pthread_mutex_unlock(&LOCK_global_system_variables);
1300
plugin_var->update(session, plugin_var, tgt, src);
1305
bool sys_var_pluginvar::update(Session *session, set_var *var)
1309
assert(is_readonly() || plugin_var->update);
1311
/* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
1312
assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
1313
session == current_session);
1318
pthread_mutex_lock(&LOCK_global_system_variables);
1319
tgt= real_value_ptr(session, var->type);
1321
if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
1323
/* variable we are updating has global scope, so we unlock after updating */
1324
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1325
pthread_mutex_unlock(&LOCK_global_system_variables);
1329
pthread_mutex_unlock(&LOCK_global_system_variables);
1330
plugin_var->update(session, plugin_var, tgt, &var->save_result);
1336
#define OPTION_SET_LIMITS(type, options, opt) \
1337
options->var_type= type; \
1338
options->def_value= (opt)->def_val; \
1339
options->min_value= (opt)->min_val; \
1340
options->max_value= (opt)->max_val; \
1341
options->block_size= (long) (opt)->blk_sz
1344
void plugin_opt_set_limits(struct my_option *options,
1345
const drizzle_sys_var *opt)
1347
options->sub_size= 0;
1349
switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
1350
PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
1351
/* global system variables */
1352
case PLUGIN_VAR_INT:
1353
OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
1355
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
1356
OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
1358
case PLUGIN_VAR_LONG:
1359
OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
1361
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
1362
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
1364
case PLUGIN_VAR_LONGLONG:
1365
OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1367
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1368
OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1370
case PLUGIN_VAR_BOOL:
1371
options->var_type= GET_BOOL;
1372
options->def_value= ((sysvar_bool_t*) opt)->def_val;
1374
case PLUGIN_VAR_STR:
1375
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1376
GET_STR_ALLOC : GET_STR);
1377
options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1379
/* threadlocal variables */
1380
case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
1381
OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
1383
case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1384
OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
1386
case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
1387
OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
1389
case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1390
OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
1392
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
1393
OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
1395
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1396
OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1398
case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1399
options->var_type= GET_BOOL;
1400
options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1402
case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
1403
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
1404
GET_STR_ALLOC : GET_STR);
1405
options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
1410
options->arg_type= REQUIRED_ARG;
1411
if (opt->flags & PLUGIN_VAR_NOCMDARG)
1412
options->arg_type= NO_ARG;
1413
if (opt->flags & PLUGIN_VAR_OPCMDARG)
1414
options->arg_type= OPT_ARG;
1417
static bool get_one_plugin_option(int, const struct my_option *, char *)
1423
static int construct_options(memory::Root *mem_root, plugin::Module *tmp,
1427
int localoptionid= 256;
1428
const string plugin_name(tmp->getManifest().name);
1430
size_t namelen= plugin_name.size(), optnamelen;
1433
int index= 0, offset= 0;
1434
drizzle_sys_var *opt, **plugin_option;
1437
string name(plugin_name);
1438
transform(name.begin(), name.end(), name.begin(), ::tolower);
1440
for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
1447
Two passes as the 2nd pass will take pointer addresses for use
1448
by my_getopt and register_var() in the first pass uses realloc
1451
for (plugin_option= tmp->getManifest().system_vars;
1452
plugin_option && *plugin_option; plugin_option++, index++)
1454
opt= *plugin_option;
1455
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1457
if (!(register_var(name, opt->name, opt->flags)))
1459
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
1460
case PLUGIN_VAR_BOOL:
1461
(((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1463
case PLUGIN_VAR_INT:
1464
(((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1466
case PLUGIN_VAR_LONG:
1467
(((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1469
case PLUGIN_VAR_LONGLONG:
1470
(((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1472
case PLUGIN_VAR_STR:
1473
(((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1476
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1477
opt->flags, plugin_name.c_str());
1482
for (plugin_option= tmp->getManifest().system_vars;
1483
plugin_option && *plugin_option; plugin_option++, index++)
1485
switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1486
case PLUGIN_VAR_BOOL:
1488
opt->check= check_func_bool;
1490
opt->update= update_func_bool;
1492
case PLUGIN_VAR_INT:
1494
opt->check= check_func_int;
1496
opt->update= update_func_int;
1498
case PLUGIN_VAR_LONG:
1500
opt->check= check_func_long;
1502
opt->update= update_func_long;
1504
case PLUGIN_VAR_LONGLONG:
1506
opt->check= check_func_int64_t;
1508
opt->update= update_func_int64_t;
1510
case PLUGIN_VAR_STR:
1512
opt->check= check_func_str;
1515
opt->update= update_func_str;
1516
if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1518
opt->flags|= PLUGIN_VAR_READONLY;
1519
errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1520
"to be read-only: string variable without "
1521
"update_func and PLUGIN_VAR_MEMALLOC flag"),
1522
opt->name, plugin_name.c_str());
1527
errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1528
opt->flags, plugin_name.c_str());
1532
if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
1533
== PLUGIN_VAR_NOCMDOPT)
1538
errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1539
plugin_name.c_str());
1543
if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
1545
optnamelen= strlen(opt->name);
1546
optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
1547
sprintf(optname, "%s-%s", name.c_str(), opt->name);
1548
optnamelen= namelen + optnamelen + 1;
1552
/* this should not fail because register_var should create entry */
1553
if (!(v= find_bookmark(name, opt->name, opt->flags)))
1555
errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1556
"in plugin '%s'."), opt->name, plugin_name.c_str());
1560
*(int*)(opt + 1)= offset= v->offset;
1562
if (opt->flags & PLUGIN_VAR_NOCMDOPT)
1565
optname= (char*) memdup_root(mem_root, v->key + 1,
1566
(optnamelen= v->name_len) + 1);
1569
/* convert '_' to '-' */
1570
for (p= optname; *p; p++)
1574
options->name= optname;
1575
options->comment= opt->comment;
1576
options->app_type= opt;
1577
options->id= localoptionid++;
1579
plugin_opt_set_limits(options, opt);
1581
if (opt->flags & PLUGIN_VAR_SessionLOCAL)
1582
options->value= options->u_max_value= (char**)
1583
(global_system_variables.dynamic_variables_ptr + offset);
1585
options->value= options->u_max_value= *(char***) (opt + 1);
1594
static my_option *construct_help_options(memory::Root *mem_root, plugin::Module *p)
1596
drizzle_sys_var **opt;
1598
uint32_t count= EXTRA_OPTIONS;
1600
for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
1602
opts= (my_option*)alloc_root(mem_root, (sizeof(my_option) * count));
1606
memset(opts, 0, sizeof(my_option) * count);
1608
if (construct_options(mem_root, p, opts))
1614
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1616
plugin_sysvar_vec.push_back(var);
1619
void drizzle_del_plugin_sysvar()
1621
vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1622
while(iter != plugin_sysvar_vec.end())
1627
plugin_sysvar_vec.clear();
562
1632
test_plugin_options()
563
1633
tmp_root temporary scratch space
564
1634
plugin internal plugin structure
1635
argc user supplied arguments
1636
argv user supplied arguments
565
1637
default_enabled default plugin enable status
567
1639
0 SUCCESS - plugin should be enabled/loaded
569
1641
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)
1643
static int test_plugin_options(memory::Root *tmp_root, plugin::Module *tmp,
1644
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);
1646
struct sys_var_chain chain= { NULL, NULL };
1647
drizzle_sys_var **opt;
1648
my_option *opts= NULL;
1651
struct st_bookmark *var;
1652
uint32_t len, count= EXTRA_OPTIONS;
1654
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1658
if (count > EXTRA_OPTIONS || (*argc > 1))
1660
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
1662
errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
1665
memset(opts, 0, sizeof(my_option) * count);
1667
if (construct_options(tmp_root, tmp, opts))
1669
errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
1673
error= handle_options(argc, &argv, opts, get_one_plugin_option);
1674
(*argc)++; /* add back one for the program name */
1678
errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
1679
tmp->getName().c_str());
1687
for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1690
if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1693
if ((var= find_bookmark(tmp->getName(), o->name, o->flags)))
1694
v= new sys_var_pluginvar(var->key + 1, o);
1697
len= tmp->getName().length() + strlen(o->name) + 2;
1698
string vname(tmp->getName());
1699
vname.push_back('-');
1700
vname.append(o->name);
1701
transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1702
string::iterator p= vname.begin();
1703
while (p != vname.end())
1710
v= new sys_var_pluginvar(vname, o);
1712
assert(v); /* check that an object was actually constructed */
1714
drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1716
Add to the chain of variables.
1717
Done like this for easier debugging so that the
1718
pointer to v is not lost on optimized builds.
1720
v->chain_sys_var(&chain);
1724
chain.last->setNext(NULL);
1725
if (mysql_add_sys_var_chain(chain.first, NULL))
1727
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
1728
tmp->getName().c_str());
1731
tmp->system_vars= chain.first;
1738
my_cleanup_options(opts);