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     const vector<string> dirs = getAnalysisLibPaths();
00072 
00073     // Find plugin module library files
00074     const string libsuffix = ".so";
00075     vector<string> pluginfiles;
00076     foreach (const string& d, dirs) {
00077       if (d.empty()) continue;
00078       oslink::directory dir(d);
00079       while (dir) {
00080         string filename = dir.next();
00081         // Require that name *starts* with 'Rivet' with new loader
00082         if (filename.find("Rivet") != 0) continue;
00083         size_t posn = filename.find(libsuffix);
00084         if (posn == string::npos || posn != filename.length()-libsuffix.length()) continue;
00085         /// @todo Make sure this is an abs path
00086         /// @todo Sys-dependent path separator instead of "/"
00087         const string path = d + "/" + filename;
00088         // Ensure no duplicate paths
00089         if (find(pluginfiles.begin(), pluginfiles.end(), path) == pluginfiles.end()) {
00090           pluginfiles += path;
00091         }
00092       }
00093     }
00094 
00095     // Load the plugin files
00096     Log::getLog("Rivet.AnalysisLoader") << Log::TRACE << "Candidate analysis plugin libs: " << pluginfiles << endl;
00097     foreach (const string& pf, pluginfiles) {
00098       Log::getLog("Rivet.AnalysisLoader") << Log::TRACE << "Trying to load plugin analyses from file " << pf << endl;
00099       void* handle = dlopen(pf.c_str(), RTLD_LAZY);
00100       if (!handle) {
00101         Log::getLog("Rivet.AnalysisLoader") << Log::WARN << "Cannot open " << pf << ": " << dlerror() << endl;
00102         continue;
00103       }
00104     }
00105   }
00106 
00107 
00108 }