~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/loader.cc

  • Committer: Brian Aker
  • Date: 2010-05-18 15:49:50 UTC
  • Revision ID: brian@gaz-20100518154950-qhctxu6lvvnyxy9i
Simplify out Open_tables_state() backup/restore (no longer needed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
#include "config.h"
17
17
 
22
22
#include <vector>
23
23
#include <map>
24
24
#include <algorithm>
25
 
#include <iostream>
26
 
 
27
 
#include <boost/program_options.hpp>
28
25
 
29
26
#include "drizzled/option.h"
 
27
#include "drizzled/my_hash.h"
30
28
#include "drizzled/internal/m_string.h"
31
29
 
32
30
#include "drizzled/plugin.h"
33
 
#include "drizzled/module/load_list.h"
34
 
#include "drizzled/module/library.h"
35
 
#include "drizzled/module/registry.h"
36
 
#include "drizzled/module/option_context.h"
 
31
#include "drizzled/plugin/load_list.h"
37
32
#include "drizzled/sql_parse.h"
38
33
#include "drizzled/show.h"
39
34
#include "drizzled/cursor.h"
40
35
#include "drizzled/set_var.h"
41
36
#include "drizzled/session.h"
42
37
#include "drizzled/item/null.h"
 
38
#include "drizzled/plugin/registry.h"
43
39
#include "drizzled/error.h"
44
40
#include "drizzled/gettext.h"
45
41
#include "drizzled/errmsg_print.h"
 
42
#include "drizzled/plugin/library.h"
46
43
#include "drizzled/strfunc.h"
47
44
#include "drizzled/pthread_globals.h"
48
45
#include "drizzled/util/tokenize.h"
49
46
 
50
 
#include <boost/foreach.hpp>
51
 
 
52
47
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
53
48
#ifndef RTLD_NOW
54
49
#define RTLD_NOW 1
55
50
#endif
56
51
 
57
 
namespace po=boost::program_options;
58
 
 
59
52
using namespace std;
60
53
 
61
 
/** These exist just to prevent symbols from being optimized out */
62
 
typedef drizzled::module::Manifest drizzled_builtin_list[];
63
 
extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
64
 
extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
65
 
drizzled::module::Manifest *drizzled_builtins[]=
66
 
{
67
 
  PANDORA_BUILTIN_SYMBOLS_LIST, NULL
68
 
};
69
 
drizzled::module::Manifest *drizzled_load_builtins[]=
70
 
{
71
 
  PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
 
54
typedef drizzled::plugin::Manifest drizzled_builtin_plugin[];
 
55
extern drizzled_builtin_plugin PANDORA_BUILTIN_LIST;
 
56
static drizzled::plugin::Manifest *drizzled_builtins[]=
 
57
{
 
58
  PANDORA_BUILTIN_LIST, NULL
72
59
};
73
60
 
74
61
namespace drizzled
75
62
{
76
63
 
77
64
 
78
 
typedef vector<string> PluginOptions;
79
 
static PluginOptions opt_plugin_load;
80
 
static PluginOptions opt_plugin_add;
81
 
static PluginOptions opt_plugin_remove;
82
 
const char *builtin_plugins= PANDORA_BUILTIN_LIST;
83
 
const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
 
65
class sys_var_pluginvar;
 
66
static vector<sys_var_pluginvar *> plugin_sysvar_vec;
 
67
 
 
68
char *opt_plugin_add= NULL;
 
69
char *opt_plugin_remove= NULL;
 
70
char *opt_plugin_load= NULL;
 
71
char *opt_plugin_dir_ptr;
 
72
char opt_plugin_dir[FN_REFLEN];
 
73
const char *opt_plugin_load_default= PANDORA_PLUGIN_LIST;
84
74
 
85
75
/* Note that 'int version' must be the first field of every plugin
86
76
   sub-structure (plugin->info).
97
87
*/
98
88
static memory::Root plugin_mem_root(4096);
99
89
static uint32_t global_variables_dynamic_size= 0;
 
90
static HASH bookmark_hash;
100
91
 
101
92
 
102
93
/*
108
99
  Item *item;
109
100
};
110
101
 
111
 
class Bookmark
 
102
 
 
103
/*
 
104
  stored in bookmark_hash, this structure is never removed from the
 
105
  hash and is used to mark a single offset for a session local variable
 
106
  even if plugins have been uninstalled and reinstalled, repeatedly.
 
107
  This structure is allocated from plugin_mem_root.
 
108
 
 
109
  The key format is as follows:
 
110
    1 byte         - variable type code
 
111
    name_len bytes - variable name
 
112
    '\0'           - end of key
 
113
*/
 
114
struct st_bookmark
112
115
{
113
 
public:
114
 
  Bookmark() :
115
 
    type_code(0),
116
 
    offset(0),
117
 
    version(0),
118
 
    key("")
119
 
  {}
120
 
  uint8_t type_code;
 
116
  uint32_t name_len;
121
117
  int offset;
122
118
  uint32_t version;
123
 
  string key;
124
 
};
125
 
 
126
 
typedef boost::unordered_map<string, Bookmark> bookmark_unordered_map;
127
 
static bookmark_unordered_map bookmark_hash;
128
 
 
 
119
  char key[1];
 
120
};
 
121
 
 
122
 
 
123
/*
 
124
  sys_var class for access to all plugin variables visible to the user
 
125
*/
 
126
class sys_var_pluginvar: public sys_var
 
127
{
 
128
public:
 
129
  plugin::Module *plugin;
 
130
  drizzle_sys_var *plugin_var;
 
131
 
 
132
  sys_var_pluginvar(const std::string name_arg,
 
133
                    drizzle_sys_var *plugin_var_arg)
 
134
    :sys_var(name_arg), plugin_var(plugin_var_arg) {}
 
135
  sys_var_pluginvar *cast_pluginvar() { return this; }
 
136
  bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; }
 
137
  bool check_type(sql_var_t type)
 
138
  { return !(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) && type != OPT_GLOBAL; }
 
139
  bool check_update_type(Item_result type);
 
140
  SHOW_TYPE show_type();
 
141
  unsigned char* real_value_ptr(Session *session, sql_var_t type);
 
142
  TYPELIB* plugin_var_typelib(void);
 
143
  unsigned char* value_ptr(Session *session, sql_var_t type,
 
144
                           const LEX_STRING *base);
 
145
  bool check(Session *session, set_var *var);
 
146
  bool check_default(sql_var_t)
 
147
    { return is_readonly(); }
 
148
  void set_default(Session *session, sql_var_t);
 
149
  bool update(Session *session, set_var *var);
 
150
};
129
151
 
130
152
 
131
153
/* prototypes */
132
154
static void plugin_prune_list(vector<string> &plugin_list,
133
155
                              const vector<string> &plugins_to_remove);
134
 
static bool plugin_load_list(module::Registry &registry,
135
 
                             memory::Root *tmp_root,
136
 
                             const set<string> &plugin_list,
137
 
                             po::options_description &long_options,
138
 
                             bool builtin= false);
139
 
static int test_plugin_options(memory::Root *, module::Module *,
140
 
                               po::options_description &long_options);
141
 
static void unlock_variables(Session *session, drizzle_system_variables *vars);
142
 
static void cleanup_variables(drizzle_system_variables *vars);
 
156
static bool plugin_load_list(plugin::Registry &registry,
 
157
                             memory::Root *tmp_root, int *argc, char **argv,
 
158
                             const set<string> &plugin_list);
 
159
static int test_plugin_options(memory::Root *, plugin::Module *,
 
160
                               int *, char **);
 
161
static void unlock_variables(Session *session, struct system_variables *vars);
 
162
static void cleanup_variables(Session *session, struct system_variables *vars);
 
163
static void plugin_vars_free_values(sys_var *vars);
143
164
 
144
165
/* declared in set_var.cc */
145
166
extern sys_var *intern_find_sys_var(const char *str, uint32_t length, bool no_error);
 
167
extern bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
 
168
                                 const std::string &name, int64_t val);
 
169
 
 
170
static bool throw_bounds_warning(Session *session, bool fixed, bool unsignd,
 
171
                                 const char *name, int64_t val)
 
172
{
 
173
  const std::string name_str(name);
 
174
  return throw_bounds_warning(session, fixed, unsignd, name_str, val);
 
175
}
 
176
 
 
177
/****************************************************************************
 
178
  Value type thunks, allows the C world to play in the C++ world
 
179
****************************************************************************/
 
180
 
 
181
static int item_value_type(drizzle_value *value)
 
182
{
 
183
  switch (((st_item_value_holder*)value)->item->result_type()) {
 
184
  case INT_RESULT:
 
185
    return DRIZZLE_VALUE_TYPE_INT;
 
186
  case REAL_RESULT:
 
187
    return DRIZZLE_VALUE_TYPE_REAL;
 
188
  default:
 
189
    return DRIZZLE_VALUE_TYPE_STRING;
 
190
  }
 
191
}
 
192
 
 
193
static const char *item_val_str(drizzle_value *value,
 
194
                                char *buffer, int *length)
 
195
{
 
196
  String str(buffer, *length, system_charset_info), *res;
 
197
  if (!(res= ((st_item_value_holder*)value)->item->val_str(&str)))
 
198
    return NULL;
 
199
  *length= res->length();
 
200
  if (res->c_ptr_quick() == buffer)
 
201
    return buffer;
 
202
 
 
203
  /*
 
204
    Lets be nice and create a temporary string since the
 
205
    buffer was too small
 
206
  */
 
207
  return current_session->strmake(res->c_ptr_quick(), res->length());
 
208
}
 
