~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_plugin.cc

  • Committer: Monty Taylor
  • Date: 2009-02-05 21:07:57 UTC
  • mto: This revision was merged to the branch mainline in revision 840.
  • Revision ID: mordred@inaugust.com-20090205210757-6487lf69y3mndcds
Fixed warnings badness in csv_alter_table test.

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 <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
 
 
35
#include <string>
 
36
#include <vector>
 
37
 
 
38
#include <drizzled/error.h>
 
39
#include <drizzled/gettext.h>
 
40
 
20
41
#define REPORT_TO_LOG  1
21
42
#define REPORT_TO_USER 2
22
43
 
23
44
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
24
45
#define plugin_int_to_ref(A) &(A)
25
46
 
 
47
using namespace std;
 
48
 
26
49
extern struct st_mysql_plugin *mysqld_builtins[];
27
50
 
28
51
char *opt_plugin_load= NULL;
41
64
  { C_STRING_WITH_LEN("UDA") },
42
65
  { C_STRING_WITH_LEN("AUDIT") },
43
66
  { C_STRING_WITH_LEN("LOGGER") },
44
 
  { C_STRING_WITH_LEN("AUTH") }
 
67
  { C_STRING_WITH_LEN("ERRMSG") },
 
68
  { C_STRING_WITH_LEN("AUTH") },
 
69
  { C_STRING_WITH_LEN("CONFIGVAR") },
 
70
  { C_STRING_WITH_LEN("QCACHE") },
 
71
  { C_STRING_WITH_LEN("PARSER") },
 
72
  { C_STRING_WITH_LEN("SCHEDULING") },
 
73
  { C_STRING_WITH_LEN("REPLICATOR") }
45
74
};
46
75
 
47
76
extern int initialize_schema_table(st_plugin_int *plugin);
63
92
  initialize_udf,  /* UDF */
64
93
  0,  /* UDA */
65
94
  0,  /* Audit */
66
 
  0,  /* Logger */
67
 
  authentication_initializer  /* Auth */
 
95
  logging_initializer,  /* Logger */
 
96
  errmsg_initializer,  /* Error Messages */
 
97
  authentication_initializer,  /* Auth */
 
98
  configvar_initializer,
 
99
  qcache_initializer,
 
100
  parser_initializer,
 
101
  scheduling_initializer,
 
102
  replicator_initializer
68
103
};
69
104
 
70
105
plugin_type_init plugin_type_deinitialize[DRIZZLE_MAX_PLUGIN_TYPE_NUM]=
75
110
  finalize_udf,  /* UDF */
76
111
  0,  /* UDA */
77
112
  0,  /* Audit */
78
 
  0,  /* Logger */
79
 
  authentication_finalizer  /* Auth */
 
113
  logging_finalizer,  /* Logger */
 
114
  errmsg_finalizer,  /* Logger */
 
115
  authentication_finalizer,  /* Auth */
 
116
  configvar_finalizer,
 
117
  qcache_finalizer,
 
118
  parser_finalizer,
 
119
  scheduling_finalizer,
 
120
  replicator_finalizer
80
121
};
81
122
 
82
123
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
98
139
  the following variables/structures
99
140
*/
100
141
static MEM_ROOT plugin_mem_root;
101
 
static uint global_variables_dynamic_size= 0;
 
142
static uint32_t global_variables_dynamic_size= 0;
102
143
static HASH bookmark_hash;
103
144
 
104
145
 
114
155
 
115
156
/*
116
157
  stored in bookmark_hash, this structure is never removed from the
117
 
  hash and is used to mark a single offset for a thd local variable
 
158
  hash and is used to mark a single offset for a session local variable
118
159
  even if plugins have been uninstalled and reinstalled, repeatedly.
119
160
  This structure is allocated from plugin_mem_root.
120
161
 
125
166
*/
126
167
struct st_bookmark
127
168
{
128
 
  uint name_len;
 
169
  uint32_t name_len;
129
170
  int offset;
130
 
  uint version;
 
171
  uint32_t version;
131
172
  char key[1];
132
173
};
133
174
 
152
193
 
153
194
  static void *operator new(size_t size, MEM_ROOT *mem_root)
154
195
  { return (void*) alloc_root(mem_root, (uint) size); }
155
 
  static void operator delete(void *ptr_arg __attribute__((unused)),
156
 
                              size_t size __attribute__((unused)))
 
196
  static void operator delete(void *, size_t)
157
197
  { TRASH(ptr_arg, size); }
158
198
 
159
199
  sys_var_pluginvar(const char *name_arg,
162
202
  sys_var_pluginvar *cast_pluginvar() { return this; }
163
203
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
164
204
  bool check_type(enum_var_type type)
165
 
  { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
 
205
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
166
206
  bool check_update_type(Item_result type);
167
207
  SHOW_TYPE show_type();
168
 
  uchar* real_value_ptr(THD *thd, enum_var_type type);
 
208
  unsigned char* real_value_ptr(Session *session, enum_var_type type);
169
209
  TYPELIB* plugin_var_typelib(void);
170
 
  uchar* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
171
 
  bool check(THD *thd, set_var *var);
172
 
  bool check_default(enum_var_type type __attribute__((unused)))
 
210
  unsigned char* value_ptr(Session *session, enum_var_type type,
 
211
                           const LEX_STRING *base);
 
212
  bool check(Session *session, set_var *var);
 
213
  bool check_default(enum_var_type)
173
214
    { return is_readonly(); }
174
 
  void set_default(THD *thd,
175
 
                   enum_var_type type __attribute__((unused)));
176
 
  bool update(THD *thd, set_var *var);
 
215
  void set_default(Session *session, enum_var_type);
 
216
  bool update(Session *session, set_var *var);
177
217
};
178
218
 
179
219
 
184
224
                               int *, char **);
185
225
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
186
226
                             struct st_plugin_int **);
187
 
static void unlock_variables(THD *thd, struct system_variables *vars);
188
 
static void cleanup_variables(THD *thd, struct system_variables *vars);
 
227
static void unlock_variables(Session *session, struct system_variables *vars);
 
228
static void cleanup_variables(Session *session, struct system_variables *vars);
189
229
static void plugin_vars_free_values(sys_var *vars);
190
230
static void plugin_opt_set_limits(struct my_option *options,
191
231
                                  const struct st_mysql_sys_var *opt);
192
 
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
193
 
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
194
 
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
195
 
                                     CALLER_INFO_PROTO);
 
232
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
 
233
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
 
234
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
196
235
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
197
236
static void reap_plugins(void);
198
237
 
199
238
 
200
239
/* declared in set_var.cc */
201
 
extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
202
 
extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
 
240
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
 
241
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
203
242
                                 const char *name, int64_t val);
204
243
 
205
244
/****************************************************************************
232
271
    Lets be nice and create a temporary string since the
233
272
    buffer was too small
234
273
  */
235
 
  return current_thd->strmake(res->c_ptr_quick(), res->length());
 
274
  return current_session->strmake(res->c_ptr_quick(), res->length());
236
275
}
237
276
 
238
277
 
262
301
 
263
302
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
264
303
{
265
 
  uint i;
 
304
  uint32_t i;
266
305
  struct st_plugin_dl *tmp;
 
306
 
267
307
  for (i= 0; i < plugin_dl_array.elements; i++)
268
308
  {
269
309
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
270
310
    if (tmp->ref_count &&
271
311
        ! my_strnncoll(files_charset_info,
272
 
                       (const uchar *)dl->str, dl->length,
273
 
                       (const uchar *)tmp->dl.str, tmp->dl.length))
 
312
                       (const unsigned char *)dl->str, dl->length,
 
313
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
274
314
      return(tmp);
275
315
  }
276
316
  return(0);
278
318
 
279
319
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
280
320
{
281
 
  uint i;
 
321
  uint32_t i;
282
322
  struct st_plugin_dl *tmp;
 
323
 
283
324
  for (i= 0; i < plugin_dl_array.elements; i++)
284
325
  {
285
326
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
289
330
      return(tmp);
290
331
    }
291
332
  }
292
 
  if (insert_dynamic(&plugin_dl_array, (uchar*)&plugin_dl))
 
333
  if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
293
334
    return(0);
294
335
  tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
295
336
                        struct st_plugin_dl **)=
296
 
      (struct st_plugin_dl *) memdup_root(&plugin_mem_root, (uchar*)plugin_dl,
 
337
      (struct st_plugin_dl *) memdup_root(&plugin_mem_root, (unsigned char*)plugin_dl,
297
338
                                           sizeof(struct st_plugin_dl));
298
339
  return(tmp);
299
340
}
302
343
{
303
344
  if (p->handle)
304
345
    dlclose(p->handle);
305
 
  my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR));
 
346
  free(p->dl.str);
306
347
}
307
348
 
308
349
 
309
350
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
310
351
{
311
 
  char dlpath[FN_REFLEN];
312
 
  uint plugin_dir_len, dummy_errors, dlpathlen;
 
352
  string dlpath;
 
353
  uint32_t plugin_dir_len, dummy_errors;
313
354
  struct st_plugin_dl *tmp, plugin_dl;
314
355
  void *sym;
315
356
  plugin_dir_len= strlen(opt_plugin_dir);
 
357
  dlpath.reserve(FN_REFLEN);
316
358
  /*
317
359
    Ensure that the dll doesn't have a path.
318
360
    This is done to ensure that only approved libraries from the
326
368
    if (report & REPORT_TO_USER)
327
369
      my_error(ER_UDF_NO_PATHS, MYF(0));
328
370
    if (report & REPORT_TO_LOG)
329
 
      sql_print_error(ER(ER_UDF_NO_PATHS));
 
371
      errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
330
372
    return(0);
331
373
  }
332
374
  /* If this dll is already loaded just increase ref_count. */
337
379
  }
338
380
  memset(&plugin_dl, 0, sizeof(plugin_dl));
339
381
  /* Compile dll path */
340
 
  dlpathlen=
341
 
    strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS) -
342
 
    dlpath;
 
382
  dlpath.append(opt_plugin_dir);
 
383
  dlpath.append("/");
 
384
  dlpath.append(dl->str);
343
385
  plugin_dl.ref_count= 1;
344
386
  /* Open new dll handle */
345
 
  if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
 
387
  if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
346
388
  {
347
389
    const char *errmsg=dlerror();
348
 
    if (!strncmp(dlpath, errmsg, dlpathlen))
 
390
    uint32_t dlpathlen= dlpath.length();
 
391
    if (!dlpath.compare(0, dlpathlen, errmsg))
349
392
    { // if errmsg starts from dlpath, trim this prefix.
350
393
      errmsg+=dlpathlen;
351
394
      if (*errmsg == ':') errmsg++;
352
395
      if (*errmsg == ' ') errmsg++;
353
396
    }
354
397
    if (report & REPORT_TO_USER)
355
 
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
 
398
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
356
399
    if (report & REPORT_TO_LOG)
357
 
      sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
 
400
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
358
401
    return(0);
359
402
  }
360
403
 
365
408
    if (report & REPORT_TO_USER)
