~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/loader.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

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