~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_plugin.cc

  • Committer: mordred
  • Date: 2009-07-15 05:28:57 UTC
  • mto: (1093.1.16 captain)
  • mto: This revision was merged to the branch mainline in revision 1097.
  • Revision ID: mordred@orisndriz02-20090715052857-fyizopg1m23l8vfo
pandora-build v0.18
Added support for ICC

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "config.h"
 
16
#include <drizzled/server_includes.h>
 
17
#include <mysys/my_getopt.h>
 
18
#include <mysys/hash.h>
17
19
 
18
 
#include <dlfcn.h>
 
20
#include <drizzled/authentication.h>
 
21
#include <drizzled/logging.h>
 
22
#include <drizzled/errmsg.h>
 
23
#include <drizzled/qcache.h>
 
24
#include <drizzled/sql_parse.h>
 
25
#include <drizzled/scheduling.h>
 
26
#include <drizzled/transaction_services.h>
 
27
#include <drizzled/show.h>
 
28
#include <drizzled/handler.h>
 
29
#include <drizzled/set_var.h>
 
30
#include <drizzled/session.h>
 
31
#include <drizzled/item/null.h>
 
32
#include <drizzled/plugin_registry.h>
19
33
 
20
34
#include <string>
21
35
#include <vector>
22
36
#include <map>
23
37
#include <algorithm>
24
38
 
25
 
#include "drizzled/my_getopt.h"
26
 
#include "drizzled/my_hash.h"
27
 
#include "drizzled/internal/m_string.h"
28
 
 
29
 
#include "drizzled/plugin.h"
30
 
#include "drizzled/plugin/load_list.h"
31
 
#include "drizzled/sql_parse.h"
32
 
#include "drizzled/show.h"
33
 
#include "drizzled/cursor.h"
34
 
#include "drizzled/set_var.h"
35
 
#include "drizzled/session.h"
36
 
#include "drizzled/item/null.h"
37
 
#include "drizzled/plugin/registry.h"
38
 
#include "drizzled/error.h"
39
 
#include "drizzled/gettext.h"
40
 
#include "drizzled/errmsg_print.h"
41
 
#include "drizzled/plugin/library.h"
42
 
#include "drizzled/strfunc.h"
43
 
#include "drizzled/pthread_globals.h"
44
 
#include "drizzled/util/tokenize.h"
45
 
 
46
 
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
47
 
#ifndef RTLD_NOW
48
 
#define RTLD_NOW 1
49
 
#endif
 
39
#include <drizzled/error.h>
 
40
#include <drizzled/gettext.h>
 
41
 
 
42
#define REPORT_TO_LOG  1
 
43
#define REPORT_TO_USER 2
50
44
 
51
45
using namespace std;
52
 
 
53
 
typedef drizzled::plugin::Manifest drizzled_builtin_plugin[];
54
 
extern drizzled_builtin_plugin PANDORA_BUILTIN_LIST;
55
 
static drizzled::plugin::Manifest *drizzled_builtins[]=
56
 
{
57
 
  PANDORA_BUILTIN_LIST, NULL
58
 
};
59
 
 
60
 
namespace drizzled
61
 
{
62
46
 
63
 
 
64
 
class sys_var_pluginvar;
65
 
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
66
 
 
67
 
char *opt_plugin_add= NULL;
68
 
char *opt_plugin_remove= NULL;
 
47
typedef struct drizzled_plugin_manifest builtin_plugin[];
 
48
extern builtin_plugin DRIZZLED_BUILTIN_LIST;
 
49
static drizzled_plugin_manifest *drizzled_builtins[]=
 
50
{
 
51
  DRIZZLED_BUILTIN_LIST,(struct drizzled_plugin_manifest *)0
 
52
};
 
53
 
69
54
char *opt_plugin_load= NULL;
 
55
const char *opt_plugin_load_default= QUOTE_ARG(DRIZZLED_PLUGIN_LIST);
70
56
char *opt_plugin_dir_ptr;
71
57
char opt_plugin_dir[FN_REFLEN];
72
 
const char *opt_plugin_load_default= PANDORA_PLUGIN_LIST;
 
58
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
73
59
 
74
60
/* Note that 'int version' must be the first field of every plugin
75
61
   sub-structure (plugin->info).
77
63
 
78
64
static bool initialized= false;
79
65
 
 
66
static DYNAMIC_ARRAY plugin_dl_array;
 
67
static DYNAMIC_ARRAY plugin_array;
80
68
 
81
69
static bool reap_needed= false;
82
70
 
84
72
  write-lock on LOCK_system_variables_hash is required before modifying
85
73
  the following variables/structures
86
74
*/
87
 
static memory::Root plugin_mem_root;
 
75
static MEM_ROOT plugin_mem_root;
88
76
static uint32_t global_variables_dynamic_size= 0;
89
77
static HASH bookmark_hash;
90
78
 
93
81
  hidden part of opaque value passed to variable check functions.
94
82
  Used to provide a object-like structure to non C++ consumers.
95
83
*/
96
 
struct st_item_value_holder : public drizzle_value
 
84
struct st_item_value_holder : public st_mysql_value
97
85
{
98
86
  Item *item;
99
87
};
120
108
 
121
109
 
122
110
/*
 
111
  skeleton of a plugin variable - portion of structure common to all.
 
112
*/
 
113
struct st_mysql_sys_var
 
114
{
 
115
  DRIZZLE_PLUGIN_VAR_HEADER;
 
116
};
 
117
 
 
118
 
 
119
/*
123
120
  sys_var class for access to all plugin variables visible to the user
124
121
*/
125
122
class sys_var_pluginvar: public sys_var
126
123
{
127
124
public:
128
 
  plugin::Module *plugin;
129
 
  drizzle_sys_var *plugin_var;
130
 
 
131
 
  sys_var_pluginvar(const std::string name_arg,
132
 
                    drizzle_sys_var *plugin_var_arg)
 
125
  struct st_plugin_int *plugin;
 
126
  struct st_mysql_sys_var *plugin_var;
 
127
 
 
128
  static void *operator new(size_t size, MEM_ROOT *mem_root)
 
129
  { return (void*) alloc_root(mem_root, (uint32_t) size); }
 
130
  static void operator delete(void *, size_t)
 
131
  { TRASH(ptr_arg, size); }
 
132
 
 
133
  sys_var_pluginvar(const char *name_arg,
 
134
                    struct st_mysql_sys_var *plugin_var_arg)
133
135
    :sys_var(name_arg), plugin_var(plugin_var_arg) {}
134
136
  sys_var_pluginvar *cast_pluginvar() { return this; }
135
137
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
136
 
  bool check_type(sql_var_t type)
 
138
  bool check_type(enum_var_type type)
137
139
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
138
140
  bool check_update_type(Item_result type);
139
141
  SHOW_TYPE show_type();
140
 
  unsigned char* real_value_ptr(Session *session, sql_var_t type);
 
142
  unsigned char* real_value_ptr(Session *session, enum_var_type type);
141
143
  TYPELIB* plugin_var_typelib(void);
142
 
  unsigned char* value_ptr(Session *session, sql_var_t type,
 
144
  unsigned char* value_ptr(Session *session, enum_var_type type,
143
145
                           const LEX_STRING *base);
144
146
  bool check(Session *session, set_var *var);
145
 
  bool check_default(sql_var_t)
 
147
  bool check_default(enum_var_type)
146
148
    { return is_readonly(); }
147
 
  void set_default(Session *session, sql_var_t);
 
149
  void set_default(Session *session, enum_var_type);
148
150
  bool update(Session *session, set_var *var);
149
151
};
150
152
 
151
153
 
152
154
/* prototypes */
153
 
static void plugin_prune_list(vector<string> &plugin_list,
154
 
                              const vector<string> &plugins_to_remove);
155
 
static bool plugin_load_list(plugin::Registry &registry,
156
 
                             memory::Root *tmp_root, int *argc, char **argv,
157
 
                             const vector<string> &plugin_list);
158
 
static int test_plugin_options(memory::Root *, plugin::Module *,
 
155
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
 
156
                             const char *list);
 
157
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
159
158
                               int *, char **);
 
159
static bool register_builtin(struct st_plugin_int *,
 
160
                             struct st_plugin_int **);
160
161
static void unlock_variables(Session *session, struct system_variables *vars);
161
162
static void cleanup_variables(Session *session, struct system_variables *vars);
162
163
static void plugin_vars_free_values(sys_var *vars);
 
164
static void plugin_opt_set_limits(struct my_option *options,
 
165
                                  const struct st_mysql_sys_var *opt);
 
166
static void reap_plugins(void);
 
167
 
163
168
 
164
169
/* declared in set_var.cc */
165
170
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
177
182
  Value type thunks, allows the C world to play in the C++ world
178
183
****************************************************************************/
179
184
 
180
 
static int item_value_type(drizzle_value *value)
 
185
static int item_value_type(struct st_mysql_value *value)
181
186
{
182
187
  switch (((st_item_value_holder*)value)->item->result_type()) {
183
188
  case INT_RESULT:
189
194
  }
190
195
}
191
196
 
192
 
static const char *item_val_str(drizzle_value *value,
 
197
static const char *item_val_str(struct st_mysql_value *value,
193
198
                                char *buffer, int *length)
194
199
{
195
200
  String str(buffer, *length, system_charset_info), *res;
207
212
}
208
213
 
209
214
 
210
 
static int item_val_int(drizzle_value *value, int64_t *buf)
 
215
static int item_val_int(struct st_mysql_value *value, int64_t *buf)
211
216
{
212
217
  Item *item= ((st_item_value_holder*)value)->item;
213
218
  *buf= item->val_int();
217
222
}
218
223
 
219
224
 
220
 
static int item_val_real(drizzle_value *value, double *buf)
 
225
static int item_val_real(struct st_mysql_value *value, double *buf)
221
226
{
222
227
  Item *item= ((st_item_value_holder*)value)->item;
223
228
  *buf= item->val_real();
231
236
  Plugin support code
232
237
****************************************************************************/
233
238
 
234
 
 
 
239
static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
 
240
{
 
241
  uint32_t i;
 
242
  struct st_plugin_dl *tmp;
 
243
 
 
244
  for (i= 0; i < plugin_dl_array.elements; i++)
 
245
  {
 
246
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
 
247
    if (! my_strnncoll(files_charset_info,
 
248
                       (const unsigned char *)dl->str, dl->length,
 
249
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
 
250
      return(tmp);
 
251
  }
 
252
  return(0);
 
253
}
 
254
 
 
255
static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
 
256
{
 
257
  uint32_t i;
 
258
  struct st_plugin_dl *tmp;
 
259
 
 
260
  for (i= 0; i < plugin_dl_array.elements; i++)
 
261
  {
 
262
    tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **);
 
263
    {
 
264
      memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
 
265
      return(tmp);
 
266
    }
 
267
  }
 
268
  if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
 
269
    return(0);
 
270
  tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
 
271
                        struct st_plugin_dl **)=
 
272
      (struct st_plugin_dl *) memdup_root(&plugin_mem_root, (unsigned char*)plugin_dl,
 
273
                                           sizeof(struct st_plugin_dl));
 
274
  return(tmp);
 
275
}
 
276
 
 
277
static inline void free_plugin_mem(struct st_plugin_dl *p)
 
278
{
 
279
  if (p->handle)
 
280
    dlclose(p->handle);
 
281
  free(p->dl.str);
 
282
}
 
283
 
 
284
 
 
285
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
 
286
{
 
287
  string dlpath;
 
288
  uint32_t plugin_dir_len;
 
289
  struct st_plugin_dl *tmp, plugin_dl;
 
290
  void *sym;
 
291
  plugin_dir_len= strlen(opt_plugin_dir);
 
292
  dlpath.reserve(FN_REFLEN);
 
293
  /*
 
294
    Ensure that the dll doesn't have a path.
 
295
    This is done to ensure that only approved libraries from the
 
296
    plugin directory are used (to make this even remotely secure).
 
297
  */
 
298
  if (strchr(dl->str, FN_LIBCHAR) ||
 
299
      check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
 
300
                               system_charset_info, 1) ||
 
301
      plugin_dir_len + dl->length + 1 >= FN_REFLEN)
 
302
  {
 
303
    if (report & REPORT_TO_USER)
 
304
      my_error(ER_UDF_NO_PATHS, MYF(0));
 
305
    if (report & REPORT_TO_LOG)
 
306
      errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
 
307
    return(0);
 
308
  }
 
309
  /* If this dll is already loaded just increase ref_count. */
 
310
  if ((tmp= plugin_dl_find(dl)))
 
311
  {
 
312
    return(tmp);
 
313
  }
 
314
  memset(&plugin_dl, 0, sizeof(plugin_dl));
 
315
  /* Compile dll path */
 
316
  dlpath.append(opt_plugin_dir);
 
317
  dlpath.append("/");
 
318
  dlpath.append(dl->str);
 
319
  /* Open new dll handle */
 
320
  if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_LAZY|RTLD_GLOBAL)))
 
