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   // Initialise static ptr collection
00013   AnalysisLoader::AnalysisBuilderMap AnalysisLoader::_ptrs;
00014 
00015 
00016   vector<string> AnalysisLoader::analysisNames() {
00017     _loadAnalysisPlugins();
00018     vector<string> names;
00019     foreach (const AnalysisBuilderMap::value_type& p, _ptrs) names += p.first;
00020     return names;
00021   }
00022   
00023   
00024   set<string> AnalysisLoader::getAllAnalysisNames() {
00025     set<string> anaset;
00026     vector<string> anas = analysisNames();
00027     foreach (const string &ana, anas) {
00028       anaset.insert(ana);
00029     }
00030     return anaset;
00031   }
00032 
00033 
00034   Analysis* AnalysisLoader::getAnalysis(const string& analysisname) {
00035     _loadAnalysisPlugins();
00036     AnalysisBuilderMap::const_iterator ai = _ptrs.find(analysisname);
00037     if (ai == _ptrs.end()) return 0;
00038     return ai->second->mkAnalysis();
00039   }
00040 
00041 
00042   vector<Analysis*> AnalysisLoader::getAllAnalyses() {
00043     _loadAnalysisPlugins();
00044     vector<Analysis*> analyses;
00045     foreach (const AnalysisBuilderMap::value_type& p, _ptrs) {
00046       analyses += p.second->mkAnalysis();
00047     }
00048     return analyses;
00049   }
00050 
00051 
00052   void AnalysisLoader::_registerBuilder(const AnalysisBuilderBase* ab) {
00053     if (!ab) return;
00054     const string name = ab->name();
00055     if (_ptrs.find(name) != _ptrs.end()) {
00056       // Protect against overwriting analyses by throwing an error
00057       /// @todo Tidy this up!
00058       Log::getLog("Rivet.AnalysisLoader") << Log::ERROR << "Tried to register a second plugin analysis called '" << name << "'" << endl;
00059       exit(1);
00060     }
00061     Log::getLog("Rivet.AnalysisLoader") << Log::TRACE << "Registering a plugin analysis called '" << name << "'" << endl;
00062     _ptrs[name] = ab;
00063   }
00064 
00065 
00066   void AnalysisLoader::_loadAnalysisPlugins() {
00067     // Only run once
00068     if (!_ptrs.empty()) return;
00069 
00070     // Build the list of directories to search
00071     vector<string> dirs;
00072     char* env = 0;
00073     env = getenv("RIVET_ANALYSIS_PATH");
00074     if (env) {
00075       // Use the Rivet analysis path variable if set...
00076       dirs += split(env);
00077     } else {
00078       // ... otherwise fall back to the Rivet library install path
00079       dirs += getLibPath();
00080     }
00081 
00082     // Find plugin module library files
00083     const string libsuffix = ".so";
00084     vector<string> pluginfiles;
00085     foreach (const string& d, dirs) {
00086       if (d.empty()) continue;
00087       oslink::directory dir(d);
00088       while (dir) {
00089         string filename = dir.next();
00090         // Require that name *starts* with 'Rivet' with new loader
00091         if (filename.find("Rivet") != 0) continue;
00092         size_t posn = filename.find(libsuffix);
00093         if (posn == string::npos || posn != filename.length()-libsuffix.length()) continue;
00094         /// @todo Make sure this is an abs path
00095         /// @todo Sys-dependent path separator instead of "/"
00096         const string path = d + "/" + filename;
00097         // Ensure no duplicate paths
00098         if (find(pluginfiles.begin(), pluginfiles.end(), path) == pluginfiles.end()) {
00099           pluginfiles += path;
00100         }
00101       }
00102     }
00103 
00104     // Load the plugin files
00105     Log::getLog("Rivet.AnalysisLoader") << Log::TRACE << "Candidate analysis plugin libs: " << pluginfiles << endl;
00106     foreach (const string& pf, pluginfiles) {
00107       Log::getLog("Rivet.AnalysisLoader") << Log::TRACE << "Trying to load plugin analyses from file " << pf << endl;
00108       void* handle = dlopen(pf.c_str(), RTLD_LAZY);
00109       if (!handle) {
00110         Log::getLog("Rivet.AnalysisLoader") << Log::WARN << "Cannot open " << pf << ": " << dlerror() << endl;
00111         continue;
00112       }
00113     }
00114   }
00115 
00116 
00117 }