~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2005 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
#include "mysql_priv.h"
17
#include <my_pthread.h>
18
#include <my_getopt.h>
19
#define REPORT_TO_LOG  1
20
#define REPORT_TO_USER 2
21
22
#define plugin_ref_to_int(A) (A ? A[0] : NULL)
23
#define plugin_int_to_ref(A) &(A)
24
25
extern struct st_mysql_plugin *mysqld_builtins[];
26
27
char *opt_plugin_load= NULL;
28
char *opt_plugin_dir_ptr;
29
char opt_plugin_dir[FN_REFLEN];
30
/*
31
  When you ad a new plugin type, add both a string and make sure that the
32
  init and deinit array are correctly updated.
33
*/
34
const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
35
{
190.1.1 by Mark Atwood
reorder plugin type numbering
36
  { C_STRING_WITH_LEN("DAEMON") },
37
  { C_STRING_WITH_LEN("STORAGE ENGINE") },
38
  { C_STRING_WITH_LEN("INFORMATION SCHEMA") },
1 by brian
clean slate
39
  { C_STRING_WITH_LEN("UDF") },
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
40
  { C_STRING_WITH_LEN("UDA") },
41
  { C_STRING_WITH_LEN("AUDIT") },
190.1.1 by Mark Atwood
reorder plugin type numbering
42
  { C_STRING_WITH_LEN("LOGGER") },
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
43
  { C_STRING_WITH_LEN("AUTH") }
1 by brian
clean slate
44
};
45
46
extern int initialize_schema_table(st_plugin_int *plugin);
47
extern int finalize_schema_table(st_plugin_int *plugin);
48
134.1.1 by Mark Atwood
more hackery to get plugin UDFs working
49
extern int initialize_udf(st_plugin_int *plugin);
50
extern int finalize_udf(st_plugin_int *plugin);
51
1 by brian
clean slate
52
/*
53
  The number of elements in both plugin_type_initialize and
54
  plugin_type_deinitialize should equal to the number of plugins
55
  defined.
56
*/
57
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
58
{
190.1.1 by Mark Atwood
reorder plugin type numbering
59
  0,  /* Daemon */
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
60
  ha_initialize_handlerton,  /* Storage Engine */
61
  initialize_schema_table,  /* Information Schema */
190.1.1 by Mark Atwood
reorder plugin type numbering
62
  initialize_udf,  /* UDF */
63
  0,  /* UDA */
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
64
  0,  /* Audit */
190.1.1 by Mark Atwood
reorder plugin type numbering
65
  0,  /* Logger */
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
66
  0  /* Auth */
1 by brian
clean slate
67
};
68
69
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
70
{
190.1.1 by Mark Atwood
reorder plugin type numbering
71
  0,  /* Daemon */
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
72
  ha_finalize_handlerton,  /* Storage Engine */
73
  finalize_schema_table,  /* Information Schema */
190.1.1 by Mark Atwood
reorder plugin type numbering
74
  finalize_udf,  /* UDF */
75
  0,  /* UDA */
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
76
  0,  /* Audit */
190.1.1 by Mark Atwood
reorder plugin type numbering
77
  0,  /* Logger */
160.1.1 by mark
Stubs for plugin types for UDA, LOG, and AUTH
78
  0  /* Auth */
1 by brian
clean slate
79
};
80
81
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
82
83
/* Note that 'int version' must be the first field of every plugin
84
   sub-structure (plugin->info).
85
*/
86
87
static bool initialized= 0;
88
89
static DYNAMIC_ARRAY plugin_dl_array;
90
static DYNAMIC_ARRAY plugin_array;
91
static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
92
static bool reap_needed= false;
93
static int plugin_array_version=0;
94
95
/*
96
  write-lock on LOCK_system_variables_hash is required before modifying
97
  the following variables/structures
98
*/
99
static MEM_ROOT plugin_mem_root;
100
static uint global_variables_dynamic_size= 0;
101
static HASH bookmark_hash;
102
103
104
/*
105
  hidden part of opaque value passed to variable check functions.
106
  Used to provide a object-like structure to non C++ consumers.
107
*/
108
struct st_item_value_holder : public st_mysql_value
109
{
110
  Item *item;
111
};
112
113
114
/*
115
  stored in bookmark_hash, this structure is never removed from the
116
  hash and is used to mark a single offset for a thd local variable
117
  even if plugins have been uninstalled and reinstalled, repeatedly.
118
  This structure is allocated from plugin_mem_root.
119
120
  The key format is as follows:
121
    1 byte         - variable type code
122
    name_len bytes - variable name
123
    '\0'           - end of key
124
*/
125
struct st_bookmark
126
{
127
  uint name_len;
128
  int offset;
129
  uint version;
130
  char key[1];
131
};
132
133
134
/*
135
  skeleton of a plugin variable - portion of structure common to all.
136
*/
137
struct st_mysql_sys_var
138
{
139
  MYSQL_PLUGIN_VAR_HEADER;
140
};
141
142
143
/*
144
  sys_var class for access to all plugin variables visible to the user
145
*/
146
class sys_var_pluginvar: public sys_var
147
{
148
public:
149
  struct st_plugin_int *plugin;
150
  struct st_mysql_sys_var *plugin_var;
151
152
  static void *operator new(size_t size, MEM_ROOT *mem_root)
153
  { return (void*) alloc_root(mem_root, (uint) size); }
77.1.46 by Monty Taylor
Finished the warnings work!
154
  static void operator delete(void *ptr_arg __attribute__((__unused__)),
155
                              size_t size __attribute__((__unused__)))
1 by brian
clean slate
156
  { TRASH(ptr_arg, size); }
157
158
  sys_var_pluginvar(const char *name_arg,
159
                    struct st_mysql_sys_var *plugin_var_arg)
160
    :sys_var(name_arg), plugin_var(plugin_var_arg) {}
161
  sys_var_pluginvar *cast_pluginvar() { return this; }
162
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
163
  bool check_type(enum_var_type type)
164
  { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; }
165
  bool check_update_type(Item_result type);
166
  SHOW_TYPE show_type();
167
  uchar* real_value_ptr(THD *thd, enum_var_type type);
168
  TYPELIB* plugin_var_typelib(void);
169
  uchar* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
170
  bool check(THD *thd, set_var *var);
77.1.46 by Monty Taylor
Finished the warnings work!
171
  bool check_default(enum_var_type type __attribute__((__unused__)))
172
    { return is_readonly(); }
173
  void set_default(THD *thd,
174
                   enum_var_type type __attribute__((__unused__)));
1 by brian
clean slate
175
  bool update(THD *thd, set_var *var);
176
};
177
178
179
/* prototypes */
180
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
181
                             const char *list);
182
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
135 by Brian Aker
Random cleanup. Dead partition tests, pass operator in sql_plugin, mtr based
183
                               int *, char **);
1 by brian
clean slate
184
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
185
                             struct st_plugin_int **);
186
static void unlock_variables(THD *thd, struct system_variables *vars);
187
static void cleanup_variables(THD *thd, struct system_variables *vars);
188
static void plugin_vars_free_values(sys_var *vars);
189
static void plugin_opt_set_limits(struct my_option *options,
190
                                  const struct st_mysql_sys_var *opt);
191
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
192
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
193
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
194
                                     CALLER_INFO_PROTO);
195
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
196
static void reap_plugins(void);
197
198
199
/* declared in set_var.cc */
200
extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
201
extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
152 by Brian Aker
longlong replacement
202
                                 const char *name, int64_t val);
1 by brian
clean slate
203
204
/****************************************************************************
205
  Value type thunks, allows the C world to play in the C++ world
206
****************************************************************************/
207
208
static int item_value_type(struct st_mysql_value *value)
209
{
210
  switch (((st_item_value_holder*)value)->item->result_type()) {
211
  case INT_RESULT:
212
    return MYSQL_VALUE_TYPE_INT;
213
  case REAL_RESULT:
214
    return MYSQL_VALUE_TYPE_REAL;
215
  default:
216
    return MYSQL_VALUE_TYPE_STRING;
217
  }
218
}
219
220
static const char *item_val_str(struct st_mysql_value *value,
221
                                char *buffer, int *length)
222
{
223
  String str(buffer, *length, system_charset_info), *res;
224
  if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
225
    return NULL;
226
  *length= res->length();
227
  if (res->c_ptr_quick() == buffer)
228
    return buffer;
229
230
  /*
231
    Lets be nice and create a temporary string since the
232
    buffer was too small
233
  */
234
  return current_thd->strmake(res->c_ptr_quick(), res->length());
235
}
236
237
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
238
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
1 by brian
clean slate
239
{
240
  Item *item= ((st_item_value_holder*)value)->item;
241
  *buf= item->val_int();
242
  if (item->is_null())
243
    return 1;
244
  return 0;
245
}
246
247
248
static int item_val_real(struct st_mysql_value *value, double *buf)
249
{
250
  Item *item= ((st_item_value_holder*)value)->item;
251
  *buf= item->val_real();
252
  if (item->is_null())
253
    return 1;
254
  return 0;
255
}
256
257
258
/****************************************************************************
259
  Plugin support code
260
****************************************************************************/
261
262
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
263
{
264
  uint i;
265
  struct st_plugin_dl *tmp;
266
  for (i= 0; i < plugin_dl_array.elements; i++)
267
  {
268
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
269
    if (tmp->ref_count &&
270
        ! my_strnncoll(files_charset_info,
271
                       (const uchar *)dl->str, dl->length,
272
                       (const uchar *)tmp->dl.str, tmp->dl.length))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
273
      return(tmp);
1 by brian
clean slate
274
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
275
  return(0);
1 by brian
clean slate
276
}
277
278
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
279
{
280
  uint i;
281
  struct st_plugin_dl *tmp;
282
  for (i= 0; i < plugin_dl_array.elements; i++)
283
  {
284
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
285
    if (! tmp->ref_count)
286
    {
287
      memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
288
      return(tmp);
1 by brian
clean slate
289
    }
290
  }
291
  if (insert_dynamic(&plugin_dl_array, (uchar*)&plugin_dl))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
292
    return(0);
1 by brian
clean slate
293
  tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
294
                        struct st_plugin_dl **)=
295
      (struct st_plugin_dl *) memdup_root(&plugin_mem_root, (uchar*)plugin_dl,
296
                                           sizeof(struct st_plugin_dl));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
297
  return(tmp);
1 by brian
clean slate
298
}
299
300
static inline void free_plugin_mem(struct st_plugin_dl *p)
301
{
302
  if (p->handle)
303
    dlclose(p->handle);
304
  my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR));
305
}
306
307
308
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
309
{
310
  char dlpath[FN_REFLEN];
311
  uint plugin_dir_len, dummy_errors, dlpathlen;
312
  struct st_plugin_dl *tmp, plugin_dl;
313
  void *sym;
314
  plugin_dir_len= strlen(opt_plugin_dir);
315
  /*
316
    Ensure that the dll doesn't have a path.
317
    This is done to ensure that only approved libraries from the
318
    plugin directory are used (to make this even remotely secure).
319
  */
320
  if (my_strchr(files_charset_info, dl->str, dl->str + dl->length, FN_LIBCHAR) ||
321
      check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
322
                               system_charset_info, 1) ||
323
      plugin_dir_len + dl->length + 1 >= FN_REFLEN)
324
  {
325
    if (report & REPORT_TO_USER)
326
      my_error(ER_UDF_NO_PATHS, MYF(0));
327
    if (report & REPORT_TO_LOG)
328
      sql_print_error(ER(ER_UDF_NO_PATHS));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
329
    return(0);
1 by brian
clean slate
330
  }
331
  /* If this dll is already loaded just increase ref_count. */
332
  if ((tmp= plugin_dl_find(dl)))
333
  {
334
    tmp->ref_count++;
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
335
    return(tmp);
1 by brian
clean slate
336
  }
337
  bzero(&plugin_dl, sizeof(plugin_dl));
338
  /* Compile dll path */
339
  dlpathlen=
340
    strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS) -
341
    dlpath;
342
  plugin_dl.ref_count= 1;
343
  /* Open new dll handle */
344
  if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