321
  {
 
322
    const char *errmsg=dlerror();
 
323
    uint32_t dlpathlen= dlpath.length();
 
324
    if (!dlpath.compare(0, dlpathlen, errmsg))
 
325
    { // if errmsg starts from dlpath, trim this prefix.
 
326
      errmsg+=dlpathlen;
 
327
      if (*errmsg == ':') errmsg++;
 
328
      if (*errmsg == ' ') errmsg++;
 
329
    }
 
330
    if (report & REPORT_TO_USER)
 
331
      my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath.c_str(), errno, errmsg);
 
332
    if (report & REPORT_TO_LOG)
 
333
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
 
334
    return(0);
 
335
  }
 
336
 
 
337
  /* Find plugin declarations */
 
338
  if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
 
339
  {
 
340
    free_plugin_mem(&plugin_dl);
 
341
    if (report & REPORT_TO_USER)
 
342
      my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
 
343
    if (report & REPORT_TO_LOG)
 
344
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
 
345
    return(0);
 
346
  }
 
347
 
 
348
  plugin_dl.plugins= (struct drizzled_plugin_manifest *)sym;
 
349
 
 
350
  /* Duplicate and convert dll name */
 
351
  plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
 
352
  if (! (plugin_dl.dl.str= (char*) calloc(plugin_dl.dl.length, sizeof(char))))
 
353
  {
 
354
    free_plugin_mem(&plugin_dl);
 
355
    if (report & REPORT_TO_USER)
 
356
      my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
 
357
    if (report & REPORT_TO_LOG)
 
358
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
 
359
    return(0);
 
360
  }
 
361
  strcpy(plugin_dl.dl.str, dl->str);
 
362
  /* Add this dll to array */
 
363
  if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
 
364
  {
 
365
    free_plugin_mem(&plugin_dl);
 
366
    if (report & REPORT_TO_USER)
 
367
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
 
368
    if (report & REPORT_TO_LOG)
 
369
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
 
370
    return(0);
 
371
  }
 
372
  return(tmp);
 
373
}
 
374
 
 
375
 
 
376
static void plugin_dl_del(const LEX_STRING *dl)
 
377
{
 
378
  uint32_t i;
 
379
 
 
380
  for (i= 0; i < plugin_dl_array.elements; i++)
 
381
  {
 
382
    struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i,
 
383
                                               struct st_plugin_dl **);
 
384
    if (! my_strnncoll(files_charset_info,
 
385
                       (const unsigned char *)dl->str, dl->length,
 
386
                       (const unsigned char *)tmp->dl.str, tmp->dl.length))
 
387
    {
 
388
      /* Do not remove this element, unless no other plugin uses this dll. */
 
389
      {
 
390
        free_plugin_mem(tmp);
 
391
        memset(tmp, 0, sizeof(struct st_plugin_dl));
 
392
      }
 
393
      break;
 
394
    }
 
395
  }
 
396
  return;
 
397
}
 
398
 
 
399
 
 
400
 
 
401
static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
 
402
{
 
403
  struct st_plugin_int *tmp;
 
404
  if (insert_dynamic(&plugin_array, (unsigned char*)&plugin))
 
405
    return(0);
 
406
  tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1,
 
407
                        struct st_plugin_int **)=
 
408
       (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)plugin,
 
409
                                            sizeof(struct st_plugin_int));
 
410
  return(tmp);
 
411
}
235
412
 
236
413
 
237
414
/*
238
415
  NOTE
239
416
    Requires that a write-lock is held on LOCK_system_variables_hash
240
417
*/
241
 
static bool plugin_add(plugin::Registry &registry, memory::Root *tmp_root,
242
 
                       plugin::Library *library,
243
 
                       int *argc, char **argv)
 
418
static bool plugin_add(MEM_ROOT *tmp_root,
 
419
                       const LEX_STRING *name, const LEX_STRING *dl,
 
420
                       int *argc, char **argv, int report)
244
421
{
 
422
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
423
 
 
424
  struct st_plugin_int tmp;
 
425
  struct drizzled_plugin_manifest *plugin;
245
426
  if (! initialized)
246
 
    return true;
 
427
    return(0);
247
428
 
248
 
  if (registry.find(library->getName()))
 
429
  if (registry.find(name))
249
430
  {
250
 
    errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
251
 
                  library->getName().c_str());
252
 
    return false;
 
431
    if (report & REPORT_TO_USER)
 
432
      my_error(ER_UDF_EXISTS, MYF(0), name->str);
 
433
    if (report & REPORT_TO_LOG)
 
434
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
 
435
    return(true);
253
436
  }
254
 
 
255
 
  plugin::Module *tmp= NULL;
 
437
  /* Clear the whole struct to catch future extensions. */
 
438
  memset(&tmp, 0, sizeof(tmp));
 
439
  if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
 
440
    return(true);
256
441
  /* Find plugin by name */
257
 
  const plugin::Manifest *manifest= library->getManifest();
258
 
 
259
 
  if (registry.find(manifest->name))
260
 
  {
261
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
262
 
                  _("Plugin '%s' contains the name '%s' in its manifest, which "
263
 
                    "has already been registered.\n"),
264
 
                  library->getName().c_str(),
265
 
                  manifest->name);
266
 
    return true;
267
 
  }
268
 
 
269
 
  tmp= new (std::nothrow) plugin::Module(manifest, library);
270
 
  if (tmp == NULL)
271
 
    return true;
272
 
 
273
 
  if (!test_plugin_options(tmp_root, tmp, argc, argv))
274
 
  {
275
 
    registry.add(tmp);
276
 
    return false;
277
 
  }
278
 
  errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY),
279
 
                library->getName().c_str());
280
 
  return true;
 
442
  for (plugin= tmp.plugin_dl->plugins; plugin->name; plugin++)
 
443
  {
 
444
    uint32_t name_len= strlen(plugin->name);
 
445
    if (! my_strnncoll(system_charset_info,
 
446
                       (const unsigned char *)name->str, name->length,
 
447
                       (const unsigned char *)plugin->name,
 
448
                       name_len))
 
449
    {
 
450
      struct st_plugin_int *tmp_plugin_ptr;
 
451
 
 
452
      tmp.plugin= plugin;
 
453
      tmp.name.str= (char *)plugin->name;
 
454
      tmp.name.length= name_len;
 
455
      tmp.isInited= false;
 
456
      if (!test_plugin_options(tmp_root, &tmp, argc, argv))
 
457
      {
 
458
        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
 
459
        {
 
460
          registry.add(tmp_plugin_ptr);
 
461
          init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
 
462
          return(false);
 
463
        }
 
464
        mysql_del_sys_var_chain(tmp.system_vars);
 
465
        goto err;
 
466
      }
 
467
      /* plugin was disabled */
 
468
      plugin_dl_del(dl);
 
469
      return(false);
 
470
    }
 
471
  }
 
