~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/module/loader.cc

  • Committer: LinuxJedi
  • Date: 2010-08-30 16:24:46 UTC
  • mto: (1738.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1739.
  • Revision ID: linuxjedi@linuxjedi-laptop-20100830162446-qdm7pnma8vp41e5m
Fix valgrind warnings (plus make exit clean up properly)

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
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 */
15
15
 
16
16
#include "config.h"
17
17
 
47
47
#include "drizzled/pthread_globals.h"
48
48
#include "drizzled/util/tokenize.h"
49
49
 
50
 
#include <boost/foreach.hpp>
51
 
 
52
50
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
53
51
#ifndef RTLD_NOW
54
52
#define RTLD_NOW 1
61
59
/** These exist just to prevent symbols from being optimized out */
62
60
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
61
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
 
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
62
drizzled::module::Manifest *drizzled_builtins[]=
66
63
{
67
64
  PANDORA_BUILTIN_SYMBOLS_LIST, NULL
68
65
};
69
 
drizzled::module::Manifest *drizzled_load_builtins[]=
70
 
{
71
 
  PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
72
 
};
73
66
 
74
67
namespace drizzled
75
68
{
76
69
 
77
70
 
78
 
typedef vector<string> PluginOptions;
79
 
static PluginOptions opt_plugin_load;
80
 
static PluginOptions opt_plugin_add;
81
 
static PluginOptions opt_plugin_remove;
 
71
class sys_var_pluginvar;
 
72
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
 
73
 
 
74
char *opt_plugin_add= NULL;
 
75
char *opt_plugin_remove= NULL;
 
76
char *opt_plugin_load= NULL;
 
77
char *opt_plugin_dir_ptr;
 
78
char opt_plugin_dir[FN_REFLEN];
 
79
const char *opt_plugin_load_default= PANDORA_PLUGIN_LIST;
82
80
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
 
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
84
81
 
85
82
/* Note that 'int version' must be the first field of every plugin
86
83
   sub-structure (plugin->info).
127
124
static bookmark_unordered_map bookmark_hash;
128
125
 
129
126
 
 
127
/*
 
128
  sys_var class for access to all plugin variables visible to the user
 
129
*/
 
130
class sys_var_pluginvar: public sys_var
 
131
{
 
132
public:
 
133
  module::Module *plugin;
 
134
  drizzle_sys_var *plugin_var;
 
135
 
 
136
  sys_var_pluginvar(const std::string name_arg,
 
137
                    drizzle_sys_var *plugin_var_arg)
 
138
    :sys_var(name_arg), plugin_var(plugin_var_arg) {}
 
139
  sys_var_pluginvar *cast_pluginvar() { return this; }
 
140
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
 
141
  bool check_type(sql_var_t type)
 
142
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
 
143
  bool check_update_type(Item_result type);
 
144
  SHOW_TYPE show_type();
 
145
  unsigned char* real_value_ptr(Session *session, sql_var_t type);
 
146
  TYPELIB* plugin_var_typelib(void);
 
147
  unsigned char* value_ptr(Session *session, sql_var_t type,
 
148
                           const LEX_STRING *base);
 
149
  bool check(Session *session, set_var *var);
 
150
  bool check_default(sql_var_t)
 
151
    { return is_readonly(); }
 
152
  void set_default(Session *session, sql_var_t);
 
153
  bool update(Session *session, set_var *var);
 
154
};
 
155
 
130
156
 
131
157
/* prototypes */
132
158
static void plugin_prune_list(vector<string> &plugin_list,
133
159
                              const vector<string> &plugins_to_remove);
134
160
static bool plugin_load_list(module::Registry &registry,
135
 
                             memory::Root *tmp_root,
 
161
                             memory::Root *tmp_root, int *argc, char **argv,
136
162
                             const set<string> &plugin_list,
137
163
                             po::options_description &long_options,
138
164
                             bool builtin= false);
139
165
static int test_plugin_options(memory::Root *, module::Module *,
 
166
                               int *, char **,
140
167
                               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);
 
168
static void unlock_variables(Session *session, struct system_variables *vars);
 
169
static void cleanup_variables(Session *session, struct system_variables *vars);
 
170
static void plugin_vars_free_values(sys_var *vars);
143
171
 
144
172
/* declared in set_var.cc */
145
173
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
 
174
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
 
175
                                 const std::string &name, int64_t val);
 
176
 
 
177
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
 
178
                                 const char *name, int64_t val)
 
179
{
 
180
  const std::string name_str(name);
 
181
  return throw_bounds_warning(session, fixed, unsignd, name_str, val);
 
182
}
 
183
 
 
184
/****************************************************************************
 
185
  Value type thunks, allows the C world to play in the C++ world
 
186
****************************************************************************/
 
187
 
 
188
static int item_value_type(drizzle_value *value)
 
189
{
 
190
  switch (((st_item_value_holder*)value)->item->result_type()) {
 
191
  case INT_RESULT:
 
192
    return DRIZZLE_VALUE_TYPE_INT;
 
193
  case REAL_RESULT:
 
194
    return DRIZZLE_VALUE_TYPE_REAL;
 
195
  default:
 
196
    return DRIZZLE_VALUE_TYPE_STRING;
 
197
  }
 
198
}
 
199
 
 
200
static const char *item_val_str(drizzle_value *value,
 
201
                                char *buffer, int *length)
 
202
{
 
203
  String str(buffer, *length, system_charset_info), *res;
 
204
  if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
 
205
    return NULL;
 
206
  *length= res->length();
 
207
  if (res->c_ptr_quick() == buffer)
 
208
    return buffer;
 
209
 
 
210
  /*
 
211
    Lets be nice and create a temporary string since the
 
212
    buffer was too small
 
213
  */
 
214
  return current_session->strmake(res->c_ptr_quick(), res->length());
 
215
}
 
216
 
 
217
 
 
218
static int item_val_int(drizzle_value *value, int64_t *buf)
 
219
{
 
220
  Item *item= ((st_item_value_holder*)value)->item;
 
221
  *buf= item->val_int();
 
222
  if (item->is_null())
 
223
    return 1;
 
224
  return 0;
 
225
}
 
226
 
 
227
 
 
228
static int item_val_real(drizzle_value *value, double *buf)
 
229
{
 
230
  Item *item= ((st_item_value_holder*)value)->item;
 
231
  *buf= item->val_real();
 
232
  if (item->is_null())
 
233
    return 1;
 
234
  return 0;
 
235
}
146
236
 
147
237
 
148
238
/****************************************************************************
158
248
*/
159
249
static bool plugin_add(module::Registry &registry, memory::Root *tmp_root,
160
250
                       module::Library *library,
 
251
                       int *argc, char **argv,
161
252
                       po::options_description &long_options)