345
  {
346
    const char *errmsg=dlerror();
347
    if (!strncmp(dlpath, errmsg, dlpathlen))
348
    { // if errmsg starts from dlpath, trim this prefix.
349
      errmsg+=dlpathlen;
350
      if (*errmsg == ':') errmsg++;
351
      if (*errmsg == ' ') errmsg++;
352
    }
353
    if (report & REPORT_TO_USER)
354
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
355
    if (report & REPORT_TO_LOG)
356
      sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
357
    return(0);
1 by brian
clean slate
358
  }
177.4.1 by mark
remove some useless version checking code from sql_plugin.cc
359
1 by brian
clean slate
360
  /* Find plugin declarations */
361
  if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
362
  {
363
    free_plugin_mem(&plugin_dl);
364
    if (report & REPORT_TO_USER)
365
      my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
366
    if (report & REPORT_TO_LOG)
367
      sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
368
    return(0);
1 by brian
clean slate
369
  }
370
371
  plugin_dl.plugins= (struct st_mysql_plugin *)sym;
372
373
  /* Duplicate and convert dll name */
374
  plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
375
  if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
376
  {
377
    free_plugin_mem(&plugin_dl);
378
    if (report & REPORT_TO_USER)
379
      my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
380
    if (report & REPORT_TO_LOG)
381
      sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
382
    return(0);
1 by brian
clean slate
383
  }
384
  plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
385
    files_charset_info, dl->str, dl->length, system_charset_info,
386
    &dummy_errors);
387
  plugin_dl.dl.str[plugin_dl.dl.length]= 0;
388
  /* Add this dll to array */
389
  if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
390
  {
391
    free_plugin_mem(&plugin_dl);
392
    if (report & REPORT_TO_USER)
393
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
394
    if (report & REPORT_TO_LOG)
395
      sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
396
    return(0);
1 by brian
clean slate
397
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
398
  return(tmp);
1 by brian
clean slate
399
}
400
401
402
static void plugin_dl_del(const LEX_STRING *dl)
403
{
404
  uint i;
405
406
  for (i= 0; i < plugin_dl_array.elements; i++)
407
  {
408
    struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
409
                                               struct st_plugin_dl **);
410
    if (tmp->ref_count &&
411
        ! my_strnncoll(files_charset_info,
412
                       (const uchar *)dl->str, dl->length,
413
                       (const uchar *)tmp->dl.str, tmp->dl.length))
414
    {
415
      /* Do not remove this element, unless no other plugin uses this dll. */
416
      if (! --tmp->ref_count)
417
      {
418
        free_plugin_mem(tmp);
419
        bzero(tmp, sizeof(struct st_plugin_dl));
420
      }
421
      break;
422
    }
423
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
424
  return;
1 by brian
clean slate
425
}
426
427
428
static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
429
{
430
  uint i;
431
  if (! initialized)
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
432
    return(0);
1 by brian
clean slate
433
434
  if (type == MYSQL_ANY_PLUGIN)
435
  {
436
    for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
437
    {
438
      struct st_plugin_int *plugin= (st_plugin_int *)
439
        hash_search(&plugin_hash[i], (const uchar *)name->str, name->length);
440
      if (plugin)
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
441
        return(plugin);
1 by brian
clean slate
442
    }
443
  }
444
  else
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
445
    return((st_plugin_int *)
1 by brian
clean slate
446
        hash_search(&plugin_hash[type], (const uchar *)name->str, name->length));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
447
  return(0);
1 by brian
clean slate
448
}
449
450
451
static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
452
{
453
  SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
454
  struct st_plugin_int *plugin;
455
  if ((plugin= plugin_find_internal(name, type)))
456
  {
457
    rc= SHOW_OPTION_DISABLED;
458
    if (plugin->state == PLUGIN_IS_READY)
459
      rc= SHOW_OPTION_YES;
460
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
461
  return(rc);
1 by brian
clean slate
462
}
463
464
465
bool plugin_is_ready(const LEX_STRING *name, int type)
466
{
163 by Brian Aker
Merge Monty's code.
467
  bool rc= false;
1 by brian
clean slate
468
  if (plugin_status(name, type) == SHOW_OPTION_YES)
163 by Brian Aker
Merge Monty's code.
469
    rc= true;
1 by brian
clean slate
470
  return rc;
471
}
472
473
474
SHOW_COMP_OPTION sys_var_have_plugin::get_option()
475
{
476
  LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len };
477
  return plugin_status(&plugin_name, plugin_type);
478
}
479
480
481
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
482
{
483
  st_plugin_int *pi= plugin_ref_to_int(rc);
484
485
  if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
486
  {
487
    plugin_ref plugin;
488
    /*
489
      For debugging, we do an additional malloc which allows the
490
      memory manager and/or valgrind to track locked references and
491
      double unlocks to aid resolving reference counting.problems.
492
    */
493
    if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
494
      return(NULL);
1 by brian
clean slate
495
496
    *plugin= pi;
497
    pi->ref_count++;
498
499
    if (lex)
500
      insert_dynamic(&lex->plugins, (uchar*)&plugin);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
501
    return(plugin);
1 by brian
clean slate
502
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
503
  return(NULL);
1 by brian
clean slate
504
}
505
506
507
plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
508
{
509
  LEX *lex= thd ? thd->lex : 0;
510
  plugin_ref rc;
511
  rc= my_intern_plugin_lock_ci(lex, *ptr);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
512
  return(rc);
1 by brian
clean slate
513
}
514
515
516
plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type
517
                               CALLER_INFO_PROTO)
518
{
519
  LEX *lex= thd ? thd->lex : 0;
520
  plugin_ref rc= NULL;
521
  st_plugin_int *plugin;
522
  if ((plugin= plugin_find_internal(name, type)))
523
    rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
524
  return(rc);
1 by brian
clean slate
525
}
526
527
528
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
529
{
530
  uint i;
531
  struct st_plugin_int *tmp;
532
  for (i= 0; i < plugin_array.elements; i++)
533
  {
534
    tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
535
    if (tmp->state == PLUGIN_IS_FREED)
536
    {
537
      memcpy(tmp, plugin, sizeof(struct st_plugin_int));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
538
      return(tmp);
1 by brian
clean slate
539
    }
540
  }
541
  if (insert_dynamic(&plugin_array, (uchar*)&plugin))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
542
    return(0);
1 by brian
clean slate
543
  tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
544
                        struct st_plugin_int **)=
545
       (struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)plugin,
546
                                            sizeof(struct st_plugin_int));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
547
  return(tmp);
1 by brian
clean slate
548
}
549
550
551
/*
552
  NOTE
553
    Requires that a write-lock is held on LOCK_system_variables_hash
554
*/
555
static bool plugin_add(MEM_ROOT *tmp_root,
556
                       const LEX_STRING *name, const LEX_STRING *dl,
557
                       int *argc, char **argv, int report)
558
{
559
  struct st_plugin_int tmp;
560
  struct st_mysql_plugin *plugin;
561
  if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
562
  {
563
    if (report & REPORT_TO_USER)
564
      my_error(ER_UDF_EXISTS, MYF(0), name->str);
565
    if (report & REPORT_TO_LOG)
566
      sql_print_error(ER(ER_UDF_EXISTS), name->str);
163 by Brian Aker
Merge Monty's code.
567
    return(true);
1 by brian
clean slate
568
  }
569
  /* Clear the whole struct to catch future extensions. */
570
  bzero((char*) &tmp, sizeof(tmp));
571
  if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
163 by Brian Aker
Merge Monty's code.
572
    return(true);
1 by brian
clean slate
573
  /* Find plugin by name */
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
574
  for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
1 by brian
clean slate
575
  {
576
    uint name_len= strlen(plugin->name);
577
    if (plugin->type >= 0 && plugin->type < MYSQL_MAX_PLUGIN_TYPE_NUM &&
578
        ! my_strnncoll(system_charset_info,
579
                       (const uchar *)name->str, name->length,
580
                       (const uchar *)plugin->name,
581
                       name_len))
582
    {
583
      struct st_plugin_int *tmp_plugin_ptr;
177.4.1 by mark
remove some useless version checking code from sql_plugin.cc
584
1 by brian
clean slate
585
      tmp.plugin= plugin;
586
      tmp.name.str= (char *)plugin->name;
587
      tmp.name.length= name_len;
588
      tmp.ref_count= 0;
589
      tmp.state= PLUGIN_IS_UNINITIALIZED;
135 by Brian Aker
Random cleanup. Dead partition tests, pass operator in sql_plugin, mtr based
590
      if (!test_plugin_options(tmp_root, &tmp, argc, argv))
1 by brian
clean slate
591
      {
592
        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
593
        {
594
          plugin_array_version++;
595
          if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
596
          {
597
            init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
163 by Brian Aker
Merge Monty's code.
598
            return(false);
1 by brian
clean slate
599
          }
600
          tmp_plugin_ptr->state= PLUGIN_IS_FREED;
601
        }
602
        mysql_del_sys_var_chain(tmp.system_vars);
603
        goto err;
604
      }
605
      /* plugin was disabled */
606
      plugin_dl_del(dl);
163 by Brian Aker
Merge Monty's code.
607
      return(false);
1 by brian
clean slate
608
    }
609
  }
610
  if (report & REPORT_TO_USER)
611
    my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
612
  if (report & REPORT_TO_LOG)
613
    sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
614
err:
615
  plugin_dl_del(dl);
163 by Brian Aker
Merge Monty's code.
616
  return(true);
1 by brian
clean slate
617
}
618
619
620
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
621
{
622
  if (plugin->plugin->status_vars)
623
  {
624
#ifdef FIX_LATER
625
    /*
626
      We have a problem right now where we can not prepend without
627
      breaking backwards compatibility. We will fix this shortly so
628
      that engines have "use names" and we wil use those for
629
      CREATE TABLE, and use the plugin name then for adding automatic
630
      variable names.
631
    */
632
    SHOW_VAR array[2]= {
633
      {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
634
      {0, 0, SHOW_UNDEF}
635
    };
636
    remove_status_vars(array);
637
#else
638
    remove_status_vars(plugin->plugin->status_vars);
639
#endif /* FIX_LATER */
640
  }
641
642
  if (plugin_type_deinitialize[plugin->plugin->type])
643
  {
644
    if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
645
    {
646
      sql_print_error("Plugin '%s' of type %s failed deinitialization",
647
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
648
    }
649
  }
650
  else if (plugin->plugin->deinit)
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
651
    plugin->plugin->deinit(plugin);
652
1 by brian
clean slate
653
  plugin->state= PLUGIN_IS_UNINITIALIZED;
654
655
  /*
656
    We do the check here because NDB has a worker THD which doesn't
657
    exit until NDB is shut down.
658
  */
659
  if (ref_check && plugin->ref_count)
660
    sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
661
                    plugin->name.str, plugin->ref_count);
662
}
663
664
665
static void plugin_del(struct st_plugin_int *plugin)
666
{
667
  /* Free allocated strings before deleting the plugin. */
668
  plugin_vars_free_values(plugin->system_vars);
669
  hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
670
  if (plugin->plugin_dl)
671
    plugin_dl_del(&plugin->plugin_dl->dl);
672
  plugin->state= PLUGIN_IS_FREED;
673
  plugin_array_version++;
674
  rw_wrlock(&LOCK_system_variables_hash);
675
  mysql_del_sys_var_chain(plugin->system_vars);
676
  rw_unlock(&LOCK_system_variables_hash);
677
  free_root(&plugin->mem_root, MYF(0));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
678
  return;
1 by brian
clean slate
679
}
680
681
static void reap_plugins(void)
682
{
683
  uint count, idx;
684
  struct st_plugin_int *plugin, **reap, **list;
685
686
  if (!reap_needed)
687
    return;
688
689
  reap_needed= false;
690
  count= plugin_array.elements;
691
  reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
692
  *(reap++)= NULL;
693
694
  for (idx= 0; idx < count; idx++)
695
  {
696
    plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
697
    if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
698
    {
699
      /* change the status flag to prevent reaping by another thread */
700
      plugin->state= PLUGIN_IS_DYING;
701
      *(reap++)= plugin;
702
    }
703
  }
704
705
  list= reap;
706
  while ((plugin= *(--list)))
707
    plugin_deinitialize(plugin, true);
708
709
  while ((plugin= *(--reap)))
710
    plugin_del(plugin);
711
712
  my_afree(reap);
713
}
714
715
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
716
{
717
  int i;
718
  st_plugin_int *pi;
719
720
  if (!plugin)
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
721
    return;
1 by brian
clean slate
722
723
  pi= plugin_ref_to_int(plugin);
724
725
  my_free((uchar*) plugin, MYF(MY_WME));
726
727
  if (lex)
728
  {
729
    /*
730
      Remove one instance of this plugin from the use list.
731
      We are searching backwards so that plugins locked last
732
      could be unlocked faster - optimizing for LIFO semantics.
733
    */
734
    for (i= lex->plugins.elements - 1; i >= 0; i--)
735
      if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
736
      {
737
        delete_dynamic_element(&lex->plugins, i);
738
        break;
739
      }
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
740
    assert(i >= 0);
1 by brian
clean slate
741
  }
742
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
743
  assert(pi->ref_count);
1 by brian
clean slate
744
  pi->ref_count--;
745
746
  if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
747
    reap_needed= true;
748
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
749
  return;
1 by brian
clean slate
750
}
751
752
753
void plugin_unlock(THD *thd, plugin_ref plugin)
754
{
755
  LEX *lex= thd ? thd->lex : 0;
756
  if (!plugin)
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
757
    return;
1 by brian
clean slate
758
  intern_plugin_unlock(lex, plugin);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
759
  return;
1 by brian
clean slate
760
}
761
762
763
void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
764
{
765
  LEX *lex= thd ? thd->lex : 0;
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
766
  assert(list);
1 by brian
clean slate
767
  while (count--)
768
    intern_plugin_unlock(lex, *list++);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
769
  return;
1 by brian
clean slate
770
}
771
772
773
static int plugin_initialize(struct st_plugin_int *plugin)
774
{
775
776
  if (plugin_type_initialize[plugin->plugin->type])
777
  {
778
    if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
779
    {
780
      sql_print_error("Plugin '%s' registration as a %s failed.",
781
                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
782
      goto err;
783
    }
784
  }
785
  else if (plugin->plugin->init)
786
  {
787
    if (plugin->plugin->init(plugin))
788
    {
789
      sql_print_error("Plugin '%s' init function returned error.",
790
                      plugin->name.str);
791
      goto err;
792
    }
793
  }
794
795
  plugin->state= PLUGIN_IS_READY;
796
797
  if (plugin->plugin->status_vars)
798
  {
799
#ifdef FIX_LATER
800
    /*
801
      We have a problem right now where we can not prepend without
802
      breaking backwards compatibility. We will fix this shortly so
803
      that engines have "use names" and we wil use those for
804
      CREATE TABLE, and use the plugin name then for adding automatic
805
      variable names.
806
    */
807
    SHOW_VAR array[2]= {
808
      {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
809
      {0, 0, SHOW_UNDEF}
810
    };
811
    if (add_status_vars(array)) // add_status_vars makes a copy
812
      goto err;
813
#else
814
    add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
815
#endif /* FIX_LATER */
816
  }
817
818
  /*
819
    set the plugin attribute of plugin's sys vars so they are pointing
820
    to the active plugin
821
  */
822
  if (plugin->system_vars)
823
  {
824
    sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
825
    for (;;)
826
    {
827
      var->plugin= plugin;
828
      if (!var->next)
829
        break;
830
      var= var->next->cast_pluginvar();
831
    }
832
  }
833
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
834
  return(0);
1 by brian
clean slate
835
err:
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
836
  return(1);
1 by brian
clean slate
837
}
838
839
146 by Brian Aker
my_bool cleanup.
840
extern "C" uchar *get_plugin_hash_key(const uchar *, size_t *, bool);
841
extern "C" uchar *get_bookmark_hash_key(const uchar *, size_t *, bool);
1 by brian
clean slate
842
843
844
uchar *get_plugin_hash_key(const uchar *buff, size_t *length,
146 by Brian Aker
my_bool cleanup.
845
                           bool not_used __attribute__((unused)))
1 by brian
clean slate
846
{
847
  struct st_plugin_int *plugin= (st_plugin_int *)buff;
848
  *length= (uint)plugin->name.length;
849
  return((uchar *)plugin->name.str);
850
}
851
852
853
uchar *get_bookmark_hash_key(const uchar *buff, size_t *length,
146 by Brian Aker
my_bool cleanup.
854
                             bool not_used __attribute__((unused)))
1 by brian
clean slate
855
{
856
  struct st_bookmark *var= (st_bookmark *)buff;
857
  *length= var->name_len + 1;
858
  return (uchar*) var->key;
859
}
860
861
862
/*
863
  The logic is that we first load and initialize all compiled in plugins.
864
  From there we load up the dynamic types (assuming we have not been told to
865
  skip this part).
866
867
  Finally we initialize everything, aka the dynamic that have yet to initialize.
868
*/
869
int plugin_init(int *argc, char **argv, int flags)
870
{
871
  uint i;
872
  struct st_mysql_plugin **builtins;
873
  struct st_mysql_plugin *plugin;
874
  struct st_plugin_int tmp, *plugin_ptr, **reap;
875
  MEM_ROOT tmp_root;
876
877
  if (initialized)
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
878
    return(0);
1 by brian
clean slate
879
880
  init_alloc_root(&plugin_mem_root, 4096, 4096);
881
  init_alloc_root(&tmp_root, 4096, 4096);
882
883
  if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
884
                  get_bookmark_hash_key, NULL, HASH_UNIQUE))
885
      goto err;
886
887
888
  if (my_init_dynamic_array(&plugin_dl_array,
889
                            sizeof(struct st_plugin_dl *),16,16) ||
890
      my_init_dynamic_array(&plugin_array,
891
                            sizeof(struct st_plugin_int *),16,16))
892
    goto err;
893
894
  for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
895
  {
896
    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
897
                  get_plugin_hash_key, NULL, HASH_UNIQUE))
898
      goto err;
899
  }