472
  if (report & REPORT_TO_USER)
 
473
    my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
 
474
  if (report & REPORT_TO_LOG)
 
475
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
 
476
err:
 
477
  plugin_dl_del(dl);
 
478
  return(true);
281
479
}
282
480
 
283
481
 
284
 
static void delete_module(plugin::Module *module)
 
482
static void plugin_del(struct st_plugin_int *plugin)
285
483
{
 
484
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
485
  if (plugin->isInited)
 
486
  {
 
487
    if (plugin->plugin->status_vars)
 
488
    {
 
489
      remove_status_vars(plugin->plugin->status_vars);
 
490
    }
 
491
 
 
492
    if (plugin->plugin->deinit)
 
493
      plugin->plugin->deinit(registry);
 
494
  }
 
495
 
286
496
  /* Free allocated strings before deleting the plugin. */
287
 
  plugin_vars_free_values(module->system_vars);
288
 
  module->isInited= false;
 
497
  plugin_vars_free_values(plugin->system_vars);
 
498
  if (plugin->plugin_dl)
 
499
    plugin_dl_del(&plugin->plugin_dl->dl);
 
500
  plugin->isInited= false;
289
501
  pthread_rwlock_wrlock(&LOCK_system_variables_hash);
290
 
  mysql_del_sys_var_chain(module->system_vars);
 
502
  mysql_del_sys_var_chain(plugin->system_vars);
291
503
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
292
 
  delete module;
293
 
}
294
 
 
295
 
 
296
 
static void reap_plugins(plugin::Registry &registry)
297
 
{
298
 
  std::map<std::string, plugin::Module *>::const_iterator modules=
299
 
    registry.getModulesMap().begin();
300
 
 
301
 
  while (modules != registry.getModulesMap().end())
302
 
  {
303
 
    plugin::Module *module= (*modules).second;
304
 
    delete_module(module);
305
 
    ++modules;
306
 
  }
307
 
 
308
 
  drizzle_del_plugin_sysvar();
309
 
}
310
 
 
311
 
 
312
 
static void plugin_initialize_vars(plugin::Module *module)
313
 
{
 
504
  free_root(&plugin->mem_root, MYF(0));
 
505
}
 
506
 
 
507
static void reap_plugins(void)
 
508
{
 
509
  size_t count;
 
510
  uint32_t idx;
 
511
  struct st_plugin_int *plugin;
 
512
 
 
513
  count= plugin_array.elements;
 
514
 
 
515
  for (idx= 0; idx < count; idx++)
 
516
  {
 
517
    plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
 
518
    plugin_del(plugin);
 
519
  }
 
520
}
 
521
 
 
522
static bool plugin_initialize(struct st_plugin_int *plugin)
 
523
{
 
524
  assert(plugin->isInited == false);
 
525
 
 
526
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
527
  if (plugin->plugin->init)
 
528
  {
 
529
    if (plugin->plugin->init(registry))
 
530
    {
 
531
      errmsg_printf(ERRMSG_LVL_ERROR,
 
532
                    _("Plugin '%s' init function returned error.\n"),
 
533
                    plugin->name.str);
 
534
      goto err;
 
535
    }
 
536
  }
 
537
  plugin->isInited= true;
 
538
 
 
539
  if (plugin->plugin->status_vars)
 
540
  {
 
541
    add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
 
542
  }
 
543
 
314
544
  /*
315
545
    set the plugin attribute of plugin's sys vars so they are pointing
316
546
    to the active plugin
317
547
  */
318
 
  if (module->system_vars)
 
548
  if (plugin->system_vars)
319
549
  {
320
 
    sys_var_pluginvar *var= module->system_vars->cast_pluginvar();
 
550
    sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
321
551
    for (;;)
322
552
    {
323
 
      var->plugin= module;
 
553
      var->plugin= plugin;
324
554
      if (! var->getNext())
325
555
        break;
326
556
      var= var->getNext()->cast_pluginvar();
327
557
    }
328
558
  }
329
 
}
330
 
 
331
 
 
332
 
static bool plugin_initialize(plugin::Registry &registry,
333
 
                              plugin::Module *module)
334
 
{
335
 
  assert(module->isInited == false);
336
 
 
337
 
  plugin::Context loading_context(registry, module);
338
 
  if (module->getManifest().init)
339
 
  {
340
 
    if (module->getManifest().init(loading_context))
341
 
    {
342
 
      errmsg_printf(ERRMSG_LVL_ERROR,
343
 
                    _("Plugin '%s' init function returned error.\n"),
344
 
                    module->getName().c_str());
345
 
      return true;
346
 
    }
347
 
  }
348
 
  module->isInited= true;
349
 
 
350
559
 
351
560
  return false;
 
561
err:
 
562
  return true;
352
563
}
353
564
 
354
565
 
355
 
static unsigned char *get_bookmark_hash_key(const unsigned char *buff,
356
 
                                            size_t *length, bool)
 
566
extern "C" unsigned char *get_bookmark_hash_key(const unsigned char *, size_t *, bool);
 
567
 
 
568
 
 
569
unsigned char *get_bookmark_hash_key(const unsigned char *buff, size_t *length, bool)
357
570
{
358
571
  struct st_bookmark *var= (st_bookmark *)buff;
359
572
  *length= var->name_len + 1;
368
581
 
369
582
  Finally we initialize everything, aka the dynamic that have yet to initialize.
370
583
*/
371
 
bool plugin_init(plugin::Registry &registry,
372
 
                 int *argc, char **argv,
373
 
                 bool skip_init)
 
584
int plugin_init(int *argc, char **argv, int flags)
374
585
{
375
 
  plugin::Manifest **builtins;
376
 
  plugin::Manifest *manifest;
377
 
  plugin::Module *module;
378
 
  memory::Root tmp_root;
 
586
  uint32_t idx;
 
587
  struct drizzled_plugin_manifest **builtins;
 
588
  struct drizzled_plugin_manifest *plugin;
 
589
  struct st_plugin_int tmp, *plugin_ptr;
 
590
  MEM_ROOT tmp_root;
379
591
 
380
592
  if (initialized)
381
 
    return false;
 
593
    return(0);
382
594
 
383
 
  init_alloc_root(&plugin_mem_root, 4096);
384
 
  init_alloc_root(&tmp_root, 4096);
 
595
  init_alloc_root(&plugin_mem_root, 4096, 4096);
 
596
  init_alloc_root(&tmp_root, 4096, 4096);
385
597
 
386
598
  if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
387
599
                  get_bookmark_hash_key, NULL, HASH_UNIQUE))
388
 
  {
389
 
    free_root(&tmp_root, MYF(0));
390
 
    return true;
391
 
  }
392
 
 
 
600
      goto err;
 
601
 
 
602
 
 
603
  if (my_init_dynamic_array(&plugin_dl_array,
 
604
                            sizeof(struct st_plugin_dl *),16,16) ||
 
605
      my_init_dynamic_array(&plugin_array,
 
606
                            sizeof(struct st_plugin_int *),16,16))
 
607
    goto err;
393
608
 
394
609
  initialized= 1;
395
610
 
398
613
  */
399
614
  for (builtins= drizzled_builtins; *builtins; builtins++)
400
615
  {
401
 
    manifest= *builtins;
402
 
    if (manifest->name != NULL)
 
616
    for (plugin= *builtins; plugin->name; plugin++)
403
617
    {
404
 
      module= new (std::nothrow) plugin::Module(manifest);
405
 
      if (module == NULL)
406
 
        return true;
 
618
      memset(&tmp, 0, sizeof(tmp));
 
619
      tmp.plugin= plugin;
 
620
      tmp.name.str= (char *)plugin->name;
 
621
      tmp.name.length= strlen(plugin->name);
407
622
 
408
 
      free_root(&tmp_root, MYF(memory::MARK_BLOCKS_FREE));
409
 
      if (test_plugin_options(&tmp_root, module, argc, argv))
 
623
      free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
 
624
      if (test_plugin_options(&tmp_root, &tmp, argc, argv))
410
625
        continue;
411
626
 
412
 
      registry.add(module);
413
 
 
414
 
      plugin_initialize_vars(module);
415
 
 
416
 
      if (! skip_init)
417
 
      {
418
 
        if (plugin_initialize(registry, module))
419
 
        {
420
 
          free_root(&tmp_root, MYF(0));
421
 
          return true;
422
 
        }
423
 
      }
 
627
      if (register_builtin(&tmp, &plugin_ptr))
 
628
        goto err_unlock;
 
629
 
 
630
      if (plugin_initialize(plugin_ptr))
 
631
        goto err_unlock;
 
632
 
424
633
    }
425
634
  }
426
635
 
427
636
 
428
 
  bool load_failed= false;
429
 
  vector<string> plugin_list;
430
 
  if (opt_plugin_load)
431
 
  {
432
 
    tokenize(opt_plugin_load, plugin_list, ",", true);
433
 
  }
434
 
  else
435
 
  {
436
 
    tokenize(opt_plugin_load_default, plugin_list, ",", true);
437
 
  }
438
 
  if (opt_plugin_add)
439
 
  {
440
 
    tokenize(opt_plugin_add, plugin_list, ",", true);
441
 
  }
