24 #include <config/config.h>
25 #include <core/exception.h>
26 #include <core/plugin.h>
27 #include <core/threading/mutex_locker.h>
28 #include <core/threading/thread_collector.h>
29 #include <core/threading/thread_initializer.h>
30 #include <logging/liblogger.h>
31 #include <plugin/listener.h>
32 #include <plugin/loader.h>
33 #include <plugin/manager.h>
34 #include <sys/types.h>
35 #include <utils/misc/string_split.h>
36 #include <utils/system/dynamic_module/module_manager.h>
37 #include <utils/system/fam_thread.h>
51 plname_eq(std::string name)
58 return (name_ == plugin->
name());
87 const char * meta_plugin_prefix,
93 this->thread_collector = thread_collector;
98 meta_plugin_prefix_ = meta_plugin_prefix;
109 fam->add_filter(
"^[^.].*\\." SOEXT
"$");
110 fam->add_listener(
this);
111 fam->watch_dir(PLUGINDIR);
112 fam_thread_->
start();
115 "File alteration monitoring not available, "
116 "cannot detect changed plugins on disk.");
130 pinfo_cache_.clear();
133 for (rpit = plugins.rbegin(); rpit != plugins.rend(); ++rpit) {
142 plugin_loader->
unload(*rpit);
146 delete plugin_loader;
167 const char * file_ext =
"." SOEXT;
169 if (NULL == (plugin_dir = opendir(PLUGINDIR))) {
170 throw Exception(errno,
"Plugin directory %s could not be opened", PLUGINDIR);
173 for (
unsigned int i = 0; NULL != (dirp = readdir(plugin_dir)); ++i) {
174 char * file_name = dirp->d_name;
175 char * pos = strstr(file_name, file_ext);
176 std::string plugin_name =
177 std::string(file_name).substr(0, strlen(file_name) - strlen(file_ext));
180 pinfo_cache_.push_back(
181 make_pair(plugin_name, plugin_loader->
get_description(plugin_name.c_str())));
184 "Could not get description of plugin %s, "
186 plugin_name.c_str());
192 closedir(plugin_dir);
198 std::string p = std::string(i->
path()).substr(meta_plugin_prefix_.length());
199 std::string s = std::string(
"Meta: ") + i->
get_string();
201 pinfo_cache_.push_back(make_pair(p, s));
217 std::list<std::pair<std::string, std::string>>
220 std::list<std::pair<std::string, std::string>> rv;
222 std::list<std::pair<std::string, std::string>>::iterator i;
223 for (i = pinfo_cache_.begin(); i != pinfo_cache_.end(); ++i) {
233 std::list<std::string>
236 std::list<std::string> rv;
239 for (pit = plugins.begin(); pit != plugins.end(); ++pit) {
240 rv.push_back((*pit)->name());
243 meta_plugins_.
lock();
244 for (mpit_ = meta_plugins_.begin(); mpit_ != meta_plugins_.end(); ++mpit_) {
245 rv.push_back(mpit_->first);
259 if (plugin_loader->
is_loaded(plugin_name.c_str())) {
263 return (meta_plugins_.find(plugin_name) != meta_plugins_.end());
275 std::string meta_plugin_path = meta_plugin_prefix_ + plugin_name;
276 return (config_->
is_string(meta_plugin_path.c_str()));
286 std::list<std::string>
289 std::string meta_plugin_path = meta_plugin_prefix_ + plugin_name;
290 std::string meta_plugin_str = config_->
get_string(meta_plugin_path.c_str());
291 return parse_plugin_list(meta_plugin_str.c_str());
300 std::list<std::string>
301 PluginManager::parse_plugin_list(
const char *plugin_list)
303 std::list<std::string> rv;
305 char *plugins = strdup(plugin_list);
309 plugin = strtok_r(plugins,
",", &saveptr);
311 rv.push_back(plugin);
312 plugin = strtok_r(NULL,
",", &saveptr);
327 load(parse_plugin_list(plugin_list.c_str()));
339 for (std::list<std::string>::const_iterator i = plugin_list.begin(); i != plugin_list.end();
341 if (i->length() == 0)
344 bool try_real_plugin =
true;
345 if (meta_plugins_.find(*i) == meta_plugins_.end()) {
346 std::string meta_plugin = meta_plugin_prefix_ + *i;
347 bool found_meta =
false;
348 std::list<std::string> pset;
350 if (config_->
is_list(meta_plugin.c_str())) {
351 std::vector<std::string> tmp = config_->
get_strings(meta_plugin.c_str());
352 pset.insert(pset.end(), tmp.begin(), tmp.end());
354 pset = parse_plugin_list(config_->
get_string(meta_plugin.c_str()).c_str());
359 try_real_plugin =
true;
363 if (pset.size() == 0) {
364 throw Exception(
"Refusing to load an empty meta plugin");
367 meta_plugins_.
lock();
370 meta_plugins_[*i] = pset;
374 "Loading plugins %s for meta plugin %s",
375 str_join(pset.begin(), pset.end(),
",").c_str(),
379 notify_loaded(i->c_str());
381 e.
append(
"Could not initialize meta plugin %s, aborting loading.", i->c_str());
386 try_real_plugin =
false;
391 && (find_if(plugins.begin(), plugins.end(), plname_eq(*i)) == plugins.end())) {
394 Plugin *plugin = plugin_loader->
load(i->c_str());
398 plugins.push_back(plugin);
399 plugin_ids[*i] = next_plugin_id++;
401 notify_loaded(i->c_str());
403 e.
append(
"Plugin >>> %s <<< could not be initialized, unloading", i->c_str());
405 plugin_loader->
unload(plugin);
411 if (meta_plugins_.find(*i) == meta_plugins_.end()) {
430 if ((pit = find_if(plugins.begin(), plugins.end(), plname_eq(plugin_name))) != plugins.end()) {
432 thread_collector->
remove((*pit)->threads());
433 plugin_loader->
unload(*pit);
435 plugin_ids.erase(plugin_name);
436 notify_unloaded(plugin_name.c_str());
439 meta_plugins_.
lock();
440 mpit_ = meta_plugins_.begin();
441 while (mpit_ != meta_plugins_.end()) {
442 std::list<std::string> pp = mpit_->second;
445 for (std::list<std::string>::iterator i = pp.begin(); i != pp.end(); ++i) {
446 if (*i == plugin_name) {
454 notify_unloaded(tmp->first.c_str());
455 meta_plugins_.erase(tmp);
464 "Could not finalize one or more threads "
465 "of plugin %s, NOT unloading plugin",
466 plugin_name.c_str());
469 }
else if (meta_plugins_.find(plugin_name) != meta_plugins_.end()) {
470 std::list<std::string> pp = meta_plugins_[plugin_name];
472 for (std::list<std::string>::reverse_iterator i = pp.rbegin(); i != pp.rend(); ++i) {
473 if (i->length() == 0)
475 if ((find_if(plugins.begin(), plugins.end(), plname_eq(*i)) == plugins.end())
476 && (meta_plugins_.find(*i) != meta_plugins_.end())) {
482 "UNloading plugin %s for meta plugin %s",
484 plugin_name.c_str());
500 std::string p = std::string(v->
path()).substr(meta_plugin_prefix_.length());
501 std::string s = std::string(
"Meta: ") + v->
get_string();
502 std::list<std::pair<std::string, std::string>>::iterator i;
504 for (i = pinfo_cache_.begin(); i != pinfo_cache_.end(); ++i) {
512 pinfo_cache_.push_back(make_pair(p, s));
527 std::string p = std::string(path).substr(meta_plugin_prefix_.length());
528 std::list<std::pair<std::string, std::string>>::iterator i;
529 for (i = pinfo_cache_.begin(); i != pinfo_cache_.end(); ++i) {
531 pinfo_cache_.erase(i);
541 const char *file_ext =
"." SOEXT;
543 const char *pos = strstr(filename, file_ext);
544 std::string p = std::string(filename).substr(0, strlen(filename) - strlen(file_ext));
548 std::list<std::pair<std::string, std::string>>::iterator i;
549 for (i = pinfo_cache_.begin(); i != pinfo_cache_.end(); ++i) {
553 pinfo_cache_.erase(i);
559 "Could not get possibly modified "
560 "description of plugin %s, exception follows",
571 if (plugin_loader->
is_loaded(p.c_str())) {
573 "Plugin %s changed on disk, but is "
574 "loaded, no new info can be loaded, keeping old.",
580 LibLogger::log_info(
"PluginManager",
"Reloaded meta-data of %s on file change", p.c_str());
581 pinfo_cache_.push_back(make_pair(p, s));
606 listeners_.push_back(listener);
618 listeners_.remove_locked(listener);
622 PluginManager::notify_loaded(
const char *plugin_name)
625 for (lit_ = listeners_.begin(); lit_ != listeners_.end(); ++lit_) {
627 (*lit_)->plugin_loaded(plugin_name);
628 }
catch (Exception &e) {
630 "PluginManagerListener threw exception "
631 "during notification of plugin loaded, exception follows.");
639 PluginManager::notify_unloaded(
const char *plugin_name)
642 for (lit_ = listeners_.begin(); lit_ != listeners_.end(); ++lit_) {
644 (*lit_)->plugin_unloaded(plugin_name);
645 }
catch (Exception &e) {
647 "PluginManagerListener threw exception "
648 "during notification of plugin unloaded, exception follows.");