900
901
  initialized= 1;
902
903
  /*
904
    First we register builtin plugins
905
  */
906
  for (builtins= mysqld_builtins; *builtins; builtins++)
907
  {
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
908
    for (plugin= *builtins; plugin->name; plugin++)
1 by brian
clean slate
909
    {
910
      bzero(&tmp, sizeof(tmp));
911
      tmp.plugin= plugin;
912
      tmp.name.str= (char *)plugin->name;
913
      tmp.name.length= strlen(plugin->name);
914
915
      free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
135 by Brian Aker
Random cleanup. Dead partition tests, pass operator in sql_plugin, mtr based
916
      if (test_plugin_options(&tmp_root, &tmp, argc, argv))
1 by brian
clean slate
917
        continue;
918
919
      if (register_builtin(plugin, &tmp, &plugin_ptr))
920
        goto err_unlock;
921
922
      if (plugin_initialize(plugin_ptr))
923
        goto err_unlock;
924
925
      /*
926
        initialize the global default storage engine so that it may
927
        not be null in any child thread.
928
      */
136 by Brian Aker
Removed loop bit that created a specialize startup for MyISAM for no longer
929
      if (my_strcasecmp(&my_charset_latin1, plugin->name, "MyISAM") == 0)
1 by brian
clean slate
930
      {
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
931
        assert(!global_system_variables.table_plugin);
1 by brian
clean slate
932
        global_system_variables.table_plugin=
933
          my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
934
        assert(plugin_ptr->ref_count == 1);
1 by brian
clean slate
935
      }
936
    }
937
  }
938
939
  /* should now be set to MyISAM storage engine */
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
940
  assert(global_system_variables.table_plugin);
1 by brian
clean slate
941
942
  /* Register all dynamic plugins */
943
  if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
944
  {
945
    if (opt_plugin_load)
946
      plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
947
  }
948
949
  if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
950
    goto end;
951
952
  /*
953
    Now we initialize all remaining plugins
954
  */
955
956
  reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
957
  *(reap++)= NULL;
958
959
  for (i= 0; i < plugin_array.elements; i++)
960
  {
961
    plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
962
    if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
963
    {
964
      if (plugin_initialize(plugin_ptr))
965
      {
966
        plugin_ptr->state= PLUGIN_IS_DYING;
967
        *(reap++)= plugin_ptr;
968
      }
969
    }
970
  }
971
972
  /*
973
    Check if any plugins have to be reaped
974
  */
975
  while ((plugin_ptr= *(--reap)))
976
  {
977
    plugin_deinitialize(plugin_ptr, true);
978
    plugin_del(plugin_ptr);
979
  }
980
981
  my_afree(reap);
982
983
end:
984
  free_root(&tmp_root, MYF(0));
985
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
986
  return(0);
1 by brian
clean slate
987
988
err_unlock:
989
err:
990
  free_root(&tmp_root, MYF(0));
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
991
  return(1);
1 by brian
clean slate
992
}
993
994
995
static bool register_builtin(struct st_mysql_plugin *plugin,
996
                             struct st_plugin_int *tmp,
997
                             struct st_plugin_int **ptr)
998
{
999
1000
  tmp->state= PLUGIN_IS_UNINITIALIZED;
1001
  tmp->ref_count= 0;
1002
  tmp->plugin_dl= 0;
1003
1004
  if (insert_dynamic(&plugin_array, (uchar*)&tmp))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1005
    return(1);
1 by brian
clean slate
1006
1007
  *ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
1008
                         struct st_plugin_int **)=
1009
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)tmp,
1010
                                             sizeof(struct st_plugin_int));
1011
1012
  if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1013
    return(1);
1 by brian
clean slate
1014
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1015
  return(0);
1 by brian
clean slate
1016
}
1017
1018
1019
/*
1020
  called only by plugin_init()
1021
*/
1022
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
1023
                             const char *list)