442
 
 
443
 
  if (opt_plugin_remove)
444
 
  {
445
 
    vector<string> plugins_to_remove;
446
 
    tokenize(opt_plugin_remove, plugins_to_remove, ",", true);
447
 
    plugin_prune_list(plugin_list, plugins_to_remove);
448
 
  }
449
 
  
450
637
  /* Register all dynamic plugins */
451
 
  load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
452
 
                                plugin_list);
453
 
  if (load_failed)
 
638
  if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
454
639
  {
455
 
    free_root(&tmp_root, MYF(0));
456
 
    return true;
 
640
    if (opt_plugin_load)
 
641
      plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
457
642
  }
458
643
 
459
 
  if (skip_init)
460
 
  {
461
 
    free_root(&tmp_root, MYF(0));
462
 
    return false;
463
 
  }
 
644
  if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
 
645
    goto end;
464
646
 
465
647
  /*
466
648
    Now we initialize all remaining plugins
467
649
  */
468
 
  std::map<std::string, plugin::Module *>::const_iterator modules=
469
 
    registry.getModulesMap().begin();
470
 
    
471
 
  while (modules != registry.getModulesMap().end())
 
650
  for (idx= 0; idx < plugin_array.elements; idx++)
472
651
  {
473
 
    module= (*modules).second;
474
 
    ++modules;
475
 
    if (module->isInited == false)
 
652
    plugin_ptr= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
 
653
    if (plugin_ptr->isInited == false)
476
654
    {
477
 
      plugin_initialize_vars(module);
478
 
 
479
 
      if (plugin_initialize(registry, module))
480
 
        delete_module(module);
 
655
      if (plugin_initialize(plugin_ptr))
 
656
        plugin_del(plugin_ptr);
481
657
    }
482
658
  }
483
659
 
484
660
 
485
 
  free_root(&tmp_root, MYF(0));
486
 
 
487
 
  return false;
488
 
}
489
 
 
490
 
class PrunePlugin :
491
 
  public unary_function<string, bool>
492
 
{
493
 
  const string to_match;
494
 
  PrunePlugin();
495
 
  PrunePlugin& operator=(const PrunePlugin&);
496
 
public:
497
 
  explicit PrunePlugin(const string &match_in) :
498
 
    to_match(match_in)
499
 
  { }
500
 
 
501
 
  result_type operator()(const string &match_against)
502
 
  {
503
 
    return match_against == to_match;
504
 
  }
505
 
};
506
 
 
507
 
static void plugin_prune_list(vector<string> &plugin_list,
508
 
                              const vector<string> &plugins_to_remove)
509
 
{
510
 
  for (vector<string>::const_iterator iter= plugins_to_remove.begin();
511
 
       iter != plugins_to_remove.end();
512
 
       ++iter)
513
 
  {
514
 
    plugin_list.erase(remove_if(plugin_list.begin(),
515
 
                                plugin_list.end(),
516
 
                                PrunePlugin(*iter)),
517
 
                      plugin_list.end());
518
 
  }
519
 
}
 
661
end:
 
662
  free_root(&tmp_root, MYF(0));
 
663
 
 
664
  return(0);
 
665
 
 
666
err_unlock:
 
667
err:
 
668
  free_root(&tmp_root, MYF(0));
 
669
  return(1);
 
670
}
 
671
 
 
672
 
 
673
static bool register_builtin(struct st_plugin_int *tmp,
 
674
                             struct st_plugin_int **ptr)
 
675
{
 
676
 
 
677
  PluginRegistry &registry= PluginRegistry::getPluginRegistry();
 
678
 
 
679
  tmp->isInited= false;
 
680
  tmp->plugin_dl= 0;
 
681
 
 
682
  if (insert_dynamic(&plugin_array, (unsigned char*)&tmp))
 
683
    return(1);
 
684
 
 
685
  *ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1,
 
686
                         struct st_plugin_int **)=
 
687
        (struct st_plugin_int *) memdup_root(&plugin_mem_root, (unsigned char*)tmp,
 
688
                                             sizeof(struct st_plugin_int));
 
689
 
 
690
  registry.add(*ptr);
 
691
 
 
692
  return(0);
 
693
}
 
694
 
520
695
 
521
696
/*
522
697
  called only by plugin_init()
523
698
*/
524
 
static bool plugin_load_list(plugin::Registry &registry,
525
 
                             memory::Root *tmp_root, int *argc, char **argv,
526
 
                             const vector<string> &plugin_list)
 
699
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
 
700
                             const char *list)
527
701
{
528
 
  plugin::Library *library= NULL;
529
 
 
530
 
  for (vector<string>::const_iterator iter= plugin_list.begin();
531
 
       iter != plugin_list.end();
532
 
       ++iter)
 
702
  char buffer[FN_REFLEN];
 
703
  LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
 
704
  struct st_plugin_dl *plugin_dl;
 
705
  struct drizzled_plugin_manifest *plugin;
 
706
  char *p= buffer;
 
707
  while (list)
533
708
  {
534
 
    const string plugin_name(*iter);
535
 
    library= registry.addLibrary(plugin_name);
536
 
    if (library == NULL)
 
709
    if (p == buffer + sizeof(buffer) - 1)
537
710
    {
538
 
      errmsg_printf(ERRMSG_LVL_ERROR,
539
 
                    _("Couldn't load plugin library named '%s'.\n"),
540
 
                    plugin_name.c_str());
541
 
      return true;
 
711
      errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
 
712
      return(true);
542
713
    }
543
714
 
544
 
    free_root(tmp_root, MYF(memory::MARK_BLOCKS_FREE));
545
 
    if (plugin_add(registry, tmp_root, library, argc, argv))
546
 
    {
547
 
      registry.removeLibrary(plugin_name);
548
 
      errmsg_printf(ERRMSG_LVL_ERROR,
549
 
                    _("Couldn't load plugin named '%s'.\n"),
550
 
                    plugin_name.c_str());
551
 
      return true;
552
 
 
 
715
    switch ((*(p++)= *(list++))) {
 
716
    case '\0':
 
717
      list= NULL; /* terminate the loop */
 
718
      /* fall through */
 
719
    case ':':     /* can't use this as delimiter as it may be drive letter */
 
720
    case ';':
 
721
      str->str[str->length]= '\0';
 
722
      if (str == &name)  // load all plugins in named module
 
723
      {
 
724
        if (!name.length)
 
725
        {
 
726
          p--;    /* reset pointer */
 
727
          continue;
 
728
        }
 
729
 
 
730
        dl= name;
 
731
        if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
 
732
        {
 
733
          for (plugin= plugin_dl->plugins; plugin->name; plugin++)
 
734
          {
 
735
            name.str= (char *) plugin->name;
 
736
            name.length= strlen(name.str);
 
737
 
 
738
            free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
 
739
            if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
 
740
              goto error;
 
741
          }
 
742
          plugin_dl_del(&dl); // reduce ref count
 
743
        }
 
744
      }
 
745
      else
 
746
      {
 
747
        free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
 
748
        if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
 
749
          goto error;
 
750
      }
 
751
      name.length= dl.length= 0;
 
752
      dl.str= NULL; name.str= p= buffer;
 
753
      str= &name;
 
754
      continue;
 
755
    case '=':
 
756
    case '#':
 
757
      if (str == &name)
 
758
      {
 
759
        name.str[name.length]= '\0';
 
760
        str= &dl;
 
761
        str->str= p;
 
762
        continue;
 
763
      }
 
764
    default:
 
765
      str->length++;
 
766
      continue;
553
767
    }
554
768
  }
555
 
  return false;
 
769
  return(false);
 
770
error:
 
771
  errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
 
772
                  name.str, dl.str);
 
773
  return(true);
556
774
}
557
775
 
558
776
 
559
 
void plugin_shutdown(plugin::Registry &registry)
 
777
void plugin_shutdown(void)
560
778
{
 
779
  uint32_t idx;
 
780
  size_t count= plugin_array.elements;
 
781
  vector<st_plugin_int *> plugins;
 
782
  vector<st_plugin_dl *> dl;
561
783
 
562
784
  if (initialized)
563
785
  {
564
786
    reap_needed= true;
565
787
 
566
 
    reap_plugins(registry);
 
788
    reap_plugins();
567
789
    unlock_variables(NULL, &global_system_variables);
568
790
    unlock_variables(NULL, &max_system_variables);
569
791
 
575
797
 
576
798
  /* Dispose of the memory */
577
799
 
 
800
  delete_dynamic(&plugin_array);
 
801
 
 
802
  count= plugin_dl_array.elements;
 
803
  dl.reserve(count);
 
804
  for (idx= 0; idx < count; idx++)
 
805
    dl.push_back(*dynamic_element(&plugin_dl_array, idx,
 
806
                 struct st_plugin_dl **));
 
807
  for (idx= 0; idx < count; idx++)
 
808
    free_plugin_mem(dl[idx]);
 
809
  delete_dynamic(&plugin_dl_array);
 
810
 
578
811
  hash_free(&bookmark_hash);
579
812
  free_root(&plugin_mem_root, MYF(0));
580
813
 
589
822
#define DRIZZLE_SYSVAR_NAME(name) name
590
823
#define PLUGIN_VAR_TYPEMASK 0x007f
591
824
 
592
 
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
 
825
#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */
593
826
 
594
827
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
595
828
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
596
829
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
597
830
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
598
831
 
 
832
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_enum_t, unsigned long);
599
833
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
 
834
typedef DECLARE_DRIZZLE_SYSVAR_TYPELIB(sysvar_set_t, uint64_t);
600
835
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
601
836
 
602
837
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
620
855
  default variable data check and update functions
621
856
****************************************************************************/
622
857
 
623
 
static int check_func_bool(Session *, drizzle_sys_var *var,
624
 
                           void *save, drizzle_value *value)
 
858
static int check_func_bool(Session *, struct st_mysql_sys_var *var,
 
859
                           void *save, st_mysql_value *value)
625
860
{
626
861
  char buff[STRING_BUFFER_USUAL_SIZE];
627
862
  const char *strvalue= "NULL", *str;
645
880
      goto err;
646
881
    if (tmp > 1)
647
882
    {
648
 
      internal::llstr(tmp, buff);
 
883
      llstr(tmp, buff);
649
884
      strvalue= buff;
650
885
      goto err;
651
886
    }
659
894
}
660
895
 
661
896
 
662
 
static int check_func_int(Session *session, drizzle_sys_var *var,
663
 
                          void *save, drizzle_value *value)
 
897
static int check_func_int(Session *session, struct st_mysql_sys_var *var,
 
898
                          void *save, st_mysql_value *value)
664
899
{
665
900
  bool fixed;
666
901
  int64_t tmp;
679
914
}
680
915
 
681
916
 
682
 
static int check_func_long(Session *session, drizzle_sys_var *var,
683
 
                          void *save, drizzle_value *value)
 
917
static int check_func_long(Session *session, struct st_mysql_sys_var *var,
 
918
                          void *save, st_mysql_value *value)
684
919
{
685
920
  bool fixed;
686
921
  int64_t tmp;
699
934
}
700
935
 
701
936
 
702
 
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
703
 
                               void *save, drizzle_value *value)
 
