~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_plugin.cc

Moved the last of the libdrizzleclient calls into Protocol.

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);
59
89
plugin_type_init plugin_type_initialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
60
90
{
61
91
  0,  /* Daemon */
62
 
  ha_initialize_handlerton,  /* Storage Engine */
 
92
  storage_engine_initializer,  /* Storage Engine */
63
93
  initialize_schema_table,  /* Information Schema */
64
94
  initialize_udf,  /* UDF */
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]=
72
108
{
73
109
  0,  /* Daemon */
74
 
  ha_finalize_handlerton,  /* Storage Engine */
 
110
  storage_engine_finalizer,  /* Storage Engine */
75
111
  finalize_schema_table,  /* Information Schema */
76
112
  finalize_udf,  /* UDF */
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_";
86
128
   sub-structure (plugin->info).
87
129
*/
88
130
 
89
 
static bool initialized= 0;
 
131
static bool initialized= false;
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);
197
 
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
 
234
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
198
235
static void reap_plugins(void);
199
236
 
200
237
 
201
238
/* declared in set_var.cc */
202
239
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,
 
240
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
204
241
                                 const char *name, int64_t val);
205
242
 
206
243
/****************************************************************************
233
270
    Lets be nice and create a temporary string since the
234
271
    buffer was too small
235
272
  */
236
 
  return current_thd->strmake(res->c_ptr_quick(), res->length());
 
273
  return current_session->strmake(res->c_ptr_quick(), res->length());
237
274
}
238
275
 
239
276
 