366
409
      my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
367
410
    if (report & REPORT_TO_LOG)
368
 
      sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
 
411
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
369
412
    return(0);
370
413
  }
371
414
 
373
416
 
374
417
  /* Duplicate and convert dll name */
375
418
  plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
376
 
  if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
 
419
  if (! (plugin_dl.dl.str= (char*) malloc(plugin_dl.dl.length)))
377
420
  {
378
421
    free_plugin_mem(&plugin_dl);
379
422
    if (report & REPORT_TO_USER)
380
423
      my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
381
424
    if (report & REPORT_TO_LOG)
382
 
      sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
 
425
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
383
426
    return(0);
384
427
  }
385
428
  plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
393
436
    if (report & REPORT_TO_USER)
394
437
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
395
438
    if (report & REPORT_TO_LOG)
396
 
      sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
 
439
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
397
440
    return(0);
398
441
  }
399
442
  return(tmp);
402
445
 
403
446
static void plugin_dl_del(const LEX_STRING *dl)
404
447
{
405
 
  uint i;
 
448
  uint32_t i;
406
449
 
407
450
  for (i= 0; i < plugin_dl_array.elements; i++)
408
451
  {
410
453
                                               struct st_plugin_dl **);
411
454
    if (tmp->ref_count &&
412
455
        ! my_strnncoll(files_charset_info,
413
 
                       (const uchar *)dl->str, dl->length,
414
 
                       (const uchar *)tmp->dl.str, tmp->dl.length))
 
456
                       (const unsigned char *)dl->str, dl->length,
 
457
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
415
458
    {
416
459
      /* Do not remove this element, unless no other plugin uses this dll. */
417
460
      if (! --tmp->ref_count)
428
471
 
429
472
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
430
473
{
431
 
  uint i;
 
474
  uint32_t i;
432
475
  if (! initialized)
433
476
    return(0);
434
477
 
437
480
    for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
438
481
    {
439
482
      struct st_plugin_int *plugin= (st_plugin_int *)
440
 
        hash_search(&plugin_hash[i], (const uchar *)name->str, name->length);
 
483
        hash_search(&plugin_hash[i], (const unsigned char *)name->str, name->length);
441
484
      if (plugin)
442
485
        return(plugin);
443
486
    }
444
487
  }
445
488
  else
446
489
    return((st_plugin_int *)
447
 
        hash_search(&plugin_hash[type], (const uchar *)name->str, name->length));
 
490
        hash_search(&plugin_hash[type], (const unsigned char *)name->str, name->length));
448
491
  return(0);
449
492
}
450
493
 
479
522
}
480
523
 
481
524
 
482
 
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
 
525
static plugin_ref intern_plugin_lock(LEX *, plugin_ref rc)
483
526
{
484
527
  st_plugin_int *pi= plugin_ref_to_int(rc);
485
528
 
491
534
      memory manager and/or valgrind to track locked references and
492
535
      double unlocks to aid resolving reference counting.problems.
493
536
    */
494
 
    if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
 
537
    if (!(plugin= (plugin_ref) malloc(sizeof(pi))))
495
538
      return(NULL);
496
539
 
497
540
    *plugin= pi;
498
541
    pi->ref_count++;
499
542
 
500
 
    if (lex)
501
 
      insert_dynamic(&lex->plugins, (uchar*)&plugin);
502
543
    return(plugin);
503
544
  }
504
545
  return(NULL);
505
546
}
506
547
 
507
548
 
508
 
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
 
549
plugin_ref plugin_lock(Session *session, plugin_ref *ptr)
509
550
{
510
 
  LEX *lex= thd ? thd->lex : 0;
 
551
  LEX *lex= session ? session->lex : 0;
511
552
  plugin_ref rc;
512
553
  rc= my_intern_plugin_lock_ci(lex, *ptr);
513
554
  return(rc);
514
555
}
515
556
 
516
557
 
517
 
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
518
 
                               CALLER_INFO_PROTO)
 
558
plugin_ref plugin_lock_by_name(Session *session, const LEX_STRING *name, int type)
519
559
{
520
 
  LEX *lex= thd ? thd->lex : 0;
 
560
  LEX *lex= session ? session->lex : 0;
521
561
  plugin_ref rc= NULL;
522
562
  st_plugin_int *plugin;
523
563
  if ((plugin= plugin_find_internal(name, type)))
528
568
 
529
569
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
530
570
{
531
 
  uint i;
 
571
  uint32_t i;
532
572
  struct st_plugin_int *tmp;
533
573
  for (i= 0; i < plugin_array.elements; i++)
534
574
  {
539
579
      return(tmp);
540
580
    }
541
581
  }
542
 
  if (insert_dynamic(&plugin_array, (uchar*)&plugin))
 
582
  if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
543
583
    return(0);
544
584
  tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
545
585
                        struct st_plugin_int **)=
546
 
       (struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)plugin,
 
586
       (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)plugin,
547
587
                                            sizeof(struct st_plugin_int));
548
588
  return(tmp);
549
589
}
564
604
    if (report & REPORT_TO_USER)
565
605
      my_error(ER_UDF_EXISTS, MYF(0), name->str);
566
606
    if (report & REPORT_TO_LOG)
567
 
      sql_print_error(ER(ER_UDF_EXISTS), name->str);
 
607
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
568
608
    return(true);
569
609
  }
570
610
  /* Clear the whole struct to catch future extensions. */
574
614
  /* Find plugin by name */
575
615
  for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
