/usr/include/arc/loader/Plugin.h is in nordugrid-arc-dev 5.0.5-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | #ifndef __ARC_PLUGIN_H__
#define __ARC_PLUGIN_H__
#include <string>
#include <map>
#include <typeinfo>
#include <inttypes.h>
#include <sys/types.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <arc/Thread.h>
#include <arc/Logger.h>
#include <arc/XMLNode.h>
#include <arc/loader/ModuleManager.h>
namespace Arc {
#define ARC_PLUGIN_DEFAULT_PRIORITY (128)
class PluginsFactory;
/// Base class for passing arguments to loadable ARC components.
/** During its creation constructor function of ARC loadable component
expects instance of class inherited from this one or wrapped in it.
Then dynamic type casting is used for obtaining class of expected kind. */
class PluginArgument {
friend class PluginsFactory;
private:
PluginsFactory* factory_;
Glib::Module* module_;
void set_factory(PluginsFactory* factory);
void set_module(Glib::Module* module);
protected:
PluginArgument(void);
public:
virtual ~PluginArgument(void);
/// Returns pointer to factory which instantiated plugin.
/** Because factory usually destroys/unloads plugins in its
destructor it should be safe to keep this pointer inside
plugin for later use. But one must always check. */
PluginsFactory* get_factory(void);
/// Returns pointer to loadable module/library which contains plugin.
/** Corresponding factory keeps list of modules till itself is destroyed.
So it should be safe to keep that pointer. But care must be taken
if module contains persistent plugins. Such modules stay in memory
after factory is detroyed. So it is advisable to use obtained
pointer only in constructor function of plugin. */
Glib::Module* get_module(void);
};
/// Base class for loadable ARC components.
/** All classes representing loadable ARC components must be either
descendants of this class or be wrapped by its offspring. */
class Plugin {
private:
Plugin(void);
Plugin& operator=(const Plugin&) { return *this; };
protected:
PluginsFactory* factory_;
Glib::Module* module_;
/// Main constructor for creating new plugin object
Plugin(PluginArgument* arg);
/// Constructor to be used if plugin want to copy itself
Plugin(const Plugin& obj);
public:
virtual ~Plugin(void);
};
/// Name of symbol refering to table of plugins.
/** This C null terminated string specifies name of symbol which
shared library should export to give an access to an array
of PluginDescriptor elements. The array is terminated by
element with all components set to NULL. */
extern const char* plugins_table_name;
#define ARC_PLUGINS_TABLE_NAME __arc_plugins_table__
#define ARC_PLUGINS_TABLE_SYMB "__arc_plugins_table__"
/// Constructor function of ARC lodable component
/** This function is called with plugin-specific argument and
should produce and return valid instance of plugin.
If plugin can't be produced by any reason (for example
because passed argument is not applicable) then NULL
is returned. No exceptions should be raised. */
typedef Plugin* (*get_plugin_instance)(PluginArgument* arg);
/// Description of ARC lodable component
typedef struct {
const char* name; // Unique name of plugin in scope of its kind
const char* kind; // Type/kind of plugin
const char* description; // Short description of plugin
uint32_t version; // Version of plugin (0 if not applicable)
get_plugin_instance instance; // Pointer to constructor function
} PluginDescriptor;
/// Description of plugin
/** This class is used for reports */
class PluginDesc {
public:
std::string name;
std::string kind;
std::string description;
uint32_t version;
uint32_t priority;
PluginDesc(void):version(0),priority(ARC_PLUGIN_DEFAULT_PRIORITY) { };
};
/// Description of loadable module
/** This class is used for reports */
class ModuleDesc {
public:
std::string name;
std::list<PluginDesc> plugins;
};
/// Generic ARC plugins loader
/** The instance of this class provides functionality
of loading pluggable ARC components stored in shared
libraries. It also makes use of Arc Plugin Description
(*.apd) files which contain textual plugin identfiers.
Arc Plugin Description files contain attributes
describing pluggable components stored in corresponding
shared libraries. Using those files allows to save
on actually loading and resolving libraries while
looking for specific component.
Specifically this class uses 'priority' attribute to sort
plugin description in internal lists. Please note
that priority affects order in which plugins tried
in get_instance(...) methods. But it only works
for plugins which were already loaded by previous
calls to load(...) and get_instance(...) methods.
For plugins discovered inside get_instance priority
in not effective.
This class mostly handles tasks of finding, identifying,
fitering and sorting ARC pluggable components. For loading
shared libraries it uses functionality of ModuleManager class.
So it is important to see documentation of ModuleManager in
order to understand how this class works.
For more information also please check ARC HED documentation.
This class is thread-safe - its methods are protected from
simultatneous use from multiple threads. Current thread
protection implementation is suboptimal and will be revised
in future.
*/
class PluginsFactory: public ModuleManager {
friend class PluginArgument;
private:
Glib::Mutex lock_;
// Combined convenient description of module and
// its representation inside module.
class descriptor_t_ {
public:
PluginDesc desc_i;
PluginDescriptor* desc_m;
};
class module_t_ {
public:
// Handle of loaded module
Glib::Module* module;
// List of contained plugins. First one is also
// pointer to plugins table.
std::list<descriptor_t_> plugins;
PluginDescriptor* get_table(void) { return plugins.empty()?NULL:(plugins.front().desc_m); };
};
//typedef std::map<std::string,module_t_> modules_t_;
// Container for all loaded modules and their plugins
class modules_t_: public std::map<std::string,module_t_> {
public:
// convenience iterator for modules
class miterator: public std::map<std::string,module_t_>::iterator {
private:
std::map<std::string,module_t_>* ref_;
public:
miterator(std::map<std::string,module_t_>& ref, std::map<std::string,module_t_>::iterator iter):std::map<std::string,module_t_>::iterator(iter),ref_(&ref) { };
operator bool(void) const { return (std::map<std::string,module_t_>::iterator&)(*this) != ref_->end(); };
bool operator!(void) const { return !((bool)(*this)); };
}; // class miterator
// iterator for accessing plugins by priority
class diterator: public std::list< std::pair<descriptor_t_*,module_t_*> >::iterator {
private:
std::list< std::pair<descriptor_t_*,module_t_*> >* ref_;
public:
diterator(std::list< std::pair<descriptor_t_*,module_t_*> >& ref, std::list< std::pair<descriptor_t_*,module_t_*> >::iterator iter):std::list< std::pair<descriptor_t_*,module_t_*> >::iterator(iter),ref_(&ref) { };
operator bool(void) const { return (std::list< std::pair<descriptor_t_*,module_t_*> >::iterator&)(*this) != ref_->end(); };
bool operator!(void) const { return !((bool)(*this)); };
}; // class diterator
operator miterator(void) { return miterator(*this,this->begin()); };
miterator find(const std::string& name) { return miterator(*this,((std::map<std::string,module_t_>*)this)->find(name)); };
operator diterator(void) { return diterator(plugins_,plugins_.begin()); };
bool add(ModuleDesc* m_i, Glib::Module* m_h, PluginDescriptor* d_h);
bool remove(miterator& module);
private:
// Plugins sorted by priority
std::list< std::pair<descriptor_t_*,module_t_*> > plugins_;
// TODO: potentially other sortings like by kind can be useful.
};
modules_t_ modules_;
bool try_load_;
static Logger logger;
bool load(const std::string& name,const std::list<std::string>& kinds,const std::list<std::string>& pnames);
public:
/** Constructor - accepts configuration (not yet used) meant to
tune loading of modules. */
PluginsFactory(XMLNode cfg);
/** Specifies if loadable module may be loaded while looking
for analyzing its content. If set to false only *.apd
files are checked. Modules without corresponding *.apd
will be ignored. Default is true; */
void TryLoad(bool v) { try_load_ = v; };
bool TryLoad(void) { return try_load_; };
/** These methods load module named lib'name', locate plugin
constructor functions of specified 'kind' and 'name' (if specified)
and call it. Supplied argument affects way plugin instance is created
in plugin-specific way.
If name of plugin is not specified then all plugins of specified kind
are tried with supplied argument till valid instance is created.
All loaded plugins are also registered in internal list of this
instance of PluginsFactory class.
If search is set to false then no attempt is made to find plugins in
loadable modules. Only plugins already loaded with previous calls to
get_instance() and load() are checked.
Returns created instance or NULL if failed. */
Plugin* get_instance(const std::string& kind,PluginArgument* arg,bool search = true);
Plugin* get_instance(const std::string& kind,int version,PluginArgument* arg,bool search = true);
Plugin* get_instance(const std::string& kind,int min_version,int max_version,PluginArgument* arg,bool search = true);
Plugin* get_instance(const std::string& kind,const std::string& name,PluginArgument* arg,bool search = true);
Plugin* get_instance(const std::string& kind,const std::string& name,int version,PluginArgument* arg,bool search = true);
Plugin* get_instance(const std::string& kind,const std::string& name,int min_version,int max_version,PluginArgument* arg,bool search = true);
/** These methods load module named lib'name' and check if it
contains ARC plugin(s) of specified 'kind' and 'name'. If there are no
specified plugins or module does not contain any ARC plugins it is
unloaded.
All loaded plugins are also registered in internal list of this
instance of PluginsFactory class.
Returns true if any plugin was loaded. */
bool load(const std::string& name);
bool load(const std::string& name,const std::string& kind);
bool load(const std::string& name,const std::string& kind,const std::string& pname);
bool load(const std::string& name,const std::list<std::string>& kinds);
bool load(const std::list<std::string>& names,const std::string& kind);
bool load(const std::list<std::string>& names,const std::string& kind,const std::string& pname);
bool load(const std::list<std::string>& names,const std::list<std::string>& kinds);
/** Collect information about plugins stored in module(s)
with specified names.
Returns true if any of specified modules has plugins. */
bool scan(const std::string& name, ModuleDesc& desc);
bool scan(const std::list<std::string>& names, std::list<ModuleDesc>& descs);
/** Provides information about currently loaded modules and plugins. */
void report(std::list<ModuleDesc>& descs);
/** Filter list of modules by kind. */
static void FilterByKind(const std::string& kind, std::list<ModuleDesc>& descs);
template<class P>
P* GetInstance(const std::string& kind,PluginArgument* arg,bool search = true) {
Plugin* plugin = get_instance(kind,arg,search);
if(!plugin) return NULL;
P* p = dynamic_cast<P*>(plugin);
if(!p) delete plugin;
return p;
}
template<class P>
P* GetInstance(const std::string& kind,const std::string& name,PluginArgument* arg,bool search = true) {
Plugin* plugin = get_instance(kind,name,arg,search);
if(!plugin) return NULL;
P* p = dynamic_cast<P*>(plugin);
if(!p) delete plugin;
return p;
}
};
template<class P>
P* PluginCast(PluginArgument* p) {
if(p == NULL) return NULL;
P* pp = dynamic_cast<P*>(p);
if(pp != NULL) return pp;
// Workaround for g++ and loadable modules
if(strcmp(typeid(P).name(),typeid(*p).name()) != 0) return NULL;
return static_cast<P*>(p);
}
template<class P>
P* PluginCast(Plugin* p) {
if(p == NULL) return NULL;
P* pp = dynamic_cast<P*>(p);
if(pp != NULL) return pp;
// Workaround for g++ and loadable modules
if(strcmp(typeid(P).name(),typeid(*p).name()) != 0) return NULL;
return static_cast<P*>(p);
}
} // namespace Arc
#endif /* __ARC_PLUGIN_H__ */
|