162
253
{
163
254
  if (! initialized)
188
279
  if (tmp == NULL)
189
280
    return true;
190
281
 
191
 
  if (!test_plugin_options(tmp_root, tmp, long_options))
 
282
  if (!test_plugin_options(tmp_root, tmp, argc, argv, long_options))
192
283
  {
193
284
    registry.add(tmp);
194
285
    return false;
199
290
}
200
291
 
201
292
 
 
293
static void delete_module(module::Module *module)
 
294
{
 
295
  /* Free allocated strings before deleting the plugin. */
 
296
  plugin_vars_free_values(module->system_vars);
 
297
  module->isInited= false;
 
298
  mysql_del_sys_var_chain(module->system_vars);
 
299
  delete module;
 
300
}
 
301
 
 
302
 
202
303
static void reap_plugins(module::Registry &registry)
203
304
{
204
305
  std::map<std::string, module::Module *>::const_iterator modules=
207
308
  while (modules != registry.getModulesMap().end())
208
309
  {
209
310
    module::Module *module= (*modules).second;
210
 
    delete module;
 
311
    delete_module(module);
211
312
    ++modules;
212
313
  }
 
314
 
 
315
  drizzle_del_plugin_sysvar();
 
316
}
 
317
 
 
318
 
 
319
static void plugin_initialize_vars(module::Module *module)
 
320
{
 
321
  /*
 
322
    set the plugin attribute of plugin's sys vars so they are pointing
 
323
    to the active plugin
 
324
  */
 
325
  if (module->system_vars)
 
326
  {
 
327
    sys_var_pluginvar *var= module->system_vars->cast_pluginvar();
 
328
    for (;;)
 
329
    {
 
330
      var->plugin= module;
 
331
      if (! var->getNext())
 
332
        break;
 
333
      var= var->getNext()->cast_pluginvar();
 
334
    }
 
335
  }
213
336
}
214
337
 
215
338
 
236
359
}
237
360
 
238
361
 
239
 
inline static void dashes_to_underscores(std::string &name_in,
240
 
                                         char from= '-', char to= '_')
241
 
{
242
 
  for (string::iterator p= name_in.begin();
243
 
       p != name_in.end();
244
 
       ++p)
245
 
  {
246
 
    if (*p == from)
247
 
    {
248
 
      *p= to;
249
 
    }
250
 
  }
251
 
}
252
 
 
253
 
inline static void underscores_to_dashes(std::string &name_in)
254
 
{
255
 
  return dashes_to_underscores(name_in, '_', '-');
256
 
}
257
 
 
258
 
static void compose_plugin_options(vector<string> &target,
259
 
                                   vector<string> options)
260
 
{
261
 
  for (vector<string>::iterator it= options.begin();
262
 
       it != options.end();
263
 
       ++it)
264
 
  {
265
 
    tokenize(*it, target, ",", true);
266
 
  }
267
 
  for (vector<string>::iterator it= target.begin();
268
 
       it != target.end();
269
 
       ++it)
270
 
  {
271
 
    dashes_to_underscores(*it);
272
 
  }
273
 
}
274
 
 
275
 
void compose_plugin_add(vector<string> options)
276
 
{
277
 
  compose_plugin_options(opt_plugin_add, options);
278
 
}
279
 
 
280
 
void compose_plugin_remove(vector<string> options)
281
 
{
282
 
  compose_plugin_options(opt_plugin_remove, options);
283
 
}
284
 
 
285
 
void notify_plugin_load(string in_plugin_load)
286
 
{
287
 
  tokenize(in_plugin_load, opt_plugin_load, ",", true);
288
 
}
289
 
 
290
362
/*
291
363
  The logic is that we first load and initialize all compiled in plugins.
292
364
  From there we load up the dynamic types (assuming we have not been told to
295
367
  Finally we initialize everything, aka the dynamic that have yet to initialize.
296
368
*/
297
369
bool plugin_init(module::Registry &registry,
 
370
                 int *argc, char **argv,
298
371
                 po::options_description &long_options)
299
372
{
300
373
  memory::Root tmp_root(4096);
304
377
 
305
378
  initialized= 1;
306
379
 
307
 
  PluginOptions builtin_load_list;
308
 
  tokenize(builtin_load_plugins, builtin_load_list, ",", true);
309
 
 
310
 
  PluginOptions builtin_list;
 
380
  vector<string> builtin_list;
311
381
  tokenize(builtin_plugins, builtin_list, ",", true);
312
382
 
313
383
  bool load_failed= false;
314
 
 
315
 
  if (opt_plugin_add.size() > 0)
316
 
  {
317
 
    for (PluginOptions::iterator iter= opt_plugin_add.begin();
318
 
         iter != opt_plugin_add.end();
319
 
         ++iter)
320
 
    {
321
 
      if (find(builtin_list.begin(),
322
 
               builtin_list.end(), *iter) != builtin_list.end())
323
 
      {
324
 
        builtin_load_list.push_back(*iter);
325
 
      }
326
 
      else
327
 
      {
328
 
        opt_plugin_load.push_back(*iter);
329
 
      }
330
 
    }
331
 
  }
332
 
 
333
 
  if (opt_plugin_remove.size() > 0)
334
 
  {
335
 
    plugin_prune_list(opt_plugin_load, opt_plugin_remove);
336
 
    plugin_prune_list(builtin_load_list, opt_plugin_remove);
 
384
  vector<string> plugin_list;
 
385
  if (opt_plugin_load)
 
386
  {
 
387
    tokenize(opt_plugin_load, plugin_list, ",", true);
 
388
  }
 
389
  else
 
390
  {
 
391
    tokenize(opt_plugin_load_default, plugin_list, ",", true);
 
392
  }
 
393
  if (opt_plugin_add)
 
394
  {
 
395
    tokenize(opt_plugin_add, plugin_list, ",", true);
 
396
  }
 
397
 
 
398
  if (opt_plugin_remove)
 
399
  {
 
400
    vector<string> plugins_to_remove;
 
401
    tokenize(opt_plugin_remove, plugins_to_remove, ",", true);
 
402
    plugin_prune_list(plugin_list, plugins_to_remove);
 
403
    plugin_prune_list(builtin_list, plugins_to_remove);
337
404
  }
338
405
 
339
406
 
340
407
  /*
341
408
    First we register builtin plugins
342
409
  */
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,
 
410
  const set<string> builtin_list_set(builtin_list.begin(), builtin_list.end());
 
411
  load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
346
412
                                builtin_list_set, long_options, true);
347
413
  if (load_failed)
348
414
  {
351
417
  }
352
418
 
353
419
  /* Uniquify the list */
354
 
  const set<string> plugin_list_set(opt_plugin_load.begin(),
355
 
                                    opt_plugin_load.end());
 
420
  const set<string> plugin_list_set(plugin_list.begin(), plugin_list.end());
356
421
  
357
422
  /* Register all dynamic plugins */
358
 
  load_failed= plugin_load_list(registry, &tmp_root,
 
423
  load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
359
424
                                plugin_list_set, long_options);
360
425
  if (load_failed)
361
426
  {
368
433
  return false;
369
434
}
370
435
 
371
 
bool plugin_finalize(module::Registry &registry)
 
436
void plugin_finalize(module::Registry &registry)
372
437
{
 
438
 
373
439
  /*
374
440
    Now we initialize all remaining plugins
375
441
  */
382
448
    ++modules;
383
449
    if (module->isInited == false)
384
450
    {
 
451
      plugin_initialize_vars(module);
 
452
 
385
453
      if (plugin_initialize(registry, module))
386
 
      {
387
 
        registry.remove(module);
388
 
        delete module;
389
 
        return true;
390
 
      }
 
454
        delete_module(module);
391
455
    }
392
456
  }
393
 
 
394
 
  BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
395
 
  {
396
 
    value.second->prime();
397
 
  }
398
 
 
399
 
  return false;
400
457
}
401
458
 
402
459
class PrunePlugin :
434
491
  called only by plugin_init()