1024
{
1025
  char buffer[FN_REFLEN];
1026
  LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
1027
  struct st_plugin_dl *plugin_dl;
1028
  struct st_mysql_plugin *plugin;
1029
  char *p= buffer;
1030
  while (list)
1031
  {
1032
    if (p == buffer + sizeof(buffer) - 1)
1033
    {
1034
      sql_print_error("plugin-load parameter too long");
163 by Brian Aker
Merge Monty's code.
1035
      return(true);
1 by brian
clean slate
1036
    }
1037
1038
    switch ((*(p++)= *(list++))) {
1039
    case '\0':
1040
      list= NULL; /* terminate the loop */
1041
      /* fall through */
1042
    case ':':     /* can't use this as delimiter as it may be drive letter */
1043
    case ';':
1044
      str->str[str->length]= '\0';
1045
      if (str == &name)  // load all plugins in named module
1046
      {
1047
        if (!name.length)
1048
        {
1049
          p--;    /* reset pointer */
1050
          continue;
1051
        }
1052
1053
        dl= name;
1054
        if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
1055
        {
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
1056
          for (plugin= plugin_dl->plugins; plugin->name; plugin++)
1 by brian
clean slate
1057
          {
1058
            name.str= (char *) plugin->name;
1059
            name.length= strlen(name.str);
1060
1061
            free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1062
            if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1063
              goto error;
1064
          }
1065
          plugin_dl_del(&dl); // reduce ref count
1066
        }
1067
      }
1068
      else
1069
      {
1070
        free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
1071
        if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
1072
          goto error;
1073
      }
1074
      name.length= dl.length= 0;
1075
      dl.str= NULL; name.str= p= buffer;
1076
      str= &name;
1077
      continue;
1078
    case '=':
1079
    case '#':
1080
      if (str == &name)
1081
      {
1082
        name.str[name.length]= '\0';
1083
        str= &dl;
1084
        str->str= p;
1085
        continue;
1086
      }
1087
    default:
1088
      str->length++;
1089
      continue;
1090
    }
1091
  }
163 by Brian Aker
Merge Monty's code.
1092
  return(false);
1 by brian
clean slate
1093
error:
1094
  sql_print_error("Couldn't load plugin named '%s' with soname '%s'.",
1095
                  name.str, dl.str);
163 by Brian Aker
Merge Monty's code.
1096
  return(true);
1 by brian
clean slate
1097
}
1098
1099
1100
void plugin_shutdown(void)
1101
{
1102
  uint i, count= plugin_array.elements, free_slots= 0;
1103
  struct st_plugin_int **plugins, *plugin;
1104
  struct st_plugin_dl **dl;
1105
1106
  if (initialized)
1107
  {
1108
    reap_needed= true;
1109
1110
    /*
1111
      We want to shut down plugins in a reasonable order, this will
1112
      become important when we have plugins which depend upon each other.
1113
      Circular references cannot be reaped so they are forced afterwards.
1114
      TODO: Have an additional step here to notify all active plugins that
1115
      shutdown is requested to allow plugins to deinitialize in parallel.
1116
    */
1117
    while (reap_needed && (count= plugin_array.elements))
1118
    {
1119
      reap_plugins();
1120
      for (i= free_slots= 0; i < count; i++)
1121
      {
1122
        plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1123
        switch (plugin->state) {
1124
        case PLUGIN_IS_READY:
1125
          plugin->state= PLUGIN_IS_DELETED;
1126
          reap_needed= true;
1127
          break;
1128
        case PLUGIN_IS_FREED:
1129
        case PLUGIN_IS_UNINITIALIZED:
1130
          free_slots++;
1131
          break;
1132
        }
1133
      }
1134
      if (!reap_needed)
1135
      {
1136
        /*
1137
          release any plugin references held.
1138
        */
1139
        unlock_variables(NULL, &global_system_variables);
1140
        unlock_variables(NULL, &max_system_variables);
1141
      }
1142
    }
1143
1144
    if (count > free_slots)
1145
      sql_print_warning("Forcing shutdown of %d plugins", count - free_slots);
1146
1147
    plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
1148
1149
    /*
1150
      If we have any plugins which did not die cleanly, we force shutdown
1151
    */
1152
    for (i= 0; i < count; i++)
1153
    {
1154
      plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
1155
      /* change the state to ensure no reaping races */
1156
      if (plugins[i]->state == PLUGIN_IS_DELETED)
1157
        plugins[i]->state= PLUGIN_IS_DYING;
1158
    }
1159
1160
    /*
1161
      We loop through all plugins and call deinit() if they have one.
1162
    */
1163
    for (i= 0; i < count; i++)
1164
      if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
1165
      {
1166
        sql_print_information("Plugin '%s' will be forced to shutdown",
1167
                              plugins[i]->name.str);
1168
        /*
1169
          We are forcing deinit on plugins so we don't want to do a ref_count
1170
          check until we have processed all the plugins.
1171
        */
1172
        plugin_deinitialize(plugins[i], false);
1173
      }
1174
1175
    /*
1176
      We defer checking ref_counts until after all plugins are deinitialized
1177
      as some may have worker threads holding on to plugin references.
1178
    */
1179
    for (i= 0; i < count; i++)
1180
    {
1181
      if (plugins[i]->ref_count)
1182
        sql_print_error("Plugin '%s' has ref_count=%d after shutdown.",
1183
                        plugins[i]->name.str, plugins[i]->ref_count);
1184
      if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
1185
        plugin_del(plugins[i]);
1186
    }
1187
1188
    /*
1189
      Now we can deallocate all memory.
1190
    */
1191
1192
    cleanup_variables(NULL, &global_system_variables);
1193
    cleanup_variables(NULL, &max_system_variables);
1194
1195
    initialized= 0;
1196
1197
    my_afree(plugins);
1198
  }
1199
1200
  /* Dispose of the memory */
1201
1202
  for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
1203
    hash_free(&plugin_hash[i]);
1204
  delete_dynamic(&plugin_array);
1205
1206
  count= plugin_dl_array.elements;
1207
  dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
1208
  for (i= 0; i < count; i++)
1209
    dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
1210
  for (i= 0; i < plugin_dl_array.elements; i++)
1211
    free_plugin_mem(dl[i]);
1212
  my_afree(dl);
1213
  delete_dynamic(&plugin_dl_array);
1214
1215
  hash_free(&bookmark_hash);
1216
  free_root(&plugin_mem_root, MYF(0));
1217
1218
  global_variables_dynamic_size= 0;
1219
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1220
  return;
1 by brian
clean slate
1221
}
1222
1223
1224
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
1225
                       int type, uint state_mask, void *arg)
1226
{
1227
  uint idx, total;
1228
  struct st_plugin_int *plugin, **plugins;
1229
  int version=plugin_array_version;
1230
1231
  if (!initialized)
163 by Brian Aker
Merge Monty's code.
1232
    return(false);
1 by brian
clean slate
1233
1234
  state_mask= ~state_mask; // do it only once
1235
1236
  total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements
1237
                                  : plugin_hash[type].records;
1238
  /*
1239
    Do the alloca out here in case we do have a working alloca:
1240
        leaving the nested stack frame invalidates alloca allocation.
1241
  */
1242
  plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
1243
  if (type == MYSQL_ANY_PLUGIN)
1244
  {
1245
    for (idx= 0; idx < total; idx++)
1246
    {
1247
      plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
1248
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1249
    }
1250
  }
1251
  else
1252
  {
1253
    HASH *hash= plugin_hash + type;
1254
    for (idx= 0; idx < total; idx++)
1255
    {
1256
      plugin= (struct st_plugin_int *) hash_element(hash, idx);
1257
      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
1258
    }
1259
  }
1260
  for (idx= 0; idx < total; idx++)
1261
  {
1262
    if (unlikely(version != plugin_array_version))
1263
    {
1264
      for (uint i=idx; i < total; i++)
1265
        if (plugins[i] && plugins[i]->state & state_mask)
1266
          plugins[i]=0;
1267
    }
1268
    plugin= plugins[idx];
163 by Brian Aker
Merge Monty's code.
1269
    /* It will stop iterating on first engine error when "func" returns true */
1 by brian
clean slate
1270
    if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
1271
        goto err;
1272
  }
1273
1274
  my_afree(plugins);
163 by Brian Aker
Merge Monty's code.
1275
  return(false);
1 by brian
clean slate
1276
err:
1277
  my_afree(plugins);
163 by Brian Aker
Merge Monty's code.
1278
  return(true);
1 by brian
clean slate
1279
}
1280
1281
1282
/****************************************************************************
1283
  Internal type declarations for variables support
1284
****************************************************************************/
1285
1286
#undef MYSQL_SYSVAR_NAME
1287
#define MYSQL_SYSVAR_NAME(name) name
1288
#define PLUGIN_VAR_TYPEMASK 0x007f
1289
1290
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
1291
153 by Brian Aker
Merging Monty's code, I did remove error on compile though (since it does
1292
typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_bool_t, bool);
1293
typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_bool_t, bool);
1 by brian
clean slate
1294
typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_str_t, char *);
1295
typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_str_t, char *);
1296
1297
typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
1298
typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_enum_t, unsigned long);
151 by Brian Aker
Ulonglong to uint64_t
1299
typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
1300
typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_set_t, uint64_t);
1 by brian
clean slate
1301
1302
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_int_t, int);
1303
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_long_t, long);
152 by Brian Aker
longlong replacement
1304
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
1 by brian
clean slate
1305
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint_t, uint);
1306
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
151 by Brian Aker
Ulonglong to uint64_t
1307
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
1 by brian
clean slate
1308
1309
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int_t, int);
1310
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_long_t, long);
152 by Brian Aker
longlong replacement
1311
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int64_t_t, int64_t);
1 by brian
clean slate
1312
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint);
1313
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
151 by Brian Aker
Ulonglong to uint64_t
1314
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint64_t_t, uint64_t);
1 by brian
clean slate
1315
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
1316
typedef bool *(*mysql_sys_var_ptr_p)(THD* a_thd, int offset);
1 by brian
clean slate
1317
1318
1319
/****************************************************************************
1320
  default variable data check and update functions
1321
****************************************************************************/
1322
77.1.46 by Monty Taylor
Finished the warnings work!
1323
static int check_func_bool(THD *thd __attribute__((__unused__)),
1324
                           struct st_mysql_sys_var *var,
1 by brian
clean slate
1325
                           void *save, st_mysql_value *value)
1326
{
1327
  char buff[STRING_BUFFER_USUAL_SIZE];
1328
  const char *strvalue= "NULL", *str;
1329
  int result, length;
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1330
  int64_t tmp;
1 by brian
clean slate
1331
1332
  if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
1333
  {
1334
    length= sizeof(buff);
1335
    if (!(str= value->val_str(value, buff, &length)) ||
1336
        (result= find_type(&bool_typelib, str, length, 1)-1) < 0)
1337
    {
1338
      if (str)
1339
        strvalue= str;
1340
      goto err;
1341
    }
1342
  }
1343
  else
1344
  {
1345
    if (value->val_int(value, &tmp) < 0)
1346
      goto err;
1347
    if (tmp > 1)
1348
    {
1349
      llstr(tmp, buff);
1350
      strvalue= buff;
1351
      goto err;
1352
    }
1353
    result= (int) tmp;
1354
  }
1355
  *(int*)save= -result;
1356
  return 0;
1357
err:
1358
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1359
  return 1;
1360
}
1361
1362
1363
static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
1364
                          void *save, st_mysql_value *value)
1365
{
143 by Brian Aker
Bool cleanup.
1366
  bool fixed;
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1367
  int64_t tmp;
1 by brian
clean slate
1368
  struct my_option options;
1369
  value->val_int(value, &tmp);
1370
  plugin_opt_set_limits(&options, var);
1371
1372
  if (var->flags & PLUGIN_VAR_UNSIGNED)
151 by Brian Aker
Ulonglong to uint64_t
1373
    *(uint *)save= (uint) getopt_ull_limit_value((uint64_t) tmp, &options,
1 by brian
clean slate
1374
                                                   &fixed);
1375
  else
1376
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
1377
1378
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
152 by Brian Aker
longlong replacement
1379
                              var->name, (int64_t) tmp);
1 by brian
clean slate
1380
}
1381
1382
1383
static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
1384
                          void *save, st_mysql_value *value)
1385
{
143 by Brian Aker
Bool cleanup.
1386
  bool fixed;
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1387
  int64_t tmp;
1 by brian
clean slate
1388
  struct my_option options;
1389
  value->val_int(value, &tmp);
1390
  plugin_opt_set_limits(&options, var);
1391
1392
  if (var->flags & PLUGIN_VAR_UNSIGNED)
151 by Brian Aker
Ulonglong to uint64_t
1393
    *(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
1 by brian
clean slate
1394
                                                   &fixed);
1395
  else
1396
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
1397
1398
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
152 by Brian Aker
longlong replacement
1399
                              var->name, (int64_t) tmp);
1 by brian
clean slate
1400
}
1401
1402
152 by Brian Aker
longlong replacement
1403
static int check_func_int64_t(THD *thd, struct st_mysql_sys_var *var,
1 by brian
clean slate
1404
                               void *save, st_mysql_value *value)
1405
{
143 by Brian Aker
Bool cleanup.
1406
  bool fixed;
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1407
  int64_t tmp;
1 by brian
clean slate
1408
  struct my_option options;
1409
  value->val_int(value, &tmp);
1410
  plugin_opt_set_limits(&options, var);
1411
1412
  if (var->flags & PLUGIN_VAR_UNSIGNED)
151 by Brian Aker
Ulonglong to uint64_t
1413
    *(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
1 by brian
clean slate
1414
                                               &fixed);
1415
  else
152 by Brian Aker
longlong replacement
1416
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
1 by brian
clean slate
1417
1418
  return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
152 by Brian Aker
longlong replacement
1419
                              var->name, (int64_t) tmp);
1 by brian
clean slate
1420
}
1421
77.1.46 by Monty Taylor
Finished the warnings work!
1422
static int check_func_str(THD *thd,
1423
                          struct st_mysql_sys_var *var __attribute__((__unused__)),
1 by brian
clean slate
1424
                          void *save, st_mysql_value *value)
1425
{
1426
  char buff[STRING_BUFFER_USUAL_SIZE];
1427
  const char *str;
1428
  int length;
1429
1430
  length= sizeof(buff);
1431
  if ((str= value->val_str(value, buff, &length)))
1432
    str= thd->strmake(str, length);
1433
  *(const char**)save= str;
1434
  return 0;
1435
}
1436
1437
77.1.46 by Monty Taylor
Finished the warnings work!
1438
static int check_func_enum(THD *thd __attribute__((__unused__)),
1439
                           struct st_mysql_sys_var *var,
1 by brian
clean slate
1440
                           void *save, st_mysql_value *value)