265
302
{
266
303
  uint32_t i;
267
304
  struct st_plugin_dl *tmp;
 
305
 
268
306
  for (i= 0; i < plugin_dl_array.elements; i++)
269
307
  {
270
308
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
271
 
    if (tmp->ref_count &&
272
 
        ! my_strnncoll(files_charset_info,
 
309
    if (! my_strnncoll(files_charset_info,
273
310
                       (const unsigned char *)dl->str, dl->length,
274
311
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
275
312
      return(tmp);
281
318
{
282
319
  uint32_t i;
283
320
  struct st_plugin_dl *tmp;
 
321
 
284
322
  for (i= 0; i < plugin_dl_array.elements; i++)
285
323
  {
286
324
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
287
 
    if (! tmp->ref_count)
288
325
    {
289
326
      memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
290
327
      return(tmp);
309
346
 
310
347
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
311
348
{
312
 
  char dlpath[FN_REFLEN];
313
 
  uint32_t plugin_dir_len, dummy_errors, dlpathlen;
 
349
  string dlpath;
 
350
  uint32_t plugin_dir_len, dummy_errors;
314
351
  struct st_plugin_dl *tmp, plugin_dl;
315
352
  void *sym;
316
353
  plugin_dir_len= strlen(opt_plugin_dir);
 
354
  dlpath.reserve(FN_REFLEN);
317
355
  /*
318
356
    Ensure that the dll doesn't have a path.
319
357
    This is done to ensure that only approved libraries from the
327
365
    if (report & REPORT_TO_USER)
328
366
      my_error(ER_UDF_NO_PATHS, MYF(0));
329
367
    if (report & REPORT_TO_LOG)
330
 
      sql_print_error(ER(ER_UDF_NO_PATHS));
 
368
      errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
331
369
    return(0);
332
370
  }
333
371
  /* If this dll is already loaded just increase ref_count. */
334
372
  if ((tmp= plugin_dl_find(dl)))
335
373
  {
336
 
    tmp->ref_count++;
337
374
    return(tmp);
338
375
  }
339
376
  memset(&plugin_dl, 0, sizeof(plugin_dl));
340
377
  /* 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;
 
378
  dlpath.append(opt_plugin_dir);
 
379
  dlpath.append("/");
 
380
  dlpath.append(dl->str);
345
381
  /* Open new dll handle */
346
 
  if (!(plugin_dl.handle= dlopen(dlpath, RTLD_LAZY|RTLD_GLOBAL)))
 
382
  if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
347
383
  {
348
384
    const char *errmsg=dlerror();
349
 
    if (!strncmp(dlpath, errmsg, dlpathlen))
 
385
    uint32_t dlpathlen= dlpath.length();
 
386
    if (!dlpath.compare(0, dlpathlen, errmsg))
350
387
    { // if errmsg starts from dlpath, trim this prefix.
351
388
      errmsg+=dlpathlen;
352
389
      if (*errmsg == ':') errmsg++;
353
390
      if (*errmsg == ' ') errmsg++;
354
391
    }
355
392
    if (report & REPORT_TO_USER)
356
 
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
 
393
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
357
394
    if (report & REPORT_TO_LOG)
358
 
      sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
 
395
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
359
396
    return(0);
360
397
  }
361
398
 
366
403
    if (report & REPORT_TO_USER)
367
404
      my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
368
405
    if (report & REPORT_TO_LOG)
369
 
      sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
 
406
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
370
407
    return(0);
371
408
  }
372
409
 
374
411
 
375
412
  /* Duplicate and convert dll name */
376
413
  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))))
 
414
  if (! (plugin_dl.dl.str= (char*) malloc(plugin_dl.dl.length)))
378
415
  {
379
416
    free_plugin_mem(&plugin_dl);
380
417
    if (report & REPORT_TO_USER)
381
418
      my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
382
419
    if (report & REPORT_TO_LOG)
383
 
      sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
 
420
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
384
421
    return(0);
385
422
  }
386
423
  plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
394
431
    if (report & REPORT_TO_USER)
395
432
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
396
433
    if (report & REPORT_TO_LOG)
397
 
      sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
 
434
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
398
435
    return(0);
399
436
  }
400
437
  return(tmp);
409
446
  {
410
447
    struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
411
448
                                               struct st_plugin_dl **);
412
 
    if (tmp->ref_count &&
413
 
        ! my_strnncoll(files_charset_info,
 
449
    if (! my_strnncoll(files_charset_info,
414
450
                       (const unsigned char *)dl->str, dl->length,
415
451
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
416
452
    {
417
453
      /* Do not remove this element, unless no other plugin uses this dll. */
418
 
      if (! --tmp->ref_count)
419
454
      {
420
455
        free_plugin_mem(tmp);
421
456
        memset(tmp, 0, sizeof(struct st_plugin_dl));
427
462
}
428
463
 
429
464
 
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
465
 
453
466
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
454
467
{
 
468
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
469
 
455
470
  SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
456
471
  struct st_plugin_int *plugin;
457
 
  if ((plugin= plugin_find_internal(name, type)))
 
472
 
 
473
  if (! initialized)
 
474
    return(rc);
 
475
 
 
476
  if ((plugin= registry.find(name, type)))
458
477
  {
459
478
    rc= SHOW_OPTION_DISABLED;
460
 
    if (plugin->state == PLUGIN_IS_READY)
 
479
    if (plugin->isInited)
461
480
      rc= SHOW_OPTION_YES;
462
481
  }
463
482
  return(rc);
480
499
}
481
500
 
482
501
 
483
 
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
 
502
static plugin_ref intern_plugin_lock(LEX *, plugin_ref rc)
484
503
{
485
504
  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);
 
505
  plugin_ref plugin;
 
506
 
 
507
  assert(pi);
 
508
  assert(rc);
 
509
 
 
510
  /*
 
511
    For debugging, we do an additional malloc which allows the
 
512
    memory manager and/or valgrind to track locked references and
 
513
    double unlocks to aid resolving reference counting.problems.
 
514
  */
 
515
  if (!(plugin= (plugin_ref) malloc(sizeof(pi))))
 
516
    return(NULL);
 
517
 
 
518
  *plugin= pi;
 
519
 
 
520
  return(plugin);
506
521
}
507
522
 
508
523
 
509
 
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
 
524
plugin_ref plugin_lock(Session *session, plugin_ref *ptr)
510
525
{
511
 
  LEX *lex= thd ? thd->lex : 0;
 
526
  LEX *lex= session ? session->lex : 0;
512
527
  plugin_ref rc;
513
 
  rc= my_intern_plugin_lock_ci(lex, *ptr);
 
528
  rc= intern_plugin_lock(lex, *ptr);
514
529
  return(rc);
515
530
}
516
531
 
517
532
 
518
 
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
519
 
                               CALLER_INFO_PROTO)
 
533
plugin_ref plugin_lock_by_name(Session *session, const LEX_STRING *name, int type)
520
534
{
521
 
  LEX *lex= thd ? thd->lex : 0;
 
535
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
536
 
 
537
  LEX *lex= session ? session->lex : 0;
522
538
  plugin_ref rc= NULL;
523
539
  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));
 
540
  if (! initialized)
 
541
    return(0);
 
542
 
 
543
  if ((plugin= registry.find(name, type)))
 
544
    rc= intern_plugin_lock(lex, plugin_int_to_ref(plugin));
526
545
  return(rc);
527
546
}
528
547
 
529
548
 
530
549
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
531
550
{
532
 
  uint32_t i;
533
551
  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
552
  if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
544
553
    return(0);
545
554
  tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
558
567
                       const LEX_STRING *name, const LEX_STRING *dl,
559
568
                       int *argc, char **argv, int report)
560
569
{
 
570
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
571
 
561
572
  struct st_plugin_int tmp;
562
573
  struct st_mysql_plugin *plugin;
563
 
  if (plugin_find_internal(name, DRIZZLE_ANY_PLUGIN))
 
574
  if (! initialized)
 
575
    return(0);
 
576
 
 
577
  if (registry.find(name, DRIZZLE_ANY_PLUGIN))
564
578
  {
565
579
    if (report & REPORT_TO_USER)
566
580
      my_error(ER_UDF_EXISTS, MYF(0), name->str);
567
581
    if (report & REPORT_TO_LOG)
568
 
      sql_print_error(ER(ER_UDF_EXISTS), name->str);
 
582
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
569
583
    return(true);
570
584
  }
571
585
  /* Clear the whole struct to catch future extensions. */
576
590
  for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
577
591
  {
578
592
    uint32_t name_len= strlen(plugin->name);
579
 
    if (plugin->type >= 0 && plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
 
593
    if (plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
580
594
        ! my_strnncoll(system_charset_info,
581
595
                       (const unsigned char *)name->str, name->length,
582
596
                       (const unsigned char *)plugin->name,
587
601
      tmp.plugin= plugin;
588
602
      tmp.name.str= (char *)plugin->name;
589
603
      tmp.name.length= name_len;
590
 
      tmp.ref_count= 0;
591
 
      tmp.state= PLUGIN_IS_UNINITIALIZED;
 
604
      tmp.isInited= false;
592
605
      if (!test_plugin_options(tmp_root, &tmp, argc, argv))
593
606
      {
594
607
        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
595
608
        {
596
609
          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;
 
610
          registry.add(plugin, tmp_plugin_ptr);
 
611
          init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
 
612
          return(false);
603
613
        }
604
614
        mysql_del_sys_var_chain(tmp.system_vars);
605
615
        goto err;
612
622
  if (report & REPORT_TO_USER)
613
623
    my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
614
624
  if (report & REPORT_TO_LOG)
615
 
    sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
 
625
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
616
626
err:
617
627
  plugin_dl_del(dl);
618
628
  return(true);
619
629
}
620
630
 
621
631
 
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
632
static void plugin_del(struct st_plugin_int *plugin)
668
633
{
 
634
  if (plugin->isInited)
 
635
  {
 
636
    if (plugin->plugin->status_vars)
 
637
    {
 
638
      remove_status_vars(plugin->plugin->status_vars);
 
639
    }
 
640
 
 
641
    if (plugin_type_deinitialize[plugin->plugin->type])
 
642
    {
 
643
      if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
 
644
      {
 
645
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' of type %s failed deinitialization"),
 
646
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
 
647
      }
 
648
    }
 
649
    else if (plugin->plugin->deinit)
 
650
      plugin->plugin->deinit(plugin);
 
651
  }
 
652
 
669
653
  /* Free allocated strings before deleting the plugin. */
670
654
  plugin_vars_free_values(plugin->system_vars);
671
 
  hash_delete(&plugin_hash[plugin->plugin->type], (unsigned char*)plugin);
672
655
  if (plugin->plugin_dl)
673
656
    plugin_dl_del(&plugin->plugin_dl->dl);
674
 
  plugin->state= PLUGIN_IS_FREED;
 
657
  plugin->isInited= false;
675
658
  plugin_array_version++;
676
 
  rw_wrlock(&LOCK_system_variables_hash);
 
659
  pthread_rwlock_wrlock(&LOCK_system_variables_hash);
677
660
  mysql_del_sys_var_chain(plugin->system_vars);
678
 
  rw_unlock(&LOCK_system_variables_hash);
 
661
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
679
662
  free_root(&plugin->mem_root, MYF(0));
680
 
  return;
681
663
}
682
664
 
683
665
static void reap_plugins(void)
684
666
{
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;
 
667
  size_t count;
 
668
  uint32_t idx;
 
669
  struct st_plugin_int *plugin;
 
670
 
692
671
  count= plugin_array.elements;
693
 
  reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
694
 
  *(reap++)= NULL;
695
672
 
696
673
  for (idx= 0; idx < count; idx++)
697
674
  {
698
675
    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
676
    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
677
  }
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
 
{
 
678
}
 
679
 
 
680
static bool plugin_initialize(struct st_plugin_int *plugin)
 
681
{
 
682
  assert(plugin->isInited == false);
777
683
 
778
684
  if (plugin_type_initialize[plugin->plugin->type])
779
685
  {
780
686
    if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
781
687
    {
782
 
      sql_print_error(_("Plugin '%s' registration as a %s failed."),
 
688
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' registration as a %s failed."),
783
689
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
784
690
      goto err;
785
691
    }
788
694
  {
789
695
    if (plugin->plugin->init(plugin))
790
696
    {
791
 
      sql_print_error(_("Plugin '%s' init function returned error."),
 
697
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' init function returned error."),
792
698
                      plugin->name.str);
793
699
      goto err;
794
700
    }
795
701
  }
796
 
 
797
 
  plugin->state= PLUGIN_IS_READY;
 
702
  plugin->isInited= true;
798
703
 
799
704
  if (plugin->plugin->status_vars)
800
705
  {
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
706
    add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
817
 
#endif /* FIX_LATER */
818
707
  }
819
708
 
820
709
  /*
833
722
    }
834
723
  }
835
724
 
836
 
  return(0);
 
725
  return false;
837
726
err:
838
 
  return(1);
 
727
  return true;
839
728
}
840
729
 
841
730
 
842
 
extern "C" unsigned char *get_plugin_hash_key(const unsigned char *, size_t *, bool);
843
731
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
844
732
 
845
733
 
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)))
 
734
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
857
735
{
858
736
  struct st_bookmark *var= (st_bookmark *)buff;
859
737
  *length= var->name_len + 1;
870
748
*/
871
749
int plugin_init(int *argc, char **argv, int flags)
872
750
{
873
 
  uint32_t i;
 
751
  uint32_t idx;
874
752
  struct st_mysql_plugin **builtins;
875
753
  struct st_mysql_plugin *plugin;
876
 
  struct st_plugin_int tmp, *plugin_ptr, **reap;
 
754
  struct st_plugin_int tmp, *plugin_ptr;
877
755
  MEM_ROOT tmp_root;
878
756
 
879
757
  if (initialized)
893
771
                            sizeof(struct st_plugin_int *),16,16))
894
772
    goto err;
895
773
 
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
774
  initialized= 1;
904
775
 
905
776
  /*
932
803
      {
933
804
        assert(!global_system_variables.table_plugin);
934
805
        global_system_variables.table_plugin=
935
 
          my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
936
 
        assert(plugin_ptr->ref_count == 1);
 
806
          intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
937
807
      }
938
808
    }
939
809
  }
954
824
  /*
955
825
    Now we initialize all remaining plugins
956
826
  */
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++)
 
827
  for (idx= 0; idx < plugin_array.elements; idx++)
962
828
  {
963
 
    plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
964
 
    if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
 
829
    plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
 
830
    if (plugin_ptr->isInited == false)
965
831
    {
966
832
      if (plugin_initialize(plugin_ptr))
967
 
      {
968
 
        plugin_ptr->state= PLUGIN_IS_DYING;
969
 
        *(reap++)= plugin_ptr;
970
 
      }
 
833
        plugin_del(plugin_ptr);
971
834
    }
972
835
  }
973
836
 
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
837
 
985
838
end:
986
839
  free_root(&tmp_root, MYF(0));
999
852
                             struct st_plugin_int **ptr)
1000
853
{
1001
854
 
1002
 
  tmp->state= PLUGIN_IS_UNINITIALIZED;
1003
 
  tmp->ref_count= 0;
 
855
  Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
856
 
 
857
  tmp->isInited= false;
1004
858
  tmp->plugin_dl= 0;
1005
859
 
1006
860
  if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
1011
865
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
1012
866
                                             sizeof(struct st_plugin_int));
1013
867
 
1014
 
  if (my_hash_insert(&plugin_hash[plugin->type],(unsigned char*) *ptr))
1015
 
    return(1);
 
868
  registry.add(plugin, *ptr);
1016
869
 
1017
870
  return(0);
1018
871
}
1033
886
  {
1034
887
    if (p == buffer + sizeof(buffer) - 1)
1035
888
    {
1036
 
      sql_print_error(_("plugin-load parameter too long"));
 
889
      errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
1037
890
      return(true);
1038
891
    }
1039
892
 
1093
946
  }
1094
947
  return(false);
1095
948
error:
1096
 
  sql_print_error(_("Couldn't load plugin named '%s' with soname '%s'."),
 
949
  errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
1097
950
                  name.str, dl.str);
1098
951
  return(true);
1099
952
}
1101
954
 
1102
955
void plugin_shutdown(void)
1103
956
{
1104
 
  uint32_t i, count= plugin_array.elements, free_slots= 0;
1105
 
  struct st_plugin_int **plugins, *plugin;
1106
 
  struct st_plugin_dl **dl;
 
957
  uint32_t idx;
 
958
  size_t count= plugin_array.elements;
 
959
  vector<st_plugin_int *> plugins;
 
960
  vector<st_plugin_dl *> dl;
1107
961
 
1108
962
  if (initialized)
1109
963
  {
1110
964
    reap_needed= true;
1111
965
 
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
 
    */
 
966
    reap_plugins();
 
967
    unlock_variables(NULL, &global_system_variables);
 
968
    unlock_variables(NULL, &max_system_variables);
1194
969
 
1195
970
    cleanup_variables(NULL, &global_system_variables);
1196
971
    cleanup_variables(NULL, &max_system_variables);
1197
972
 
1198
973
    initialized= 0;
1199
 
 
1200
 
    my_afree(plugins);
1201
974
  }
1202
975
 
1203
976
  /* Dispose of the memory */
1204
977
 
1205
 
  for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1206
 
    hash_free(&plugin_hash[i]);
1207
978
  delete_dynamic(&plugin_array);
1208
979
 
1209
980
  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);
 
981
  dl.reserve(count);
 
982
  for (idx= 0; idx < count; idx++)
 
983
    dl.push_back(*dynamic_element(&plugin_dl_array, idx,
 
984
                 struct st_plugin_dl **));
 
985
  for (idx= 0; idx < count; idx++)
 
986
    free_plugin_mem(dl[idx]);
1216
987
  delete_dynamic(&plugin_dl_array);
1217
988
 
1218
989
  hash_free(&bookmark_hash);
1219
990
  free_root(&plugin_mem_root, MYF(0));
1220
991
 
1221
992
  global_variables_dynamic_size= 0;
1222
 
 
1223
 
  return;
1224
993
}
1225
994
 
1226
 
 
1227
 
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1228
 
                       int type, uint32_t state_mask, void *arg)
 
995
/**
 
996
 *
 
997
 * all: List all plugins
 
998
 */
 
999
bool plugin_foreach(Session *session, plugin_foreach_func *func, int type, void *arg, bool all)
1229
1000
{
1230
 
  uint32_t idx, total;
1231
 
  struct st_plugin_int *plugin, **plugins;
 
1001
  uint32_t idx;
 
1002
  struct st_plugin_int *plugin;
 
1003
  vector<st_plugin_int *> plugins;
1232
1004
  int version=plugin_array_version;
1233
1005
 
1234
1006
  if (!initialized)
1235
1007
    return(false);
1236
1008
 
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
1009
  if (type == DRIZZLE_ANY_PLUGIN)
1247
1010
  {
1248
 
    for (idx= 0; idx < total; idx++)
 
1011
    plugins.reserve(plugin_array.elements);
 
1012
    for (idx= 0; idx < plugin_array.elements; idx++)
1249
1013
    {
1250
1014
      plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1251
 
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
 
1015
      if (all)
 
1016
        plugins.push_back(plugin);
 
1017
      else if (plugin->isInited)
 
1018
        plugins.push_back(plugin);
1252
1019
    }
1253
1020
  }
1254
1021
  else
1255
1022
  {
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
 
    }
 
1023
    Plugin_registry registry= Plugin_registry::get_plugin_registry();
 
1024
    registry.get_list(type, plugins, all);
1262
1025
  }
1263
 
  for (idx= 0; idx < total; idx++)
 
1026
 
 
1027
  vector<st_plugin_int *>::iterator plugin_iter;
 
1028
  for (plugin_iter= plugins.begin();
 
1029
       plugin_iter != plugins.end();
 
1030
       plugin_iter++)
1264
1031
  {
1265
1032
    if (unlikely(version != plugin_array_version))
1266
1033
    {
1267
 
      for (uint32_t i=idx; i < total; i++)
1268
 
        if (plugins[i] && plugins[i]->state & state_mask)
1269
 
          plugins[i]=0;
 
1034
      vector<st_plugin_int *>::iterator reset_iter;
 
1035
      for (reset_iter= plugin_iter;
 
1036
           reset_iter != plugins.end();
 
1037
           reset_iter++)
 
1038
        if (*reset_iter && (*reset_iter)->isInited && all)
 
1039
          *reset_iter=0;
1270
1040
    }
1271
 
    plugin= plugins[idx];
 
1041
    plugin= *plugin_iter;
1272
1042
    /* It will stop iterating on first engine error when "func" returns true */
1273
 
    if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
 
1043
    if (plugin && func(session, plugin_int_to_ref(plugin), arg))
1274
1044
        goto err;
1275
1045
  }
1276
1046
 
1277
 
  my_afree(plugins);
1278
 
  return(false);
 
1047
  return false;
1279
1048
err:
1280
 
  my_afree(plugins);
1281
 
  return(true);
 
1049
  return true;
1282
1050
}
1283
1051
 
1284
1052
 
1293
1061
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1294
1062
 
1295
1063
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1296
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_bool_t, bool);
 
1064
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1297
1065
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1298
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_str_t, char *);
 
1066
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1299
1067
 
1300
1068
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1301
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
 
1069
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1302
1070
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1303
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
 
1071
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1304
1072
 
1305
1073
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1306
1074
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1309
1077
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1310
1078
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1311
1079
 
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);
 
1080
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
 
1081
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
 
1082
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
 
1083
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
 
1084
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
 
1085
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1318
1086
 
1319
 
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
 
1087
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1320
1088
 
1321
1089
 
1322
1090
/****************************************************************************
1323
1091
  default variable data check and update functions
1324
1092
****************************************************************************/
1325
1093
 
1326
 
static int check_func_bool(THD *thd __attribute__((unused)),
1327
 
                           struct st_mysql_sys_var *var,
 
1094
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
1328
1095
                           void *save, st_mysql_value *value)
1329
1096
{
1330
1097
  char buff[STRING_BUFFER_USUAL_SIZE];
1363
1130
}
1364
1131
 
1365
1132
 
1366
 
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
 
1133
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1367
1134
                          void *save, st_mysql_value *value)
1368
1135
{
1369
1136
  bool fixed;
1373
1140
  plugin_opt_set_limits(&options, var);
1374
1141
 
1375
1142
  if (var->flags & PLUGIN_VAR_UNSIGNED)
1376
 
    *(uint32_t *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
 
1143
    *(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
1377
1144
                                                   &fixed);
1378
1145
  else
1379
1146
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1380
1147
 
1381
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1148
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1382
1149
                              var->name, (int64_t) tmp);
1383
1150
}
1384
1151
 
1385
1152
 
1386
 
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
 
1153
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1387
1154
                          void *save, st_mysql_value *value)
1388
1155
{
1389
1156
  bool fixed;
1398
1165
  else
1399
1166
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1400
1167
 
1401
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1168
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1402
1169
                              var->name, (int64_t) tmp);
1403
1170
}
1404
1171
 
