~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_plugin.cc

  • Committer: Monty Taylor
  • Date: 2009-03-24 17:44:41 UTC
  • mto: (960.5.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 964.
  • Revision ID: mordred@inaugust.com-20090324174441-nmsq0gwjlgf7f0mt
Changed handlerton to StorageEngine.

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/configvar.h>
 
24
#include <drizzled/qcache.h>
 
25
#include <drizzled/parser.h>
 
26
#include <drizzled/sql_parse.h>
 
27
#include <drizzled/scheduling.h>
 
28
#include <drizzled/replicator.h>
 
29
#include <drizzled/show.h>
 
30
#include <drizzled/handler.h>
 
31
#include <drizzled/set_var.h>
 
32
#include <drizzled/session.h>
 
33
#include <drizzled/item/null.h>
 
34
#include <drizzled/plugin_registry.h>
 
35
 
 
36
#include <string>
 
37
#include <vector>
 
38
#include <map>
 
39
 
 
40
#include <drizzled/error.h>
 
41
#include <drizzled/gettext.h>
 
42
 
21
43
#define REPORT_TO_LOG  1
22
44
#define REPORT_TO_USER 2
23
45
 
24
46
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
25
47
#define plugin_int_to_ref(A) &(A)
26
48
 
 
49
using namespace std;
 
50
 
27
51
extern struct st_mysql_plugin *mysqld_builtins[];
28
52
 
29
53
char *opt_plugin_load= NULL;
42
66
  { C_STRING_WITH_LEN("UDA") },
43
67
  { C_STRING_WITH_LEN("AUDIT") },
44
68
  { C_STRING_WITH_LEN("LOGGER") },
45
 
  { C_STRING_WITH_LEN("AUTH") }
 
69
  { C_STRING_WITH_LEN("ERRMSG") },
 
70
  { C_STRING_WITH_LEN("AUTH") },
 
71
  { C_STRING_WITH_LEN("CONFIGVAR") },
 
72
  { C_STRING_WITH_LEN("QCACHE") },
 
73
  { C_STRING_WITH_LEN("PARSER") },
 
74
  { C_STRING_WITH_LEN("SCHEDULING") },
 
75
  { C_STRING_WITH_LEN("REPLICATOR") }
46
76
};
47
77
 
48
78
extern int initialize_schema_table(st_plugin_int *plugin);
65
95
  0,  /* UDA */
66
96
  0,  /* Audit */
67
97
  logging_initializer,  /* Logger */
68
 
  authentication_initializer  /* Auth */
 
98
  errmsg_initializer,  /* Error Messages */
 
99
  authentication_initializer,  /* Auth */
 
100
  configvar_initializer,
 
101
  qcache_initializer,
 
102
  parser_initializer,
 
103
  scheduling_initializer,
 
104
  replicator_initializer
69
105
};
70
106
 
71
107
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
77
113
  0,  /* UDA */
78
114
  0,  /* Audit */
79
115
  logging_finalizer,  /* Logger */
80
 
  authentication_finalizer  /* Auth */
 
116
  errmsg_finalizer,  /* Logger */
 
117
  authentication_finalizer,  /* Auth */
 
118
  configvar_finalizer,
 
119
  qcache_finalizer,
 
120
  parser_finalizer,
 
121
  scheduling_finalizer,
 
122
  replicator_finalizer
81
123
};
82
124
 
83
125
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
90
132
 
91
133
static DYNAMIC_ARRAY plugin_dl_array;
92
134
static DYNAMIC_ARRAY plugin_array;
93
 
static HASH plugin_hash[DRIZZLE_MAX_PLUGIN_TYPE_NUM];
 
135
 
94
136
static bool reap_needed= false;
95
137
static int plugin_array_version=0;
96
138
 
115
157
 
116
158
/*
117
159
  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
 
160
  hash and is used to mark a single offset for a session local variable
119
161
  even if plugins have been uninstalled and reinstalled, repeatedly.
120
162
  This structure is allocated from plugin_mem_root.
121
163
 
152
194
  struct st_mysql_sys_var *plugin_var;
153
195
 
154
196
  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)))
 
197
  { return (void*) alloc_root(mem_root, (uint32_t) size); }
 
198
  static void operator delete(void *, size_t)
158
199
  { TRASH(ptr_arg, size); }
159
200
 
160
201
  sys_var_pluginvar(const char *name_arg,
163
204
  sys_var_pluginvar *cast_pluginvar() { return this; }
164
205
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
165
206
  bool check_type(enum_var_type type)
166
 
  { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
 
207
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
167
208
  bool check_update_type(Item_result type);
168
209
  SHOW_TYPE show_type();
169
 
  unsigned char* real_value_ptr(THD *thd, enum_var_type type);
 
210
  unsigned char* real_value_ptr(Session *session, enum_var_type type);
170
211
  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)))
 
212
  unsigned char* value_ptr(Session *session, enum_var_type type,
 
213
                           const LEX_STRING *base);
 
214
  bool check(Session *session, set_var *var);
 
215
  bool check_default(enum_var_type)
174
216
    { return is_readonly(); }
175
 
  void set_default(THD *thd,
176
 
                   enum_var_type type __attribute__((unused)));
177
 
  bool update(THD *thd, set_var *var);
 
217
  void set_default(Session *session, enum_var_type);
 
218
  bool update(Session *session, set_var *var);
178
219
};
179
220
 
180
221
 
185
226
                               int *, char **);
186
227
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
187
228
                             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);
 
229
static void unlock_variables(Session *session, struct system_variables *vars);
 
230
static void cleanup_variables(Session *session, struct system_variables *vars);
190
231
static void plugin_vars_free_values(sys_var *vars);
191
232
static void plugin_opt_set_limits(struct my_option *options,
192
233
                                  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);
 
234
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
 
235
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
 
236
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
197
237
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
198
238
static void reap_plugins(void);
199
239
 
200
240
 
201
241
/* declared in set_var.cc */
202
242
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,
 
243
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
204
244
                                 const char *name, int64_t val);
205
245
 
206
246
/****************************************************************************
233
273
    Lets be nice and create a temporary string since the
234
274
    buffer was too small
235
275
  */
236
 
  return current_thd->strmake(res->c_ptr_quick(), res->length());
 
276
  return current_session->strmake(res->c_ptr_quick(), res->length());
237
277
}
238
278
 
239
279
 
265
305
{
266
306
  uint32_t i;
267
307
  struct st_plugin_dl *tmp;
 
308
 
268
309
  for (i= 0; i < plugin_dl_array.elements; i++)
269
310
  {
270
311
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
281
322
{
282
323
  uint32_t i;
283
324
  struct st_plugin_dl *tmp;
 
325
 
284
326
  for (i= 0; i < plugin_dl_array.elements; i++)
285
327
  {
286
328
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
309
351
 
310
352
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
311
353
{
312
 
  char dlpath[FN_REFLEN];
313
 
  uint32_t plugin_dir_len, dummy_errors, dlpathlen;
 
354
  string dlpath;
 
355
  uint32_t plugin_dir_len, dummy_errors;
314
356
  struct st_plugin_dl *tmp, plugin_dl;
315
357
  void *sym;
316
358
  plugin_dir_len= strlen(opt_plugin_dir);
 
359
  dlpath.reserve(FN_REFLEN);
317
360
  /*
318
361
    Ensure that the dll doesn't have a path.
319
362
    This is done to ensure that only approved libraries from the
327
370
    if (report & REPORT_TO_USER)
328
371
      my_error(ER_UDF_NO_PATHS, MYF(0));
329
372
    if (report & REPORT_TO_LOG)
330
 
      sql_print_error(ER(ER_UDF_NO_PATHS));
 
373
      errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
331
374
    return(0);
332
375
  }
333
376
  /* If this dll is already loaded just increase ref_count. */
338
381
  }
339
382
  memset(&plugin_dl, 0, sizeof(plugin_dl));
340
383
  /* Compile dll path */
341
 
  dlpathlen=
342
 
    strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NULL) -
343
 
    dlpath;
 
384
  dlpath.append(opt_plugin_dir);
 
385
  dlpath.append("/");
 
386
  dlpath.append(dl->str);
344
387
  plugin_dl.ref_count= 1;
345
388
  /* Open new dll handle */
346
 
  if (!(plugin_dl.handle= dlopen(dlpath, RTLD_LAZY|RTLD_GLOBAL)))
 
389
  if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
347
390
  {
348
391
    const char *errmsg=dlerror();
349
 
    if (!strncmp(dlpath, errmsg, dlpathlen))
 
392
    uint32_t dlpathlen= dlpath.length();
 
393
    if (!dlpath.compare(0, dlpathlen, errmsg))
350
394
    { // if errmsg starts from dlpath, trim this prefix.
351
395
      errmsg+=dlpathlen;
352
396
      if (*errmsg == ':') errmsg++;
353
397
      if (*errmsg == ' ') errmsg++;
354
398
    }
355
399
    if (report & REPORT_TO_USER)
356
 
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
 
400
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
357
401
    if (report & REPORT_TO_LOG)
358
 
      sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
 
402
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
359
403
    return(0);
360
404
  }
361
405
 
366
410
    if (report & REPORT_TO_USER)
367
411
      my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
368
412
    if (report & REPORT_TO_LOG)
369
 
      sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
 
413
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
370
414
    return(0);
371
415
  }
372
416
 
374
418
 
375
419
  /* Duplicate and convert dll name */
376
420
  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))))
 