1441
{
1442
  char buff[STRING_BUFFER_USUAL_SIZE];
1443
  const char *strvalue= "NULL", *str;
1444
  TYPELIB *typelib;
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1445
  int64_t tmp;
1 by brian
clean slate
1446
  long result;
1447
  int length;
1448
1449
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1450
    typelib= ((thdvar_enum_t*) var)->typelib;
1451
  else
1452
    typelib= ((sysvar_enum_t*) var)->typelib;
1453
1454
  if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
1455
  {
1456
    length= sizeof(buff);
1457
    if (!(str= value->val_str(value, buff, &length)))
1458
      goto err;
1459
    if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
1460
    {
1461
      strvalue= str;
1462
      goto err;
1463
    }
1464
  }
1465
  else
1466
  {
1467
    if (value->val_int(value, &tmp))
1468
      goto err;
1469
    if (tmp >= typelib->count)
1470
    {
1471
      llstr(tmp, buff);
1472
      strvalue= buff;
1473
      goto err;
1474
    }
1475
    result= (long) tmp;
1476
  }
1477
  *(long*)save= result;
1478
  return 0;
1479
err:
1480
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1481
  return 1;
1482
}
1483
1484
77.1.46 by Monty Taylor
Finished the warnings work!
1485
static int check_func_set(THD *thd __attribute__((__unused__)),
1486
                          struct st_mysql_sys_var *var,
1 by brian
clean slate
1487
                          void *save, st_mysql_value *value)
1488
{
1489
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
1490
  const char *strvalue= "NULL", *str;
1491
  TYPELIB *typelib;
151 by Brian Aker
Ulonglong to uint64_t
1492
  uint64_t result;
1 by brian
clean slate
1493
  uint error_len;
1494
  bool not_used;
1495
  int length;
1496
1497
  if (var->flags & PLUGIN_VAR_THDLOCAL)
1498
    typelib= ((thdvar_set_t*) var)->typelib;
1499
  else
1500
    typelib= ((sysvar_set_t*)var)->typelib;
1501
1502
  if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
1503
  {
1504
    length= sizeof(buff);
1505
    if (!(str= value->val_str(value, buff, &length)))
1506
      goto err;
1507
    result= find_set(typelib, str, length, NULL,
1508
                     &error, &error_len, &not_used);
1509
    if (error_len)
1510
    {
1511
      strmake(buff, error, min(sizeof(buff), error_len));
1512
      strvalue= buff;
1513
      goto err;
1514
    }
1515
  }
1516
  else
1517
  {
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1518
    if (value->val_int(value, (int64_t *)&result))
1 by brian
clean slate
1519
      goto err;
80.1.1 by Brian Aker
LL() cleanup
1520
    if (unlikely((result >= (1ULL << typelib->count)) &&
1 by brian
clean slate
1521
                 (typelib->count < sizeof(long)*8)))
1522
    {
1523
      llstr(result, buff);
1524
      strvalue= buff;
1525
      goto err;
1526
    }
1527
  }
151 by Brian Aker
Ulonglong to uint64_t
1528
  *(uint64_t*)save= result;
1 by brian
clean slate
1529
  return 0;
1530
err:
1531
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
1532
  return 1;
1533
}
1534
1535
77.1.46 by Monty Taylor
Finished the warnings work!
1536
static void update_func_bool(THD *thd __attribute__((__unused__)),
1537
                             struct st_mysql_sys_var *var __attribute__((__unused__)),
1 by brian
clean slate
1538
                             void *tgt, const void *save)
1539
{
199 by Brian Aker
my_bool...
1540
  *(bool *) tgt= *(int *) save ? 1 : 0;
1 by brian
clean slate
1541
}
1542
1543
77.1.46 by Monty Taylor
Finished the warnings work!
1544
static void update_func_int(THD *thd __attribute__((__unused__)),
1545
                            struct st_mysql_sys_var *var __attribute__((__unused__)),
1 by brian
clean slate
1546
                             void *tgt, const void *save)
1547
{
1548
  *(int *)tgt= *(int *) save;
1549
}
1550
1551
77.1.46 by Monty Taylor
Finished the warnings work!
1552
static void update_func_long(THD *thd __attribute__((__unused__)),
1553
                             struct st_mysql_sys_var *var __attribute__((__unused__)),
1 by brian
clean slate
1554
                             void *tgt, const void *save)
1555
{
1556
  *(long *)tgt= *(long *) save;
1557
}
1558
1559
152 by Brian Aker
longlong replacement
1560
static void update_func_int64_t(THD *thd __attribute__((__unused__)),
77.1.46 by Monty Taylor
Finished the warnings work!
1561
                                 struct st_mysql_sys_var *var __attribute__((__unused__)),
1562
                                 void *tgt, const void *save)
1 by brian
clean slate
1563
{
152 by Brian Aker
longlong replacement
1564
  *(int64_t *)tgt= *(uint64_t *) save;
1 by brian
clean slate
1565
}
1566
1567
77.1.46 by Monty Taylor
Finished the warnings work!
1568
static void update_func_str(THD *thd __attribute__((__unused__)), struct st_mysql_sys_var *var,
1 by brian
clean slate
1569
                             void *tgt, const void *save)
1570
{
1571
  char *old= *(char **) tgt;
1572
  *(char **)tgt= *(char **) save;
1573
  if (var->flags & PLUGIN_VAR_MEMALLOC)
1574
  {
1575
    *(char **)tgt= my_strdup(*(char **) save, MYF(0));
1576
    my_free(old, MYF(0));
1577
  }
1578
}
1579
1580
1581
/****************************************************************************
1582
  System Variables support
1583
****************************************************************************/
1584
1585
1586
sys_var *find_sys_var(THD *thd, const char *str, uint length)
1587
{
1588
  sys_var *var;
1589
  sys_var_pluginvar *pi= NULL;
1590
  plugin_ref plugin;
1591
1592
  rw_rdlock(&LOCK_system_variables_hash);
1593
  if ((var= intern_find_sys_var(str, length, false)) &&
1594
      (pi= var->cast_pluginvar()))
1595
  {
1596
    rw_unlock(&LOCK_system_variables_hash);
1597
    LEX *lex= thd ? thd->lex : 0;
1598
    if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
1599
      var= NULL; /* failed to lock it, it must be uninstalling */
1600
    else
1601
    if (!(plugin_state(plugin) & PLUGIN_IS_READY))
1602
    {
1603
      /* initialization not completed */
1604
      var= NULL;
1605
      intern_plugin_unlock(lex, plugin);
1606
    }
1607
  }
1608
  else
1609
    rw_unlock(&LOCK_system_variables_hash);
1610
1611
  /*
1612
    If the variable exists but the plugin it is associated with is not ready
1613
    then the intern_plugin_lock did not raise an error, so we do it here.
1614
  */
1615
  if (pi && !var)
1616
    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1617
  return(var);
1 by brian
clean slate
1618
}
1619
1620
1621
/*
1622
  called by register_var, construct_options and test_plugin_options.
1623
  Returns the 'bookmark' for the named variable.
1624
  LOCK_system_variables_hash should be at least read locked
1625
*/
138 by Brian Aker
Refactoring around sql_plugin.
1626
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
1 by brian
clean slate
1627
{
1628
  st_bookmark *result= NULL;
1629
  uint namelen, length, pluginlen= 0;
1630
  char *varname, *p;
1631
1632
  if (!(flags & PLUGIN_VAR_THDLOCAL))
1633
    return NULL;
1634
1635
  namelen= strlen(name);
1636
  if (plugin)
1637
    pluginlen= strlen(plugin) + 1;
1638
  length= namelen + pluginlen + 2;
1639
  varname= (char*) my_alloca(length);
1640
1641
  if (plugin)
1642
  {
1643
    strxmov(varname + 1, plugin, "_", name, NullS);
1644
    for (p= varname + 1; *p; p++)
1645
      if (*p == '-')
1646
        *p= '_';
1647
  }
1648
  else
1649
    memcpy(varname + 1, name, namelen + 1);
1650
1651
  varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1652
1653
  result= (st_bookmark*) hash_search(&bookmark_hash,
1654
                                     (const uchar*) varname, length - 1);
1655
1656
  my_afree(varname);
1657
  return result;
1658
}
1659
1660
1661
/*
1662
  returns a bookmark for thd-local variables, creating if neccessary.
1663
  returns null for non thd-local variables.
1664
  Requires that a write lock is obtained on LOCK_system_variables_hash
1665
*/
1666
static st_bookmark *register_var(const char *plugin, const char *name,
1667
                                 int flags)
1668
{
1669
  uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
1670
  st_bookmark *result;
1671
  char *varname, *p;
1672
1673
  if (!(flags & PLUGIN_VAR_THDLOCAL))
1674
    return NULL;
1675
1676
  switch (flags & PLUGIN_VAR_TYPEMASK) {
1677
  case PLUGIN_VAR_BOOL:
199 by Brian Aker
my_bool...
1678
    size= sizeof(bool);
1 by brian
clean slate
1679
    break;
1680
  case PLUGIN_VAR_INT:
1681
    size= sizeof(int);
1682
    break;
1683
  case PLUGIN_VAR_LONG:
1684
  case PLUGIN_VAR_ENUM:
1685
    size= sizeof(long);
1686
    break;
1687
  case PLUGIN_VAR_LONGLONG:
1688
  case PLUGIN_VAR_SET:
151 by Brian Aker
Ulonglong to uint64_t
1689
    size= sizeof(uint64_t);
1 by brian
clean slate
1690
    break;
1691
  case PLUGIN_VAR_STR:
1692
    size= sizeof(char*);
1693
    break;
1694
  default:
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
1695
    assert(0);
1 by brian
clean slate
1696
    return NULL;
1697
  };
1698
1699
  varname= ((char*) my_alloca(length));
1700
  strxmov(varname + 1, plugin, "_", name, NullS);
1701
  for (p= varname + 1; *p; p++)
1702
    if (*p == '-')
1703
      *p= '_';
1704
1705
  if (!(result= find_bookmark(NULL, varname + 1, flags)))
1706
  {
1707
    result= (st_bookmark*) alloc_root(&plugin_mem_root,
1708
                                      sizeof(struct st_bookmark) + length-1);
1709
    varname[0]= flags & PLUGIN_VAR_TYPEMASK;
1710
    memcpy(result->key, varname, length);
1711
    result->name_len= length - 2;
1712
    result->offset= -1;
1713
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
1714
    assert(size && !(size & (size-1))); /* must be power of 2 */
1 by brian
clean slate
1715
1716
    offset= global_system_variables.dynamic_variables_size;
1717
    offset= (offset + size - 1) & ~(size - 1);
1718
    result->offset= (int) offset;
1719
1720
    new_size= (offset + size + 63) & ~63;
1721
1722
    if (new_size > global_variables_dynamic_size)
1723
    {
1724
      global_system_variables.dynamic_variables_ptr= (char*)
1725
        my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
1726
                   MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1727
      max_system_variables.dynamic_variables_ptr= (char*)
1728
        my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
1729
                   MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1730
      /*
1731
        Clear the new variable value space. This is required for string
1732
        variables. If their value is non-NULL, it must point to a valid
1733
        string.
1734
      */
1735
      bzero(global_system_variables.dynamic_variables_ptr +
1736
            global_variables_dynamic_size,
1737
            new_size - global_variables_dynamic_size);
1738
      bzero(max_system_variables.dynamic_variables_ptr +
1739
            global_variables_dynamic_size,
1740
            new_size - global_variables_dynamic_size);
1741
      global_variables_dynamic_size= new_size;
1742
    }
1743
1744
    global_system_variables.dynamic_variables_head= offset;
1745
    max_system_variables.dynamic_variables_head= offset;
1746
    global_system_variables.dynamic_variables_size= offset + size;
1747
    max_system_variables.dynamic_variables_size= offset + size;
1748
    global_system_variables.dynamic_variables_version++;
1749
    max_system_variables.dynamic_variables_version++;
1750
1751
    result->version= global_system_variables.dynamic_variables_version;
1752
1753
    /* this should succeed because we have already checked if a dup exists */
1754
    if (my_hash_insert(&bookmark_hash, (uchar*) result))
1755
    {
1756
      fprintf(stderr, "failed to add placeholder to hash");
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
1757
      assert(0);
1 by brian
clean slate
1758
    }
1759
  }
1760
  my_afree(varname);
1761
  return result;
1762
}
1763
1764
1765
/*
1766
  returns a pointer to the memory which holds the thd-local variable or
1767
  a pointer to the global variable if thd==null.
1768
  If required, will sync with global variables if the requested variable
1769
  has not yet been allocated in the current thread.
1770
*/
1771
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
1772
{
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
1773
  assert(offset >= 0);
1774
  assert((uint)offset <= global_system_variables.dynamic_variables_head);
1 by brian
clean slate
1775
1776
  if (!thd)
1777
    return (uchar*) global_system_variables.dynamic_variables_ptr + offset;
1778
1779
  /*
1780
    dynamic_variables_head points to the largest valid offset
1781
  */
1782
  if (!thd->variables.dynamic_variables_ptr ||
1783
      (uint)offset > thd->variables.dynamic_variables_head)
1784
  {
1785
    uint idx;
1786
1787
    rw_rdlock(&LOCK_system_variables_hash);
1788
1789
    thd->variables.dynamic_variables_ptr= (char*)
1790
      my_realloc(thd->variables.dynamic_variables_ptr,
1791
                 global_variables_dynamic_size,
1792
                 MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1793
1794
    if (global_lock)
1795
      pthread_mutex_lock(&LOCK_global_system_variables);
1796
1797
    safe_mutex_assert_owner(&LOCK_global_system_variables);
1798
1799
    memcpy(thd->variables.dynamic_variables_ptr +
1800
             thd->variables.dynamic_variables_size,
1801
           global_system_variables.dynamic_variables_ptr +
1802
             thd->variables.dynamic_variables_size,
1803
           global_system_variables.dynamic_variables_size -
1804
             thd->variables.dynamic_variables_size);
1805
1806
    /*
1807
      now we need to iterate through any newly copied 'defaults'
1808
      and if it is a string type with MEMALLOC flag, we need to strdup
1809
    */
1810
    for (idx= 0; idx < bookmark_hash.records; idx++)
1811
    {
1812
      sys_var_pluginvar *pi;
1813
      sys_var *var;
1814
      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
1815
1816
      if (v->version <= thd->variables.dynamic_variables_version ||
1817
          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1818
          !(pi= var->cast_pluginvar()) ||
1819
          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1820
        continue;
1821
1822
      /* Here we do anything special that may be required of the data types */
1823
1824
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1825
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
1826
      {
1827
         char **pp= (char**) (thd->variables.dynamic_variables_ptr +
1828
                             *(int*)(pi->plugin_var + 1));
1829
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
1830
                             *(int*)(pi->plugin_var + 1))))
1831
           *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
1832
      }
1833
    }
1834
1835
    if (global_lock)
1836
      pthread_mutex_unlock(&LOCK_global_system_variables);
1837
1838
    thd->variables.dynamic_variables_version=
1839
           global_system_variables.dynamic_variables_version;
1840
    thd->variables.dynamic_variables_head=
1841
           global_system_variables.dynamic_variables_head;
1842
    thd->variables.dynamic_variables_size=
1843
           global_system_variables.dynamic_variables_size;
1844
1845
    rw_unlock(&LOCK_system_variables_hash);
1846
  }