435
492
*/
436
493
static bool plugin_load_list(module::Registry &registry,
437
 
                             memory::Root *tmp_root,
 
494
                             memory::Root *tmp_root, int *argc, char **argv,
438
495
                             const set<string> &plugin_list,
439
496
                             po::options_description &long_options,
440
497
                             bool builtin)
457
514
    }
458
515
 
459
516
    tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
460
 
    if (plugin_add(registry, tmp_root, library, long_options))
 
517
    if (plugin_add(registry, tmp_root, library, argc, argv, long_options))
461
518
    {
462
519
      registry.removeLibrary(plugin_name);
463
520
      errmsg_printf(ERRMSG_LVL_ERROR,
482
539
    unlock_variables(NULL, &global_system_variables);
483
540
    unlock_variables(NULL, &max_system_variables);
484
541
 
485
 
    cleanup_variables(&global_system_variables);
486
 
    cleanup_variables(&max_system_variables);
 
542
    cleanup_variables(NULL, &global_system_variables);
 
543
    cleanup_variables(NULL, &max_system_variables);
487
544
 
488
545
    initialized= 0;
489
546
  }
494
551
  global_variables_dynamic_size= 0;
495
552
}
496
553
 
 
554
/****************************************************************************
 
555
  Internal type declarations for variables support
 
556
****************************************************************************/
 
557
 
 
558
#undef DRIZZLE_SYSVAR_NAME
 
559
#define DRIZZLE_SYSVAR_NAME(name) name
 
560
#define PLUGIN_VAR_TYPEMASK 0x007f
 
561
 
 
562
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
 
563
 
 
564
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
 
565
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
 
566
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
 
567
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
 
568
 
 
569
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
 
570
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
 
571
 
 
572
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
 
573
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
 
574
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
 
575
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
 
576
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
 
577
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
 
578
 
 
579
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
 
580
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
 
581
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
 
582
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
 
583
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
 
584
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
 
585
 
 
586
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
 
587
 
 
588
 
 
589
/****************************************************************************
 
590
  default variable data check and update functions
 
591
****************************************************************************/
 
592
 
 
593
static int check_func_bool(Session *, drizzle_sys_var *var,
 
594
                           void *save, drizzle_value *value)
 
595
{
 
596
  char buff[STRING_BUFFER_USUAL_SIZE];
 
597
  const char *strvalue= "NULL", *str;
 
598
  int result, length;
 
599
  int64_t tmp;
 
600
 
 
601
  if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
 
602
  {
 
603
    length= sizeof(buff);
 
604
    if (!(str= value->val_str(value, buff, &length)) ||
 
605
        (result= find_type(&bool_typelib, str, length, 1)-1) < 0)
 
606
    {
 
607
      if (str)
 
608
        strvalue= str;
 
609
      goto err;
 
610
    }
 
611
  }
 
612
  else
 
613
  {
 
614
    if (value->val_int(value, &tmp) < 0)
 
615
      goto err;
 
616
    if (tmp > 1)
 
617
    {
 
618
      internal::llstr(tmp, buff);
 
619
      strvalue= buff;
 
620
      goto err;
 
621
    }
 
622
    result= (int) tmp;
 
623
  }
 
624
  *(int*)save= -result;
 
625
  return 0;
 
626
err:
 
627
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
 
628
  return 1;
 
629
}
 
630
 
 
631
 
 
632
static int check_func_int(Session *session, drizzle_sys_var *var,
 
633
                          void *save, drizzle_value *value)
 
634
{
 
635
  bool fixed;
 
636
  int64_t tmp;
 
637
  struct option options;
 
638
  value->val_int(value, &tmp);
 
639
  plugin_opt_set_limits(&options, var);
 
640
 
 
641
  if (var->flags & PLUGIN_VAR_UNSIGNED)
 
642
    *(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
 
643
                                                   &fixed);
 
644
  else
 
645
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
 
646
 
 
647
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
648
                              var->name, (int64_t) tmp);
 
649
}
 
650
 
 
651
 
 
652
static int check_func_long(Session *session, drizzle_sys_var *var,
 
653
                          void *save, drizzle_value *value)
 
654
{
 
655
  bool fixed;
 
656
  int64_t tmp;
 
657
  struct option options;
 
658
  value->val_int(value, &tmp);
 
659
  plugin_opt_set_limits(&options, var);
 
660
 
 
661
  if (var->flags & PLUGIN_VAR_UNSIGNED)
 
662
    *(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
 
663
                                                   &fixed);
 
664
  else
 
665
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
 
666
 
 
667
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
668
                              var->name, (int64_t) tmp);
 
669
}
 
670
 
 
671
 
 
672
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
 
673
                               void *save, drizzle_value *value)
 
674
{
 
675
  bool fixed;
 
676
  int64_t tmp;
 
677
  struct option options;
 
678
  value->val_int(value, &tmp);
 
679
  plugin_opt_set_limits(&options, var);
 
680
 
 
681
  if (var->flags & PLUGIN_VAR_UNSIGNED)
 
682
    *(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
 
683
                                               &fixed);
 
684
  else
 
685
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
 
686
 
 
687
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
688
                              var->name, (int64_t) tmp);
 
689
}
 
690
 
 
691
static int check_func_str(Session *session, drizzle_sys_var *,
 
692
                          void *save, drizzle_value *value)
 
693
{
 
694
  char buff[STRING_BUFFER_USUAL_SIZE];
 
695
  const char *str;
 
696
  int length;
 
697
 
 
698
  length= sizeof(buff);
 
699
  if ((str= value->val_str(value, buff, &length)))
 
700
    str= session->strmake(str, length);
 
701
  *(const char**)save= str;
 
702
  return 0;
 
703
}
 
704
 
 
705
 
 
706
static void update_func_bool(Session *, drizzle_sys_var *,
 
707
                             void *tgt, const void *save)
 
708
{
 
709
  *(bool *) tgt= *(int *) save ? 1 : 0;
 
710
}
 
711
 
 
712
 
 
713
static void update_func_int(Session *, drizzle_sys_var *,
 
714
                             void *tgt, const void *save)
 
715
{
 
716
  *(int *)tgt= *(int *) save;
 
717
}
 
718
 
 
719
 
 
720
static void update_func_long(Session *, drizzle_sys_var *,
 
721
                             void *tgt, const void *save)
 
722
{
 
723
  *(long *)tgt= *(long *) save;
 
724
}
 
725
 
 
726
 
 
727
static void update_func_int64_t(Session *, drizzle_sys_var *,
 
728
                                 void *tgt, const void *save)
 
729
{
 
730
  *(int64_t *)tgt= *(uint64_t *) save;
 
731
}
 
732
 
 
733
 
 
734
static void update_func_str(Session *, drizzle_sys_var *var,
 
735
                             void *tgt, const void *save)
 
736
{
 
737
  char *old= *(char **) tgt;
 
738
  *(char **)tgt= *(char **) save;
 
739
  if (var->flags & PLUGIN_VAR_MEMALLOC)
 
740
  {
 
741
    *(char **)tgt= strdup(*(char **) save);
 
742
    free(old);
 
743
    /*
 
744
     * There isn't a _really_ good thing to do here until this whole set_var
 
745
     * mess gets redesigned
 
746
     */
 
747
    if (tgt == NULL)
 
748
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
 
749
 
 
750
  }
 
751
}
 
752
 
