14#define GAUDI_PLUGIN_SERVICE_V1
32 std::mutex registrySingletonMutex;
41 constexpr struct is_space_t {
42 bool operator()(
int i )
const {
return std::isspace( i ); }
46 static inline std::string& ltrim( std::string& s ) {
47 s.erase(
s.begin(), std::find_if_not(
s.begin(),
s.end(), is_space ) );
52 static inline std::string& rtrim( std::string& s ) {
53 s.erase( std::find_if_not(
s.rbegin(),
s.rend(), is_space ).base(),
s.end() );
57 static inline std::string& trim( std::string& s ) {
return ltrim( rtrim( s ) ); }
64 inline void factoryInfoSetHelper( std::string& dest,
const std::string& value,
const std::string& desc,
65 const std::string&
id ) {
68 }
else if ( dest != value ) {
69 Gaudi::PluginService::Details::logger().warning(
"new factory loaded for '" +
id +
"' with different " + desc +
70 ": " + dest +
" != " + value );
76 void operator()(
const char c ) {
85 name.push_back(
'_' );
88 name.push_back(
'r' );
91 name.push_back(
'p' );
102 std::string old_style_name(
const std::string& name ) {
103 return std::for_each(
name.begin(),
name.end(), OldStyleCnv() ).name;
115 void*
getCreator(
const std::string&
id,
const std::string& type ) {
121 auto realname = std::unique_ptr<char, decltype( free )*>(
122 abi::__cxa_demangle(
id.c_str(),
nullptr,
nullptr, &status ), free );
123 if ( !realname )
return id;
124 return std::regex_replace(
126 std::regex{
"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >( (?=>))?" },
132 auto _guard = std::scoped_lock{ ::registrySingletonMutex };
140 auto _guard = std::scoped_lock{
m_mutex };
145 logger().
debug( std::string(
" looking into " ) + dirName );
147 DIR* dir = opendir( dirName.c_str() );
149 struct dirent* entry;
150 while ( ( entry = readdir( dir ) ) ) {
151 std::string name( entry->d_name );
153 std::string::size_type extpos = name.find(
".components" );
154 if ( ( extpos != std::string::npos ) && ( ( extpos + 11 ) == name.size() ) ) {
155 std::string fullPath = ( dirName +
'/' + name );
158 stat( fullPath.c_str(), &buf );
159 if ( !S_ISREG( buf.st_mode ) )
continue;
162 logger().
debug( std::string(
" reading " ) + name );
165 int factoriesCount = 0;
172 if ( line.empty() || line[0] ==
'#' )
continue;
174 if ( line.substr( 0, 4 ) ==
"v1::" )
175 line = line.substr( 4 );
179 auto pos = line.find(
':' );
180 if ( pos == std::string::npos ) {
181 logger().
warning(
"failed to parse line " + fullPath +
':' + std::to_string( lineCount ) );
184 const std::string lib( line, 0, pos );
185 const std::string fact( line, pos + 1 );
187#ifdef GAUDI_REFLEX_COMPONENT_ALIASES
189 std::string old_name = old_style_name( fact );
190 if ( fact != old_name ) {
199 logger().
debug(
" found " + std::to_string( factoriesCount ) +
" factories" );
209 const std::string& rtype,
const std::string& className,
211 auto _guard = std::scoped_lock{
m_mutex };
213 auto entry = facts.find(
id );
214 if ( entry == facts.end() ) {
216 entry = facts.emplace(
id,
FactoryInfo(
"unknown", factory, type, rtype, className, props ) ).first;
219 if ( !entry->second.ptr ) entry->second.ptr = factory;
220 factoryInfoSetHelper( entry->second.type, type,
"type",
id );
221 factoryInfoSetHelper( entry->second.rtype, rtype,
"return type",
id );
222 factoryInfoSetHelper( entry->second.className, className,
"class",
id );
224#ifdef GAUDI_REFLEX_COMPONENT_ALIASES
226 std::string old_name = old_style_name(
id );
227 if (
id != old_name )
228 add( old_name, factory, type, rtype, className, props ).
properties[
"ReflexName"] =
"true";
230 return entry->second;
233 void*
Registry::get(
const std::string&
id,
const std::string& type )
const {
234 auto _guard = std::scoped_lock{
m_mutex };
236 auto f = facts.find(
id );
237 if ( f != facts.end() ) {
238#ifdef GAUDI_REFLEX_COMPONENT_ALIASES
239 const Properties& props = f->second.properties;
240 if ( props.find(
"ReflexName" ) != props.end() )
244 f->second.className +
"' instead" );
246 if ( !f->second.ptr ) {
247 if ( !dlopen( f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL ) ) {
248 logger().
warning(
"cannot load " + f->second.library +
" for factory " +
id );
249 char* dlmsg = dlerror();
253 f = facts.find(
id );
255 if ( f->second.type == type )
return f->second.ptr;
257 " instead of " +
demangle( type ) );
263 auto _guard = std::scoped_lock{
m_mutex };
266 auto f = facts.find(
id );
267 return ( f != facts.end() ) ? f->second : unknown;
271 auto _guard = std::scoped_lock{
m_mutex };
273 auto f = facts.find(
id );
274 if ( f != facts.end() ) f->second.properties[k] = v;
279 auto _guard = std::scoped_lock{
m_mutex };
282 if ( f.second.ptr ) l.insert( f.first );
288 static const char* levels[] = {
"DEBUG : ",
"INFO : ",
"WARNING: ",
"ERROR : " };
289 if ( lvl >=
level() ) { std::cerr << levels[lvl] << msg << std::endl; }
292 static auto s_logger = std::make_unique<Logger>();
300 Logger& l = logger();
301 if ( debugLevel > 1 )
302 l.setLevel( Logger::Debug );
303 else if ( debugLevel > 0 )
304 l.setLevel( Logger::Info );
306 l.setLevel( Logger::Warning );
311 switch ( logger().level() ) {
#define GAUDI_PLUGIN_SERVICE_V1_INLINE
Simple logging class, just to provide a default implementation.
void debug(const std::string &msg)
void warning(const std::string &msg)
virtual void report(Level lvl, const std::string &msg)
const FactoryInfo & getInfo(const std::string &id) const
Retrieve the FactoryInfo object for an id.
bool m_initialized
Flag recording if the registry has been initialized or not.
void * get(const std::string &id, const std::string &type) const
Retrieve the factory for the given id.
static Registry & instance()
Retrieve the singleton instance of Registry.
std::set< KeyType > loadedFactoryNames() const
Return a list of all the known and loaded factories.
std::map< KeyType, FactoryInfo > FactoryMap
Type used for the database implementation.
std::recursive_mutex m_mutex
Mutex used to control concurrent access to the internal data.
FactoryInfo & add(const I &id, typename F::FuncType ptr)
Add a factory to the database.
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.).
void initialize()
Initialize the registry loading the list of factories from the .component files in the library search...
Registry()
Private constructor for the singleton pattern.
const FactoryMap & factories() const
Return the known factories (loading the list if not yet done).
FactoryMap m_factories
Internal storage for factories.
const char * what() const override
Exception(std::string msg)
GAUDIPS_API void setLogger(Logger *logger)
Set the logger instance to use.
GAUDIPS_API Logger & logger()
Return the current logger instance.
std::string demangle()
Return a canonical name for the template argument.
GAUDIPS_API std::string demangle(const std::type_info &id)
Return a canonical name for type_info object (implementation borrowed from GaudiKernel/System).
GAUDIPS_API void * getCreator(const std::string &id, const std::string &type)
Function used to load a specific factory function.
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
GAUDIPS_API int Debug()
Backward compatibility with Reflex.
const std::vector< std::string > & getPluginSearchPath()
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...