576
616
  {
577
 
    uint name_len= strlen(plugin->name);
578
 
    if (plugin->type >= 0 && plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
 
617
    uint32_t name_len= strlen(plugin->name);
 
618
    if (plugin->type < DRIZZLE_MAX_PLUGIN_TYPE_NUM &&
579
619
        ! my_strnncoll(system_charset_info,
580
 
                       (const uchar *)name->str, name->length,
581
 
                       (const uchar *)plugin->name,
 
620
                       (const unsigned char *)name->str, name->length,
 
621
                       (const unsigned char *)plugin->name,
582
622
                       name_len))
583
623
    {
584
624
      struct st_plugin_int *tmp_plugin_ptr;
593
633
        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
594
634
        {
595
635
          plugin_array_version++;
596
 
          if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
 
636
          if (!my_hash_insert(&plugin_hash[plugin->type], (unsigned char*)tmp_plugin_ptr))
597
637
          {
598
638
            init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
599
639
            return(false);
611
651
  if (report & REPORT_TO_USER)
612
652
    my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
613
653
  if (report & REPORT_TO_LOG)
614
 
    sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
 
654
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
615
655
err:
616
656
  plugin_dl_del(dl);
617
657
  return(true);
644
684
  {
645
685
    if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
646
686
    {
647
 
      sql_print_error("Plugin '%s' of type %s failed deinitialization",
 
687
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' of type %s failed deinitialization"),
648
688
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
649
689
    }
650
690
  }
654
694
  plugin->state= PLUGIN_IS_UNINITIALIZED;
655
695
 
656
696
  /*
657
 
    We do the check here because NDB has a worker THD which doesn't
 
697
    We do the check here because NDB has a worker Session which doesn't
658
698
    exit until NDB is shut down.
659
699
  */
660
700
  if (ref_check && plugin->ref_count)
661
 
    sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
 
701
    errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has ref_count=%d after deinitialization."),
662
702
                    plugin->name.str, plugin->ref_count);
663
703
}
664
704
 
667
707
{
668
708
  /* Free allocated strings before deleting the plugin. */
669
709
  plugin_vars_free_values(plugin->system_vars);
670
 
  hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
 
710
  hash_delete(&plugin_hash[plugin->plugin->type], (unsigned char*)plugin);
671
711
  if (plugin->plugin_dl)
672
712
    plugin_dl_del(&plugin->plugin_dl->dl);
673
713
  plugin->state= PLUGIN_IS_FREED;
674
714
  plugin_array_version++;
675
 
  rw_wrlock(&LOCK_system_variables_hash);
 
715
  pthread_rwlock_wrlock(&LOCK_system_variables_hash);
676
716
  mysql_del_sys_var_chain(plugin->system_vars);
677
 
  rw_unlock(&LOCK_system_variables_hash);
 
717
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
678
718
  free_root(&plugin->mem_root, MYF(0));
679
719
  return;
680
720
}
681
721
 
682
722
static void reap_plugins(void)
683
723
{
684
 
  uint count, idx;
685
 
  struct st_plugin_int *plugin, **reap, **list;
686
 
 
687
 
  if (!reap_needed)
688
 
    return;
 
724
  size_t count;
 
725
  uint32_t idx;
 
726
  struct st_plugin_int *plugin;
689
727
 
690
728
  reap_needed= false;
691
729
  count= plugin_array.elements;
692
 
  reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
693
 
  *(reap++)= NULL;
694
730
 
695
731
  for (idx= 0; idx < count; idx++)
696
732
  {
697
733
    plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
698
 
    if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
699
 
    {
700
 
      /* change the status flag to prevent reaping by another thread */
701
 
      plugin->state= PLUGIN_IS_DYING;
702
 
      *(reap++)= plugin;
703
 
    }
704
 
  }
705
 
 
706
 
  list= reap;
707
 
  while ((plugin= *(--list)))
 
734
    plugin->state= PLUGIN_IS_DYING;
708
735
    plugin_deinitialize(plugin, true);
709
 
 
710
 
  while ((plugin= *(--reap)))
711
736
    plugin_del(plugin);
712
 
 
713
 
  my_afree(reap);
 
737
  }
714
738
}
715
739
 
716
 
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
 
740
static void intern_plugin_unlock(LEX *, plugin_ref plugin)
717
741
{
718
 
  int i;
719
742
  st_plugin_int *pi;
720
743
 
721
744
  if (!plugin)
723
746
 
724
747
  pi= plugin_ref_to_int(plugin);
725
748
 
726
 
  my_free((uchar*) plugin, MYF(MY_WME));
727
 
 
728
 
  if (lex)
729
 
  {
730
 
    /*
731
 
      Remove one instance of this plugin from the use list.
732
 
      We are searching backwards so that plugins locked last
733
 
      could be unlocked faster - optimizing for LIFO semantics.
734
 
    */
735
 
    for (i= lex->plugins.elements - 1; i >= 0; i--)
736
 
      if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
737
 
      {
738
 
        delete_dynamic_element(&lex->plugins, i);
739
 
        break;
740
 
      }
741
 
    assert(i >= 0);
742
 
  }
743
 
 
744
 
  assert(pi->ref_count);
745
 
  pi->ref_count--;
 
749
  free((void *) plugin);
 
750
 
 
751
  //assert(pi->ref_count);
 
752
  if (pi->ref_count > 0)
 
753
    pi->ref_count--;
746
754
 
747
755
  if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
748
756
    reap_needed= true;
751
759
}
752
760
 
753
761
 
754
 
void plugin_unlock(THD *thd, plugin_ref plugin)
 
762
void plugin_unlock(Session *session, plugin_ref plugin)
755
763
{
756
 
  LEX *lex= thd ? thd->lex : 0;
 
764
  LEX *lex= session ? session->lex : 0;
757
765
  if (!plugin)
758
766
    return;
759
767
  intern_plugin_unlock(lex, plugin);
761
769
}
762
770
 
763
771
 
764
 
void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
 
772
void plugin_unlock_list(Session *session, plugin_ref *list, uint32_t count)
765
773
{
766
 
  LEX *lex= thd ? thd->lex : 0;
 
774
  LEX *lex= session ? session->lex : 0;
767
775
  assert(list);
768
776
  while (count--)
769
777
    intern_plugin_unlock(lex, *list++);
773
781
 
774
782
static int plugin_initialize(struct st_plugin_int *plugin)
775
783
{
 
784
  plugin->state= PLUGIN_IS_UNINITIALIZED;
776
785
 
777
786
  if (plugin_type_initialize[plugin->plugin->type])
778
787
  {
779
788
    if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
780
789
    {
781
 
      sql_print_error("Plugin '%s' registration as a %s failed.",
 
790
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' registration as a %s failed."),
782
791
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
783
792
      goto err;
784
793
    }
787
796
  {
788
797
    if (plugin->plugin->init(plugin))
789
798
    {
790
 
      sql_print_error("Plugin '%s' init function returned error.",
 
799
      errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' init function returned error."),
791
800
                      plugin->name.str);
792
801
      goto err;
793
802
    }
 
803
    plugin->state= PLUGIN_IS_READY;
794
804
  }
795
805
 
796
 
  plugin->state= PLUGIN_IS_READY;
797
 
 
798
806
  if (plugin->plugin->status_vars)
799
807
  {
800
808
#ifdef FIX_LATER
838
846
}
839
847
 
840
848
 
841
 
extern "C" uchar *get_plugin_hash_key(const uchar *, size_t *, bool);
842
 
extern "C" uchar *get_bookmark_hash_key(const uchar *, size_t *, bool);
843
 
 
844
 
 
845
 
uchar *get_plugin_hash_key(const uchar *buff, size_t *length,
846
 
                           bool not_used __attribute__((unused)))
 
849
extern "C" unsigned char *get_plugin_hash_key(const unsigned char *, size_t *, bool);
 
850
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
 
851
 
 
852
 
 
853
unsigned char *get_plugin_hash_key(const unsigned char *buff, size_t *length, bool)
847
854
{
848
855
  struct st_plugin_int *plugin= (st_plugin_int *)buff;
849
856
  *length= (uint)plugin->name.length;
850
 
  return((uchar *)plugin->name.str);
 
857
  return((unsigned char *)plugin->name.str);
851
858
}
852
859
 
853
860
 
854
 
uchar *get_bookmark_hash_key(const uchar *buff, size_t *length,
855
 
                             bool not_used __attribute__((unused)))
 
861
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
856
862
{
857
863
  struct st_bookmark *var= (st_bookmark *)buff;
858
864
  *length= var->name_len + 1;
859
 
  return (uchar*) var->key;
 
865
  return (unsigned char*) var->key;
860
866
}
861
867
 
862
868
 
869
875
*/
870
876
int plugin_init(int *argc, char **argv, int flags)
871
877
{
872
 
  uint i;
 
878
  uint32_t idx;
873
879
  struct st_mysql_plugin **builtins;
874
880
  struct st_mysql_plugin *plugin;
875
 
  struct st_plugin_int tmp, *plugin_ptr, **reap;
 
881
  struct st_plugin_int tmp, *plugin_ptr;
876
882
  MEM_ROOT tmp_root;
877
883
 
878
884
  if (initialized)
892
898
                            sizeof(struct st_plugin_int *),16,16))
893
899
    goto err;
894
900
 
895
 
  for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
 
901
  for (idx= 0; idx < DRIZZLE_MAX_PLUGIN_TYPE_NUM; idx++)
896
902
  {
897
 
    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
 
903
    if (hash_init(&plugin_hash[idx], system_charset_info, 16, 0, 0,
898
904
                  get_plugin_hash_key, NULL, HASH_UNIQUE))
899
905
      goto err;
900
906
  }
927
933
        initialize the global default storage engine so that it may
928
934
        not be null in any child thread.
929
935
      */
930
 
      if (my_strcasecmp(&my_charset_latin1, plugin->name, "MyISAM") == 0)
 
936
      if (my_strcasecmp(&my_charset_utf8_general_ci, plugin->name, "MyISAM") == 0)
931
937
      {
932
938
        assert(!global_system_variables.table_plugin);
933
939
        global_system_variables.table_plugin=
953
959
  /*
954
960
    Now we initialize all remaining plugins
955
961
  */
956
 
 
957
 
  reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
958
 
  *(reap++)= NULL;
959
 
 
960
 
  for (i= 0; i < plugin_array.elements; i++)
 
962
  for (idx= 0; idx < plugin_array.elements; idx++)
961
963
  {
962
 
    plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
 
964
    plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
963
965
    if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
964
966
    {
965
967
      if (plugin_initialize(plugin_ptr))
966
968
      {
967
969
        plugin_ptr->state= PLUGIN_IS_DYING;
968
 
        *(reap++)= plugin_ptr;
 
970
        plugin_deinitialize(plugin_ptr, true);
 
971
        plugin_del(plugin_ptr);
969
972
      }
970
973
    }
971
974
  }
972
975
 
973
 
  /*
974
 
    Check if any plugins have to be reaped
975
 
  */
976
 
  while ((plugin_ptr= *(--reap)))
977
 
  {
978
 
    plugin_deinitialize(plugin_ptr, true);
979
 
    plugin_del(plugin_ptr);
980
 
  }
981
 
 
982
 
  my_afree(reap);
983
976
 
984
977
end:
985
978
  free_root(&tmp_root, MYF(0));
1002
995
  tmp->ref_count= 0;
1003
996
  tmp->plugin_dl= 0;
1004
997
 
1005
 
  if (insert_dynamic(&plugin_array, (uchar*)&tmp))
 
998
  if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
1006
999
    return(1);
1007
1000
 
1008
1001
  *ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1009
1002
                         struct st_plugin_int **)=
1010
 
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)tmp,
 
1003
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
1011
1004
                                             sizeof(struct st_plugin_int));
1012
1005
 
1013
 
  if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr))
 
1006
  if (my_hash_insert(&plugin_hash[plugin->type],(unsigned char*) *ptr))
1014
1007
    return(1);
1015
1008
 
1016
1009
  return(0);
1032
1025
  {
1033
1026
    if (p == buffer + sizeof(buffer) - 1)
1034
1027
    {
1035
 
      sql_print_error("plugin-load parameter too long");
 
1028
      errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
1036
1029
      return(true);
1037
1030
    }
1038
1031
 
1092
1085
  }
1093
1086
  return(false);
1094
1087
error:
1095
 
  sql_print_error("Couldn't load plugin named '%s' with soname '%s'.",
 
1088
  errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
1096
1089
                  name.str, dl.str);
1097
1090
  return(true);
1098
1091
}
1100
1093
 
1101
1094
void plugin_shutdown(void)
1102
1095
{
1103
 
  uint i, count= plugin_array.elements, free_slots= 0;
1104
 
  struct st_plugin_int **plugins, *plugin;
1105
 
  struct st_plugin_dl **dl;
 
1096
  uint32_t idx, free_slots= 0;
 
1097
  size_t count= plugin_array.elements;
 
1098
  struct st_plugin_int *plugin;
 
1099
  vector<st_plugin_int *> plugins;
 
1100
  vector<st_plugin_dl *> dl;
1106
1101
 
1107
1102
  if (initialized)
1108
1103
  {
1118
1113
    while (reap_needed && (count= plugin_array.elements))
1119
1114
    {
1120
1115
      reap_plugins();
1121
 
      for (i= free_slots= 0; i < count; i++)
 
1116
      for (idx= free_slots= 0; idx < count; idx++)
1122
1117
      {
1123
 
        plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
 
1118
        plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1124
1119
        switch (plugin->state) {
1125
1120
        case PLUGIN_IS_READY:
1126
1121
          plugin->state= PLUGIN_IS_DELETED;
1143
1138
    }
1144
1139
 
1145
1140
    if (count > free_slots)
1146
 
      sql_print_warning("Forcing shutdown of %d plugins", count - free_slots);
 
1141
      errmsg_printf(ERRMSG_LVL_WARN, _("Forcing shutdown of %"PRIu64" plugins"),
 
1142
                        (uint64_t)count - free_slots);
1147
1143
 
1148
 
    plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
 
1144
    plugins.reserve(count);
1149
1145
 
1150
1146
    /*
1151
1147
      If we have any plugins which did not die cleanly, we force shutdown
1152
1148
    */
1153
 
    for (i= 0; i < count; i++)
 
1149
    for (idx= 0; idx < count; idx++)
1154
1150
    {
1155
 
      plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
 
1151
      plugins.push_back(*dynamic_element(&plugin_array, idx,
 
1152
                                         struct st_plugin_int **));
1156
1153
      /* change the state to ensure no reaping races */
1157
 
      if (plugins[i]->state == PLUGIN_IS_DELETED)
1158
 
        plugins[i]->state= PLUGIN_IS_DYING;
 
1154
      if (plugins[idx]->state == PLUGIN_IS_DELETED)
 
1155
        plugins[idx]->state= PLUGIN_IS_DYING;
1159
1156
    }
1160
1157
 
1161
1158
    /*
1162
1159
      We loop through all plugins and call deinit() if they have one.
1163
1160
    */
1164
 
    for (i= 0; i < count; i++)
1165
 
      if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
 
1161
    for (idx= 0; idx < count; idx++)
 
1162
      if (!(plugins[idx]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1166
1163
      {
1167
 
        sql_print_information("Plugin '%s' will be forced to shutdown",
1168
 
                              plugins[i]->name.str);
 
1164
        errmsg_printf(ERRMSG_LVL_INFO, _("Plugin '%s' will be forced to shutdown"),
 
1165
                              plugins[idx]->name.str);
1169
1166
        /*
1170
1167
          We are forcing deinit on plugins so we don't want to do a ref_count
1171
1168
          check until we have processed all the plugins.
1172
1169
        */
1173
 
        plugin_deinitialize(plugins[i], false);
 
1170
        plugin_deinitialize(plugins[idx], false);
1174
1171
      }
1175
1172
 
1176
1173
    /*
1177
1174
      We defer checking ref_counts until after all plugins are deinitialized
1178
1175
      as some may have worker threads holding on to plugin references.
1179
1176
    */
1180
 
    for (i= 0; i < count; i++)
 
1177
    for (idx= 0; idx < count; idx++)
1181
1178
    {
1182
 
      if (plugins[i]->ref_count)
1183
 
        sql_print_error("Plugin '%s' has ref_count=%d after shutdown.",
1184
 
                        plugins[i]->name.str, plugins[i]->ref_count);
1185
 
      if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1186
 
        plugin_del(plugins[i]);
 
1179
      if (plugins[idx]->ref_count)
 
1180
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has ref_count=%d after shutdown."),
 
1181
                        plugins[idx]->name.str, plugins[idx]->ref_count);
 
1182
      if (plugins[idx]->state & PLUGIN_IS_UNINITIALIZED)
 
1183
        plugin_del(plugins[idx]);
1187
1184
    }
1188
1185
 
1189
1186
    /*
1195
1192
 
1196
1193
    initialized= 0;
1197
1194
 
1198
 
    my_afree(plugins);
1199
1195
  }
1200
1196
 
1201
1197
  /* Dispose of the memory */
1202
1198
 
1203
 
  for (i= 0; i < DRIZZLE_MAX_PLUGIN_TYPE_NUM; i++)
1204
 
    hash_free(&plugin_hash[i]);
 
1199
  for (idx= 0; idx < DRIZZLE_MAX_PLUGIN_TYPE_NUM; idx++)
 
1200
    hash_free(&plugin_hash[idx]);
1205
1201
  delete_dynamic(&plugin_array);
1206
1202
 
1207
1203
  count= plugin_dl_array.elements;
1208
 
  dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1209
 
  for (i= 0; i < count; i++)
1210
 
    dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1211
 
  for (i= 0; i < plugin_dl_array.elements; i++)
1212
 
    free_plugin_mem(dl[i]);
1213
 
  my_afree(dl);
 
1204
  dl.reserve(count);
 
1205
  for (idx= 0; idx < count; idx++)
 
1206
    dl.push_back(*dynamic_element(&plugin_dl_array, idx,
 
1207
                 struct st_plugin_dl **));
 
1208
  for (idx= 0; idx < count; idx++)
 
1209
    free_plugin_mem(dl[idx]);
1214
1210
  delete_dynamic(&plugin_dl_array);
1215
1211
 
1216
1212
  hash_free(&bookmark_hash);
1222
1218
}
1223
1219
 
1224
1220
 
1225
 
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1226
 
                       int type, uint state_mask, void *arg)
 
1221
bool plugin_foreach_with_mask(Session *session, plugin_foreach_func *func,
 
1222
                       int type, uint32_t state_mask, void *arg)
1227
1223
{
1228
 
  uint idx, total;
1229
 
  struct st_plugin_int *plugin, **plugins;
 
1224
  uint32_t idx;
 
1225
  size_t total;
 
1226
  struct st_plugin_int *plugin;
 
1227
  vector<st_plugin_int *> plugins;
1230
1228
  int version=plugin_array_version;
1231
1229
 
1232
1230
  if (!initialized)
1236
1234
 
1237
1235
  total= type == DRIZZLE_ANY_PLUGIN ? plugin_array.elements
1238
1236
                                  : plugin_hash[type].records;
1239
 
  /*
1240
 
    Do the alloca out here in case we do have a working alloca:
1241
 
        leaving the nested stack frame invalidates alloca allocation.
1242
 
  */
1243
 
  plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
 
1237
  plugins.reserve(total);
 
1238
 
1244
1239
  if (type == DRIZZLE_ANY_PLUGIN)
1245
1240
  {
1246
1241
    for (idx= 0; idx < total; idx++)
1247
1242
    {
1248
1243
      plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1249
 
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
 
1244
      plugins.push_back(!(plugin->state & state_mask) ? plugin : NULL);
1250
1245
    }
1251
1246
  }
1252
1247
  else
1255
1250
    for (idx= 0; idx < total; idx++)
1256
1251
    {
1257
1252
      plugin= (struct st_plugin_int *) hash_element(hash, idx);
1258
 
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
 
1253
      plugins.push_back(!(plugin->state & state_mask) ? plugin : NULL);
1259
1254
    }
1260
1255
  }
1261
1256
  for (idx= 0; idx < total; idx++)
1262
1257
  {
1263
1258
    if (unlikely(version != plugin_array_version))
1264
1259
    {
1265
 
      for (uint i=idx; i < total; i++)
 
1260
      for (uint32_t i=idx; i < total; i++)
1266
1261
        if (plugins[i] && plugins[i]->state & state_mask)
1267
1262
          plugins[i]=0;
1268
1263
    }
1269
1264
    plugin= plugins[idx];
1270
1265
    /* It will stop iterating on first engine error when "func" returns true */
1271
 
    if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
 
1266
    if (plugin && func(session, plugin_int_to_ref(plugin), arg))
1272
1267
        goto err;
1273
1268
  }
1274
1269
 
1275
 
  my_afree(plugins);
1276
 
  return(false);
 
1270
  return false;
1277
1271
err:
1278
 
  my_afree(plugins);
1279
 
  return(true);
 
1272
  return true;
1280
1273
}
1281
1274
 
1282
1275
 
1291
1284
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1292
1285
 
1293
1286
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
1294
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_bool_t, bool);
 
1287
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
1295
1288
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
1296
 
typedef DECLARE_DRIZZLE_THDVAR_BASIC(thdvar_str_t, char *);
 
1289
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
1297
1290
 
1298
1291
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1299
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
 
1292
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
1300
1293
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1301
 
typedef DECLARE_DRIZZLE_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
 
1294
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
1302
1295
 
1303
1296
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
1304
1297
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
1307
1300
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
1308
1301
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1309
1302
 
1310
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int_t, int);
1311
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_long_t, long);
1312
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_int64_t_t, int64_t);
1313
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint_t, uint);
1314
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
1315
 