421
  if (! (plugin_dl.dl.str= (char*) malloc(plugin_dl.dl.length)))
378
422
  {
379
423
    free_plugin_mem(&plugin_dl);
380
424
    if (report & REPORT_TO_USER)
381
425
      my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
382
426
    if (report & REPORT_TO_LOG)
383
 
      sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
 
427
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
384
428
    return(0);
385
429
  }
386
430
  plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
394
438
    if (report & REPORT_TO_USER)
395
439
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
396
440
    if (report & REPORT_TO_LOG)
397
 
      sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
 
441
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
398
442
    return(0);
399
443
  }
400
444
  return(tmp);
427
471
}
428
472
 
429
473
 
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
474
 
453
475
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
454
476
{
 
477
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
478
 
455
479
  SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
456
480
  struct st_plugin_int *plugin;
457
 
  if ((plugin= plugin_find_internal(name, type)))
 
481
 
 
482
  if (! initialized)
 
483
    return(rc);
 
484
 
 
485
  if ((plugin= registry.find(name, type)))
458
486
  {
459
487
    rc= SHOW_OPTION_DISABLED;
460
488
    if (plugin->state == PLUGIN_IS_READY)
480
508
}
481
509
 
482
510
 
483
 
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
 
511
static plugin_ref intern_plugin_lock(LEX *, plugin_ref rc)
484
512
{
485
513
  st_plugin_int *pi= plugin_ref_to_int(rc);
486
514
 
492
520
      memory manager and/or valgrind to track locked references and
493
521
      double unlocks to aid resolving reference counting.problems.
494
522
    */
495
 
    if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
 
523
    if (!(plugin= (plugin_ref) malloc(sizeof(pi))))
496
524
      return(NULL);
497
525
 
498
526
    *plugin= pi;
499
527
    pi->ref_count++;
500
528
 
501
 
    if (lex)
502
 
      insert_dynamic(&lex->plugins, (unsigned char*)&plugin);
503
529
    return(plugin);
504
530
  }
505
531
  return(NULL);
506
532
}
507
533
 
508
534
 
509
 
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
 
535
plugin_ref plugin_lock(Session *session, plugin_ref *ptr)
510
536
{
511
 
  LEX *lex= thd ? thd->lex : 0;
 
537
  LEX *lex= session ? session->lex : 0;
512
538
  plugin_ref rc;
513
539
  rc= my_intern_plugin_lock_ci(lex, *ptr);
514
540
  return(rc);
515
541
}
516
542
 
517
543
 
518
 
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
519
 
                               CALLER_INFO_PROTO)
 
544
plugin_ref plugin_lock_by_name(Session *session, const LEX_STRING *name, int type)
520
545
{
521
 
  LEX *lex= thd ? thd->lex : 0;
 
546
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
547
 
 
548
  LEX *lex= session ? session->lex : 0;
522
549
  plugin_ref rc= NULL;
523
550
  st_plugin_int *plugin;
524
 
  if ((plugin= plugin_find_internal(name, type)))
 
551
  if (! initialized)
 
552
    return(0);
 
553
 
 
554
  if ((plugin= registry.find(name, type)))
525
555
    rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
526
556
  return(rc);
527
557
}
558
588
                       const LEX_STRING *name, const LEX_STRING *dl,
559
589
                       int *argc, char **argv, int report)
