CMS 3D CMS Logo

List of all members | Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | Friends
edmplugin::PluginManager Class Reference

#include <PluginManager.h>

Classes

class  Config
 

Public Types

typedef std::map< std::string, InfosCategoryToInfos
 
typedef std::vector< PluginInfoInfos
 
typedef std::vector< std::string > SearchPath
 

Public Member Functions

const CategoryToInfoscategoryToInfos () const
 
const SharedLibraryload (const std::string &iCategory, const std::string &iPlugin)
 
const std::filesystem::path & loadableFor (const std::string &iCategory, const std::string &iPlugin)
 
const PluginManageroperator= (const PluginManager &)=delete
 
 PluginManager (const PluginManager &)=delete
 
const SharedLibrarytryToLoad (const std::string &iCategory, const std::string &iPlugin)
 
 ~PluginManager ()
 

Static Public Member Functions

static PluginManagerconfigure (const Config &)
 
static PluginManagerget ()
 
static bool isAvailable ()
 
static const std::string & loadingFile ()
 file name of the shared object being loaded More...
 
static const std::string & staticallyLinkedLoadingFileName ()
 if the value returned from loadingFile matches this string then the file is statically linked More...
 

Public Attributes

edm::signalslot::Signal< void(const std::string &, const std::string &)> askedToLoadCategoryWithPlugin_
 
edm::signalslot::Signal< void(const std::filesystem::path &)> goingToLoad_
 
edm::signalslot::Signal< void(const SharedLibrary &)> justLoaded_
 

Private Member Functions

const std::filesystem::path & loadableFor_ (const std::string &iCategory, const std::string &iPlugin, bool &ioThrowIfFailElseSucceedStatus)
 
void newFactory (const PluginFactoryBase *)
 
std::recursive_mutex & pluginLoadMutex ()
 
 PluginManager (const Config &)
 

Static Private Member Functions

static std::string & loadingLibraryNamed_ ()
 
static PluginManager *& singleton ()
 

Private Attributes

CategoryToInfos categoryToInfos_
 
oneapi::tbb::concurrent_unordered_map< std::filesystem::path, std::shared_ptr< SharedLibrary >, PluginManagerPathHasherloadables_
 
std::recursive_mutex pluginLoadMutex_
 
SearchPath searchPath_
 

Friends

class DummyFriend
 

Detailed Description

Definition at line 45 of file PluginManager.h.

Member Typedef Documentation

◆ CategoryToInfos

typedef std::map<std::string, Infos> edmplugin::PluginManager::CategoryToInfos

Definition at line 51 of file PluginManager.h.

◆ Infos

Definition at line 50 of file PluginManager.h.

◆ SearchPath

typedef std::vector<std::string> edmplugin::PluginManager::SearchPath

Definition at line 49 of file PluginManager.h.

Constructor & Destructor Documentation

◆ PluginManager() [1/2]

edmplugin::PluginManager::PluginManager ( const PluginManager )
delete

Referenced by configure().

◆ ~PluginManager()

PluginManager::~PluginManager ( )

Definition at line 126 of file PluginManager.cc.

126 {}

◆ PluginManager() [2/2]

PluginManager::PluginManager ( const Config iConfig)
private

Definition at line 58 of file PluginManager.cc.

References edmplugin::PluginFactoryManager::begin(), edmplugin::standard::cachefileName(), categoryToInfos_, DeadROC_duringRun::dir, MillePedeFileConverter_cfg::e, edmplugin::PluginFactoryManager::end(), Exception, edmplugin::PluginFactoryManager::get(), mps_fire::i, loadingLibraryNamed_(), edmplugin::PluginManager::Config::mustHaveCache(), newFactory(), edmplugin::PluginFactoryManager::newFactory_, EnsembleCalibrationLA_cfg::path, edmplugin::standard::poisonedCachefileName(), edmplugin::readCacheFile(), and searchPath_.