typedef DECLARE_DRIZZLE_THDVAR_SIMPLE(thdvar_uint64_t_t, uint64_t);
 
1303
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
 
1304
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
 
1305
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
 
1306
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
 
1307
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
 
1308
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
1316
1309
 
1317
 
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
 
1310
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
1318
1311
 
1319
1312
 
1320
1313
/****************************************************************************
1321
1314
  default variable data check and update functions
1322
1315
****************************************************************************/
1323
1316
 
1324
 
static int check_func_bool(THD *thd __attribute__((unused)),
1325
 
                           struct st_mysql_sys_var *var,
 
1317
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
1326
1318
                           void *save, st_mysql_value *value)
1327
1319
{
1328
1320
  char buff[STRING_BUFFER_USUAL_SIZE];
1361
1353
}
1362
1354
 
1363
1355
 
1364
 
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
 
1356
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
1365
1357
                          void *save, st_mysql_value *value)
1366
1358
{
1367
1359
  bool fixed;
1371
1363
  plugin_opt_set_limits(&options, var);
1372
1364
 
1373
1365
  if (var->flags & PLUGIN_VAR_UNSIGNED)
1374
 
    *(uint *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
 
1366
    *(uint32_t *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
1375
1367
                                                   &fixed);
1376
1368
  else
1377
1369
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1378
1370
 
1379
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1371
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1380
1372
                              var->name, (int64_t) tmp);
1381
1373
}
1382
1374
 
1383
1375
 
1384
 
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
 
1376
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
1385
1377
                          void *save, st_mysql_value *value)
1386
1378
{
1387
1379
  bool fixed;
1396
1388
  else
1397
1389
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1398
1390
 
1399
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1391
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1400
1392
                              var->name, (int64_t) tmp);
1401
1393
}
1402
1394
 
1403
1395
 
1404
 
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
 
1396
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
1405
1397
                               void *save, st_mysql_value *value)
1406
1398
{
1407
1399
  bool fixed;
1416
1408
  else
1417
1409
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1418
1410
 
1419
 
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
1411
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
1420
1412
                              var->name, (int64_t) tmp);
1421
1413
}
1422
1414
 
1423
 