560
590
{
 
591
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
592
 
561
593
  struct st_plugin_int tmp;
562
594
  struct st_mysql_plugin *plugin;
563
 
  if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
 
595
  if (! initialized)
 
596
    return(0);
 
597
 
 
598
  if (registry.find(name, DRIZZLE_ANY_PLUGIN))
564
599
  {
565
600
    if (report & REPORT_TO_USER)
566
601
      my_error(ER_UDF_EXISTS, MYF(0), name->str);
567
602
    if (report & REPORT_TO_LOG)
568
 
      sql_print_error(ER(ER_UDF_EXISTS), name->str);
 
603
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
569
604
    return(true);
570
605
  }
571
606
  /* Clear the whole struct to catch future extensions. */
576
611
  for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
577
612
  {
578
613
    uint32_t name_len= strlen(plugin->name);
579
 
    if (plugin->type >= 0 && plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
 
614
    if (plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
580
615
        ! my_strnncoll(system_charset_info,
581
616
                       (const unsigned char *)name->str, name->length,
582
617
                       (const unsigned char *)plugin->name,
594
629
        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
595
630
        {
596
631
          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;
 
632
          registry.add(plugin, tmp_plugin_ptr);
 
633
          init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
 
634
          return(false);
603
635
        }
604
636
        mysql_del_sys_var_chain(tmp.system_vars);
605
637
        goto err;
612
644
  if (report & REPORT_TO_USER)
613
645
    my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
614
646
  if (report & REPORT_TO_LOG)
615
 
    sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
 
647
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
616
648
err:
617
649
  plugin_dl_del(dl);
618
650
  return(true);
645
677
  {
646
678
    if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
647
679
    {
648
 
      sql_print_error(_("Plugin '%s' of type %s failed deinitialization"),
 
680
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' of type %s failed deinitialization"),
649
681
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
650
682
    }
651
683
  }
655
687
  plugin->state= PLUGIN_IS_UNINITIALIZED;
656
688
 
657
689
  /*
658
 
    We do the check here because NDB has a worker THD which doesn't
 
690
    We do the check here because NDB has a worker Session which doesn't
659
691
    exit until NDB is shut down.
660
692
  */
661
693
  if (ref_check && plugin->ref_count)
662
 
    sql_print_error(_("Plugin '%s' has ref_count=%d after deinitialization."),
 
694
    errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has ref_count=%d after deinitialization."),
663
695
                    plugin->name.str, plugin->ref_count);
664
696
}
665
697
 
668
700
{
669
701
  /* Free allocated strings before deleting the plugin. */
670
702
  plugin_vars_free_values(plugin->system_vars);
671
 
  hash_delete(&plugin_hash[plugin->plugin->type], (unsigned char*)plugin);
672
703
  if (plugin->plugin_dl)
673
704
    plugin_dl_del(&plugin->plugin_dl->dl);
674
705
  plugin->state= PLUGIN_IS_FREED;
675
706
  plugin_array_version++;
676
 
  rw_wrlock(&LOCK_system_variables_hash);
 
707
  pthread_rwlock_wrlock(&LOCK_system_variables_hash);
677
708
  mysql_del_sys_var_chain(plugin->system_vars);
678
 
  rw_unlock(&LOCK_system_variables_hash);
 
709
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
679
710
  free_root(&plugin->mem_root, MYF(0));
680
711
  return;
681
712
}
682
713
 
683
714
static void reap_plugins(void)
684
715
{
685
 
  uint32_t count, idx;
686
 
  struct st_plugin_int *plugin, **reap, **list;
687
 
 
688
 
  if (!reap_needed)
689
 
    return;
 
716
  size_t count;
 
717
  uint32_t idx;
 
718
  struct st_plugin_int *plugin;
690
719
 
691
720
  reap_needed= false;
692
721
  count= plugin_array.elements;
693
 
  reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
694
 
  *(reap++)= NULL;
695
722
 
696
723
  for (idx= 0; idx < count; idx++)
697
724
  {
698
725
    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)))
 
726
    plugin->state= PLUGIN_IS_DYING;
709
727
    plugin_deinitialize(plugin, true);
710
 
 
711
 
  while ((plugin= *(--reap)))
712
728
    plugin_del(plugin);
713
 
 
714
 
  my_afree(reap);
 
729
  }
715
730
}
716
731
 
717
 
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
 
732
static void intern_plugin_unlock(LEX *, plugin_ref plugin)
718
733
{
719
 
  int i;
720
734
  st_plugin_int *pi;
721
735
 
722
736
  if (!plugin)
724
738
 
725
739
  pi= plugin_ref_to_int(plugin);
726
740
 
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--;
 
741
  free((void *) plugin);
 
742
 
 
743
  //assert(pi->ref_count);
 
744
  if (pi->ref_count > 0)
 
745
    pi->ref_count--;
747
746
 
748
747
  if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
749
748
    reap_needed= true;
752
751
}
753
752
 
754
753
 
755
 
void plugin_unlock(THD *thd, plugin_ref plugin)
 
754
void plugin_unlock(Session *session, plugin_ref plugin)
756
755
{
757
 
  LEX *lex= thd ? thd->lex : 0;
 
756
  LEX *lex= session ? session->lex : 0;
758
757
  if (!plugin)
759
758
    return;
760
759
  intern_plugin_unlock(lex, plugin);
762
761
}
763
762
 
764
763
 
765
 
void plugin_unlock_list(THD *thd, plugin_ref *list, uint32_t count)
 
764
void plugin_unlock_list(Session *session, plugin_ref *list, uint32_t count)
766
765
{
767
 
  LEX *lex= thd ? thd->lex : 0;
 
766
  LEX *lex= session ? session->lex : 0;
768
767
  assert(list);
769
768
  while (count--)
770
769
    intern_plugin_unlock(lex, *list++);
774
773
 
775
774
static int plugin_initialize(struct st_plugin_int *plugin)
776
775
{
 
776
  plugin->state= PLUGIN_IS_UNINITIALIZED;
777
777
 
778
778
  if (plugin_type_initialize[plugin->plugin->type])
779
779
  {
780
780
    if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
781
781
    {
782
 
      sql_print_error(_("Plugin '%s' registration as a %s failed."),
 
782
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' registration as a %s failed."),
783
783
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
784
784
      goto err;
785
785
    }
788
788
  {
789
789
    if (plugin->plugin->init(plugin))
790
790
    {
791
 
      sql_print_error(_("Plugin '%s' init function returned error."),
 
791
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' init function returned error."),
792
792
                      plugin->name.str);
793
793
      goto err;
794
794
    }
 
795
    plugin->state= PLUGIN_IS_READY;
795
796
  }
796
797
 
797
 
  plugin->state= PLUGIN_IS_READY;
798
 
 
799
798
  if (plugin->plugin->status_vars)
800
799
  {
801
800
#ifdef FIX_LATER
839
838
}
840
839
 
841
840
 
842
 
extern "C" unsigned char *get_plugin_hash_key(const unsigned char *, size_t *, bool);
843
841
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
844
842
 
845
843
 
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)))
 
844
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
857
845
{
858
846
  struct st_bookmark *var= (st_bookmark *)buff;
859
847
  *length= var->name_len + 1;
870
858
*/
871
859
int plugin_init(int *argc, char **argv, int flags)
872
860
{
873
 
  uint32_t i;
 
861
  uint32_t idx;
874
862
  struct st_mysql_plugin **builtins;
875
863
  struct st_mysql_plugin *plugin;
876
 
  struct st_plugin_int tmp, *plugin_ptr, **reap;
 
864
  struct st_plugin_int tmp, *plugin_ptr;
877
865
  MEM_ROOT tmp_root;
878
866
 
879
867
  if (initialized)
893
881
                            sizeof(struct st_plugin_int *),16,16))
894
882
    goto err;
895
883
 
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
884
  initialized= 1;
904
885
 
905
886
  /*
954
935
  /*
955
936
    Now we initialize all remaining plugins
956
937
  */
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++)
 
938
  for (idx= 0; idx < plugin_array.elements; idx++)
962
939
  {
963
 
    plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
 
940
    plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
964
941
    if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
965
942
    {
966
943
      if (plugin_initialize(plugin_ptr))
967
944
      {
968
945
        plugin_ptr->state= PLUGIN_IS_DYING;
969
 
        *(reap++)= plugin_ptr;
 
946
        plugin_deinitialize(plugin_ptr, true);
 
947
        plugin_del(plugin_ptr);
970
948
      }
971
949
    }
972
950
  }
973
951
 
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
952
 
985
953
end:
986
954
  free_root(&tmp_root, MYF(0));
999
967
                             struct st_plugin_int **ptr)
1000
968
{
1001
969
 
 
970
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
971
 
1002
972
  tmp->state= PLUGIN_IS_UNINITIALIZED;
1003
973
  tmp->ref_count= 0;
1004
974
  tmp->plugin_dl= 0;
1011
981
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
1012
982
                                             sizeof(struct st_plugin_int));
1013
983
 
1014
 
  if (my_hash_insert(&plugin_hash[plugin->type],(unsigned char*) *ptr))
1015
 
    return(1);
 
984
  registry.add(plugin, *ptr);
1016
985
 
1017
986
  return(0);
1018
987
}
1033
1002
  {
1034
1003
    if (p == buffer + sizeof(buffer) - 1)
1035
1004
    {
1036
 
      sql_print_error(_("plugin-load parameter too long"));
 
1005
      errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
1037
1006
      return(true);
1038
1007
    }
1039
1008
 
1093
1062
  }
1094
1063
  return(false);
1095
1064
error:
1096
 
  sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
 
1065
  errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
1097
1066
                  name.str, dl.str);
1098
1067
  return(true);
1099
1068
}
1101
1070
 
1102
1071
void plugin_shutdown(void)
1103
1072
{
1104
 
  uint32_t i, count= plugin_array.elements, free_slots= 0;
1105
 
  struct st_plugin_int **plugins, *plugin;
1106
 
  struct st_plugin_dl **dl;
 
1073
  uint32_t idx, free_slots= 0;
 
1074
  size_t count= plugin_array.elements;
 
1075
  struct st_plugin_int *plugin;
 
1076
  vector<st_plugin_int *> plugins;
 
1077
  vector<st_plugin_dl *> dl;
1107
1078
 
1108
1079
  if (initialized)
1109
1080
  {
1119
1090
    while (reap_needed && (count= plugin_array.elements))
1120
1091
    {
1121
1092
      reap_plugins();
1122
 
      for (i= free_slots= 0; i < count; i++)
 
1093
      for (idx= free_slots= 0; idx < count; idx++)
1123
1094
      {
1124
 
        plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
 
1095
        plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1125
1096
        switch (plugin->state) {
1126
1097
        case PLUGIN_IS_READY:
1127
1098
          plugin->state= PLUGIN_IS_DELETED;
1144
1115
    }
1145
1116
 
1146
1117
    if (count > free_slots)
1147
 
      sql_print_warning(_("Forcing shutdown of %d plugins"),
1148
 
                        count - free_slots);
 
1118
      errmsg_printf(ERRMSG_LVL_WARN, _("Forcing shutdown of %"PRIu64" plugins"),
 
1119
                        (uint64_t)count - free_slots);
1149
1120
 
1150
 
    plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
 
1121
    plugins.reserve(count);
1151
1122
 
1152
1123
    /*
1153
1124
      If we have any plugins which did not die cleanly, we force shutdown
1154
1125
    */
1155
 
    for (i= 0; i < count; i++)
 
1126
    for (idx= 0; idx < count; idx++)
1156
1127
    {
1157
 
      plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
 
1128
      plugins.push_back(*dynamic_element(&plugin_array, idx,
 
1129
                                         struct st_plugin_int **));
1158
1130
      /* change the state to ensure no reaping races */
1159
 
      if (plugins[i]->state == PLUGIN_IS_DELETED)
1160
 
        plugins[i]->state= PLUGIN_IS_DYING;
 
1131
      if (plugins[idx]->state == PLUGIN_IS_DELETED)
 
1132
        plugins[idx]->state= PLUGIN_IS_DYING;
1161
1133
    }
1162
1134
 
1163
1135
    /*
1164
1136
      We loop through all plugins and call deinit() if they have one.
1165
1137
    */
1166
 
    for (i= 0; i < count; i++)
1167
 
      if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
 
1138
    for (idx= 0; idx < count; idx++)
 
1139
      if (!(plugins[idx]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1168
1140
      {
1169
 
        sql_print_information(_("Plugin '%s' will be forced to shutdown"),
1170
 
                              plugins[i]->name.str);
 
1141
        errmsg_printf(ERRMSG_LVL_INFO, _("Plugin '%s' will be forced to shutdown"),
 
1142
                              plugins[idx]->name.str);
1171
1143
        /*
1172
1144
          We are forcing deinit on plugins so we don't want to do a ref_count
1173
1145
          check until we have processed all the plugins.
1174
1146
        */
1175
 
        plugin_deinitialize(plugins[i], false);
 
1147
        plugin_deinitialize(plugins[idx], false);
1176
1148
      }
1177
1149
 
1178
1150
    /*
1179
1151
      We defer checking ref_counts until after all plugins are deinitialized
1180
1152
      as some may have worker threads holding on to plugin references.
1181
1153
    */
1182
 
    for (i= 0; i < count; i++)
 
1154
    for (idx= 0; idx < count; idx++)
1183
1155
    {
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]);
 
1156
      if (plugins[idx]->ref_count)
 
1157
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has ref_count=%d after shutdown."),
 
1158
                        plugins[idx]->name.str, plugins[idx]->ref_count);
 
1159
      if (plugins[idx]->state & PLUGIN_IS_UNINITIALIZED)
 
1160
        plugin_del(plugins[idx]);
1189
1161
    }
1190
1162
 
1191
1163
    /*
1197
1169
 
1198
1170
    initialized= 0;
1199
1171
 
1200
 
    my_afree(plugins);
1201
1172
  }
1202
1173
 
1203
1174
  /* Dispose of the memory */
1204
1175
 
1205
 
  for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1206
 
    hash_free(&plugin_hash[i]);
1207
1176
  delete_dynamic(&plugin_array);
1208
1177
 
1209
1178
  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);
 
1179
  dl.reserve(count);
 
1180
  for (idx= 0; idx < count; idx++)
 
1181
    dl.push_back(*dynamic_element(&plugin_dl_array, idx,
 
1182
                 struct st_plugin_dl **));
 
1183
  for (idx= 0; idx < count; idx++)
 
1184
    free_plugin_mem(dl[idx]);
1216
1185
  delete_dynamic(&plugin_dl_array);
1217
1186
 
1218
1187
  hash_free(&bookmark_hash);
1223
1192
  return;
1224
1193
}
1225
1194
 
1226
 
 
1227
 
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1228
 
                       int type, uint32_t state_mask, void *arg)
 