58  : searchPath_(iConfig.searchPath()) {
59  using std::placeholders::_1;
61  // This is the filename of a file which contains plugins which exist in the
62  // base release and which should exists in the local area, otherwise they
63  // were removed and we want to catch their usage.
64  const std::filesystem::path& kPoisonedCacheFile(standard::poisonedCachefileName());
65  //NOTE: This may not be needed :/
67  pfm->newFactory_.connect(std::bind(std::mem_fn(&PluginManager::newFactory), this, _1));
68 
69  // When building a single big executable the plugins are already registered in the
70  // PluginFactoryManager, we therefore only need to populate the categoryToInfos_ map
71  // with the relevant information.
72  for (PluginFactoryManager::const_iterator i = pfm->begin(), e = pfm->end(); i != e; ++i) {
73  categoryToInfos_[(*i)->category()] = (*i)->available();
74  }
75 
76  //read in the files
77  //Since we are looping in the 'precidence' order then the lists in categoryToInfos_ will also be
78  // in that order
79  bool foundAtLeastOneCacheFile = false;
80  std::set<std::string> alreadySeen;
81  for (SearchPath::const_iterator itPath = searchPath_.begin(), itEnd = searchPath_.end(); itPath != itEnd;
82  ++itPath) {
83  //take care of the case where the same path is passed in multiple times
84  if (alreadySeen.find(*itPath) != alreadySeen.end()) {
85  continue;
86  }
87  alreadySeen.insert(*itPath);
88  std::filesystem::path dir(*itPath);
89  if (exists(dir)) {
90  if (not is_directory(dir)) {
91  throw cms::Exception("PluginManagerBadPath")
92  << "The path '" << dir.string() << "' for the PluginManager is not a directory";
93  }
94  std::filesystem::path cacheFile = dir / kCacheFile;
95 
96  if (readCacheFile(cacheFile, dir, categoryToInfos_)) {
97  foundAtLeastOneCacheFile = true;
98  }
99 
100  // We do not check for return code since we do not want to consider a
101  // poison cache file as a valid cache file having been found.
102  std::filesystem::path poisonedCacheFile = dir / kPoisonedCacheFile;
103  readCacheFile(poisonedCacheFile, dir / "poisoned", categoryToInfos_);
104  }
105  }
106  if (not foundAtLeastOneCacheFile and iConfig.mustHaveCache()) {
107  auto ex = cms::Exception("PluginManagerNoCacheFile")
108  << "No cache files named '" << standard::cachefileName() << "' were found in the directories \n";
109  for (auto const& seen : alreadySeen) {
110  ex << " '" << seen << "'\n";
111  }
112  throw ex;
113  }
114  if (iConfig.mustHaveCache() and categoryToInfos_.empty()) {
115  throw cms::Exception("PluginManagerCacheFilesEmpty") << "Cache files were found but all were empty.";
116  }
117  //Since this should not be called until after 'main' has started, we can set the value
118  loadingLibraryNamed_() = "<loaded by another plugin system>";
119  }
CategoryToInfos categoryToInfos_
const std::filesystem::path & poisonedCachefileName()
Definition: standard.cc:52
const std::filesystem::path & cachefileName()
Definition: standard.cc:47
static bool readCacheFile(const std::filesystem::path &cacheFile, const std::filesystem::path &dir, PluginManager::CategoryToInfos &categoryToInfos)
static std::string & loadingLibraryNamed_()
std::vector< const PluginFactoryBase * >::const_iterator const_iterator
void newFactory(const PluginFactoryBase *)
static PluginFactoryManager * get()

Member Function Documentation

◆ categoryToInfos()

const CategoryToInfos& edmplugin::PluginManager::categoryToInfos ( ) const
inline

The container is ordered by category, then plugin name and then by precidence order of the plugin files. Therefore the first match on category and plugin name will be the proper file to load

Definition at line 82 of file PluginManager.h.

References categoryToInfos_.

Referenced by PrintLoadingPlugins::askedToLoad(), FWDetailViewManager::findViewersFor(), FWEveViewManager::FWEveViewManager(), FWItemAccessorFactory::hasAccessor(), main(), and sim::sensitiveDetectorMakers().

82 { return categoryToInfos_; }
CategoryToInfos categoryToInfos_

◆ configure()

PluginManager & PluginManager::configure ( const Config iConfig)
static

Definition at line 318 of file PluginManager.cc.

References Exception, PluginManager(), alignCSCRings::s, edmplugin::PluginManager::Config::searchPath(), and singleton().

