~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_plugin.cc

  • Committer: Brian Aker
  • Date: 2009-05-15 17:06:35 UTC
  • mto: This revision was merged to the branch mainline in revision 1023.
  • Revision ID: brian@gaz-20090515170635-croy1u63a3gqdn9n
Dead convert functions for character sets.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
#include <drizzled/server_includes.h>
17
17
#include <mysys/my_getopt.h>
18
 
#include <authentication.h>
19
 
#include <logging.h>
20
 
#include <drizzled/drizzled_error_messages.h>
 
18
#include <mysys/hash.h>
 
19
 
 
20
#include <drizzled/authentication.h>
 
21
#include <drizzled/logging.h>
 
22
#include <drizzled/errmsg.h>
 
23
#include <drizzled/qcache.h>
 
24
#include <drizzled/protocol.h>
 
25
#include <drizzled/sql_parse.h>
 
26
#include <drizzled/scheduling.h>
 
27
#include <drizzled/transaction_services.h>
 
28
#include <drizzled/show.h>
 
29
#include <drizzled/handler.h>
 
30
#include <drizzled/set_var.h>
 
31
#include <drizzled/session.h>
 
32
#include <drizzled/item/null.h>
 
33
#include <drizzled/plugin_registry.h>
 
34
 
 
35
#include <string>
 
36
#include <vector>
 
37
#include <map>
 
38
 
 
39
#include <drizzled/error.h>
 
40
#include <drizzled/gettext.h>
 
41
 
21
42
#define REPORT_TO_LOG  1
22
43
#define REPORT_TO_USER 2
23
44
 
24
 
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
25
 
#define plugin_int_to_ref(A) &(A)
26
 
 
27
 
extern struct st_mysql_plugin *mysqld_builtins[];
 
45
using namespace std;
 
46
 
 
47
typedef struct drizzled_plugin_manifest builtin_plugin[];
 
48
extern builtin_plugin DRIZZLED_BUILTIN_LIST;
 
49
static drizzled_plugin_manifest *drizzled_builtins[]=
 
50
{
 
51
  DRIZZLED_BUILTIN_LIST,(struct drizzled_plugin_manifest *)0
 
52
};
28
53
 
29
54
char *opt_plugin_load= NULL;
 
55
const char *opt_plugin_load_default= QUOTE_ARG(DRIZZLED_PLUGIN_LIST);
30
56
char *opt_plugin_dir_ptr;
31
57
char opt_plugin_dir[FN_REFLEN];
32
 
/*
33
 
  When you ad a new plugin type, add both a string and make sure that the
34
 
  init and deinit array are correctly updated.
35
 
*/
36
 
const LEX_STRING plugin_type_names[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
37
 
{
38
 
  { C_STRING_WITH_LEN("DAEMON") },
39
 
  { C_STRING_WITH_LEN("STORAGE ENGINE") },
40
 
  { C_STRING_WITH_LEN("INFORMATION SCHEMA") },
41
 
  { C_STRING_WITH_LEN("UDF") },
42
 
  { C_STRING_WITH_LEN("UDA") },
43
 
  { C_STRING_WITH_LEN("AUDIT") },
44
 
  { C_STRING_WITH_LEN("LOGGER") },
45
 
  { C_STRING_WITH_LEN("AUTH") }
46
 
};
47
 
 
48
 
extern int initialize_schema_table(st_plugin_int *plugin);
49
 
extern int finalize_schema_table(st_plugin_int *plugin);
50
 
 
51
 
extern int initialize_udf(st_plugin_int *plugin);
52
 
extern int finalize_udf(st_plugin_int *plugin);
53
 
 
54
 
/*
55
 
  The number of elements in both plugin_type_initialize and
56
 
  plugin_type_deinitialize should equal to the number of plugins
57
 
  defined.
58
 
*/
59
 
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
60
 
{
61
 
  0,  /* Daemon */
62
 
  ha_initialize_handlerton,  /* Storage Engine */
63
 
  initialize_schema_table,  /* Information Schema */
64
 
  initialize_udf,  /* UDF */
65
 
  0,  /* UDA */
66
 
  0,  /* Audit */
67
 
  logging_initializer,  /* Logger */
68
 
  authentication_initializer  /* Auth */
69
 
};
70
 
 
71
 
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
72
 
{
73
 
  0,  /* Daemon */
74
 
  ha_finalize_handlerton,  /* Storage Engine */
75
 
  finalize_schema_table,  /* Information Schema */
76
 
  finalize_udf,  /* UDF */
77
 
  0,  /* UDA */
78
 
  0,  /* Audit */
79
 
  logging_finalizer,  /* Logger */
80
 
  authentication_finalizer  /* Auth */
81
 
};
82
 
 
83
58
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
84
59
 
85
60
/* Note that 'int version' must be the first field of every plugin
86
61
   sub-structure (plugin->info).
87
62
*/
88
63
 
89
 
static bool initialized= 0;
 
64
static bool initialized= false;
90
65
 
91
66
static DYNAMIC_ARRAY plugin_dl_array;
92
67
static DYNAMIC_ARRAY plugin_array;
93
 
static HASH plugin_hash[DRIZZLE_MAX_PLUGIN_TYPE_NUM];
 
68
 
94
69
static bool reap_needed= false;
95
 
static int plugin_array_version=0;
96
70
 
97
71
/*
98
72
  write-lock on LOCK_system_variables_hash is required before modifying
115
89
 
116
90
/*
117
91
  stored in bookmark_hash, this structure is never removed from the
118
 
  hash and is used to mark a single offset for a thd local variable
 
92
  hash and is used to mark a single offset for a session local variable
119
93
  even if plugins have been uninstalled and reinstalled, repeatedly.
120
94
  This structure is allocated from plugin_mem_root.
121
95
 
152
126
  struct st_mysql_sys_var *plugin_var;
153
127
 
154
128
  static void *operator new(size_t size, MEM_ROOT *mem_root)
155
 
  { return (void*) alloc_root(mem_root, (uint) size); }
156
 
  static void operator delete(void *ptr_arg __attribute__((unused)),
157
 
                              size_t size __attribute__((unused)))
 
129
  { return (void*) alloc_root(mem_root, (uint32_t) size); }
 
130
  static void operator delete(void *, size_t)
158
131
  { TRASH(ptr_arg, size); }
159
132
 
160
133
  sys_var_pluginvar(const char *name_arg,
163
136
  sys_var_pluginvar *cast_pluginvar() { return this; }
164
137
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
165
138
  bool check_type(enum_var_type type)
166
 
  { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
 
139
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
167
140
  bool check_update_type(Item_result type);
168
141
  SHOW_TYPE show_type();
169
 
  unsigned char* real_value_ptr(THD *thd, enum_var_type type);
 
142
  unsigned char* real_value_ptr(Session *session, enum_var_type type);
170
143
  TYPELIB* plugin_var_typelib(void);
171
 
  unsigned char* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
172
 
  bool check(THD *thd, set_var *var);
173
 
  bool check_default(enum_var_type type __attribute__((unused)))
 
144
  unsigned char* value_ptr(Session *session, enum_var_type type,
 
145
                           const LEX_STRING *base);
 
146
  bool check(Session *session, set_var *var);
 
147
  bool check_default(enum_var_type)
174
148
    { return is_readonly(); }
175
 
  void set_default(THD *thd,
176
 
                   enum_var_type type __attribute__((unused)));
177
 
  bool update(THD *thd, set_var *var);
 
149
  void set_default(Session *session, enum_var_type);
 
150
  bool update(Session *session, set_var *var);
178
151
};
179
152
 
180
153
 
183
156
                             const char *list);
184
157
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
185
158
                               int *, char **);
186
 
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
 
159
static bool register_builtin(struct st_plugin_int *,
187
160
                             struct st_plugin_int **);
188
 
static void unlock_variables(THD *thd, struct system_variables *vars);
189
 
static void cleanup_variables(THD *thd, struct system_variables *vars);
 
161
static void unlock_variables(Session *session, struct system_variables *vars);
 
162
static void cleanup_variables(Session *session, struct system_variables *vars);
190
163
static void plugin_vars_free_values(sys_var *vars);
191
164
static void plugin_opt_set_limits(struct my_option *options,
192
165
                                  const struct st_mysql_sys_var *opt);
193
 
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
194
 
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
195
 
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
196
 
                                     CALLER_INFO_PROTO);
197
 
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
198
166
static void reap_plugins(void);
199
167
 
200
168
 
201
169
/* declared in set_var.cc */
202
170
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
203
 
extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
 
171
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
204
172
                                 const char *name, int64_t val);
205
173
 
206
174
/****************************************************************************
233
201
    Lets be nice and create a temporary string since the
234
202
    buffer was too small
235
203
  */
236
 
  return current_thd->strmake(res->c_ptr_quick(), res->length());
 
204
  return current_session->strmake(res->c_ptr_quick(), res->length());
237
205
}
238
206
 
239
207
 