1195
/**
 
1196
 *
 
1197
 * state_mask: defaults to PLUGIN_IS_READY
 
1198
 */
 
1199
bool plugin_foreach(Session *session, plugin_foreach_func *func,
 
1200
                    int type, void *arg,
 
1201
                    uint32_t state_mask)
1229
1202
{
1230
 
  uint32_t idx, total;
1231
 
  struct st_plugin_int *plugin, **plugins;
 
1203
  uint32_t idx;
 
1204
  struct st_plugin_int *plugin;
 
1205
  vector<st_plugin_int *> plugins;
1232
1206
  int version=plugin_array_version;
1233
1207
 
1234
1208
  if (!initialized)
1236
1210
 
1237
1211
  state_mask= ~state_mask; // do it only once
1238
1212
 
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));
 
1213
 
1246
1214
  if (type == DRIZZLE_ANY_PLUGIN)
1247
1215
  {
1248
 
    for (idx= 0; idx < total; idx++)
 
1216
    plugins.reserve(plugin_array.elements);
 
1217
    for (idx= 0; idx < plugin_array.elements; idx++)
1249
1218
    {
1250
1219
      plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1251
 
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
 
1220
      plugins.push_back(!(plugin->state & state_mask) ? plugin : NULL);
1252
1221
    }
1253
1222
  }
1254
1223
  else
1255
1224
  {
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
 
    }
 
1225
    Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
1226
    registry.get_mask_list(type, plugins, state_mask);
1262
1227
  }
1263
 
  for (idx= 0; idx < total; idx++)
 
1228
 
 
1229
  vector<st_plugin_int *>::iterator plugin_iter;
 
1230
  for (plugin_iter= plugins.begin();
 
1231
       plugin_iter != plugins.end();
 
1232
       plugin_iter++)
1264
1233
  {
1265
1234
    if (unlikely(version != plugin_array_version))
1266
1235
    {
1267
 
      for (uint32_t i=idx; i < total; i++)
1268
 
        if (plugins[i] && plugins[i]->state & state_mask)
1269
 
          plugins[i]=0;
 
1236
      vector<st_plugin_int *>::iterator reset_iter;
 
1237
      for (reset_iter= plugin_iter;
 
1238
           reset_iter != plugins.end();
 
1239
           reset_iter++)
 
1240
        if (*reset_iter && (*reset_iter)->state & state_mask)
 
1241
          *reset_iter=0;
1270
1242
    }
1271
 
    plugin= plugins[idx];
 
1243
    plugin= *plugin_iter;
1272
1244
    /* It will stop iterating on first engine error when "func" returns true */
1273
 
    if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
 
1245
    if (plugin && func(session, plugin_int_to_ref(plugin), arg))
1274
1246
        goto err;
1275
1247
  }
1276
1248
 
1277
 
  my_afree(plugins);
1278
 
  return(false);
 
1249
  return false;
1279
1250
err:
1280
 
  my_afree(plugins);
1281
 
  return(true);
 
1251
  return true;
1282
1252
}
1283
1253
 
1284
1254
 
1293
1263
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1294
1264
 
1295
1265
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1296
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_bool_t, bool);
 
1266
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1297
1267
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1298
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_str_t, char *);
 
1268
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1299
1269
 
1300
1270
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1301
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
 
1271
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1302
1272
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1303
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
 
1273
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1304
1274
 
1305
1275
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1306
1276
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1309
1279
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1310
1280
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1311
1281
 
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);
 
1282
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
 
1283
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
 
1284
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
 
1285
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
 
1286
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
 
1287
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1318
1288
 
1319
 
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
 
1289
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1320
1290
 
1321
1291
 
1322
1292
/****************************************************************************
1323
1293
  default variable data check and update functions
1324
1294
****************************************************************************/
1325
1295
 
1326
 
static int check_func_bool(THD *thd __attribute__((unused)),
1327
 
                           struct st_mysql_sys_var *var,
 
1296
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
1328
1297
                           void *save, st_mysql_value *value)
1329
1298
{
1330
1299
  char buff[STRING_BUFFER_USUAL_SIZE];
1363
1332
}
1364
1333
 
1365
1334
 
1366
 
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
 
1335
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1367
1336
                          void *save, st_mysql_value *value)
1368
1337
{
1369
1338
  bool fixed;
1373
1342
  plugin_opt_set_limits(&options, var);
1374
1343
 
1375
1344
  if (var->flags & PLUGIN_VAR_UNSIGNED)
1376
 
    *(uint32_t *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
 
1345
    *(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
1377
1346
                                                   &fixed);
1378
1347
  else
1379
1348
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1380
1349
 
1381
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1350
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1382
1351
                              var->name, (int64_t) tmp);
1383
1352
}
1384
1353
 
1385
1354
 
1386
 
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
 
1355
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1387
1356
                          void *save, st_mysql_value *value)
1388
1357
{
1389
1358
  bool fixed;
1398
1367
  else
1399
1368
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1400
1369
 
1401
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1370
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1402
1371
                              var->name, (int64_t) tmp);
1403
1372
}
1404
1373
 
1405
1374
 
1406
 
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
 
1375
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1407
1376
                               void *save, st_mysql_value *value)
1408
1377
{
1409
1378
  bool fixed;
1418
1387
  else
1419
1388
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1420
1389
 
1421
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1390
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1422
1391
                              var->name, (int64_t) tmp);
1423
1392
}
1424
1393
 
1425
 
static int check_func_str(THD *thd,
1426
 
                          struct st_mysql_sys_var *var __attribute__((unused)),
 
1394
static int check_func_str(Session *session, struct st_mysql_sys_var *,
1427
1395
                          void *save, st_mysql_value *value)
1428
1396
{
1429
1397
  char buff[STRING_BUFFER_USUAL_SIZE];
1432
1400
 
1433
1401
  length= sizeof(buff);
1434
1402
  if ((str= value->val_str(value, buff, &length)))
1435
 
    str= thd->strmake(str, length);
 
1403
    str= session->strmake(str, length);
1436
1404
  *(const char**)save= str;
1437
1405
  return 0;
1438
1406
}
1439
1407
 
1440
1408
 
1441
 
static int check_func_enum(THD *thd __attribute__((unused)),
1442
 
                           struct st_mysql_sys_var *var,
 
1409
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
1443
1410
                           void *save, st_mysql_value *value)
1444
1411
{
1445
1412
  char buff[STRING_BUFFER_USUAL_SIZE];
1449
1416
  long result;
1450
1417
  int length;
1451
1418
 
1452
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1453
 
    typelib= ((thdvar_enum_t*) var)->typelib;
 
1419
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1420
    typelib= ((sessionvar_enum_t*) var)->typelib;
1454
1421
  else
1455
1422
    typelib= ((sysvar_enum_t*) var)->typelib;
1456
1423
 
1485
1452
}
1486
1453
 
1487
1454
 
1488
 
static int check_func_set(THD *thd __attribute__((unused)),
1489
 
                          struct st_mysql_sys_var *var,
 
1455
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1490
1456
                          void *save, st_mysql_value *value)
1491
1457
{
1492
1458
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1497
1463
  bool not_used;
1498
1464
  int length;
1499
1465
 
1500
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1501
 
    typelib= ((thdvar_set_t*) var)->typelib;
 
1466
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1467
    typelib= ((sessionvar_set_t*) var)->typelib;
1502
1468
  else
1503
1469
    typelib= ((sysvar_set_t*)var)->typelib;
1504
1470
 
1511
1477
                     &error, &error_len, &not_used);
1512
1478
    if (error_len)
1513
1479
    {
1514
 
      strmake(buff, error, cmin(sizeof(buff), (unsigned long)error_len));
 
1480
      length= cmin(sizeof(buff), (unsigned long)error_len);
 
1481
      strncpy(buff, error, length);
 
1482
      buff[length]= '\0';
1515
1483
      strvalue= buff;
1516
1484
      goto err;
1517
1485
    }
1536
1504
}
1537
1505
 