Referenced by FWLiteEnabler::enable(), edm::storage::StorageFactory::getMaker(), main(), edm::ProblemTracker::ProblemTracker(), cond::Utilities::run(), and edm::PluginDescription< T >::writeCfi_().

318  {
319  PluginManager*& s = singleton();
320  if (nullptr != s) {
321  throw cms::Exception("PluginManagerReconfigured");
322  }
323 
324  const Config& realConfig = iConfig;
325  if (realConfig.searchPath().empty()) {
326  throw cms::Exception("PluginManagerEmptySearchPath");
327  }
328  s = new PluginManager(realConfig);
329  return *s;
330  }
static PluginManager *& singleton()
PluginManager(const PluginManager &)=delete
Definition: Config.py:1

◆ get()

PluginManager * PluginManager::get ( )
static

Definition at line 309 of file PluginManager.cc.

References Exception, and singleton().

Referenced by Options.Options::__getitem__(), betterConfigParser.BetterConfigParser::__updateDict(), submitPVValidationJobs.BetterConfigParser::__updateDict(), PrintLoadingPlugins::askedToLoad(), edmplugin::PluginFactoryBase::checkProperLoadable(), rrapi.RRApi::columns(), rrapi.RRApi::count(), rrapi.RRApi::data(), edmplugin::PluginFactoryBase::findPMaker(), FWDetailViewManager::findViewersFor(), FWEveViewManager::FWEveViewManager(), betterConfigParser.BetterConfigParser::getCompares(), betterConfigParser.BetterConfigParser::getGeneral(), betterConfigParser.BetterConfigParser::getResultingSection(), submitPVValidationJobs.BetterConfigParser::getResultingSection(), FWItemAccessorFactory::hasAccessor(), edmplugin::PluginCapabilities::load(), edm::service::LoadAllDictionaries::LoadAllDictionaries(), main(), PrintLoadingPlugins::PrintLoadingPlugins(), edm::PluginDescription< T >::printNestedContent_(), rrapi.RRApi::report(), rrapi.RRApi::reports(), sim::sensitiveDetectorMakers(), rrapi.RRApi::tables(), rrapi.RRApi::tags(), rrapi.RRApi::templates(), edmplugin::PluginFactoryBase::tryToFindPMaker(), edmplugin::PluginCapabilities::tryToLoad(), and rrapi.RRApi::workspaces().

309  {
310  PluginManager* manager = singleton();
311  if (nullptr == manager) {
312  throw cms::Exception("PluginManagerNotConfigured")
313  << "PluginManager::get() was called before PluginManager::configure.";
314  }
315  return manager;
316  }
static PluginManager *& singleton()

◆ isAvailable()

bool PluginManager::isAvailable ( )
static

◆ load()

const SharedLibrary & PluginManager::load ( const std::string &  iCategory,
const std::string &  iPlugin 
)

Definition at line 229 of file PluginManager.cc.

References askedToLoadCategoryWithPlugin_, MillePedeFileConverter_cfg::e, goingToLoad_, justLoaded_, loadableFor(), loadables_, loadingLibraryNamed_(), AlCaHLTBitMon_ParallelJobs::p, EnsembleCalibrationLA_cfg::path, pluginLoadMutex(), and alignCSCRings::s.

Referenced by edmplugin::PluginFactoryBase::findPMaker(), and edmplugin::PluginCapabilities::load().