static int check_func_str(THD *thd,
1424
 
                          struct st_mysql_sys_var *var __attribute__((unused)),
 
1415
static int check_func_str(Session *session, struct st_mysql_sys_var *,
1425
1416
                          void *save, st_mysql_value *value)
1426
1417
{
1427
1418
  char buff[STRING_BUFFER_USUAL_SIZE];
1430
1421
 
1431
1422
  length= sizeof(buff);
1432
1423
  if ((str= value->val_str(value, buff, &length)))
1433
 
    str= thd->strmake(str, length);
 
1424
    str= session->strmake(str, length);
1434
1425
  *(const char**)save= str;
1435
1426
  return 0;
1436
1427
}
1437
1428
 
1438
1429
 
1439
 
static int check_func_enum(THD *thd __attribute__((unused)),
1440
 
                           struct st_mysql_sys_var *var,
 
1430
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
1441
1431
                           void *save, st_mysql_value *value)
1442
1432
{
1443
1433
  char buff[STRING_BUFFER_USUAL_SIZE];
1447
1437
  long result;
1448
1438
  int length;
1449
1439
 
1450
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1451
 
    typelib= ((thdvar_enum_t*) var)->typelib;
 
1440
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1441
    typelib= ((sessionvar_enum_t*) var)->typelib;
1452
1442
  else
1453
1443
    typelib= ((sysvar_enum_t*) var)->typelib;
1454
1444
 
1483
1473
}
1484
1474
 
1485
1475
 
1486
 
static int check_func_set(THD *thd __attribute__((unused)),
1487
 
                          struct st_mysql_sys_var *var,
 
1476
static int check_func_set(Session *, struct st_mysql_sys_var *var,
1488
1477
                          void *save, st_mysql_value *value)
1489
1478
{
1490
1479
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1491
1480
  const char *strvalue= "NULL", *str;
1492
1481
  TYPELIB *typelib;
1493
1482
  uint64_t result;
1494
 
  uint error_len;
 
1483
  uint32_t error_len;
1495
1484
  bool not_used;
1496
1485
  int length;
1497
1486
 
1498
 
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1499
 
    typelib= ((thdvar_set_t*) var)->typelib;
 
1487
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1488
    typelib= ((sessionvar_set_t*) var)->typelib;
1500
1489
  else
1501
1490
    typelib= ((sysvar_set_t*)var)->typelib;
1502
1491
 
1509
1498
                     &error, &error_len, &not_used);
1510
1499
    if (error_len)
1511
1500
    {
1512
 
      strmake(buff, error, min(sizeof(buff), (unsigned long)error_len));
 
1501
      length= cmin(sizeof(buff), (unsigned long)error_len);
 
1502
      strncpy(buff, error, length);
 
1503
      buff[length]= '\0';
1513
1504
      strvalue= buff;
1514
1505
      goto err;
1515
1506
    }
1518
1509
  {
1519
1510
    if (value->val_int(value, (int64_t *)&result))
1520
1511
      goto err;
1521
 
    if (unlikely((result >= (1ULL << typelib->count)) &&
 
1512
    if (unlikely((result >= (1UL << typelib->count)) &&
1522
1513
                 (typelib->count < sizeof(long)*8)))
1523
1514
    {
1524
1515
      llstr(result, buff);
1534
1525
}
1535
1526
 
1536
1527
 
1537
 
static void update_func_bool(THD *thd __attribute__((unused)),
1538
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1528
static void update_func_bool(Session *, struct st_mysql_sys_var *,
1539
1529
                             void *tgt, const void *save)
1540
1530
{
1541
1531
  *(bool *) tgt= *(int *) save ? 1 : 0;
1542
1532
}
1543
1533
 
1544
1534
 
1545
 
static void update_func_int(THD *thd __attribute__((unused)),
1546
 
                            struct st_mysql_sys_var *var __attribute__((unused)),
 
1535
static void update_func_int(Session *, struct st_mysql_sys_var *,
1547
1536
                             void *tgt, const void *save)
1548
1537
{
1549
1538
  *(int *)tgt= *(int *) save;
1550
1539
}
1551
1540
 
1552
1541
 
1553
 
static void update_func_long(THD *thd __attribute__((unused)),
1554
 
                             struct st_mysql_sys_var *var __attribute__((unused)),
 
1542
static void update_func_long(Session *, struct st_mysql_sys_var *,
1555
1543
                             void *tgt, const void *save)
1556
1544
{
1557
1545
  *(long *)tgt= *(long *) save;
1558
1546
}
1559
1547
 
1560
1548
 
1561
 
static void update_func_int64_t(THD *thd __attribute__((unused)),
1562
 
                                 struct st_mysql_sys_var *var __attribute__((unused)),
 
1549
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
1563
1550
                                 void *tgt, const void *save)
1564
1551
{
1565
1552
  *(int64_t *)tgt= *(uint64_t *) save;
1566
1553
}
1567
1554
 
1568
1555
 
1569
 
static void update_func_str(THD *thd __attribute__((unused)), struct st_mysql_sys_var *var,
 
1556
static void update_func_str(Session *, struct st_mysql_sys_var *var,
1570
1557
                             void *tgt, const void *save)
1571
1558
{
1572
1559
  char *old= *(char **) tgt;
1573
1560
  *(char **)tgt= *(char **) save;
1574
1561
  if (var->flags & PLUGIN_VAR_MEMALLOC)
1575
1562
  {
1576
 
    *(char **)tgt= my_strdup(*(char **) save, MYF(0));
1577
 
    my_free(old, MYF(0));
 
1563
    *(char **)tgt= strdup(*(char **) save);
 
1564
    free(old);
 
1565
    /*
 
1566
     * There isn't a _really_ good thing to do here until this whole set_var
 
1567
     * mess gets redesigned
 
1568
     */
 
1569
    if (tgt == NULL)
 
1570
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
 
1571
 
1578
1572
  }
1579
1573
}
1580
1574
 
1584
1578
****************************************************************************/
1585
1579
 
1586
1580
 
1587
 
sys_var *find_sys_var(THD *thd, const char *str, uint length)
 
1581
sys_var *find_sys_var(Session *session, const char *str, uint32_t length)
1588
1582
{
1589
1583
  sys_var *var;
1590
1584
  sys_var_pluginvar *pi= NULL;
1591
1585
  plugin_ref plugin;
1592
1586
 
1593
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1587
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1594
1588
  if ((var= intern_find_sys_var(str, length, false)) &&
1595
1589
      (pi= var->cast_pluginvar()))
1596
1590
  {
1597
 
    rw_unlock(&LOCK_system_variables_hash);
1598
 
    LEX *lex= thd ? thd->lex : 0;
 
1591
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
1592
    LEX *lex= session ? session->lex : 0;
1599
1593
    if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1600
1594
      var= NULL; /* failed to lock it, it must be uninstalling */
1601
1595
    else
1607
1601
    }
1608
1602
  }
1609
1603
  else
1610
 
    rw_unlock(&LOCK_system_variables_hash);
 
1604
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1611
1605
 
1612
1606
  /*
1613
1607
    If the variable exists but the plugin it is associated with is not ready
1627
1621
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1628
1622
{
1629
1623
  st_bookmark *result= NULL;
1630
 
  uint namelen, length, pluginlen= 0;
 
1624
  uint32_t namelen, length, pluginlen= 0;
1631
1625
  char *varname, *p;
1632
1626
 
1633
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1627
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1634
1628
    return NULL;
1635
1629
 
1636
1630
  namelen= strlen(name);
1637
1631
  if (plugin)
1638
1632
    pluginlen= strlen(plugin) + 1;
1639
1633
  length= namelen + pluginlen + 2;
1640
 
  varname= (char*) my_alloca(length);
 
1634
  varname= (char*) malloc(length);
1641
1635
 
1642
1636
  if (plugin)
1643
1637
  {
1644
 
    strxmov(varname + 1, plugin, "_", name, NullS);
 
1638
    sprintf(varname+1,"%s_%s",plugin,name);
1645
1639
    for (p= varname + 1; *p; p++)
1646
1640
      if (*p == '-')
1647
1641
        *p= '_';
1652
1646
  varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1653
1647
 
1654
1648
  result= (st_bookmark*) hash_search(&bookmark_hash,
1655
 
                                     (const uchar*) varname, length - 1);
 
1649
                                     (const unsigned char*) varname, length - 1);
1656
1650
 
1657
 
  my_afree(varname);
 
1651
  free(varname);
1658
1652
  return result;
1659
1653
}
1660
1654
 
1661
1655
 
1662
1656
/*
1663
 
  returns a bookmark for thd-local variables, creating if neccessary.
1664
 
  returns null for non thd-local variables.
 
1657
  returns a bookmark for session-local variables, creating if neccessary.
 
1658
  returns null for non session-local variables.
1665
1659
  Requires that a write lock is obtained on LOCK_system_variables_hash
1666
1660
*/
1667
1661
static st_bookmark *register_var(const char *plugin, const char *name,
1668
1662
                                 int flags)
1669
1663
{
1670
 
  uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
 
1664
  uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1671
1665
  st_bookmark *result;
1672
1666
  char *varname, *p;
1673
1667
 
1674
 
  if (!(flags & PLUGIN_VAR_THDLOCAL))
 
1668
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
1675
1669
    return NULL;
1676
1670
 
1677
1671
  switch (flags & PLUGIN_VAR_TYPEMASK) {
1697
1691
    return NULL;
1698
1692
  };
1699
1693
 
1700
 
  varname= ((char*) my_alloca(length));
1701
 
  strxmov(varname + 1, plugin, "_", name, NullS);
 
1694
  varname= ((char*) malloc(length));
 
1695
  sprintf(varname+1, "%s_%s", plugin, name);
1702
1696
  for (p= varname + 1; *p; p++)
1703
1697
    if (*p == '-')
1704
1698
      *p= '_';
1722
1716
 
1723
1717
    if (new_size > global_variables_dynamic_size)
1724
1718
    {
1725
 
      global_system_variables.dynamic_variables_ptr= (char*)
1726
 
        my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1727
 
                   MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1728
 
      max_system_variables.dynamic_variables_ptr= (char*)
1729
 
        my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1730
 
                   MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
 
1719
      char* tmpptr= NULL;
 
1720
      if (!(tmpptr=
 
1721
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
 
1722
                              new_size)))
 
1723
        return NULL;
 
1724
      global_system_variables.dynamic_variables_ptr= tmpptr;
 
1725
      tmpptr= NULL;
 
1726
      if (!(tmpptr=
 
1727
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
 
1728
                              new_size)))
 
1729
        return NULL;
 
1730
      max_system_variables.dynamic_variables_ptr= tmpptr;
 
1731
           
1731
1732
      /*
1732
1733
        Clear the new variable value space. This is required for string
1733
1734
        variables. If their value is non-NULL, it must point to a valid
1737
1738
             global_variables_dynamic_size, 0,
1738
1739
             new_size - global_variables_dynamic_size);
1739
1740
      memset(max_system_variables.dynamic_variables_ptr +
1740
 
             global_variables_dynamic_size, 0, 
 
1741
             global_variables_dynamic_size, 0,
1741
1742
             new_size - global_variables_dynamic_size);
1742
1743
      global_variables_dynamic_size= new_size;
1743
1744
    }
1752
1753
    result->version= global_system_variables.dynamic_variables_version;
1753
1754
 
1754
1755
    /* this should succeed because we have already checked if a dup exists */
1755
 
    if (my_hash_insert(&bookmark_hash, (uchar*) result))
 
1756
    if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
1756
1757
    {
1757
1758
      fprintf(stderr, "failed to add placeholder to hash");
1758
1759
      assert(0);
1759
1760
    }
1760
1761
  }
1761
 
  my_afree(varname);
 
1762
  free(varname);
1762
1763
  return result;
1763
1764
}
1764
1765
 
1765
1766
 
1766
1767
/*
1767
 
  returns a pointer to the memory which holds the thd-local variable or
1768
 
  a pointer to the global variable if thd==null.
 
1768
  returns a pointer to the memory which holds the session-local variable or
 
1769
  a pointer to the global variable if session==null.
1769
1770
  If required, will sync with global variables if the requested variable
1770
1771
  has not yet been allocated in the current thread.
1771
1772
*/
1772
 
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
 
1773
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
1773
1774
{
1774
1775
  assert(offset >= 0);
1775
1776
  assert((uint)offset <= global_system_variables.dynamic_variables_head);
1776
1777
 
1777
 
  if (!thd)
1778
 
    return (uchar*) global_system_variables.dynamic_variables_ptr + offset;
 
1778
  if (!session)
 
1779
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
1779
1780
 
1780
1781
  /*
1781
1782
    dynamic_variables_head points to the largest valid offset
1782
1783
  */
1783
 
  if (!thd->variables.dynamic_variables_ptr ||
1784
 
      (uint)offset > thd->variables.dynamic_variables_head)
 
1784
  if (!session->variables.dynamic_variables_ptr ||
 
1785
      (uint)offset > session->variables.dynamic_variables_head)
1785
1786
  {
1786
 
    uint idx;
1787
 
 
1788
 
    rw_rdlock(&LOCK_system_variables_hash);
1789
 
 
1790
 
    thd->variables.dynamic_variables_ptr= (char*)
1791
 
      my_realloc(thd->variables.dynamic_variables_ptr,
1792
 
                 global_variables_dynamic_size,
1793
 
                 MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
 
1787
    uint32_t idx;
 
1788
 
 
1789
    pthread_rwlock_rdlock(&LOCK_system_variables_hash);
 
1790
 
 
1791
    char *tmpptr= NULL;
 
1792
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
 
1793
                                  global_variables_dynamic_size)))
 
1794
      return NULL;
 
1795
    session->variables.dynamic_variables_ptr= tmpptr;
1794
1796
 
1795
1797
    if (global_lock)
1796
1798
      pthread_mutex_lock(&LOCK_global_system_variables);
1797
1799
 
1798
1800
    safe_mutex_assert_owner(&LOCK_global_system_variables);
1799
1801
 
1800
 
    memcpy(thd->variables.dynamic_variables_ptr +
1801
 
             thd->variables.dynamic_variables_size,
 
1802
    memcpy(session->variables.dynamic_variables_ptr +
 
1803
             session->variables.dynamic_variables_size,
1802
1804
           global_system_variables.dynamic_variables_ptr +
1803
 
             thd->variables.dynamic_variables_size,
 
1805
             session->variables.dynamic_variables_size,
1804
1806
           global_system_variables.dynamic_variables_size -
1805
 
             thd->variables.dynamic_variables_size);
 
1807
             session->variables.dynamic_variables_size);
1806
1808
 
1807
1809
    /*
1808
1810
      now we need to iterate through any newly copied 'defaults'
1814
1816
      sys_var *var;
1815
1817
      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1816
1818
 
1817
 
      if (v->version <= thd->variables.dynamic_variables_version ||
 
1819
      if (v->version <= session->variables.dynamic_variables_version ||
1818
1820
          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1819
1821
          !(pi= var->cast_pluginvar()) ||
1820
1822
          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1825
1827
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1826
1828
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1827
1829
      {
1828
 
         char **pp= (char**) (thd->variables.dynamic_variables_ptr +
 
1830
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
1829
1831
                             *(int*)(pi->plugin_var + 1));
1830
1832
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1831
1833
                             *(int*)(pi->plugin_var + 1))))
1832
 
           *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
 
1834
           *pp= strdup(*pp);
 
1835
         if (*pp == NULL)
 
1836
           return NULL;
1833
1837
      }
1834
1838
    }
1835
1839
 
1836
1840
    if (global_lock)
1837
1841
      pthread_mutex_unlock(&LOCK_global_system_variables);
1838
1842
 
1839
 
    thd->variables.dynamic_variables_version=
 
1843
    session->variables.dynamic_variables_version=
1840
1844
           global_system_variables.dynamic_variables_version;
1841
 
    thd->variables.dynamic_variables_head=
 
1845
    session->variables.dynamic_variables_head=
1842
1846
           global_system_variables.dynamic_variables_head;
1843
 
    thd->variables.dynamic_variables_size=
 
1847
    session->variables.dynamic_variables_size=
1844
1848
           global_system_variables.dynamic_variables_size;
1845
1849
 
1846
 
    rw_unlock(&LOCK_system_variables_hash);
 
1850
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
1847
1851
  }
1848
 
  return (uchar*)thd->variables.dynamic_variables_ptr + offset;
1849
 
}
1850
 
 
1851
 
static bool *mysql_sys_var_ptr_bool(THD* a_thd, int offset)
1852
 
{
1853
 
  return (bool *)intern_sys_var_ptr(a_thd, offset, true);
1854
 
}
1855
 
 
1856
 
static int *mysql_sys_var_ptr_int(THD* a_thd, int offset)
1857
 
{
1858
 
  return (int *)intern_sys_var_ptr(a_thd, offset, true);
1859
 
}
1860
 
 
1861
 
static long *mysql_sys_var_ptr_long(THD* a_thd, int offset)
1862
 
{
1863
 
  return (long *)intern_sys_var_ptr(a_thd, offset, true);
1864
 
}
1865
 
 
1866
 
static int64_t *mysql_sys_var_ptr_int64_t(THD* a_thd, int offset)
1867
 
{
1868
 
  return (int64_t *)intern_sys_var_ptr(a_thd, offset, true);
1869
 
}
1870
 
 
1871
 
static char **mysql_sys_var_ptr_str(THD* a_thd, int offset)
1872
 
{
1873
 
  return (char **)intern_sys_var_ptr(a_thd, offset, true);
1874
 
}
1875
 
 
1876
 
static uint64_t *mysql_sys_var_ptr_set(THD* a_thd, int offset)
1877
 
{
1878
 
  return (uint64_t *)intern_sys_var_ptr(a_thd, offset, true);
1879
 
}
1880
 
 
1881
 
static unsigned long *mysql_sys_var_ptr_enum(THD* a_thd, int offset)
1882
 
{
1883
 
  return (unsigned long *)intern_sys_var_ptr(a_thd, offset, true);
1884
 
}
1885
 
 
1886
 
 
1887
 
void plugin_thdvar_init(THD *thd)
1888
 
{
1889
 
  plugin_ref old_table_plugin= thd->variables.table_plugin;
1890
 
  
1891
 
  thd->variables.table_plugin= NULL;
1892
 
  cleanup_variables(thd, &thd->variables);
1893
 
  
1894
 
  thd->variables= global_system_variables;
1895
 
  thd->variables.table_plugin= NULL;
 
1852
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
 
1853
}
 
1854
 
 
1855
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
 
1856
{
 
1857
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
 
1858
}
 
1859
 
 
1860
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
 
1861
{
 
1862
  return (int *)intern_sys_var_ptr(a_session, offset, true);
 
1863
}
 
1864
 
 
1865
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
 
1866
{
 
1867
  return (long *)intern_sys_var_ptr(a_session, offset, true);
 
1868
}
 
1869
 
 
1870
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
 
1871
{
 
1872
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1873
}
 
1874
 
 
1875
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
 
1876
{
 
1877
  return (char **)intern_sys_var_ptr(a_session, offset, true);
 
1878
}
 
1879
 
 
1880
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
 
1881
{
 
1882
  return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1883
}
 
1884
 
 
1885
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
 
1886
{
 
1887
  return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
 
1888
}
 
1889
 
 
1890
 
 
1891
void plugin_sessionvar_init(Session *session)
 
1892
{
 
1893
  plugin_ref old_table_plugin= session->variables.table_plugin;
 
1894
 
 
1895
  session->variables.table_plugin= NULL;
 
1896
  cleanup_variables(session, &session->variables);
 
1897
 
 
1898
  session->variables= global_system_variables;
 
1899
  session->variables.table_plugin= NULL;
1896
1900
 
1897
1901
  /* we are going to allocate these lazily */
1898
 
  thd->variables.dynamic_variables_version= 0;
1899
 
  thd->variables.dynamic_variables_size= 0;
1900
 
  thd->variables.dynamic_variables_ptr= 0;
 
1902
  session->variables.dynamic_variables_version= 0;
 
1903
  session->variables.dynamic_variables_size= 0;
 
1904
  session->variables.dynamic_variables_ptr= 0;
1901
1905
 
1902
 
  thd->variables.table_plugin=
 
1906
  session->variables.table_plugin=
1903
1907
        my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1904
1908
  intern_plugin_unlock(NULL, old_table_plugin);
1905
1909
  return;
1909
1913
/*
1910
1914
  Unlocks all system variables which hold a reference
1911
1915
*/
1912
 
static void unlock_variables(THD *thd __attribute__((unused)),
1913
 
                             struct system_variables *vars)
 
1916
static void unlock_variables(Session *, struct system_variables *vars)
1914
1917
{
1915
1918
  intern_plugin_unlock(NULL, vars->table_plugin);
1916
1919
  vars->table_plugin= NULL;
1923
1926
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
1924
1927
  it's used on shutdown.
1925
1928
*/
1926
 
static void cleanup_variables(THD *thd, struct system_variables *vars)
 
1929
static void cleanup_variables(Session *session, struct system_variables *vars)
1927
1930
{
1928
1931
  st_bookmark *v;
1929
1932
  sys_var_pluginvar *pivar;
1930
1933
  sys_var *var;
1931
1934
  int flags;
1932
 
  uint idx;
 
1935
  uint32_t idx;
1933
1936
 
1934
 
  rw_rdlock(&LOCK_system_variables_hash);
 
1937
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
1935
1938
  for (idx= 0; idx < bookmark_hash.records; idx++)
1936
1939
  {
1937
1940
    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1944
1947
    flags= pivar->plugin_var->flags;
1945
1948
 
1946
1949
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1947
 
        flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
 
1950
        flags & PLUGIN_VAR_SessionLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1948
1951
    {
1949
 
      char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
1950
 
      my_free(*ptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
 
1952
      char **ptr= (char**) pivar->real_value_ptr(session, OPT_SESSION);
 
1953
      free(*ptr);
1951
1954
      *ptr= NULL;
1952
1955
    }
1953
1956
  }
1954
 
  rw_unlock(&LOCK_system_variables_hash);
 
1957
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
1955
1958
 
1956
1959
  assert(vars->table_plugin == NULL);
1957
1960
 
1958
 
  my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR));
 
1961
  free(vars->dynamic_variables_ptr);
1959
1962
  vars->dynamic_variables_ptr= NULL;
1960
1963
  vars->dynamic_variables_size= 0;
1961
1964
  vars->dynamic_variables_version= 0;
1962
1965
}
1963
1966
 
1964
1967
 
1965
 
void plugin_thdvar_cleanup(THD *thd)
 
1968
void plugin_sessionvar_cleanup(Session *session)
1966
1969
{
1967
 
  uint idx;
1968
 
  plugin_ref *list;
1969
 
 
1970
 
  unlock_variables(thd, &thd->variables);
1971
 
  cleanup_variables(thd, &thd->variables);
1972
 
 
1973
 
  if ((idx= thd->lex->plugins.elements))
1974
 
  {
1975
 
    list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
1976
 
    while ((uchar*) list >= thd->lex->plugins.buffer)
1977
 
      intern_plugin_unlock(NULL, *list--);
1978
 
  }
1979
 
 
1980
 
  reset_dynamic(&thd->lex->plugins);
1981
 
 
1982
 
  return;
 
1970
  unlock_variables(session, &session->variables);
 
1971
  cleanup_variables(session, &session->variables);
1983
1972
}
1984
1973
 
1985
1974
 
2006
1995
    {
2007
1996
      /* Free the string from global_system_variables. */
2008
1997
      char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2009
 
      my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
 
1998
      free(*valptr);
2010
1999
      *valptr= NULL;
2011
2000
    }
2012
2001
  }
2054
2043
}
2055
2044
 
2056
2045
 
2057
 
uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
 
2046
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
2058
2047
{
2059
 
  assert(thd || (type == OPT_GLOBAL));
2060
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
2048
  assert(session || (type == OPT_GLOBAL));
 
2049
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2061
2050
  {
2062
2051
    if (type == OPT_GLOBAL)
2063
 
      thd= NULL;
 
2052
      session= NULL;
2064
2053
 
2065
 
    return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
 
2054
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
2066
2055
  }
2067
 
  return *(uchar**) (plugin_var+1);
 
2056
  return *(unsigned char**) (plugin_var+1);
2068
2057
}
2069
2058
 
2070
2059
 
2071
2060
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2072
2061
{
2073
 
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
 
2062
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
2074
2063
  case PLUGIN_VAR_ENUM:
2075
2064
    return ((sysvar_enum_t *)plugin_var)->typelib;
2076
2065
  case PLUGIN_VAR_SET:
2077
2066
    return ((sysvar_set_t *)plugin_var)->typelib;
2078
 
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2079
 
    return ((thdvar_enum_t *)plugin_var)->typelib;
2080
 
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2081
 
    return ((thdvar_set_t *)plugin_var)->typelib;
 
2067
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
 
2068
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
2069
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
 
2070
    return ((sessionvar_set_t *)plugin_var)->typelib;
2082
2071
  default:
2083
2072
    return NULL;
2084
2073
  }
2086
2075
}
2087
2076
 
2088
2077
 
2089
 
uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
2090
 
                                    LEX_STRING *base __attribute__((unused)))
 
2078
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
2091
2079
{
2092
 
  uchar* result;
 
2080
  unsigned char* result;
2093
2081
 
2094
 
  result= real_value_ptr(thd, type);
 
2082
  result= real_value_ptr(session, type);
2095
2083
 
2096
2084
  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2097
 
    result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result);
 
2085
    result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
2098
2086
  else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2099
2087
  {
2100
2088
    char buffer[STRING_BUFFER_USUAL_SIZE];
2101
2089
    String str(buffer, sizeof(buffer), system_charset_info);
2102
2090
    TYPELIB *typelib= plugin_var_typelib();
2103
2091
    uint64_t mask= 1, value= *(uint64_t*) result;
2104
 
    uint i;
 
2092
    uint32_t i;
2105
2093
 
2106
2094
    str.length(0);
2107
2095
    for (i= 0; i < typelib->count; i++, mask<<=1)
2112
2100
      str.append(',');
2113
2101
    }
2114
2102
 
2115
 
    result= (uchar*) "";
 
2103
    result= (unsigned char*) "";
2116
2104
    if (str.length())
2117
 
      result= (uchar*) thd->strmake(str.ptr(), str.length()-1);
 
2105
      result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
2118
2106
  }
2119
2107
  return result;
2120
2108
}
2121
2109
 
2122
2110
 
2123
 
bool sys_var_pluginvar::check(THD *thd, set_var *var)
 
2111
bool sys_var_pluginvar::check(Session *session, set_var *var)
2124
2112
{
2125
2113
  st_item_value_holder value;
2126
2114
  assert(is_readonly() || plugin_var->check);
2132
2120
  value.item= var->value;
2133
2121
 
2134
2122
  return is_readonly() ||
2135
 
         plugin_var->check(thd, plugin_var, &var->save_result, &value);
 
2123
         plugin_var->check(session, plugin_var, &var->save_result, &value);
2136
2124
}
2137
2125
 
2138
2126
 
2139
 
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
 
2127
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
2140
2128
{
2141
2129
  const void *src;
2142
2130
  void *tgt;
2147
2135
    return;
2148
2136
 
2149
2137
  pthread_mutex_lock(&LOCK_global_system_variables);
2150
 
  tgt= real_value_ptr(thd, type);
 
2138
  tgt= real_value_ptr(session, type);
2151
2139
  src= ((void **) (plugin_var + 1) + 1);
2152
2140
 
2153
 
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
 
2141
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
2154
2142
  {
2155
2143
    if (type != OPT_GLOBAL)
2156
 
      src= real_value_ptr(thd, OPT_GLOBAL);
 
2144
      src= real_value_ptr(session, OPT_GLOBAL);
2157
2145
    else
2158
2146
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2159
2147
        case PLUGIN_VAR_INT:
2160
 
          src= &((thdvar_uint_t*) plugin_var)->def_val;
 
2148
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
2161
2149
          break;
2162
2150
        case PLUGIN_VAR_LONG:
2163
 
          src= &((thdvar_ulong_t*) plugin_var)->def_val;
 
2151
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
2164
2152
          break;
2165
2153
        case PLUGIN_VAR_LONGLONG:
2166
 
          src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
 
2154
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
2167
2155
          break;
2168
2156
        case PLUGIN_VAR_ENUM:
2169
 
          src= &((thdvar_enum_t*) plugin_var)->def_val;
 
2157
          src= &((sessionvar_enum_t*) plugin_var)->def_val;
2170
2158
          break;
2171
2159
        case PLUGIN_VAR_SET:
2172
 
          src= &((thdvar_set_t*) plugin_var)->def_val;
 
2160
          src= &((sessionvar_set_t*) plugin_var)->def_val;
2173
2161
          break;
2174
2162
        case PLUGIN_VAR_BOOL:
2175
 
          src= &((thdvar_bool_t*) plugin_var)->def_val;
 
2163
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
2176
2164
          break;
2177
2165
        case PLUGIN_VAR_STR:
2178
 
          src= &((thdvar_str_t*) plugin_var)->def_val;
 
2166
          src= &((sessionvar_str_t*) plugin_var)->def_val;
2179
2167
          break;
2180
2168
        default:
2181
2169
          assert(0);
2182
2170
        }
2183
2171
  }
2184
2172
 
2185
 
  /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2186
 
  assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2187
 
              thd == current_thd);
 