209
 
 
210
 
 
211
static int item_val_int(drizzle_value *value, int64_t *buf)
 
212
{
 
213
  Item *item= ((st_item_value_holder*)value)->item;
 
214
  *buf= item->val_int();
 
215
  if (item->is_null())
 
216
    return 1;
 
217
  return 0;
 
218
}
 
219
 
 
220
 
 
221
static int item_val_real(drizzle_value *value, double *buf)
 
222
{
 
223
  Item *item= ((st_item_value_holder*)value)->item;
 
224
  *buf= item->val_real();
 
225
  if (item->is_null())
 
226
    return 1;
 
227
  return 0;
 
228
}
146
229
 
147
230
 
148
231
/****************************************************************************
156
239
  NOTE
157
240
    Requires that a write-lock is held on LOCK_system_variables_hash
158
241
*/
159
 
static bool plugin_add(module::Registry &registry, memory::Root *tmp_root,
160
 
                       module::Library *library,
161
 
                       po::options_description &long_options)
 
242
static bool plugin_add(plugin::Registry &registry, memory::Root *tmp_root,
 
243
                       plugin::Library *library,
 
244
                       int *argc, char **argv)
162
245
{
163
246
  if (! initialized)
164
247
    return true;
170
253
    return false;
171
254
  }
172
255
 
173
 
  module::Module *tmp= NULL;
 
256
  plugin::Module *tmp= NULL;
174
257
  /* Find plugin by name */
175
 
  const module::Manifest *manifest= library->getManifest();
 
258
  const plugin::Manifest *manifest= library->getManifest();
176
259
 
177
260
  if (registry.find(manifest->name))
178
261
  {
184
267
    return true;
185
268
  }
186
269
 
187
 
  tmp= new (std::nothrow) module::Module(manifest, library);
 
270
  tmp= new (std::nothrow) plugin::Module(manifest, library);
188
271
  if (tmp == NULL)
189
272
    return true;
190
273
 
191
 
  if (!test_plugin_options(tmp_root, tmp, long_options))
 
274
  if (!test_plugin_options(tmp_root, tmp, argc, argv))
192
275
  {
193
276
    registry.add(tmp);
194
277
    return false;
199
282
}
200
283
 
201
284
 
202
 
static void reap_plugins(module::Registry &registry)
203
 
{
204
 
  std::map<std::string, module::Module *>::const_iterator modules=
 
285
static void delete_module(plugin::Module *module)
 
286
{
 
287
  /* Free allocated strings before deleting the plugin. */
 
288
  plugin_vars_free_values(module->system_vars);
 
289
  module->isInited= false;
 
290
  pthread_rwlock_wrlock(&LOCK_system_variables_hash);
 
291
  mysql_del_sys_var_chain(module->system_vars);
 
292
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
293
  delete module;
 
294
}
 
295
 
 
296
 
 
297
static void reap_plugins(plugin::Registry &registry)
 
298
{
 
299
  std::map<std::string, plugin::Module *>::const_iterator modules=
205
300
    registry.getModulesMap().begin();
206
301
 
207
302
  while (modules != registry.getModulesMap().end())
208
303
  {
209
 
    module::Module *module= (*modules).second;
210
 
    delete module;
 
304
    plugin::Module *module= (*modules).second;
 
305
    delete_module(module);
211
306
    ++modules;
212
307
  }
213
 
}
214
 
 
215
 
 
216
 
static bool plugin_initialize(module::Registry &registry,
217
 
                              module::Module *module)
 
308
 
 
309
  drizzle_del_plugin_sysvar();
 
310
}
 
311
 
 
312
 
 
313
static void plugin_initialize_vars(plugin::Module *module)
 
314
{
 
315
  /*
 
316
    set the plugin attribute of plugin's sys vars so they are pointing
 
317
    to the active plugin
 
318
  */
 
319
  if (module->system_vars)
 
320
  {
 
321
    sys_var_pluginvar *var= module->system_vars->cast_pluginvar();
 
322
    for (;;)
 
323
    {
 
324
      var->plugin= module;
 
325
      if (! var->getNext())
 
326
        break;
 
327
      var= var->getNext()->cast_pluginvar();
 
328
    }
 
329
  }
 
330
}
 
331
 
 
332
 
 
333
static bool plugin_initialize(plugin::Registry &registry,
 
334
                              plugin::Module *module)
218
335
{
219
336
  assert(module->isInited == false);
220
337
 
221
 
  module::Context loading_context(registry, module);
 
338
  plugin::Context loading_context(registry, module);
222
339
  if (module->getManifest().init)
223
340
  {
224
341
    if (module->getManifest().init(loading_context))
236
353
}
237
354
 
238
355
 
239
 
inline static void dashes_to_underscores(std::string &name_in,
240
 
                                         char from= '-', char to= '_')
241
 
{
242
 
  for (string::iterator p= name_in.begin();
243
 
       p != name_in.end();
244
 
       ++p)
245
 
  {
246
 
    if (*p == from)
247
 
    {
248
 
      *p= to;
249
 
    }
250
 
  }
251
 
}
252
 
 
253
 
inline static void underscores_to_dashes(std::string &name_in)
254
 
{
255
 
  return dashes_to_underscores(name_in, '_', '-');
256
 
}
257
 
 
258
 
static void compose_plugin_options(vector<string> &target,
259
 
                                   vector<string> options)
260
 
{
261
 
  for (vector<string>::iterator it= options.begin();
262
 
       it != options.end();
263
 
       ++it)
264
 
  {
265
 
    tokenize(*it, target, ",", true);
266
 
  }
267
 
  for (vector<string>::iterator it= target.begin();
268
 
       it != target.end();
269
 
       ++it)
270
 
  {
271
 
    dashes_to_underscores(*it);
272
 
  }
273
 
}
274
 
 
275
 
void compose_plugin_add(vector<string> options)
276
 
{
277
 
  compose_plugin_options(opt_plugin_add, options);
278
 
}
279
 
 
280
 
void compose_plugin_remove(vector<string> options)
281
 
{
282
 
  compose_plugin_options(opt_plugin_remove, options);
283
 
}
284
 
 
285
 
void notify_plugin_load(string in_plugin_load)
286
 
{
287
 
  tokenize(in_plugin_load, opt_plugin_load, ",", true);
288
 
}
 
356
static unsigned char *get_bookmark_hash_key(const unsigned char *buff,
 
357
                                            size_t *length, bool)
 
358
{
 
359
  struct st_bookmark *var= (st_bookmark *)buff;
 
360
  *length= var->name_len + 1;
 
361
  return (unsigned char*) var->key;
 
362
}
 
363
 
289
364
 
290
365
/*
291
366
  The logic is that we first load and initialize all compiled in plugins.
294
369
 
295
370
  Finally we initialize everything, aka the dynamic that have yet to initialize.
296
371
*/
297
 
bool plugin_init(module::Registry &registry,
298
 
                 po::options_description &long_options)
 
372
bool plugin_init(plugin::Registry &registry,
 
373
                 int *argc, char **argv,
 
374
                 bool skip_init)
299
375
{
 
376
  plugin::Manifest **builtins;
 
377
  plugin::Manifest *manifest;
 
378
  plugin::Module *module;
300
379
  memory::Root tmp_root(4096);
301
380
 
302
381
  if (initialized)
303
382
    return false;
304
383
 
 
384
  if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
 
385
                  get_bookmark_hash_key, NULL, HASH_UNIQUE))
 
386
  {
 
387
    tmp_root.free_root(MYF(0));
 
388
    return true;
 
389
  }
 
390
 
 
391
 
305
392
  initialized= 1;
306
393
 
307
 
  PluginOptions builtin_load_list;
308
 
  tokenize(builtin_load_plugins, builtin_load_list, ",", true);
309
 
 
310
 
  PluginOptions builtin_list;
311
 
  tokenize(builtin_plugins, builtin_list, ",", true);
 
394
  /*
 
395
    First we register builtin plugins
 
396
  */
 
397
  for (builtins= drizzled_builtins; *builtins; builtins++)
 
398
  {
 
399
    manifest= *builtins;
 
400
    if (manifest->name != NULL)
 
401
    {
 
402
      module= new (std::nothrow) plugin::Module(manifest);
 
403
      if (module == NULL)
 
404
        return true;
 
405
 
 
406
      tmp_root.free_root(MYF(memory::MARK_BLOCKS_FREE));
 
407
      if (test_plugin_options(&tmp_root, module, argc, argv))
 
408
        continue;
 
409
 
 
410
      registry.add(module);
 
411
 
 
412
      plugin_initialize_vars(module);
 
413
 
 
414
      if (! skip_init)
 
415
      {
 
416
        if (plugin_initialize(registry, module))
 
417
        {
 
418
          tmp_root.free_root(MYF(0));
 
419
          return true;
 
420
        }
 
421
      }
 
422
    }
 
423
  }
 
424
 
312
425
 
313
426
  bool load_failed= false;
314
 
 
315
 
  if (opt_plugin_add.size() > 0)
316
 
  {
317
 
    for (PluginOptions::iterator iter= opt_plugin_add.begin();
318
 
         iter != opt_plugin_add.end();
319
 
         ++iter)
320
 
    {
321
 
      if (find(builtin_list.begin(),
322
 
               builtin_list.end(), *iter) != builtin_list.end())
323
 
      {
324
 
        builtin_load_list.push_back(*iter);
325
 
      }
326
 
      else
327
 
      {
328
 
        opt_plugin_load.push_back(*iter);
329
 
      }
330
 
    }
331
 
  }