1405
1172
 
1406
 
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
 
1173
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1407
1174
                               void *save, st_mysql_value *value)
1408
1175
{
1409
1176
  bool fixed;
1418
1185
  else
1419
1186
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1420
1187
 
1421
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1188
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1422
1189
                              var->name, (int64_t) tmp);
1423
1190
}
1424
1191
 
1425
 
static int check_func_str(THD *thd,
1426
 
                          struct st_mysql_sys_var *var __attribute__((unused)),
 
1192
static int check_func_str(Session *session, struct st_mysql_sys_var *,
1427
1193
                          void *save, st_mysql_value *value)
1428
1194
{
1429
1195
  char buff[STRING_BUFFER_USUAL_SIZE];
1432
1198
 
1433
1199
  length= sizeof(buff);
1434
1200
  if ((str= value->val_str(value, buff, &length)))
1435
 
    str= thd->strmake(str, length);
 
1201
    str= session->strmake(str, length);
1436
1202
  *(const char**)save= str;
1437
1203
  return 0;
1438
1204
}
1439
1205
 
1440
1206
 
1441
 
static int check_func_enum(THD *thd __attribute__((unused)),
1442
 
                           struct st_mysql_sys_var *var,
 
1207
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
1443
1208
                           void *save, st_mysql_value *value)
1444
1209
{
1445
1210
  char buff[STRING_BUFFER_USUAL_SIZE];
1449
1214
  long result;
1450
1215
  int length;
1451
1216
 
1452
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1453
 
    typelib= ((thdvar_enum_t*) var)->typelib;
 
1217
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1218
    typelib= ((sessionvar_enum_t*) var)->typelib;
1454
1219
  else
1455
1220
    typelib= ((sysvar_enum_t*) var)->typelib;
1456
1221
 
1485
1250
}
1486
1251
 
1487
1252
 
1488
 
static int check_func_set(THD *thd __attribute__((unused)),
1489
 
                          struct st_mysql_sys_var *var,
 
1253
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1490
1254
                          void *save, st_mysql_value *value)
1491
1255
{
1492
1256
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1497
1261
  bool not_used;
1498
1262
  int length;
1499
1263
 
1500
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1501
 
    typelib= ((thdvar_set_t*) var)->typelib;
 
1264
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1265
    typelib= ((sessionvar_set_t*) var)->typelib;
1502
1266
  else
1503
1267
    typelib= ((sysvar_set_t*)var)->typelib;
1504
1268
 
1511
1275
                     &error, &error_len, &not_used);
1512
1276
    if (error_len)
1513
1277
    {
1514
 
      strmake(buff, error, cmin(sizeof(buff), (unsigned long)error_len));
 
1278
      length= cmin(sizeof(buff), (unsigned long)error_len);
 
1279
      strncpy(buff, error, length);
 
1280
      buff[length]= '\0';
1515
1281
      strvalue= buff;
1516
1282
      goto err;
1517
1283
    }
1536
1302
}
1537
1303
 