1847
  return (uchar*)thd->variables.dynamic_variables_ptr + offset;
1848
}
1849
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
1850
static bool *mysql_sys_var_ptr_bool(THD* a_thd, int offset)
1851
{
1852
  return (bool *)intern_sys_var_ptr(a_thd, offset, true);
1853
}
1854
1855
static int *mysql_sys_var_ptr_int(THD* a_thd, int offset)
1856
{
1857
  return (int *)intern_sys_var_ptr(a_thd, offset, true);
1858
}
1859
1860
static long *mysql_sys_var_ptr_long(THD* a_thd, int offset)
1861
{
1862
  return (long *)intern_sys_var_ptr(a_thd, offset, true);
1863
}
1864
1865
static int64_t *mysql_sys_var_ptr_int64_t(THD* a_thd, int offset)
1866
{
1867
  return (int64_t *)intern_sys_var_ptr(a_thd, offset, true);
1868
}
1869
1870
static char **mysql_sys_var_ptr_str(THD* a_thd, int offset)
1871
{
1872
  return (char **)intern_sys_var_ptr(a_thd, offset, true);
1873
}
1874
1875
static uint64_t *mysql_sys_var_ptr_set(THD* a_thd, int offset)
1876
{
1877
  return (uint64_t *)intern_sys_var_ptr(a_thd, offset, true);
1878
}
1879
1880
static unsigned long *mysql_sys_var_ptr_enum(THD* a_thd, int offset)
1881
{
1882
  return (unsigned long *)intern_sys_var_ptr(a_thd, offset, true);
1 by brian
clean slate
1883
}
1884
1885
1886
void plugin_thdvar_init(THD *thd)
1887
{
1888
  plugin_ref old_table_plugin= thd->variables.table_plugin;
1889
  
1890
  thd->variables.table_plugin= NULL;
1891
  cleanup_variables(thd, &thd->variables);
1892
  
1893
  thd->variables= global_system_variables;
1894
  thd->variables.table_plugin= NULL;
1895
1896
  /* we are going to allocate these lazily */
1897
  thd->variables.dynamic_variables_version= 0;
1898
  thd->variables.dynamic_variables_size= 0;
1899
  thd->variables.dynamic_variables_ptr= 0;
1900
1901
  thd->variables.table_plugin=
1902
        my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
1903
  intern_plugin_unlock(NULL, old_table_plugin);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1904
  return;
1 by brian
clean slate
1905
}
1906
1907
1908
/*
1909
  Unlocks all system variables which hold a reference
1910
*/
77.1.46 by Monty Taylor
Finished the warnings work!
1911
static void unlock_variables(THD *thd __attribute__((__unused__)),
1912
                             struct system_variables *vars)
1 by brian
clean slate
1913
{
1914
  intern_plugin_unlock(NULL, vars->table_plugin);
1915
  vars->table_plugin= NULL;
1916
}
1917
1918
1919
/*
1920
  Frees memory used by system variables
1921
1922
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
1923
  it's used on shutdown.
1924
*/
1925
static void cleanup_variables(THD *thd, struct system_variables *vars)
1926
{
1927
  st_bookmark *v;
1928
  sys_var_pluginvar *pivar;
1929
  sys_var *var;
1930
  int flags;
1931
  uint idx;
1932
1933
  rw_rdlock(&LOCK_system_variables_hash);
1934
  for (idx= 0; idx < bookmark_hash.records; idx++)
1935
  {
1936
    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
1937
    if (v->version > vars->dynamic_variables_version ||
1938
        !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
1939
        !(pivar= var->cast_pluginvar()) ||
1940
        v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
1941
      continue;
1942
1943
    flags= pivar->plugin_var->flags;
1944
1945
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
1946
        flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
1947
    {
1948
      char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
1949
      my_free(*ptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
1950
      *ptr= NULL;
1951
    }
1952
  }
1953
  rw_unlock(&LOCK_system_variables_hash);
1954
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
1955
  assert(vars->table_plugin == NULL);
1 by brian
clean slate
1956
1957
  my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR));
1958
  vars->dynamic_variables_ptr= NULL;
1959
  vars->dynamic_variables_size= 0;
1960
  vars->dynamic_variables_version= 0;
1961
}
1962
1963
1964
void plugin_thdvar_cleanup(THD *thd)
1965
{
1966
  uint idx;
1967
  plugin_ref *list;
1968
1969
  unlock_variables(thd, &thd->variables);
1970
  cleanup_variables(thd, &thd->variables);
1971
1972
  if ((idx= thd->lex->plugins.elements))
1973
  {
1974
    list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
1975
    while ((uchar*) list >= thd->lex->plugins.buffer)
1976
      intern_plugin_unlock(NULL, *list--);
1977
  }
1978
1979
  reset_dynamic(&thd->lex->plugins);
1980
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
1981
  return;
1 by brian
clean slate
1982
}
1983
1984
1985
/**
1986
  @brief Free values of thread variables of a plugin.
1987
1988
  This must be called before a plugin is deleted. Otherwise its
1989
  variables are no longer accessible and the value space is lost. Note
1990
  that only string values with PLUGIN_VAR_MEMALLOC are allocated and
1991
  must be freed.
1992
1993
  @param[in]        vars        Chain of system variables of a plugin
1994
*/
1995
1996
static void plugin_vars_free_values(sys_var *vars)
1997
{
1998
1999
  for (sys_var *var= vars; var; var= var->next)
2000
  {
2001
    sys_var_pluginvar *piv= var->cast_pluginvar();
2002
    if (piv &&
2003
        ((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
2004
        (piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
2005
    {
2006
      /* Free the string from global_system_variables. */
2007
      char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
2008
      my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
2009
      *valptr= NULL;
2010
    }
2011
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2012
  return;
1 by brian
clean slate
2013
}
2014
2015
2016
bool sys_var_pluginvar::check_update_type(Item_result type)
2017
{
2018
  if (is_readonly())
2019
    return 1;
2020
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2021
  case PLUGIN_VAR_INT:
2022
  case PLUGIN_VAR_LONG:
2023
  case PLUGIN_VAR_LONGLONG:
2024
    return type != INT_RESULT;
2025
  case PLUGIN_VAR_STR:
2026
    return type != STRING_RESULT;
2027
  default:
2028
    return 0;
2029
  }
2030
}
2031
2032
2033
SHOW_TYPE sys_var_pluginvar::show_type()
2034
{
2035
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2036
  case PLUGIN_VAR_BOOL:
2037
    return SHOW_MY_BOOL;
2038
  case PLUGIN_VAR_INT:
2039
    return SHOW_INT;
2040
  case PLUGIN_VAR_LONG:
2041
    return SHOW_LONG;
2042
  case PLUGIN_VAR_LONGLONG:
2043
    return SHOW_LONGLONG;
2044
  case PLUGIN_VAR_STR:
2045
    return SHOW_CHAR_PTR;
2046
  case PLUGIN_VAR_ENUM:
2047
  case PLUGIN_VAR_SET:
2048
    return SHOW_CHAR;
2049
  default:
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2050
    assert(0);
1 by brian
clean slate
2051
    return SHOW_UNDEF;
2052
  }
2053
}
2054
2055
2056
uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
2057
{
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2058
  assert(thd || (type == OPT_GLOBAL));
1 by brian
clean slate
2059
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
2060
  {
2061
    if (type == OPT_GLOBAL)
2062
      thd= NULL;
2063
2064
    return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
2065
  }
2066
  return *(uchar**) (plugin_var+1);
2067
}
2068
2069
2070
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
2071
{
2072
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) {
2073
  case PLUGIN_VAR_ENUM:
2074
    return ((sysvar_enum_t *)plugin_var)->typelib;
2075
  case PLUGIN_VAR_SET:
2076
    return ((sysvar_set_t *)plugin_var)->typelib;
2077
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2078
    return ((thdvar_enum_t *)plugin_var)->typelib;
2079
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2080
    return ((thdvar_set_t *)plugin_var)->typelib;
2081
  default:
2082
    return NULL;
2083
  }
2084
  return NULL;
2085
}
2086
2087
2088
uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
77.1.46 by Monty Taylor
Finished the warnings work!
2089
                                    LEX_STRING *base __attribute__((__unused__)))
1 by brian
clean slate
2090
{
2091
  uchar* result;
2092
2093
  result= real_value_ptr(thd, type);
2094
2095
  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
2096
    result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result);
2097
  else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
2098
  {
2099
    char buffer[STRING_BUFFER_USUAL_SIZE];
2100
    String str(buffer, sizeof(buffer), system_charset_info);
2101
    TYPELIB *typelib= plugin_var_typelib();
151 by Brian Aker
Ulonglong to uint64_t
2102
    uint64_t mask= 1, value= *(uint64_t*) result;
1 by brian
clean slate
2103
    uint i;
2104
2105
    str.length(0);
2106
    for (i= 0; i < typelib->count; i++, mask<<=1)
2107
    {
2108
      if (!(value & mask))
2109
        continue;
2110
      str.append(typelib->type_names[i], typelib->type_lengths[i]);
2111
      str.append(',');
2112
    }
2113
2114
    result= (uchar*) "";
2115
    if (str.length())
2116
      result= (uchar*) thd->strmake(str.ptr(), str.length()-1);
2117
  }
2118
  return result;
2119
}
2120
2121
2122
bool sys_var_pluginvar::check(THD *thd, set_var *var)
2123
{
2124
  st_item_value_holder value;
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2125
  assert(is_readonly() || plugin_var->check);
1 by brian
clean slate
2126
2127
  value.value_type= item_value_type;
2128
  value.val_str= item_val_str;
2129
  value.val_int= item_val_int;
2130
  value.val_real= item_val_real;
2131
  value.item= var->value;
2132
2133
  return is_readonly() ||
2134
         plugin_var->check(thd, plugin_var, &var->save_result, &value);
2135
}
2136
2137
2138
void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
2139
{
2140
  const void *src;
2141
  void *tgt;
2142
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2143
  assert(is_readonly() || plugin_var->update);
1 by brian
clean slate
2144
2145
  if (is_readonly())
2146
    return;
2147
2148
  pthread_mutex_lock(&LOCK_global_system_variables);
2149
  tgt= real_value_ptr(thd, type);
2150
  src= ((void **) (plugin_var + 1) + 1);
2151
2152
  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
2153
  {
2154
    if (type != OPT_GLOBAL)
2155
      src= real_value_ptr(thd, OPT_GLOBAL);
2156
    else
2157
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
2158
	case PLUGIN_VAR_INT:
2159
	  src= &((thdvar_uint_t*) plugin_var)->def_val;
2160
	  break;
2161
	case PLUGIN_VAR_LONG:
2162
	  src= &((thdvar_ulong_t*) plugin_var)->def_val;
2163
	  break;
2164
	case PLUGIN_VAR_LONGLONG:
151 by Brian Aker
Ulonglong to uint64_t
2165
	  src= &((thdvar_uint64_t_t*) plugin_var)->def_val;
1 by brian
clean slate
2166
	  break;
2167
	case PLUGIN_VAR_ENUM:
2168
	  src= &((thdvar_enum_t*) plugin_var)->def_val;
2169
	  break;
2170
	case PLUGIN_VAR_SET:
2171
	  src= &((thdvar_set_t*) plugin_var)->def_val;
2172
	  break;
2173
	case PLUGIN_VAR_BOOL:
2174
	  src= &((thdvar_bool_t*) plugin_var)->def_val;
2175
	  break;
2176
	case PLUGIN_VAR_STR:
2177
	  src= &((thdvar_str_t*) plugin_var)->def_val;
2178
	  break;
2179
	default:
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2180
	  assert(0);
1 by brian
clean slate
2181
	}
2182
  }