332
 
 
333
 
  if (opt_plugin_remove.size() > 0)
334
 
  {
335
 
    plugin_prune_list(opt_plugin_load, opt_plugin_remove);
336
 
    plugin_prune_list(builtin_load_list, opt_plugin_remove);
337
 
  }
338
 
 
339
 
 
340
 
  /*
341
 
    First we register builtin plugins
342
 
  */
343
 
  const set<string> builtin_list_set(builtin_load_list.begin(),
344
 
                                     builtin_load_list.end());
345
 
  load_failed= plugin_load_list(registry, &tmp_root,
346
 
                                builtin_list_set, long_options, true);
347
 
  if (load_failed)
348
 
  {
349
 
    tmp_root.free_root(MYF(0));
350
 
    return true;
 
427
  vector<string> plugin_list;
 
428
  if (opt_plugin_load)
 
429
  {
 
430
    tokenize(opt_plugin_load, plugin_list, ",", true);
 
431
  }
 
432
  else
 
433
  {
 
434
    tokenize(opt_plugin_load_default, plugin_list, ",", true);
 
435
  }
 
436
  if (opt_plugin_add)
 
437
  {
 
438
    tokenize(opt_plugin_add, plugin_list, ",", true);
 
439
  }
 
440
 
 
441
  if (opt_plugin_remove)
 
442
  {
 
443
    vector<string> plugins_to_remove;
 
444
    tokenize(opt_plugin_remove, plugins_to_remove, ",", true);
 
445
    plugin_prune_list(plugin_list, plugins_to_remove);
351
446
  }
352
447
 
353
448
  /* Uniquify the list */
354
 
  const set<string> plugin_list_set(opt_plugin_load.begin(),
355
 
                                    opt_plugin_load.end());
 
449
  const set<string> plugin_list_set(plugin_list.begin(), plugin_list.end());
356
450
  
357
451
  /* Register all dynamic plugins */
358
 
  load_failed= plugin_load_list(registry, &tmp_root,
359
 
                                plugin_list_set, long_options);
 
452
  load_failed= plugin_load_list(registry, &tmp_root, argc, argv,
 
453
                                plugin_list_set);
360
454
  if (load_failed)
361
455
  {
362
456
    tmp_root.free_root(MYF(0));
363
457
    return true;
364
458
  }
365
459
 
366
 
  tmp_root.free_root(MYF(0));
367
 
 
368
 
  return false;
369
 
}
370
 
 
371
 
bool plugin_finalize(module::Registry &registry)
372
 
{
 
460
  if (skip_init)
 
461
  {
 
462
    tmp_root.free_root(MYF(0));
 
463
    return false;
 
464
  }
 
465
 
373
466
  /*
374
467
    Now we initialize all remaining plugins
375
468
  */
376
 
  std::map<std::string, module::Module *>::const_iterator modules=
 
469
  std::map<std::string, plugin::Module *>::const_iterator modules=
377
470
    registry.getModulesMap().begin();
378
471
    
379
472
  while (modules != registry.getModulesMap().end())
380
473
  {
381
 
    module::Module *module= (*modules).second;
 
474
    module= (*modules).second;
382
475
    ++modules;
383
476
    if (module->isInited == false)
384
477
    {
 
478
      plugin_initialize_vars(module);
 
479
 
385
480
      if (plugin_initialize(registry, module))
386
 
      {
387
 
        registry.remove(module);
388
 
        delete module;
389
 
        return true;
390
 
      }
 
481
        delete_module(module);
391
482
    }
392
483
  }
393
484
 
394
 
  BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
395
 
  {
396
 
    value.second->prime();
397
 
  }
 
485
 
 
486
  tmp_root.free_root(MYF(0));
398
487
 
399
488
  return false;
400
489
}
433
522
/*
434
523
  called only by plugin_init()
435
524
*/
436
 
static bool plugin_load_list(module::Registry &registry,
437
 
                             memory::Root *tmp_root,
438
 
                             const set<string> &plugin_list,
439
 
                             po::options_description &long_options,
440
 
                             bool builtin)
 
525
static bool plugin_load_list(plugin::Registry &registry,
 
526
                             memory::Root *tmp_root, int *argc, char **argv,
 
527
                             const set<string> &plugin_list)
441
528
{
442
 
  module::Library *library= NULL;
 
529
  plugin::Library *library= NULL;
443
530
 
444
531
  for (set<string>::const_iterator iter= plugin_list.begin();
445
532
       iter != plugin_list.end();
446
533
       ++iter)
447
534
  {
448
535
    const string plugin_name(*iter);
449
 
 
450
 
    library= registry.addLibrary(plugin_name, builtin);
 
536
    library= registry.addLibrary(plugin_name);
451
537
    if (library == NULL)
452
538
    {
453
539
      errmsg_printf(ERRMSG_LVL_ERROR,
457
543
    }
458
544
 
459
545
    tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
460
 
    if (plugin_add(registry, tmp_root, library, long_options))
 
546
    if (plugin_add(registry, tmp_root, library, argc, argv))
461
547
    {
462
548
      registry.removeLibrary(plugin_name);
463
549
      errmsg_printf(ERRMSG_LVL_ERROR,
471
557
}
472
558
 
473
559
 
474
 
void module_shutdown(module::Registry &registry)
 
560
void plugin_shutdown(plugin::Registry &registry)
475
561
{
476
562
 
477
563
  if (initialized)
482
568
    unlock_variables(NULL, &global_system_variables);
483
569
    unlock_variables(NULL, &max_system_variables);
484
570
 
485
 
    cleanup_variables(&global_system_variables);
486
 
    cleanup_variables(&max_system_variables);
 
571
    cleanup_variables(NULL, &global_system_variables);
 
572
    cleanup_variables(NULL, &max_system_variables);
487
573
 
488
574
    initialized= 0;
489
575
  }
490
576
 
491
577
  /* Dispose of the memory */
 
578
 
 
579
  hash_free(&bookmark_hash);
492
580
  plugin_mem_root.free_root(MYF(0));
493
581
 
494
582
  global_variables_dynamic_size= 0;
495
583
}
496
584
 
 
585
/****************************************************************************
 
586
  Internal type declarations for variables support
 
587
****************************************************************************/
 
588
 
 
589
#undef DRIZZLE_SYSVAR_NAME
 
590
#define DRIZZLE_SYSVAR_NAME(name) name
 
591
#define PLUGIN_VAR_TYPEMASK 0x007f
 
592
 
 
593
static const uint32_t EXTRA_OPTIONS= 1; /* handle the NULL option */
 
594
 
 
595
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_bool_t, bool);
 
596
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_bool_t, bool);
 
597
typedef DECLARE_DRIZZLE_SYSVAR_BASIC(sysvar_str_t, char *);
 
598
typedef DECLARE_DRIZZLE_SessionVAR_BASIC(sessionvar_str_t, char *);
 
599
 
 
600
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_enum_t, unsigned long);
 
601
typedef DECLARE_DRIZZLE_SessionVAR_TYPELIB(sessionvar_set_t, uint64_t);
 
602
 
 
603
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int_t, int);
 
604
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_long_t, long);
 
605
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_int64_t_t, int64_t);
 
606
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint_t, uint);
 
607
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
 
608
typedef DECLARE_DRIZZLE_SYSVAR_SIMPLE(sysvar_uint64_t_t, uint64_t);
 
609
 
 
610
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int_t, int);
 
611
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_long_t, long);
 
612
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_int64_t_t, int64_t);
 
613
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint_t, uint);
 
614
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_ulong_t, ulong);
 
615
typedef DECLARE_DRIZZLE_SessionVAR_SIMPLE(sessionvar_uint64_t_t, uint64_t);
 
616
 
 
617
typedef bool *(*mysql_sys_var_ptr_p)(Session* a_session, int offset);
 
618
 
 
619
 
 
620
/****************************************************************************
 
621
  default variable data check and update functions
 
622
****************************************************************************/
 
623
 
 
624
static int check_func_bool(Session *, drizzle_sys_var *var,
 
625
                           void *save, drizzle_value *value)
 
626
{
 
627
  char buff[STRING_BUFFER_USUAL_SIZE];
 
628
  const char *strvalue= "NULL", *str;
 
629
  int result, length;
 
630
  int64_t tmp;
 
631
 
 
632
  if (value->value_type(value) == DRIZZLE_VALUE_TYPE_STRING)
 
633
  {
 
634
    length= sizeof(buff);
 
635
    if (!(str= value->val_str(value, buff, &length)) ||
 
636
        (result= find_type(&bool_typelib, str, length, 1)-1) < 0)
 
637
    {
 
638
      if (str)
 
639
        strvalue= str;
 
640
      goto err;
 
641
    }
 
642
  }
 
643
  else
 
644
  {
 
645
    if (value->val_int(value, &tmp) < 0)
 
646
      goto err;
 
647
    if (tmp > 1)
 
648
    {
 
649
      internal::llstr(tmp, buff);
 
650
      strvalue= buff;
 
651
      goto err;
 
652
    }
 
653
    result= (int) tmp;
 
654
  }
 
655
  *(int*)save= -result;
 
656
  return 0;
 
657
err:
 
658
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
 
659
  return 1;
 
660
}
 