1538
1304
 
1539
 
static void update_func_bool(THD *thd __attribute__((unused)),
1540
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1305
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1541
1306
                             void *tgt, const void *save)
1542
1307
{
1543
1308
  *(bool *) tgt= *(int *) save ? 1 : 0;
1544
1309
}
1545
1310
 
1546
1311
 
1547
 
static void update_func_int(THD *thd __attribute__((unused)),
1548
 
                            struct st_mysql_sys_var *var __attribute__((unused)),
 
1312
static void update_func_int(Session *, struct st_mysql_sys_var *,
1549
1313
                             void *tgt, const void *save)
1550
1314
{
1551
1315
  *(int *)tgt= *(int *) save;
1552
1316
}
1553
1317
 
1554
1318
 
1555
 
static void update_func_long(THD *thd __attribute__((unused)),
1556
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1319
static void update_func_long(Session *, struct st_mysql_sys_var *,
1557
1320
                             void *tgt, const void *save)
1558
1321
{
1559
1322
  *(long *)tgt= *(long *) save;
1560
1323
}
1561
1324
 
1562
1325
 
1563
 
static void update_func_int64_t(THD *thd __attribute__((unused)),
1564
 
                                 struct st_mysql_sys_var *var __attribute__((unused)),
 
1326
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1565
1327
                                 void *tgt, const void *save)
1566
1328
{
1567
1329
  *(int64_t *)tgt= *(uint64_t *) save;
1568
1330
}
1569
1331
 
1570
1332
 
1571
 
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
 
1333
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1572
1334
                             void *tgt, const void *save)
1573
1335
{
1574
1336
  char *old= *(char **) tgt;
1575
1337
  *(char **)tgt= *(char **) save;
1576
1338
  if (var->flags & PLUGIN_VAR_MEMALLOC)
1577
1339
  {
1578
 
    *(char **)tgt= my_strdup(*(char **) save, MYF(0));
 
1340
    *(char **)tgt= strdup(*(char **) save);
1579
1341
    free(old);
 
1342
    /*
 
1343
     * There isn't a _really_ good thing to do here until this whole set_var
 
1344
     * mess gets redesigned
 
1345
     */
 
1346
    if (tgt == NULL)
 
1347
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
 
1348
 
1580
1349
  }
1581
1350
}
1582
1351
 
1586
1355
****************************************************************************/
1587
1356
 
1588
1357
 
1589
 
sys_var *find_sys_var(THD *thd, const char *str, uint32_t length)
 
1358
sys_var *find_sys_var(Session *session, const char *str, uint32_t length)
1590
1359
{
1591
1360
  sys_var *var;
1592
1361
  sys_var_pluginvar *pi= NULL;
1593
1362
  plugin_ref plugin;
1594
1363
 
1595
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1364
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1596
1365
  if ((var= intern_find_sys_var(str, length, false)) &&
1597
1366
      (pi= var->cast_pluginvar()))
1598
1367
  {
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))))
 