497
753
 
498
754
/****************************************************************************
499
755
  System Variables support
500
756
****************************************************************************/
501
757
 
502
758
 
503
 
sys_var *find_sys_var(const char *str, uint32_t length)
504
 
{
505
 
  return intern_find_sys_var(str, length, false);
506
 
}
507
 
 
 
759
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
 
760
{
 
761
  sys_var *var;
 
762
  sys_var_pluginvar *pi= NULL;
 
763
  module::Module *module;
 
764
 
 
765
  if ((var= intern_find_sys_var(str, length, false)) &&
 
766
      (pi= var->cast_pluginvar()))
 
767
  {
 
768
    if (!(module= pi->plugin))
 
769
      var= NULL; /* failed to lock it, it must be uninstalling */
 
770
    else if (module->isInited == false)
 
771
    {
 
772
      var= NULL;
 
773
    }
 
774
  }
 
775
 
 
776
  /*
 
777
    If the variable exists but the plugin it is associated with is not ready
 
778
    then the intern_plugin_lock did not raise an error, so we do it here.
 
779
  */
 
780
  if (pi && !var)
 
781
    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
 
782
  return(var);
 
783
}
 
784
 
 
785
static const string make_bookmark_name(const string &plugin, const char *name)
 
786
{
 
787
  string varname(plugin);
 
788
  varname.push_back('_');
 
789
  varname.append(name);
 
790
 
 
791
  for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
 
792
  {
 
793
    if (*p == '-')
 
794
    {
 
795
      *p= '_';
 
796
    }
 
797
  }
 
798
  return varname;
 
799
}
 
800
 
 
801
/*
 
802
  called by register_var, construct_options and test_plugin_options.
 
803
  Returns the 'bookmark' for the named variable.
 
804
  LOCK_system_variables_hash should be at least read locked
 
805
*/
 
806
static Bookmark *find_bookmark(const string &plugin, const char *name, int flags)
 
807
{
 
808
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
 
809
    return NULL;
 
810
 
 
811
  const string varname(make_bookmark_name(plugin, name));
 
812
 
 
813
  bookmark_unordered_map::iterator iter= bookmark_hash.find(varname);
 
814
  if (iter != bookmark_hash.end())
 
815
  {
 
816
    return &((*iter).second);
 
817
  }
 
818
  return NULL;
 
819
}
 
820
 
 
821
 
 
822
/*
 
823
  returns a bookmark for session-local variables, creating if neccessary.
 
824
  returns null for non session-local variables.
 
825
  Requires that a write lock is obtained on LOCK_system_variables_hash
 
826
*/
 
827
static Bookmark *register_var(const string &plugin, const char *name,
 
828
                                 int flags)
 
829
{
 
830
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
 
831
    return NULL;
 
832
 
 
833
  uint32_t size= 0, offset, new_size;
 
834
  Bookmark *result= NULL;
 
835
 
 
836
  switch (flags & PLUGIN_VAR_TYPEMASK) {
 
837
  case PLUGIN_VAR_BOOL:
 
838
    size= ALIGN_SIZE(sizeof(bool));
 
839
    break;
 
840
  case PLUGIN_VAR_INT:
 
841
    size= ALIGN_SIZE(sizeof(int));
 
842
    break;
 
843
  case PLUGIN_VAR_LONG:
 
844
    size= ALIGN_SIZE(sizeof(long));
 
845
    break;
 
846
  case PLUGIN_VAR_LONGLONG:
 
847
    size= ALIGN_SIZE(sizeof(uint64_t));
 
848
    break;
 
849
  case PLUGIN_VAR_STR:
 
850
    size= ALIGN_SIZE(sizeof(char*));
 
851
    break;
 
852
  default:
 
853
    assert(0);
 
854
    return NULL;
 
855
  };
 
856
 
 
857
 
 
858
  if (!(result= find_bookmark(plugin, name, flags)))
 
859
  {
 
860
    const string varname(make_bookmark_name(plugin, name));
 
861
 
 
862
    Bookmark new_bookmark;
 
863
    new_bookmark.key= varname;
 
864
    new_bookmark.offset= -1;
 
865
 
 
866
    assert(size && !(size & (size-1))); /* must be power of 2 */
 
867
 
 
868
    offset= global_system_variables.dynamic_variables_size;
 
869
    offset= (offset + size - 1) & ~(size - 1);
 
870
    new_bookmark.offset= (int) offset;
 
871
 
 
872
    new_size= (offset + size + 63) & ~63;
 
873
 
 
874
    if (new_size > global_variables_dynamic_size)
 
875
    {
 
876
      char* tmpptr= NULL;
 
877
      if (!(tmpptr=
 
878
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
 
879
                              new_size)))
 
880
        return NULL;
 
881
      global_system_variables.dynamic_variables_ptr= tmpptr;
 
882
      tmpptr= NULL;
 
883
      if (!(tmpptr=
 
884
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
 
885
                              new_size)))
 
886
        return NULL;
 
887
      max_system_variables.dynamic_variables_ptr= tmpptr;
 
888
           
 
889
      /*
 
890
        Clear the new variable value space. This is required for string
 
891
        variables. If their value is non-NULL, it must point to a valid
 
892
        string.
 
893
      */
 
894
      memset(global_system_variables.dynamic_variables_ptr +
 
895
             global_variables_dynamic_size, 0,
 
896
             new_size - global_variables_dynamic_size);
 
897
      memset(max_system_variables.dynamic_variables_ptr +
 
898
             global_variables_dynamic_size, 0,
 
899
             new_size - global_variables_dynamic_size);
 
900
      global_variables_dynamic_size= new_size;
 
901
    }
 
902
 
 
903
    global_system_variables.dynamic_variables_head= offset;
 
904
    max_system_variables.dynamic_variables_head= offset;
 
905
    global_system_variables.dynamic_variables_size= offset + size;
 
906
    max_system_variables.dynamic_variables_size= offset + size;
 
907
    global_system_variables.dynamic_variables_version++;
 
908
    max_system_variables.dynamic_variables_version++;
 
909
 
 
910
    new_bookmark.version= global_system_variables.dynamic_variables_version;
 
911
    new_bookmark.type_code= flags;
 
912
 
 
913
    /* this should succeed because we have already checked if a dup exists */
 
914
    bookmark_hash.insert(make_pair(varname, new_bookmark));
 
915
    result= find_bookmark(plugin, name, flags);
 
916
  }
 
917
  return result;
 
918
}
 
919
 
 
920
 
 
921
/*
 
922
  returns a pointer to the memory which holds the session-local variable or
 
923
  a pointer to the global variable if session==null.
 
924
  If required, will sync with global variables if the requested variable
 
925
  has not yet been allocated in the current thread.
 
926
*/
 
927
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
 
928
{
 
929
  assert(offset >= 0);
 
930
  assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
 
931
 
 
932
  if (!session)
 
933
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
 
934
 
 
935
  /*
 
936
    dynamic_variables_head points to the largest valid offset
 
937
  */
 
938
  if (!session->variables.dynamic_variables_ptr ||
 
939
      (uint32_t)offset > session->variables.dynamic_variables_head)
 
940
  {
 
941
    char *tmpptr= NULL;
 
942
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
 
943
                                  global_variables_dynamic_size)))
 
944
      return NULL;
 
945
    session->variables.dynamic_variables_ptr= tmpptr;
 