265
233
{
266
234
  uint32_t i;
267
235
  struct st_plugin_dl *tmp;
 
236
 
268
237
  for (i= 0; i < plugin_dl_array.elements; i++)
269
238
  {
270
239
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
271
 
    if (tmp->ref_count &&
272
 
        ! my_strnncoll(files_charset_info,
 
240
    if (! my_strnncoll(files_charset_info,
273
241
                       (const unsigned char *)dl->str, dl->length,
274
242
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
275
243
      return(tmp);
281
249
{
282
250
  uint32_t i;
283
251
  struct st_plugin_dl *tmp;
 
252
 
284
253
  for (i= 0; i < plugin_dl_array.elements; i++)
285
254
  {
286
255
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
287
 
    if (! tmp->ref_count)
288
256
    {
289
257
      memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
290
258
      return(tmp);
309
277
 
310
278
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
311
279
{
312
 
  char dlpath[FN_REFLEN];
313
 
  uint32_t plugin_dir_len, dummy_errors, dlpathlen;
 
280
  string dlpath;
 
281
  uint32_t plugin_dir_len, dummy_errors;
314
282
  struct st_plugin_dl *tmp, plugin_dl;
315
283
  void *sym;
316
284
  plugin_dir_len= strlen(opt_plugin_dir);
 
285
  dlpath.reserve(FN_REFLEN);
317
286
  /*
318
287
    Ensure that the dll doesn't have a path.
319
288
    This is done to ensure that only approved libraries from the
327
296
    if (report & REPORT_TO_USER)
328
297
      my_error(ER_UDF_NO_PATHS, MYF(0));
329
298
    if (report & REPORT_TO_LOG)
330
 
      sql_print_error(ER(ER_UDF_NO_PATHS));
 
299
      errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
331
300
    return(0);
332
301
  }
333
302
  /* If this dll is already loaded just increase ref_count. */
334
303
  if ((tmp= plugin_dl_find(dl)))
335
304
  {
336
 
    tmp->ref_count++;
337
305
    return(tmp);
338
306
  }
339
307
  memset(&plugin_dl, 0, sizeof(plugin_dl));
340
308
  /* Compile dll path */
341
 
  dlpathlen=
342
 
    strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NULL) -
343
 
    dlpath;
344
 
  plugin_dl.ref_count= 1;
 
309
  dlpath.append(opt_plugin_dir);
 
310
  dlpath.append("/");
 
311
  dlpath.append(dl->str);
345
312
  /* Open new dll handle */
346
 
  if (!(plugin_dl.handle= dlopen(dlpath, RTLD_LAZY|RTLD_GLOBAL)))
 
313
  if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
347
314
  {
348
315
    const char *errmsg=dlerror();
349
 
    if (!strncmp(dlpath, errmsg, dlpathlen))
 
316
    uint32_t dlpathlen= dlpath.length();
 
317
    if (!dlpath.compare(0, dlpathlen, errmsg))
350
318
    { // if errmsg starts from dlpath, trim this prefix.
351
319
      errmsg+=dlpathlen;
352
320
      if (*errmsg == ':') errmsg++;
353
321
      if (*errmsg == ' ') errmsg++;
354
322
    }
355
323
    if (report & REPORT_TO_USER)
356
 
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
 
324
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
357
325
    if (report & REPORT_TO_LOG)
358
 
      sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
 
326
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
359
327
    return(0);
360
328
  }
361
329
 
366
334
    if (report & REPORT_TO_USER)
367
335
      my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
368
336
    if (report & REPORT_TO_LOG)
369
 
      sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
 
337
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
370
338
    return(0);
371
339
  }
372
340
 
373
 
  plugin_dl.plugins= (struct st_mysql_plugin *)sym;
 
341
  plugin_dl.plugins= (struct drizzled_plugin_manifest *)sym;
374
342
 
375
343
  /* Duplicate and convert dll name */
376
344
  plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
377
 
  if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
 
345
  if (! (plugin_dl.dl.str= (char*) malloc(plugin_dl.dl.length)))
378
346
  {
379
347
    free_plugin_mem(&plugin_dl);
380
348
    if (report & REPORT_TO_USER)
381
349
      my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
382
350
    if (report & REPORT_TO_LOG)
383
 
      sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
 
351
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
384
352
    return(0);
385
353
  }
386
354
  plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
394
362
    if (report & REPORT_TO_USER)
395
363
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
396
364
    if (report & REPORT_TO_LOG)
397
 
      sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
 
365
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
398
366
    return(0);
399
367
  }
400
368
  return(tmp);
409
377
  {
410
378
    struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
411
379
                                               struct st_plugin_dl **);
412
 
    if (tmp->ref_count &&
413
 
        ! my_strnncoll(files_charset_info,
 
380
    if (! my_strnncoll(files_charset_info,
414
381
                       (const unsigned char *)dl->str, dl->length,
415
382
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
416
383
    {
417
384
      /* Do not remove this element, unless no other plugin uses this dll. */
418
 
      if (! --tmp->ref_count)
419
385
      {
420
386
        free_plugin_mem(tmp);
421
387
        memset(tmp, 0, sizeof(struct st_plugin_dl));
427
393
}
428
394
 
429
395
 
430
 
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
431
 
{
432
 
  uint32_t i;
433
 
  if (! initialized)
434
 
    return(0);
435
 
 
436
 
  if (type == DRIZZLE_ANY_PLUGIN)
437
 
  {
438
 
    for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
439
 
    {
440
 
      struct st_plugin_int *plugin= (st_plugin_int *)
441
 
        hash_search(&plugin_hash[i], (const unsigned char *)name->str, name->length);
442
 
      if (plugin)
443
 
        return(plugin);
444
 
    }
445
 
  }
446
 
  else
447
 
    return((st_plugin_int *)
448
 
        hash_search(&plugin_hash[type], (const unsigned char *)name->str, name->length));
449
 
  return(0);
450
 
}
451
 
 
452
 
 
453
 
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
454
 
{
455
 
  SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
456
 
  struct st_plugin_int *plugin;
457
 
  if ((plugin= plugin_find_internal(name, type)))
458
 
  {
459
 
    rc= SHOW_OPTION_DISABLED;
460
 
    if (plugin->state == PLUGIN_IS_READY)
461
 
      rc= SHOW_OPTION_YES;
462
 
  }
463
 
  return(rc);
464
 
}
465
 
 
466
 
 
467
 
bool plugin_is_ready(const LEX_STRING *name, int type)
468
 
{
469
 
  bool rc= false;
470
 
  if (plugin_status(name, type) == SHOW_OPTION_YES)
471
 
    rc= true;
472
 
  return rc;
473
 
}
474
 
 
475
 
 
476
 
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
477
 
{
478
 
  LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
479
 
  return plugin_status(&plugin_name, plugin_type);
480
 
}
481
 
 
482
 
 
483
 
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
484
 
{
485
 
  st_plugin_int *pi= plugin_ref_to_int(rc);
486
 
 
487
 
  if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
488
 
  {
489
 
    plugin_ref plugin;
490
 
    /*
491
 
      For debugging, we do an additional malloc which allows the
492
 
      memory manager and/or valgrind to track locked references and
493
 
      double unlocks to aid resolving reference counting.problems.
494
 
    */
495
 
    if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
496
 
      return(NULL);
497
 
 
498
 
    *plugin= pi;
499
 
    pi->ref_count++;
500
 
 
501
 
    if (lex)
502
 
      insert_dynamic(&lex->plugins, (unsigned char*)&plugin);
503
 
    return(plugin);
504
 
  }
505
 
  return(NULL);
506
 
}
507
 
 
508
 
 
509
 
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
510
 
{
511
 
  LEX *lex= thd ? thd->lex : 0;
512
 
  plugin_ref rc;
513
 
  rc= my_intern_plugin_lock_ci(lex, *ptr);
514
 
  return(rc);
515
 
}
516
 
 
517
 
 
518
 
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
519
 
                               CALLER_INFO_PROTO)
520
 
{
521
 
  LEX *lex= thd ? thd->lex : 0;
522
 
  plugin_ref rc= NULL;
523
 
  st_plugin_int *plugin;
524
 
  if ((plugin= plugin_find_internal(name, type)))
525
 
    rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
526
 
  return(rc);
527
 
}
528
 
 
529
396
 
530
397
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
531
398
{
532
 
  uint32_t i;
533
399
  struct st_plugin_int *tmp;
534
 
  for (i= 0; i < plugin_array.elements; i++)
535
 
  {
536
 
    tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
537
 
    if (tmp->state == PLUGIN_IS_FREED)
538
 
    {
539
 
      memcpy(tmp, plugin, sizeof(struct st_plugin_int));
540
 
      return(tmp);
541
 
    }
542
 
  }
543
400
  if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
544
401
    return(0);
545
402
  tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
558
415
                       const LEX_STRING *name, const LEX_STRING *dl,
559
416
                       int *argc, char **argv, int report)
560
417
{
 
418
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
419
 
561
420
  struct st_plugin_int tmp;
562
 
  struct st_mysql_plugin *plugin;
563
 
  if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
 
421
  struct drizzled_plugin_manifest *plugin;
 
422
  if (! initialized)
 
423
    return(0);
 
424
 
 
425
  if (registry.find(name))
564
426
  {
565
427
    if (report & REPORT_TO_USER)
566
428
      my_error(ER_UDF_EXISTS, MYF(0), name->str);
567
429
    if (report & REPORT_TO_LOG)
568
 
      sql_print_error(ER(ER_UDF_EXISTS), name->str);
 
430
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
569
431
    return(true);
570
432
  }
571
433
  /* Clear the whole struct to catch future extensions. */
576
438
  for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
577
439
  {
578
440
    uint32_t name_len= strlen(plugin->name);
579
 
    if (plugin->type >= 0 && plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
580
 
        ! my_strnncoll(system_charset_info,
 
441
    if (! my_strnncoll(system_charset_info,
581
442
                       (const unsigned char *)name->str, name->length,
582
443
                       (const unsigned char *)plugin->name,
583
444
                       name_len))
587
448
      tmp.plugin= plugin;
588
449
      tmp.name.str= (char *)plugin->name;
589
450
      tmp.name.length= name_len;
590
 
      tmp.ref_count= 0;
591
 
      tmp.state= PLUGIN_IS_UNINITIALIZED;
 
451
      tmp.isInited= false;
592
452
      if (!test_plugin_options(tmp_root, &tmp, argc, argv))
593
453
      {
594
454
        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
595
455
        {
596
 
          plugin_array_version++;
597
 
          if (!my_hash_insert(&plugin_hash[plugin->type], (unsigned char*)tmp_plugin_ptr))
598
 
          {
599
 
            init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
600
 
            return(false);
601
 
          }
602
 
          tmp_plugin_ptr->state= PLUGIN_IS_FREED;
 
456
          registry.add(tmp_plugin_ptr);
 
457
          init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
 
458
          return(false);
603
459
        }
604
460
        mysql_del_sys_var_chain(tmp.system_vars);
605
461
        goto err;
612
468
  if (report & REPORT_TO_USER)
613
469
    my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
614
470
  if (report & REPORT_TO_LOG)
615
 
    sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
 
471
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
616
472
err:
617
473
  plugin_dl_del(dl);
618
474
  return(true);
619
475
}
620
476
 
621
477
 
622
 
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
623
 
{
624
 
  if (plugin->plugin->status_vars)
625
 
  {
626
 
#ifdef FIX_LATER
627
 
    /*
628
 
      We have a problem right now where we can not prepend without
629
 
      breaking backwards compatibility. We will fix this shortly so
630
 
      that engines have "use names" and we wil use those for
631
 
      CREATE TABLE, and use the plugin name then for adding automatic
632
 
      variable names.
633
 
    */
634
 
    SHOW_VAR array[2]= {
635
 
      {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
636
 
      {0, 0, SHOW_UNDEF}
637
 
    };
638
 
    remove_status_vars(array);
639
 
#else
640
 
    remove_status_vars(plugin->plugin->status_vars);
641
 
#endif /* FIX_LATER */
642
 
  }
643
 
 
644
 
  if (plugin_type_deinitialize[plugin->plugin->type])
645
 
  {
646
 
    if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
647
 
    {
648
 
      sql_print_error(_("Plugin '%s' of type %s failed deinitialization"),
649
 
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
650
 
    }
651
 
  }
652
 
  else if (plugin->plugin->deinit)
653
 
    plugin->plugin->deinit(plugin);
654
 
 
655
 
  plugin->state= PLUGIN_IS_UNINITIALIZED;
656
 
 
657
 
  /*
658
 
    We do the check here because NDB has a worker THD which doesn't
659
 
    exit until NDB is shut down.
660
 
  */
661
 
  if (ref_check && plugin->ref_count)
662
 
    sql_print_error(_("Plugin '%s' has ref_count=%d after deinitialization."),
663
 
                    plugin->name.str, plugin->ref_count);
664
 
}
665
 
 
666
 
 
667
478
static void plugin_del(struct st_plugin_int *plugin)
668
479
{
 
480
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
481
  if (plugin->isInited)
 
482
  {
 
483
    if (plugin->plugin->status_vars)
 
484
    {
 
485
      remove_status_vars(plugin->plugin->status_vars);
 
486
    }
 
487
 
 
488
    if (plugin->plugin->deinit)
 
489
      plugin->plugin->deinit(registry);
 
490
  }
 
491
 
669
492
  /* Free allocated strings before deleting the plugin. */
670
493
  plugin_vars_free_values(plugin->system_vars);
671
 
  hash_delete(&plugin_hash[plugin->plugin->type], (unsigned char*)plugin);
672
494
  if (plugin->plugin_dl)
673
495
    plugin_dl_del(&plugin->plugin_dl->dl);
674
 
  plugin->state= PLUGIN_IS_FREED;
675
 
  plugin_array_version++;
676
 
  rw_wrlock(&LOCK_system_variables_hash);
 
496
  plugin->isInited= false;
 
497
  pthread_rwlock_wrlock(&LOCK_system_variables_hash);
677
498
  mysql_del_sys_var_chain(plugin->system_vars);
678
 
  rw_unlock(&LOCK_system_variables_hash);
 
499
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
679
500
  free_root(&plugin->mem_root, MYF(0));
680
 
  return;
681
501
}
682
502
 
683
503
static void reap_plugins(void)
684
504
{
685
 
  uint32_t count, idx;
686
 
  struct st_plugin_int *plugin, **reap, **list;
687
 
 
688
 
  if (!reap_needed)
689
 
    return;
690
 
 
691
 
  reap_needed= false;
 
505
  size_t count;
 
506
  uint32_t idx;
 
507
  struct st_plugin_int *plugin;
 
508
 
692
509
  count= plugin_array.elements;
693
 
  reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
694
 
  *(reap++)= NULL;
695
510
 
696
511
  for (idx= 0; idx < count; idx++)
697
512
  {
698
513
    plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
699
 
    if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
700
 
    {
701
 
      /* change the status flag to prevent reaping by another thread */
702
 
      plugin->state= PLUGIN_IS_DYING;
703
 
      *(reap++)= plugin;
704
 
    }
705
 
  }
706
 
 
707
 
  list= reap;
708
 
  while ((plugin= *(--list)))
709
 
    plugin_deinitialize(plugin, true);
710
 
 
711
 
  while ((plugin= *(--reap)))
712
514
    plugin_del(plugin);
713
 
 
714
 
  my_afree(reap);
715
 
}
716
 
 
717
 
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
718
 
{
719
 
  int i;
720
 
  st_plugin_int *pi;
721
 
 
722
 
  if (!plugin)
723
 
    return;
724
 
 
725
 
  pi= plugin_ref_to_int(plugin);
726
 
 
727
 
  free((unsigned char*) plugin);
728
 
 
729
 
  if (lex)
730
 
  {
731
 
    /*
732
 
      Remove one instance of this plugin from the use list.
733
 
      We are searching backwards so that plugins locked last
734
 
      could be unlocked faster - optimizing for LIFO semantics.
735
 
    */
736
 
    for (i= lex->plugins.elements - 1; i >= 0; i--)
737
 
      if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
738
 
      {
739
 
        delete_dynamic_element(&lex->plugins, i);
740
 
        break;
741
 
      }
742
 
    assert(i >= 0);
743
 
  }
744
 
 
745
 
  assert(pi->ref_count);
746
 
  pi->ref_count--;
747
 
 
748
 
  if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
749
 
    reap_needed= true;
750
 
 
751
 
  return;
752
 
}
753
 
 
754
 
 
755
 
void plugin_unlock(THD *thd, plugin_ref plugin)
756
 
{
757
 
  LEX *lex= thd ? thd->lex : 0;
758
 
  if (!plugin)
759
 
    return;
760
 
  intern_plugin_unlock(lex, plugin);
761
 
  return;
762
 
}
763
 
 
764
 
 
765
 
void plugin_unlock_list(THD *thd, plugin_ref *list, uint32_t count)
766
 
{
767
 
  LEX *lex= thd ? thd->lex : 0;
768
 
  assert(list);
769
 
  while (count--)
770
 
    intern_plugin_unlock(lex, *list++);
771
 
  return;
772
 
}
773
 
 
774
 
 
775
 
static int plugin_initialize(struct st_plugin_int *plugin)
776
 
{
777
 
 
778
 
  if (plugin_type_initialize[plugin->plugin->type])
779
 
  {
780
 
    if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
781
 
    {
782
 
      sql_print_error(_("Plugin '%s' registration as a %s failed."),
783
 
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
784
 
      goto err;
785
 
    }
786
 
  }
787
 
  else if (plugin->plugin->init)
788
 
  {
789
 
    if (plugin->plugin->init(plugin))
790
 
    {
791
 
      sql_print_error(_("Plugin '%s' init function returned error."),
792
 
                      plugin->name.str);
793
 
      goto err;
794
 
    }
795
 
  }
796
 
 
797
 
  plugin->state= PLUGIN_IS_READY;
 
515
  }
 
516
}
 
517
 
 
518
static bool plugin_initialize(struct st_plugin_int *plugin)
 
519
{
 
520
  assert(plugin->isInited == false);
 
521
 
 
522
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
523
  if (plugin->plugin->init)
 
524
  {
 
525
    if (plugin->plugin->init(registry))
 
526
    {
 
527
      errmsg_printf(ERRMSG_LVL_ERROR,
 
528
                    _("Plugin '%s' init function returned error."),
 
529
                    plugin->name.str);
 
530
      goto err;
 
531
    }
 
532
  }
 
533
  plugin->isInited= true;
798
534
 
799
535
  if (plugin->plugin->status_vars)
800
536
  {
801
 
#ifdef FIX_LATER
802
 
    /*
803
 
      We have a problem right now where we can not prepend without
804
 
      breaking backwards compatibility. We will fix this shortly so
805
 
      that engines have "use names" and we wil use those for
806
 
      CREATE TABLE, and use the plugin name then for adding automatic
807
 
      variable names.
808
 
    */
809
 
    SHOW_VAR array[2]= {
810
 
      {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
811
 
      {0, 0, SHOW_UNDEF}
812
 
    };
813
 
    if (add_status_vars(array)) // add_status_vars makes a copy
814
 
      goto err;
815
 
#else
816
537
    add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
817
 
#endif /* FIX_LATER */
818
538
  }
819
539
 
820
540
  /*
833
553
    }
834
554
  }
835
555
 
836
 
  return(0);
 
556
  return false;
837
557
err:
838
 
  return(1);
 
558
  return true;
839
559
}
840
560
 
841
561
 
842
 
extern "C" unsigned char *get_plugin_hash_key(const unsigned char *, size_t *, bool);
843
562
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
844
563
 
845
564
 
846
 
unsigned char *get_plugin_hash_key(const unsigned char *buff, size_t *length,
847
 
                           bool not_used __attribute__((unused)))
848
 
{
849
 
  struct st_plugin_int *plugin= (st_plugin_int *)buff;
850
 
  *length= (uint)plugin->name.length;
851
 
  return((unsigned char *)plugin->name.str);
852
 
}
853
 
 
854
 
 
855
 
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length,
856
 
                             bool not_used __attribute__((unused)))
 
565
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
857
566
{
858
567
  struct st_bookmark *var= (st_bookmark *)buff;
859
568
  *length= var->name_len + 1;
870
579
*/
871
580
int plugin_init(int *argc, char **argv, int flags)
872
581
{
873
 
  uint32_t i;
874
 
  struct st_mysql_plugin **builtins;
875
 
  struct st_mysql_plugin *plugin;
876
 
  struct st_plugin_int tmp, *plugin_ptr, **reap;
 
582
  uint32_t idx;
 
583
  struct drizzled_plugin_manifest **builtins;
 
584
  struct drizzled_plugin_manifest *plugin;
 
585
  struct st_plugin_int tmp, *plugin_ptr;
877
586
  MEM_ROOT tmp_root;
878
587
 
879
588
  if (initialized)
893
602
                            sizeof(struct st_plugin_int *),16,16))
894
603
    goto err;
895
604
 
896
 
  for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
897
 
  {
898
 
    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
899
 
                  get_plugin_hash_key, NULL, HASH_UNIQUE))
900
 
      goto err;
901
 
  }
902
 
 
903
605
  initialized= 1;
904
606
 
905
607
  /*
906
608
    First we register builtin plugins
907
609
  */
908
 
  for (builtins= mysqld_builtins; *builtins; builtins++)
 
610
  for (builtins= drizzled_builtins; *builtins; builtins++)
909
611
  {
910
612
    for (plugin= *builtins; plugin->name; plugin++)
911
613
    {
918
620
      if (test_plugin_options(&tmp_root, &tmp, argc, argv))
919
621
        continue;
920
622
 
921
 
      if (register_builtin(plugin, &tmp, &plugin_ptr))
 
623
      if (register_builtin(&tmp, &plugin_ptr))
922
624
        goto err_unlock;
923
625
 
924
626
      if (plugin_initialize(plugin_ptr))
925
627
        goto err_unlock;
926
628
 
927
 
      /*
928
 
        initialize the global default storage engine so that it may
929
 
        not be null in any child thread.
930
 
      */
931
 
      if (my_strcasecmp(&my_charset_utf8_general_ci, plugin->name, "MyISAM") == 0)
932
 
      {
933
 
        assert(!global_system_variables.table_plugin);
934
 
        global_system_variables.table_plugin=
935
 
          my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
936
 
        assert(plugin_ptr->ref_count == 1);
937
 
      }
938
629
    }
939
630
  }
940
631
 
941
 
  /* should now be set to MyISAM storage engine */
942
 
  assert(global_system_variables.table_plugin);
943
632
 
944
633
  /* Register all dynamic plugins */
945
634
  if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
954
643
  /*
955
644
    Now we initialize all remaining plugins
956
645
  */
957
 
 
958
 
  reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
959
 
  *(reap++)= NULL;
960
 
 
961
 
  for (i= 0; i < plugin_array.elements; i++)
 
646
  for (idx= 0; idx < plugin_array.elements; idx++)
962
647
  {
963
 
    plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
964
 
    if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
 
648
    plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
 
649
    if (plugin_ptr->isInited == false)
965
650
    {
966
651
      if (plugin_initialize(plugin_ptr))
967
 
      {
968
 
        plugin_ptr->state= PLUGIN_IS_DYING;
969
 
        *(reap++)= plugin_ptr;
970
 
      }
 
652
        plugin_del(plugin_ptr);
971
653
    }
972
654
  }
973
655
 
974
 
  /*
975
 
    Check if any plugins have to be reaped
976
 
  */
977
 
  while ((plugin_ptr= *(--reap)))
978
 
  {
979
 
    plugin_deinitialize(plugin_ptr, true);
980
 
    plugin_del(plugin_ptr);
981
 
  }
982
 
 
983
 
  my_afree(reap);
984
656
 
985
657
end:
986
658
  free_root(&tmp_root, MYF(0));
994
666
}
995
667
 
996
668
 
997
 
static bool register_builtin(struct st_mysql_plugin *plugin,
998
 
                             struct st_plugin_int *tmp,
 
669
static bool register_builtin(struct st_plugin_int *tmp,
999
670
                             struct st_plugin_int **ptr)
1000
671
{
1001
672
 
1002
 
  tmp->state= PLUGIN_IS_UNINITIALIZED;
1003
 
  tmp->ref_count= 0;
 
673
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
674
 
 
675
  tmp->isInited= false;
1004
676
  tmp->plugin_dl= 0;
1005
677
 
1006
678
  if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
1011
683
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
1012
684
                                             sizeof(struct st_plugin_int));
1013
685
 
1014
 
  if (my_hash_insert(&plugin_hash[plugin->type],(unsigned char*) *ptr))
1015
 
    return(1);
 
686
  registry.add(*ptr);
1016
687
 
1017
688
  return(0);
1018
689
}
1027
698
  char buffer[FN_REFLEN];
1028
699
  LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
1029
700
  struct st_plugin_dl *plugin_dl;
1030
 
  struct st_mysql_plugin *plugin;
 
701
  struct drizzled_plugin_manifest *plugin;
1031
702
  char *p= buffer;
1032
703
  while (list)
1033
704
  {
1034
705
    if (p == buffer + sizeof(buffer) - 1)
1035
706
    {
1036
 
      sql_print_error(_("plugin-load parameter too long"));
 
707
      errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
1037
708
      return(true);
1038
709
    }
1039
710
 
1093
764
  }
1094
765
  return(false);
1095
766
error:
1096
 
  sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
 
767
  errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
1097
768
                  name.str, dl.str);
1098
769
  return(true);
1099
770
}
1101
772
 
1102
773
void plugin_shutdown(void)
1103
774
{
1104
 
  uint32_t i, count= plugin_array.elements, free_slots= 0;
1105
 
  struct st_plugin_int **plugins, *plugin;
1106
 
  struct st_plugin_dl **dl;
 
775
  uint32_t idx;
 
776
  size_t count= plugin_array.elements;
 
777
  vector<st_plugin_int *> plugins;
 
778
  vector<st_plugin_dl *> dl;
1107
779
 
1108
780
  if (initialized)
1109
781
  {
1110
782
    reap_needed= true;
1111
783
 
1112
 
    /*
1113
 
      We want to shut down plugins in a reasonable order, this will
1114
 
      become important when we have plugins which depend upon each other.
1115
 
      Circular references cannot be reaped so they are forced afterwards.
1116
 
      TODO: Have an additional step here to notify all active plugins that
1117
 
      shutdown is requested to allow plugins to deinitialize in parallel.
1118
 
    */
1119
 
    while (reap_needed && (count= plugin_array.elements))
1120
 
    {
1121
 
      reap_plugins();
1122
 
      for (i= free_slots= 0; i < count; i++)
1123
 
      {
1124
 
        plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1125
 
        switch (plugin->state) {
1126
 
        case PLUGIN_IS_READY:
1127
 
          plugin->state= PLUGIN_IS_DELETED;
1128
 
          reap_needed= true;
1129
 
          break;
1130
 
        case PLUGIN_IS_FREED:
1131
 
        case PLUGIN_IS_UNINITIALIZED:
1132
 
          free_slots++;
1133
 
          break;
1134
 
        }
1135
 
      }
1136
 
      if (!reap_needed)
1137
 
      {
1138
 
        /*
1139
 
          release any plugin references held.
1140
 
        */
1141
 
        unlock_variables(NULL, &global_system_variables);
1142
 
        unlock_variables(NULL, &max_system_variables);
1143
 
      }
1144
 
    }
1145
 
 
1146
 
    if (count > free_slots)
1147
 
      sql_print_warning(_("Forcing shutdown of %d plugins"),
1148
 
                        count - free_slots);
1149
 
 
1150
 
    plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1151
 
 
1152
 
    /*
1153
 
      If we have any plugins which did not die cleanly, we force shutdown
1154
 
    */
1155
 
    for (i= 0; i < count; i++)
1156
 
    {
1157
 
      plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1158
 
      /* change the state to ensure no reaping races */
1159
 
      if (plugins[i]->state == PLUGIN_IS_DELETED)
1160
 
        plugins[i]->state= PLUGIN_IS_DYING;
1161
 
    }
1162
 
 
1163
 
    /*
1164
 
      We loop through all plugins and call deinit() if they have one.
1165
 
    */
1166
 
    for (i= 0; i < count; i++)
1167
 
      if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1168
 
      {
1169
 
        sql_print_information(_("Plugin '%s' will be forced to shutdown"),
1170
 
                              plugins[i]->name.str);
1171
 
        /*
1172
 
          We are forcing deinit on plugins so we don't want to do a ref_count
1173
 
          check until we have processed all the plugins.
1174
 
        */
1175
 
        plugin_deinitialize(plugins[i], false);
1176
 
      }
1177
 
 
1178
 
    /*
1179
 
      We defer checking ref_counts until after all plugins are deinitialized
1180
 
      as some may have worker threads holding on to plugin references.
1181
 
    */
1182
 
    for (i= 0; i < count; i++)
1183
 
    {
1184
 
      if (plugins[i]->ref_count)
1185
 
        sql_print_error(_("Plugin '%s' has ref_count=%d after shutdown."),
1186
 
                        plugins[i]->name.str, plugins[i]->ref_count);
1187
 
      if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1188
 
        plugin_del(plugins[i]);
1189
 
    }
1190
 
 
1191
 
    /*
1192
 
      Now we can deallocate all memory.
1193
 
    */
 
784
    reap_plugins();
 
785
    unlock_variables(NULL, &global_system_variables);
 
786
    unlock_variables(NULL, &max_system_variables);
1194
787
 
1195
788
    cleanup_variables(NULL, &global_system_variables);
1196
789
    cleanup_variables(NULL, &max_system_variables);
1197
790
 
1198
791
    initialized= 0;
1199
 
 
1200
 
    my_afree(plugins);
1201
792
  }
1202
793
 
1203
794
  /* Dispose of the memory */
1204
795
 
1205
 
  for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1206
 
    hash_free(&plugin_hash[i]);
1207
796
  delete_dynamic(&plugin_array);
1208
797
 
1209
798
  count= plugin_dl_array.elements;
1210
 
  dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1211
 
  for (i= 0; i < count; i++)
1212
 
    dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1213
 
  for (i= 0; i < plugin_dl_array.elements; i++)
1214
 
    free_plugin_mem(dl[i]);
1215
 
  my_afree(dl);
 
799
  dl.reserve(count);
 
800
  for (idx= 0; idx < count; idx++)
 
801
    dl.push_back(*dynamic_element(&plugin_dl_array, idx,
 
802
                 struct st_plugin_dl **));
 
803
  for (idx= 0; idx < count; idx++)
 
804
    free_plugin_mem(dl[idx]);
1216
805
  delete_dynamic(&plugin_dl_array);
1217
806
 
1218
807
  hash_free(&bookmark_hash);
1219
808
  free_root(&plugin_mem_root, MYF(0));
1220
809
 
1221
810
  global_variables_dynamic_size= 0;
1222
 
 
1223
 
  return;
1224
 
}
1225
 
 
1226
 
 
1227
 
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1228
 
                       int type, uint32_t state_mask, void *arg)
1229
 
{
1230
 
  uint32_t idx, total;
1231
 
  struct st_plugin_int *plugin, **plugins;
1232
 
  int version=plugin_array_version;
1233
 
 
1234
 
  if (!initialized)
1235
 
    return(false);
1236
 
 
1237
 
  state_mask= ~state_mask; // do it only once
1238
 
 
1239
 
  total= type == DRIZZLE_ANY_PLUGIN ? plugin_array.elements
1240
 
                                  : plugin_hash[type].records;
1241
 
  /*
1242
 
    Do the alloca out here in case we do have a working alloca:
1243
 
        leaving the nested stack frame invalidates alloca allocation.
1244
 
  */
1245
 
  plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1246
 
  if (type == DRIZZLE_ANY_PLUGIN)
1247
 
  {
1248
 
    for (idx= 0; idx < total; idx++)
1249
 
    {
1250
 
      plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1251
 
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1252
 
    }
1253
 
  }
1254
 
  else
1255
 
  {
1256
 
    HASH *hash= plugin_hash + type;
1257
 
    for (idx= 0; idx < total; idx++)
1258
 
    {
1259
 
      plugin= (struct st_plugin_int *) hash_element(hash, idx);
1260
 
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1261
 
    }
1262
 
  }
1263
 
  for (idx= 0; idx < total; idx++)
1264
 
  {
1265
 
    if (unlikely(version != plugin_array_version))
1266
 
    {
1267
 
      for (uint32_t i=idx; i < total; i++)
1268
 
        if (plugins[i] && plugins[i]->state & state_mask)
1269
 
          plugins[i]=0;
1270
 
    }
1271
 
    plugin= plugins[idx];
1272
 
    /* It will stop iterating on first engine error when "func" returns true */
1273
 
    if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
1274
 
        goto err;
1275
 
  }
1276
 
 
1277
 
  my_afree(plugins);
1278
 
  return(false);
1279
 
err:
1280
 
  my_afree(plugins);
1281
 
  return(true);
1282
 
}
1283
 
 
 
811
}
1284
812
 
1285
813
/****************************************************************************
1286
814
  Internal type declarations for variables support
1293
821
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1294
822
 
1295
823
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1296
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_bool_t, bool);
 
824
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1297
825
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1298
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_str_t, char *);
 
826
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1299
827
 
1300
828
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1301
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
 
829
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1302
830
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1303
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
 
831
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1304
832
 
1305
833
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1306
834
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1309
837
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1310
838
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1311
839
 
1312
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int_t, int);
1313
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_long_t, long);
1314
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int64_t_t, int64_t);
1315
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint_t, uint);
1316
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
1317
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint64_t_t, uint64_t);
 
840
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
 
841
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
 
842
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
 
843
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
 
844
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
 
845
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1318
846
 
1319
 
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
 
847
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1320
848
 
1321
849
 
1322
850
/****************************************************************************
1323
851
  default variable data check and update functions
1324
852
****************************************************************************/
1325
853
 
1326
 
static int check_func_bool(THD *thd __attribute__((unused)),
1327
 
                           struct st_mysql_sys_var *var,
 
854
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
1328
855
                           void *save, st_mysql_value *value)
1329
856
{
1330
857
  char buff[STRING_BUFFER_USUAL_SIZE];
1363
890
}
1364
891
 
1365
892
 
1366
 
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
 
893
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1367
894
                          void *save, st_mysql_value *value)
1368
895
{
1369
896
  bool fixed;
1373
900
  plugin_opt_set_limits(&options, var);
1374
901
 
1375
902
  if (var->flags & PLUGIN_VAR_UNSIGNED)
1376
 
    *(uint32_t *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
 
903
    *(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
1377
904
                                                   &fixed);
1378
905
  else
1379
906
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1380
907
 
1381
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
908
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1382
909
                              var->name, (int64_t) tmp);
1383
910
}
1384
911
 
1385
912
 
1386
 
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
 
913
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1387
914
                          void *save, st_mysql_value *value)
1388
915
{
1389
916
  bool fixed;
1398
925
  else
1399
926
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1400
927
 
1401
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
928
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1402
929
                              var->name, (int64_t) tmp);
1403
930
}
1404
931
 
1405
932
 
1406
 
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
 
933
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1407
934
                               void *save, st_mysql_value *value)
1408
935
{
1409
936
  bool fixed;
1418
945
  else
1419
946
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1420
947
 
1421
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
948
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1422
949
                              var->name, (int64_t) tmp);
1423
950
}
1424
951
 
1425
 
static int check_func_str(THD *thd,
1426
 
                          struct st_mysql_sys_var *var __attribute__((unused)),
 
952
static int check_func_str(Session *session, struct st_mysql_sys_var *,
1427
953
                          void *save, st_mysql_value *value)
1428
954
{
1429
955
  char buff[STRING_BUFFER_USUAL_SIZE];
1432
958
 
1433
959
  length= sizeof(buff);
1434
960
  if ((str= value->val_str(value, buff, &length)))
1435
 
    str= thd->strmake(str, length);
 
961
    str= session->strmake(str, length);
1436
962
  *(const char**)save= str;
1437
963
  return 0;
1438
964
}
1439
965
 
1440
966
 
1441
 
static int check_func_enum(THD *thd __attribute__((unused)),
1442
 
                           struct st_mysql_sys_var *var,
 
967
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
1443
968
                           void *save, st_mysql_value *value)
1444
969
{
1445
970
  char buff[STRING_BUFFER_USUAL_SIZE];
1449
974
  long result;
1450
975
  int length;
1451
976
 
1452
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1453
 
    typelib= ((thdvar_enum_t*) var)->typelib;
 
977
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
978
    typelib= ((sessionvar_enum_t*) var)->typelib;
1454
979
  else
1455
980
    typelib= ((sysvar_enum_t*) var)->typelib;
1456
981
 
1485
1010
}
1486
1011
 
1487
1012
 
1488
 
static int check_func_set(THD *thd __attribute__((unused)),
1489
 
                          struct st_mysql_sys_var *var,
 
1013
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1490
1014
                          void *save, st_mysql_value *value)
1491
1015
{
1492
1016
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1497
1021
  bool not_used;
1498
1022
  int length;
1499
1023
 
1500
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1501
 
    typelib= ((thdvar_set_t*) var)->typelib;
 
1024
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1025
    typelib= ((sessionvar_set_t*) var)->typelib;
1502
1026
  else
1503
1027
    typelib= ((sysvar_set_t*)var)->typelib;
1504
1028
 
1511
1035
                     &error, &error_len, &not_used);
1512
1036
    if (error_len)
1513
1037
    {
1514
 
      strmake(buff, error, cmin(sizeof(buff), (unsigned long)error_len));
 
1038
      length= cmin(sizeof(buff), (unsigned long)error_len);
 
1039
      strncpy(buff, error, length);
 
1040
      buff[length]= '\0';
1515
1041
      strvalue= buff;
1516
1042
      goto err;
1517
1043
    }
1536
1062
}
1537
1063
 
1538
1064
 
1539
 
static void update_func_bool(THD *thd __attribute__((unused)),
1540
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1065
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1541
1066
                             void *tgt, const void *save)
1542
1067
{
1543
1068
  *(bool *) tgt= *(int *) save ? 1 : 0;
1544
1069
}
1545
1070
 
1546
1071
 
1547
 
static void update_func_int(THD *thd __attribute__((unused)),
1548
 
                            struct st_mysql_sys_var *var __attribute__((unused)),
 
1072
static void update_func_int(Session *, struct st_mysql_sys_var *,
1549
1073
                             void *tgt, const void *save)
1550
1074
{
1551
1075
  *(int *)tgt= *(int *) save;
1552
1076
}
1553
1077
 
1554
1078
 
1555
 
static void update_func_long(THD *thd __attribute__((unused)),
1556
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1079
static void update_func_long(Session *, struct st_mysql_sys_var *,
1557
1080
                             void *tgt, const void *save)
1558
1081
{
1559
1082
  *(long *)tgt= *(long *) save;
1560
1083
}
1561
1084
 
1562
1085
 
1563
 
static void update_func_int64_t(THD *thd __attribute__((unused)),
1564
 
                                 struct st_mysql_sys_var *var __attribute__((unused)),
 
1086
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1565
1087
                                 void *tgt, const void *save)
1566
1088
{
1567
1089
  *(int64_t *)tgt= *(uint64_t *) save;
1568
1090
}
1569
1091
 
1570
1092
 
1571
 
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
 
1093
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1572
1094
                             void *tgt, const void *save)
1573
1095
{
1574
1096
  char *old= *(char **) tgt;
1575
1097
  *(char **)tgt= *(char **) save;
1576
1098
  if (var->flags & PLUGIN_VAR_MEMALLOC)
1577
1099
  {
1578
 
    *(char **)tgt= my_strdup(*(char **) save, MYF(0));
 
1100
    *(char **)tgt= strdup(*(char **) save);
1579
1101
    free(old);
 
1102
    /*
 
1103
     * There isn't a _really_ good thing to do here until this whole set_var
 
1104
     * mess gets redesigned
 
1105
     */
 
1106
    if (tgt == NULL)
 
1107
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
 
1108
 
1580
1109
  }
1581
1110
}
1582
1111
 
1586
1115
****************************************************************************/
1587
1116
 
1588
1117
 
1589
 
sys_var *find_sys_var(THD *thd, const char *str, uint32_t length)
 
1118
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
1590
1119
{
1591
1120
  sys_var *var;
1592
1121
  sys_var_pluginvar *pi= NULL;
1593
 
  plugin_ref plugin;
 
1122
  st_plugin_int *plugin;
1594
1123
 
1595
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1124
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1596
1125
  if ((var= intern_find_sys_var(str, length, false)) &&
1597
1126
      (pi= var->cast_pluginvar()))
1598
1127
  {
1599
 
    rw_unlock(&LOCK_system_variables_hash);
1600
 
    LEX *lex= thd ? thd->lex : 0;
1601
 
    if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
 
1128
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
1129
    if (!(plugin= pi->plugin))
1602
1130
      var= NULL; /* failed to lock it, it must be uninstalling */
1603
 
    else
1604
 
    if (!(plugin_state(plugin) & PLUGIN_IS_READY))
 
1131
    else if (plugin->isInited == false)
1605
1132
    {
1606
 
      /* initialization not completed */
1607
1133
      var= NULL;
1608
 
      intern_plugin_unlock(lex, plugin);
1609
1134
    }
1610
1135
  }
1611
1136
  else
1612
 
    rw_unlock(&LOCK_system_variables_hash);
 
1137
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1613
1138
 
1614
1139
  /*
1615
1140
    If the variable exists but the plugin it is associated with is not ready
1632
1157
  uint32_t namelen, length, pluginlen= 0;
1633
1158
  char *varname, *p;
1634
1159
 
1635
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1160
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1636
1161
    return NULL;
1637
1162
 
1638
1163
  namelen= strlen(name);
1639
1164
  if (plugin)
1640
1165
    pluginlen= strlen(plugin) + 1;
1641
1166
  length= namelen + pluginlen + 2;
1642
 
  varname= (char*) my_alloca(length);
 
1167
  varname= (char*) malloc(length);
1643
1168
 
1644
1169
  if (plugin)
1645
1170
  {
1646
 
    strxmov(varname + 1, plugin, "_", name, NULL);
 
1171
    sprintf(varname+1,"%s_%s",plugin,name);
1647
1172
    for (p= varname + 1; *p; p++)
1648
1173
      if (*p == '-')
1649
1174
        *p= '_';
1656
1181
  result= (st_bookmark*) hash_search(&bookmark_hash,
1657
1182
                                     (const unsigned char*) varname, length - 1);
1658
1183
 
1659
 
  my_afree(varname);
 
1184
  free(varname);
1660
1185
  return result;
1661
1186
}
1662
1187
 
1663
1188
 
1664
1189
/*
1665
 
  returns a bookmark for thd-local variables, creating if neccessary.
1666
 
  returns null for non thd-local variables.
 
1190
  returns a bookmark for session-local variables, creating if neccessary.
 
1191
  returns null for non session-local variables.
1667
1192
  Requires that a write lock is obtained on LOCK_system_variables_hash
1668
1193
*/
1669
1194
static st_bookmark *register_var(const char *plugin, const char *name,
1673
1198
  st_bookmark *result;
1674
1199
  char *varname, *p;
1675
1200
 
1676
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1201
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1677
1202
    return NULL;
1678
1203
 
1679
1204
  switch (flags & PLUGIN_VAR_TYPEMASK) {
1680
1205
  case PLUGIN_VAR_BOOL:
1681
 
    size= sizeof(bool);
 
1206
    size= ALIGN_SIZE(sizeof(bool));
1682
1207
    break;
1683
1208
  case PLUGIN_VAR_INT:
1684
 
    size= sizeof(int);
 
1209
    size= ALIGN_SIZE(sizeof(int));
1685
1210
    break;
1686
1211
  case PLUGIN_VAR_LONG:
1687
1212
  case PLUGIN_VAR_ENUM:
1688
 
    size= sizeof(long);
 
1213
    size= ALIGN_SIZE(sizeof(long));
1689
1214
    break;
1690
1215
  case PLUGIN_VAR_LONGLONG:
1691
1216
  case PLUGIN_VAR_SET:
1692
 
    size= sizeof(uint64_t);
 
1217
    size= ALIGN_SIZE(sizeof(uint64_t));
1693
1218
    break;
1694
1219
  case PLUGIN_VAR_STR:
1695
 
    size= sizeof(char*);
 
1220
    size= ALIGN_SIZE(sizeof(char*));
1696
1221
    break;
1697
1222
  default:
1698
1223
    assert(0);
1699
1224
    return NULL;
1700
1225
  };
1701
1226
 
1702
 
  varname= ((char*) my_alloca(length));
1703
 
  strxmov(varname + 1, plugin, "_", name, NULL);
 
1227
  varname= ((char*) malloc(length));
 
1228
  sprintf(varname+1, "%s_%s", plugin, name);
1704
1229
  for (p= varname + 1; *p; p++)
1705
1230
    if (*p == '-')
1706
1231
      *p= '_';
1724
1249
 
1725
1250
    if (new_size > global_variables_dynamic_size)
1726
1251
    {
1727
 
      global_system_variables.dynamic_variables_ptr= (char*)
1728
 
        my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1729
 
                   MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1730
 
      max_system_variables.dynamic_variables_ptr= (char*)
1731
 
        my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1732
 
                   MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
 
1252
      char* tmpptr= NULL;
 
1253
      if (!(tmpptr=
 
1254
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
 
1255
                              new_size)))
 
1256
        return NULL;
 
1257
      global_system_variables.dynamic_variables_ptr= tmpptr;
 
1258
      tmpptr= NULL;
 
1259
      if (!(tmpptr=
 
1260
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
 
1261
                              new_size)))
 
1262
        return NULL;
 
1263
      max_system_variables.dynamic_variables_ptr= tmpptr;
 
1264
           
1733
1265
      /*
1734
1266
        Clear the new variable value space. This is required for string
1735
1267
        variables. If their value is non-NULL, it must point to a valid
1739
1271
             global_variables_dynamic_size, 0,
1740
1272
             new_size - global_variables_dynamic_size);
1741
1273
      memset(max_system_variables.dynamic_variables_ptr +
1742
 
             global_variables_dynamic_size, 0, 
 
1274
             global_variables_dynamic_size, 0,
1743
1275
             new_size - global_variables_dynamic_size);
1744
1276
      global_variables_dynamic_size= new_size;
1745
1277
    }
1760
1292
      assert(0);
1761
1293
    }
1762
1294
  }
1763
 
  my_afree(varname);
 
1295
  free(varname);
1764
1296
  return result;
1765
1297
}
1766
1298
 
1767
1299
 
1768
1300
/*
1769
 
  returns a pointer to the memory which holds the thd-local variable or
1770
 
  a pointer to the global variable if thd==null.
 
1301
  returns a pointer to the memory which holds the session-local variable or
 
1302
  a pointer to the global variable if session==null.
1771
1303
  If required, will sync with global variables if the requested variable
1772
1304
  has not yet been allocated in the current thread.
1773
1305
*/
1774
 
static unsigned char *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
 
1306
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1775
1307
{
1776
1308
  assert(offset >= 0);
1777
 
  assert((uint)offset <= global_system_variables.dynamic_variables_head);
 
1309
  assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1778
1310
 
1779
 
  if (!thd)
 
1311
  if (!session)
1780
1312
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1781
1313
 
1782
1314
  /*
1783
1315
    dynamic_variables_head points to the largest valid offset
1784
1316
  */
1785
 
  if (!thd->variables.dynamic_variables_ptr ||
1786
 
      (uint)offset > thd->variables.dynamic_variables_head)
 
1317
  if (!session->variables.dynamic_variables_ptr ||
 
1318
      (uint32_t)offset > session->variables.dynamic_variables_head)
1787
1319
  {
1788
1320
    uint32_t idx;
1789
1321
 
1790
 
    rw_rdlock(&LOCK_system_variables_hash);
 
1322
    pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1791
1323
 
1792
 
    thd->variables.dynamic_variables_ptr= (char*)
1793
 
      my_realloc(thd->variables.dynamic_variables_ptr,
1794
 
                 global_variables_dynamic_size,
1795
 
                 MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
 
1324
    char *tmpptr= NULL;
 
1325
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
 
1326
                                  global_variables_dynamic_size)))
 
1327
      return NULL;
 
1328
    session->variables.dynamic_variables_ptr= tmpptr;
1796
1329
 
1797
1330
    if (global_lock)
1798
1331
      pthread_mutex_lock(&LOCK_global_system_variables);
1799
1332
 
1800
1333
    safe_mutex_assert_owner(&LOCK_global_system_variables);
1801
1334
 
1802
 
    memcpy(thd->variables.dynamic_variables_ptr +
1803
 
             thd->variables.dynamic_variables_size,
 
1335
    memcpy(session->variables.dynamic_variables_ptr +
 
1336
             session->variables.dynamic_variables_size,
1804
1337
           global_system_variables.dynamic_variables_ptr +
1805
 
             thd->variables.dynamic_variables_size,
 
1338
             session->variables.dynamic_variables_size,
1806
1339
           global_system_variables.dynamic_variables_size -
1807
 
             thd->variables.dynamic_variables_size);
 
1340
             session->variables.dynamic_variables_size);
1808
1341
 
1809
1342
    /*
1810
1343
      now we need to iterate through any newly copied 'defaults'
1816
1349
      sys_var *var;
1817
1350
      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1818
1351
 
1819
 
      if (v->version <= thd->variables.dynamic_variables_version ||
 
1352
      if (v->version <= session->variables.dynamic_variables_version ||
1820
1353
          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1821
1354
          !(pi= var->cast_pluginvar()) ||
1822
1355
          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1827
1360
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1828
1361
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1829
1362
      {
1830
 
         char **pp= (char**) (thd->variables.dynamic_variables_ptr +
 
1363
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
1831
1364
                             *(int*)(pi->plugin_var + 1));
1832
1365
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1833
1366
                             *(int*)(pi->plugin_var + 1))))
1834
 
           *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
 
1367
           *pp= strdup(*pp);
 
1368
         if (*pp == NULL)
 
1369
           return NULL;
1835
1370
      }
1836
1371
    }
1837
1372
 
1838
1373
    if (global_lock)
1839
1374
      pthread_mutex_unlock(&LOCK_global_system_variables);
1840
1375
 
1841
 
    thd->variables.dynamic_variables_version=
 
1376
    session->variables.dynamic_variables_version=
1842
1377
           global_system_variables.dynamic_variables_version;
1843
 
    thd->variables.dynamic_variables_head=
 
1378
    session->variables.dynamic_variables_head=
1844
1379
           global_system_variables.dynamic_variables_head;
1845
 
    thd->variables.dynamic_variables_size=
 
1380
    session->variables.dynamic_variables_size=
1846
1381
           global_system_variables.dynamic_variables_size;
1847
1382
 
1848
 
    rw_unlock(&LOCK_system_variables_hash);
 
1383
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1849
1384
  }
1850
 
  return (unsigned char*)thd->variables.dynamic_variables_ptr + offset;
1851
 
}
1852
 
 
1853
 
static bool *mysql_sys_var_ptr_bool(THD* a_thd, int offset)
1854
 
{
1855
 
  return (bool *)intern_sys_var_ptr(a_thd, offset, true);
1856
 
}
1857
 
 
1858
 
static int *mysql_sys_var_ptr_int(THD* a_thd, int offset)
1859
 
{
1860
 
  return (int *)intern_sys_var_ptr(a_thd, offset, true);
1861
 
}
1862
 
 
1863
 
static long *mysql_sys_var_ptr_long(THD* a_thd, int offset)
1864
 
{
1865
 
  return (long *)intern_sys_var_ptr(a_thd, offset, true);
1866
 
}
1867
 
 
1868
 
static int64_t *mysql_sys_var_ptr_int64_t(THD* a_thd, int offset)
1869
 
{
1870
 
  return (int64_t *)intern_sys_var_ptr(a_thd, offset, true);
1871
 
}
1872
 
 
1873
 
static char **mysql_sys_var_ptr_str(THD* a_thd, int offset)
1874
 
{
1875
 
  return (char **)intern_sys_var_ptr(a_thd, offset, true);
1876
 
}
1877
 
 
1878
 
static uint64_t *mysql_sys_var_ptr_set(THD* a_thd, int offset)
1879
 
{
1880
 
  return (uint64_t *)intern_sys_var_ptr(a_thd, offset, true);
1881
 
}
1882
 
 
1883
 
static unsigned long *mysql_sys_var_ptr_enum(THD* a_thd, int offset)
1884
 
{
1885
 
  return (unsigned long *)intern_sys_var_ptr(a_thd, offset, true);
1886
 
}
1887
 
 
1888
 
 
1889
 
void plugin_thdvar_init(THD *thd)
1890
 
{
1891
 
  plugin_ref old_table_plugin= thd->variables.table_plugin;
1892
 
  
1893
 
  thd->variables.table_plugin= NULL;
1894
 
  cleanup_variables(thd, &thd->variables);
1895
 
  
1896
 
  thd->variables= global_system_variables;
1897
 
  thd->variables.table_plugin= NULL;
 
1385
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
 
1386
}
 
1387
 
 
1388
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
 
1389
{
 
1390
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
 
1391
}
 
1392
 
 
1393
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
 
1394
{
 
1395
  return (int *)intern_sys_var_ptr(a_session, offset, true);
 
1396
}
 
1397
 
 
1398
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
 
1399
{
 
1400
  return (long *)intern_sys_var_ptr(a_session, offset, true);
 
1401
}
 
1402
 
 
1403
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
 
1404
{
 
1405
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1406
}
 
1407
 
 
1408
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
 
1409
{
 
1410
  return (char **)intern_sys_var_ptr(a_session, offset, true);
 
1411
}
 
1412
 
 
1413
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
 
1414
{
 
1415
  return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1416
}
 
1417
 
 
1418
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
 
1419
{
 
1420
  return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
 
1421
}
 
1422
 
 
1423
 
 
1424
void plugin_sessionvar_init(Session *session)
 
1425
{
 
1426
  session->variables.storage_engine= NULL;
 
1427
  cleanup_variables(session, &session->variables);
 
1428
 
 
1429
  session->variables= global_system_variables;
 
1430
  session->variables.storage_engine= NULL;
1898
1431
 
1899
1432
  /* we are going to allocate these lazily */
1900
 
  thd->variables.dynamic_variables_version= 0;
1901
 
  thd->variables.dynamic_variables_size= 0;
1902
 
  thd->variables.dynamic_variables_ptr= 0;
 
1433
  session->variables.dynamic_variables_version= 0;
 
1434
  session->variables.dynamic_variables_size= 0;
 
1435
  session->variables.dynamic_variables_ptr= 0;
1903
1436
 
1904
 
  thd->variables.table_plugin=
1905
 
        my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1906
 
  intern_plugin_unlock(NULL, old_table_plugin);
1907
 
  return;
 
1437
  session->variables.storage_engine= global_system_variables.storage_engine;
1908
1438
}
1909
1439
 
1910
1440
 
1911
1441
/*
1912
1442
  Unlocks all system variables which hold a reference
1913
1443
*/
1914
 
static void unlock_variables(THD *thd __attribute__((unused)),
1915
 
                             struct system_variables *vars)
 
1444
static void unlock_variables(Session *, struct system_variables *vars)
1916
1445
{
1917
 
  intern_plugin_unlock(NULL, vars->table_plugin);
1918
 
  vars->table_plugin= NULL;
 
1446
  vars->storage_engine= NULL;
1919
1447
}
1920
1448
 
1921
1449
 
1925
1453
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
1926
1454
  it's used on shutdown.
1927
1455
*/
1928
 
static void cleanup_variables(THD *thd, struct system_variables *vars)
 
1456
static void cleanup_variables(Session *session, struct system_variables *vars)
1929
1457
{
1930
1458
  st_bookmark *v;
1931
1459
  sys_var_pluginvar *pivar;
1933
1461
  int flags;
1934
1462
  uint32_t idx;
1935
1463
 
1936
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1464
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1937
1465
  for (idx= 0; idx < bookmark_hash.records; idx++)
1938
1466
  {
1939
1467
    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1946
1474
    flags= pivar->plugin_var->flags;
1947
1475
 
1948
1476
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1949
 
        flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
 
1477
        flags & PLUGIN_VAR_SessionLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1950
1478
    {
1951
 
      char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
 
1479
      char **ptr= (char**) pivar->real_value_ptr(session, OPT_SESSION);
1952
1480
      free(*ptr);
1953
1481
      *ptr= NULL;
1954
1482
    }
1955
1483
  }
1956
 
  rw_unlock(&LOCK_system_variables_hash);
 
1484
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
1957
1485
 
1958
 
  assert(vars->table_plugin == NULL);
 
1486
  assert(vars->storage_engine == NULL);
1959
1487
 
1960
1488
  free(vars->dynamic_variables_ptr);
1961
1489
  vars->dynamic_variables_ptr= NULL;
1964
1492
}
1965
1493
 
1966
1494
 
1967
 
void plugin_thdvar_cleanup(THD *thd)
 
1495
void plugin_sessionvar_cleanup(Session *session)
1968
1496
{
1969
 
  uint32_t idx;
1970
 
  plugin_ref *list;
1971
 
 
1972
 
  unlock_variables(thd, &thd->variables);
1973
 
  cleanup_variables(thd, &thd->variables);
1974
 
 
1975
 
  if ((idx= thd->lex->plugins.elements))
1976
 
  {
1977
 
    list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
1978
 
    while ((unsigned char*) list >= thd->lex->plugins.buffer)
1979
 
      intern_plugin_unlock(NULL, *list--);
1980
 
  }
1981
 
 
1982
 
  reset_dynamic(&thd->lex->plugins);
1983
 
 
1984
 
  return;
 
1497
  unlock_variables(session, &session->variables);
 
1498
  cleanup_variables(session, &session->variables);
1985
1499
}
1986
1500
 
1987
1501
 
2056
1570
}
2057
1571
 
2058
1572
 
2059
 
unsigned char* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
 
1573
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2060
1574
{
2061
 
  assert(thd || (type == OPT_GLOBAL));
2062
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
1575
  assert(session || (type == OPT_GLOBAL));
 
1576
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2063
1577
  {
2064
1578
    if (type == OPT_GLOBAL)
2065
 
      thd= NULL;
 
1579
      session= NULL;
2066
1580
 
2067
 
    return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
 
1581
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2068
1582
  }
2069
1583
  return *(unsigned char**) (plugin_var+1);
2070
1584
}
2072
1586
 
2073
1587
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2074
1588
{
2075
 
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
 
1589
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2076
1590
  case PLUGIN_VAR_ENUM:
2077
1591
    return ((sysvar_enum_t *)plugin_var)->typelib;
2078
1592
  case PLUGIN_VAR_SET:
2079
1593
    return ((sysvar_set_t *)plugin_var)->typelib;
2080
 
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2081
 
    return ((thdvar_enum_t *)plugin_var)->typelib;
2082
 
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2083
 
    return ((thdvar_set_t *)plugin_var)->typelib;
 
1594
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
 
1595
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
1596
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
 
1597
    return ((sessionvar_set_t *)plugin_var)->typelib;
2084
1598
  default:
2085
1599
    return NULL;
2086
1600
  }
2088
1602
}
2089
1603
 
2090
1604
 
2091
 
unsigned char* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
2092
 
                                    LEX_STRING *base __attribute__((unused)))
 
1605
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
2093
1606
{
2094
1607
  unsigned char* result;
2095
1608
 
2096
 
  result= real_value_ptr(thd, type);
 
1609
  result= real_value_ptr(session, type);
2097
1610
 
2098
1611
  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2099
1612
    result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2116
1629
 
2117
1630
    result= (unsigned char*) "";
2118
1631
    if (str.length())
2119
 
      result= (unsigned char*) thd->strmake(str.ptr(), str.length()-1);
 
1632
      result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2120
1633
  }
2121
1634
  return result;
2122
1635
}
2123
1636
 
2124
1637
 
2125
 
bool sys_var_pluginvar::check(THD *thd, set_var *var)
 
1638
bool sys_var_pluginvar::check(Session *session, set_var *var)
2126
1639
{
2127
1640
  st_item_value_holder value;
2128
1641
  assert(is_readonly() || plugin_var->check);
2134
1647
  value.item= var->value;
2135
1648
 
2136
1649
  return is_readonly() ||
2137
 
         plugin_var->check(thd, plugin_var, &var->save_result, &value);
 
1650
         plugin_var->check(session, plugin_var, &var->save_result, &value);
2138
1651
}
2139
1652
 
2140
1653
 
2141
 
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
 
1654
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2142
1655
{
2143
1656
  const void *src;
2144
1657
  void *tgt;
2149
1662
    return;
2150
1663
 
2151
1664
  pthread_mutex_lock(&LOCK_global_system_variables);
2152
 
  tgt= real_value_ptr(thd, type);
 
1665
  tgt= real_value_ptr(session, type);
2153
1666
  src= ((void **) (plugin_var + 1) + 1);
2154
1667
 
2155
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
1668
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2156
1669
  {
2157
1670
    if (type != OPT_GLOBAL)
2158
 
      src= real_value_ptr(thd, OPT_GLOBAL);
 
1671
      src= real_value_ptr(session, OPT_GLOBAL);
2159
1672
    else
2160
1673
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2161
1674
        case PLUGIN_VAR_INT:
2162
 
          src= &((thdvar_uint_t*) plugin_var)->def_val;
 
1675
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
2163
1676
          break;
2164
1677
        case PLUGIN_VAR_LONG:
2165
 
          src= &((thdvar_ulong_t*) plugin_var)->def_val;
 
1678
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2166
1679
          break;
2167
1680
        case PLUGIN_VAR_LONGLONG:
2168
 
          src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
 
1681
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2169
1682
          break;
2170
1683
        case PLUGIN_VAR_ENUM:
2171
 
          src= &((thdvar_enum_t*) plugin_var)->def_val;
 
1684
          src= &((sessionvar_enum_t*) plugin_var)->def_val;
2172
1685
          break;
2173
1686
        case PLUGIN_VAR_SET:
2174
 
          src= &((thdvar_set_t*) plugin_var)->def_val;
 
1687
          src= &((sessionvar_set_t*) plugin_var)->def_val;
2175
1688
          break;
2176
1689
        case PLUGIN_VAR_BOOL:
2177
 
          src= &((thdvar_bool_t*) plugin_var)->def_val;
 
1690
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
2178
1691
          break;
2179
1692
        case PLUGIN_VAR_STR:
2180
 
          src= &((thdvar_str_t*) plugin_var)->def_val;
 
1693
          src= &((sessionvar_str_t*) plugin_var)->def_val;
2181
1694
          break;
2182
1695
        default:
2183
1696
          assert(0);
2184
1697
        }
2185
1698
  }
2186
1699
 
2187
 
  /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2188
 
  assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2189
 
              thd == current_thd);
 
1700
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1701
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1702
              session == current_session);
2190
1703
 
2191
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
 
1704
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2192
1705
  {
2193
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
1706
    plugin_var->update(session, plugin_var, tgt, src);
2194
1707
    pthread_mutex_unlock(&LOCK_global_system_variables);
2195
1708
  }
2196
1709
  else
2197
1710
  {
2198
1711
    pthread_mutex_unlock(&LOCK_global_system_variables);
2199
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
1712
    plugin_var->update(session, plugin_var, tgt, src);
2200
1713
  }
2201
1714
}
2202
1715
 