1368
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
1369
    LEX *lex= session ? session->lex : 0;
 
1370
    if (!(plugin= intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1602
1371
      var= NULL; /* failed to lock it, it must be uninstalling */
1603
 
    else
1604
 
    if (!(plugin_state(plugin) & PLUGIN_IS_READY))
 
1372
    else if (plugin[0]->isInited == false)
1605
1373
    {
1606
 
      /* initialization not completed */
1607
1374
      var= NULL;
1608
 
      intern_plugin_unlock(lex, plugin);
1609
1375
    }
1610
1376
  }
1611
1377
  else
1612
 
    rw_unlock(&LOCK_system_variables_hash);
 
1378
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1613
1379
 
1614
1380
  /*
1615
1381
    If the variable exists but the plugin it is associated with is not ready
1632
1398
  uint32_t namelen, length, pluginlen= 0;
1633
1399
  char *varname, *p;
1634
1400
 
1635
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1401
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1636
1402
    return NULL;
1637
1403
 
1638
1404
  namelen= strlen(name);
1639
1405
  if (plugin)
1640
1406
    pluginlen= strlen(plugin) + 1;
1641
1407
  length= namelen + pluginlen + 2;
1642
 
  varname= (char*) my_alloca(length);
 
1408
  varname= (char*) malloc(length);
1643
1409
 
1644
1410
  if (plugin)
1645
1411
  {
1646
 
    strxmov(varname + 1, plugin, "_", name, NULL);
 
1412
    sprintf(varname+1,"%s_%s",plugin,name);
1647
1413
    for (p= varname + 1; *p; p++)
1648
1414
      if (*p == '-')
1649
1415
        *p= '_';
1656
1422
  result= (st_bookmark*) hash_search(&bookmark_hash,
1657
1423
                                     (const unsigned char*) varname, length - 1);
1658
1424
 
1659
 
  my_afree(varname);
 
1425
  free(varname);
1660
1426
  return result;
1661
1427
}
1662
1428
 
1663
1429
 
1664
1430
/*
1665
 
  returns a bookmark for thd-local variables, creating if neccessary.
1666
 
  returns null for non thd-local variables.
 
1431
  returns a bookmark for session-local variables, creating if neccessary.
 
1432
  returns null for non session-local variables.
1667
1433
  Requires that a write lock is obtained on LOCK_system_variables_hash
1668
1434
*/
1669
1435
static st_bookmark *register_var(const char *plugin, const char *name,
1673
1439
  st_bookmark *result;
1674
1440
  char *varname, *p;
1675
1441
 
1676
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1442
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1677
1443
    return NULL;
1678
1444
 
1679
1445
  switch (flags & PLUGIN_VAR_TYPEMASK) {
1680
1446
  case PLUGIN_VAR_BOOL:
1681
 
    size= sizeof(bool);
 
1447
    size= ALIGN_SIZE(sizeof(bool));
1682
1448
    break;
1683
1449
  case PLUGIN_VAR_INT:
1684
 
    size= sizeof(int);
 
1450
    size= ALIGN_SIZE(sizeof(int));
1685
1451
    break;
1686
1452
  case PLUGIN_VAR_LONG:
1687
1453
  case PLUGIN_VAR_ENUM:
1688
 
    size= sizeof(long);
 
1454
    size= ALIGN_SIZE(sizeof(long));
1689
1455
    break;
1690
1456
  case PLUGIN_VAR_LONGLONG:
1691
1457
  case PLUGIN_VAR_SET:
1692
 
    size= sizeof(uint64_t);
 
1458
    size= ALIGN_SIZE(sizeof(uint64_t));
1693
1459
    break;
1694
1460
  case PLUGIN_VAR_STR:
1695
 
    size= sizeof(char*);
 
1461
    size= ALIGN_SIZE(sizeof(char*));
1696
1462
    break;
1697
1463
  default:
1698
1464
    assert(0);
1699
1465
    return NULL;
1700
1466
  };
1701
1467
 
1702
 
  varname= ((char*) my_alloca(length));
1703
 
  strxmov(varname + 1, plugin, "_", name, NULL);
 
1468
  varname= ((char*) malloc(length));
 
1469
  sprintf(varname+1, "%s_%s", plugin, name);
1704
1470
  for (p= varname + 1; *p; p++)
1705
1471
    if (*p == '-')
1706
1472
      *p= '_';
1724
1490
 
1725
1491
    if (new_size > global_variables_dynamic_size)
1726
1492
    {
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));
 
1493
      char* tmpptr= NULL;
 
1494
      if (!(tmpptr=
 
1495
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
 
1496
                              new_size)))
 
1497
        return NULL;
 
1498
      global_system_variables.dynamic_variables_ptr= tmpptr;
 
1499
      tmpptr= NULL;
 
1500
      if (!(tmpptr=
 
1501
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
 
1502
                              new_size)))
 
1503
        return NULL;
 
1504
      max_system_variables.dynamic_variables_ptr= tmpptr;
 
1505
           
1733
1506
      /*
1734
1507
        Clear the new variable value space. This is required for string
1735
1508
        variables. If their value is non-NULL, it must point to a valid
1739
1512
             global_variables_dynamic_size, 0,
1740
1513
             new_size - global_variables_dynamic_size);
1741
1514
      memset(max_system_variables.dynamic_variables_ptr +
1742
 
             global_variables_dynamic_size, 0, 
 
1515
             global_variables_dynamic_size, 0,
1743
1516
             new_size - global_variables_dynamic_size);
1744
1517
      global_variables_dynamic_size= new_size;
1745
1518
    }
1760
1533
      assert(0);
1761
1534
    }
1762
1535
  }
1763
 
  my_afree(varname);
 
1536
  free(varname);
1764
1537
  return result;
1765
1538
}
1766
1539
 
1767
1540
 
1768
1541
/*
1769
 
  returns a pointer to the memory which holds the thd-local variable or
1770
 
  a pointer to the global variable if thd==null.
 
1542
  returns a pointer to the memory which holds the session-local variable or
 
1543
  a pointer to the global variable if session==null.
1771
1544
  If required, will sync with global variables if the requested variable
1772
1545
  has not yet been allocated in the current thread.
1773
1546
*/
1774
 
static unsigned char *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
 
1547
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1775
1548
{
1776
1549
  assert(offset >= 0);
1777
 
  assert((uint)offset <= global_system_variables.dynamic_variables_head);
 
1550
  assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
1778
1551
 
1779
 
  if (!thd)
 
1552
  if (!session)
1780
1553
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1781
1554
 
1782
1555
  /*
1783
1556
    dynamic_variables_head points to the largest valid offset
1784
1557
  */
1785
 
  if (!thd->variables.dynamic_variables_ptr ||
1786
 
      (uint)offset > thd->variables.dynamic_variables_head)
 
1558
  if (!session->variables.dynamic_variables_ptr ||
 
1559
      (uint32_t)offset > session->variables.dynamic_variables_head)
1787
1560
  {
1788
1561
    uint32_t idx;
1789
1562
 
1790
 
    rw_rdlock(&LOCK_system_variables_hash);
 
1563
    pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1791
1564
 
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));
 
1565
    char *tmpptr= NULL;
 
1566
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
 
1567
                                  global_variables_dynamic_size)))
 
1568
      return NULL;
 
1569
    session->variables.dynamic_variables_ptr= tmpptr;
1796
1570
 
1797
1571
    if (global_lock)
1798
1572
      pthread_mutex_lock(&LOCK_global_system_variables);