2173
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
2174
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
2175
              session == current_session);
2188
2176
 
2189
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
 
2177
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
2190
2178
  {
2191
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
2179
    plugin_var->update(session, plugin_var, tgt, src);
2192
2180
    pthread_mutex_unlock(&LOCK_global_system_variables);
2193
2181
  }
2194
2182
  else
2195
2183
  {
2196
2184
    pthread_mutex_unlock(&LOCK_global_system_variables);
2197
 
    plugin_var->update(thd, plugin_var, tgt, src);
 
2185
    plugin_var->update(session, plugin_var, tgt, src);
2198
2186
  }
2199
2187
}
2200
2188
 
2201
2189
 
2202
 
bool sys_var_pluginvar::update(THD *thd, set_var *var)
 
2190
bool sys_var_pluginvar::update(Session *session, set_var *var)
2203
2191
{
2204
2192
  void *tgt;
2205
2193
 
2206
2194
  assert(is_readonly() || plugin_var->update);
2207
2195
 
2208
 
  /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
2209
 
  assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
2210
 
              thd == current_thd);
 
2196
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
2197
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
2198
              session == current_session);
2211
2199
 
2212
2200
  if (is_readonly())
2213
2201
    return 1;
2214
2202
 
2215
2203
  pthread_mutex_lock(&LOCK_global_system_variables);