2203
1716
 
2204
 
bool sys_var_pluginvar::update(THD *thd, set_var *var)
 
1717
bool sys_var_pluginvar::update(Session *session, set_var *var)
2205
1718
{
2206
1719
  void *tgt;
2207
1720
 
2208
1721
  assert(is_readonly() || plugin_var->update);
2209
1722
 
2210
 
  /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2211
 
  assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2212
 
              thd == current_thd);
 
1723
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1724
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1725
              session == current_session);
2213
1726
 
2214
1727
  if (is_readonly())
2215
1728
    return 1;
2216
1729
 
2217
1730
  pthread_mutex_lock(&LOCK_global_system_variables);
2218
 
  tgt= real_value_ptr(thd, var->type);
 
1731
  tgt= real_value_ptr(session, var->type);
2219
1732
 
2220
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
 
1733
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2221
1734
  {
2222
1735
    /* variable we are updating has global scope, so we unlock after updating */
2223
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
1736
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2224
1737
    pthread_mutex_unlock(&LOCK_global_system_variables);
2225
1738
  }
2226
1739
  else
2227
1740
  {
2228
1741
    pthread_mutex_unlock(&LOCK_global_system_variables);
2229
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
1742
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2230
1743
  }
2231
1744
 return 0;
2232
1745
}
2246
1759
  options->sub_size= 0;