1799
1573
 
1800
1574
    safe_mutex_assert_owner(&LOCK_global_system_variables);
1801
1575
 
1802
 
    memcpy(thd->variables.dynamic_variables_ptr +
1803
 
             thd->variables.dynamic_variables_size,
 
1576
    memcpy(session->variables.dynamic_variables_ptr +
 
1577
             session->variables.dynamic_variables_size,
1804
1578
           global_system_variables.dynamic_variables_ptr +
1805
 
             thd->variables.dynamic_variables_size,
 
1579
             session->variables.dynamic_variables_size,
1806
1580
           global_system_variables.dynamic_variables_size -
1807
 
             thd->variables.dynamic_variables_size);
 
1581
             session->variables.dynamic_variables_size);
1808
1582
 
1809
1583
    /*
1810
1584
      now we need to iterate through any newly copied 'defaults'
1816
1590
      sys_var *var;
1817
1591
      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1818
1592
 
1819
 
      if (v->version <= thd->variables.dynamic_variables_version ||
 
1593
      if (v->version <= session->variables.dynamic_variables_version ||
1820
1594
          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1821
1595
          !(pi= var->cast_pluginvar()) ||
1822
1596
          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1827
1601
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1828
1602
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1829
1603
      {
1830
 
         char **pp= (char**) (thd->variables.dynamic_variables_ptr +
 
1604
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
1831
1605
                             *(int*)(pi->plugin_var + 1));
1832
1606
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1833
1607
                             *(int*)(pi->plugin_var + 1))))
1834
 
           *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
 
1608
           *pp= strdup(*pp);
 
1609
         if (*pp == NULL)
 
1610
           return NULL;
1835
1611
      }
1836
1612
    }
1837
1613
 
1838
1614
    if (global_lock)
1839
1615
      pthread_mutex_unlock(&LOCK_global_system_variables);
1840
1616
 
1841
 
    thd->variables.dynamic_variables_version=
 
1617
    session->variables.dynamic_variables_version=
1842
1618
           global_system_variables.dynamic_variables_version;
1843
 
    thd->variables.dynamic_variables_head=
 
1619
    session->variables.dynamic_variables_head=
1844
1620
           global_system_variables.dynamic_variables_head;
1845
 
    thd->variables.dynamic_variables_size=
 
1621
    session->variables.dynamic_variables_size=
1846
1622
           global_system_variables.dynamic_variables_size;
1847
1623
 
1848
 
    rw_unlock(&LOCK_system_variables_hash);
 
1624
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1849
1625
  }
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;
 
1626
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
 
1627
}
 
1628
 
 
1629
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
 
1630
{
 
1631
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
 
1632
}
 
1633
 
 
1634
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
 
1635
{
 
1636
  return (int *)intern_sys_var_ptr(a_session, offset, true);
 
1637
}
 
1638
 
 
1639
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
 
1640
{
 
1641
  return (long *)intern_sys_var_ptr(a_session, offset, true);
 
1642
}
 
1643
 
 
1644
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
 
1645
{
 
1646
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1647
}
 
1648
 
 
1649
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
 
1650
{
 
1651
  return (char **)intern_sys_var_ptr(a_session, offset, true);
 
1652
}
 
1653
 
 
1654
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
 
1655
{
 
1656
  return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1657
}
 
1658
 
 
1659
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
 
1660
{
 
1661
  return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
 
1662
}
 
1663
 
 
1664
 
 
1665
void plugin_sessionvar_init(Session *session)
 
1666
{
 
1667
  session->variables.table_plugin= NULL;
 
1668
  cleanup_variables(session, &session->variables);
 
1669
 
 
1670
  session->variables= global_system_variables;
 
1671
  session->variables.table_plugin= NULL;
1898
1672
 
1899
1673
  /* 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;
 
1674
  session->variables.dynamic_variables_version= 0;
 
1675
  session->variables.dynamic_variables_size= 0;
 
1676
  session->variables.dynamic_variables_ptr= 0;
1903
1677
 
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;
 
1678
  session->variables.table_plugin=
 
1679
    intern_plugin_lock(NULL, global_system_variables.table_plugin);
1908
1680
}
1909
1681
 
1910
1682
 
1911
1683
/*
1912
1684
  Unlocks all system variables which hold a reference
1913
1685
*/
1914
 
static void unlock_variables(THD *thd __attribute__((unused)),
1915
 
                             struct system_variables *vars)
 
1686
static void unlock_variables(Session *, struct system_variables *vars)
1916
1687
{
1917
 
  intern_plugin_unlock(NULL, vars->table_plugin);
1918
1688
  vars->table_plugin= NULL;
1919
1689
}
1920
1690
 
1925
1695
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
1926
1696
  it's used on shutdown.
1927
1697
*/
1928
 
static void cleanup_variables(THD *thd, struct system_variables *vars)
 
1698
static void cleanup_variables(Session *session, struct system_variables *vars)
1929
1699
{
1930
1700
  st_bookmark *v;
1931
1701
  sys_var_pluginvar *pivar;
1933
1703
  int flags;
1934
1704
  uint32_t idx;
1935
1705
 
1936
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1706
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1937
1707
  for (idx= 0; idx < bookmark_hash.records; idx++)
1938
1708
  {
1939
1709
    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1946
1716
    flags= pivar->plugin_var->flags;
1947
1717
 
1948
1718
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1949
 
        flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
 
1719
        flags & PLUGIN_VAR_SessionLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1950
1720
    {
1951
 
      char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
 
1721
      char **ptr= (char**) pivar->real_value_ptr(session, OPT_SESSION);
1952
1722
      free(*ptr);
1953
1723
      *ptr= NULL;
1954
1724
    }
1955
1725
  }
1956
 
  rw_unlock(&LOCK_system_variables_hash);
 
1726
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
1957
1727
 
1958
1728
  assert(vars->table_plugin == NULL);
1959
1729
 
1964
1734
}
1965
1735
 
1966
1736
 
1967
 
void plugin_thdvar_cleanup(THD *thd)
 
1737
void plugin_sessionvar_cleanup(Session *session)
1968
1738
{
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;
 
1739
  unlock_variables(session, &session->variables);
 
1740
  cleanup_variables(session, &session->variables);
1985
1741
}
1986
1742
 
1987
1743
 
2056
1812
}
2057
1813
 
2058
1814
 
2059
 
unsigned char* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
 
1815
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2060
1816
{
2061
 
  assert(thd || (type == OPT_GLOBAL));
2062
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
1817
  assert(session || (type == OPT_GLOBAL));
 
1818
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2063
1819
  {
2064
1820
    if (type == OPT_GLOBAL)
2065
 
      thd= NULL;
 
1821
      session= NULL;
2066
1822
 
2067
 
    return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
 
1823
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2068
1824
  }
2069
1825
  return *(unsigned char**) (plugin_var+1);
2070
1826
}
2072
1828
 
2073
1829
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2074
1830
{
2075
 
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
 
1831
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2076
1832
  case PLUGIN_VAR_ENUM:
2077
1833
    return ((sysvar_enum_t *)plugin_var)->typelib;
2078
1834
  case PLUGIN_VAR_SET:
2079
1835
    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;
 
1836
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
 
1837
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
1838
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
 
1839
    return ((sessionvar_set_t *)plugin_var)->typelib;
2084
1840
  default:
2085
1841
    return NULL;
2086
1842
  }
2088
1844
}
2089
1845
 
2090
1846
 
2091
 
unsigned char* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
2092
 
                                    LEX_STRING *base __attribute__((unused)))
 
