14 #include <Gaudi/PluginService.h>
27 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
28 #define REG_SCOPE_LOCK \
29 std::lock_guard<std::recursive_mutex> _guard(m_mutex);
32 std::mutex registrySingletonMutex;
34 #define SINGLETON_LOCK \
35 std::lock_guard<std::mutex> _guard(::registrySingletonMutex);
37 #define REG_SCOPE_LOCK
38 #define SINGLETON_LOCK
42 #include "boost/algorithm/string/trim.hpp"
49 inline void factoryInfoSetHelper(std::string&
dest,
const std::string
value,
50 const std::string& desc,
51 const std::string&
id) {
54 }
else if (dest != value) {
56 "new factory loaded for '" +
id +
"' with different "
57 + desc +
": " + dest +
" != " + value );
63 void operator() (
const char c) {
72 name.push_back(
'_');
break;
74 name.push_back(
'r');
break;
76 name.push_back(
'p');
break;
79 name.push_back(c);
break;
84 std::string old_style_name(
const std::string&
name) {
85 return std::for_each(name.begin(), name.end(), OldStyleCnv()).name;
89 namespace Gaudi {
namespace PluginService {
104 auto realname = std::unique_ptr<char,decltype(free)*>( abi::__cxa_demangle(
id.c_str(), 0, 0, &status),
106 if (!realname)
return id;
107 return std::string{realname.get()};
126 const char* envVar =
"PATH";
127 const char sep =
';';
129 const char* envVar =
"LD_LIBRARY_PATH";
130 const char sep =
':';
132 char *search_path = ::getenv(envVar);
134 logger().
debug(std::string(
"searching factories in ") + envVar);
135 std::string
path(search_path);
136 std::string::size_type pos = 0;
137 std::string::size_type newpos = 0;
138 while (pos != std::string::npos) {
141 newpos = path.find(sep, pos);
142 if (newpos != std::string::npos) {
143 dirName = path.substr(pos, newpos - pos);
146 dirName = path.substr(pos);
149 logger().
debug(std::string(
" looking into ") + dirName);
151 DIR *dir = opendir(dirName.c_str());
153 struct dirent * entry;
154 while ((entry = readdir(dir))) {
155 std::string
name(entry->d_name);
157 std::string::size_type extpos = name.find(
".components");
158 if ((extpos != std::string::npos) &&
159 ((extpos+11) == name.size())) {
160 std::string fullPath = (dirName +
'/' +
name);
163 stat(fullPath.c_str(), &buf);
164 if (!S_ISREG(buf.st_mode))
continue;
170 int factoriesCount = 0;
175 boost::algorithm::trim(line);
177 if (line.empty() || line[0] ==
'#')
continue;
179 auto pos = line.find(
':');
180 if (pos == std::string::npos) {
183 + std::to_string(lineCount) );
186 const std::string lib(line, 0, pos);
187 const std::string fact(line, pos+1);
189 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
191 std::string old_name = old_style_name(fact);
192 if (fact != old_name) {
201 logger().
debug(
" found " + std::to_string( factoriesCount )
214 const std::string&
type,
const std::string& rtype,
215 const std::string& className,
219 auto entry = facts.find(
id);
220 if (entry == facts.end())
223 entry = facts.emplace(
id,
FactoryInfo(
"unknown", factory,
224 type, rtype, className, props) ).first;
227 if (!entry->second.ptr) entry->second.ptr = factory;
228 factoryInfoSetHelper(entry->second.type, type,
"type",
id);
229 factoryInfoSetHelper(entry->second.rtype, rtype,
"return type",
id);
230 factoryInfoSetHelper(entry->second.className, className,
"class",
id);
232 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
234 std::string old_name = old_style_name(
id);
236 add(old_name, factory, type, rtype, className, props)
239 return entry->second;
245 auto f = facts.find(
id);
246 if (f != facts.end())
248 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
249 const Properties& props = f->second.properties;
250 if (props.find(
"ReflexName") != props.end())
251 logger().
warning(
"requesting factory via old name '" +
id +
"'"
252 "use '" + f->second.className +
"' instead");
254 if (!f->second.ptr) {
255 if (!dlopen(f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL)) {
257 " for factory " +
id);
258 char *dlmsg = dlerror();
264 if (f->second.type == type)
return f->second.ptr;
265 logger().
warning(
"found factory " +
id +
", but of wrong type: " +
275 auto f = facts.find(
id);
276 return (f != facts.end()) ? f->second : unknown;
281 const std::string& k,
282 const std::string& v) {
285 auto f = facts.find(
id);
286 if (f != facts.end()) f->second.properties[k] = v;
294 for (
const auto& f : facts )
296 if (f.second.ptr) l.insert(f.first);
302 static const char* levels[] = {
"DEBUG : ",
306 if (lvl >=
level()) {
307 std::cerr << levels[lvl] << msg << std::endl;
311 static std::unique_ptr<Logger> s_logger(
new Logger);
318 using namespace Details;
322 else if (debugLevel > 0)
328 using namespace Details;
const FactoryInfo & getInfo(const std::string &id) const
Retrieve the FactoryInfo object for an id.
Registry & addProperty(const std::string &id, const std::string &k, const std::string &v)
Add a property to an already existing FactoryInfo object (via its id.)
Registry()
Private constructor for the singleton pattern.
void initialize()
Initialize the registry loading the list of factories from the .component files in the library search...
GAUDIPS_API Logger & logger()
Return the current logger instance.
GAUDIPS_API void * getCreator(const std::string &id, const std::string &type)
Function used to load a specific factory function.
std::set< KeyType > loadedFactories() const
Return a list of all the known and loaded factories.
std::map< KeyType, std::string > Properties
Type used for the properties implementation.
Simple logging class, just to provide a default implementation.
GAUDIPS_API int Debug()
Backward compatibility with Reflex.
void * get(const std::string &id, const std::string &type) const
Retrieve the factory for the given id.
const FactoryMap & factories() const
Return the known factories (loading the list if not yet done).
GAUDIPS_API std::string demangle(const std::type_info &id)
Return a canonical name for type_info object (implementation borrowed from GaudiKernel/System).
virtual void report(Level lvl, const std::string &msg)
void warning(const std::string &msg)
Exception(std::string msg)
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
GAUDIPS_API void setLogger(Logger *logger)
Set the logger instance to use.
static Registry & instance()
Retrieve the singleton instance of Registry.
In-memory database of the loaded factories.
FactoryInfo & add(const I &id, typename F::FuncType ptr)
Add a factory to the database.
virtual const char * what() const
std::map< KeyType, FactoryInfo > FactoryMap
Type used for the database implementation.
FactoryMap m_factories
Internal storage for factories.
Helper functions to set/get the application return code.
bool m_initialized
Flag recording if the registry has been initialized or not.
void debug(const std::string &msg)