946
 
 
947
    if (global_lock)
 
948
      LOCK_global_system_variables.lock();
 
949
 
 
950
    //safe_mutex_assert_owner(&LOCK_global_system_variables);
 
951
 
 
952
    memcpy(session->variables.dynamic_variables_ptr +
 
953
             session->variables.dynamic_variables_size,
 
954
           global_system_variables.dynamic_variables_ptr +
 
955
             session->variables.dynamic_variables_size,
 
956
           global_system_variables.dynamic_variables_size -
 
957
             session->variables.dynamic_variables_size);
 
958
 
 
959
    /*
 
960
      now we need to iterate through any newly copied 'defaults'
 
961
      and if it is a string type with MEMALLOC flag, we need to strdup
 
962
    */
 
963
    bookmark_unordered_map::iterator iter= bookmark_hash.begin();
 
964
    for (; iter != bookmark_hash.end() ; ++iter)
 
965
    {
 
966
      sys_var_pluginvar *pi;
 
967
      sys_var *var;
 
968
      const Bookmark &v= (*iter).second;
 
969
      const string var_name((*iter).first);
 
970
 
 
971
      if (v.version <= session->variables.dynamic_variables_version ||
 
972
          !(var= intern_find_sys_var(var_name.c_str(), var_name.size(), true)) ||
 
973
          !(pi= var->cast_pluginvar()) ||
 
974
          v.type_code != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
 
975
        continue;
 
976
 
 
977
      /* Here we do anything special that may be required of the data types */
 
978
 
 
979
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
 
980
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
 
981
      {
 
982
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
 
983
                             *(int*)(pi->plugin_var + 1));
 
984
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
 
985
                             *(int*)(pi->plugin_var + 1))))
 
986
           *pp= strdup(*pp);
 
987
         if (*pp == NULL)
 
988
           return NULL;
 
989
      }
 
990
    }
 
991
 
 
992
    if (global_lock)
 
993
      LOCK_global_system_variables.unlock();
 
994
 
 
995
    session->variables.dynamic_variables_version=
 
996
           global_system_variables.dynamic_variables_version;
 
997
    session->variables.dynamic_variables_head=
 
998
           global_system_variables.dynamic_variables_head;
 
999
    session->variables.dynamic_variables_size=
 
1000
           global_system_variables.dynamic_variables_size;
 
1001
  }
 
1002
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
 
1003
}
 
1004
 
 
1005
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
 
1006
{
 
1007
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
 
1008
}
 
1009
 
 
1010
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
 
1011
{
 
1012
  return (int *)intern_sys_var_ptr(a_session, offset, true);
 
1013
}
 
1014
 
 
1015
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
 
1016
{
 
1017
  return (long *)intern_sys_var_ptr(a_session, offset, true);
 
1018
}
 
1019
 
 
1020
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
 
1021
{
 
1022
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1023
}
 
1024
 
 
1025
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
 
1026
{
 
1027
  return (char **)intern_sys_var_ptr(a_session, offset, true);
 
1028
}
508
1029
 
509
1030
void plugin_sessionvar_init(Session *session)
510
1031
{
511
1032
  session->variables.storage_engine= NULL;
512
 
  cleanup_variables(&session->variables);
 
1033
  cleanup_variables(session, &session->variables);
513
1034
 
514
1035
  session->variables= global_system_variables;
515
1036
  session->variables.storage_engine= NULL;
526
1047
/*
527
1048
  Unlocks all system variables which hold a reference
528
1049
*/
529
 
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
 
1050
static void unlock_variables(Session *, struct system_variables *vars)
530
1051
{
531
1052
  vars->storage_engine= NULL;
532
1053
}
538
1059
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
539
1060
  it's used on shutdown.
540
1061
*/
541
 
static void cleanup_variables(drizzle_system_variables *vars)
 
1062
static void cleanup_variables(Session *session, struct system_variables *vars)
542
1063
{
 
1064
  sys_var_pluginvar *pivar;
 
1065
  sys_var *var;
 
1066
  int flags;
 
1067
 
 
1068
  bookmark_unordered_map::iterator iter= bookmark_hash.begin();
 
1069
  for (; iter != bookmark_hash.end() ; ++iter)
 
1070
  {
 
1071
    const Bookmark &v= (*iter).second;
 
1072
    const string key_name((*iter).first);
 
1073
    if (v.version > vars->dynamic_variables_version ||
 
1074
        !(var= intern_find_sys_var(key_name.c_str(), key_name.size(), true)) ||
 
1075
        !(pivar= var->cast_pluginvar()) ||
 
1076
        v.type_code != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
 
1077
      continue;
 
1078
 
 
1079
    flags= pivar->plugin_var->flags;
 
1080
 
 
1081
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
 
1082
        flags & PLUGIN_VAR_SessionLOCAL && flags & PLUGIN_VAR_MEMALLOC)
 
1083
    {
 
1084
      char **ptr= (char**) pivar->real_value_ptr(session, OPT_SESSION);
 
1085
      free(*ptr);
 
1086
      *ptr= NULL;
 
1087
    }
 
1088
  }
 
1089
 
543
1090
  assert(vars->storage_engine == NULL);
544
1091
 
545
1092
  free(vars->dynamic_variables_ptr);
552
1099
void plugin_sessionvar_cleanup(Session *session)
553
1100
{
554
1101
  unlock_variables(session, &session->variables);
555
 
  cleanup_variables(&session->variables);
556
 
}
557
 
 
558
 
 
 
1102
  cleanup_variables(session, &session->variables);
 
1103
}
 
1104
 
 
1105
 
 
1106
/**
 
1107
  @brief Free values of thread variables of a plugin.
 
1108
 
 
1109
  This must be called before a plugin is deleted. Otherwise its
 
1110
  variables are no longer accessible and the value space is lost. Note
 
1111
  that only string values with PLUGIN_VAR_MEMALLOC are allocated and
 
1112
  must be freed.
 
1113
 
 
1114
  @param[in]        vars        Chain of system variables of a plugin
 
1115
*/
 
1116
 
 
1117
static void plugin_vars_free_values(sys_var *vars)
 
1118
{
 
1119
 
 
1120
  for (sys_var *var= vars; var; var= var->getNext())
 
1121
  {
 
1122
    sys_var_pluginvar *piv= var->cast_pluginvar();
 
1123
    if (piv &&
 
1124
        ((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
 
1125
        (piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
 
1126
    {
 
1127
      /* Free the string from global_system_variables. */
 
1128
      char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
 
1129
      free(*valptr);
 
1130
      *valptr= NULL;
 
1131
    }
 
1132
  }
 
1133
  return;
 
1134
}
 
1135
 
 
1136
 
 
1137
bool sys_var_pluginvar::check_update_type(Item_result type)
 
1138
{
 
1139
  if (is_readonly())
 
1140
    return 1;
 
1141
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
 
1142
  case PLUGIN_VAR_INT:
 
1143
  case PLUGIN_VAR_LONG:
 
1144
  case PLUGIN_VAR_LONGLONG:
 
1145
    return type != INT_RESULT;
 
1146
  case PLUGIN_VAR_STR:
 
1147
    return type != STRING_RESULT;
 
1148
  default:
 
1149
    return 0;
 
1150
  }
 
1151
}
 
1152
 
 
1153
 
 
1154
SHOW_TYPE sys_var_pluginvar::show_type()
 
1155
{
 
1156
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
 
1157
  case PLUGIN_VAR_BOOL:
 
1158
    return SHOW_MY_BOOL;
 
1159
  case PLUGIN_VAR_INT:
 
1160
    return SHOW_INT;
 
1161
  case PLUGIN_VAR_LONG:
 
1162
    return SHOW_LONG;
 
1163
  case PLUGIN_VAR_LONGLONG:
 
1164
    return SHOW_LONGLONG;
 
1165
  case PLUGIN_VAR_STR:
 
1166
    return SHOW_CHAR_PTR;
 
1167
  default:
 
1168
    assert(0);
 
1169
    return SHOW_UNDEF;
 
1170
  }
 
1171
}
 
1172
 
 
1173
 
 
1174
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
 
1175
{
 
1176
  assert(session || (type == OPT_GLOBAL));
 
1177
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
 
1178
  {
 
1179
    if (type == OPT_GLOBAL)
 
1180
      session= NULL;
 
1181
 
 
1182
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
 
1183
  }
 
1184
  return *(unsigned char**) (plugin_var+1);
 
1185
}
 
1186
 
 
1187
 
 
1188
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
 
1189
{
 
1190
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
 
1191
  case PLUGIN_VAR_SessionLOCAL:
 
1192
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
1193
  default:
 
1194
    return NULL;
 
1195
  }
 
1196
  return NULL;
 
1197
}
 
1198
 
 
1199
 
 
1200
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
 
1201
{
 
1202
  unsigned char* result;
 
1203
 
 
1204
  result= real_value_ptr(session, type);
 
1205
 
 
1206
  return result;
 
1207
}
 
1208
 
 
1209
 
 
1210
bool sys_var_pluginvar::check(Session *session, set_var *var)
 
1211
{
 
1212
  st_item_value_holder value;
 
1213
  assert(is_readonly() || plugin_var->check);
 
1214
 
 
1215
  value.value_type= item_value_type;
 
1216
  value.val_str= item_val_str;
 
1217
  value.val_int= item_val_int;
 
1218
  value.val_real= item_val_real;
 
1219
  value.item= var->value;
 
1220
 
 
1221
  return is_readonly() ||
 
1222
         plugin_var->check(session, plugin_var, &var->save_result, &value);
 
1223
}
 
1224
 
 
1225
 
 
1226
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
 
1227
{
 
1228
  const void *src;
 
1229
  void *tgt;
 
1230
 
 
1231
  assert(is_readonly() || plugin_var->update);
 
1232
 
 
1233
  if (is_readonly())
 
1234
    return;
 
1235
 
 
1236
  LOCK_global_system_variables.lock();
 
1237
  tgt= real_value_ptr(session, type);
 
1238
  src= ((void **) (plugin_var + 1) + 1);
 
1239
 
 
1240
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
 
1241
  {
 
1242
    if (type != OPT_GLOBAL)
 
1243
      src= real_value_ptr(session, OPT_GLOBAL);
 
1244
    else
 
1245
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
 
1246
        case PLUGIN_VAR_INT:
 
1247
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
 
1248
          break;
 
1249
        case PLUGIN_VAR_LONG:
 
1250
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
 
1251
          break;
 
1252
        case PLUGIN_VAR_LONGLONG:
 
1253
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
 
1254
          break;
 
1255
        case PLUGIN_VAR_BOOL:
 
1256
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
 
1257
          break;
 
1258
        case PLUGIN_VAR_STR:
 
1259
          src= &((sessionvar_str_t*) plugin_var)->def_val;
 
1260
          break;
 
1261
        default:
 
1262
          assert(0);
 
1263
        }
 
1264
  }
 
1265
 
 
1266
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1267
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1268
              session == current_session);
 
1269
 
 
1270
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
 
1271
  {
 
1272
    plugin_var->update(session, plugin_var, tgt, src);
 
1273
    LOCK_global_system_variables.unlock();
 
1274
  }
 
1275
  else
 
1276
  {
 
1277
    LOCK_global_system_variables.unlock();
 
1278
    plugin_var->update(session, plugin_var, tgt, src);
 
1279
  }
 
1280
}
 