1847
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
2093
1848
{
2094
1849
  unsigned char* result;
2095
1850
 
2096
 
  result= real_value_ptr(thd, type);
 
1851
  result= real_value_ptr(session, type);
2097
1852
 
2098
1853
  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2099
1854
    result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2116
1871
 
2117
1872
    result= (unsigned char*) "";
2118
1873
    if (str.length())
2119
 
      result= (unsigned char*) thd->strmake(str.ptr(), str.length()-1);
 
1874
      result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2120
1875
  }
2121
1876
  return result;
2122
1877
}
2123
1878
 
2124
1879
 
2125
 
bool sys_var_pluginvar::check(THD *thd, set_var *var)
 
1880
bool sys_var_pluginvar::check(Session *session, set_var *var)
2126
1881
{
2127
1882
  st_item_value_holder value;
2128
1883
  assert(is_readonly() || plugin_var->check);
2134
1889
  value.item= var->value;
2135
1890
 
2136
1891
  return is_readonly() ||
2137
 
         plugin_var->check(thd, plugin_var, &var->save_result, &value);
 
1892
         plugin_var->check(session, plugin_var, &var->save_result, &value);
2138
1893
}
2139
1894
 
2140
1895
 
2141
 
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
 
1896
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2142
1897
{
2143
1898
  const void *src;
2144
1899
  void *tgt;
2149
1904
    return;
2150
1905
 
2151
1906
  pthread_mutex_lock(&LOCK_global_system_variables);
2152
 
  tgt= real_value_ptr(thd, type);
 
1907
  tgt= real_value_ptr(session, type);
2153
1908
  src= ((void **) (plugin_var + 1) + 1);
2154
1909
 
2155
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
1910
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2156
1911
  {
2157
1912
    if (type != OPT_GLOBAL)
2158
 
      src= real_value_ptr(thd, OPT_GLOBAL);
 
1913
      src= real_value_ptr(session, OPT_GLOBAL);
2159
1914
    else
2160
1915
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2161
1916
        case PLUGIN_VAR_INT:
2162
 
          src= &((thdvar_uint_t*) plugin_var)->def_val;
 
1917
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
2163
1918
          break;
2164
1919
        case PLUGIN_VAR_LONG:
2165
 
          src= &((thdvar_ulong_t*) plugin_var)->def_val;
 
1920
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2166
1921
          break;
2167
1922
        case PLUGIN_VAR_LONGLONG:
2168
 
          src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
 
1923
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2169
1924
          break;
2170
1925
        case PLUGIN_VAR_ENUM:
2171
 
          src= &((thdvar_enum_t*) plugin_var)->def_val;
 
1926
          src= &((sessionvar_enum_t*) plugin_var)->def_val;
2172
1927
          break;
2173
1928
        case PLUGIN_VAR_SET:
2174
 
          src= &((thdvar_set_t*) plugin_var)->def_val;
 
1929
          src= &((sessionvar_set_t*) plugin_var)->def_val;
2175
1930
          break;
2176
1931
        case PLUGIN_VAR_BOOL:
2177
 
          src= &((thdvar_bool_t*) plugin_var)->def_val;
 
1932
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
2178
1933
          break;
2179
1934
        case PLUGIN_VAR_STR:
2180
 
          src= &((thdvar_str_t*) plugin_var)->def_val;
 
1935
          src= &((sessionvar_str_t*) plugin_var)->def_val;
2181
1936
          break;
2182
1937
        default:
2183
1938
          assert(0);
2184
1939
        }
2185
1940
  }
2186
1941
 
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);
 
1942
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1943
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1944
              session == current_session);
2190
1945
 
2191
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
 
1946
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2192
1947
  {
2193
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
1948
    plugin_var->update(session, plugin_var, tgt, src);
2194
1949
    pthread_mutex_unlock(&LOCK_global_system_variables);
2195
1950
  }
2196
1951
  else
2197
1952
  {
2198
1953
    pthread_mutex_unlock(&LOCK_global_system_variables);
2199
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
1954
    plugin_var->update(session, plugin_var, tgt, src);
2200
1955
  }
2201
1956
}
2202
1957
 
2203
1958
 
2204
 
bool sys_var_pluginvar::update(THD *thd, set_var *var)
 
1959
bool sys_var_pluginvar::update(Session *session, set_var *var)
2205
1960
{
2206
1961
  void *tgt;
2207
1962
 
2208
1963
  assert(is_readonly() || plugin_var->update);
2209
1964
 
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);
 
1965
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1966
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1967
              session == current_session);
2213
1968
 
2214
1969
  if (is_readonly())
2215
1970
    return 1;
2216
1971
 
2217
1972
  pthread_mutex_lock(&LOCK_global_system_variables);
2218
 
  tgt= real_value_ptr(thd, var->type);
 
1973
  tgt= real_value_ptr(session, var->type);
2219
1974
 
2220
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
 
1975
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2221
1976
  {
2222
1977
    /* variable we are updating has global scope, so we unlock after updating */
2223
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
1978
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2224
1979
    pthread_mutex_unlock(&LOCK_global_system_variables);
2225
1980
  }
2226
1981
  else
2227
1982
  {
2228
1983
    pthread_mutex_unlock(&LOCK_global_system_variables);
2229
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
1984
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2230
1985
  }
2231
1986
 return 0;
2232
1987
}
2246
2001
  options->sub_size= 0;
2247
2002
 
2248
2003
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2249
 
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
 
2004
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2250
2005
  /* global system variables */
2251
2006
  case PLUGIN_VAR_INT:
2252
2007
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2258
2013
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2259
2014
    break;
2260
2015
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2261
 
    OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
 
2016
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
2262
2017
    break;
2263
2018
  case PLUGIN_VAR_LONGLONG:
2264
2019
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
2290
2045
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2291
2046
    break;
2292
2047
  /* 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:
 
2048
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
 
2049
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
 
2050
    break;
 
2051
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2052
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
 
2053
    break;
 
2054
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
 
2055
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
 
2056
    break;
 
2057
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2058
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
 
2059
    break;
 
2060
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
 
2061
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
 
2062
    break;
 
2063
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2064
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
 
2065
    break;
 
2066
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2312
2067
    options->var_type= GET_ENUM;
2313
 
    options->typelib= ((thdvar_enum_t*) opt)->typelib;
2314
 
    options->def_value= ((thdvar_enum_t*) opt)->def_val;
 
2068
    options->typelib= ((sessionvar_enum_t*) opt)->typelib;
 
2069
    options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2315
2070
    options->min_value= options->block_size= 0;
2316
2071
    options->max_value= options->typelib->count - 1;
2317
2072
    break;
2318
 
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
 
2073
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2319
2074
    options->var_type= GET_SET;
2320
 
    options->typelib= ((thdvar_set_t*) opt)->typelib;
2321
 
    options->def_value= ((thdvar_set_t*) opt)->def_val;
 
2075
    options->typelib= ((sessionvar_set_t*) opt)->typelib;
 
2076
    options->def_value= ((sessionvar_set_t*) opt)->def_val;
2322
2077
    options->min_value= options->block_size= 0;
2323
2078
    options->max_value= (1UL << options->typelib->count) - 1;
2324
2079
    break;
2325
 
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
 
2080
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2326
2081
    options->var_type= GET_BOOL;
2327
 
    options->def_value= ((thdvar_bool_t*) opt)->def_val;
 
2082
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2328
2083
    break;
2329
 
  case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
 
2084
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2330
2085
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2331
2086
                        GET_STR_ALLOC : GET_STR);
2332
 
    options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
 
2087
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2333
2088
    break;
2334
2089
  default:
2335
2090
    assert(0);
2344
2099
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2345
2100
                                         char *);
2346
2101
 
2347
 
bool get_one_plugin_option(int optid __attribute__((unused)),
2348
 
                              const struct my_option *opt __attribute__((unused)),
2349
 
                              char *argument __attribute__((unused)))
 
2102
bool get_one_plugin_option(int, const struct my_option *, char *)
2350
2103
{
2351
2104
  return 0;
2352
2105
}
2367
2120
  /* support --skip-plugin-foo syntax */