661
 
 
662
 
 
663
static int check_func_int(Session *session, drizzle_sys_var *var,
 
664
                          void *save, drizzle_value *value)
 
665
{
 
666
  bool fixed;
 
667
  int64_t tmp;
 
668
  struct option options;
 
669
  value->val_int(value, &tmp);
 
670
  plugin_opt_set_limits(&options, var);
 
671
 
 
672
  if (var->flags & PLUGIN_VAR_UNSIGNED)
 
673
    *(uint32_t *)save= (uint32_t) getopt_ull_limit_value((uint64_t) tmp, &options,
 
674
                                                   &fixed);
 
675
  else
 
676
    *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
 
677
 
 
678
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
679
                              var->name, (int64_t) tmp);
 
680
}
 
681
 
 
682
 
 
683
static int check_func_long(Session *session, drizzle_sys_var *var,
 
684
                          void *save, drizzle_value *value)
 
685
{
 
686
  bool fixed;
 
687
  int64_t tmp;
 
688
  struct option options;
 
689
  value->val_int(value, &tmp);
 
690
  plugin_opt_set_limits(&options, var);
 
691
 
 
692
  if (var->flags & PLUGIN_VAR_UNSIGNED)
 
693
    *(ulong *)save= (ulong) getopt_ull_limit_value((uint64_t) tmp, &options,
 
694
                                                   &fixed);
 
695
  else
 
696
    *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
 
697
 
 
698
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
699
                              var->name, (int64_t) tmp);
 
700
}
 
701
 
 
702
 
 
703
static int check_func_int64_t(Session *session, drizzle_sys_var *var,
 
704
                               void *save, drizzle_value *value)
 
705
{
 
706
  bool fixed;
 
707
  int64_t tmp;
 
708
  struct option options;
 
709
  value->val_int(value, &tmp);
 
710
  plugin_opt_set_limits(&options, var);
 
711
 
 
712
  if (var->flags & PLUGIN_VAR_UNSIGNED)
 
713
    *(uint64_t *)save= getopt_ull_limit_value((uint64_t) tmp, &options,
 
714
                                               &fixed);
 
715
  else
 
716
    *(int64_t *)save= getopt_ll_limit_value(tmp, &options, &fixed);
 
717
 
 
718
  return throw_bounds_warning(session, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
 
719
                              var->name, (int64_t) tmp);
 
720
}
 
721
 
 
722
static int check_func_str(Session *session, drizzle_sys_var *,
 
723
                          void *save, drizzle_value *value)
 
724
{
 
725
  char buff[STRING_BUFFER_USUAL_SIZE];
 
726
  const char *str;
 
727
  int length;
 
728
 
 
729
  length= sizeof(buff);
 
730
  if ((str= value->val_str(value, buff, &length)))
 
731
    str= session->strmake(str, length);
 
732
  *(const char**)save= str;
 
733
  return 0;
 
734
}
 
735
 
 
736
 
 
737
static void update_func_bool(Session *, drizzle_sys_var *,
 
738
                             void *tgt, const void *save)
 
739
{
 
740
  *(bool *) tgt= *(int *) save ? 1 : 0;
 
741
}
 
742
 
 
743
 
 
744
static void update_func_int(Session *, drizzle_sys_var *,
 
745
                             void *tgt, const void *save)
 
746
{
 
747
  *(int *)tgt= *(int *) save;
 
748
}
 
749
 
 
750
 
 
751
static void update_func_long(Session *, drizzle_sys_var *,
 
752
                             void *tgt, const void *save)
 
753
{
 
754
  *(long *)tgt= *(long *) save;
 
755
}
 
756
 
 
757
 
 
758
static void update_func_int64_t(Session *, drizzle_sys_var *,
 
759
                                 void *tgt, const void *save)
 
760
{
 
761
  *(int64_t *)tgt= *(uint64_t *) save;
 
762
}
 
763
 
 
764
 
 
765
static void update_func_str(Session *, drizzle_sys_var *var,
 
766
                             void *tgt, const void *save)
 
767
{
 
768
  char *old= *(char **) tgt;
 
769
  *(char **)tgt= *(char **) save;
 
770
  if (var->flags & PLUGIN_VAR_MEMALLOC)
 
771
  {
 
772
    *(char **)tgt= strdup(*(char **) save);
 
773
    free(old);
 
774
    /*
 
775
     * There isn't a _really_ good thing to do here until this whole set_var
 
776
     * mess gets redesigned
 
777
     */
 
778
    if (tgt == NULL)
 
779
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory."));
 
780
 
 
781
  }
 
782
}
 
783
 
497
784
 
498
785
/****************************************************************************
499
786
  System Variables support
500
787
****************************************************************************/
501
788
 
502
789
 
503
 
sys_var *find_sys_var(const char *str, uint32_t length)
504
 
{
505
 
  return intern_find_sys_var(str, length, false);
506
 
}
507
 
 
 
790
sys_var *find_sys_var(Session *, const char *str, uint32_t length)
 
791
{
 
792
  sys_var *var;
 
793
  sys_var_pluginvar *pi= NULL;
 
794
  plugin::Module *module;
 
795
 
 
796
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
 
797
  if ((var= intern_find_sys_var(str, length, false)) &&
 
798
      (pi= var->cast_pluginvar()))
 
799
  {
 
800
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
801
    if (!(module= pi->plugin))
 
802
      var= NULL; /* failed to lock it, it must be uninstalling */
 
803
    else if (module->isInited == false)
 
804
    {
 
805
      var= NULL;
 
806
    }
 
807
  }
 
808
  else
 
809
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
810
 
 
811
  /*
 
812
    If the variable exists but the plugin it is associated with is not ready
 
813
    then the intern_plugin_lock did not raise an error, so we do it here.
 
814
  */
 
815
  if (pi && !var)
 
816
    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
 
817
  return(var);
 
818
}
 
819
 
 
820
static const string make_bookmark_name(const string &plugin, const char *name, int flags)
 
821
{
 
822
  /* Embed the flags into the first char of the string */
 
823
  string varname(1, static_cast<char>(flags & PLUGIN_VAR_TYPEMASK));
 
824
  varname.append(plugin);
 
825
  varname.push_back('_');
 
826
  varname.append(name);
 
827
 
 
828
  for (string::iterator p= varname.begin() + 1; p != varname.end(); ++p)
 
829
  {
 
830
    if (*p == '-')
 
831
    {
 
832
      *p= '_';
 
833
    }
 
834
  }
 
835
  return varname;
 
836
}
 
837
 
 
838
/*
 
839
  called by register_var, construct_options and test_plugin_options.
 
840
  Returns the 'bookmark' for the named variable.
 
841
  LOCK_system_variables_hash should be at least read locked
 
842
*/
 
843
static st_bookmark *find_bookmark(const string &plugin, const char *name, int flags)
 
844
{
 
845
  st_bookmark *result= NULL;
 
846
 
 
847
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
 
848
    return NULL;
 
849
 
 
850
  const string varname(make_bookmark_name(plugin, name, flags));
 
851
 
 
852
 
 
853
  result= (st_bookmark*) hash_search(&bookmark_hash,
 
854
                                     (const unsigned char*) varname.c_str(), varname.size() - 1);
 
855
 
 
856
  return result;
 
857
}
 
858
 
 
859
 
 
860
/*
 
861
  returns a bookmark for session-local variables, creating if neccessary.
 
862
  returns null for non session-local variables.
 
863
  Requires that a write lock is obtained on LOCK_system_variables_hash
 
864
*/
 
865
static st_bookmark *register_var(const string &plugin, const char *name,
 
866
                                 int flags)
 