2216
 
  tgt= real_value_ptr(thd, var->type);
 
2204
  tgt= real_value_ptr(session, var->type);
2217
2205
 
2218
 
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
 
2206
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
2219
2207
  {
2220
2208
    /* variable we are updating has global scope, so we unlock after updating */
2221
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
2209
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2222
2210
    pthread_mutex_unlock(&LOCK_global_system_variables);
2223
2211
  }
2224
2212
  else
2225
2213
  {
2226
2214
    pthread_mutex_unlock(&LOCK_global_system_variables);
2227
 
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
 
2215
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
2228
2216
  }
2229
2217
 return 0;
2230
2218
}
2231
2219
 
2232
2220
 
2233
2221
#define OPTION_SET_LIMITS(type, options, opt) \
2234
 
  options->var_type= type; \
2235
 
  options->def_value= (opt)->def_val; \
2236
 
  options->min_value= (opt)->min_val; \
2237
 
  options->max_value= (opt)->max_val; \
 
2222
  options->var_type= type;                    \
 
2223
  options->def_value= (opt)->def_val;         \
 
2224
  options->min_value= (opt)->min_val;         \
 
2225
  options->max_value= (opt)->max_val;         \
2238
2226
  options->block_size= (long) (opt)->blk_sz
2239
2227
 
2240
2228
 
2244
2232
  options->sub_size= 0;
2245
2233
 
2246
2234
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2247
 
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
 
2235
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
2248
2236
  /* global system variables */
2249
2237
  case PLUGIN_VAR_INT:
2250
2238
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2276
2264
    options->typelib= ((sysvar_set_t*) opt)->typelib;
2277
2265
    options->def_value= ((sysvar_set_t*) opt)->def_val;
2278
2266
    options->min_value= options->block_size= 0;
2279
 
    options->max_value= (1ULL << options->typelib->count) - 1;
 
2267
    options->max_value= (1UL << options->typelib->count) - 1;
2280
2268
    break;
2281
2269
  case PLUGIN_VAR_BOOL:
2282
2270
    options->var_type= GET_BOOL;
2288
2276
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
2289
2277
    break;
2290
2278
  /* threadlocal variables */
2291
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
2292
 
    OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
2293
 
    break;
2294
 
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2295
 
    OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
2296
 
    break;
2297
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
2298
 
    OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
2299
 
    break;
2300
 
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2301
 
    OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
2302
 
    break;
2303
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
2304
 
    OPTION_SET_LIMITS(GET_LL, options, (thdvar_int64_t_t*) opt);
2305
 
    break;
2306
 
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2307
 
    OPTION_SET_LIMITS(GET_ULL, options, (thdvar_uint64_t_t*) opt);
2308
 
    break;
2309
 
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
 
2279
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
 
2280
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
 
2281
    break;
 
2282
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2283
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
 
2284
    break;
 
2285
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
 
2286
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
 
2287
    break;
 
2288
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2289
    OPTION_SET_LIMITS(GET_ULONG, options, (sessionvar_ulong_t*) opt);
 
2290
    break;
 
2291
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
 
2292
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
 
2293
    break;
 
2294
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
2295
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
 
2296
    break;
 
2297
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
2310
2298
    options->var_type= GET_ENUM;
2311
 
    options->typelib= ((thdvar_enum_t*) opt)->typelib;
2312
 
    options->def_value= ((thdvar_enum_t*) opt)->def_val;
 
2299
    options->typelib= ((sessionvar_enum_t*) opt)->typelib;
 
2300
    options->def_value= ((sessionvar_enum_t*) opt)->def_val;
2313
2301
    options->min_value= options->block_size= 0;
2314
2302
    options->max_value= options->typelib->count - 1;
2315
2303
    break;
2316
 
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
 
2304
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
2317
2305
    options->var_type= GET_SET;
2318
 
    options->typelib= ((thdvar_set_t*) opt)->typelib;
2319
 
    options->def_value= ((thdvar_set_t*) opt)->def_val;
 
2306
    options->typelib= ((sessionvar_set_t*) opt)->typelib;
 
2307
    options->def_value= ((sessionvar_set_t*) opt)->def_val;
2320
2308
    options->min_value= options->block_size= 0;
2321
 
    options->max_value= (1ULL << options->typelib->count) - 1;
 
2309
    options->max_value= (1UL << options->typelib->count) - 1;
2322
2310
    break;
2323
 
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
 
2311
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
2324
2312
    options->var_type= GET_BOOL;
2325
 
    options->def_value= ((thdvar_bool_t*) opt)->def_val;
 
2313
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
2326
2314
    break;
2327
 
  case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
 
2315
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
2328
2316
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2329
2317
                        GET_STR_ALLOC : GET_STR);
2330
 
    options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
 
2318
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
2331
2319
    break;
2332
2320
  default:
2333
2321
    assert(0);
2342
2330
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
2343
2331
                                         char *);
2344
2332
 
2345
 
bool get_one_plugin_option(int optid __attribute__((unused)),
2346
 
                              const struct my_option *opt __attribute__((unused)),
2347
 
                              char *argument __attribute__((unused)))
 
2333
bool get_one_plugin_option(int, const struct my_option *, char *)
2348
2334
{
2349
2335
  return 0;
2350
2336
}
2354
2340
                             my_option *options, bool can_disable)