1538
1506
 
1539
 
static void update_func_bool(THD *thd __attribute__((unused)),
1540
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1507
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1541
1508
                             void *tgt, const void *save)
1542
1509
{
1543
1510
  *(bool *) tgt= *(int *) save ? 1 : 0;
1544
1511
}
1545
1512
 
1546
1513
 
1547
 
static void update_func_int(THD *thd __attribute__((unused)),
1548
 
                            struct st_mysql_sys_var *var __attribute__((unused)),
 
1514
static void update_func_int(Session *, struct st_mysql_sys_var *,
1549
1515
                             void *tgt, const void *save)
1550
1516
{
1551
1517
  *(int *)tgt= *(int *) save;
1552
1518
}
1553
1519
 
1554
1520
 
1555
 
static void update_func_long(THD *thd __attribute__((unused)),
1556
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1521
static void update_func_long(Session *, struct st_mysql_sys_var *,
1557
1522
                             void *tgt, const void *save)
1558
1523
{
1559
1524
  *(long *)tgt= *(long *) save;
1560
1525
}
1561
1526
 
1562
1527
 
1563
 
static void update_func_int64_t(THD *thd __attribute__((unused)),
1564
 
                                 struct st_mysql_sys_var *var __attribute__((unused)),
 
1528
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1565
1529
                                 void *tgt, const void *save)
1566
1530
{
1567
1531
  *(int64_t *)tgt= *(uint64_t *) save;
1568
1532
}
1569
1533
 
1570
1534
 
1571
 
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
 
1535
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1572
1536
                             void *tgt, const void *save)
1573
1537
{
1574
1538
  char *old= *(char **) tgt;
1575
1539
  *(char **)tgt= *(char **) save;
1576
1540
  if (var->flags & PLUGIN_VAR_MEMALLOC)
1577
1541
  {
1578
 
    *(char **)tgt= my_strdup(*(char **) save, MYF(0));
 
1542
    *(char **)tgt= strdup(*(char **) save);
1579
1543
    free(old);
 
1544
    /*
 
1545
     * There isn't a _really_ good thing to do here until this whole set_var
 
1546
     * mess gets redesigned
 
1547
     */
 
1548
    if (tgt == NULL)
 
1549
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
 
1550
 
1580
1551
  }
1581
1552
}
1582
1553
 
1586
1557
****************************************************************************/
1587
1558
 
1588
1559
 
1589
 
sys_var *find_sys_var(THD *thd, const char *str, uint32_t length)
 
1560
sys_var *find_sys_var(Session *session, const char *str, uint32_t length)
1590
1561
{
1591
1562
  sys_var *var;
1592
1563
  sys_var_pluginvar *pi= NULL;
1593
1564
  plugin_ref plugin;
1594
1565
 
1595
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1566
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1596
1567
  if ((var= intern_find_sys_var(str, length, false)) &&
1597
1568
      (pi= var->cast_pluginvar()))
1598
1569
  {
1599
 
    rw_unlock(&LOCK_system_variables_hash);
1600
 
    LEX *lex= thd ? thd->lex : 0;
 
1570
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
1571
    LEX *lex= session ? session->lex : 0;
1601
1572
    if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1602
1573
      var= NULL; /* failed to lock it, it must be uninstalling */
1603
1574
    else
1609
1580
    }
1610
1581
  }
1611
1582
  else
1612
 
    rw_unlock(&LOCK_system_variables_hash);
 
1583
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1613
1584
 
1614
1585
  /*
1615
1586
    If the variable exists but the plugin it is associated with is not ready
1632
1603
  uint32_t namelen, length, pluginlen= 0;
1633
1604
  char *varname, *p;
1634
1605
 
1635
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1606
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1636
1607
    return NULL;
1637
1608
 
1638
1609
  namelen= strlen(name);
1639
1610
  if (plugin)
1640
1611
    pluginlen= strlen(plugin) + 1;
1641
1612
  length= namelen + pluginlen + 2;
1642
 
  varname= (char*) my_alloca(length);
 
1613
  varname= (char*) malloc(length);
1643
1614
 
1644
1615
  if (plugin)
1645
1616
  {
1646
 
    strxmov(varname + 1, plugin, "_", name, NULL);
 
1617
    sprintf(varname+1,"%s_%s",plugin,name);
1647
1618
    for (p= varname + 1; *p; p++)
1648
1619
      if (*p == '-')
1649
1620
        *p= '_';
1656
1627
  result= (st_bookmark*) hash_search(&bookmark_hash,
1657
1628
                                     (const unsigned char*) varname, length - 1);
1658
1629
 
1659
 
  my_afree(varname);
 
1630
  free(varname);
1660
1631
  return result;
1661
1632
}
1662
1633
 
1663
1634
 
1664
1635
/*
1665
 
  returns a bookmark for thd-local variables, creating if neccessary.
1666
 
  returns null for non thd-local variables.
 
1636
  returns a bookmark for session-local variables, creating if neccessary.
 
1637
  returns null for non session-local variables.
1667
1638
  Requires that a write lock is obtained on LOCK_system_variables_hash
1668
1639
*/
1669
1640
static st_bookmark *register_var(const char *plugin, const char *name,
1673
1644
  st_bookmark *result;
1674
1645
  char *varname, *p;
1675
1646
 
1676
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1647
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1677
1648
    return NULL;
1678
1649
 
1679
1650
  switch (flags & PLUGIN_VAR_TYPEMASK) {
1680
1651
  case PLUGIN_VAR_BOOL:
1681
 
    size= sizeof(bool);
 
1652
    size= ALIGN_SIZE(sizeof(bool));
1682
1653
    break;
1683
1654
  case PLUGIN_VAR_INT:
1684
 
    size= sizeof(int);
 
1655
    size= ALIGN_SIZE(sizeof(int));
1685
1656
    break;
1686
1657
  case PLUGIN_VAR_LONG:
1687
1658
  case PLUGIN_VAR_ENUM:
1688
 
    size= sizeof(long);
 
1659
    size= ALIGN_SIZE(sizeof(long));
1689
1660
    break;
1690
1661
  case PLUGIN_VAR_LONGLONG:
1691
1662
  case PLUGIN_VAR_SET:
1692
 
    size= sizeof(uint64_t);
 
1663
    size= ALIGN_SIZE(sizeof(uint64_t));
1693
1664
    break;
1694
1665
  case PLUGIN_VAR_STR:
1695
 
    size= sizeof(char*);
 
1666
    size= ALIGN_SIZE(sizeof(char*));
1696
1667
    break;
1697
1668
  default:
1698
1669
    assert(0);
1699
1670
    return NULL;
1700
1671
  };
1701
1672
 
1702
 
  varname= ((char*) my_alloca(length));
1703
 
  strxmov(varname + 1, plugin, "_", name, NULL);
 
1673
  varname= ((char*) malloc(length));
 
1674
  sprintf(varname+1, "%s_%s", plugin, name);
1704
1675
  for (p= varname + 1; *p; p++)
1705
1676
    if (*p == '-')
1706
1677
      *p= '_';
1724
1695
 
1725
1696
    if (new_size > global_variables_dynamic_size)
1726
1697
    {
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));
 
1698
      char* tmpptr= NULL;
 
1699
      if (!(tmpptr=
 
1700
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
 
1701
                              new_size)))
 
1702
        return NULL;
 