867
{
 
868
  if (!(flags & PLUGIN_VAR_SessionLOCAL))
 
869
    return NULL;
 
870
 
 
871
  uint32_t size= 0, offset, new_size;
 
872
  st_bookmark *result;
 
873
 
 
874
  switch (flags & PLUGIN_VAR_TYPEMASK) {
 
875
  case PLUGIN_VAR_BOOL:
 
876
    size= ALIGN_SIZE(sizeof(bool));
 
877
    break;
 
878
  case PLUGIN_VAR_INT:
 
879
    size= ALIGN_SIZE(sizeof(int));
 
880
    break;
 
881
  case PLUGIN_VAR_LONG:
 
882
    size= ALIGN_SIZE(sizeof(long));
 
883
    break;
 
884
  case PLUGIN_VAR_LONGLONG:
 
885
    size= ALIGN_SIZE(sizeof(uint64_t));
 
886
    break;
 
887
  case PLUGIN_VAR_STR:
 
888
    size= ALIGN_SIZE(sizeof(char*));
 
889
    break;
 
890
  default:
 
891
    assert(0);
 
892
    return NULL;
 
893
  };
 
894
 
 
895
 
 
896
  if (!(result= find_bookmark(plugin, name, flags)))
 
897
  {
 
898
    const string varname(make_bookmark_name(plugin, name, flags));
 
899
 
 
900
    result= static_cast<st_bookmark*>(plugin_mem_root.alloc_root(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;
 
904
    result->offset= -1;
 
905
 
 
906
    assert(size && !(size & (size-1))); /* must be power of 2 */
 
907
 
 
908
    offset= global_system_variables.dynamic_variables_size;
 
909
    offset= (offset + size - 1) & ~(size - 1);
 
910
    result->offset= (int) offset;
 
911
 
 
912
    new_size= (offset + size + 63) & ~63;
 
913
 
 
914
    if (new_size > global_variables_dynamic_size)
 
915
    {
 
916
      char* tmpptr= NULL;
 
917
      if (!(tmpptr=
 
918
              (char *)realloc(global_system_variables.dynamic_variables_ptr,
 
919
                              new_size)))
 
920
        return NULL;
 
921
      global_system_variables.dynamic_variables_ptr= tmpptr;
 
922
      tmpptr= NULL;
 
923
      if (!(tmpptr=
 
924
              (char *)realloc(max_system_variables.dynamic_variables_ptr,
 
925
                              new_size)))
 
926
        return NULL;
 
927
      max_system_variables.dynamic_variables_ptr= tmpptr;
 
928
           
 
929
      /*
 
930
        Clear the new variable value space. This is required for string
 
931
        variables. If their value is non-NULL, it must point to a valid
 
932
        string.
 
933
      */
 
934
      memset(global_system_variables.dynamic_variables_ptr +
 
935
             global_variables_dynamic_size, 0,
 
936
             new_size - global_variables_dynamic_size);
 
937
      memset(max_system_variables.dynamic_variables_ptr +
 
938
             global_variables_dynamic_size, 0,
 
939
             new_size - global_variables_dynamic_size);
 
940
      global_variables_dynamic_size= new_size;
 
941
    }
 
942
 
 
943
    global_system_variables.dynamic_variables_head= offset;
 
944
    max_system_variables.dynamic_variables_head= offset;
 
945
    global_system_variables.dynamic_variables_size= offset + size;
 
946
    max_system_variables.dynamic_variables_size= offset + size;
 
947
    global_system_variables.dynamic_variables_version++;
 
948
    max_system_variables.dynamic_variables_version++;
 
949
 
 
950
    result->version= global_system_variables.dynamic_variables_version;
 
951
 
 
952
    /* this should succeed because we have already checked if a dup exists */
 
953
    if (my_hash_insert(&bookmark_hash, (unsigned char*) result))
 
954
    {
 
955
      fprintf(stderr, "failed to add placeholder to hash");
 
956
      assert(0);
 
957
    }
 
958
  }
 
959
  return result;
 
960
}
 
961
 
 
962
 
 
963
/*
 
964
  returns a pointer to the memory which holds the session-local variable or
 
965
  a pointer to the global variable if session==null.
 
966
  If required, will sync with global variables if the requested variable
 
967
  has not yet been allocated in the current thread.
 
968
*/
 
969
static unsigned char *intern_sys_var_ptr(Session* session, int offset, bool global_lock)
 
970
{
 
971
  assert(offset >= 0);
 
972
  assert((uint32_t)offset <= global_system_variables.dynamic_variables_head);
 
973
 
 
974
  if (!session)
 
975
    return (unsigned char*) global_system_variables.dynamic_variables_ptr + offset;
 
976
 
 
977
  /*
 
978
    dynamic_variables_head points to the largest valid offset
 
979
  */
 
980
  if (!session->variables.dynamic_variables_ptr ||
 
981
      (uint32_t)offset > session->variables.dynamic_variables_head)
 
982
  {
 
983
    uint32_t idx;
 
984
 
 
985
    pthread_rwlock_rdlock(&LOCK_system_variables_hash);
 
986
 
 
987
    char *tmpptr= NULL;
 
988
    if (!(tmpptr= (char *)realloc(session->variables.dynamic_variables_ptr,
 
989
                                  global_variables_dynamic_size)))
 
990
      return NULL;
 
991
    session->variables.dynamic_variables_ptr= tmpptr;
 
992
 
 
993
    if (global_lock)
 
994
      pthread_mutex_lock(&LOCK_global_system_variables);
 
995
 
 
996
    //safe_mutex_assert_owner(&LOCK_global_system_variables);
 
997
 
 
998
    memcpy(session->variables.dynamic_variables_ptr +
 
999
             session->variables.dynamic_variables_size,
 
1000
           global_system_variables.dynamic_variables_ptr +
 
1001
             session->variables.dynamic_variables_size,
 
1002
           global_system_variables.dynamic_variables_size -
 
1003
             session->variables.dynamic_variables_size);
 
1004
 
 
1005
    /*
 
1006
      now we need to iterate through any newly copied 'defaults'
 
1007
      and if it is a string type with MEMALLOC flag, we need to strdup
 
1008
    */
 
1009
    for (idx= 0; idx < bookmark_hash.records; idx++)
 
1010
    {
 
1011
      sys_var_pluginvar *pi;
 
1012
      sys_var *var;
 
1013
      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
 
1014
 
 
1015
      if (v->version <= session->variables.dynamic_variables_version ||
 
1016
          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
 
1017
          !(pi= var->cast_pluginvar()) ||
 
1018
          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
 
1019
        continue;
 
1020
 
 
1021
      /* Here we do anything special that may be required of the data types */
 
1022
 
 
1023
      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
 
1024
          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
 
1025
      {
 
1026
         char **pp= (char**) (session->variables.dynamic_variables_ptr +
 
1027
                             *(int*)(pi->plugin_var + 1));
 
1028
         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
 
1029
                             *(int*)(pi->plugin_var + 1))))
 
1030
           *pp= strdup(*pp);
 
1031
         if (*pp == NULL)
 
1032
           return NULL;
 
1033
      }
 
1034
    }
 
1035
 
 
1036
    if (global_lock)
 
1037
      pthread_mutex_unlock(&LOCK_global_system_variables);
 
1038
 
 
1039
    session->variables.dynamic_variables_version=
 
1040
           global_system_variables.dynamic_variables_version;
 
1041
    session->variables.dynamic_variables_head=
 
1042
           global_system_variables.dynamic_variables_head;
 
1043
    session->variables.dynamic_variables_size=
 
1044
           global_system_variables.dynamic_variables_size;
 
1045
 
 
1046
    pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
1047
  }
 
1048
  return (unsigned char*)session->variables.dynamic_variables_ptr + offset;
 
1049
}
 
1050
 
 
1051
static bool *mysql_sys_var_ptr_bool(Session* a_session, int offset)
 
1052
{
 
1053
  return (bool *)intern_sys_var_ptr(a_session, offset, true);
 
1054
}
 
1055
 
 
1056
static int *mysql_sys_var_ptr_int(Session* a_session, int offset)
 
1057
{
 
1058
  return (int *)intern_sys_var_ptr(a_session, offset, true);
 
1059
}
 
1060
 
 
1061
static long *mysql_sys_var_ptr_long(Session* a_session, int offset)
 
1062
{
 
1063
  return (long *)intern_sys_var_ptr(a_session, offset, true);
 
1064
}
 
1065
 
 
1066
static int64_t *mysql_sys_var_ptr_int64_t(Session* a_session, int offset)
 
1067
{
 
1068
  return (int64_t *)intern_sys_var_ptr(a_session, offset, true);
 
1069
}
 
1070
 
 
1071
static char **mysql_sys_var_ptr_str(Session* a_session, int offset)
 
1072
{
 
1073
  return (char **)intern_sys_var_ptr(a_session, offset, true);
 
1074
}
508
1075
 