2247
1760
 
2248
1761
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2249
 
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
 
1762
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2250
1763
  /* global system variables */
2251
1764
  case PLUGIN_VAR_INT:
2252
1765
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2258
1771
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2259
1772
    break;
2260
1773
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2261
 
    OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
 
1774
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
2262
1775
    break;
2263
1776
  case PLUGIN_VAR_LONGLONG:
2264
1777
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2290
1803
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2291
1804
    break;
2292
1805
  /* threadlocal variables */
2293
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
2294
 
    OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
2295
 
    break;
2296
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2297
 
    OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
2298
 
    break;
2299
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
2300
 
    OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
2301
 
    break;
2302
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2303
 
    OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
2304
 
    break;
2305
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
2306
 
    OPTION_SET_LIMITS(GET_LL, options, (thdvar_int64_t_t*) opt);
2307
 
    break;
2308
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2309
 
    OPTION_SET_LIMITS(GET_ULL, options, (thdvar_uint64_t_t*) opt);
2310
 
    break;
2311
 
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
 
1806
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
 
1807
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
 
1808
    break;
 
1809
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1810
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
 
1811
    break;
 
1812
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
 
1813
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
 
1814
    break;
 
1815
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1816
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
 
1817
    break;
 
1818
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
 
1819
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
 