1281
 
 
1282
 
 
1283
bool sys_var_pluginvar::update(Session *session, set_var *var)
 
1284
{
 
1285
  void *tgt;
 
1286
 
 
1287
  assert(is_readonly() || plugin_var->update);
 
1288
 
 
1289
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1290
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1291
              session == current_session);
 
1292
 
 
1293
  if (is_readonly())
 
1294
    return 1;
 
1295
 
 
1296
  LOCK_global_system_variables.lock();
 
1297
  tgt= real_value_ptr(session, var->type);
 
1298
 
 
1299
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
 
1300
  {
 
1301
    /* variable we are updating has global scope, so we unlock after updating */
 
1302
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
 
1303
    LOCK_global_system_variables.unlock();
 
1304
  }
 
1305
  else
 
1306
  {
 
1307
    LOCK_global_system_variables.unlock();
 
1308
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
 
1309
  }
 
1310
 return 0;
 
1311
}
 
1312
 
 
1313
 
 
1314
#define OPTION_SET_LIMITS(type, options, opt) \
 
1315
  options->var_type= type;                    \
 
1316
  options->def_value= (opt)->def_val;         \
 
1317
  options->min_value= (opt)->min_val;         \
 
1318
  options->max_value= (opt)->max_val;         \
 
1319
  options->block_size= (long) (opt)->blk_sz
 
1320
 
 
1321
 
 
1322
void plugin_opt_set_limits(struct option *options,
 
1323
                                                                                                         const drizzle_sys_var *opt)
 
1324
{
 
1325
  options->sub_size= 0;
 
1326
 
 
1327
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
 
1328
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
 
1329
  /* global system variables */
 
1330
  case PLUGIN_VAR_INT:
 
1331
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
 
1332
    break;
 
1333
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
 
1334
    OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
 
1335
    break;
 
1336
  case PLUGIN_VAR_LONG:
 
1337
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
 
1338
    break;
 
1339
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
 
1340
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
 
1341
    break;
 
1342
  case PLUGIN_VAR_LONGLONG:
 
1343
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
 
1344
    break;
 
1345
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
 
1346
    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
 
1347
    break;
 
1348
  case PLUGIN_VAR_BOOL:
 
1349
    options->var_type= GET_BOOL;
 
1350
    options->def_value= ((sysvar_bool_t*) opt)->def_val;
 
1351
    break;
 
1352
  case PLUGIN_VAR_STR:
 
1353
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
 
1354
                        GET_STR_ALLOC : GET_STR);
 
1355
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
 
1356
    break;
 
1357
  /* threadlocal variables */
 
1358
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
 
1359
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
 
1360
    break;
 
1361
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1362
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
 
1363
    break;
 
1364
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
 
1365
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
 
1366
    break;
 
1367
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1368
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
 
1369
    break;
 
1370
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
 
1371
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
 
1372
    break;
 
1373
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1374
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
 
1375
    break;
 
1376
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
 
1377
    options->var_type= GET_BOOL;
 
1378
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
 
1379
    break;
 
1380
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
 
1381
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
 
1382
                        GET_STR_ALLOC : GET_STR);
 
1383
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
 
1384
    break;
 
1385
  default:
 
1386
    assert(0);
 
1387
  }
 
1388
  options->arg_type= REQUIRED_ARG;
 