509
1076
void plugin_sessionvar_init(Session *session)
510
1077
{
511
1078
  session->variables.storage_engine= NULL;
512
 
  cleanup_variables(&session->variables);
 
1079
  cleanup_variables(session, &session->variables);
513
1080
 
514
1081
  session->variables= global_system_variables;
515
1082
  session->variables.storage_engine= NULL;
526
1093
/*
527
1094
  Unlocks all system variables which hold a reference
528
1095
*/
529
 
static void unlock_variables(Session *, struct drizzle_system_variables *vars)
 
1096
static void unlock_variables(Session *, struct system_variables *vars)
530
1097
{
531
1098
  vars->storage_engine= NULL;
532
1099
}
538
1105
  Unlike plugin_vars_free_values() it frees all variables of all plugins,
539
1106
  it's used on shutdown.
540
1107
*/
541
 
static void cleanup_variables(drizzle_system_variables *vars)
 
1108
static void cleanup_variables(Session *session, struct system_variables *vars)
542
1109
{
 
1110
  st_bookmark *v;
 
1111
  sys_var_pluginvar *pivar;
 
1112
  sys_var *var;
 
1113
  int flags;
 
1114
  uint32_t idx;
 
1115
 
 
1116
  pthread_rwlock_rdlock(&LOCK_system_variables_hash);
 
1117
  for (idx= 0; idx < bookmark_hash.records; idx++)
 
1118
  {
 
1119
    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
 
1120
    if (v->version > vars->dynamic_variables_version ||
 
1121
        !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
 
1122
        !(pivar= var->cast_pluginvar()) ||
 
1123
        v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
 
1124
      continue;
 
1125
 
 
1126
    flags= pivar->plugin_var->flags;
 
1127
 
 
1128
    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
 
1129
        flags & PLUGIN_VAR_SessionLOCAL && flags & PLUGIN_VAR_MEMALLOC)
 
1130
    {
 
1131
      char **ptr= (char**) pivar->real_value_ptr(session, OPT_SESSION);
 
1132
      free(*ptr);
 
1133
      *ptr= NULL;
 
1134
    }
 
1135
  }
 
1136
  pthread_rwlock_unlock(&LOCK_system_variables_hash);
 
1137
 
543
1138
  assert(vars->storage_engine == NULL);
544
1139
 
545
1140
  free(vars->dynamic_variables_ptr);
552
1147
void plugin_sessionvar_cleanup(Session *session)
553
1148
{
554
1149
  unlock_variables(session, &session->variables);
555
 
  cleanup_variables(&session->variables);
556
 
}
557
 
 
558
 
 
 
1150
  cleanup_variables(session, &session->variables);
 
1151
}
 
1152
 
 
1153
 
 
1154
/**
 
1155
  @brief Free values of thread variables of a plugin.
 
1156
 
 
1157
  This must be called before a plugin is deleted. Otherwise its
 
1158
  variables are no longer accessible and the value space is lost. Note
 
1159
  that only string values with PLUGIN_VAR_MEMALLOC are allocated and
 
1160
  must be freed.
 
1161
 
 
1162
  @param[in]        vars        Chain of system variables of a plugin
 
1163
*/
 
1164
 
 
1165
static void plugin_vars_free_values(sys_var *vars)
 
1166
{
 
1167
 
 
1168
  for (sys_var *var= vars; var; var= var->getNext())
 
1169
  {
 
1170
    sys_var_pluginvar *piv= var->cast_pluginvar();
 
1171
    if (piv &&
 
1172
        ((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
 
1173
        (piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
 
1174
    {
 
1175
      /* Free the string from global_system_variables. */
 
1176
      char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
 
1177
      free(*valptr);
 
1178
      *valptr= NULL;
 
1179
    }
 
1180
  }
 
1181
  return;
 
1182
}
 
1183
 
 
1184
 
 
1185
bool sys_var_pluginvar::check_update_type(Item_result type)
 
1186
{
 
1187
  if (is_readonly())
 
1188
    return 1;
 
1189
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
 
1190
  case PLUGIN_VAR_INT:
 
1191
  case PLUGIN_VAR_LONG:
 
1192
  case PLUGIN_VAR_LONGLONG:
 
1193
    return type != INT_RESULT;
 
1194
  case PLUGIN_VAR_STR:
 
1195
    return type != STRING_RESULT;
 
1196
  default:
 
1197
    return 0;
 
1198
  }
 
1199
}
 
1200
 
 
1201
 
 
1202
SHOW_TYPE sys_var_pluginvar::show_type()
 
1203
{
 
1204
  switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
 
1205
  case PLUGIN_VAR_BOOL:
 
1206
    return SHOW_MY_BOOL;
 
1207
  case PLUGIN_VAR_INT:
 
1208
    return SHOW_INT;
 
1209
  case PLUGIN_VAR_LONG:
 
1210
    return SHOW_LONG;
 
1211
  case PLUGIN_VAR_LONGLONG:
 
1212
    return SHOW_LONGLONG;
 
1213
  case PLUGIN_VAR_STR:
 
1214
    return SHOW_CHAR_PTR;
 
1215
  default:
 
1216
    assert(0);
 
1217
    return SHOW_UNDEF;
 
1218
  }
 
1219
}
 
1220
 
 
1221
 
 
1222
unsigned char* sys_var_pluginvar::real_value_ptr(Session *session, sql_var_t type)
 
1223
{
 
1224
  assert(session || (type == OPT_GLOBAL));
 
1225
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
 
1226
  {
 
1227
    if (type == OPT_GLOBAL)
 
1228
      session= NULL;
 
1229
 
 
1230
    return intern_sys_var_ptr(session, *(int*) (plugin_var+1), false);
 
1231
  }
 
1232
  return *(unsigned char**) (plugin_var+1);
 
1233
}
 
1234
 
 
1235
 
 
1236
TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
 
1237
{
 
1238
  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_SessionLOCAL)) {
 
1239
  case PLUGIN_VAR_SessionLOCAL:
 
1240
    return ((sessionvar_enum_t *)plugin_var)->typelib;
 
1241
  default:
 
1242
    return NULL;
 
1243
  }
 
1244
  return NULL;
 
1245
}
 
1246
 
 
1247
 
 
1248
unsigned char* sys_var_pluginvar::value_ptr(Session *session, sql_var_t type, const LEX_STRING *)
 
1249
{
 
1250
  unsigned char* result;
 
1251
 
 
1252
  result= real_value_ptr(session, type);
 
1253
 
 
1254
  return result;
 
1255
}
 
1256
 
 
1257
 
 
1258
bool sys_var_pluginvar::check(Session *session, set_var *var)
 
1259
{
 
1260
  st_item_value_holder value;
 
1261
  assert(is_readonly() || plugin_var->check);
 
1262
 
 
1263
  value.value_type= item_value_type;
 
1264
  value.val_str= item_val_str;
 
1265
  value.val_int= item_val_int;
 
1266
  value.val_real= item_val_real;
 
1267
  value.item= var->value;
 
1268
 
 
1269
  return is_readonly() ||
 
1270
         plugin_var->check(session, plugin_var, &var->save_result, &value);
 
1271
}
 
1272
 
 
1273
 
 
1274
void sys_var_pluginvar::set_default(Session *session, sql_var_t type)
 
1275
{
 
1276
  const void *src;
 
1277
  void *tgt;
 
1278
 
 
1279
  assert(is_readonly() || plugin_var->update);
 
1280
 
 
1281
  if (is_readonly())
 
1282
    return;
 
1283
 
 
1284
  pthread_mutex_lock(&LOCK_global_system_variables);
 
1285
  tgt= real_value_ptr(session, type);
 
1286
  src= ((void **) (plugin_var + 1) + 1);
 
1287
 
 
1288
  if (plugin_var->flags & PLUGIN_VAR_SessionLOCAL)
 
1289
  {
 
1290
    if (type != OPT_GLOBAL)
 
1291
      src= real_value_ptr(session, OPT_GLOBAL);
 
1292
    else
 
1293
    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
 
1294
        case PLUGIN_VAR_INT:
 
1295
          src= &((sessionvar_uint_t*) plugin_var)->def_val;
 
1296
          break;
 
1297
        case PLUGIN_VAR_LONG:
 
1298
          src= &((sessionvar_ulong_t*) plugin_var)->def_val;
 
1299
          break;
 
1300
        case PLUGIN_VAR_LONGLONG:
 
1301
          src= &((sessionvar_uint64_t_t*) plugin_var)->def_val;
 
1302
          break;
 
1303
        case PLUGIN_VAR_BOOL:
 
1304
          src= &((sessionvar_bool_t*) plugin_var)->def_val;
 
1305
          break;
 
1306
        case PLUGIN_VAR_STR:
 
1307
          src= &((sessionvar_str_t*) plugin_var)->def_val;
 
1308
          break;
 
1309
        default:
 
1310
          assert(0);
 
1311
        }
 
1312
  }
 
1313
 
 
1314
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1315
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1316
              session == current_session);
 
1317
 
 
1318
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || type == OPT_GLOBAL)
 
1319
  {
 
1320
    plugin_var->update(session, plugin_var, tgt, src);
 
1321
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
1322
  }
 
1323
  else
 
1324
  {
 
1325
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
1326
    plugin_var->update(session, plugin_var, tgt, src);
 
1327
  }
 
1328
}
 
1329
 
 
1330
 
 
1331
bool sys_var_pluginvar::update(Session *session, set_var *var)
 
1332
{
 
1333
  void *tgt;
 
1334
 
 
1335
  assert(is_readonly() || plugin_var->update);
 
1336
 
 
1337
  /* session must equal current_session if PLUGIN_VAR_SessionLOCAL flag is set */
 
1338
  assert(!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) ||
 
1339
              session == current_session);
 
1340
 
 
1341
  if (is_readonly())
 
1342
    return 1;
 
1343
 
 
1344
  pthread_mutex_lock(&LOCK_global_system_variables);
 
1345
  tgt= real_value_ptr(session, var->type);
 
1346
 
 
1347
  if (!(plugin_var->flags & PLUGIN_VAR_SessionLOCAL) || var->type == OPT_GLOBAL)
 
1348
  {
 
1349
    /* variable we are updating has global scope, so we unlock after updating */
 
1350
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
 
1351
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
1352
  }
 
1353
  else
 
1354
  {
 
1355
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
1356
    plugin_var->update(session, plugin_var, tgt, &var->save_result);
 
1357
  }
 
1358
 return 0;
 
1359
}
 
1360
 
 
1361
 
 
1362
#define OPTION_SET_LIMITS(type, options, opt) \
 
1363
  options->var_type= type;                    \
 
1364
  options->def_value= (opt)->def_val;         \
 
1365
  options->min_value= (opt)->min_val;         \
 
1366
  options->max_value= (opt)->max_val;         \
 
1367
  options->block_size= (long) (opt)->blk_sz
 
1368
 
 
1369
 
 
1370
void plugin_opt_set_limits(struct option *options,
 
1371
                                                                                                         const drizzle_sys_var *opt)
 
1372
{
 
1373
  options->sub_size= 0;
 
1374
 
 
1375
  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
 
1376
                        PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL)) {
 
1377
  /* global system variables */
 
1378
  case PLUGIN_VAR_INT:
 
1379
    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
 
1380
    break;
 
1381
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
 
1382
    OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
 
1383
    break;
 
1384
  case PLUGIN_VAR_LONG:
 
1385
    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
 
1386
    break;
 
1387
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
 
1388
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sysvar_ulong_t*) opt);
 
1389
    break;
 
1390
  case PLUGIN_VAR_LONGLONG:
 
1391
    OPTION_SET_LIMITS(GET_LL, options, (sysvar_int64_t_t*) opt);
 
