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