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/Utils.hh"
00004 #include "Rivet/Tools/osdir.hh"
00005 #include "Rivet/Tools/Logging.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   Analysis* AnalysisLoader::getAnalysis(const string& analysisname) {
00041     _loadAnalysisPlugins();
00042     AnalysisBuilderMap::const_iterator ai = _ptrs.find(analysisname);
00043     if (ai == _ptrs.end()) return 0;
00044     return ai->second->mkAnalysis();
00045   }
00046 
00047 
00048   vector<Analysis*> AnalysisLoader::getAllAnalyses() {
00049     _loadAnalysisPlugins();
00050     vector<Analysis*> analyses;
00051     foreach (const AnalysisBuilderMap::value_type& p, _ptrs) {
00052       analyses += 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 
00071 
00072   void AnalysisLoader::_loadAnalysisPlugins() {
00073     // Only run once
00074     if (!_ptrs.empty()) return;
00075 
00076     // Build the list of directories to search
00077     const vector<string> dirs = getAnalysisLibPaths();
00078 
00079     // Find plugin module library files
00080     const string libsuffix = ".so";
00081     vector<string> pluginfiles;
00082     foreach (const string& d, dirs) {
00083       if (d.empty()) continue;
00084       oslink::directory dir(d);
00085       while (dir) {
00086         string filename = dir.next();
00087         // Require that plugin lib name starts with 'Rivet'
00088         if (filename.find("Rivet") != 0) continue;
00089         size_t posn = filename.find(libsuffix);
00090         if (posn == string::npos || posn != filename.length()-libsuffix.length()) continue;
00091         /// @todo Make sure this is an abs path
00092         /// @todo Sys-dependent path separator instead of "/"
00093         const string path = d + "/" + filename;
00094         // Ensure no duplicate paths
00095         if (find(pluginfiles.begin(), pluginfiles.end(), path) == pluginfiles.end()) {
00096           pluginfiles += path;
00097         }
00098       }
00099     }
00100 
00101     // Load the plugin files
00102     MSG_TRACE("Candidate analysis plugin libs: " << pluginfiles);
00103     foreach (const string& pf, pluginfiles) {
00104       MSG_TRACE("Trying to load plugin analyses from file " << pf);
00105       void* handle = dlopen(pf.c_str(), RTLD_LAZY);
00106       if (!handle) {
00107         MSG_WARNING("Cannot open " << pf << ": " << dlerror());
00108         continue;
00109       }
00110     }
00111   }
00112 
00113 
00114 }