00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017
00018 #include <dlfcn.h>
00019
00020 #include <cstdio>
00021 #include <string>
00022 #include <vector>
00023 #include <map>
00024 #include <algorithm>
00025 #include <iostream>
00026
00027 #include <boost/program_options.hpp>
00028
00029 #include <drizzled/option.h>
00030 #include <drizzled/internal/m_string.h>
00031
00032 #include <drizzled/plugin.h>
00033 #include <drizzled/module/load_list.h>
00034 #include <drizzled/module/library.h>
00035 #include <drizzled/module/registry.h>
00036 #include <drizzled/module/option_context.h>
00037 #include <drizzled/sql_parse.h>
00038 #include <drizzled/show.h>
00039 #include <drizzled/cursor.h>
00040 #include <drizzled/set_var.h>
00041 #include <drizzled/session.h>
00042 #include <drizzled/item/null.h>
00043 #include <drizzled/error.h>
00044 #include <drizzled/gettext.h>
00045 #include <drizzled/errmsg_print.h>
00046 #include <drizzled/pthread_globals.h>
00047 #include <drizzled/util/tokenize.h>
00048 #include <drizzled/system_variables.h>
00049
00050 #include <boost/foreach.hpp>
00051
00052
00053 #ifndef RTLD_NOW
00054 #define RTLD_NOW 1
00055 #endif
00056
00057 namespace po=boost::program_options;
00058
00059 using namespace std;
00060
00062 typedef drizzled::module::Manifest drizzled_builtin_list[];
00063 extern drizzled_builtin_list PANDORA_BUILTIN_SYMBOLS_LIST;
00064 extern drizzled_builtin_list PANDORA_BUILTIN_LOAD_SYMBOLS_LIST;
00065 drizzled::module::Manifest *drizzled_builtins[]=
00066 {
00067 PANDORA_BUILTIN_SYMBOLS_LIST, NULL
00068 };
00069 drizzled::module::Manifest *drizzled_load_builtins[]=
00070 {
00071 PANDORA_BUILTIN_LOAD_SYMBOLS_LIST, NULL
00072 };
00073
00074 namespace drizzled {
00075
00076
00077 typedef vector<string> PluginOptions;
00078 static PluginOptions opt_plugin_load;
00079 static PluginOptions opt_plugin_add;
00080 static PluginOptions opt_plugin_remove;
00081 const char *builtin_plugins= PANDORA_BUILTIN_LIST;
00082 const char *builtin_load_plugins= PANDORA_BUILTIN_LOAD_LIST;
00083
00084
00085
00086
00087
00088 static bool initialized= false;
00089
00090
00091 static bool reap_needed= false;
00092
00093
00094
00095
00096
00097 static memory::Root plugin_mem_root(4096);
00098 static uint32_t global_variables_dynamic_size= 0;
00099
00100
00101
00102
00103
00104
00105 struct st_item_value_holder : public drizzle_value
00106 {
00107 Item *item;
00108 };
00109
00110
00111 static void plugin_prune_list(vector<string> &plugin_list, const vector<string> &plugins_to_remove);
00112 static bool plugin_load_list(module::Registry ®istry,
00113 memory::Root *tmp_root,
00114 const set<string> &plugin_list,
00115 po::options_description &long_options,
00116 bool builtin= false);
00117 static int test_plugin_options(memory::Root*, module::Module*, po::options_description&long_options);
00118 static void unlock_variables(Session *session, drizzle_system_variables *vars);
00119 static void cleanup_variables(drizzle_system_variables *vars);
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 static bool plugin_add(module::Registry ®istry, memory::Root *tmp_root,
00134 module::Library *library,
00135 po::options_description &long_options)
00136 {
00137 if (! initialized)
00138 return true;
00139
00140 if (registry.find(library->getName()))
00141 {
00142 errmsg_printf(error::WARN, ER(ER_PLUGIN_EXISTS),
00143 library->getName().c_str());
00144 return false;
00145 }
00146
00147
00148 const module::Manifest *manifest= library->getManifest();
00149
00150 if (registry.find(manifest->name))
00151 {
00152 errmsg_printf(error::ERROR,
00153 _("Plugin '%s' contains the name '%s' in its manifest, which "
00154 "has already been registered.\n"),
00155 library->getName().c_str(),
00156 manifest->name);
00157 return true;
00158 }
00159
00160 module::Module* tmp= new module::Module(manifest, library);
00161
00162 if (!test_plugin_options(tmp_root, tmp, long_options))
00163 {
00164 registry.add(tmp);
00165 return false;
00166 }
00167 errmsg_printf(error::ERROR, ER(ER_CANT_FIND_DL_ENTRY),
00168 library->getName().c_str());
00169 return true;
00170 }
00171
00172
00173 static void reap_plugins(module::Registry ®istry)
00174 {
00175 BOOST_FOREACH(module::Registry::ModuleMap::const_reference module, registry.getModulesMap())
00176 delete module.second;
00177 }
00178
00179
00180 static bool plugin_initialize(module::Registry ®istry,
00181 module::Module *module)
00182 {
00183 assert(module->isInited == false);
00184
00185 module::Context loading_context(registry, module);
00186 if (module->getManifest().init)
00187 {
00188 if (module->getManifest().init(loading_context))
00189 {
00190 errmsg_printf(error::ERROR,
00191 _("Plugin '%s' init function returned error.\n"),
00192 module->getName().c_str());
00193 return true;
00194 }
00195 }
00196 module->isInited= true;
00197 return false;
00198 }
00199
00200 static void compose_plugin_options(vector<string> &target,
00201 vector<string> options)
00202 {
00203 BOOST_FOREACH(vector<string>::reference it, options)
00204 tokenize(it, target, ",", true);
00205 BOOST_FOREACH(vector<string>::reference it, target)
00206 std::replace(it.begin(), it.end(), '-', '_');
00207 }
00208
00209 void compose_plugin_add(const vector<string>& options)
00210 {
00211 compose_plugin_options(opt_plugin_add, options);
00212 }
00213
00214 void compose_plugin_remove(const vector<string>& options)
00215 {
00216 compose_plugin_options(opt_plugin_remove, options);
00217 }
00218
00219 void notify_plugin_load(const string& in_plugin_load)
00220 {
00221 tokenize(in_plugin_load, opt_plugin_load, ",", true);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231 bool plugin_init(module::Registry ®istry,
00232 po::options_description &long_options)
00233 {
00234 if (initialized)
00235 return false;
00236
00237 initialized= true;
00238
00239 PluginOptions builtin_load_list;
00240 tokenize(builtin_load_plugins, builtin_load_list, ",", true);
00241
00242 PluginOptions builtin_list;
00243 tokenize(builtin_plugins, builtin_list, ",", true);
00244
00245 bool load_failed= false;
00246
00247 if (opt_plugin_add.size() > 0)
00248 {
00249 for (PluginOptions::iterator iter= opt_plugin_add.begin();
00250 iter != opt_plugin_add.end();
00251 ++iter)
00252 {
00253 if (find(builtin_list.begin(),
00254 builtin_list.end(), *iter) != builtin_list.end())
00255 {
00256 builtin_load_list.push_back(*iter);
00257 }
00258 else
00259 {
00260 opt_plugin_load.push_back(*iter);
00261 }
00262 }
00263 }
00264
00265 if (opt_plugin_remove.size() > 0)
00266 {
00267 plugin_prune_list(opt_plugin_load, opt_plugin_remove);
00268 plugin_prune_list(builtin_load_list, opt_plugin_remove);
00269 }
00270
00271 memory::Root tmp_root(4096);
00272
00273
00274
00275 const set<string> builtin_list_set(builtin_load_list.begin(),
00276 builtin_load_list.end());
00277 load_failed= plugin_load_list(registry, &tmp_root,
00278 builtin_list_set, long_options, true);
00279 if (load_failed)
00280 {
00281 tmp_root.free_root(MYF(0));
00282 return true;
00283 }
00284
00285
00286 const set<string> plugin_list_set(opt_plugin_load.begin(),
00287 opt_plugin_load.end());
00288
00289
00290 load_failed= plugin_load_list(registry, &tmp_root,
00291 plugin_list_set, long_options);
00292 if (load_failed)
00293 {
00294 tmp_root.free_root(MYF(0));
00295 return true;
00296 }
00297
00298 tmp_root.free_root(MYF(0));
00299
00300 return false;
00301 }
00302
00303 bool plugin_finalize(module::Registry ®istry)
00304 {
00305
00306
00307
00308 BOOST_FOREACH(module::Registry::ModuleList::const_reference module, registry.getList())
00309 {
00310 if (not module->isInited && plugin_initialize(registry, module))
00311 {
00312 registry.remove(module);
00313 delete module;
00314 return true;
00315 }
00316 }
00317 BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
00318 {
00319 value.second->prime();
00320 }
00321 return false;
00322 }
00323
00324
00325
00326
00327 void plugin_startup_window(module::Registry ®istry, drizzled::Session &session)
00328 {
00329 BOOST_FOREACH(plugin::Plugin::map::value_type value, registry.getPluginsMap())
00330 {
00331 value.second->startup(session);
00332 }
00333 }
00334
00335 class PrunePlugin :
00336 public unary_function<string, bool>
00337 {
00338 const string to_match;
00339 public:
00340 explicit PrunePlugin(const string &match_in) :
00341 to_match(match_in)
00342 { }
00343
00344 result_type operator()(const string &match_against)
00345 {
00346 return match_against == to_match;
00347 }
00348 };
00349
00350 static void plugin_prune_list(vector<string> &plugin_list,
00351 const vector<string> &plugins_to_remove)
00352 {
00353 for (vector<string>::const_iterator iter= plugins_to_remove.begin();
00354 iter != plugins_to_remove.end();
00355 ++iter)
00356 {
00357 plugin_list.erase(remove_if(plugin_list.begin(),
00358 plugin_list.end(),
00359 PrunePlugin(*iter)),
00360 plugin_list.end());
00361 }
00362 }
00363
00364
00365
00366
00367 static bool plugin_load_list(module::Registry ®istry,
00368 memory::Root *tmp_root,
00369 const set<string> &plugin_list,
00370 po::options_description &long_options,
00371 bool builtin)
00372 {
00373 BOOST_FOREACH(const string& plugin_name, plugin_list)
00374 {
00375 module::Library* library= registry.addLibrary(plugin_name, builtin);
00376 if (library == NULL)
00377 {
00378 errmsg_printf(error::ERROR,
00379 _("Couldn't load plugin library named '%s'.\n"),
00380 plugin_name.c_str());
00381 return true;
00382 }
00383
00384 tmp_root->free_root(MYF(memory::MARK_BLOCKS_FREE));
00385 if (plugin_add(registry, tmp_root, library, long_options))
00386 {
00387 registry.removeLibrary(plugin_name);
00388 errmsg_printf(error::ERROR,
00389 _("Couldn't load plugin named '%s'.\n"),
00390 plugin_name.c_str());
00391 return true;
00392 }
00393 }
00394 return false;
00395 }
00396
00397 void module_shutdown(module::Registry ®istry)
00398 {
00399 if (initialized)
00400 {
00401 reap_needed= true;
00402
00403 reap_plugins(registry);
00404 unlock_variables(NULL, &global_system_variables);
00405 unlock_variables(NULL, &max_system_variables);
00406
00407 cleanup_variables(&global_system_variables);
00408 cleanup_variables(&max_system_variables);
00409
00410 initialized= 0;
00411 }
00412
00413
00414 plugin_mem_root.free_root(MYF(0));
00415
00416 global_variables_dynamic_size= 0;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426 void plugin_sessionvar_init(Session *session)
00427 {
00428 session->variables.storage_engine= NULL;
00429 cleanup_variables(&session->variables);
00430
00431 session->variables= global_system_variables;
00432 session->variables.storage_engine= NULL;
00433
00434
00435 session->variables.dynamic_variables_version= 0;
00436 session->variables.dynamic_variables_size= 0;
00437 session->variables.dynamic_variables_ptr= 0;
00438
00439 session->variables.storage_engine= global_system_variables.storage_engine;
00440 }
00441
00442
00443
00444
00445
00446 static void unlock_variables(Session *, struct drizzle_system_variables *vars)
00447 {
00448 vars->storage_engine= NULL;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458 static void cleanup_variables(drizzle_system_variables *vars)
00459 {
00460 assert(vars->storage_engine == NULL);
00461
00462 free(vars->dynamic_variables_ptr);
00463 vars->dynamic_variables_ptr= NULL;
00464 vars->dynamic_variables_size= 0;
00465 vars->dynamic_variables_version= 0;
00466 }
00467
00468
00469 void plugin_sessionvar_cleanup(Session *session)
00470 {
00471 unlock_variables(session, &session->variables);
00472 cleanup_variables(&session->variables);
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 static int test_plugin_options(memory::Root *,
00489 module::Module *test_module,
00490 po::options_description &long_options)
00491 {
00492
00493 if (test_module->getManifest().init_options != NULL)
00494 {
00495 string plugin_section_title("Options used by ");
00496 plugin_section_title.append(test_module->getName());
00497 po::options_description module_options(plugin_section_title);
00498 module::option_context opt_ctx(test_module->getName(),
00499 module_options.add_options());
00500 test_module->getManifest().init_options(opt_ctx);
00501 long_options.add(module_options);
00502 }
00503
00504 return 0;
00505 }
00506
00507
00508
00509
00510
00511
00512 class OptionCmp
00513 {
00514 public:
00515 bool operator() (const option &a, const option &b)
00516 {
00517 return my_charset_utf8_general_ci.strcasecmp(a.name, b.name);
00518 }
00519 };
00520
00521
00522 void my_print_help_inc_plugins(option *main_options)
00523 {
00524 module::Registry ®istry= module::Registry::singleton();
00525 vector<option> all_options;
00526 memory::Root mem_root(4096);
00527
00528
00529 if (initialized)
00530 {
00531 std::map<std::string, module::Module *>::const_iterator modules=
00532 registry.getModulesMap().begin();
00533
00534 while (modules != registry.getModulesMap().end())
00535 {
00536 module::Module *p= (*modules).second;
00537 ++modules;
00538
00539
00540
00541 if (p->getManifest().init_options != NULL)
00542 continue;
00543
00544 }
00545 }
00546
00547 for (;main_options->id; main_options++)
00548 {
00549 if (main_options->comment)
00550 {
00551 all_options.push_back(*main_options);
00552 }
00553 }
00554
00561
00562 all_options.push_back(*main_options);
00563
00564 my_print_help(&*(all_options.begin()));
00565
00566 mem_root.free_root(MYF(0));
00567 }
00568
00569 }
00570
00571