2183
2184
  /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2185
  assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
1 by brian
clean slate
2186
              thd == current_thd);
2187
2188
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL)
2189
  {
2190
    plugin_var->update(thd, plugin_var, tgt, src);
2191
    pthread_mutex_unlock(&LOCK_global_system_variables);
2192
  }
2193
  else
2194
  {
2195
    pthread_mutex_unlock(&LOCK_global_system_variables);
2196
    plugin_var->update(thd, plugin_var, tgt, src);
2197
  }
2198
}
2199
2200
2201
bool sys_var_pluginvar::update(THD *thd, set_var *var)
2202
{
2203
  void *tgt;
2204
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2205
  assert(is_readonly() || plugin_var->update);
1 by brian
clean slate
2206
2207
  /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2208
  assert(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) ||
1 by brian
clean slate
2209
              thd == current_thd);
2210
2211
  if (is_readonly())
2212
    return 1;
2213
2214
  pthread_mutex_lock(&LOCK_global_system_variables);
2215
  tgt= real_value_ptr(thd, var->type);
2216
2217
  if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL)
2218
  {
2219
    /* variable we are updating has global scope, so we unlock after updating */
2220
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2221
    pthread_mutex_unlock(&LOCK_global_system_variables);
2222
  }
2223
  else
2224
  {
2225
    pthread_mutex_unlock(&LOCK_global_system_variables);
2226
    plugin_var->update(thd, plugin_var, tgt, &var->save_result);
2227
  }
2228
 return 0;
2229
}
2230
2231
2232
#define OPTION_SET_LIMITS(type, options, opt) \
2233
  options->var_type= type; \
2234
  options->def_value= (opt)->def_val; \
2235
  options->min_value= (opt)->min_val; \
2236
  options->max_value= (opt)->max_val; \
2237
  options->block_size= (long) (opt)->blk_sz
2238
2239
2240
static void plugin_opt_set_limits(struct my_option *options,
2241
                                  const struct st_mysql_sys_var *opt)
2242
{
2243
  options->sub_size= 0;
2244
2245
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
2246
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
2247
  /* global system variables */
2248
  case PLUGIN_VAR_INT:
2249
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
2250
    break;
2251
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
2252
    OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
2253
    break;
2254
  case PLUGIN_VAR_LONG:
2255
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
2256
    break;
2257
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
2258
    OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
2259
    break;
2260
  case PLUGIN_VAR_LONGLONG:
152 by Brian Aker
longlong replacement
2261
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
1 by brian
clean slate
2262
    break;
2263
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
151 by Brian Aker
Ulonglong to uint64_t
2264
    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1 by brian
clean slate
2265
    break;
2266
  case PLUGIN_VAR_ENUM:
2267
    options->var_type= GET_ENUM;
2268
    options->typelib= ((sysvar_enum_t*) opt)->typelib;
2269
    options->def_value= ((sysvar_enum_t*) opt)->def_val;
2270
    options->min_value= options->block_size= 0;
2271
    options->max_value= options->typelib->count - 1;
2272
    break;
2273
  case PLUGIN_VAR_SET:
2274
    options->var_type= GET_SET;
2275
    options->typelib= ((sysvar_set_t*) opt)->typelib;
2276
    options->def_value= ((sysvar_set_t*) opt)->def_val;
2277
    options->min_value= options->block_size= 0;
80.1.1 by Brian Aker
LL() cleanup
2278
    options->max_value= (1ULL << options->typelib->count) - 1;
1 by brian
clean slate
2279
    break;
2280
  case PLUGIN_VAR_BOOL:
2281
    options->var_type= GET_BOOL;
2282
    options->def_value= ((sysvar_bool_t*) opt)->def_val;
2283
    break;
2284
  case PLUGIN_VAR_STR:
2285
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2286
                        GET_STR_ALLOC : GET_STR);
157 by Brian Aker
Second pass cleanup on removal of my_uint types
2287
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
1 by brian
clean slate
2288
    break;
2289
  /* threadlocal variables */
2290
  case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
2291
    OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
2292
    break;
2293
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2294
    OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
2295
    break;
2296
  case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
2297
    OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
2298
    break;
2299
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
2300
    OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
2301
    break;
2302
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
152 by Brian Aker
longlong replacement
2303
    OPTION_SET_LIMITS(GET_LL, options, (thdvar_int64_t_t*) opt);
1 by brian
clean slate
2304
    break;
2305
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
151 by Brian Aker
Ulonglong to uint64_t
2306
    OPTION_SET_LIMITS(GET_ULL, options, (thdvar_uint64_t_t*) opt);
1 by brian
clean slate
2307
    break;
2308
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
2309
    options->var_type= GET_ENUM;
2310
    options->typelib= ((thdvar_enum_t*) opt)->typelib;
2311
    options->def_value= ((thdvar_enum_t*) opt)->def_val;
2312
    options->min_value= options->block_size= 0;
2313
    options->max_value= options->typelib->count - 1;
2314
    break;
2315
  case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
2316
    options->var_type= GET_SET;
2317
    options->typelib= ((thdvar_set_t*) opt)->typelib;
2318
    options->def_value= ((thdvar_set_t*) opt)->def_val;
2319
    options->min_value= options->block_size= 0;
80.1.1 by Brian Aker
LL() cleanup
2320
    options->max_value= (1ULL << options->typelib->count) - 1;
1 by brian
clean slate
2321
    break;
2322
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
2323
    options->var_type= GET_BOOL;
2324
    options->def_value= ((thdvar_bool_t*) opt)->def_val;
2325
    break;
2326
  case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
2327
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
2328
                        GET_STR_ALLOC : GET_STR);
157 by Brian Aker
Second pass cleanup on removal of my_uint types
2329
    options->def_value= (intptr_t) ((thdvar_str_t*) opt)->def_val;
1 by brian
clean slate
2330
    break;
2331
  default:
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2332
    assert(0);
1 by brian
clean slate
2333
  }
2334
  options->arg_type= REQUIRED_ARG;
2335
  if (opt->flags & PLUGIN_VAR_NOCMDARG)
2336
    options->arg_type= NO_ARG;
2337
  if (opt->flags & PLUGIN_VAR_OPCMDARG)
2338
    options->arg_type= OPT_ARG;
2339
}
2340
143 by Brian Aker
Bool cleanup.
2341
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
1 by brian
clean slate
2342
                                         char *);
2343
143 by Brian Aker
Bool cleanup.
2344
bool get_one_plugin_option(int optid __attribute__((unused)),
77.1.46 by Monty Taylor
Finished the warnings work!
2345
                              const struct my_option *opt __attribute__((__unused__)),
2346
                              char *argument __attribute__((__unused__)))
1 by brian
clean slate
2347
{
2348
  return 0;
2349
}
2350
2351
2352
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
138 by Brian Aker
Refactoring around sql_plugin.
2353
                             my_option *options, bool can_disable)
1 by brian
clean slate
2354
{
2355
  const char *plugin_name= tmp->plugin->name;
2356
  uint namelen= strlen(plugin_name), optnamelen;
2357
  uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
2358
  char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
2359
  char *optname, *p;
2360
  int index= 0, offset= 0;
2361
  st_mysql_sys_var *opt, **plugin_option;
2362
  st_bookmark *v;
2363
2364
  /* support --skip-plugin-foo syntax */
2365
  memcpy(name, plugin_name, namelen + 1);
2366
  my_casedn_str(&my_charset_latin1, name);
2367
  strxmov(name + namelen + 1, "plugin-", name, NullS);
2368
  /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
2369
2370
  for (p= name + namelen*2 + 8; p > name; p--)
2371
    if (*p == '_')
2372
      *p= '-';
2373
2374
  if (can_disable)
2375
  {
2376
    strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
2377
            "Disable with --skip-", name," (will save memory).", NullS);
2378
    /*
2379
      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
2380
      20 + namelen + 20 + 1 == namelen * 4 + 67.
2381
    */
2382
2383
    options[0].comment= name + namelen*2 + 10;
2384
  }
2385
2386
  options[1].name= (options[0].name= name) + namelen + 1;
2387
  options[0].id= options[1].id= 256; /* must be >255. dup id ok */
2388
  options[0].var_type= options[1].var_type= GET_BOOL;
2389
  options[0].arg_type= options[1].arg_type= NO_ARG;
138 by Brian Aker
Refactoring around sql_plugin.
2390
  options[0].def_value= options[1].def_value= true;
1 by brian
clean slate
2391
  options[0].value= options[0].u_max_value=
77.1.78 by Monty Taylor
One last bunch of warnings edits.
2392
  options[1].value= options[1].u_max_value= (char**) (name - 1);
1 by brian
clean slate
2393
  options+= 2;
2394
2395
  /*
2396
    Two passes as the 2nd pass will take pointer addresses for use
2397
    by my_getopt and register_var() in the first pass uses realloc
2398
  */
2399
2400
  for (plugin_option= tmp->plugin->system_vars;
2401
       plugin_option && *plugin_option; plugin_option++, index++)