1820
    break;
 
1821
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1822
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
 
1823
    break;
 
1824
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2312
1825
    options->var_type= GET_ENUM;
2313
 
    options->typelib= ((thdvar_enum_t*) opt)->typelib;
2314
 
    options->def_value= ((thdvar_enum_t*) opt)->def_val;
 
1826
    options->typelib= ((sessionvar_enum_t*) opt)->typelib;
 
1827
    options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2315
1828
    options->min_value= options->block_size= 0;
2316
1829
    options->max_value= options->typelib->count - 1;
2317
1830
    break;
2318
 
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
 
1831
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2319
1832
    options->var_type= GET_SET;
2320
 
    options->typelib= ((thdvar_set_t*) opt)->typelib;
2321
 
    options->def_value= ((thdvar_set_t*) opt)->def_val;
 
1833
    options->typelib= ((sessionvar_set_t*) opt)->typelib;
 
1834
    options->def_value= ((sessionvar_set_t*) opt)->def_val;
2322
1835
    options->min_value= options->block_size= 0;
2323
1836
    options->max_value= (1UL << options->typelib->count) - 1;
2324
1837
    break;
2325
 
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
 
1838
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2326
1839
    options->var_type= GET_BOOL;
2327
 
    options->def_value= ((thdvar_bool_t*) opt)->def_val;
 
