DD4hep  1.28.0
Detector Description Toolkit for High Energy Physics
Plugins.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Plugins.h>
16 #include <cstdlib>
17 
18 using namespace dd4hep;
19 
20 namespace {
21  inline int* s_debug_value() {
22  static int s_debug_value = ::getenv("DD4HEP_TRACE") == 0 ? 0 : 1;
23  return &s_debug_value;
24  }
25 }
26 
28  return *s_debug_value() ? true : false;
29 }
30 
31 bool PluginService::setDebug(bool new_value) {
32  int *ptr = s_debug_value();
33  bool old_value = *ptr;
34  *ptr = new_value ? 1 : 0;
35  return old_value;
36 }
37 
38 #if defined(__linux) && !defined(__APPLE__)
39 #define DD4HEP_PARSERS_NO_ROOT
40 #endif
41 
42 #include "DD4hep/Printout.h"
43 #if !defined(DD4HEP_PARSERS_NO_ROOT)
44 #include "TSystem.h"
45 #else
46 #include <dlfcn.h>
47 #endif
48 #include <cstring>
49 
50 
51 #define MAKE_GAUDI_PLUGIN_SERVICE_ENTRY(n,v) "dd4hep_pluginmgr_" #n "_V" #v
52 #define MAKE_FUNC(name,version) MAKE_GAUDI_PLUGIN_SERVICE_ENTRY(name,version)
53 
54 namespace {
55  struct PluginInterface {
56  int (*getDebug)();
57  int (*setDebug)(int new_value);
58  PluginService::stub_t (*create)(const char* identifier, const char* signature);
59  void (*add)(const char* identifier,
60  PluginService::stub_t&& creator_stub,
61  const char* signature,
62  const char* return_type);
63  PluginInterface() noexcept(false);
64  static PluginInterface& instance() noexcept(false) {
65  static PluginInterface s_instance;
66  return s_instance;
67  }
68  };
69 
70  template <typename FUNCTION> struct _FP {
71  union { void* ptr; FUNCTION fcn; } fptr;
72  _FP(FUNCTION func) { fptr.fcn = func; }
73  _FP(void* _p) { fptr.ptr = _p; }
74  };
75 
76  template <typename T>
77  static inline T get_func(void* handle, const char* plugin, const char* entry) {
78 #if !defined(DD4HEP_PARSERS_NO_ROOT)
79  _FP<Func_t> fun(gSystem->DynFindSymbol(plugin,entry));
80  _FP<T> fp(fun.fptr.ptr);
81  if ( handle ) {}
82 #else
83  _FP<T> fp(::dlsym(handle, entry));
84  if ( !fp.fptr.ptr ) fp.fptr.ptr = ::dlsym(0, entry);
85 #endif
86  if ( 0 == fp.fptr.ptr ) {
87  std::string err = "dd4hep:PluginService: Failed to access symbol "
88  "\""+std::string(entry)+"\" in plugin library "+std::string(plugin)+
89  " ["+std::string(::strerror(errno))+"]";
90  throw std::runtime_error(err);
91  }
92  return fp.fptr.fcn;
93  }
94 
95  PluginInterface::PluginInterface() noexcept(false)
96  : getDebug(0), setDebug(0), create(nullptr), add(nullptr)
97  {
98  void* handle = 0;
99  const char* plugin_name = ::getenv("DD4HEP_PLUGINMGR");
100 #if defined(__linux) && !defined(__APPLE__)
101  if ( 0 == plugin_name ) plugin_name = "libDD4hepGaudiPluginMgr.so";
102 #else
103  if ( 0 == plugin_name ) plugin_name = "libDD4hepGaudiPluginMgr";
104 #endif
105 #if defined(DD4HEP_PARSERS_NO_ROOT)
106  struct handle_guard {
107  void* _handle {nullptr};
108  handle_guard(void* hdl) : _handle(hdl) {
109  }
110  ~handle_guard() {
111  if ( _handle ) ::dlclose(_handle);
112  _handle = nullptr;
113  }
114  };
115  static handle_guard _guard(nullptr);
116  if ( nullptr == _guard._handle ) {
117  _guard._handle = handle = ::dlopen(plugin_name, RTLD_LAZY | RTLD_GLOBAL);
118  }
119  if ( !handle ) {
120  throw std::runtime_error("Failed to load plugin manager library: "+std::string(plugin_name));
121  }
122 #else
123  if ( 0 != gSystem->Load(plugin_name) ) {}
124 #endif
125  getDebug = get_func< int (*) ()>(handle, plugin_name,MAKE_FUNC(getdebug,DD4HEP_PLUGINSVC_VERSION));
126  setDebug = get_func< int (*) (int)>(handle, plugin_name,MAKE_FUNC(setdebug,DD4HEP_PLUGINSVC_VERSION));
127  create = get_func< PluginService::stub_t (*)(const char*,
128  const char*)>(handle, plugin_name,MAKE_FUNC(create,DD4HEP_PLUGINSVC_VERSION));
129  add = get_func< void (*) (const char* identifier,
130  PluginService::stub_t&& creator_stub,
131  const char* signature,
132  const char* return_type)>(handle, plugin_name,MAKE_FUNC(add_factory,DD4HEP_PLUGINSVC_VERSION));
133  }
134 }
135 
137 PluginDebug::PluginDebug(int dbg) noexcept(false) : m_debug(0) {
138  m_debug = PluginInterface::instance().setDebug(dbg);
139 }
140 
142 PluginDebug::~PluginDebug() noexcept(false) {
143  PluginInterface::instance().setDebug(m_debug);
144 }
145 
147 std::string PluginDebug::missingFactory(const std::string& name) const {
148  std::string factoryname = "Create("+name+")";
149  std::string msg = "\t\tNo factory with name " + factoryname + " for type " + name + " found.\n"
150  "\t\tPlease check library load path and/or plugin factory name.";
151  return msg;
152 }
153 
154 PluginService::stub_t PluginService::getCreator(const std::string& id, const std::type_info& info) {
155  return PluginInterface::instance().create(id.c_str(), info.name());
156 }
157 
158 void PluginService::addFactory(const std::string& id,
159  PluginService::stub_t&& stub,
160  const std::type_info& signature_type,
161  const std::type_info& return_type)
162 {
163  if ( PluginService::debug() ) {
164  printout(INFO,"PluginService","+++ Declared factory[%s] with signature %s type:%s.",
165  id.c_str(),signature_type.name(),return_type.name());
166  }
167  PluginInterface::instance().add(id.c_str(),std::move(stub),signature_type.name(),return_type.name());
168 }
169 
170 void PluginService::print_bad_cast(const std::string& id,
171  const stub_t& stub,
172  const std::type_info& signature,
173  const char* msg) {
174  bool dbg = PluginInterface::instance().getDebug();
175  if ( dbg ) {
176  std::stringstream str;
177  str << "Factory requested: " << id << " (" << typeid(signature).name() << ") :" << msg;
178  printout(ERROR,"PluginService","%s", str.str().c_str());
179  str.str("");
180  if ( !any_has_value(stub) ) {
181  str << "Stub is invalid!";
182  printout(ERROR,"PluginService","%s", str.str().c_str());
183  }
184  }
185 }
dd4hep::PluginService::addFactory
static void addFactory(const std::string &id, stub_t &&func, const std::type_info &signature_type, const std::type_info &return_type)
Definition: Plugins.cpp:158
std::any_has_value
bool any_has_value(std::any a)
Definition: Plugins.h:34
MAKE_FUNC
#define MAKE_FUNC(name, version)
Definition: Plugins.cpp:52
dd4hep::PluginService::stub_t
std::any stub_t
Definition: Plugins.h:88
dd4hep::info
std::size_t info(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:65
dd4hep::PluginDebug::PluginDebug
PluginDebug(int dbg=2) noexcept(false)
Default constructor.
Definition: Plugins.cpp:137
dd4hep::PluginService::getCreator
static stub_t getCreator(const std::string &id, const std::type_info &info)
Definition: Plugins.cpp:154
DD4HEP_PLUGINSVC_VERSION
#define DD4HEP_PLUGINSVC_VERSION
Valid implementations of the Gaudi plugin service are 1 and 2.
Definition: config.h:35
Plugins.h
dd4hep::PluginDebug::~PluginDebug
~PluginDebug() noexcept(false)
Default destructor.
Definition: Plugins.cpp:142
dd4hep::PluginDebug::missingFactory
std::string missingFactory(const std::string &name) const
Helper to check factory existence.
Definition: Plugins.cpp:147
dd4hep::PluginService::setDebug
static bool setDebug(bool new_value)
Definition: Plugins.cpp:31
dd4hep::PluginService::debug
static bool debug()
Definition: Plugins.cpp:27
dd4hep::PluginService::print_bad_cast
static void print_bad_cast(const std::string &id, const stub_t &stub, const std::type_info &signature, const char *msg)
Definition: Plugins.cpp:170
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
_p
#define _p(x)
Definition: IoStreams.cpp:94
dd4hep::PluginDebug::m_debug
int m_debug
Definition: Plugins.h:75
Printout.h
handle
void handle(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1105