1703
      global_system_variables.dynamic_variables_ptr= tmpptr;
 
1704
      tmpptr= NULL;
 
1705
      if (!(tmpptr=
 
1706
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
 
1707
                              new_size)))
 
1708
        return NULL;
 
1709
      max_system_variables.dynamic_variables_ptr= tmpptr;
 
1710
           
1733
1711
      /*
1734
1712
        Clear the new variable value space. This is required for string
1735
1713
        variables. If their value is non-NULL, it must point to a valid
1739
1717
             global_variables_dynamic_size, 0,
1740
1718
             new_size - global_variables_dynamic_size);
1741
1719
      memset(max_system_variables.dynamic_variables_ptr +
1742
 
             global_variables_dynamic_size, 0, 
 
1720
             global_variables_dynamic_size, 0,
1743
1721
             new_size - global_variables_dynamic_size);
1744
1722
      global_variables_dynamic_size= new_size;
1745
1723
    }
1760
1738
      assert(0);
1761
1739
    }
1762
1740
  }
1763
 
  my_afree(varname);
 
1741
  free(varname);
1764
1742
  return result;
1765
1743
}
1766
1744
 
1767
1745
 
1768
1746
/*
1769
 
  returns a pointer to the memory which holds the thd-local variable or
1770
 
  a pointer to the global variable if thd==null.
 
1747
  returns a pointer to the memory which holds the session-local variable or
 
1748
  a pointer to the global variable if session==null.
1771
1749
  If required, will sync with global variables if the requested variable
1772
1750
  has not yet been allocated in the current thread.
1773
1751
*/
1774
 
static unsigned char *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
 
1752
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1775
1753
{
1776
1754
  assert(offset >= 0);
1777
 
  assert((uint)offset <= global_system_variables.dynamic_variables_head);
 
1755
  assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1778
1756
 
1779
 
  if (!thd)
 
1757
  if (!session)
1780
1758
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1781
1759
 
1782
1760
  /*
1783
1761
    dynamic_variables_head points to the largest valid offset
1784
1762
  */
1785
 
  if (!thd->variables.dynamic_variables_ptr ||
1786
 
      (uint)offset > thd->variables.dynamic_variables_head)
 
1763
  if (!session->variables.dynamic_variables_ptr ||
 
1764
      (uint32_t)offset > session->variables.dynamic_variables_head)
1787
1765
  {
1788
1766
    uint32_t idx;
1789
1767
 
1790
 
    rw_rdlock(&LOCK_system_variables_hash);
 
1768
    pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1791
1769
 
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));
 
1770
    char *tmpptr= NULL;
 
1771
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
 
1772
                                  global_variables_dynamic_size)))
 
1773
      return NULL;
 
1774
    session->variables.dynamic_variables_ptr= tmpptr;
1796
1775
 
1797
1776
    if (global_lock)
1798
1777
      pthread_mutex_lock(&LOCK_global_system_variables);
1799
1778
 
1800
1779
    safe_mutex_assert_owner(&LOCK_global_system_variables);
1801
1780
 
1802
 
    memcpy(thd->variables.dynamic_variables_ptr +
1803
 
             thd->variables.dynamic_variables_size,
 
1781
    memcpy(session->variables.dynamic_variables_ptr +
 
1782
             session->variables.dynamic_variables_size,
1804
1783
           global_system_variables.dynamic_variables_ptr +
1805
 
             thd->variables.dynamic_variables_size,
 
1784
             session->variables.dynamic_variables_size,
1806
1785
           global_system_variables.dynamic_variables_size -
1807
 
             thd->variables.dynamic_variables_size);
 
1786
             session->variables.dynamic_variables_size);
1808
1787
 
1809
1788
    /*
1810
1789
      now we need to iterate through any newly copied 'defaults'
1816
1795
      sys_var *var;
1817
1796
      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1818
1797
 
1819
 
      if (v->version <= thd->variables.dynamic_variables_version ||
 
1798
      if (v->version <= session->variables.dynamic_variables_version ||
1820
1799
          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1821
1800
          !(pi= var->cast_pluginvar()) ||
1822
1801
          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1827
1806
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1828
1807
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1829
1808
      {
1830
 
         char **pp= (char**) (thd->variables.dynamic_variables_ptr +
 
1809
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
1831
1810
                             *(int*)(pi->plugin_var + 1));
1832
1811
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1833
1812
                             *(int*)(pi->plugin_var + 1))))
1834
 
           *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
 
1813
           *pp= strdup(*pp);
 
1814
         if (*pp == NULL)
 
1815
           return NULL;
1835
1816
      }
1836
1817
    }
1837
1818
 
1838
1819
    if (global_lock)
1839
1820
      pthread_mutex_unlock(&LOCK_global_system_variables);
1840
1821
 
1841
 
    thd->variables.dynamic_variables_version=
 
1822
    session->variables.dynamic_variables_version=
1842
1823
           global_system_variables.dynamic_variables_version;
1843
 
    thd->variables.dynamic_variables_head=
 
1824
    session->variables.dynamic_variables_head=
1844
1825
           global_system_variables.dynamic_variables_head;
1845
 
    thd->variables.dynamic_variables_size=
 
1826
    session->variables.dynamic_variables_size=
1846
1827
           global_system_variables.dynamic_variables_size;
1847
1828
 
1848
 
    rw_unlock(&LOCK_system_variables_hash);
 
1829
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1849
1830
  }
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;
 
1831
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
 
1832
}
 
1833
 
 
1834
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
 
1835
{
 
1836
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
 
1837
}
 
1838
 
 
1839
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
 
1840
{
 
1841
  return (int *)intern_sys_var_ptr(a_session, offset, true);
 
1842
}
 
1843
 
 
1844
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
 
1845
{
 
1846
  return (long *)intern_sys_var_ptr(a_session, offset, true);
 
1847
}
 
1848
 
 
1849
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
 
1850
{
 
1851
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1852
}
 
1853
 
 
1854
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
 
1855
{
 
1856
  return (char **)intern_sys_var_ptr(a_session, offset, true);
 
1857
}
 
1858
 
 
1859
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
 
1860
{
 
1861
  return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1862
}
 
1863
 
 
1864
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
 
1865
{
 
1866
  return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
 
1867
}
 
1868
 
 
1869
 
 
1870
void plugin_sessionvar_init(Session *session)
 
1871
{
 
1872
  plugin_ref old_table_plugin= session->variables.table_plugin;
 
1873
 
 
1874
  session->variables.table_plugin= NULL;
 
1875
  cleanup_variables(session, &session->variables);
 
1876
 
 
1877
  session->variables= global_system_variables;
 
1878
  session->variables.table_plugin= NULL;
1898
1879
 
1899
1880
  /* 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;
 
1881
  session->variables.dynamic_variables_version= 0;
 
1882
  session->variables.dynamic_variables_size= 0;
 
1883
  session->variables.dynamic_variables_ptr= 0;
1903
1884
 
1904
 
  thd->variables.table_plugin=
 
1885
  session->variables.table_plugin=
1905
1886
        my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1906
1887
  intern_plugin_unlock(NULL, old_table_plugin);
1907
1888
  return;
1911
1892
/*
1912
1893
  Unlocks all system variables which hold a reference
1913
1894
*/
1914
 
static void unlock_variables(THD *thd __attribute__((unused)),
1915
 
                             struct system_variables *vars)
 
1895
static void unlock_variables(Session *, struct system_variables *vars)
1916
1896
{
1917
1897
  intern_plugin_unlock(NULL, vars->table_plugin);
1918
1898
  vars->table_plugin= NULL;
1925
1905
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
1926
1906
  it's used on shutdown.
1927
1907
*/
1928
 
static void cleanup_variables(THD *thd, struct system_variables *vars)
 
1908
static void cleanup_variables(Session *session, struct system_variables *vars)
1929
1909
{
1930
1910
  st_bookmark *v;
1931
1911
  sys_var_pluginvar *pivar;
1933
1913
  int flags;
1934
1914
  uint32_t idx;
1935
1915
 
1936
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1916
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1937
1917
  for (idx= 0; idx < bookmark_hash.records; idx++)
1938
1918
  {
1939
1919
    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1946
1926
    flags= pivar->plugin_var->flags;
1947
1927
 
1948
1928
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1949
 
        flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
 
1929
        flags & PLUGIN_VAR_SessionLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1950
1930
    {
1951
 
      char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
 
1931
      char **ptr= (char**) pivar->real_value_ptr(session, OPT_SESSION);
1952
1932
      free(*ptr);
1953
1933
      *ptr= NULL;
1954
1934
    }
1955
1935
  }
1956
 
  rw_unlock(&LOCK_system_variables_hash);
 
1936
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
1957
1937
 
1958
1938
  assert(vars->table_plugin == NULL);
1959
1939
 
1964
1944
}
1965
1945
 
1966
1946
 
1967
 
void plugin_thdvar_cleanup(THD *thd)
 
1947
void plugin_sessionvar_cleanup(Session *session)
1968
1948
{
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;
 
1949
  unlock_variables(session, &session->variables);
 
1950
  cleanup_variables(session, &session->variables);
1985
1951
}
1986
1952
 
1987
1953
 
2056
2022
}
2057
2023
 