1840
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2328
1841
    break;
2329
 
  case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
 
1842
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2330
1843
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2331
1844
                        GET_STR_ALLOC : GET_STR);
2332
 
    options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
 
1845
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2333
1846
    break;
2334
1847
  default:
2335
1848
    assert(0);
2344
1857
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2345
1858
                                         char *);
2346
1859
 
2347
 
bool get_one_plugin_option(int optid __attribute__((unused)),
2348
 
                              const struct my_option *opt __attribute__((unused)),
2349
 
                              char *argument __attribute__((unused)))
 
1860
bool get_one_plugin_option(int, const struct my_option *, char *)
2350
1861
{
2351
1862
  return 0;
2352
1863
}
2367
1878
  /* support --skip-plugin-foo syntax */
2368
1879
  memcpy(name, plugin_name, namelen + 1);
2369
1880
  my_casedn_str(&my_charset_utf8_general_ci, name);
2370
 
  strxmov(name + namelen + 1, "plugin-", name, NULL);
 
1881
  sprintf(name+namelen+1, "plugin-%s", name);
2371
1882
  /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2372
1883
 
2373
1884
  for (p= name + namelen*2 + 8; p > name; p--)
2376
1887
 
2377
1888
  if (can_disable)
2378
1889
  {
2379
 
    strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2380
 
            "Disable with --skip-", name," (will save memory).", NULL);
 