2402
  {
2403
    opt= *plugin_option;
2404
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
2405
      continue;
2406
    if (!(register_var(name, opt->name, opt->flags)))
2407
      continue;
2408
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
2409
    case PLUGIN_VAR_BOOL:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2410
      (((thdvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
1 by brian
clean slate
2411
      break;
2412
    case PLUGIN_VAR_INT:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2413
      (((thdvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
1 by brian
clean slate
2414
      break;
2415
    case PLUGIN_VAR_LONG:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2416
      (((thdvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
1 by brian
clean slate
2417
      break;
2418
    case PLUGIN_VAR_LONGLONG:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2419
      (((thdvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
1 by brian
clean slate
2420
      break;
2421
    case PLUGIN_VAR_STR:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2422
      (((thdvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1 by brian
clean slate
2423
      break;
2424
    case PLUGIN_VAR_ENUM:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2425
      (((thdvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
1 by brian
clean slate
2426
      break;
2427
    case PLUGIN_VAR_SET:
77.1.99 by Monty Taylor
Type-punning fix for sql_plugin.cc.
2428
      (((thdvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
1 by brian
clean slate
2429
      break;
2430
    default:
2431
      sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
2432
                      opt->flags, plugin_name);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2433
      return(-1);
1 by brian
clean slate
2434
    };
2435
  }
2436
2437
  for (plugin_option= tmp->plugin->system_vars;
2438
       plugin_option && *plugin_option; plugin_option++, index++)
2439
  {
2440
    switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
2441
    case PLUGIN_VAR_BOOL:
2442
      if (!opt->check)
2443
        opt->check= check_func_bool;
2444
      if (!opt->update)
2445
        opt->update= update_func_bool;
2446
      break;
2447
    case PLUGIN_VAR_INT:
2448
      if (!opt->check)
2449
        opt->check= check_func_int;
2450
      if (!opt->update)
2451
        opt->update= update_func_int;
2452
      break;
2453
    case PLUGIN_VAR_LONG:
2454
      if (!opt->check)
2455
        opt->check= check_func_long;
2456
      if (!opt->update)
2457
        opt->update= update_func_long;
2458
      break;
2459
    case PLUGIN_VAR_LONGLONG:
2460
      if (!opt->check)
152 by Brian Aker
longlong replacement
2461
        opt->check= check_func_int64_t;
1 by brian
clean slate
2462
      if (!opt->update)
152 by Brian Aker
longlong replacement
2463
        opt->update= update_func_int64_t;
1 by brian
clean slate
2464
      break;
2465
    case PLUGIN_VAR_STR:
2466
      if (!opt->check)
2467
        opt->check= check_func_str;
2468
      if (!opt->update)
2469
      {
2470
        opt->update= update_func_str;
9 by Brian Aker
Warnings cleanup
2471
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
1 by brian
clean slate
2472
        {
2473
          opt->flags|= PLUGIN_VAR_READONLY;
2474
          sql_print_warning("Server variable %s of plugin %s was forced "
2475
                            "to be read-only: string variable without "
2476
                            "update_func and PLUGIN_VAR_MEMALLOC flag",
2477
                            opt->name, plugin_name);
2478
        }
2479
      }
2480
      break;
2481
    case PLUGIN_VAR_ENUM:
2482
      if (!opt->check)
2483
        opt->check= check_func_enum;
2484
      if (!opt->update)
2485
        opt->update= update_func_long;
2486
      break;
2487
    case PLUGIN_VAR_SET:
2488
      if (!opt->check)
2489
        opt->check= check_func_set;
2490
      if (!opt->update)
152 by Brian Aker
longlong replacement
2491
        opt->update= update_func_int64_t;
1 by brian
clean slate
2492
      break;
2493
    default:
2494
      sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
2495
                      opt->flags, plugin_name);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2496
      return(-1);
1 by brian
clean slate
2497
    }
2498
2499
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
2500
                    == PLUGIN_VAR_NOCMDOPT)
2501
      continue;
2502
2503
    if (!opt->name)
2504
    {
2505
      sql_print_error("Missing variable name in plugin '%s'.",
2506
                      plugin_name);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2507
      return(-1);
1 by brian
clean slate
2508
    }
2509
2510
    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
2511
    {
2512
      optnamelen= strlen(opt->name);
2513
      optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
2514
      strxmov(optname, name, "-", opt->name, NullS);
2515
      optnamelen= namelen + optnamelen + 1;
2516
    }
2517
    else
2518
    {
2519
      /* this should not fail because register_var should create entry */
2520
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
2521
      {
2522
        sql_print_error("Thread local variable '%s' not allocated "
2523
                        "in plugin '%s'.", opt->name, plugin_name);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2524
        return(-1);
1 by brian
clean slate
2525
      }
2526
2527
      *(int*)(opt + 1)= offset= v->offset;
2528
2529
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
2530
        continue;
2531
2532
      optname= (char*) memdup_root(mem_root, v->key + 1, 
2533
                                   (optnamelen= v->name_len) + 1);
2534
    }
2535
2536
    /* convert '_' to '-' */
2537
    for (p= optname; *p; p++)
2538
      if (*p == '_')
2539
        *p= '-';
2540
2541
    options->name= optname;
2542
    options->comment= opt->comment;
2543
    options->app_type= opt;
2544
    options->id= (options-1)->id + 1;
2545
2546
    plugin_opt_set_limits(options, opt);
2547
2548
    if (opt->flags & PLUGIN_VAR_THDLOCAL)
77.1.78 by Monty Taylor
One last bunch of warnings edits.
2549
      options->value= options->u_max_value= (char**)
1 by brian
clean slate
2550
        (global_system_variables.dynamic_variables_ptr + offset);
2551
    else
77.1.78 by Monty Taylor
One last bunch of warnings edits.
2552
      options->value= options->u_max_value= *(char***) (opt + 1);
1 by brian
clean slate
2553
2554
    options[1]= options[0];
2555
    options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
2556
    options[1].comment= 0; // hidden
2557
    strxmov(p, "plugin-", optname, NullS);
2558
2559
    options+= 2;
2560
  }
2561
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2562
  return(0);
1 by brian
clean slate
2563
}
2564
2565
2566
static my_option *construct_help_options(MEM_ROOT *mem_root,
2567
                                         struct st_plugin_int *p)
2568
{
2569
  st_mysql_sys_var **opt;
2570
  my_option *opts;
138 by Brian Aker
Refactoring around sql_plugin.
2571
  bool can_disable;
1 by brian
clean slate
2572
  uint count= EXTRA_OPTIONS;
2573
9 by Brian Aker
Warnings cleanup
2574
  for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
1 by brian
clean slate
2575
2576
  if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2577
    return(NULL);
1 by brian
clean slate
2578
2579
  bzero(opts, sizeof(my_option) * count);
2580
138 by Brian Aker
Refactoring around sql_plugin.
2581
  if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") == 0))
2582
    can_disable= false;
2583
  else if ((my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY") == 0))
2584
    can_disable= false;
2585
  else
2586
    can_disable= true;
2587
2588
2589
  if (construct_options(mem_root, p, opts, can_disable))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2590
    return(NULL);
1 by brian
clean slate
2591
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2592
  return(opts);
1 by brian
clean slate
2593
}
2594
2595
2596
/*
2597
  SYNOPSIS
2598
    test_plugin_options()
2599
    tmp_root                    temporary scratch space
2600
    plugin                      internal plugin structure
2601
    argc                        user supplied arguments
2602
    argv                        user supplied arguments
2603
    default_enabled             default plugin enable status
2604
  RETURNS:
2605
    0 SUCCESS - plugin should be enabled/loaded
2606
  NOTE:
2607
    Requires that a write-lock is held on LOCK_system_variables_hash
2608
*/
2609
static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
135 by Brian Aker
Random cleanup. Dead partition tests, pass operator in sql_plugin, mtr based
2610
                               int *argc, char **argv)
1 by brian
clean slate
2611
{
2612
  struct sys_var_chain chain= { NULL, NULL };
138 by Brian Aker
Refactoring around sql_plugin.
2613
  bool enabled_saved= true;
2614
  bool can_disable;
1 by brian
clean slate
2615
  MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
2616
                      &tmp->mem_root : &plugin_mem_root;
2617
  st_mysql_sys_var **opt;
2618
  my_option *opts= NULL;
2619
  char *p, *varname;
2620
  int error;
2621
  st_mysql_sys_var *o;
2622
  sys_var *v;
2623
  struct st_bookmark *var;
2624
  uint len, count= EXTRA_OPTIONS;
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2625
  assert(tmp->plugin && tmp->name.str);
1 by brian
clean slate
2626
2627
  for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
2628
    count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
2629
138 by Brian Aker
Refactoring around sql_plugin.
2630
  if ((my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") == 0))
2631
    can_disable= false;
2632
  else if ((my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY") == 0))
2633
    can_disable= false;
2634
  else
2635
    can_disable= true;
1 by brian
clean slate
2636
2637
  if (count > EXTRA_OPTIONS || (*argc > 1))
2638
  {
2639
    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
2640
    {
2641
      sql_print_error("Out of memory for plugin '%s'.", tmp->name.str);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2642
      return(-1);
1 by brian
clean slate
2643
    }
2644
    bzero(opts, sizeof(my_option) * count);
2645
138 by Brian Aker
Refactoring around sql_plugin.
2646
    if (construct_options(tmp_root, tmp, opts, can_disable))
1 by brian
clean slate
2647
    {
2648
      sql_print_error("Bad options for plugin '%s'.", tmp->name.str);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2649
      return(-1);
1 by brian
clean slate
2650
    }
2651
2652
    error= handle_options(argc, &argv, opts, get_one_plugin_option);
2653
    (*argc)++; /* add back one for the program name */
2654
2655
    if (error)
2656
    {
2657
       sql_print_error("Parsing options for plugin '%s' failed.",
2658
                       tmp->name.str);
2659
       goto err;
2660
    }
2661
  }
2662
2663
  error= 1;
2664
2665
  {
2666
    for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
2667
    {
2668
      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
2669
        continue;
2670
2671
      if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
2672
        v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
2673
      else
2674
      {
2675
        len= tmp->name.length + strlen(o->name) + 2;
2676
        varname= (char*) alloc_root(mem_root, len);
2677
        strxmov(varname, tmp->name.str, "-", o->name, NullS);
2678
        my_casedn_str(&my_charset_latin1, varname);
2679
2680
        for (p= varname; *p; p++)
2681
          if (*p == '-')
2682
            *p= '_';
2683
2684
        v= new (mem_root) sys_var_pluginvar(varname, o);
2685
      }
51.1.62 by Jay Pipes
Removed/replaced BUG symbols and standardized TRUE/FALSE
2686
      assert(v); /* check that an object was actually constructed */
1 by brian
clean slate
2687
2688
      /*
2689
        Add to the chain of variables.
2690
        Done like this for easier debugging so that the
2691
        pointer to v is not lost on optimized builds.
2692
      */
2693
      v->chain_sys_var(&chain);
2694
    }
2695
    if (chain.first)
2696
    {
2697
      chain.last->next = NULL;
2698
      if (mysql_add_sys_var_chain(chain.first, NULL))
2699
      {
2700
        sql_print_error("Plugin '%s' has conflicting system variables",
2701
                        tmp->name.str);
2702
        goto err;
2703
      }
2704
      tmp->system_vars= chain.first;
2705
    }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2706
    return(0);
1 by brian
clean slate
2707
  }
2708
2709
  if (enabled_saved && global_system_variables.log_warnings)
2710
    sql_print_information("Plugin '%s' disabled by command line option",
2711
                          tmp->name.str);
2712
err:
2713
  if (opts)
2714
    my_cleanup_options(opts);
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
2715
  return(error);
1 by brian
clean slate
2716
}
2717
2718
2719
/****************************************************************************
2720
  Help Verbose text with Plugin System Variables
2721
****************************************************************************/
2722
2723
static int option_cmp(my_option *a, my_option *b)
2724
{
2725
  return my_strcasecmp(&my_charset_latin1, a->name, b->name);
2726
}
2727
2728
2729
void my_print_help_inc_plugins(my_option *main_options, uint size)
2730
{
2731
  DYNAMIC_ARRAY all_options;
2732
  struct st_plugin_int *p;
2733
  MEM_ROOT mem_root;
2734
  my_option *opt;
2735
2736
  init_alloc_root(&mem_root, 4096, 4096);
2737
  my_init_dynamic_array(&all_options, sizeof(my_option), size, size/4);
2738
2739
  if (initialized)
2740
    for (uint idx= 0; idx < plugin_array.elements; idx++)
2741
    {
2742
      p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
2743
2744
      if (!p->plugin->system_vars ||
2745
          !(opt= construct_help_options(&mem_root, p)))
2746
        continue;
2747
2748
      /* Only options with a non-NULL comment are displayed in help text */
2749
      for (;opt->id; opt++)
2750
        if (opt->comment)
2751
          insert_dynamic(&all_options, (uchar*) opt);
2752
    }
2753
2754
  for (;main_options->id; main_options++)
2755
    insert_dynamic(&all_options, (uchar*) main_options);
2756
2757
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
2758
2759
  /* main_options now points to the empty option terminator */
2760
  insert_dynamic(&all_options, (uchar*) main_options);
2761
2762
  my_print_help((my_option*) all_options.buffer);
2763
  my_print_variables((my_option*) all_options.buffer);
2764
2765
  delete_dynamic(&all_options);
2766
  free_root(&mem_root, MYF(0));
2767
}
2768