937
static int check_func_int64_t(Session *session, struct st_mysql_sys_var *var,
 
938
                               void *save, st_mysql_value *value)
704
939
{
705
940
  bool fixed;
706
941
  int64_t tmp;
718
953
                              var->name, (int64_t) tmp);
719
954
}
720
955
 
721
 
static int check_func_str(Session *session, drizzle_sys_var *,
722
 
                          void *save, drizzle_value *value)
 
956
static int check_func_str(Session *session, struct st_mysql_sys_var *,
 
957
                          void *save, st_mysql_value *value)
723
958
{
724
959
  char buff[STRING_BUFFER_USUAL_SIZE];
725
960
  const char *str;
733
968
}
734
969
 
735
970
 
736
 
static void update_func_bool(Session *, drizzle_sys_var *,
 
971
static int check_func_enum(Session *, struct st_mysql_sys_var *var,
 
972
                           void *save, st_mysql_value *value)
 
973
{
 
974
  char buff[STRING_BUFFER_USUAL_SIZE];
 
975
  const char *strvalue= "NULL", *str;
 
976
  TYPELIB *typelib;
 
977
  int64_t tmp;
 
978
  long result;
 
979
  int length;
 
980
 
 
981
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
982
    typelib= ((sessionvar_enum_t*) var)->typelib;
 
983
  else
 
984
    typelib= ((sysvar_enum_t*) var)->typelib;
 
985
 
 
986
  if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
 
987
  {
 
988
    length= sizeof(buff);
 
989
    if (!(str= value->val_str(value, buff, &length)))
 
990
      goto err;
 
991
    if ((result= (long)find_type(typelib, str, length, 1)-1) < 0)
 
992
    {
 
993
      strvalue= str;
 
994
      goto err;
 
995
    }
 
996
  }
 
997
  else
 
998
  {
 
999
    if (value->val_int(value, &tmp))
 
1000
      goto err;
 
1001
    if (tmp >= typelib->count)
 
1002
    {
 
1003
      llstr(tmp, buff);
 
1004
      strvalue= buff;
 
1005
      goto err;
 
1006
    }
 
1007
    result= (long) tmp;
 
1008
  }
 
1009
  *(long*)save= result;
 
1010
  return 0;
 
1011
err:
 
1012
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
 
1013
  return 1;
 
1014
}
 
1015
 
 
1016
 
 
1017
static int check_func_set(Session *, struct st_mysql_sys_var *var,
 
1018
                          void *save, st_mysql_value *value)
 
1019
{
 
1020
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
 
1021
  const char *strvalue= "NULL", *str;
 
1022
  TYPELIB *typelib;
 
1023
  uint64_t result;
 
1024
  uint32_t error_len;
 
1025
  bool not_used;
 
1026
  int length;
 
1027
 
 
1028
  if (var->flags & PLUGIN_VAR_SessionLOCAL)
 
1029
    typelib= ((sessionvar_set_t*) var)->typelib;
 
1030
  else
 
1031
    typelib= ((sysvar_set_t*)var)->typelib;
 
1032
 
 
1033
  if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
 
1034
  {
 
1035
    length= sizeof(buff);
 
1036
    if (!(str= value->val_str(value, buff, &length)))
 
1037
      goto err;
 
1038
    result= find_set(typelib, str, length, NULL,
 
1039
                     &error, &error_len, &not_used);
 
1040
    if (error_len)
 
1041
    {
 
1042
      length= min((uint32_t)sizeof(buff), error_len);
 
1043
      strncpy(buff, error, length);
 
1044
      buff[length]= '\0';
 
1045
      strvalue= buff;
 
1046
      goto err;
 
1047
    }
 
1048
  }
 
1049
  else
 
1050
  {
 
1051
    if (value->val_int(value, (int64_t *)&result))
 
1052
      goto err;
 
1053
    if (unlikely((result >= (1UL << typelib->count)) &&
 
1054
                 (typelib->count < sizeof(long)*8)))
 
1055
    {
 
1056
      llstr(result, buff);
 
1057
      strvalue= buff;
 
1058
      goto err;
 
1059
    }
 
1060
  }
 
1061
  *(uint64_t*)save= result;
 
1062
  return 0;
 
1063
err:
 
1064
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
 
1065
  return 1;
 
1066
}
 
1067
 
 
1068
 
 
1069
static void update_func_bool(Session *, struct st_mysql_sys_var *,
737
1070
                             void *tgt, const void *save)
738
1071
{
739
1072
  *(bool *) tgt= *(int *) save ? 1 : 0;
740
1073
}
741
1074
 
742
1075
 
743
 
static void update_func_int(Session *, drizzle_sys_var *,
 
1076
static void update_func_int(Session *, struct st_mysql_sys_var *,
744
1077
                             void *tgt, const void *save)
745
1078
{
746
1079
  *(int *)tgt= *(int *) save;
747
1080
}
748
1081
 
749
1082
 
750
 
static void update_func_long(Session *, drizzle_sys_var *,
 
1083
static void update_func_long(Session *, struct st_mysql_sys_var *,
751
1084
                             void *tgt, const void *save)
752
1085
{
753
1086
  *(long *)tgt= *(long *) save;
754
1087
}
755
1088
 
756
1089
 
757
 
static void update_func_int64_t(Session *, drizzle_sys_var *,
 
1090
static void update_func_int64_t(Session *, struct st_mysql_sys_var *,
758
1091
                                 void *tgt, const void *save)
759
1092
{
760
1093
  *(int64_t *)tgt= *(uint64_t *) save;
761
1094
}
762
1095
 
763
1096
 
764
 
static void update_func_str(Session *, drizzle_sys_var *var,
 
1097
static void update_func_str(Session *, struct st_mysql_sys_var *var,
765
1098
                             void *tgt, const void *save)
766
1099
{
767
1100
  char *old= *(char **) tgt;
790
1123
{
791
1124
  sys_var *var;
792
1125
  sys_var_pluginvar *pi= NULL;
793
 
  plugin::Module *module;
 
1126
  st_plugin_int *plugin;
794
1127
 
795
1128
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
796
1129
  if ((var= intern_find_sys_var(str, length, false)) &&
797
1130
      (pi= var->cast_pluginvar()))
798
1131
  {
799
1132
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
800
 
    if (!(module= pi->plugin))
 
1133
    if (!(plugin= pi->plugin))
801
1134
      var= NULL; /* failed to lock it, it must be uninstalling */
802
 
    else if (module->isInited == false)
 
1135
    else if (plugin->isInited == false)
803
1136
    {
804
1137
      var= NULL;
805
1138
    }
816
1149
  return(var);
817
1150
}
818
1151
 
819
 
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
820
 
{
821
 
  /* Embed the flags into the first char of the string */
822
 
  string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
823
 
  varname.append(plugin);
824
 
  varname.push_back('_');
825
 
  varname.append(name);
826
 
 
827
 
  for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
828
 
  {
829
 
    if (*p == '-')
830
 
    {
831
 
      *p= '_';
832
 
    }
833
 
  }
834
 
  return varname;
835
 
}
836
1152
 
837
1153
/*
838
1154
  called by register_var, construct_options and test_plugin_options.
839
1155
  Returns the 'bookmark' for the named variable.
840
1156
  LOCK_system_variables_hash should be at least read locked
841
1157
*/
842
 
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
 
1158
static st_bookmark *find_bookmark(const char *plugin, const char *name, int flags)
843
1159
{
844
1160
  st_bookmark *result= NULL;
 
1161
  uint32_t namelen, length, pluginlen= 0;
 
1162
  char *varname, *p;
845
1163
 
846
1164
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
847
1165
    return NULL;
848
1166
 
849
 
  const string varname(make_bookmark_name(plugin, name, flags));
850
 
 
 
1167
  namelen= strlen(name);
 
1168
  if (plugin)
 
1169
    pluginlen= strlen(plugin) + 1;
 
1170
  length= namelen + pluginlen + 2;
 
1171
  varname= (char*) malloc(length);
 
1172
 
 
1173
  if (plugin)
 
1174
  {
 
1175
    sprintf(varname+1,"%s_%s",plugin,name);
 
1176
    for (p= varname + 1; *p; p++)
 
1177
      if (*p == '-')
 
1178
        *p= '_';
 
1179
  }
 
1180
  else
 
1181
    memcpy(varname + 1, name, namelen + 1);
 
1182
 
 
1183
  varname[0]= flags & PLUGIN_VAR_TYPEMASK;
851
1184
 
852
1185
  result= (st_bookmark*) hash_search(&bookmark_hash,
853
 
                                     (const unsigned char*) varname.c_str(), varname.size() - 1);
 
1186
                                     (const unsigned char*) varname, length - 1);
854
1187
 
 
1188
  free(varname);
855
1189
  return result;
856
1190
}
857
1191
 
861
1195
  returns null for non session-local variables.
862
1196
  Requires that a write lock is obtained on LOCK_system_variables_hash
863
1197
*/
864
 
static st_bookmark *register_var(const string &plugin, const char *name,
 
1198
static st_bookmark *register_var(const char *plugin, const char *name,
865
1199
                                 int flags)
866
1200
{
867
 
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
868
 
    return NULL;
869
 
 
870
 
  uint32_t size= 0, offset, new_size;
 
1201
  uint32_t length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
871
1202
  st_bookmark *result;
 
1203
  char *varname, *p;
 
1204
 
 
1205
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
 
1206
    return NULL;
872
1207
 
873
1208
  switch (flags & PLUGIN_VAR_TYPEMASK) {
874
1209
  case PLUGIN_VAR_BOOL:
878
1213
    size= ALIGN_SIZE(sizeof(int));
879
1214
    break;
880
1215
  case PLUGIN_VAR_LONG:
 
1216
  case PLUGIN_VAR_ENUM:
881
1217
    size= ALIGN_SIZE(sizeof(long));
882
1218
    break;
883
1219
  case PLUGIN_VAR_LONGLONG:
 
1220
  case PLUGIN_VAR_SET:
884
1221
    size= ALIGN_SIZE(sizeof(uint64_t));
885
1222
    break;
886
1223
  case PLUGIN_VAR_STR:
891
1228
    return NULL;
892
1229
  };
893
1230
 
 
1231
  varname= ((char*) malloc(length));
 
1232
  sprintf(varname+1, "%s_%s", plugin, name);
 
1233
  for (p= varname + 1; *p; p++)
 
1234
    if (*p == '-')
 
1235
      *p= '_';
894
1236
 
895
 
  if (!(result= find_bookmark(plugin, name, flags)))
 
1237
  if (!(result= find_bookmark(NULL, varname + 1, flags)))
896
1238
  {
897
 
    const string varname(make_bookmark_name(plugin, name, flags));
898
 
 
899
 
    result= static_cast<st_bookmark*>(alloc_root(&plugin_mem_root,
900
 
                                      sizeof(struct st_bookmark) + varname.size() + 1));
901
 
    memset(result->key, 0, varname.size()+1);
902
 
    memcpy(result->key, varname.c_str(), varname.size());
903
 
    result->name_len= varname.size() - 2;
 
1239
    result= (st_bookmark*) alloc_root(&plugin_mem_root,
 
1240
                                      sizeof(struct st_bookmark) + length-1);
 
1241
    varname[0]= flags & PLUGIN_VAR_TYPEMASK;
 
1242
    memcpy(result->key, varname, length);
 
1243
    result->name_len= length - 2;
904
1244
    result->offset= -1;
905
1245
 
906
1246
    assert(size && !(size & (size-1))); /* must be power of 2 */
956
1296
      assert(0);
957
1297
    }
958
1298
  }
 
1299
  free(varname);
959
1300
  return result;
960
1301
}
961
1302
 
993
1334
    if (global_lock)
994
1335
      pthread_mutex_lock(&LOCK_global_system_variables);
995
1336
 
996
 
    //safe_mutex_assert_owner(&LOCK_global_system_variables);
 
1337
    safe_mutex_assert_owner(&LOCK_global_system_variables);
997
1338
 
998
1339
    memcpy(session->variables.dynamic_variables_ptr +
999
1340
             session->variables.dynamic_variables_size,
1073
1414
  return (char **)intern_sys_var_ptr(a_session, offset, true);
1074
1415
}
1075
1416
 
 
1417
static uint64_t *mysql_sys_var_ptr_set(Session* a_session, int offset)
 
1418
{
 
1419
  return (uint64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1420
}
 
1421
 
 
1422
static unsigned long *mysql_sys_var_ptr_enum(Session* a_session, int offset)
 
1423
{
 
1424
  return (unsigned long *)intern_sys_var_ptr(a_session, offset, true);
 
1425
}
 
1426
 
 
1427
 
1076
1428
void plugin_sessionvar_init(Session *session)
1077
1429
{
1078
1430
  session->variables.storage_engine= NULL;
1212
1564
    return SHOW_LONGLONG;
1213
1565
  case PLUGIN_VAR_STR:
1214
1566
    return SHOW_CHAR_PTR;
 
1567
  case PLUGIN_VAR_ENUM:
 
1568
  case PLUGIN_VAR_SET:
 
1569
    return SHOW_CHAR;
1215
1570
  default:
1216
1571
    assert(0);
1217
1572
    return SHOW_UNDEF;
1219
1574
}
1220
1575
 
1221
1576
 
1222
 
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
 
1577
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, enum_var_type type)
1223
1578
{
1224
1579
  assert(session || (type == OPT_GLOBAL));
1225
1580
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
1236
1591
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
1237
1592
{
1238
1593
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
1239
 
  case PLUGIN_VAR_SessionLOCAL:
 
1594
  case PLUGIN_VAR_ENUM:
 
1595
    return ((sysvar_enum_t *)plugin_var)->typelib;
 
1596
  case PLUGIN_VAR_SET:
 
1597
    return ((sysvar_set_t *)plugin_var)->typelib;
 
1598
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
1240
1599
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
1600
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
 
1601
    return ((sessionvar_set_t *)plugin_var)->typelib;
1241
1602
  default:
1242
1603
    return NULL;
1243
1604
  }
1245
1606
}
1246
1607
 
1247
1608
 
1248
 
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
 
1609
unsigned char* sys_var_pluginvar::value_ptr(Session *session, enum_var_type type, const LEX_STRING *)
1249
1610
{
1250
1611
  unsigned char* result;
1251
1612
 
1252
1613
  result= real_value_ptr(session, type);
1253
1614
 
 
1615
  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM)
 
1616
    result= (unsigned char*) get_type(plugin_var_typelib(), *(ulong*)result);
 
1617
  else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET)
 
1618
  {
 
1619
    char buffer[STRING_BUFFER_USUAL_SIZE];
 
1620
    String str(buffer, sizeof(buffer), system_charset_info);
 
1621
    TYPELIB *typelib= plugin_var_typelib();
 
1622
    uint64_t mask= 1, value= *(uint64_t*) result;
 
1623
    uint32_t i;
 
1624
 
 
1625
    str.length(0);
 
1626
    for (i= 0; i < typelib->count; i++, mask<<=1)
 
1627
    {
 
1628
      if (!(value & mask))
 
1629
        continue;
 
1630
      str.append(typelib->type_names[i], typelib->type_lengths[i]);
 
1631
      str.append(',');
 
1632
    }
 
1633
 
 
1634
    result= (unsigned char*) "";
 
1635
    if (str.length())
 
1636
      result= (unsigned char*) session->strmake(str.ptr(), str.length()-1);
 
1637
  }
1254
1638
  return result;
1255
1639
}
1256
1640
 
1271
1655
}
1272
1656
 
1273
1657
 
1274
 
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
 
1658
void sys_var_pluginvar::set_default(Session *session, enum_var_type type)
1275
1659
{
1276
1660
  const void *src;
1277
1661
  void *tgt;
1300
1684
        case PLUGIN_VAR_LONGLONG:
1301
1685
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
1302
1686
          break;
 
1687
        case PLUGIN_VAR_ENUM:
 
1688
          src= &((sessionvar_enum_t*) plugin_var)->def_val;
 
1689
          break;
 
1690
        case PLUGIN_VAR_SET:
 
1691
          src= &((sessionvar_set_t*) plugin_var)->def_val;
 
1692
          break;
1303
1693
        case PLUGIN_VAR_BOOL:
1304
1694
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
1305
1695
          break;
1367
1757
  options->block_size= (long) (opt)->blk_sz
1368
1758
 
1369
1759
 
1370
 
void plugin_opt_set_limits(struct my_option *options,
1371
 
                                                                                                         const drizzle_sys_var *opt)
 
1760
static void plugin_opt_set_limits(struct my_option *options,
 
1761
                                  const struct st_mysql_sys_var *opt)
1372
1762
{
1373
1763
  options->sub_size= 0;
1374
1764
 
1393
1783
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
1394
1784
    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
1395
1785
    break;
 
1786
  case PLUGIN_VAR_ENUM:
 
1787
    options->var_type= GET_ENUM;
 
1788
    options->typelib= ((sysvar_enum_t*) opt)->typelib;
 
1789
    options->def_value= ((sysvar_enum_t*) opt)->def_val;
 
1790
    options->min_value= options->block_size= 0;
 
1791
    options->max_value= options->typelib->count - 1;
 
1792
    break;
 
1793
  case PLUGIN_VAR_SET:
 
1794
    options->var_type= GET_SET;
 
1795
    options->typelib= ((sysvar_set_t*) opt)->typelib;
 
1796
    options->def_value= ((sysvar_set_t*) opt)->def_val;
 
1797
    options->min_value= options->block_size= 0;
 
1798
    options->max_value= (1UL << options->typelib->count) - 1;
 
1799
    break;
1396
1800
  case PLUGIN_VAR_BOOL:
1397
1801
    options->var_type= GET_BOOL;
1398
1802
    options->def_value= ((sysvar_bool_t*) opt)->def_val;
1421
1825
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
1422
1826
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
1423
1827
    break;
 
1828
  case PLUGIN_VAR_ENUM | PLUGIN_VAR_SessionLOCAL:
 
1829
    options->var_type= GET_ENUM;
 
1830
    options->typelib= ((sessionvar_enum_t*) opt)->typelib;
 
1831
    options->def_value= ((sessionvar_enum_t*) opt)->def_val;
 
1832
    options->min_value= options->block_size= 0;
 
1833
    options->max_value= options->typelib->count - 1;
 
1834
    break;
 
1835
  case PLUGIN_VAR_SET | PLUGIN_VAR_SessionLOCAL:
 
1836
    options->var_type= GET_SET;
 
1837
    options->typelib= ((sessionvar_set_t*) opt)->typelib;
 
1838
    options->def_value= ((sessionvar_set_t*) opt)->def_val;
 
1839
    options->min_value= options->block_size= 0;
 
1840
    options->max_value= (1UL << options->typelib->count) - 1;
 
1841
    break;
1424
1842
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
1425
1843
    options->var_type= GET_BOOL;
1426
1844
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
1440
1858
    options->arg_type= OPT_ARG;
1441
1859
}
1442
1860
 
1443
 
static bool get_one_plugin_option(int, const struct my_option *, char *)
 
1861
extern "C" bool get_one_plugin_option(int optid, const struct my_option *,
 
1862
                                         char *);
 
1863
 
 
1864
bool get_one_plugin_option(int, const struct my_option *, char *)
1444
1865
{
1445
1866
  return 0;
1446
1867
}
1447
1868
 
1448
1869
 
1449
 
static int construct_options(memory::Root *mem_root, plugin::Module *tmp,
1450
 
                             my_option *options)
 
1870
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
 
1871
                             my_option *options, bool can_disable)
1451
1872
{
1452
 
  
1453
 
  int localoptionid= 256;
1454
 
  const string plugin_name(tmp->getManifest().name);
1455
 
 
1456
 
  size_t namelen= plugin_name.size(), optnamelen;
1457
 
 
 
1873
  const char *plugin_name= tmp->plugin->name;
 
1874
  uint32_t namelen= strlen(plugin_name), optnamelen;
 
1875
  uint32_t buffer_length= namelen * 4 + (can_disable ? 75 : 10);
 
1876
  char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
1458
1877
  char *optname, *p;
1459
1878
  int index= 0, offset= 0;
1460
 
  drizzle_sys_var *opt, **plugin_option;
 
1879
  st_mysql_sys_var *opt, **plugin_option;
1461
1880
  st_bookmark *v;
1462
1881
 
1463
 
  string name(plugin_name);
1464
 
  transform(name.begin(), name.end(), name.begin(), ::tolower);
1465
 
 
1466
 
  for (string::iterator iter= name.begin(); iter != name.end(); ++iter)
 
1882
  /* support --skip-plugin-foo syntax */
 
1883
  memcpy(name, plugin_name, namelen + 1);
 
1884
  my_casedn_str(&my_charset_utf8_general_ci, name);
 
1885
  sprintf(name+namelen+1, "plugin-%s", name);
 
1886
  /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
 
1887
 
 
1888
  for (p= name + namelen*2 + 8; p > name; p--)
 
1889
    if (*p == '_')
 
1890
      *p= '-';
 
1891
 
 
1892
  if (can_disable)
1467
1893
  {
1468
 
    if (*iter == '_')
1469
 
      *iter= '-';
 
1894
    sprintf(name+namelen*2+10,
 
1895
            "Enable %s plugin. Disable with --skip-%s (will save memory).",
 
1896
            plugin_name, name);
 
1897
    /*
 
1898
      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
 
1899
      20 + namelen + 20 + 1 == namelen * 4 + 67.
 
1900
    */
 
1901
 
 
1902
    options[0].comment= name + namelen*2 + 10;
1470
1903
  }
1471
1904
 
 
1905
  options[1].name= (options[0].name= name) + namelen + 1;
 
1906
  options[0].id= options[1].id= 256; /* must be >255. dup id ok */
 
1907
  options[0].var_type= options[1].var_type= GET_BOOL;
 
1908
  options[0].arg_type= options[1].arg_type= NO_ARG;
 
1909
  options[0].def_value= options[1].def_value= true;
 
1910
  options[0].value= options[0].u_max_value=
 
1911
  options[1].value= options[1].u_max_value= (char**) (name - 1);
 
1912
  options+= 2;
 
1913
 
1472
1914
  /*
1473
1915
    Two passes as the 2nd pass will take pointer addresses for use
1474
1916
    by my_getopt and register_var() in the first pass uses realloc
1475
1917
  */
1476
1918
 
1477
 
  for (plugin_option= tmp->getManifest().system_vars;
 
1919
  for (plugin_option= tmp->plugin->system_vars;
1478
1920
       plugin_option && *plugin_option; plugin_option++, index++)
1479
1921
  {
1480
1922
    opt= *plugin_option;
1498
1940
    case PLUGIN_VAR_STR:
1499
1941
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
1500
1942
      break;
 
1943
    case PLUGIN_VAR_ENUM:
 
1944
      (((sessionvar_enum_t *)opt)->resolve)= mysql_sys_var_ptr_enum;
 
1945
      break;
 
1946
    case PLUGIN_VAR_SET:
 
1947
      (((sessionvar_set_t *)opt)->resolve)= mysql_sys_var_ptr_set;
 
1948
      break;
1501
1949
    default:
1502
1950
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1503
 
                      opt->flags, plugin_name.c_str());
 
1951
                      opt->flags, plugin_name);
1504
1952
      return(-1);
1505
1953
    };
1506
1954
  }
1507
1955
 
1508
 
  for (plugin_option= tmp->getManifest().system_vars;
 
1956
  for (plugin_option= tmp->plugin->system_vars;
1509
1957
       plugin_option && *plugin_option; plugin_option++, index++)
1510
1958
  {
1511
1959
    switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
1545
1993
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
1546
1994
                            "to be read-only: string variable without "
1547
1995
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
1548
 
                            opt->name, plugin_name.c_str());
 
1996
                            opt->name, plugin_name);
1549
1997
        }
1550
1998
      }