1389
  if (opt->flags & PLUGIN_VAR_NOCMDARG)
 
1390
    options->arg_type= NO_ARG;
 
1391
  if (opt->flags & PLUGIN_VAR_OPCMDARG)
 
1392
    options->arg_type= OPT_ARG;
 
1393
}
 
1394
 
 
1395
static int get_one_plugin_option(int, const struct option *, char *)
 
1396
{
 
1397
  return 0;
 
1398
}
 
1399
 
 
1400
 
 
1401
static int construct_options(memory::Root *mem_root, module::Module *tmp,
 
1402
                             option *options)
 
1403
{
 
1404
  
 
1405
  int localoptionid= 256;
 
1406
  const string plugin_name(tmp->getManifest().name);
 
1407
 
 
1408
  size_t namelen= plugin_name.size(), optnamelen;
 
1409
 
 
1410
  char *optname, *p;
 
1411
  int index= 0, offset= 0;
 
1412
  drizzle_sys_var *opt, **plugin_option;
 
1413
  Bookmark *v;
 
1414
 
 
1415
  string name(plugin_name);
 
1416
  transform(name.begin(), name.end(), name.begin(), ::tolower);
 
1417
 
 
1418
  for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
 
1419
  {
 
1420
    if (*iter == '_')
 
1421
      *iter= '-';
 
1422
  }
 
1423
 
 
1424
  /*
 
1425
    Two passes as the 2nd pass will take pointer addresses for use
 
1426
    by my_getopt and register_var() in the first pass uses realloc
 
1427
  */
 
1428
 
 
1429
  for (plugin_option= tmp->getManifest().system_vars;
 
1430
       plugin_option && *plugin_option; plugin_option++, index++)
 
1431
  {
 
1432
    opt= *plugin_option;
 
1433
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
 
1434
      continue;
 
1435
    if (!(register_var(name, opt->name, opt->flags)))
 
1436
      continue;
 
1437
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
 
1438
    case PLUGIN_VAR_BOOL:
 
1439
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
 
1440
      break;
 
1441
    case PLUGIN_VAR_INT:
 
1442
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
 
1443
      break;
 
1444
    case PLUGIN_VAR_LONG:
 
1445
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
 
1446
      break;
 
1447
    case PLUGIN_VAR_LONGLONG:
 
1448
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
 
1449
      break;
 
1450
    case PLUGIN_VAR_STR:
 
1451
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
 
1452
      break;
 
1453
    default:
 
1454
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
 
1455
                      opt->flags, plugin_name.c_str());
 
1456
      return(-1);
 
1457
    };
 
1458
  }
 
1459
 
 
1460
  for (plugin_option= tmp->getManifest().system_vars;
 
1461
       plugin_option && *plugin_option; plugin_option++, index++)
 
1462
  {
 
1463
    switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
 
1464
    case PLUGIN_VAR_BOOL:
 
1465
      if (!opt->check)
 
1466
        opt->check= check_func_bool;
 
1467
      if (!opt->update)
 
1468
        opt->update= update_func_bool;
 
1469
      break;
 
1470
    case PLUGIN_VAR_INT:
 
1471
      if (!opt->check)
 
1472
        opt->check= check_func_int;
 
1473
      if (!opt->update)
 
1474
        opt->update= update_func_int;
 
1475
      break;
 
1476
    case PLUGIN_VAR_LONG:
 
1477
      if (!opt->check)
 
1478
        opt->check= check_func_long;
 
1479
      if (!opt->update)
 
1480
        opt->update= update_func_long;
 
1481
      break;
 
1482
    case PLUGIN_VAR_LONGLONG:
 
1483
      if (!opt->check)
 
1484
        opt->check= check_func_int64_t;
 
1485
      if (!opt->update)
 
1486
        opt->update= update_func_int64_t;
 
1487
      break;
 
1488
    case PLUGIN_VAR_STR:
 
1489
      if (!opt->check)
 
1490
        opt->check= check_func_str;
 
1491
      if (!opt->update)
 
1492
      {
 
1493
        opt->update= update_func_str;
 
1494
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
 
1495
        {
 
1496
          opt->flags|= PLUGIN_VAR_READONLY;
 
1497
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
 
1498
                            "to be read-only: string variable without "
 
1499
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
 
1500
                            opt->name, plugin_name.c_str());
 
1501
        }
 
1502
      }
 
1503
      break;
 
1504
    default:
 
1505
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
 
1506
                      opt->flags, plugin_name.c_str());
 
1507
      return(-1);
 
1508
    }
 
1509
 
 
1510
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
 
1511
                    == PLUGIN_VAR_NOCMDOPT)
 
1512
      continue;
 
1513
 
 
1514
    if (!opt->name)
 
1515
    {
 
1516
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
 
1517
                    plugin_name.c_str());
 
1518
      return(-1);
 
1519
    }
 
1520
 
 
1521
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
 
1522
    {
 
1523
      optnamelen= strlen(opt->name);
 
1524
      optname= (char*) mem_root->alloc_root(namelen + optnamelen + 2);
 
1525
      sprintf(optname, "%s-%s", name.c_str(), opt->name);
 
1526
      optnamelen= namelen + optnamelen + 1;
 
1527
    }
 
1528
    else
 
1529
    {
 
1530
      /* this should not fail because register_var should create entry */
 
1531
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
 
1532
      {
 
1533
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
 
1534
                      "in plugin '%s'."), opt->name, plugin_name.c_str());
 
1535
        return(-1);
 
1536
      }
 
1537
 
 
1538
      *(int*)(opt + 1)= offset= v->offset;
 
1539
 
 
1540
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
 
1541
        continue;
 
1542
 
 
1543
      optname= (char*) mem_root->memdup_root(v->key.c_str(), (optnamelen= v->key.size()) + 1);
 
1544
    }
 
1545
 
 
1546
    /* convert '_' to '-' */
 
1547
    for (p= optname; *p; p++)
 
1548
      if (*p == '_')
 
1549
        *p= '-';
 
1550
 
 
1551
    options->name= optname;
 
1552
    options->comment= opt->comment;
 
1553
    options->app_type= opt;
 
1554
    options->id= localoptionid++;
 
1555
 
 
1556
    plugin_opt_set_limits(options, opt);
 
1557
 
 
1558
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
 
1559
      options->value= options->u_max_value= (char**)
 
1560
        (global_system_variables.dynamic_variables_ptr + offset);
 
1561
    else
 
1562
      options->value= options->u_max_value= *(char***) (opt + 1);
 
1563
 
 
1564
    options++;
 
1565
  }
 
1566
 
 
1567
  return(0);
 
1568
}
 
1569
 
 
1570
 
 
1571
static option *construct_help_options(memory::Root *mem_root, module::Module *p)
 
1572
{
 
1573
  drizzle_sys_var **opt;
 
1574
  option *opts;
 
1575
  uint32_t count= EXTRA_OPTIONS;
 
1576
 
 
1577
  for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
 
1578
 
 
1579
  opts= (option*)mem_root->alloc_root((sizeof(option) * count));
 
1580
  if (opts == NULL)
 
1581
    return NULL;
 
1582
 
 
1583
  memset(opts, 0, sizeof(option) * count);
 
1584
 
 
1585
  if (construct_options(mem_root, p, opts))
 
1586
    return NULL;
 
1587
 
 
1588
  return(opts);
 
1589
}
 