2058
2024
 
2059
 
unsigned char* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
 
2025
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2060
2026
{
2061
 
  assert(thd || (type == OPT_GLOBAL));
2062
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
2027
  assert(session || (type == OPT_GLOBAL));
 
2028
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2063
2029
  {
2064
2030
    if (type == OPT_GLOBAL)
2065
 
      thd= NULL;
 
2031
      session= NULL;
2066
2032
 
2067
 
    return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
 
2033
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2068
2034
  }
2069
2035
  return *(unsigned char**) (plugin_var+1);
2070
2036
}
2072
2038
 
2073
2039
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2074
2040
{
2075
 
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
 
2041
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2076
2042
  case PLUGIN_VAR_ENUM:
2077
2043
    return ((sysvar_enum_t *)plugin_var)->typelib;
2078
2044
  case PLUGIN_VAR_SET:
2079
2045
    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;
 
2046
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
 
2047
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
2048
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
 
2049
    return ((sessionvar_set_t *)plugin_var)->typelib;
2084
2050
  default:
2085
2051
    return NULL;
2086
2052
  }
2088
2054
}
2089
2055
 
2090
2056
 
2091
 
unsigned char* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
2092
 
                                    LEX_STRING *base __attribute__((unused)))
 
2057
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
2093
2058
{
2094
2059
  unsigned char* result;
2095
2060
 
2096
 
  result= real_value_ptr(thd, type);
 
2061
  result= real_value_ptr(session, type);
2097
2062
 
2098
2063
  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2099
2064
    result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2116
2081
 
2117
2082
    result= (unsigned char*) "";
2118
2083
    if (str.length())
2119
 
      result= (unsigned char*) thd->strmake(str.ptr(), str.length()-1);
 
2084
      result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2120
2085
  }
2121
2086
  return result;
2122
2087
}
2123
2088
 
2124
2089
 
2125
 
bool sys_var_pluginvar::check(THD *thd, set_var *var)
 
2090
bool sys_var_pluginvar::check(Session *session, set_var *var)
2126
2091
{
2127
2092
  st_item_value_holder value;
2128
2093
  assert(is_readonly() || plugin_var->check);
2134
2099
  value.item= var->value;
2135
2100
 
2136
2101
  return is_readonly() ||
2137
 
         plugin_var->check(thd, plugin_var, &var->save_result, &value);
 
2102
         plugin_var->check(session, plugin_var, &var->save_result, &value);
2138
2103
}
2139
2104
 
2140
2105
 
2141
 
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
 
2106
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2142
2107
{
2143
2108
  const void *src;
2144
2109
  void *tgt;
2149
2114
    return;
2150
2115
 
2151
2116
  pthread_mutex_lock(&LOCK_global_system_variables);
2152
 
  tgt= real_value_ptr(thd, type);
 
2117
  tgt= real_value_ptr(session, type);
2153
2118
  src= ((void **) (plugin_var + 1) + 1);
2154
2119
 
2155
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
2120
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2156
2121
  {
2157
2122
    if (type != OPT_GLOBAL)
2158
 
      src= real_value_ptr(thd, OPT_GLOBAL);
 
2123
      src= real_value_ptr(session, OPT_GLOBAL);
2159
2124
    else
2160
2125
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2161
2126
        case PLUGIN_VAR_INT:
2162
 
          src= &((thdvar_uint_t*) plugin_var)->def_val;
 
2127
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
2163
2128
          break;
2164
2129
        case PLUGIN_VAR_LONG:
2165
 
          src= &((thdvar_ulong_t*) plugin_var)->def_val;
 
2130
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2166
2131
          break;
2167
2132
        case PLUGIN_VAR_LONGLONG:
2168
 
          src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
 
2133
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2169
2134
          break;
2170
2135
        case PLUGIN_VAR_ENUM:
2171
 
          src= &((thdvar_enum_t*) plugin_var)->def_val;
 
2136
          src= &((sessionvar_enum_t*) plugin_var)->def_val;
2172
2137
          break;
2173
2138
        case PLUGIN_VAR_SET:
2174
 
          src= &((thdvar_set_t*) plugin_var)->def_val;
 
2139
          src= &((sessionvar_set_t*) plugin_var)->def_val;
2175
2140
          break;
2176
2141
        case PLUGIN_VAR_BOOL:
2177
 
          src= &((thdvar_bool_t*) plugin_var)->def_val;
 
2142
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
2178
2143
          break;
2179
2144
        case PLUGIN_VAR_STR:
2180
 
          src= &((thdvar_str_t*) plugin_var)->def_val;
 
2145
          src= &((sessionvar_str_t*) plugin_var)->def_val;
2181
2146
          break;
2182
2147
        default:
2183
2148
          assert(0);
2184
2149
        }
2185
2150
  }
2186
2151
 
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);
 
2152
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
2153
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
2154
              session == current_session);
2190
2155
 
2191
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
 
2156
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2192
2157
  {
2193
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
2158
    plugin_var->update(session, plugin_var, tgt, src);
2194
2159
    pthread_mutex_unlock(&LOCK_global_system_variables);
2195
2160
  }
2196
2161
  else
2197
2162
  {
2198
2163
    pthread_mutex_unlock(&LOCK_global_system_variables);
2199
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
2164
    plugin_var->update(session, plugin_var, tgt, src);
2200
2165
  }
2201
2166
}
2202
2167
 
2203
2168
 
2204
 
bool sys_var_pluginvar::update(THD *thd, set_var *var)
 
2169
bool sys_var_pluginvar::update(Session *session, set_var *var)
2205
2170
{
2206
2171
  void *tgt;
2207
2172
 
2208
2173
  assert(is_readonly() || plugin_var->update);
2209
2174
 
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);
 
2175
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
2176
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
2177
              session == current_session);
2213
2178
 
2214
2179
  if (is_readonly())
2215
2180
    return 1;
2216
2181
 
2217
2182
  pthread_mutex_lock(&LOCK_global_system_variables);
2218
 
  tgt= real_value_ptr(thd, var->type);
 
2183
  tgt= real_value_ptr(session, var->type);
2219
2184
 
2220
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
 
2185
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2221
2186
  {
2222
2187
    /* variable we are updating has global scope, so we unlock after updating */
2223
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
2188
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2224
2189
    pthread_mutex_unlock(&LOCK_global_system_variables);
2225
2190
  }
2226
2191
  else
2227
2192
  {
2228
2193
    pthread_mutex_unlock(&LOCK_global_system_variables);
2229
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
2194
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2230
2195
  }
2231
2196
 return 0;
2232
2197
}
2246
2211
  options->sub_size= 0;
2247
2212
 
2248
2213
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2249
 
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
 
2214
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2250
2215
  /* global system variables */
2251
2216
  case PLUGIN_VAR_INT:
2252
2217
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2258
2223
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2259
2224
    break;
2260
2225
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2261
 
    OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
 
2226
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
2262
2227
    break;
2263
2228
  case PLUGIN_VAR_LONGLONG:
2264
2229
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2290
2255
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2291
2256
    break;