229  {
230  askedToLoadCategoryWithPlugin_(iCategory, iPlugin);
231  const std::filesystem::path& p = loadableFor(iCategory, iPlugin);
232 
233  //have we already loaded this?
234  auto itLoaded = loadables_.find(p);
235  if (itLoaded == loadables_.end()) {
236  //Need to make sure we only have on SharedLibrary loading at a time
237  std::lock_guard<std::recursive_mutex> guard(pluginLoadMutex());
238  //Another thread may have gotten this while we were waiting on the mutex
239  itLoaded = loadables_.find(p);
240  if (itLoaded == loadables_.end()) {
241  //try to make one
242  goingToLoad_(p);
243  Sentry s(loadingLibraryNamed_(), p.string());
244  //std::filesystem::path native(p.string());
245  std::shared_ptr<SharedLibrary> ptr;
246  {
247  //TEMPORARY: to avoid possible deadlocks from ROOT, we must
248  // take the lock ourselves
249  R__LOCKGUARD2(gInterpreterMutex);
250  try {
251  ptr = std::make_shared<SharedLibrary>(p);
252  } catch (cms::Exception& e) {
253  e.addContext("While attempting to load plugin " + iPlugin);
254  throw;
255  }
256  }
257  loadables_.emplace(p, ptr);
258  justLoaded_(*ptr);
259  return *ptr;
260  }
261  }
262  return *(itLoaded->second);
263  }
edm::signalslot::Signal< void(const std::filesystem::path &)> goingToLoad_
oneapi::tbb::concurrent_unordered_map< std::filesystem::path, std::shared_ptr< SharedLibrary >, PluginManagerPathHasher > loadables_
edm::signalslot::Signal< void(const std::string &, const std::string &)> askedToLoadCategoryWithPlugin_
edm::signalslot::Signal< void(const SharedLibrary &)> justLoaded_
std::recursive_mutex & pluginLoadMutex()
const std::filesystem::path & loadableFor(const std::string &iCategory, const std::string &iPlugin)
static std::string & loadingLibraryNamed_()

◆ loadableFor()

const std::filesystem::path & PluginManager::loadableFor ( const std::string &  iCategory,
const std::string &  iPlugin 
)

Definition at line 153 of file PluginManager.cc.

References loadableFor_().

Referenced by edmplugin::PluginFactoryBase::checkProperLoadable(), and load().

153  {
154  bool throwIfFail = true;
155  return loadableFor_(iCategory, iPlugin, throwIfFail);
156  }
const std::filesystem::path & loadableFor_(const std::string &iCategory, const std::string &iPlugin, bool &ioThrowIfFailElseSucceedStatus)

◆ loadableFor_()

const std::filesystem::path & PluginManager::loadableFor_ ( const std::string &  iCategory,
const std::string &  iPlugin,
bool &  ioThrowIfFailElseSucceedStatus 
)
private

Definition at line 158 of file PluginManager.cc.

References categoryToInfos_, Exception, mps_fire::i, EnsembleCalibrationLA_cfg::path, and isotrackApplyRegressor::range.

Referenced by loadableFor(), and tryToLoad().

160  {
161  const bool throwIfFail = ioThrowIfFailElseSucceedStatus;
162  ioThrowIfFailElseSucceedStatus = true;
163  CategoryToInfos::iterator itFound = categoryToInfos_.find(iCategory);
164  if (itFound == categoryToInfos_.end()) {
165  if (throwIfFail) {
166  throw cms::Exception("PluginNotFound") << "Unable to find plugin '" << iPlugin << "' because the category '"
167  << iCategory << "' has no known plugins";
168  } else {
169  ioThrowIfFailElseSucceedStatus = false;
170  static const std::filesystem::path s_path;
171  return s_path;
172  }
173  }
174 
175  PluginInfo i;
176  i.name_ = iPlugin;
177  typedef std::vector<PluginInfo>::iterator PIItr;
178  std::pair<PIItr, PIItr> range = std::equal_range(itFound->second.begin(), itFound->second.end(), i, PICompare());
179 
180  if (range.first == range.second) {
181  if (throwIfFail) {
182  throw cms::Exception("PluginNotFound") << "Unable to find plugin '" << iPlugin << "' in category '" << iCategory
183  << "'. Please check spelling of name.";
184  } else {
185  ioThrowIfFailElseSucceedStatus = false;
186  static const std::filesystem::path s_path;
187  return s_path;
188  }
189  }
190 
191  if (range.second - range.first > 1) {
192  //see if the come from the same directory
193  if (range.first->loadable_.parent_path() == (range.first + 1)->loadable_.parent_path()) {
194  //std::cout<<range.first->name_ <<" " <<(range.first+1)->name_<<std::endl;
195  throw cms::Exception("MultiplePlugins")
196  << "The plugin '" << iPlugin
197  << "' is found in multiple files \n"
198  " '"
199  << range.first->loadable_.filename() << "'\n '" << (range.first + 1)->loadable_.filename()
200  << "'\n"
201  "in directory '"
202  << range.first->loadable_.parent_path().string()
203  << "'.\n"
204  "The code must be changed so the plugin only appears in one plugin file. "
205  "You will need to remove the macro which registers the plugin so it only appears in"
206  " one of these files.\n"
207  " If none of these files register such a plugin, "
208  "then the problem originates in a library to which all these files link.\n"
209  "The plugin registration must be removed from that library since plugins are not allowed in regular "
210  "libraries.";
211  }
212  }
213 
214  return range.first->loadable_;
215  }
CategoryToInfos categoryToInfos_