2355
2341
{
2356
2342
  const char *plugin_name= tmp->plugin->name;
2357
 
  uint namelen= strlen(plugin_name), optnamelen;
2358
 
  uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
 
2343
  uint32_t namelen= strlen(plugin_name), optnamelen;
 
2344
  uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2359
2345
  char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2360
2346
  char *optname, *p;
2361
2347
  int index= 0, offset= 0;
2364
2350
 
2365
2351
  /* support --skip-plugin-foo syntax */
2366
2352
  memcpy(name, plugin_name, namelen + 1);
2367
 
  my_casedn_str(&my_charset_latin1, name);
2368
 
  strxmov(name + namelen + 1, "plugin-", name, NullS);
 
2353
  my_casedn_str(&my_charset_utf8_general_ci, name);
 
2354
  sprintf(name+namelen+1, "plugin-%s", name);
2369
2355
  /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2370
2356
 
2371
2357
  for (p= name + namelen*2 + 8; p > name; p--)
2374
2360
 
2375
2361
  if (can_disable)
2376
2362
  {
2377
 
    strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2378
 
            "Disable with --skip-", name," (will save memory).", NullS);
 
2363
    sprintf(name+namelen*2+10,
 
2364
            "Enable %s plugin. Disable with --skip-%s (will save memory).",
 
2365
            plugin_name, name);
2379
2366
    /*
2380
2367
      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2381
2368
      20 + namelen + 20 + 1 == namelen * 4 + 67.
2402
2389
       plugin_option && *plugin_option; plugin_option++, index++)
2403
2390
  {
2404
2391
    opt= *plugin_option;
2405
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2392
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2406
2393
      continue;
2407
2394
    if (!(register_var(name, opt->name, opt->flags)))
2408
2395
      continue;
2409
2396
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2410
2397
    case PLUGIN_VAR_BOOL:
2411
 
      (((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
 
2398
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
2412
2399
      break;
2413
2400
    case PLUGIN_VAR_INT:
2414
 
      (((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
 
2401
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
2415
2402
      break;
2416
2403
    case PLUGIN_VAR_LONG:
2417
 
      (((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
 
2404
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
2418
2405
      break;
2419
2406
    case PLUGIN_VAR_LONGLONG:
2420
 
      (((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
 
2407
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
2421
2408
      break;
2422
2409
    case PLUGIN_VAR_STR:
2423
 
      (((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
 
2410
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
2424
2411
      break;
2425
2412
    case PLUGIN_VAR_ENUM:
2426
 
      (((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
 
2413
      (((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
2427
2414
      break;
2428
2415
    case PLUGIN_VAR_SET:
2429
 
      (((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
 
2416
      (((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
2430
2417
      break;
2431
2418
    default:
2432
 
      sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
 
2419
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2433
2420
                      opt->flags, plugin_name);
2434
2421
      return(-1);
2435
2422
    };
2472
2459
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
2473
2460
        {
2474
2461
          opt->flags|= PLUGIN_VAR_READONLY;
2475
 
          sql_print_warning("Server variable %s of plugin %s was forced "
 
2462
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
2476
2463
                            "to be read-only: string variable without "
2477
 
                            "update_func and PLUGIN_VAR_MEMALLOC flag",
 
2464
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
2478
2465
                            opt->name, plugin_name);
2479
2466
        }
2480
2467
      }
2492
2479
        opt->update= update_func_int64_t;
2493
2480
      break;
2494
2481
    default:
2495
 
      sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
 
2482
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
2496
2483
                      opt->flags, plugin_name);
2497
2484
      return(-1);
2498
2485
    }
2499
2486
 
2500
 
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
 
2487
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
2501
2488
                    == PLUGIN_VAR_NOCMDOPT)
2502
2489
      continue;
2503
2490
 
2504
2491
    if (!opt->name)
2505
2492
    {
2506
 
      sql_print_error("Missing variable name in plugin '%s'.",
 
2493
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
2507
2494
                      plugin_name);
2508
2495
      return(-1);
2509
2496
    }
2510
2497
 
2511
 
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
 
2498
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
2512
2499
    {
2513
2500
      optnamelen= strlen(opt->name);
2514
2501
      optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2515
 
      strxmov(optname, name, "-", opt->name, NullS);
 
2502
      sprintf(optname, "%s-%s", name, opt->name);
2516
2503
      optnamelen= namelen + optnamelen + 1;
2517
2504
    }
2518
2505
    else
2520
2507
      /* this should not fail because register_var should create entry */
2521
2508
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
2522
2509
      {
2523
 
        sql_print_error("Thread local variable '%s' not allocated "
2524
 
                        "in plugin '%s'.", opt->name, plugin_name);
 
2510
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
 
2511
                        "in plugin '%s'."), opt->name, plugin_name);
2525
2512
        return(-1);
2526
2513
      }
2527
2514
 
2530
2517
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2531
2518
        continue;
2532
2519
 
2533
 
      optname= (char*) memdup_root(mem_root, v->key + 1, 
 
2520
      optname= (char*) memdup_root(mem_root, v->key + 1,
2534
2521
                                   (optnamelen= v->name_len) + 1);
2535
2522
    }
2536
2523
 
2546
2533
 
2547
2534
    plugin_opt_set_limits(options, opt);
2548
2535
 
2549
 
    if (opt->flags & PLUGIN_VAR_THDLOCAL)
 
2536
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
2550
2537
      options->value= options->u_max_value= (char**)
2551
2538
        (global_system_variables.dynamic_variables_ptr + offset);
2552
2539
    else
2555
2542
    options[1]= options[0];
2556
2543
    options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2557
2544
    options[1].comment= 0; // hidden
2558
 
    strxmov(p, "plugin-", optname, NullS);
 
2545
    sprintf(p,"plugin-%s",optname);
2559
2546
 
2560
2547
    options+= 2;
2561
2548
  }
2570
2557
  st_mysql_sys_var **opt;
2571
2558
  my_option *opts;
2572
2559
  bool can_disable;
2573
 
  uint count= EXTRA_OPTIONS;
 
2560
  uint32_t count= EXTRA_OPTIONS;
2574
2561
 
2575
2562
  for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
2576
2563
 
2579
2566
 
2580
2567
  memset(opts, 0, sizeof(my_option) * count);
2581
2568
 
2582
 
  if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") == 0))
 
2569
  if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
2583
2570
    can_disable= false;
2584
 
  else if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY") == 0))
 
2571
  else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
2585
2572
    can_disable= false;
2586
2573
  else
2587
2574
    can_disable= true;
2622
2609
  st_mysql_sys_var *o;
2623
2610
  sys_var *v;
2624
2611
  struct st_bookmark *var;
2625
 
  uint len, count= EXTRA_OPTIONS;
 
2612
  uint32_t len, count= EXTRA_OPTIONS;
2626
2613
  assert(tmp->plugin && tmp->name.str);
2627
2614
 
2628
2615
  for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
2629
2616
    count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
2630
2617
 
2631
 
  if ((my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") == 0))
 
2618
  if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->name.str, "MyISAM") == 0))
2632
2619
    can_disable= false;
2633
 
  else if ((my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY") == 0))
 
2620
  else if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->name.str, "MEMORY") == 0))
2634
2621
    can_disable= false;
2635
2622
  else
2636
2623
    can_disable= true;
2639
2626
  {
2640
2627
    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2641
2628
    {
2642
 
      sql_print_error("Out of memory for plugin '%s'.", tmp->name.str);
 
2629
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->name.str);
2643
2630
      return(-1);
2644
2631
    }
2645
2632
    memset(opts, 0, sizeof(my_option) * count);
2646
2633
 
2647
2634
    if (construct_options(tmp_root, tmp, opts, can_disable))
2648
2635
    {
2649
 
      sql_print_error("Bad options for plugin '%s'.", tmp->name.str);
 
2636
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->name.str);
2650
2637
      return(-1);
2651
2638
    }
2652
2639
 
2655
2642
 
2656
2643
    if (error)
2657
2644
    {
2658
 
       sql_print_error("Parsing options for plugin '%s' failed.",
 
2645
       errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
2659
2646
                       tmp->name.str);
2660
2647
       goto err;
2661
2648
    }
2675
2662
      {
2676
2663
        len= tmp->name.length + strlen(o->name) + 2;
2677
2664
        varname= (char*) alloc_root(mem_root, len);
2678
 
        strxmov(varname, tmp->name.str, "-", o->name, NullS);
2679
 
        my_casedn_str(&my_charset_latin1, varname);
 
2665
        sprintf(varname,"%s-%s",tmp->name.str,o->name);
 
2666
        my_casedn_str(&my_charset_utf8_general_ci, varname);
2680
2667
 
2681
2668
        for (p= varname; *p; p++)
2682
2669
          if (*p == '-')
2698
2685
      chain.last->next = NULL;
2699
2686
      if (mysql_add_sys_var_chain(chain.first, NULL))
2700
2687
      {
2701
 
        sql_print_error("Plugin '%s' has conflicting system variables",
 
2688
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
2702
2689
                        tmp->name.str);
2703
2690
        goto err;
2704
2691
      }
2708
2695
  }
2709
2696
 
2710
2697
  if (enabled_saved && global_system_variables.log_warnings)
2711
 
    sql_print_information("Plugin '%s' disabled by command line option",
 
2698
    errmsg_printf(ERRMSG_LVL_INFO, _("Plugin '%s' disabled by command line option"),
2712
2699
                          tmp->name.str);
2713
2700
err:
2714
2701
  if (opts)
2723
2710
 
2724
2711
static int option_cmp(my_option *a, my_option *b)
2725
2712
{
2726
 
  return my_strcasecmp(&my_charset_latin1, a->name, b->name);
 
2713
  return my_strcasecmp(&my_charset_utf8_general_ci, a->name, b->name);
2727
2714
}
2728
2715
 
2729
2716
 
2730
 
void my_print_help_inc_plugins(my_option *main_options, uint size)
 
2717
void my_print_help_inc_plugins(my_option *main_options, uint32_t size)
2731
2718
{
2732
2719
  DYNAMIC_ARRAY all_options;
2733
2720
  struct st_plugin_int *p;
2738
2725
  my_init_dynamic_array(&all_options, sizeof(my_option), size, size/4);
2739
2726
 
2740
2727
  if (initialized)
2741
 
    for (uint idx= 0; idx < plugin_array.elements; idx++)
 
2728
    for (uint32_t idx= 0; idx < plugin_array.elements; idx++)
2742
2729
    {
2743
2730
      p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
2744
2731
 
2749
2736
      /* Only options with a non-NULL comment are displayed in help text */
2750
2737
      for (;opt->id; opt++)
2751
2738
        if (opt->comment)
2752
 
          insert_dynamic(&all_options, (uchar*) opt);
 
2739
          insert_dynamic(&all_options, (unsigned char*) opt);
2753
2740
    }
2754
2741
 
2755
2742
  for (;main_options->id; main_options++)
2756
 
    insert_dynamic(&all_options, (uchar*) main_options);
 
2743
    insert_dynamic(&all_options, (unsigned char*) main_options);
2757
2744
 
2758
2745
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
2759
2746
 
2760
2747
  /* main_options now points to the empty option terminator */
2761
 
  insert_dynamic(&all_options, (uchar*) main_options);
 
2748
  insert_dynamic(&all_options, (unsigned char*) main_options);
2762
2749
 
2763
2750
  my_print_help((my_option*) all_options.buffer);
2764
2751
  my_print_variables((my_option*) all_options.buffer);