1551
1999
      break;
 
2000
    case PLUGIN_VAR_ENUM:
 
2001
      if (!opt->check)
 
2002
        opt->check= check_func_enum;
 
2003
      if (!opt->update)
 
2004
        opt->update= update_func_long;
 
2005
      break;
 
2006
    case PLUGIN_VAR_SET:
 
2007
      if (!opt->check)
 
2008
        opt->check= check_func_set;
 
2009
      if (!opt->update)
 
2010
        opt->update= update_func_int64_t;
 
2011
      break;
1552
2012
    default:
1553
2013
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
1554
 
                      opt->flags, plugin_name.c_str());
 
2014
                      opt->flags, plugin_name);
1555
2015
      return(-1);
1556
2016
    }
1557
2017
 
1562
2022
    if (!opt->name)
1563
2023
    {
1564
2024
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
1565
 
                    plugin_name.c_str());
 
2025
                      plugin_name);
1566
2026
      return(-1);
1567
2027
    }
1568
2028
 
1570
2030
    {
1571
2031
      optnamelen= strlen(opt->name);
1572
2032
      optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
1573
 
      sprintf(optname, "%s-%s", name.c_str(), opt->name);
 
2033
      sprintf(optname, "%s-%s", name, opt->name);
1574
2034
      optnamelen= namelen + optnamelen + 1;
1575
2035
    }