◆ loadingFile()

static const std::string& edmplugin::PluginManager::loadingFile ( )
inlinestatic

file name of the shared object being loaded

Definition at line 89 of file PluginManager.h.

References loadingLibraryNamed_().

Referenced by edmplugin::PluginFactoryBase::newPlugin(), and edmplugin::PluginFactoryBase::registerPMaker().

89 { return loadingLibraryNamed_(); }
static std::string & loadingLibraryNamed_()

◆ loadingLibraryNamed_()

std::string & PluginManager::loadingLibraryNamed_ ( )
staticprivate

Definition at line 337 of file PluginManager.cc.

References CMS_THREAD_SAFE, staticallyLinkedLoadingFileName(), and AlCaHLTBitMon_QueryRunRegistry::string.

Referenced by load(), loadingFile(), PluginManager(), and tryToLoad().

337  {
338  //NOTE: pluginLoadMutex() indirectly guards this since this value
339  // is only accessible via the Sentry call which us guarded by the mutex
341  return s_name;
342  }
static const std::string & staticallyLinkedLoadingFileName()
if the value returned from loadingFile matches this string then the file is statically linked ...
#define CMS_THREAD_SAFE

◆ newFactory()

void PluginManager::newFactory ( const PluginFactoryBase )
private

Definition at line 143 of file PluginManager.cc.

Referenced by PluginManager().

143 {}

◆ operator=()

const PluginManager& edmplugin::PluginManager::operator= ( const PluginManager )
delete

◆ pluginLoadMutex()

std::recursive_mutex& edmplugin::PluginManager::pluginLoadMutex ( )
inlineprivate

Definition at line 111 of file PluginManager.h.

References pluginLoadMutex_.

Referenced by load(), and tryToLoad().

111 { return pluginLoadMutex_; }
std::recursive_mutex pluginLoadMutex_

◆ singleton()

PluginManager *& PluginManager::singleton ( )
staticprivate

Definition at line 344 of file PluginManager.cc.

References CMS_THREAD_SAFE.

Referenced by configure(), get(), and isAvailable().

344  {
345  CMS_THREAD_SAFE static PluginManager* s_singleton = nullptr;
346  return s_singleton;
347  }
#define CMS_THREAD_SAFE

◆ staticallyLinkedLoadingFileName()

const std::string & PluginManager::staticallyLinkedLoadingFileName ( )
static

if the value returned from loadingFile matches this string then the file is statically linked

Definition at line 332 of file PluginManager.cc.

References AlCaHLTBitMon_QueryRunRegistry::string.

Referenced by edmplugin::PluginFactoryBase::checkProperLoadable(), and loadingLibraryNamed_().

332  {
333  static const std::string s_name("static");
334  return s_name;
335  }

◆ tryToLoad()

const SharedLibrary * PluginManager::tryToLoad ( const std::string &  iCategory,
const std::string &  iPlugin 
)

Definition at line 265 of file PluginManager.cc.

References askedToLoadCategoryWithPlugin_, MillePedeFileConverter_cfg::e, goingToLoad_, justLoaded_, loadableFor_(), loadables_, loadingLibraryNamed_(), AlCaHLTBitMon_ParallelJobs::p, EnsembleCalibrationLA_cfg::path, pluginLoadMutex(), and alignCSCRings::s.

Referenced by edmplugin::PluginFactoryBase::tryToFindPMaker(), and edmplugin::PluginCapabilities::tryToLoad().