1890
    sprintf(name+namelen*2+10,
 
1891
            "Enable %s plugin. Disable with --skip-%s (will save memory).",
 
1892
            plugin_name, name);
2381
1893
    /*
2382
1894
      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2383
1895
      20 + namelen + 20 + 1 == namelen * 4 + 67.
2404
1916
       plugin_option && *plugin_option; plugin_option++, index++)
2405
1917
  {
2406
1918
    opt= *plugin_option;
2407
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
1919
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2408
1920
      continue;
2409
1921
    if (!(register_var(name, opt->name, opt->flags)))
2410
1922
      continue;
2411
1923
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2412
1924
    case PLUGIN_VAR_BOOL:
2413
 
      (((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
 
1925
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2414
1926
      break;
2415
1927
    case PLUGIN_VAR_INT:
2416
 
      (((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
 
1928
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2417
1929
      break;
2418
1930
    case PLUGIN_VAR_LONG:
2419
 
      (((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
 
1931
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2420
1932
      break;
2421
1933
    case PLUGIN_VAR_LONGLONG:
2422
 
      (((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
 
1934
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2423
1935
      break;
2424
1936
    case PLUGIN_VAR_STR:
2425
 
      (((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
 
1937
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2426
1938
      break;
2427
1939
    case PLUGIN_VAR_ENUM:
2428
 
      (((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
 
1940
      (((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2429
1941
      break;
2430
1942
    case PLUGIN_VAR_SET:
2431
 
      (((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
 
1943
      (((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2432
1944
      break;
2433
1945
    default:
2434
 
      sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
 
1946
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2435
1947
                      opt->flags, plugin_name);
2436
1948
      return(-1);
2437
1949
    };
2474
1986
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2475
1987
        {
2476
1988
          opt->flags|= PLUGIN_VAR_READONLY;
2477
 
          sql_print_warning(_("Server variable %s of plugin %s was forced "
 
1989
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2478
1990
                            "to be read-only: string variable without "
2479
1991
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
2480
1992
                            opt->name, plugin_name);
2494
2006
        opt->update= update_func_int64_t;
2495
2007
      break;
2496
2008
    default:
2497
 
      sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
 
2009
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2498
2010
                      opt->flags, plugin_name);
2499
2011
      return(-1);
2500
2012
    }
2501
2013
 
2502
 
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
 
2014
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2503
2015
                    == PLUGIN_VAR_NOCMDOPT)
2504
2016
      continue;
2505
2017
 
2506
2018
    if (!opt->name)
2507
2019
    {
2508
 
      sql_print_error(_("Missing variable name in plugin '%s'."),
 
2020
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2509
2021
                      plugin_name);
2510
2022
      return(-1);
2511
2023
    }
2512
2024
 
2513
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2025
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2514
2026
    {
2515
2027
      optnamelen= strlen(opt->name);
2516
2028
      optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2517
 
      strxmov(optname, name, "-", opt->name, NULL);
 
2029
      sprintf(optname, "%s-%s", name, opt->name);
2518
2030
      optnamelen= namelen + optnamelen + 1;
2519
2031
    }
2520
2032
    else
2522
2034
      /* this should not fail because register_var should create entry */