1576
2036
    else
1579
2039
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
1580
2040
      {
1581
2041
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
1582
 
                      "in plugin '%s'."), opt->name, plugin_name.c_str());
 
2042
                        "in plugin '%s'."), opt->name, plugin_name);
1583
2043
        return(-1);
1584
2044
      }
1585
2045
 
1600
2060
    options->name= optname;
1601
2061
    options->comment= opt->comment;
1602
2062
    options->app_type= opt;
1603
 
    options->id= localoptionid++;
 
2063
    options->id= (options-1)->id + 1;
1604
2064
 
1605
2065
    plugin_opt_set_limits(options, opt);
1606
2066
 
1610
2070
    else
1611
2071
      options->value= options->u_max_value= *(char***) (opt + 1);
1612
2072
 
1613
 
    options++;
 
2073
    options[1]= options[0];
 
2074
    options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
 
2075
    options[1].comment= 0; // hidden
 
2076
    sprintf(p,"plugin-%s",optname);
 
2077
 
 
2078
    options+= 2;
1614
2079
  }
1615
2080
 
1616
2081
  return(0);
1617
2082
}
1618
2083
 
1619
2084
 
1620
 
static my_option *construct_help_options(memory::Root *mem_root, plugin::Module *p)
 
2085
static my_option *construct_help_options(MEM_ROOT *mem_root,
 
2086
                                         struct st_plugin_int *p)
1621
2087
{
1622
 
  drizzle_sys_var **opt;
 
2088
  st_mysql_sys_var **opt;
1623
2089
  my_option *opts;
 
2090
  bool can_disable;
1624
2091
  uint32_t count= EXTRA_OPTIONS;
1625
2092
 
1626
 
  for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
 
2093
  for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) {};
1627
2094
 
1628
 
  opts= (my_option*)alloc_root(mem_root, (sizeof(my_option) * count));
1629
 
  if (opts == NULL)
 
2095
  if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
1630
2096
    return NULL;
1631
2097
 
1632
2098
  memset(opts, 0, sizeof(my_option) * count);
1633
2099
 
1634
 
  if (construct_options(mem_root, p, opts))
 
2100
  if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MyISAM") == 0))
 