1590
 
 
1591
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
 
1592
{
 
1593
  plugin_sysvar_vec.push_back(var);
 
1594
}
 
1595
 
 
1596
void drizzle_del_plugin_sysvar()
 
1597
{
 
1598
  vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
 
1599
  while(iter != plugin_sysvar_vec.end())
 
1600
  {
 
1601
    delete *iter;
 
1602
    ++iter;
 
1603
  }
 
1604
  plugin_sysvar_vec.clear();
 
1605
}
559
1606
 
560
1607
/*
561
1608
  SYNOPSIS
562
1609
    test_plugin_options()
563
1610
    tmp_root                    temporary scratch space
564
1611
    plugin                      internal plugin structure
 
1612
    argc                        user supplied arguments
 
1613
    argv                        user supplied arguments
565
1614
    default_enabled             default plugin enable status
566
1615
  RETURNS:
567
1616
    0 SUCCESS - plugin should be enabled/loaded
568
1617
  NOTE:
569
1618
    Requires that a write-lock is held on LOCK_system_variables_hash
570
1619
*/
571
 
static int test_plugin_options(memory::Root *,
 
1620
static int test_plugin_options(memory::Root *module_root,
572
1621
                               module::Module *test_module,
 
1622
                               int *argc, char **argv,
573
1623
                               po::options_description &long_options)
574
1624
{
 
1625
  struct sys_var_chain chain= { NULL, NULL };
 
1626
  drizzle_sys_var **opt;
 
1627
  option *opts= NULL;
 
1628
  int error;
 
1629
  drizzle_sys_var *o;
 
1630
  Bookmark *var;
 
1631
  uint32_t len, count= EXTRA_OPTIONS;
575
1632
 
576
1633
  if (test_module->getManifest().init_options != NULL)
577
1634
  {
582
1639
                                   module_options.add_options());
583
1640
    test_module->getManifest().init_options(opt_ctx);
584
1641
    long_options.add(module_options);
585
 
  }
586
 
 
587
 
  return 0;
 
1642
 
 
1643
  }
 
1644
 
 
1645
  for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
 
1646
  {
 
1647
    count++;
 
1648
  }
 
1649
 
 
1650
  if (count > EXTRA_OPTIONS || (*argc > 1))
 
1651
  {
 
1652
    if (!(opts= (option*) module_root->alloc_root(sizeof(option) * count)))
 
1653
    {
 
1654
      errmsg_printf(ERRMSG_LVL_ERROR,
 
1655
                    _("Out of memory for plugin '%s'."),
 
1656
                    test_module->getName().c_str());
 
1657
      return(-1);
 
1658
    }
 
1659
    memset(opts, 0, sizeof(option) * count);
 
1660
 
 
1661
    if (construct_options(module_root, test_module, opts))
 
1662
    {
 
1663
      errmsg_printf(ERRMSG_LVL_ERROR,
 
1664
                    _("Bad options for plugin '%s'."),
 
1665
                    test_module->getName().c_str());
 
1666
      return(-1);
 
1667
    }
 
1668
 
 
1669
    if (test_module->getManifest().init_options == NULL)
 
1670
    {
 
1671
      error= handle_options(argc, &argv, opts, get_one_plugin_option);
 
1672
      (*argc)++; /* add back one for the program name */
 
1673
 
 
1674
      if (error)
 
1675
      {
 
1676
        errmsg_printf(ERRMSG_LVL_ERROR,
 
1677
                      _("Parsing options for plugin '%s' failed."),
 
1678
                      test_module->getName().c_str());
 
1679
        goto err;
 
1680
      }
 
1681
    }
 
1682
  }
 
1683
 
 
1684
  error= 1;
 
1685
 
 
1686
  {
 
1687
    for (opt= test_module->getManifest().system_vars; opt && *opt; opt++)
 
1688
    {
 
1689
      sys_var *v;
 
1690
      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
 
1691
        continue;
 
1692
 
 
1693
      if ((var= find_bookmark(test_module->getName(), o->name, o->flags)))
 
1694
      {
 
1695
        v= new sys_var_pluginvar(var->key.c_str(), o);
 
1696
      }
 
1697
      else
 
1698
      {
 
1699
        len= test_module->getName().length() + strlen(o->name) + 2;
 
1700
        string vname(test_module->getName());
 
1701
        vname.push_back('-');
 
1702
        vname.append(o->name);
 
1703
        transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
 
1704
        string::iterator p= vname.begin();      
 
1705
        while  (p != vname.end())
 
1706
        {
 
1707
          if (*p == '-')
 
1708
            *p= '_';
 
1709
          ++p;
 
1710
        }
 
1711
 
 
1712
        v= new sys_var_pluginvar(vname, o);
 
1713
      }
 
1714
      assert(v); /* check that an object was actually constructed */
 
1715
 
 
1716
      drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
 
1717
      /*
 
1718
        Add to the chain of variables.
 
1719
        Done like this for easier debugging so that the
 
1720
        pointer to v is not lost on optimized builds.
 
1721
      */
 
1722
      v->chain_sys_var(&chain);
 
1723
    }
 
1724
    if (chain.first)
 
1725
    {
 
1726
      chain.last->setNext(NULL);
 
1727
      if (mysql_add_sys_var_chain(chain.first, NULL))
 
1728
      {
 
1729
        errmsg_printf(ERRMSG_LVL_ERROR,
 
1730
                      _("Plugin '%s' has conflicting system variables"),
 
1731
                      test_module->getName().c_str());
 
1732
        goto err;
 
1733
      }
 
1734
      test_module->system_vars= chain.first;
 
1735
    }
 
1736
    return(0);
 
1737
  }
 
1738
 
 
1739
err:
 
1740
  if (opts)
 
1741
    my_cleanup_options(opts);
 
1742
  return(error);
588
1743
}
589
1744
 
590
1745
 
602
1757
};
603
1758
 
604
1759
 
605
 
void my_print_help_inc_plugins(option *main_options)
 
1760
void my_print_help_inc_plugins(option *main_options,
 
1761
                               po::options_description &long_options)
606
1762
{
607
1763
  module::Registry &registry= module::Registry::singleton();
608
1764
  vector<option> all_options;
609
1765
  memory::Root mem_root(4096);
 
1766
  option *opt= NULL;
610
1767
 
611
1768
 
612
1769
  if (initialized)
624
1781
      if (p->getManifest().init_options != NULL)
625
1782
        continue;
626
1783
 
 
1784
      if (p->getManifest().system_vars == NULL)
 
1785
        continue;
 
1786
 
 
1787
      opt= construct_help_options(&mem_root, p);
 
1788
      if (opt == NULL)
 
1789
        continue;
 
1790
 
 
1791
      /* Only options with a non-NULL comment are displayed in help text */
 
1792
      for (;opt->id; opt++)
 
1793
      {
 
1794
        if (opt->comment)
 
1795
        {
 
1796
          all_options.push_back(*opt);
 
1797
          
 
1798
        }
 
1799
      }
627
1800
    }
628
1801
  }
629
1802
 
645
1818
  all_options.push_back(*main_options);
646
1819
 
647
1820
  my_print_help(&*(all_options.begin()));
 
1821
  cout << long_options << endl;
 
1822
  my_print_variables(&*(all_options.begin()));
648
1823
 
649
1824
  mem_root.free_root(MYF(0));
650
1825
}