1392
    break;
 
1393
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
 
1394
    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_uint64_t_t*) opt);
 
1395
    break;
 
1396
  case PLUGIN_VAR_BOOL:
 
1397
    options->var_type= GET_BOOL;
 
1398
    options->def_value= ((sysvar_bool_t*) opt)->def_val;
 
1399
    break;
 
1400
  case PLUGIN_VAR_STR:
 
1401
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
 
1402
                        GET_STR_ALLOC : GET_STR);
 
1403
    options->def_value= (intptr_t) ((sysvar_str_t*) opt)->def_val;
 
1404
    break;
 
1405
  /* threadlocal variables */
 
1406
  case PLUGIN_VAR_INT | PLUGIN_VAR_SessionLOCAL:
 
1407
    OPTION_SET_LIMITS(GET_INT, options, (sessionvar_int_t*) opt);
 
1408
    break;
 
1409
  case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1410
    OPTION_SET_LIMITS(GET_UINT, options, (sessionvar_uint_t*) opt);
 
1411
    break;
 
1412
  case PLUGIN_VAR_LONG | PLUGIN_VAR_SessionLOCAL:
 
1413
    OPTION_SET_LIMITS(GET_LONG, options, (sessionvar_long_t*) opt);
 
1414
    break;
 
1415
  case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1416
    OPTION_SET_LIMITS(GET_ULONG_IS_FAIL, options, (sessionvar_ulong_t*) opt);
 
1417
    break;
 
1418
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_SessionLOCAL:
 
1419
    OPTION_SET_LIMITS(GET_LL, options, (sessionvar_int64_t_t*) opt);
 
1420
    break;
 
1421
  case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_SessionLOCAL:
 
1422
    OPTION_SET_LIMITS(GET_ULL, options, (sessionvar_uint64_t_t*) opt);
 
1423
    break;
 
1424
  case PLUGIN_VAR_BOOL | PLUGIN_VAR_SessionLOCAL:
 
1425
    options->var_type= GET_BOOL;
 
1426
    options->def_value= ((sessionvar_bool_t*) opt)->def_val;
 
1427
    break;
 
1428
  case PLUGIN_VAR_STR | PLUGIN_VAR_SessionLOCAL:
 
1429
    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
 
1430
                        GET_STR_ALLOC : GET_STR);
 
1431
    options->def_value= (intptr_t) ((sessionvar_str_t*) opt)->def_val;
 
1432
    break;
 
1433
  default:
 
1434
    assert(0);
 
1435
  }
 
1436
  options->arg_type= REQUIRED_ARG;
 
1437
  if (opt->flags & PLUGIN_VAR_NOCMDARG)
 
1438
    options->arg_type= NO_ARG;
 
1439
  if (opt->flags & PLUGIN_VAR_OPCMDARG)
 
1440
    options->arg_type= OPT_ARG;
 
1441
}
 
1442
 
 
1443
static int get_one_plugin_option(int, const struct option *, char *)
 
1444
{
 
1445
  return 0;
 
1446
}
 
1447
 
 
1448
 
 
1449
static int construct_options(memory::Root *mem_root, plugin::Module *tmp,
 
1450
                             option *options)
 
1451
{
 
1452
  
 
1453
  int localoptionid= 256;
 
1454
  const string plugin_name(tmp->getManifest().name);
 
1455
 
 
1456
  size_t namelen= plugin_name.size(), optnamelen;
 
1457
 
 
1458
  char *optname, *p;
 
1459
  int index= 0, offset= 0;
 
1460
  drizzle_sys_var *opt, **plugin_option;
 
1461
  st_bookmark *v;
 
1462
 
 
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)
 
1467
  {
 
1468
    if (*iter == '_')
 
1469
      *iter= '-';
 
1470
  }
 
1471
 
 
1472
  /*
 
1473
    Two passes as the 2nd pass will take pointer addresses for use
 
1474
    by my_getopt and register_var() in the first pass uses realloc
 
1475
  */
 
1476
 
 
1477
  for (plugin_option= tmp->getManifest().system_vars;
 
1478
       plugin_option && *plugin_option; plugin_option++, index++)
 
1479
  {
 
1480
    opt= *plugin_option;
 
1481
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
 
1482
      continue;
 
1483
    if (!(register_var(name, opt->name, opt->flags)))
 
1484
      continue;
 
1485
    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
 
1486
    case PLUGIN_VAR_BOOL:
 
1487
      (((sessionvar_bool_t *)opt)->resolve)= mysql_sys_var_ptr_bool;
 
1488
      break;
 
1489
    case PLUGIN_VAR_INT:
 
1490
      (((sessionvar_int_t *)opt)->resolve)= mysql_sys_var_ptr_int;
 
1491
      break;
 
1492
    case PLUGIN_VAR_LONG:
 
1493
      (((sessionvar_long_t *)opt)->resolve)= mysql_sys_var_ptr_long;
 
1494
      break;
 
1495
    case PLUGIN_VAR_LONGLONG:
 
1496
      (((sessionvar_int64_t_t *)opt)->resolve)= mysql_sys_var_ptr_int64_t;
 
1497
      break;
 
1498
    case PLUGIN_VAR_STR:
 
1499
      (((sessionvar_str_t *)opt)->resolve)= mysql_sys_var_ptr_str;
 
1500
      break;
 
1501
    default:
 
1502
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
 
1503
                      opt->flags, plugin_name.c_str());
 
1504
      return(-1);
 
1505
    };
 
1506
  }
 
1507
 
 
1508
  for (plugin_option= tmp->getManifest().system_vars;
 
1509
       plugin_option && *plugin_option; plugin_option++, index++)
 
1510
  {
 
1511
    switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
 
1512
    case PLUGIN_VAR_BOOL:
 
1513
      if (!opt->check)
 
1514
        opt->check= check_func_bool;
 
1515
      if (!opt->update)
 
1516
        opt->update= update_func_bool;
 
1517
      break;
 
1518
    case PLUGIN_VAR_INT:
 
1519
      if (!opt->check)
 
1520
        opt->check= check_func_int;
 
1521
      if (!opt->update)
 
1522
        opt->update= update_func_int;
 
1523
      break;
 
1524
    case PLUGIN_VAR_LONG:
 
1525
      if (!opt->check)
 
1526
        opt->check= check_func_long;
 
1527
      if (!opt->update)
 
1528
        opt->update= update_func_long;
 
1529
      break;
 
1530
    case PLUGIN_VAR_LONGLONG:
 
1531
      if (!opt->check)
 
1532
        opt->check= check_func_int64_t;
 
1533
      if (!opt->update)
 
1534
        opt->update= update_func_int64_t;
 
1535
      break;
 
1536
    case PLUGIN_VAR_STR:
 
1537
      if (!opt->check)
 
1538
        opt->check= check_func_str;
 
1539
      if (!opt->update)
 
1540
      {
 
1541
        opt->update= update_func_str;
 
1542
        if ((opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) == false)
 
1543
        {
 
1544
          opt->flags|= PLUGIN_VAR_READONLY;
 
1545
          errmsg_printf(ERRMSG_LVL_WARN, _("Server variable %s of plugin %s was forced "
 
1546
                            "to be read-only: string variable without "
 
1547
                            "update_func and PLUGIN_VAR_MEMALLOC flag"),
 
1548
                            opt->name, plugin_name.c_str());
 
1549
        }
 
1550
      }
 
1551
      break;
 
1552
    default:
 
1553
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown variable type code 0x%x in plugin '%s'."),
 
1554
                      opt->flags, plugin_name.c_str());
 
1555
      return(-1);
 
1556
    }
 
1557
 
 
1558
    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_SessionLOCAL))
 
1559
                    == PLUGIN_VAR_NOCMDOPT)
 
1560
      continue;
 
1561
 
 
1562
    if (!opt->name)
 
1563
    {
 
1564
      errmsg_printf(ERRMSG_LVL_ERROR, _("Missing variable name in plugin '%s'."),
 
1565
                    plugin_name.c_str());
 
1566
      return(-1);
 
1567
    }
 
1568
 
 
1569
    if (!(opt->flags & PLUGIN_VAR_SessionLOCAL))
 
1570
    {
 
1571
      optnamelen= strlen(opt->name);
 
1572
      optname= (char*) mem_root->alloc_root(namelen + optnamelen + 2);
 
1573
      sprintf(optname, "%s-%s", name.c_str(), opt->name);
 
1574
      optnamelen= namelen + optnamelen + 1;
 
1575
    }
 
1576
    else
 
1577
    {
 
1578
      /* this should not fail because register_var should create entry */
 
1579
      if (!(v= find_bookmark(name, opt->name, opt->flags)))
 
1580
      {
 
1581
        errmsg_printf(ERRMSG_LVL_ERROR, _("Thread local variable '%s' not allocated "
 
1582
                      "in plugin '%s'."), opt->name, plugin_name.c_str());
 
1583
        return(-1);
 
1584
      }
 
1585
 
 
1586
      *(int*)(opt + 1)= offset= v->offset;
 
1587
 
 
1588
      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
 
1589
        continue;
 
1590
 
 
1591
      optname= (char*) mem_root->memdup_root(v->key + 1, (optnamelen= v->name_len) + 1);
 
1592
    }
 
1593
 
 
1594
    /* convert '_' to '-' */
 
1595
    for (p= optname; *p; p++)
 
1596
      if (*p == '_')
 
1597
        *p= '-';
 