2101
    can_disable= false;
 
2102
  else if ((my_strcasecmp(&my_charset_utf8_general_ci, p->name.str, "MEMORY") == 0))
 
2103
    can_disable= false;
 
2104
  else
 
2105
    can_disable= true;
 
2106
 
 
2107
 
 
2108
  if (construct_options(mem_root, p, opts, can_disable))
1635
2109
    return NULL;
1636
2110
 
1637
2111
  return(opts);
1638
2112
}
1639
2113
 
1640
 
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
1641
 
{
1642
 
  plugin_sysvar_vec.push_back(var);
1643
 
}
1644
 
 
1645
 
void drizzle_del_plugin_sysvar()
1646
 
{
1647
 
  vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
1648
 
  while(iter != plugin_sysvar_vec.end())
1649
 
  {
1650
 
    delete *iter;
1651
 
    ++iter;
1652
 
  }
1653
 
  plugin_sysvar_vec.clear();
1654
 
}
1655
2114
 
1656
2115
/*
1657
2116
  SYNOPSIS
1666
2125
  NOTE:
1667
2126
    Requires that a write-lock is held on LOCK_system_variables_hash
1668
2127
*/
1669
 
static int test_plugin_options(memory::Root *tmp_root, plugin::Module *tmp,
 
2128
static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
1670
2129
                               int *argc, char **argv)
1671
2130
{
1672
2131
  struct sys_var_chain chain= { NULL, NULL };
1673
 
  drizzle_sys_var **opt;
 
2132
  bool can_disable;
 
2133
  MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
 
2134
                      &tmp->mem_root : &plugin_mem_root;
 
2135
  st_mysql_sys_var **opt;
1674
2136
  my_option *opts= NULL;
 
2137
  char *p, *varname;
1675
2138
  int error;
1676
 
  drizzle_sys_var *o;
 
2139
  st_mysql_sys_var *o;
 
2140
  sys_var *v;
1677
2141
  struct st_bookmark *var;
1678
2142
  uint32_t len, count= EXTRA_OPTIONS;
1679
 
 
1680
 
  for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
1681
 
    count++;
1682
 
 
 
2143
  assert(tmp->plugin && tmp->name.str);
 
2144
 
 
2145
  for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
 
2146
    count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
 
2147
 
 
2148
  if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->name.str, "MyISAM") == 0))
 
2149
    can_disable= false;
 
2150
  else if ((my_strcasecmp(&my_charset_utf8_general_ci, tmp->name.str, "MEMORY") == 0))
 
2151
    can_disable= false;
 
2152
  else
 
2153
    can_disable= true;
1683
2154
 
1684
2155
  if (count > EXTRA_OPTIONS || (*argc > 1))
1685
2156
  {
1686
2157
    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
1687
2158
    {
1688
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
 
2159
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->name.str);
1689
2160
      return(-1);
1690
2161
    }
1691
2162
    memset(opts, 0, sizeof(my_option) * count);
1692
2163
 
1693
 
    if (construct_options(tmp_root, tmp, opts))
 
2164
    if (construct_options(tmp_root, tmp, opts, can_disable))
1694
2165
    {
1695
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
 
2166
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->name.str);
1696
2167
      return(-1);
1697
2168
    }
1698
2169
 
1702
2173
    if (error)
1703
2174
    {
1704
2175
       errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
1705
 
                       tmp->getName().c_str());
 
2176
                       tmp->name.str);
1706
2177
       goto err;
1707
2178
    }
1708
2179
  }
1710
2181
  error= 1;
1711
2182
 
1712
2183
  {
1713
 
    for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
 
2184
    for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
1714
2185
    {
1715
 
      sys_var *v;
1716
2186
      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
1717
2187
        continue;
1718
2188
 
1719
 
      if ((var= find_bookmark(tmp->getName(), o->name, o->flags)))
1720
 
        v= new sys_var_pluginvar(var->key + 1, o);
 
2189
      if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
 
2190
        v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
1721
2191
      else
1722
2192
      {
1723
 
        len= tmp->getName().length() + strlen(o->name) + 2;
1724
 
        string vname(tmp->getName());
1725
 
        vname.push_back('-');
1726
 
        vname.append(o->name);
1727
 
        transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
1728
 
        string::iterator p= vname.begin();      
1729
 
        while  (p != vname.end())
1730
 
        {
 
2193
        len= tmp->name.length + strlen(o->name) + 2;
 
2194
        varname= (char*) alloc_root(mem_root, len);
 
2195
        sprintf(varname,"%s-%s",tmp->name.str,o->name);
 
2196
        my_casedn_str(&my_charset_utf8_general_ci, varname);
 
2197
 
 
2198
        for (p= varname; *p; p++)
1731
2199
          if (*p == '-')
1732
2200
            *p= '_';
1733
 
          ++p;
1734
 
        }
1735
2201
 
1736
 
        v= new sys_var_pluginvar(vname, o);
 
2202
        v= new (mem_root) sys_var_pluginvar(varname, o);
1737
2203
      }
1738
2204
      assert(v); /* check that an object was actually constructed */
1739
2205
 
1740
 
      drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
1741
2206
      /*
1742
2207
        Add to the chain of variables.
1743
2208
        Done like this for easier debugging so that the
1751
2216
      if (mysql_add_sys_var_chain(chain.first, NULL))
1752
2217
      {
1753
2218
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
1754
 
                        tmp->getName().c_str());
 
2219
                        tmp->name.str);
1755
2220
        goto err;
1756
2221
      }
1757
2222
      tmp->system_vars= chain.first;
1770
2235
  Help Verbose text with Plugin System Variables
1771
2236
****************************************************************************/
1772
2237
 
1773
 
class OptionCmp
1774
 
{
1775
 
public:
1776
 
  bool operator() (const my_option &a, const my_option &b)
1777
 
  {
1778
 
    return my_strcasecmp(&my_charset_utf8_general_ci, a.name, b.name);
1779
 
  }
1780
 
};
1781
 
 
1782
 
 
1783
 
void my_print_help_inc_plugins(my_option *main_options)
1784
 
{
1785
 
  plugin::Registry &registry= plugin::Registry::singleton();
1786
 
  vector<my_option> all_options;
1787
 
  plugin::Module *p;
1788
 
  memory::Root mem_root;
1789
 
  my_option *opt= NULL;
1790
 
 
1791
 
  init_alloc_root(&mem_root, 4096);
 
2238
static int option_cmp(my_option *a, my_option *b)
 
2239
{
 
2240
  return my_strcasecmp(&my_charset_utf8_general_ci, a->name, b->name);
 
2241
}
 
2242
 
 
2243
 
 
2244
void my_print_help_inc_plugins(my_option *main_options, uint32_t size)
 
2245
{
 
2246
  DYNAMIC_ARRAY all_options;
 
2247
  struct st_plugin_int *p;
 
2248
  MEM_ROOT mem_root;
 
2249
  my_option *opt;
 
2250
 
 
2251
  init_alloc_root(&mem_root, 4096, 4096);
 
2252
  my_init_dynamic_array(&all_options, sizeof(my_option), size, size/4);
1792
2253
 
1793
2254
  if (initialized)
1794
 
  {
1795
 
    std::map<std::string, plugin::Module *>::const_iterator modules=
1796
 
      registry.getModulesMap().begin();
1797
 
    
1798
 
    while (modules != registry.getModulesMap().end())
 
2255
    for (uint32_t idx= 0; idx < plugin_array.elements; idx++)
1799
2256
    {
1800
 
      p= (*modules).second;
1801
 
      ++modules;
1802
 
 
1803
 
      if (p->getManifest().system_vars == NULL)
1804
 
        continue;
1805
 
 
1806
 
      opt= construct_help_options(&mem_root, p);
1807
 
      if (opt == NULL)
 
2257
      p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
 
2258
 
 
2259
      if (!p->plugin->system_vars ||
 
2260
          !(opt= construct_help_options(&mem_root, p)))
1808
2261
        continue;
1809
2262
 
1810
2263
      /* Only options with a non-NULL comment are displayed in help text */
1811
2264
      for (;opt->id; opt++)
1812
 
      {
1813
2265
        if (opt->comment)
1814
 
        {
1815
 
          all_options.push_back(*opt);
1816
 
          
1817
 
        }
1818
 
      }
 
2266
          insert_dynamic(&all_options, (unsigned char*) opt);
1819
2267
    }
1820
 
  }
1821
2268
 
1822
2269
  for (;main_options->id; main_options++)
1823
 
  {
1824
 
    if (main_options->comment)
1825
 
    {
1826
 
      all_options.push_back(*main_options);
1827
 
    }
1828
 
  }
 
2270
    insert_dynamic(&all_options, (unsigned char*) main_options);
1829
2271
 
1830
 
  /** 
1831
 
   * @TODO: Fix the my_option building so that it doens't break sort
1832
 
   *
1833
 
   * sort(all_options.begin(), all_options.end(), OptionCmp());
1834
 
   */
 
2272
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
1835
2273
 
1836
2274
  /* main_options now points to the empty option terminator */
1837
 
  all_options.push_back(*main_options);
1838
 
 
1839
 
  my_print_help(&*(all_options.begin()));
1840
 
  my_print_variables(&*(all_options.begin()));
1841
 
 
 
2275
  insert_dynamic(&all_options, (unsigned char*) main_options);
 
2276
 
 
2277
  my_print_help((my_option*) all_options.buffer);
 
2278
  my_print_variables((my_option*) all_options.buffer);
 
2279
 
 
2280
  delete_dynamic(&all_options);
1842
2281
  free_root(&mem_root, MYF(0));
1843
 
 
1844
2282
}
1845
2283
 
1846
 
} /* namespace drizzled */