2292
2257
  /* 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:
 
2258
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
 
2259
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
 
2260
    break;
 
2261
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2262
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
 
2263
    break;
 
2264
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
 
2265
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
 
2266
    break;
 
2267
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2268
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
 
2269
    break;
 
2270
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
 
2271
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
 
2272
    break;
 
2273
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2274
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
 
2275
    break;
 
2276
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2312
2277
    options->var_type= GET_ENUM;
2313
 
    options->typelib= ((thdvar_enum_t*) opt)->typelib;
2314
 
    options->def_value= ((thdvar_enum_t*) opt)->def_val;
 
2278
    options->typelib= ((sessionvar_enum_t*) opt)->typelib;
 
2279
    options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2315
2280
    options->min_value= options->block_size= 0;
2316
2281
    options->max_value= options->typelib->count - 1;
2317
2282
    break;
2318
 
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
 
2283
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2319
2284
    options->var_type= GET_SET;
2320
 
    options->typelib= ((thdvar_set_t*) opt)->typelib;
2321
 
    options->def_value= ((thdvar_set_t*) opt)->def_val;
 
2285
    options->typelib= ((sessionvar_set_t*) opt)->typelib;
 
2286
    options->def_value= ((sessionvar_set_t*) opt)->def_val;
2322
2287
    options->min_value= options->block_size= 0;
2323
2288
    options->max_value= (1UL << options->typelib->count) - 1;
2324
2289
    break;
2325
 
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
 
2290
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2326
2291
    options->var_type= GET_BOOL;
2327
 
    options->def_value= ((thdvar_bool_t*) opt)->def_val;
 
2292
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2328
2293
    break;
2329
 
  case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
 
2294
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2330
2295
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2331
2296
                        GET_STR_ALLOC : GET_STR);
2332
 
    options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
 
2297
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2333
2298
    break;
2334
2299
  default:
2335
2300
    assert(0);
2344
2309
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2345
2310
                                         char *);
2346
2311
 
2347
 
bool get_one_plugin_option(int optid __attribute__((unused)),
2348
 
                              const struct my_option *opt __attribute__((unused)),
2349
 
                              char *argument __attribute__((unused)))
 
2312
bool get_one_plugin_option(int, const struct my_option *, char *)
2350
2313
{
2351
2314
  return 0;
2352
2315
}
2367
2330
  /* support --skip-plugin-foo syntax */
2368
2331
  memcpy(name, plugin_name, namelen + 1);
2369
2332
  my_casedn_str(&my_charset_utf8_general_ci, name);
2370
 
  strxmov(name + namelen + 1, "plugin-", name, NULL);
 
2333
  sprintf(name+namelen+1, "plugin-%s", name);
2371
2334
  /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2372
2335
 
2373
2336
  for (p= name + namelen*2 + 8; p > name; p--)
2376
2339
 
2377
2340
  if (can_disable)
2378
2341
  {
2379
 
    strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2380
 
            "Disable with --skip-", name," (will save memory).", NULL);
 
2342
    sprintf(name+namelen*2+10,
 
2343
            "Enable %s plugin. Disable with --skip-%s (will save memory).",
 
2344
            plugin_name, name);
2381
2345
    /*
2382
2346
      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2383
2347
      20 + namelen + 20 + 1 == namelen * 4 + 67.
2404
2368
       plugin_option && *plugin_option; plugin_option++, index++)
2405
2369
  {
2406
2370
    opt= *plugin_option;
2407
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2371
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2408
2372
      continue;
2409
2373
    if (!(register_var(name, opt->name, opt->flags)))
2410
2374
      continue;
2411
2375
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2412
2376
    case PLUGIN_VAR_BOOL:
2413
 
      (((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
 
2377
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2414
2378
      break;
2415
2379
    case PLUGIN_VAR_INT:
2416
 
      (((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
 
2380
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2417
2381
      break;
2418
2382
    case PLUGIN_VAR_LONG:
2419
 
      (((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
 
2383
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2420
2384
      break;
2421
2385
    case PLUGIN_VAR_LONGLONG:
2422
 
      (((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
 
2386
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2423
2387
      break;
2424
2388
    case PLUGIN_VAR_STR:
2425
 
      (((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
 
2389
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2426
2390
      break;
2427
2391
    case PLUGIN_VAR_ENUM:
2428
 
      (((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
 
2392
      (((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2429
2393
      break;
2430
2394
    case PLUGIN_VAR_SET:
2431
 
      (((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
 
2395
      (((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2432
2396
      break;
2433
2397
    default:
2434
 
      sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
 
2398
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2435
2399
                      opt->flags, plugin_name);
2436
2400
      return(-1);
2437
2401
    };
2474
2438
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2475
2439
        {
2476
2440
          opt->flags|= PLUGIN_VAR_READONLY;
2477
 
          sql_print_warning(_("Server variable %s of plugin %s was forced "
 
2441
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2478
2442
                            "to be read-only: string variable without "
2479
2443
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
2480
2444
                            opt->name, plugin_name);
2494
2458
        opt->update= update_func_int64_t;
2495
2459
      break;
2496
2460
    default:
2497
 
      sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
 
2461
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2498
2462
                      opt->flags, plugin_name);
2499
2463
      return(-1);
2500
2464
    }
2501
2465
 
2502
 
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
 
2466
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2503
2467
                    == PLUGIN_VAR_NOCMDOPT)
2504
2468
      continue;
2505
2469
 
2506
2470
    if (!opt->name)
2507
2471
    {
2508
 
      sql_print_error(_("Missing variable name in plugin '%s'."),
 
2472
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2509
2473
                      plugin_name);
2510
2474
      return(-1);
2511
2475
    }
2512
2476
 
2513
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2477
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2514
2478
    {
2515
2479
      optnamelen= strlen(opt->name);
2516
2480
      optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2517
 
      strxmov(optname, name, "-", opt->name, NULL);
 
2481
      sprintf(optname, "%s-%s", name, opt->name);
2518
2482
      optnamelen= namelen + optnamelen + 1;
2519
2483
    }
2520
2484
    else
2522
2486
      /* this should not fail because register_var should create entry */
2523
2487
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
2524
2488
      {
2525
 
        sql_print_error(_("Thread local variable '%s' not allocated "
 
2489
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2526
2490
                        "in plugin '%s'."), opt->name, plugin_name);
2527
2491
        return(-1);
2528
2492
      }
2532
2496
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2533
2497
        continue;
2534
2498
 
2535
 
      optname= (char*) memdup_root(mem_root, v->key + 1, 
 
2499
      optname= (char*) memdup_root(mem_root, v->key + 1,
2536
2500
                                   (optnamelen= v->name_len) + 1);
2537
2501
    }
2538
2502
 
2548
2512
 
2549
2513
    plugin_opt_set_limits(options, opt);
2550
2514
 
2551
 
    if (opt->flags & PLUGIN_VAR_THDLOCAL)
 
2515
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2552
2516
      options->value= options->u_max_value= (char**)
2553
2517
        (global_system_variables.dynamic_variables_ptr + offset);
2554
2518
    else
2557
2521
    options[1]= options[0];
2558
2522
    options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2559
2523
    options[1].comment= 0; // hidden
2560
 
    strxmov(p, "plugin-", optname, NULL);
 
2524
    sprintf(p,"plugin-%s",optname);
2561
2525
 
2562
2526
    options+= 2;
2563
2527
  }
2613
2577
                               int *argc, char **argv)
2614
2578
{
2615
2579
  struct sys_var_chain chain= { NULL, NULL };
2616
 
  bool enabled_saved= true;
2617
2580
  bool can_disable;
2618
2581
  MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
2619
2582
                      &tmp->mem_root : &plugin_mem_root;
2641
2604
  {
2642
2605
    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2643
2606
    {
2644
 
      sql_print_error(_("Out of memory for plugin '%s'."), tmp->name.str);
 
2607
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->name.str);
2645
2608
      return(-1);
2646
2609
    }
2647
2610
    memset(opts, 0, sizeof(my_option) * count);
2648
2611
 
2649
2612
    if (construct_options(tmp_root, tmp, opts, can_disable))
2650
2613
    {
2651
 
      sql_print_error(_("Bad options for plugin '%s'."), tmp->name.str);
 
2614
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->name.str);
2652
2615
      return(-1);
2653
2616
    }
2654
2617
 
2657
2620
 
2658
2621
    if (error)
2659
2622
    {
2660
 
       sql_print_error(_("Parsing options for plugin '%s' failed."),
 
2623
       errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2661
2624
                       tmp->name.str);
2662
2625
       goto err;
2663
2626
    }
2677
2640
      {
2678
2641
        len= tmp->name.length + strlen(o->name) + 2;
2679
2642
        varname= (char*) alloc_root(mem_root, len);
2680
 
        strxmov(varname, tmp->name.str, "-", o->name, NULL);
 
2643
        sprintf(varname,"%s-%s",tmp->name.str,o->name);
2681
2644
        my_casedn_str(&my_charset_utf8_general_ci, varname);
2682
2645
 
2683
2646
        for (p= varname; *p; p++)
2700
2663
      chain.last->next = NULL;
2701
2664
      if (mysql_add_sys_var_chain(chain.first, NULL))
2702
2665
      {
2703
 
        sql_print_error(_("Plugin '%s' has conflicting system variables"),
 
2666
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2704
2667
                        tmp->name.str);
2705
2668
        goto err;
2706
2669
      }
2709
2672
    return(0);
2710
2673
  }
2711
2674
 
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
2675
err:
2716
2676
  if (opts)
2717
2677
    my_cleanup_options(opts);