1598
 
 
1599
    options->name= optname;
 
1600
    options->comment= opt->comment;
 
1601
    options->app_type= opt;
 
1602
    options->id= localoptionid++;
 
1603
 
 
1604
    plugin_opt_set_limits(options, opt);
 
1605
 
 
1606
    if (opt->flags & PLUGIN_VAR_SessionLOCAL)
 
1607
      options->value= options->u_max_value= (char**)
 
1608
        (global_system_variables.dynamic_variables_ptr + offset);
 
1609
    else
 
1610
      options->value= options->u_max_value= *(char***) (opt + 1);
 
1611
 
 
1612
    options++;
 
1613
  }
 
1614
 
 
1615
  return(0);
 
1616
}
 
1617
 
 
1618
 
 
1619
static option *construct_help_options(memory::Root *mem_root, plugin::Module *p)
 
1620
{
 
1621
  drizzle_sys_var **opt;
 
1622
  option *opts;
 
1623
  uint32_t count= EXTRA_OPTIONS;
 
1624
 
 
1625
  for (opt= p->getManifest().system_vars; opt && *opt; opt++, count++) {};
 
1626
 
 
1627
  opts= (option*)mem_root->alloc_root((sizeof(option) * count));
 
1628
  if (opts == NULL)
 
1629
    return NULL;
 
1630
 
 
1631
  memset(opts, 0, sizeof(option) * count);
 
1632
 
 
1633
  if (construct_options(mem_root, p, opts))
 
1634
    return NULL;
 
1635
 
 
1636
  return(opts);
 
1637
}
 
1638
 
 
1639
void drizzle_add_plugin_sysvar(sys_var_pluginvar *var)
 
1640
{
 
1641
  plugin_sysvar_vec.push_back(var);
 
1642
}
 
1643
 
 
1644
void drizzle_del_plugin_sysvar()
 
1645
{
 
1646
  vector<sys_var_pluginvar *>::iterator iter= plugin_sysvar_vec.begin();
 
1647
  while(iter != plugin_sysvar_vec.end())
 
1648
  {
 
1649
    delete *iter;
 
1650
    ++iter;
 
1651
  }
 
1652
  plugin_sysvar_vec.clear();
 
1653
}
559
1654
 
560
1655
/*
561
1656
  SYNOPSIS
562
1657
    test_plugin_options()
563
1658
    tmp_root                    temporary scratch space
564
1659
    plugin                      internal plugin structure
 
1660
    argc                        user supplied arguments
 
1661
    argv                        user supplied arguments
565
1662
    default_enabled             default plugin enable status
566
1663
  RETURNS:
567
1664
    0 SUCCESS - plugin should be enabled/loaded
568
1665
  NOTE:
569
1666
    Requires that a write-lock is held on LOCK_system_variables_hash
570
1667
*/
571
 
static int test_plugin_options(memory::Root *,
572
 
                               module::Module *test_module,
573
 
                               po::options_description &long_options)
 
1668
static int test_plugin_options(memory::Root *tmp_root, plugin::Module *tmp,
 
1669
                               int *argc, char **argv)
574
1670
{
575
 
 
576
 
  if (test_module->getManifest().init_options != NULL)
577
 
  {
578
 
    string plugin_section_title("Options used by ");
579
 
    plugin_section_title.append(test_module->getName());
580
 
    po::options_description module_options(plugin_section_title);
581
 
    module::option_context opt_ctx(test_module->getName(),
582
 
                                   module_options.add_options());
583
 
    test_module->getManifest().init_options(opt_ctx);
584
 
    long_options.add(module_options);
585
 
  }
586
 
 
587
 
  return 0;
 
1671
  struct sys_var_chain chain= { NULL, NULL };
 
1672
  drizzle_sys_var **opt;
 
1673
  option *opts= NULL;
 
1674
  int error;
 
1675
  drizzle_sys_var *o;
 
1676
  struct st_bookmark *var;
 
1677
  uint32_t len, count= EXTRA_OPTIONS;
 
1678
 
 
1679
  for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
 
1680
    count++;
 
1681
 
 
1682
 
 
1683
  if (count > EXTRA_OPTIONS || (*argc > 1))
 
1684
  {
 
1685
    if (!(opts= (option*) tmp_root->alloc_root(sizeof(option) * count)))
 
1686
    {
 
1687
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory for plugin '%s'."), tmp->getName().c_str());
 
1688
      return(-1);
 
1689
    }
 
1690
    memset(opts, 0, sizeof(option) * count);
 
1691
 
 
1692
    if (construct_options(tmp_root, tmp, opts))
 
1693
    {
 
1694
      errmsg_printf(ERRMSG_LVL_ERROR, _("Bad options for plugin '%s'."), tmp->getName().c_str());
 
1695
      return(-1);
 
1696
    }
 
1697
 
 
1698
    error= handle_options(argc, &argv, opts, get_one_plugin_option);
 
1699
    (*argc)++; /* add back one for the program name */
 
1700
 
 
1701
    if (error)
 
1702
    {
 
1703
       errmsg_printf(ERRMSG_LVL_ERROR, _("Parsing options for plugin '%s' failed."),
 
1704
                       tmp->getName().c_str());
 
1705
       goto err;
 
1706
    }
 
1707
  }
 
1708
 
 
1709
  error= 1;
 
1710
 
 
1711
  {
 
1712
    for (opt= tmp->getManifest().system_vars; opt && *opt; opt++)
 
1713
    {
 
1714
      sys_var *v;
 
1715
      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
 
1716
        continue;
 
1717
 
 
1718
      if ((var= find_bookmark(tmp->getName(), o->name, o->flags)))
 
1719
        v= new sys_var_pluginvar(var->key + 1, o);
 
1720
      else
 
1721
      {
 
1722
        len= tmp->getName().length() + strlen(o->name) + 2;
 
1723
        string vname(tmp->getName());
 
1724
        vname.push_back('-');
 
1725
        vname.append(o->name);
 
1726
        transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
 
1727
        string::iterator p= vname.begin();      
 
1728
        while  (p != vname.end())
 
1729
        {
 
1730
          if (*p == '-')
 
1731
            *p= '_';
 
1732
          ++p;
 
1733
        }
 
1734
 
 
1735
        v= new sys_var_pluginvar(vname, o);
 
1736
      }
 
1737
      assert(v); /* check that an object was actually constructed */
 
1738
 
 
1739
      drizzle_add_plugin_sysvar(static_cast<sys_var_pluginvar *>(v));
 
1740
      /*
 
1741
        Add to the chain of variables.
 
1742
        Done like this for easier debugging so that the
 
1743
        pointer to v is not lost on optimized builds.
 
1744
      */
 
1745
      v->chain_sys_var(&chain);
 
1746
    }
 
1747
    if (chain.first)
 
1748
    {
 
1749
      chain.last->setNext(NULL);
 
1750
      if (mysql_add_sys_var_chain(chain.first, NULL))
 
1751
      {
 
1752
        errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' has conflicting system variables"),
 
1753
                        tmp->getName().c_str());
 
1754
        goto err;
 
1755
      }
 
1756
      tmp->system_vars= chain.first;
 
1757
    }
 
1758
    return(0);
 
1759
  }
 
1760
 
 
1761
err:
 
1762
  if (opts)
 
1763
    my_cleanup_options(opts);
 
1764
  return(error);
588
1765
}
589
1766
 
590
1767
 
604
1781
 
605
1782
void my_print_help_inc_plugins(option *main_options)
606
1783
{
607
 
  module::Registry &registry= module::Registry::singleton();
 
1784
  plugin::Registry &registry= plugin::Registry::singleton();
608
1785
  vector<option> all_options;
 
1786
  plugin::Module *p;
609
1787
  memory::Root mem_root(4096);
610
 
 
 
1788
  option *opt= NULL;
611
1789
 
612
1790
  if (initialized)
613
1791
  {
614
 
    std::map<std::string, module::Module *>::const_iterator modules=
 
1792
    std::map<std::string, plugin::Module *>::const_iterator modules=
615
1793
      registry.getModulesMap().begin();
616
1794
    
617
1795
    while (modules != registry.getModulesMap().end())
618
1796
    {
619
 
      module::Module *p= (*modules).second;
 
1797
      p= (*modules).second;
620
1798
      ++modules;
621
1799
 
622
 
      /* If we have an init_options function, we are registering
623
 
         commmand line options that way, so don't do them this way */
624
 
      if (p->getManifest().init_options != NULL)
625
 
        continue;
626
 
 
 
1800
      if (p->getManifest().system_vars == NULL)
 
1801
        continue;
 
1802
 
 
1803
      opt= construct_help_options(&mem_root, p);
 
1804
      if (opt == NULL)
 
1805
        continue;
 
1806
 
 
1807
      /* Only options with a non-NULL comment are displayed in help text */
 
1808
      for (;opt->id; opt++)
 
1809
      {
 
1810
        if (opt->comment)
 
1811
        {
 
1812
          all_options.push_back(*opt);
 
1813
          
 
1814
        }
 
1815
      }
627
1816
    }
628
1817
  }
629
1818
 
645
1834
  all_options.push_back(*main_options);
646
1835
 
647
1836
  my_print_help(&*(all_options.begin()));
 
1837
  my_print_variables(&*(all_options.begin()));
648
1838
 
649
1839
  mem_root.free_root(MYF(0));
650
1840
}
651
1841
 
652
1842
} /* namespace drizzled */
653
 
 
654