2368
2121
  memcpy(name, plugin_name, namelen + 1);
2369
2122
  my_casedn_str(&my_charset_utf8_general_ci, name);
2370
 
  strxmov(name + namelen + 1, "plugin-", name, NULL);
 
2123
  sprintf(name+namelen+1, "plugin-%s", name);
2371
2124
  /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2372
2125
 
2373
2126
  for (p= name + namelen*2 + 8; p > name; p--)
2376
2129
 
2377
2130
  if (can_disable)
2378
2131
  {
2379
 
    strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2380
 
            "Disable with --skip-", name," (will save memory).", NULL);
 
2132
    sprintf(name+namelen*2+10,
 
2133
            "Enable %s plugin. Disable with --skip-%s (will save memory).",
 
2134
            plugin_name, name);
2381
2135
    /*
2382
2136
      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2383
2137
      20 + namelen + 20 + 1 == namelen * 4 + 67.
2404
2158
       plugin_option && *plugin_option; plugin_option++, index++)
2405
2159
  {
2406
2160
    opt= *plugin_option;
2407
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2161
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2408
2162
      continue;
2409
2163
    if (!(register_var(name, opt->name, opt->flags)))
2410
2164
      continue;
2411
2165
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2412
2166
    case PLUGIN_VAR_BOOL:
2413
 
      (((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
 
2167
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2414
2168
      break;
2415
2169
    case PLUGIN_VAR_INT:
2416
 
      (((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
 
2170
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2417
2171
      break;
2418
2172
    case PLUGIN_VAR_LONG:
2419
 
      (((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
 
2173
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2420
2174
      break;
2421
2175
    case PLUGIN_VAR_LONGLONG:
2422
 
      (((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
 
2176
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2423
2177
      break;
2424
2178
    case PLUGIN_VAR_STR:
2425
 
      (((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
 
2179
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2426
2180
      break;
2427
2181
    case PLUGIN_VAR_ENUM:
2428
 
      (((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
 
2182
      (((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2429
2183
      break;
2430
2184
    case PLUGIN_VAR_SET:
2431
 
      (((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
 
2185
      (((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2432
2186
      break;
2433
2187
    default:
2434
 
      sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
 
2188
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2435
2189
                      opt->flags, plugin_name);
2436
2190
      return(-1);
2437
2191
    };
2474
2228
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2475
2229
        {
2476
2230
          opt->flags|= PLUGIN_VAR_READONLY;
2477
 
          sql_print_warning(_("Server variable %s of plugin %s was forced "
 
2231
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2478
2232
                            "to be read-only: string variable without "
2479
2233
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
2480
2234
                            opt->name, plugin_name);
2494
2248
        opt->update= update_func_int64_t;
2495
2249
      break;
2496
2250
    default:
2497
 
      sql_print_error(_("Unknown variable type code 0x%x in plugin '%s'."),
 
2251
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2498
2252
                      opt->flags, plugin_name);
2499
2253
      return(-1);
2500
2254
    }
2501
2255
 
2502
 
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
 
2256
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2503
2257
                    == PLUGIN_VAR_NOCMDOPT)
2504
2258
      continue;
2505
2259
 
2506
2260
    if (!opt->name)
2507
2261
    {
2508
 
      sql_print_error(_("Missing variable name in plugin '%s'."),
 
2262
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2509
2263
                      plugin_name);
2510
2264
      return(-1);
2511
2265
    }
2512
2266
 
2513
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2267
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2514
2268
    {
2515
2269
      optnamelen= strlen(opt->name);
2516
2270
      optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2517
 
      strxmov(optname, name, "-", opt->name, NULL);
 
2271
      sprintf(optname, "%s-%s", name, opt->name);
2518
2272
      optnamelen= namelen + optnamelen + 1;
2519
2273
    }
2520
2274
    else
2522
2276
      /* this should not fail because register_var should create entry */
2523
2277
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
2524
2278
      {
2525
 
        sql_print_error(_("Thread local variable '%s' not allocated "
 
2279
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
2526
2280
                        "in plugin '%s'."), opt->name, plugin_name);
2527
2281
        return(-1);
2528
2282
      }
2532
2286
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2533
2287
        continue;
2534
2288
 
2535
 
      optname= (char*) memdup_root(mem_root, v->key + 1, 
 
2289
      optname= (char*) memdup_root(mem_root, v->key + 1,
2536
2290
                                   (optnamelen= v->name_len) + 1);
2537
2291
    }
2538
2292
 
2548
2302
 
2549
2303
    plugin_opt_set_limits(options, opt);
2550
2304
 
2551
 
    if (opt->flags & PLUGIN_VAR_THDLOCAL)
 
2305
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2552
2306
      options->value= options->u_max_value= (char**)
2553
2307
        (global_system_variables.dynamic_variables_ptr + offset);
2554
2308
    else
2557
2311
    options[1]= options[0];
2558
2312
    options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2559
2313
    options[1].comment= 0; // hidden
2560
 
    strxmov(p, "plugin-", optname, NULL);
 
2314
    sprintf(p,"plugin-%s",optname);
2561
2315
 
2562
2316
    options+= 2;
2563
2317
  }
2613
2367
                               int *argc, char **argv)
2614
2368
{
2615
2369
  struct sys_var_chain chain= { NULL, NULL };
2616
 
  bool enabled_saved= true;
2617
2370
  bool can_disable;
2618
2371
  MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
2619
2372
                      &tmp->mem_root : &plugin_mem_root;
2641
2394
  {
2642
2395
    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2643
2396
    {
2644
 
      sql_print_error(_("Out of memory for plugin '%s'."), tmp->name.str);
 
2397
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->name.str);
2645
2398
      return(-1);
2646
2399
    }
2647
2400
    memset(opts, 0, sizeof(my_option) * count);
2648
2401
 
2649
2402
    if (construct_options(tmp_root, tmp, opts, can_disable))
2650
2403
    {
2651
 
      sql_print_error(_("Bad options for plugin '%s'."), tmp->name.str);
 
2404
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->name.str);
2652
2405
      return(-1);
2653
2406
    }
2654
2407
 
2657
2410
 
2658
2411
    if (error)
2659
2412
    {
2660
 
       sql_print_error(_("Parsing options for plugin '%s' failed."),
 
2413
       errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2661
2414
                       tmp->name.str);
2662
2415
       goto err;
2663
2416
    }
2677
2430
      {
2678
2431
        len= tmp->name.length + strlen(o->name) + 2;
2679
2432
        varname= (char*) alloc_root(mem_root, len);
2680
 
        strxmov(varname, tmp->name.str, "-", o->name, NULL);
 
2433
        sprintf(varname,"%s-%s",tmp->name.str,o->name);
2681
2434
        my_casedn_str(&my_charset_utf8_general_ci, varname);
2682
2435
 
2683
2436
        for (p= varname; *p; p++)
2700
2453
      chain.last->next = NULL;
2701
2454
      if (mysql_add_sys_var_chain(chain.first, NULL))
2702
2455
      {
2703
 
        sql_print_error(_("Plugin '%s' has conflicting system variables"),
 
2456
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2704
2457
                        tmp->name.str);
2705
2458
        goto err;
2706
2459
      }
2709
2462
    return(0);
2710
2463
  }
2711
2464
 
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
2465
err:
2716
2466
  if (opts)
2717
2467
    my_cleanup_options(opts);