2523
2035
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
2524
2036
      {
2525
 
        sql_print_error(_("Thread local variable '%s' not allocated "
 
2037
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2526
2038
                        "in plugin '%s'."), opt->name, plugin_name);
2527
2039
        return(-1);
2528
2040
      }
2532
2044
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2533
2045
        continue;
2534
2046
 
2535
 
      optname= (char*) memdup_root(mem_root, v->key + 1, 
 
2047
      optname= (char*) memdup_root(mem_root, v->key + 1,
2536
2048
                                   (optnamelen= v->name_len) + 1);
2537
2049
    }
2538
2050
 
2548
2060
 
2549
2061
    plugin_opt_set_limits(options, opt);
2550
2062
 
2551
 
    if (opt->flags & PLUGIN_VAR_THDLOCAL)
 
2063
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2552
2064
      options->value= options->u_max_value= (char**)
2553
2065
        (global_system_variables.dynamic_variables_ptr + offset);
2554
2066
    else
2557
2069
    options[1]= options[0];
2558
2070
    options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2559
2071
    options[1].comment= 0; // hidden
2560
 
    strxmov(p, "plugin-", optname, NULL);
 
2072
    sprintf(p,"plugin-%s",optname);
2561
2073
 
2562
2074
    options+= 2;
2563
2075
  }
2577
2089
  for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2578
2090
 
2579
2091
  if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
2580
 
    return(NULL);
 
2092
    return NULL;
2581
2093
 
2582
2094
  memset(opts, 0, sizeof(my_option) * count);
2583
2095
 
2590
2102
 
2591
2103
 
2592
2104
  if (construct_options(mem_root, p, opts, can_disable))
2593
 
    return(NULL);
 
2105
    return NULL;
2594
2106
 
2595
2107
  return(opts);
2596
2108
}
2613
2125
                               int *argc, char **argv)
2614
2126
{
2615
2127
  struct sys_var_chain chain= { NULL, NULL };
2616
 
  bool enabled_saved= true;
2617
2128
  bool can_disable;
2618
2129
  MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
2619
2130
                      &tmp->mem_root : &plugin_mem_root;
2641
2152
  {
2642
2153
    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2643
2154
    {
2644
 
      sql_print_error(_("Out of memory for plugin '%s'."), tmp->name.str);
 
2155
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->name.str);
2645
2156
      return(-1);
2646
2157
    }
2647
2158
    memset(opts, 0, sizeof(my_option) * count);
2648
2159
 
2649
2160
    if (construct_options(tmp_root, tmp, opts, can_disable))
2650
2161
    {
2651
 
      sql_print_error(_("Bad options for plugin '%s'."), tmp->name.str);
 
2162
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->name.str);
2652
2163
      return(-1);
2653
2164
    }
2654
2165
 
2657
2168
 
2658
2169
    if (error)
2659
2170
    {
2660
 
       sql_print_error(_("Parsing options for plugin '%s' failed."),
 
2171
       errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2661
2172
                       tmp->name.str);
2662
2173
       goto err;
2663
2174
    }
2677
2188
      {
2678
2189
        len= tmp->name.length + strlen(o->name) + 2;
2679
2190
        varname= (char*) alloc_root(mem_root, len);
2680
 
        strxmov(varname, tmp->name.str, "-", o->name, NULL);
 
2191
        sprintf(varname,"%s-%s",tmp->name.str,o->name);
2681
2192
        my_casedn_str(&my_charset_utf8_general_ci, varname);
2682
2193
 
2683
2194
        for (p= varname; *p; p++)
2700
2211
      chain.last->next = NULL;
2701
2212
      if (mysql_add_sys_var_chain(chain.first, NULL))
2702
2213
      {
2703
 
        sql_print_error(_("Plugin '%s' has conflicting system variables"),
 
2214
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2704
2215
                        tmp->name.str);
2705
2216
        goto err;
2706
2217
      }
2709
2220
    return(0);
2710
2221
  }
2711
2222
 
2712
 
  if (enabled_saved && global_system_variables.log_warnings)
2713
 
    sql_print_information(_("Plugin '%s' disabled by command line option"),
2714
 
                          tmp->name.str);
2715
2223
err:
2716
2224
  if (opts)
2717
2225
    my_cleanup_options(opts);