265  {
266  askedToLoadCategoryWithPlugin_(iCategory, iPlugin);
267  bool ioThrowIfFailElseSucceedStatus = false;
268  const std::filesystem::path& p = loadableFor_(iCategory, iPlugin, ioThrowIfFailElseSucceedStatus);
269 
270  if (not ioThrowIfFailElseSucceedStatus) {
271  return nullptr;
272  }
273 
274  //have we already loaded this?
275  auto itLoaded = loadables_.find(p);
276  if (itLoaded == loadables_.end()) {
277  //Need to make sure we only have on SharedLibrary loading at a time
278  std::lock_guard<std::recursive_mutex> guard(pluginLoadMutex());
279  //Another thread may have gotten this while we were waiting on the mutex
280  itLoaded = loadables_.find(p);
281  if (itLoaded == loadables_.end()) {
282  //try to make one
283  goingToLoad_(p);
284  Sentry s(loadingLibraryNamed_(), p.string());
285  //std::filesystem::path native(p.string());
286  std::shared_ptr<SharedLibrary> ptr;
287  {
288  //TEMPORARY: to avoid possible deadlocks from ROOT, we must
289  // take the lock ourselves
290  R__LOCKGUARD(gInterpreterMutex);
291  try {
292  ptr = std::make_shared<SharedLibrary>(p);
293  } catch (cms::Exception& e) {
294  e.addContext("While attempting to load plugin " + iPlugin);
295  throw;
296  }
297  }
298  loadables_[p] = ptr;
299  justLoaded_(*ptr);
300  return ptr.get();
301  }
302  }
303  return (itLoaded->second).get();
304  }
edm::signalslot::Signal< void(const std::filesystem::path &)> goingToLoad_
oneapi::tbb::concurrent_unordered_map< std::filesystem::path, std::shared_ptr< SharedLibrary >, PluginManagerPathHasher > loadables_
const std::filesystem::path & loadableFor_(const std::string &iCategory, const std::string &iPlugin, bool &ioThrowIfFailElseSucceedStatus)
edm::signalslot::Signal< void(const std::string &, const std::string &)> askedToLoadCategoryWithPlugin_
edm::signalslot::Signal< void(const SharedLibrary &)> justLoaded_
std::recursive_mutex & pluginLoadMutex()
static std::string & loadingLibraryNamed_()

Friends And Related Function Documentation

◆ DummyFriend

friend class DummyFriend
friend

Definition at line 46 of file PluginManager.h.

Member Data Documentation

◆ askedToLoadCategoryWithPlugin_

edm::signalslot::Signal<void(const std::string&, const std::string&)> edmplugin::PluginManager::askedToLoadCategoryWithPlugin_

Definition at line 102 of file PluginManager.h.

Referenced by load(), PrintLoadingPlugins::PrintLoadingPlugins(), and tryToLoad().

◆ categoryToInfos_

CategoryToInfos edmplugin::PluginManager::categoryToInfos_
private

Definition at line 121 of file PluginManager.h.

Referenced by categoryToInfos(), loadableFor_(), and PluginManager().

◆ goingToLoad_

edm::signalslot::Signal<void(const std::filesystem::path&)> edmplugin::PluginManager::goingToLoad_

Definition at line 100 of file PluginManager.h.

Referenced by load(), PrintLoadingPlugins::PrintLoadingPlugins(), and tryToLoad().

◆ justLoaded_

edm::signalslot::Signal<void(const SharedLibrary&)> edmplugin::PluginManager::justLoaded_

Definition at line 101 of file PluginManager.h.

Referenced by load(), and tryToLoad().

◆ loadables_

oneapi::tbb::concurrent_unordered_map<std::filesystem::path, std::shared_ptr<SharedLibrary>, PluginManagerPathHasher> edmplugin::PluginManager::loadables_
private

Definition at line 119 of file PluginManager.h.

Referenced by load(), and tryToLoad().

◆ pluginLoadMutex_

std::recursive_mutex edmplugin::PluginManager::pluginLoadMutex_
private

Definition at line 122 of file PluginManager.h.

Referenced by pluginLoadMutex().

◆ searchPath_

SearchPath edmplugin::PluginManager::searchPath_
private

Definition at line 117 of file PluginManager.h.

Referenced by PluginManager().