Fawkes API  Fawkes Development Version
manager.cpp
1 
2 /***************************************************************************
3  * manager.cpp - Fawkes plugin manager
4  *
5  * Created: Wed Nov 15 23:31:55 2006 (on train to Cologne)
6  * Copyright 2006-2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <plugin/manager.h>
25 #include <plugin/listener.h>
26 #include <plugin/loader.h>
27 
28 #include <core/plugin.h>
29 #include <core/threading/thread_collector.h>
30 #include <core/threading/thread_initializer.h>
31 #include <core/threading/mutex_locker.h>
32 #include <core/exception.h>
33 #include <logging/liblogger.h>
34 #ifdef HAVE_INOTIFY
35 # include <utils/system/fam_thread.h>
36 #endif
37 #include <config/config.h>
38 #include <utils/system/dynamic_module/module_manager.h>
39 
40 #include <algorithm>
41 #include <cstring>
42 #include <cstdlib>
43 #include <cerrno>
44 
45 #include <sys/types.h>
46 #include <dirent.h>
47 
48 namespace fawkes {
49 #if 0 /* just to make Emacs auto-indent happy */
50 }
51 #endif
52 
53 /// @cond INTERNALS
54 class plname_eq
55 {
56 public:
57  plname_eq(std::string name) {
58  __name = name;
59  }
60  bool operator()(Plugin *plugin)
61  {
62  return (__name == plugin->name());
63  }
64 private:
65  std::string __name;
66 };
67 /// @endcond INTERNALS
68 
69 /** @class PluginManager <plugin/manager.h>
70  * Fawkes Plugin Manager.
71  * This class provides a manager for the plugins used in fawkes. It can
72  * load and unload modules.
73  *
74  * @author Tim Niemueller
75  */
76 
77 /** Constructor.
78  * @param thread_collector thread manager plugin threads will be added to
79  * and removed from appropriately.
80  * @param config Fawkes configuration
81  * @param meta_plugin_prefix Path prefix for meta plugins
82  * @param module_flags flags to use to open plugin modules
83  * @param init_cache true to initialize the plugin cache, false to skip this
84  * step. Note that some functions like transmitting a list of available plugins
85  * is unavailable until the cache has been initialized. You can defer
86  * initialization of the cache if required.
87  */
88 PluginManager::PluginManager(ThreadCollector *thread_collector,
89  Configuration *config,
90  const char *meta_plugin_prefix,
91  Module::ModuleFlags module_flags,
92  bool init_cache)
93  : ConfigurationChangeHandler(meta_plugin_prefix)
94 {
95  __mutex = new Mutex();
96  this->thread_collector = thread_collector;
97  plugin_loader = new PluginLoader(PLUGINDIR, config);
98  plugin_loader->get_module_manager()->set_open_flags(module_flags);
99  next_plugin_id = 1;
100  __config = config;
101  __meta_plugin_prefix = meta_plugin_prefix;
102 
103  if (init_cache) {
105  }
106 
107  __config->add_change_handler(this);
108 
109 #ifdef HAVE_INOTIFY
110  __fam_thread = new FamThread();
111  RefPtr<FileAlterationMonitor> fam = __fam_thread->get_fam();
112  fam->add_filter("^[^.].*\\."SOEXT"$");
113  fam->add_listener(this);
114  fam->watch_dir(PLUGINDIR);
115  __fam_thread->start();
116 #else
117  LibLogger::log_warn("PluginManager", "File alteration monitoring not available, "
118  "cannot detect changed plugins on disk.");
119 #endif
120 }
121 
122 
123 /** Destructor. */
125 {
126 #ifdef HAVE_INOTIFY
127  __fam_thread->cancel();
128  __fam_thread->join();
129  delete __fam_thread;
130 #endif
131  __config->rem_change_handler(this);
132  __pinfo_cache.lock();
133  __pinfo_cache.clear();
134  __pinfo_cache.unlock();
135  // Unload all plugins
136  for (rpit = plugins.rbegin(); rpit != plugins.rend(); ++rpit) {
137  thread_collector->force_remove((*rpit)->threads());
138  plugin_loader->unload(*rpit);
139  }
140  plugins.clear();
141  plugin_ids.clear();
142  delete plugin_loader;
143  delete __mutex;
144 }
145 
146 
147 /** Set flags to open modules with.
148  * @param flags flags to pass to modules when opening them
149  */
150 void
152 {
153  plugin_loader->get_module_manager()->set_open_flags(flags);
154 }
155 
156 
157 /** Initialize plugin info cache. */
158 void
160 {
161  __pinfo_cache.lock();
162 
163  DIR *plugin_dir;
164  struct dirent* dirp;
165  const char *file_ext = "."SOEXT;
166 
167  if ( NULL == (plugin_dir = opendir(PLUGINDIR)) ) {
168  throw Exception(errno, "Plugin directory %s could not be opened", PLUGINDIR);
169  }
170 
171  for (unsigned int i = 0; NULL != (dirp = readdir(plugin_dir)); ++i) {
172  char *file_name = dirp->d_name;
173  char *pos = strstr(file_name, file_ext);
174  std::string plugin_name = std::string(file_name).substr(0, strlen(file_name) - strlen(file_ext));
175  if (NULL != pos) {
176  try {
177  __pinfo_cache.push_back(make_pair(plugin_name,
178  plugin_loader->get_description(plugin_name.c_str())));
179  } catch (Exception &e) {
180  LibLogger::log_warn("PluginManager", "Could not get description of plugin %s, "
181  "exception follows", plugin_name.c_str());
182  LibLogger::log_warn("PluginManager", e);
183  }
184  }
185  }
186 
187  closedir(plugin_dir);
188 
189  try {
190  Configuration::ValueIterator *i = __config->search(__meta_plugin_prefix.c_str());
191  while (i->next()) {
192  if (i->is_string()) {
193  std::string p = std::string(i->path()).substr(__meta_plugin_prefix.length());
194  std::string s = std::string("Meta: ") + i->get_string();
195 
196  __pinfo_cache.push_back(make_pair(p, s));
197  }
198  }
199  delete i;
200  } catch (Exception &e) {
201  }
202 
203  __pinfo_cache.sort();
204  __pinfo_cache.unlock();
205 }
206 
207 /** Generate list of all available plugins.
208  * @return list of plugins that are available, each plugin is represented by
209  * a pair of strings. The first string is the plugin name, the second is its
210  * description.
211  */
212 std::list<std::pair<std::string, std::string> >
214 {
215  std::list<std::pair<std::string, std::string> > rv;
216 
217  std::list<std::pair<std::string, std::string> >::iterator i;
218  for (i = __pinfo_cache.begin(); i != __pinfo_cache.end(); ++i) {
219  rv.push_back(*i);
220  }
221 
222  return rv;
223 }
224 
225 /** Get list of loaded plugins.
226  * @return list of names of real and meta plugins currently loaded
227  */
228 std::list<std::string>
230 {
231  std::list<std::string> rv;
232 
233  plugins.lock();
234  for (pit = plugins.begin(); pit != plugins.end(); ++pit) {
235  rv.push_back((*pit)->name());
236  }
237  plugins.unlock();
238  __meta_plugins.lock();
239  for (__mpit = __meta_plugins.begin(); __mpit != __meta_plugins.end(); ++__mpit) {
240  rv.push_back(__mpit->first);
241  }
242  __meta_plugins.unlock();
243 
244  return rv;
245 }
246 
247 
248 /** Check if plugin is loaded.
249  * @param plugin_name plugin to check if it is loaded
250  * @return true if the plugin is currently loaded, false otherwise
251  */
252 bool
253 PluginManager::is_loaded(const char *plugin_name)
254 {
255  if (plugin_loader->is_loaded(plugin_name)) {
256  return true;
257  } else {
258  // Could still be a meta plugin
259  return (__meta_plugins.find(plugin_name) != __meta_plugins.end());
260  }
261 }
262 
263 
264 /** Parse a list of plugin types.
265  * Takes a comma-separated list of plugins and parses them into the individual
266  * plugin names.
267  * @param plugin_type_list string containing a comma-separated list of plugin types
268  * @return parsed list of plugin types
269  */
270 std::list<std::string>
271 PluginManager::parse_plugin_list(const char *plugin_list)
272 {
273  std::list<std::string> rv;
274 
275  char *plugins = strdup(plugin_list);
276  char *saveptr;
277  char *plugin;
278 
279  plugin = strtok_r(plugins, ",", &saveptr);
280  while ( plugin ) {
281  rv.push_back(plugin);
282  plugin = strtok_r(NULL, ",", &saveptr);
283  }
284  free(plugins);
285 
286  return rv;
287 }
288 
289 
290 /** Load plugin.
291  * The loading is interrupted if any of the plugins does not load properly.
292  * The already loaded plugins are *not* unloaded, but kept.
293  * @param plugin_list string containing a comma-separated list of plugins
294  * to load. The plugin list can contain meta plugins.
295  */
296 void
297 PluginManager::load(const char *plugin_list)
298 {
299  std::list<std::string> pp = parse_plugin_list(plugin_list);
300 
301  for (std::list<std::string>::iterator i = pp.begin(); i != pp.end(); ++i) {
302  if ( i->length() == 0 ) continue;
303 
304  bool try_real_plugin = true;
305  if ( __meta_plugins.find(*i) == __meta_plugins.end() ) {
306  std::string meta_plugin = __meta_plugin_prefix + *i;
307  try {
308  std::string pset = __config->get_string(meta_plugin.c_str());
309  if (pset.length() == 0) {
310  throw Exception("Refusing to load an empty meta plugin");
311  }
312  //printf("Going to load meta plugin %s (%s)\n", i->c_str(), pset.c_str());
313  __meta_plugins.lock();
314  // Setting has to happen here, so that a meta plugin will not cause an
315  // endless loop if it references itself!
316  __meta_plugins[*i] = pset;
317  __meta_plugins.unlock();
318  try {
319  LibLogger::log_info("PluginManager", "Loading plugins %s for meta plugin %s",
320  pset.c_str(), i->c_str());
321  load(pset.c_str());
322  notify_loaded(i->c_str());
323  } catch (Exception &e) {
324  e.append("Could not initialize meta plugin %s, aborting loading.", i->c_str());
325  __meta_plugins.erase_locked(*i);
326  throw;
327  }
328 
329  try_real_plugin = false;
330  } catch (ConfigEntryNotFoundException &e) {
331  // no meta plugin defined by that name
332  //printf("No meta plugin defined with the name %s\n", i->c_str());
333  try_real_plugin = true;
334  }
335  }
336 
337  if (try_real_plugin &&
338  (find_if(plugins.begin(), plugins.end(), plname_eq(*i)) == plugins.end()))
339  {
340  try {
341  //printf("Going to load real plugin %s\n", i->c_str());
342  Plugin *plugin = plugin_loader->load(i->c_str());
343  plugins.lock();
344  try {
345  thread_collector->add(plugin->threads());
346  plugins.push_back(plugin);
347  plugin_ids[*i] = next_plugin_id++;
348  notify_loaded(i->c_str());
349  } catch (CannotInitializeThreadException &e) {
350  e.prepend("Plugin >>> %s <<< could not be initialized, unloading", i->c_str());
351  plugins.unlock();
352  plugin_loader->unload(plugin);
353  throw;
354  }
355  plugins.unlock();
356  } catch (Exception &e) {
357  MutexLocker lock(__meta_plugins.mutex());
358  if ( __meta_plugins.find(*i) == __meta_plugins.end() ) {
359  // only throw exception if no meta plugin with that name has
360  // already been loaded
361  throw;
362  }
363  }
364  }
365  }
366 }
367 
368 
369 /** Unload plugin.
370  * Note that this method does not allow to pass a list of plugins, but it will
371  * only accept a single plugin at a time.
372  * @param plugin_name plugin to unload, can be a meta plugin.
373  */
374 void
375 PluginManager::unload(const char *plugin_name)
376 {
377  MutexLocker lock(plugins.mutex());
378  if ( (pit = find_if(plugins.begin(), plugins.end(), plname_eq(plugin_name)))
379  != plugins.end()) {
380  try {
381  thread_collector->remove((*pit)->threads());
382  plugin_loader->unload(*pit);
383  plugins.erase(pit);
384  plugin_ids.erase(plugin_name);
385  notify_unloaded(plugin_name);
386  // find all meta plugins that required this module, this can no longer
387  // be considered loaded
388  __meta_plugins.lock();
389  __mpit = __meta_plugins.begin();
390  while (__mpit != __meta_plugins.end()) {
391  std::list<std::string> pp = parse_plugin_list(__mpit->second.c_str());
392 
393  bool erase = false;
394  for (std::list<std::string>::iterator i = pp.begin(); i != pp.end(); ++i) {
395  if ( *i == plugin_name ) {
396  erase = true;
397  break;
398  }
399  }
400  if ( erase ) {
402  ++__mpit;
403  notify_unloaded(tmp->first.c_str());
404  __meta_plugins.erase(tmp);
405  } else {
406  ++__mpit;
407  }
408  }
409  __meta_plugins.unlock();
410 
411  } catch (Exception &e) {
412  LibLogger::log_error("PluginManager", "Could not finalize one or more threads of plugin %s, NOT unloading plugin", plugin_name);
413  throw;
414  }
415  } else if (__meta_plugins.find(plugin_name) != __meta_plugins.end()) {
416  std::list<std::string> pp = parse_plugin_list(__meta_plugins[plugin_name].c_str());
417 
418  for (std::list<std::string>::reverse_iterator i = pp.rbegin(); i != pp.rend(); ++i) {
419  if ( i->length() == 0 ) continue;
420  if ((find_if(plugins.begin(), plugins.end(), plname_eq(*i)) == plugins.end())
421  && (__meta_plugins.find(*i) != __meta_plugins.end()) ) {
422  continue;
423  }
424 
425  __meta_plugins.erase_locked(*i);
426  LibLogger::log_info("PluginManager", "UNloading plugin %s for meta plugin %s",
427  i->c_str(), plugin_name);
428  unload(i->c_str());
429  }
430  }
431 }
432 
433 
434 void
436 {
437 }
438 
439 void
441 {
442  if (v->is_string()) {
443  __pinfo_cache.lock();
444  std::string p = std::string(v->path()).substr(__meta_plugin_prefix.length());
445  std::string s = std::string("Meta: ") + v->get_string();
446  std::list<std::pair<std::string, std::string> >::iterator i;
447  bool found = false;
448  for (i = __pinfo_cache.begin(); i != __pinfo_cache.end(); ++i) {
449  if (p == i->first) {
450  i->second = s;
451  found = true;
452  break;
453  }
454  }
455  if (! found) {
456  __pinfo_cache.push_back(make_pair(p, s));
457  }
458  __pinfo_cache.unlock();
459  }
460 }
461 
462 void
464 {
465 }
466 
467 void
469 {
470  __pinfo_cache.lock();
471  std::string p = std::string(path).substr(__meta_plugin_prefix.length());
472  std::list<std::pair<std::string, std::string> >::iterator i;
473  for (i = __pinfo_cache.begin(); i != __pinfo_cache.end(); ++i) {
474  if (p == i->first) {
475  __pinfo_cache.erase(i);
476  break;
477  }
478  }
479  __pinfo_cache.unlock();
480 }
481 
482 
483 void
484 PluginManager::fam_event(const char *filename, unsigned int mask)
485 {
486  const char *file_ext = "."SOEXT;
487 
488  const char *pos = strstr(filename, file_ext);
489  std::string p = std::string(filename).substr(0, strlen(filename) - strlen(file_ext));
490  if (NULL != pos) {
491  __pinfo_cache.lock();
492  bool found = false;
493  std::list<std::pair<std::string, std::string> >::iterator i;
494  for (i = __pinfo_cache.begin(); i != __pinfo_cache.end(); ++i) {
495  if (p == i->first) {
496  found = true;
497  if ((mask & FAM_DELETE) || (mask & FAM_MOVED_FROM)) {
498  __pinfo_cache.erase(i);
499  } else {
500  try {
501  i->second = plugin_loader->get_description(p.c_str());
502  } catch (Exception &e) {
503  LibLogger::log_warn("PluginManager", "Could not get possibly modified "
504  "description of plugin %s, exception follows",
505  p.c_str());
506  LibLogger::log_warn("PluginManager", e);
507  }
508  }
509  break;
510  }
511  }
512  if (! found &&
513  !(mask & FAM_ISDIR) &&
514  ((mask & FAM_MODIFY) || (mask & FAM_MOVED_TO) || (mask & FAM_CREATE))) {
515  if (plugin_loader->is_loaded(p.c_str())) {
516  LibLogger::log_info("PluginManager", "Plugin %s changed on disk, but is "
517  "loaded, no new info can be loaded, keeping old.",
518  p.c_str());
519  }
520  try {
521  std::string s = plugin_loader->get_description(p.c_str());
522  __pinfo_cache.push_back(make_pair(p, s));
523  } catch (Exception &e) {
524  LibLogger::log_warn("PluginManager", "Could not get possibly modified "
525  "description of plugin %s, exception follows",
526  p.c_str());
527  LibLogger::log_warn("PluginManager", e);
528  }
529  }
530 
531  __pinfo_cache.sort();
532  __pinfo_cache.unlock();
533  }
534 }
535 
536 
537 /** Add listener.
538  * Listeners are notified of plugin load and unloda events.
539  * @param listener listener to add
540  */
541 void
543 {
544  __listeners.lock();
545  __listeners.push_back(listener);
546  __listeners.sort();
547  __listeners.unique();
548  __listeners.unlock();
549 }
550 
551 /** Remove listener.
552  * @param listener listener to remove
553  */
554 void
556 {
557  __listeners.remove_locked(listener);
558 }
559 
560 void
561 PluginManager::notify_loaded(const char *plugin_name)
562 {
563  __listeners.lock();
564  for (__lit = __listeners.begin(); __lit != __listeners.end(); ++__lit) {
565  try {
566  (*__lit)->plugin_loaded(plugin_name);
567  } catch (Exception &e) {
568  LibLogger::log_warn("PluginManager", "PluginManagerListener threw exception "
569  "during notification of plugin loaded, exception follows.");
570  LibLogger::log_warn("PluginManager", e);
571  }
572  }
573  __listeners.unlock();
574 }
575 
576 void
577 PluginManager::notify_unloaded(const char *plugin_name)
578 {
579  __listeners.lock();
580  for (__lit = __listeners.begin(); __lit != __listeners.end(); ++__lit) {
581  try {
582  (*__lit)->plugin_unloaded(plugin_name);
583  } catch (Exception &e) {
584  LibLogger::log_warn("PluginManager", "PluginManagerListener threw exception "
585  "during notification of plugin unloaded, exception follows.");
586  LibLogger::log_warn("PluginManager", e);
587  }
588  }
589  __listeners.unlock();
590 }
591 
592 
593 /** Lock plugin manager.
594  * This is an utility method that you can use for mutual access to the plugin
595  * manager. The mutex is not used internally, but meant to be used from
596  * callers.
597  */
598 void
600 {
601  __mutex->lock();
602 }
603 
604 
605 /** Try to lock plugin manager.
606  * This is an utility method that you can use for mutual access to the plugin
607  * manager. The mutex is not used internally, but meant to be used from
608  * callers.
609  * @return true if the lock was acquired, false otherwise
610  */
611 bool
613 {
614  return __mutex->try_lock();
615 }
616 
617 /** Unlock plugin manager. */
618 void
620 {
621  __mutex->unlock();
622 }
623 
624 } // end namespace fawkes
void set_open_flags(Module::ModuleFlags open_flags)
Set flags to open modules with.
static void log_info(const char *component, const char *format,...)
Log informational message.
Definition: liblogger.cpp:142
~PluginManager()
Destructor.
Definition: manager.cpp:124
Plugin interface class.
Definition: plugin.h:33
void set_module_flags(Module::ModuleFlags flags)
Set flags to open modules with.
Definition: manager.cpp:151
void erase_locked(const KeyType &key)
Remove item with lock.
Definition: lock_map.h:132
virtual void fam_event(const char *filename, unsigned int mask)
Event has been raised.
Definition: manager.cpp:484
virtual void remove(ThreadList &tl)=0
Remove multiple threads.
void unlock() const
Unlock list.
Definition: lock_map.h:120
std::list< std::pair< std::string, std::string > > get_available_plugins()
Generate list of all available plugins.
Definition: manager.cpp:213
void init_pinfo_cache()
Initialize plugin info cache.
Definition: manager.cpp:159
Fawkes library namespace.
void unlock()
Unlock the mutex.
Definition: mutex.cpp:135
bool try_lock()
Try to lock plugin manager.
Definition: manager.cpp:612
virtual void unlock() const
Unlock list.
Definition: lock_list.h:144
Mutex locking helper.
Definition: mutex_locker.h:33
Interface for configuration change handling.
virtual void config_comment_changed(const Configuration::ValueIterator *v)
Called whenever a comment of a watched value has changed.
Definition: manager.cpp:463
virtual std::string get_string() const =0
Get string value.
virtual bool is_string() const =0
Check if current value is a string.
Thrown if a config entry could not be found.
Definition: config.h:44
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
static const unsigned int FAM_CREATE
Subfile was created.
Definition: fam.h:50
Thread collector.
virtual bool next()=0
Check if there is another element and advance to this if possible.
virtual void lock() const
Lock list.
Definition: lock_list.h:128
virtual const char * path() const =0
Path of value.
ThreadList & threads()
Get a list of threads.
Definition: plugin.cpp:110
RefPtr< Mutex > mutex() const
Get access to the internal mutex.
Definition: lock_map.h:146
static const unsigned int FAM_ISDIR
Event occurred against dir.
Definition: fam.h:62
This class manages plugins.
Definition: loader.h:61
ModuleFlags
Flags for the loading process.
Definition: module.h:44
Map with a lock.
Definition: lock_map.h:37
void lock()
Lock plugin manager.
Definition: manager.cpp:599
PluginManager listener.
Definition: listener.h:32
void add_listener(PluginManagerListener *listener)
Add listener.
Definition: manager.cpp:542
static void log_error(const char *component, const char *format,...)
Log error message.
Definition: liblogger.cpp:178
void unload(Plugin *plugin)
Unload the given plugin This will unload the given plugin.
Definition: loader.cpp:269
Thread cannot be initialized.
ModuleManager * get_module_manager() const
Get module manager.
Definition: loader.cpp:141
virtual void config_tag_changed(const char *new_location)
Called whenever the tag has changed.
Definition: manager.cpp:435
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void force_remove(fawkes::ThreadList &tl)=0
Force removal of multiple threads.
void lock() const
Lock list.
Definition: lock_map.h:100
void load(const char *plugin_list)
Load plugin.
Definition: manager.cpp:297
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
Definition: config.cpp:496
void prepend(const char *format,...)
Prepend messages to the message list.
Definition: exception.cpp:322
void remove_listener(PluginManagerListener *listener)
Remove listener.
Definition: manager.cpp:555
std::list< std::string > get_loaded_plugins()
Get list of loaded plugins.
Definition: manager.cpp:229
std::string get_description(const char *plugin_name)
Get plugin description.
Definition: loader.cpp:230
void unload(const char *plugin_name)
Unload plugin.
Definition: manager.cpp:375
static const unsigned int FAM_MOVED_FROM
File was moved from X.
Definition: fam.h:47
virtual void add(ThreadList &tl)=0
Add multiple threads.
static const unsigned int FAM_MOVED_TO
File was moved to Y.
Definition: fam.h:48
static void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: liblogger.cpp:160
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:120
virtual void config_value_changed(const Configuration::ValueIterator *v)
Called whenever a watched value has changed.
Definition: manager.cpp:440
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:49
virtual void config_value_erased(const char *path)
Called whenever a value has been erased from the config.
Definition: manager.cpp:468
bool is_loaded(const char *plugin_name)
Check if plugin is loaded.
Definition: manager.cpp:253
Iterator interface to iterate over config values.
Definition: config.h:68
FileAlterationMonitor thread wrapper.
Definition: fam_thread.h:35
void lock()
Lock this mutex.
Definition: mutex.cpp:89
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
Definition: config.cpp:479
static const unsigned int FAM_DELETE
Subfile was deleted.
Definition: fam.h:51
static const unsigned int FAM_MODIFY
File was modified.
Definition: fam.h:41
void unlock()
Unlock plugin manager.
Definition: manager.cpp:619
bool is_loaded(const char *plugin_name)
Check if a plugin is loaded.
Definition: loader.cpp:251
Mutex mutual exclusion lock.
Definition: mutex.h:32
Interface for configuration handling.
Definition: config.h:63
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
Plugin * load(const char *plugin_name)
Load a specific plugin The plugin loader is clever and guarantees that every plugin is only loaded on...
Definition: loader.cpp:201