rivet is hosted by Hepforge, IPPP Durham
AnalysisLoader.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/AnalysisLoader.hh"
00003 #include "Rivet/Tools/RivetPaths.hh"
00004 #include "Rivet/Tools/Utils.hh"
00005 #include "Rivet/Tools/osdir.hh"
00006 #include "Rivet/Analysis.hh"
00007 #include <dlfcn.h>
00008 
00009 namespace Rivet {
00010 
00011 
00012   namespace {
00013     inline Log& getLog() {
00014       return Log::getLog("Rivet.AnalysisLoader");
00015     }
00016   }
00017 
00018   // Initialise static ptr collection
00019   AnalysisLoader::AnalysisBuilderMap AnalysisLoader::_ptrs;
00020 
00021 
00022   vector<string> AnalysisLoader::analysisNames() {
00023     _loadAnalysisPlugins();
00024     vector<string> names;
00025     foreach (const AnalysisBuilderMap::value_type& p, _ptrs) names += p.first;
00026     return names;
00027   }
00028 
00029 
00030   set<string> AnalysisLoader::getAllAnalysisNames() {
00031     set<string> anaset;
00032     vector<string> anas = analysisNames();
00033     foreach (const string &ana, anas) {
00034       anaset.insert(ana);
00035     }
00036     return anaset;
00037   }
00038 
00039 
00040   unique_ptr<Analysis> AnalysisLoader::getAnalysis(const string& analysisname) {
00041     _loadAnalysisPlugins();
00042     AnalysisBuilderMap::const_iterator ai = _ptrs.find(analysisname);
00043     if (ai == _ptrs.end()) return nullptr;
00044     return ai->second->mkAnalysis();
00045   }
00046 
00047 
00048   vector<unique_ptr<Analysis>> AnalysisLoader::getAllAnalyses() {
00049     _loadAnalysisPlugins();
00050     vector<unique_ptr<Analysis>> analyses;
00051     foreach (const auto & p, _ptrs) {
00052       analyses.emplace_back( p.second->mkAnalysis() );
00053     }
00054     return analyses;
00055   }
00056 
00057 
00058   void AnalysisLoader::_registerBuilder(const AnalysisBuilderBase* ab) {
00059     if (!ab) return;
00060     const string name = ab->name();
00061     if (_ptrs.find(name) != _ptrs.end()) {
00062       // Duplicate analyses will be ignored... loudly
00063       //cerr << "Ignoring duplicate plugin analysis called '" << name << "'" << endl;
00064       MSG_WARNING("Ignoring duplicate plugin analysis called '" << name << "'");
00065     } else {
00066       MSG_TRACE("Registering a plugin analysis called '" << name << "'");
00067       _ptrs[name] = ab;
00068     }
00069 
00070     const string aname = ab->alias();
00071     if (!aname.empty()) {
00072       //MSG_WARNING("ALIAS!!! " << aname);
00073       if (_ptrs.find(aname) != _ptrs.end()) {
00074         MSG_WARNING("Ignoring duplicate plugin analysis alias '" << aname << "'");
00075       } else {
00076         MSG_TRACE("Registering a plugin analysis via alias '" << aname << "'");
00077         _ptrs[aname] = ab;
00078       }
00079     }
00080   }
00081 
00082 
00083   void AnalysisLoader::_loadAnalysisPlugins() {
00084     // Only run once
00085     if (!_ptrs.empty()) return;
00086 
00087     // Build the list of directories to search
00088     const vector<string> dirs = getAnalysisLibPaths();
00089 
00090     // Find plugin module library files
00091     const string libsuffix = ".so";
00092     vector<string> pluginfiles;
00093     foreach (const string& d, dirs) {
00094       if (d.empty()) continue;
00095       oslink::directory dir(d);
00096       while (dir) {
00097         string filename = dir.next();
00098         // Require that plugin lib name starts with 'Rivet'
00099         if (filename.find("Rivet") != 0) continue;
00100         size_t posn = filename.find(libsuffix);
00101         if (posn == string::npos || posn != filename.length()-libsuffix.length()) continue;
00102         /// @todo Make sure this is an abs path
00103         /// @todo Sys-dependent path separator instead of "/"
00104         const string path = d + "/" + filename;
00105         // Ensure no duplicate paths
00106         if (find(pluginfiles.begin(), pluginfiles.end(), path) == pluginfiles.end()) {
00107           pluginfiles += path;
00108         }
00109       }
00110     }
00111 
00112     // Load the plugin files
00113     MSG_TRACE("Candidate analysis plugin libs: " << pluginfiles);
00114     foreach (const string& pf, pluginfiles) {
00115       MSG_TRACE("Trying to load plugin analyses from file " << pf);
00116       void* handle = dlopen(pf.c_str(), RTLD_LAZY);
00117       if (!handle) {
00118         MSG_WARNING("Cannot open " << pf << ": " << dlerror());
00119         continue;
00120       }
00121     }
00122   }
00123 
00124 
00125 }