CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/src/IOPool/Common/bin/EdmProvDump.cc

Go to the documentation of this file.
00001 #include "DataFormats/Provenance/interface/BranchType.h"
00002 #include "DataFormats/Provenance/interface/EventSelectionID.h"
00003 #include "DataFormats/Provenance/interface/History.h"
00004 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00005 #include "DataFormats/Provenance/interface/ProcessConfigurationRegistry.h"
00006 #include "DataFormats/Provenance/interface/ParameterSetID.h"
00007 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00008 #include "DataFormats/Provenance/interface/ProcessConfigurationID.h"
00009 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00010 #include "DataFormats/Provenance/interface/Parentage.h"
00011 #include "DataFormats/Provenance/interface/ProductProvenance.h"
00012 #include "DataFormats/Provenance/interface/StoredProductProvenance.h"
00013 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
00014 #include "FWCore/Catalog/interface/InputFileCatalog.h"
00015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00016 #include "FWCore/ParameterSet/interface/Registry.h"
00017 #include "FWCore/ParameterSet/interface/FillProductRegistryTransients.h"
00018 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
00019 #include "FWCore/Services/src/SiteLocalConfigService.h"
00020 
00021 #include "FWCore/Utilities/interface/Algorithms.h"
00022 #include "FWCore/Utilities/interface/Exception.h"
00023 
00024 #include "Cintex/Cintex.h"
00025 #include "TError.h"
00026 #include "TFile.h"
00027 #include "TTree.h"
00028 
00029 #include "boost/program_options.hpp"
00030 
00031 #include <assert.h>
00032 #include <iostream>
00033 #include <memory>
00034 #include <map>
00035 #include <set>
00036 #include <sstream>
00037 #include <vector>
00038 
00039 typedef std::map<std::string, std::vector<edm::BranchDescription> > IdToBranches;
00040 typedef std::map<std::pair<std::string, std::string>, IdToBranches> ModuleToIdBranches;
00041 
00042 static std::ostream& prettyPrint(std::ostream& oStream, edm::ParameterSet const& iPSet, std::string const& iIndent, std::string const& iIndentDelta);
00043 
00044 namespace {
00045 typedef std::map<edm::ParameterSetID, edm::ParameterSetBlob> ParameterSetMap;
00046 
00047   class HistoryNode {
00048   public:
00049     HistoryNode() :
00050       config_(),
00051       simpleId_(0) {
00052     }
00053 
00054     HistoryNode(edm::ProcessConfiguration const& iConfig, unsigned int iSimpleId) :
00055       config_(iConfig),
00056       simpleId_(iSimpleId) {
00057     }
00058 
00059     void addChild(HistoryNode const& child) {
00060       children_.push_back(child);
00061     }
00062 
00063     edm::ParameterSetID const&
00064     parameterSetID() const {
00065       return config_.parameterSetID();
00066     }
00067 
00068     std::string const&
00069     processName() const {
00070       return config_.processName();
00071     }
00072 
00073     std::size_t
00074     size() const {
00075       return children_.size();
00076     }
00077 
00078     HistoryNode *
00079     lastChildAddress() {
00080       return &children_.back();
00081     }
00082 
00083     typedef std::vector<HistoryNode>::const_iterator const_iterator;
00084     typedef std::vector<HistoryNode>::iterator iterator;
00085 
00086     iterator begin() { return children_.begin();}
00087     iterator end() { return children_.end();}
00088 
00089     const_iterator begin() const { return children_.begin();}
00090     const_iterator end() const { return children_.end();}
00091 
00092     void print(std::ostream& os) const {
00093       os << config_.processName()
00094          << " '" << config_.passID() << "' '"
00095          << config_.releaseVersion() << "' ["
00096          << simpleId_ << "]  ("
00097          << config_.parameterSetID() << ")"
00098          << std::endl;
00099     }
00100 
00101     void printHistory(std::string const& iIndent = std::string("  ")) const;
00102     void printEventSetupHistory(ParameterSetMap const& iPSM,
00103                                 std::string const& iFindMatch,
00104                                 std::ostream& oErrorLog) const;
00105     void printOtherModulesHistory(ParameterSetMap const& iPSM,
00106                                   ModuleToIdBranches const&,
00107                                   std::string const& iFindMatch,
00108                                   std::ostream& oErrorLog) const;
00109     void printTopLevelPSetsHistory(ParameterSetMap const& iPSM,
00110                                    std::string const& iFindMatch,
00111                                    std::ostream& oErrorLog) const;
00112 
00113     edm::ProcessConfigurationID
00114     configurationID() const {
00115       return config_.id();
00116     }
00117 
00118     static bool sort_;
00119   private:
00120     edm::ProcessConfiguration config_;
00121     std::vector<HistoryNode>  children_;
00122     unsigned int              simpleId_;
00123   };
00124 
00125   std::ostream& operator<<(std::ostream& os, HistoryNode const& node) {
00126     node.print(os);
00127     return os;
00128   }
00129   bool HistoryNode::sort_ = false;
00130 }
00131 
00132 std::ostream&
00133 operator<<(std::ostream& os, edm::ProcessHistory& iHist) {
00134   std::string const indentDelta("  ");
00135   std::string indent = indentDelta;
00136   for(edm::ProcessHistory::const_iterator i = iHist.begin(), e = iHist.end();
00137        i != e;
00138        ++i) {
00139     os << indent
00140        << i->processName() << " '"
00141        << i->passID()      << "' '"
00142        << i->releaseVersion() << "' ("
00143        << i->parameterSetID() << ")"
00144        << std::endl;
00145     indent += indentDelta;
00146   }
00147   return os;
00148 }
00149 
00150 void HistoryNode::printHistory(std::string const& iIndent) const {
00151   std::string const indentDelta("  ");
00152   std::string indent = iIndent;
00153   for(const_iterator i = begin(), e = end();
00154        i != e;
00155        ++i) {
00156     std::cout << indent << *i;
00157     i->printHistory(indent+indentDelta);
00158   }
00159 }
00160 
00161 std::string eventSetupComponent(char const* iType,
00162                                 std::string const& iCompName,
00163                                 edm::ParameterSet const& iProcessConfig,
00164                                 std::string const& iProcessName) {
00165   std::ostringstream result;
00166   edm::ParameterSet const& pset = iProcessConfig.getParameterSet(iCompName);
00167   std::string name(pset.getParameter<std::string>("@module_label"));
00168   if(0 == name.size()) {
00169     name = pset.getParameter<std::string>("@module_type");
00170   }
00171 
00172   result << iType << ": " << name << " " << iProcessName << "\n"
00173          << " parameters: ";
00174   prettyPrint(result, pset, " ", " ");
00175   return result.str();
00176 }
00177 
00178 void HistoryNode::printEventSetupHistory(ParameterSetMap const& iPSM,
00179                                          std::string const& iFindMatch,
00180                                          std::ostream& oErrorLog) const {
00181   for(const_iterator itH = begin(), e = end();
00182        itH != e;
00183        ++itH) {
00184     //Get ParameterSet for process
00185     ParameterSetMap::const_iterator itFind = iPSM.find(itH->parameterSetID());
00186     if(itFind == iPSM.end()){
00187       oErrorLog << "No ParameterSetID for " << itH->parameterSetID() << std::endl;
00188     } else {
00189       edm::ParameterSet processConfig(itFind->second.pset());
00190       std::vector<std::string> sourceStrings, moduleStrings;
00191       //get the sources
00192       std::vector<std::string> sources = processConfig.getParameter<std::vector<std::string> >("@all_essources");
00193       for(std::vector<std::string>::iterator itM = sources.begin(); itM != sources.end(); ++itM) {
00194         std::string retValue = eventSetupComponent("ESSource",
00195                                                    *itM,
00196                                                    processConfig,
00197                                                    itH->processName());
00198         if(iFindMatch.empty() or retValue.find(iFindMatch) != std::string::npos) {
00199           sourceStrings.push_back(std::move(retValue));
00200         }
00201       }
00202       //get the modules
00203       std::vector<std::string> modules = processConfig.getParameter<std::vector<std::string> >("@all_esmodules");
00204       for(std::vector<std::string>::iterator itM = modules.begin(); itM != modules.end(); ++itM) {
00205         std::string retValue = eventSetupComponent("ESModule",
00206                                                    *itM,
00207                                                    processConfig,
00208                                                    itH->processName());
00209         if(iFindMatch.empty() or retValue.find(iFindMatch) != std::string::npos) {
00210           moduleStrings.push_back(std::move(retValue));
00211         }
00212       }
00213       if(sort_) {
00214         std::sort(sourceStrings.begin(), sourceStrings.end());
00215         std::sort(moduleStrings.begin(), moduleStrings.end());
00216       }
00217       std::copy(sourceStrings.begin(), sourceStrings.end(),
00218                 std::ostream_iterator<std::string>(std::cout, "\n"));
00219       std::copy(moduleStrings.begin(), moduleStrings.end(),
00220                 std::ostream_iterator<std::string>(std::cout, "\n"));
00221 
00222     }
00223     itH->printEventSetupHistory(iPSM, iFindMatch, oErrorLog);
00224   }
00225 }
00226 
00227 std::string nonProducerComponent(std::string const& iCompName,
00228                                  edm::ParameterSet const& iProcessConfig,
00229                                  std::string const& iProcessName) {
00230   std::ostringstream result;
00231   edm::ParameterSet const& pset = iProcessConfig.getParameterSet(iCompName);
00232   std::string label(pset.getParameter<std::string>("@module_label"));
00233 
00234   result << "Module: " << label << " " << iProcessName << "\n" << " parameters: ";
00235   prettyPrint(result, pset, " ", " ");
00236   return result.str();
00237 }
00238 
00239 void HistoryNode::printOtherModulesHistory(ParameterSetMap const& iPSM,
00240                                            ModuleToIdBranches const& iModules,
00241                                            std::string const& iFindMatch,
00242                                            std::ostream& oErrorLog) const {
00243   for(const_iterator itH = begin(), e = end();
00244        itH != e;
00245        ++itH) {
00246     //Get ParameterSet for process
00247     ParameterSetMap::const_iterator itFind = iPSM.find(itH->parameterSetID());
00248     if(itFind == iPSM.end()){
00249       oErrorLog << "No ParameterSetID for " << itH->parameterSetID() << std::endl;
00250     } else {
00251       edm::ParameterSet processConfig(itFind->second.pset());
00252       std::vector<std::string> moduleStrings;
00253       //get all modules
00254       std::vector<std::string> modules = processConfig.getParameter<std::vector<std::string> >("@all_modules");
00255       for(std::vector<std::string>::iterator itM = modules.begin(); itM != modules.end(); ++itM) {
00256         //if we didn't already handle this from the branches
00257         if(iModules.end() == iModules.find(std::make_pair(itH->processName(), *itM))) {
00258           std::string retValue(nonProducerComponent(
00259                                                     *itM,
00260                                                     processConfig,
00261                                                     itH->processName()));
00262           if(iFindMatch.empty() or retValue.find(iFindMatch) != std::string::npos) {
00263             moduleStrings.push_back(std::move(retValue));
00264           }
00265         }
00266       }
00267       if(sort_) {
00268         std::sort(moduleStrings.begin(), moduleStrings.end());
00269       }
00270       std::copy(moduleStrings.begin(), moduleStrings.end(),
00271                 std::ostream_iterator<std::string>(std::cout, "\n"));
00272     }
00273     itH->printOtherModulesHistory(iPSM, iModules, iFindMatch, oErrorLog);
00274   }
00275 }
00276 
00277 static void appendToSet(std::set<std::string>&iSet, std::vector<std::string> const& iFrom){
00278   for( auto const& n: iFrom){
00279     iSet.insert(n);
00280   }
00281 }
00282 
00283 static std::string topLevelPSet(std::string const& iName,
00284                                 edm::ParameterSet const& iProcessConfig,
00285                                 std::string const& iProcessName) {
00286   std::ostringstream result;
00287   edm::ParameterSet const& pset = iProcessConfig.getParameterSet(iName);
00288   
00289   result << "PSet: " << iName << " " << iProcessName << "\n" << " parameters: ";
00290   prettyPrint(result, pset, " ", " ");
00291   return result.str();
00292 }
00293 
00294 
00295 void HistoryNode::printTopLevelPSetsHistory(ParameterSetMap const& iPSM,
00296                                             std::string const& iFindMatch,
00297                                             std::ostream& oErrorLog) const {
00298   for(const_iterator itH = begin(), e = end();
00299       itH != e;
00300       ++itH) {
00301     //Get ParameterSet for process
00302     ParameterSetMap::const_iterator itFind = iPSM.find(itH->parameterSetID());
00303     if(itFind == iPSM.end()){
00304       oErrorLog << "No ParameterSetID for " << itH->parameterSetID() << std::endl;
00305     } else {
00306       edm::ParameterSet processConfig(itFind->second.pset());
00307       //Need to get the names of PSets which are used by the framework (e.g. names of modules)
00308       std::set<std::string> namesToExclude;
00309       appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_modules"));
00310       appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_sources"));
00311       appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_loopers"));
00312       //appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_subprocesses"));//untracked
00313       appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_esmodules"));
00314       appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_essources"));
00315       appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_esprefers"));
00316       if (processConfig.existsAs<std::vector<std::string>>("all_aliases")) {
00317         appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_aliases"));
00318       }
00319 
00320       std::vector<std::string> allNames{};
00321       processConfig.getParameterSetNames(allNames);
00322 
00323       std::vector<std::string> results;
00324       for(auto const& name: allNames){
00325         if (name.size() == 0 || '@' == name[0] || namesToExclude.find(name)!=namesToExclude.end()) {
00326           continue;
00327         }
00328         std::string retValue = topLevelPSet(name,processConfig,itH->processName());
00329         if(iFindMatch.empty() or retValue.find(iFindMatch) != std::string::npos) {
00330           results.push_back(std::move(retValue));
00331         }
00332       }
00333       if(sort_) {
00334         std::sort(results.begin(), results.end());
00335       }
00336       std::copy(results.begin(), results.end(),
00337                 std::ostream_iterator<std::string>(std::cout, "\n"));
00338     }
00339     itH->printTopLevelPSetsHistory(iPSM, iFindMatch, oErrorLog);
00340   }
00341 }
00342 
00343 
00344 namespace {
00345   std::unique_ptr<TFile>
00346   makeTFileWithLookup(std::string const& filename) {
00347     // See if it is a logical file name.
00348     std::auto_ptr<edm::SiteLocalConfig> slcptr(new edm::service::SiteLocalConfigService(edm::ParameterSet()));
00349     boost::shared_ptr<edm::serviceregistry::ServiceWrapper<edm::SiteLocalConfig> > slc(new edm::serviceregistry::ServiceWrapper<edm::SiteLocalConfig>(slcptr));
00350     edm::ServiceToken slcToken = edm::ServiceRegistry::createContaining(slc);
00351     edm::ServiceRegistry::Operate operate(slcToken);
00352     std::string override;
00353     std::vector<std::string> fileNames;
00354     fileNames.push_back(filename);
00355     edm::InputFileCatalog catalog(fileNames, override, true);
00356     if(catalog.fileNames()[0] == filename) {
00357       throw cms::Exception("FileNotFound", "RootFile::RootFile()")
00358         << "File " << filename << " was not found or could not be opened.\n";
00359     }
00360     // filename is a valid LFN.
00361     std::unique_ptr<TFile> result(TFile::Open(catalog.fileNames()[0].c_str()));
00362     if(!result.get()) {
00363       throw cms::Exception("FileNotFound", "RootFile::RootFile()")
00364         << "File " << fileNames[0] << " was not found or could not be opened.\n";
00365     }
00366     return result;
00367   }
00368 
00369   // Open the input file, returning the TFile object that represents it.
00370   // The returned unique_ptr will not be null. The argument must not be null.
00371   // We first try the file name as a PFN, so that the catalog and related
00372   // services are not loaded unless needed.
00373   std::unique_ptr<TFile>
00374   makeTFile(std::string const& filename) {
00375     gErrorIgnoreLevel = kFatal;
00376     std::unique_ptr<TFile> result(TFile::Open(filename.c_str()));
00377     gErrorIgnoreLevel = kError;
00378     if(!result.get()) {
00379       // Try again with catalog.
00380       return makeTFileWithLookup(filename);
00381     }
00382     return result;
00383   }
00384 }
00385 
00386 
00387 static std::ostream& prettyPrint(std::ostream& os, edm::ParameterSetEntry const& psetEntry, std::string const& iIndent, std::string const& iIndentDelta) {
00388   char const* trackiness = (psetEntry.isTracked()?"tracked":"untracked");
00389   os << "PSet " << trackiness << " = (";
00390   prettyPrint(os, psetEntry.pset(), iIndent + iIndentDelta, iIndentDelta);
00391   os << ")";
00392   return os;
00393 }
00394 
00395 static std::ostream& prettyPrint(std::ostream& os, edm::VParameterSetEntry const& vpsetEntry, std::string const& iIndent, std::string const& iIndentDelta) {
00396   std::vector<edm::ParameterSet> const& vps = vpsetEntry.vpset();
00397   os << "VPSet " << (vpsetEntry.isTracked() ? "tracked" : "untracked") << " = ({" << std::endl;
00398   std::string newIndent = iIndent+iIndentDelta;
00399   std::string start;
00400   std::string const between(",\n");
00401   for(std::vector<edm::ParameterSet>::const_iterator i = vps.begin(), e = vps.end(); i != e; ++i) {
00402     os << start << newIndent;
00403     prettyPrint(os, *i, newIndent, iIndentDelta);
00404     start = between;
00405   }
00406   if(!vps.empty()) {
00407     os << std::endl;
00408   }
00409   os << iIndent<< "})";
00410   return os;
00411 }
00412 
00413 
00414 static std::ostream& prettyPrint(std::ostream& oStream, edm::ParameterSet const& iPSet, std::string const& iIndent, std::string const& iIndentDelta) {
00415   std::string newIndent = iIndent+iIndentDelta;
00416 
00417   oStream << "{" << std::endl;
00418   for(edm::ParameterSet::table::const_iterator i = iPSet.tbl().begin(), e = iPSet.tbl().end(); i != e; ++i) {
00419     // indent a bit
00420     oStream << newIndent<< i->first << ": " << i->second << std::endl;
00421   }
00422   for(edm::ParameterSet::psettable::const_iterator i = iPSet.psetTable().begin(), e = iPSet.psetTable().end(); i != e; ++i) {
00423     // indent a bit
00424     edm::ParameterSetEntry const& pe = i->second;
00425     oStream << newIndent << i->first << ": ";
00426     prettyPrint(oStream, pe, iIndent, iIndentDelta);
00427     oStream<<  std::endl;
00428   }
00429   for(edm::ParameterSet::vpsettable::const_iterator i = iPSet.vpsetTable().begin(), e = iPSet.vpsetTable().end(); i != e; ++i) {
00430     // indent a bit
00431     edm::VParameterSetEntry const& pe = i->second;
00432     oStream << newIndent << i->first << ": ";
00433     prettyPrint(oStream, pe, newIndent, iIndentDelta);
00434     oStream<<  std::endl;
00435   }
00436   oStream << iIndent<< "}";
00437 
00438   return oStream;
00439 }
00440 
00441 
00442 class ProvenanceDumper {
00443 public:
00444   // It is illegal to call this constructor with a null pointer; a
00445   // legal C-style string is required.
00446   ProvenanceDumper(std::string const& filename,
00447                    bool showDependencies,
00448                    bool excludeESModules,
00449                    bool showAllModules,
00450                    bool showTopLevelPSets,
00451                    std::string const& findMatch);
00452 
00453   ProvenanceDumper(ProvenanceDumper const&) = delete; // Disallow copying and moving
00454   ProvenanceDumper& operator=(ProvenanceDumper const&) = delete; // Disallow copying and moving
00455 
00456   // Write the provenenace information to the given stream.
00457   void dump();
00458   void printErrors(std::ostream& os);
00459   int exitCode() const;
00460 
00461 private:
00462   std::string              filename_;
00463   std::unique_ptr<TFile>   inputFile_;
00464   int                      exitCode_;
00465   std::stringstream        errorLog_;
00466   int                      errorCount_;
00467   edm::ProductRegistry     reg_;
00468   edm::ProcessConfigurationVector phc_;
00469   edm::ProcessHistoryVector phv_;
00470   ParameterSetMap          psm_;
00471   HistoryNode              historyGraph_;
00472   bool                     showDependencies_;
00473   bool                     excludeESModules_;
00474   bool                     showOtherModules_;
00475   bool                     showTopLevelPSets_;
00476   std::string              findMatch_;
00477 
00478   void work_();
00479   void dumpProcessHistory_();
00480   void dumpEventFilteringParameterSets_(TFile * file);
00481   void dumpEventFilteringParameterSets(edm::EventSelectionIDVector const& ids);
00482   void dumpParameterSetForID_(edm::ParameterSetID const& id);
00483 };
00484 
00485 ProvenanceDumper::ProvenanceDumper(std::string const& filename,
00486                                    bool showDependencies,
00487                                    bool excludeESModules,
00488                                    bool showOtherModules,
00489                                    bool showTopLevelPSets,
00490                                    std::string const& findMatch) :
00491   filename_(filename),
00492   inputFile_(makeTFile(filename)),
00493   exitCode_(0),
00494   errorLog_(),
00495   errorCount_(0),
00496   showDependencies_(showDependencies),
00497   excludeESModules_(excludeESModules),
00498   showOtherModules_(showOtherModules),
00499   showTopLevelPSets_(showTopLevelPSets),
00500   findMatch_(findMatch) {
00501 }
00502 
00503 void
00504 ProvenanceDumper::dump() {
00505   work_();
00506 }
00507 
00508 void
00509 ProvenanceDumper::printErrors(std::ostream& os) {
00510   if(errorCount_ > 0) os << errorLog_.str() << std::endl;
00511 }
00512 
00513 int
00514 ProvenanceDumper::exitCode() const {
00515   return exitCode_;
00516 }
00517 
00518 void
00519 ProvenanceDumper::dumpEventFilteringParameterSets(edm::EventSelectionIDVector const& ids) {
00520   edm::EventSelectionIDVector::size_type num_ids = ids.size();
00521   if(num_ids == 0) {
00522     std::cout << "No event filtering information is available.\n";
00523     std::cout << "------------------------------\n";
00524   } else {
00525     std::cout << "Event filtering information for "
00526               << num_ids
00527               << " processing steps is available.\n"
00528               << "The ParameterSets will be printed out, "
00529               << "with the oldest printed first.\n";
00530     for(edm::EventSelectionIDVector::size_type i = 0; i != num_ids; ++i) {
00531       dumpParameterSetForID_(ids[i]);
00532     }
00533   }
00534 }
00535 
00536 void
00537 ProvenanceDumper::dumpEventFilteringParameterSets_(TFile* file) {
00538 
00539   TTree* history = dynamic_cast<TTree*>(file->Get(edm::poolNames::eventHistoryTreeName().c_str()));
00540   if(history != 0) {
00541     edm::History h;
00542     edm::History* ph = &h;
00543 
00544     history->SetBranchAddress(edm::poolNames::eventHistoryBranchName().c_str(), &ph);
00545     if(history->GetEntry(0) <= 0) {
00546       std::cout << "No event filtering information is available; the event history tree has no entries\n";
00547     } else {
00548       dumpEventFilteringParameterSets(h.eventSelectionIDs());
00549     }
00550   } else {
00551     TTree* events = dynamic_cast<TTree*>(file->Get(edm::poolNames::eventTreeName().c_str()));
00552     assert (events != 0);
00553     TBranch* eventSelectionsBranch = events->GetBranch(edm::poolNames::eventSelectionsBranchName().c_str());
00554     assert (eventSelectionsBranch != 0);
00555     edm::EventSelectionIDVector ids;
00556     edm::EventSelectionIDVector* pids = &ids;
00557     eventSelectionsBranch->SetAddress(&pids);
00558     if(eventSelectionsBranch->GetEntry(0) <= 0) {
00559       std::cout << "No event filtering information is available; the event selections branch has no entries\n";
00560     } else {
00561       dumpEventFilteringParameterSets(ids);
00562     }
00563   }
00564 }
00565 
00566 void
00567 ProvenanceDumper::dumpParameterSetForID_(edm::ParameterSetID const& id) {
00568   std::cout << "ParameterSetID: " << id << '\n';
00569   if(id.isValid()) {
00570     ParameterSetMap::const_iterator i = psm_.find(id);
00571     if(i == psm_.end()) {
00572       std::cout << "We are unable to find the corresponding ParameterSet\n";
00573       edm::ParameterSet empty;
00574       if(id == empty.id()) {
00575         std::cout << "But it would have been empty anyway\n";
00576       }
00577     } else {
00578       edm::ParameterSet ps(i->second.pset());
00579       prettyPrint(std::cout, ps, " ", " ");
00580       std::cout<< '\n';
00581     }
00582   } else {
00583     std::cout << "This ID is not valid\n";
00584   }
00585   std::cout << "     -------------------------\n";
00586 }
00587 
00588 void
00589 ProvenanceDumper::dumpProcessHistory_() {
00590   std::cout << "Processing History:" << std::endl;
00591   if(1 == phv_.size()) {
00592     std::cout << *phv_.begin();
00593     historyGraph_.addChild(HistoryNode(*(phv_.begin()->begin()), 1));
00594   } else {
00595     std::map<edm::ProcessConfigurationID, unsigned int> simpleIDs;
00596     for(edm::ProcessHistoryVector::const_iterator it = phv_.begin(), itEnd = phv_.end();
00597          it != itEnd;
00598          ++it) {
00599       //loop over the history entries looking for matches
00600       HistoryNode* parent = &historyGraph_;
00601       for(edm::ProcessHistory::const_iterator itH = it->begin(), e = it->end();
00602            itH != e;
00603            ++itH) {
00604         if(parent->size() == 0) {
00605           unsigned int id = simpleIDs[itH->id()];
00606           if(0 == id) {
00607             id = 1;
00608             simpleIDs[itH->id()] = id;
00609           }
00610           parent->addChild(HistoryNode(*itH, id));
00611           parent = parent->lastChildAddress();
00612         } else {
00613           //see if this is unique
00614           bool isUnique = true;
00615           for(HistoryNode::iterator itChild = parent->begin(), itChildEnd = parent->end();
00616                itChild != itChildEnd;
00617                ++itChild) {
00618             if(itChild->configurationID() == itH->id()) {
00619               isUnique = false;
00620               parent = &(*itChild);
00621               break;
00622             }
00623           }
00624           if(isUnique) {
00625             simpleIDs[itH->id()] = parent->size() + 1;
00626             parent->addChild(HistoryNode(*itH, simpleIDs[itH->id()]));
00627             parent = parent->lastChildAddress();
00628           }
00629         }
00630       }
00631     }
00632     historyGraph_.printHistory();
00633   }
00634 }
00635 
00636 void
00637 ProvenanceDumper::work_() {
00638 
00639   TTree* meta = dynamic_cast<TTree*>(inputFile_->Get(edm::poolNames::metaDataTreeName().c_str()));
00640   assert(0 != meta);
00641 
00642   edm::ProductRegistry* pReg = &reg_;
00643   meta->SetBranchAddress(edm::poolNames::productDescriptionBranchName().c_str(), &pReg);
00644 
00645   ParameterSetMap* pPsm = &psm_;
00646   if(meta->FindBranch(edm::poolNames::parameterSetMapBranchName().c_str()) != 0) {
00647     meta->SetBranchAddress(edm::poolNames::parameterSetMapBranchName().c_str(), &pPsm);
00648   } else {
00649     TTree* psetTree = dynamic_cast<TTree *>(inputFile_->Get(edm::poolNames::parameterSetsTreeName().c_str()));
00650     assert(0 != psetTree);
00651     typedef std::pair<edm::ParameterSetID, edm::ParameterSetBlob> IdToBlobs;
00652     IdToBlobs idToBlob;
00653     IdToBlobs* pIdToBlob = &idToBlob;
00654     psetTree->SetBranchAddress(edm::poolNames::idToParameterSetBlobsBranchName().c_str(), &pIdToBlob);
00655     for(long long i = 0; i != psetTree->GetEntries(); ++i) {
00656       psetTree->GetEntry(i);
00657       psm_.insert(idToBlob);
00658     }
00659   }
00660   edm::ProcessConfigurationVector* pPhc = &phc_;
00661   if(meta->FindBranch(edm::poolNames::processConfigurationBranchName().c_str()) != 0) {
00662     meta->SetBranchAddress(edm::poolNames::processConfigurationBranchName().c_str(), &pPhc);
00663   }
00664 
00665   edm::ProcessHistoryVector* pPhv = &phv_;
00666   if(meta->FindBranch(edm::poolNames::processHistoryBranchName().c_str()) != 0) {
00667     meta->SetBranchAddress(edm::poolNames::processHistoryBranchName().c_str(), &pPhv);
00668   }
00669 
00670   edm::ProcessHistoryMap phm;
00671   edm::ProcessHistoryMap* pPhm = &phm;
00672   if(meta->FindBranch(edm::poolNames::processHistoryMapBranchName().c_str()) != 0) {
00673     meta->SetBranchAddress(edm::poolNames::processHistoryMapBranchName().c_str(), &pPhm);
00674   }
00675 
00676   if(meta->FindBranch(edm::poolNames::moduleDescriptionMapBranchName().c_str()) != 0) {
00677     if(meta->GetBranch(edm::poolNames::moduleDescriptionMapBranchName().c_str())->GetSplitLevel() != 0) {
00678       meta->SetBranchStatus((edm::poolNames::moduleDescriptionMapBranchName() + ".*").c_str(), 0);
00679     } else {
00680       meta->SetBranchStatus(edm::poolNames::moduleDescriptionMapBranchName().c_str(), 0);
00681     }
00682   }
00683 
00684   meta->GetEntry(0);
00685   assert(0 != pReg);
00686 
00687   edm::pset::Registry& psetRegistry = *edm::pset::Registry::instance();
00688   for(ParameterSetMap::const_iterator i = psm_.begin(), iEnd = psm_.end(); i != iEnd; ++i) {
00689     edm::ParameterSet pset(i->second.pset());
00690     pset.setID(i->first);
00691     psetRegistry.insertMapped(pset);
00692   }
00693 
00694 
00695   // backward compatibility
00696   if(!phm.empty()) {
00697     for(edm::ProcessHistoryMap::const_iterator i = phm.begin(), e = phm.end(); i != e; ++i) {
00698       phv_.push_back(i->second);
00699       for(edm::ProcessConfigurationVector::const_iterator j = i->second.begin(), f = i->second.end(); j != f; ++j) {
00700         phc_.push_back(*j);
00701       }
00702     }
00703     edm::sort_all(phc_);
00704     phc_.erase(std::unique(phc_.begin(), phc_.end()), phc_.end());
00705   }
00706 
00707   fillProductRegistryTransients(phc_, reg_, true);
00708 
00709   //Prepare the parentage information if requested
00710   std::map<edm::BranchID, std::set<edm::ParentageID> > perProductParentage;
00711 
00712   if(showDependencies_){
00713     TTree* parentageTree = dynamic_cast<TTree*>(inputFile_->Get(edm::poolNames::parentageTreeName().c_str()));
00714     if(0 == parentageTree) {
00715       std::cerr << "no Parentage tree available so can not show dependencies/n";
00716       showDependencies_ = false;
00717     } else {
00718 
00719       edm::ParentageRegistry& registry = *edm::ParentageRegistry::instance();
00720 
00721       std::vector<edm::ParentageID> orderedParentageIDs;
00722       orderedParentageIDs.reserve(parentageTree->GetEntries());
00723       for(Long64_t i = 0, numEntries = parentageTree->GetEntries(); i < numEntries; ++i) {
00724         edm::Parentage parentageBuffer;
00725         edm::Parentage *pParentageBuffer = &parentageBuffer;
00726         parentageTree->SetBranchAddress(edm::poolNames::parentageBranchName().c_str(), &pParentageBuffer);
00727         parentageTree->GetEntry(i);
00728         registry.insertMapped(parentageBuffer);
00729         orderedParentageIDs.push_back(parentageBuffer.id());
00730       }
00731       parentageTree->SetBranchAddress(edm::poolNames::parentageBranchName().c_str(), 0);
00732 
00733       TTree* eventMetaTree = dynamic_cast<TTree*>(inputFile_->Get(edm::BranchTypeToMetaDataTreeName(edm::InEvent).c_str()));
00734       if(0 == eventMetaTree) {
00735         eventMetaTree = dynamic_cast<TTree*>(inputFile_->Get(edm::BranchTypeToProductTreeName(edm::InEvent).c_str()));
00736       }
00737       if(0 == eventMetaTree) {
00738         std::cerr << "no '" << edm::BranchTypeToProductTreeName(edm::InEvent)<< "' Tree in file so can not show dependencies\n";
00739         showDependencies_ = false;
00740       } else {
00741         TBranch* storedProvBranch = eventMetaTree->GetBranch(edm::BranchTypeToProductProvenanceBranchName(edm::InEvent).c_str());
00742 
00743         if(0!=storedProvBranch) {
00744           std::vector<edm::StoredProductProvenance> info;
00745           std::vector<edm::StoredProductProvenance>* pInfo = &info;
00746           storedProvBranch->SetAddress(&pInfo);
00747           for(Long64_t i = 0, numEntries = eventMetaTree->GetEntries(); i < numEntries; ++i) {
00748             storedProvBranch->GetEntry(i);
00749             for(std::vector<edm::StoredProductProvenance>::const_iterator it = info.begin(), itEnd = info.end();
00750                 it != itEnd; ++it) {
00751               edm::BranchID bid(it->branchID_);
00752               perProductParentage[bid].insert(orderedParentageIDs[it->parentageIDIndex_]);
00753             }
00754           }
00755         } else {
00756           //backwards compatible check
00757           TBranch* productProvBranch = eventMetaTree->GetBranch(edm::BranchTypeToBranchEntryInfoBranchName(edm::InEvent).c_str());
00758           if (0 != productProvBranch) {
00759             std::vector<edm::ProductProvenance> info;
00760             std::vector<edm::ProductProvenance>* pInfo = &info;
00761             productProvBranch->SetAddress(&pInfo);
00762             for(Long64_t i = 0, numEntries = eventMetaTree->GetEntries(); i < numEntries; ++i) {
00763               productProvBranch->GetEntry(i);
00764               for(std::vector<edm::ProductProvenance>::const_iterator it = info.begin(), itEnd = info.end();
00765                   it != itEnd; ++it) {
00766                 perProductParentage[it->branchID()].insert(it->parentageID());
00767               }
00768             }
00769           } else {
00770             std::cerr <<" could not find provenance information so can not show dependencies\n";
00771             showDependencies_=false;
00772           }
00773         }
00774       }
00775     }
00776   }
00777 
00778 
00779   dumpEventFilteringParameterSets_(inputFile_.get());
00780 
00781   dumpProcessHistory_();
00782 
00783   std::cout << "---------Producers with data in file---------" << std::endl;
00784 
00785   //using edm::ParameterSetID as the key does not work
00786   //   typedef std::map<edm::ParameterSetID, std::vector<edm::BranchDescription> > IdToBranches
00787   ModuleToIdBranches moduleToIdBranches;
00788   //IdToBranches idToBranches;
00789 
00790   std::map<edm::BranchID, std::string> branchIDToBranchName;
00791 
00792   for(edm::ProductRegistry::ProductList::const_iterator it =
00793          reg_.productList().begin(), itEnd = reg_.productList().end();
00794        it != itEnd;
00795        ++it) {
00796     //force it to rebuild the branch name
00797     it->second.init();
00798 
00799     if(showDependencies_) {
00800       branchIDToBranchName[it->second.branchID()] = it->second.branchName();
00801     }
00802     /*
00803       std::cout << it->second.branchName()
00804       << " id " << it->second.productID() << std::endl;
00805     */
00806     for(std::map<edm::ProcessConfigurationID, edm::ParameterSetID>::const_iterator
00807            itId = it->second.parameterSetIDs().begin(),
00808            itIdEnd = it->second.parameterSetIDs().end();
00809            itId != itIdEnd;
00810            ++itId) {
00811 
00812       std::stringstream s;
00813       s << itId->second;
00814       moduleToIdBranches[std::make_pair(it->second.processName(), it->second.moduleLabel())][s.str()].push_back(it->second);
00815       //idToBranches[*itId].push_back(it->second);
00816     }
00817   }
00818   for(ModuleToIdBranches::const_iterator it = moduleToIdBranches.begin(),
00819          itEnd = moduleToIdBranches.end();
00820        it != itEnd;
00821        ++it) {
00822     std::ostringstream sout;
00823     sout << "Module: " << it->first.second << " " << it->first.first << std::endl;
00824     IdToBranches const& idToBranches = it->second;
00825     for(IdToBranches::const_iterator itIdBranch = idToBranches.begin(),
00826            itIdBranchEnd = idToBranches.end();
00827          itIdBranch != itIdBranchEnd;
00828          ++itIdBranch) {
00829       sout << " PSet id:" << itIdBranch->first << std::endl;
00830       sout << " products: {" << std::endl;
00831       std::set<edm::BranchID> branchIDs;
00832       for(std::vector<edm::BranchDescription>::const_iterator itBranch = itIdBranch->second.begin(),
00833              itBranchEnd = itIdBranch->second.end();
00834            itBranch != itBranchEnd;
00835            ++itBranch) {
00836         sout << "  " << itBranch->branchName() << std::endl;
00837         branchIDs.insert(itBranch->branchID());
00838       }
00839       sout << " }" << std::endl;
00840       edm::ParameterSetID psid(itIdBranch->first);
00841       ParameterSetMap::const_iterator itpsm = psm_.find(psid);
00842       if(psm_.end() == itpsm) {
00843         ++errorCount_;
00844         errorLog_ << "No ParameterSetID for " << psid << std::endl;
00845         exitCode_ = 1;
00846       } else {
00847         sout << " parameters: ";
00848         prettyPrint(sout, edm::ParameterSet((*itpsm).second.pset()), " ", " ");
00849         sout << std::endl;
00850       }
00851       if(showDependencies_) {
00852         edm::ParentageRegistry& registry = *edm::ParentageRegistry::instance();
00853 
00854         sout << " dependencies: {" << std::endl;
00855         std::set<edm::ParentageID> parentageIDs;
00856         for(std::set<edm::BranchID>::const_iterator itBranch = branchIDs.begin(), itBranchEnd = branchIDs.end();
00857             itBranch != itBranchEnd;
00858             ++itBranch) {
00859           std::set<edm::ParentageID> const& temp = perProductParentage[*itBranch];
00860           parentageIDs.insert(temp.begin(), temp.end());
00861         }
00862         for(std::set<edm::ParentageID>::const_iterator itParentID = parentageIDs.begin(), itEndParentID = parentageIDs.end();
00863             itParentID != itEndParentID;
00864             ++itParentID) {
00865           edm::Parentage const* parentage = registry.getMapped(*itParentID);
00866           if(0 != parentage) {
00867             for(std::vector<edm::BranchID>::const_iterator itBranch = parentage->parents().begin(), itEndBranch = parentage->parents().end();
00868                 itBranch != itEndBranch;
00869                 ++itBranch) {
00870               sout << "  " << branchIDToBranchName[*itBranch] << std::endl;
00871             }
00872           } else {
00873             sout << "  ERROR:parentage info not in registry ParentageID=" << *itParentID << std::endl;
00874           }
00875         }
00876         if(parentageIDs.empty()) {
00877           sout << "  no dependencies recorded (event may not contain data from this module)" << std::endl;
00878         }
00879         sout << " }" << std::endl;
00880       }
00881       if(findMatch_.empty() or sout.str().find(findMatch_) != std::string::npos) {
00882         std::cout <<sout.str()<<std::endl;
00883       }
00884     }
00885   }
00886   if(showOtherModules_) {
00887     std::cout << "---------Other Modules---------" << std::endl;
00888     historyGraph_.printOtherModulesHistory(psm_, moduleToIdBranches, findMatch_, errorLog_);
00889   }
00890 
00891   if(!excludeESModules_) {
00892     std::cout << "---------EventSetup---------" << std::endl;
00893     historyGraph_.printEventSetupHistory(psm_, findMatch_, errorLog_);
00894   }
00895   
00896   if(showTopLevelPSets_) {
00897     std::cout << "---------Top Level PSets---------" << std::endl;
00898     historyGraph_.printTopLevelPSetsHistory(psm_, findMatch_, errorLog_);
00899   }
00900   if(errorCount_ != 0) {
00901     exitCode_ = 1;
00902   }
00903 }
00904 
00905 static char const* const kSortOpt = "sort";
00906 static char const* const kSortCommandOpt = "sort,s";
00907 static char const* const kDependenciesOpt = "dependencies";
00908 static char const* const kDependenciesCommandOpt = "dependencies,d";
00909 static char const* const kExcludeESModulesOpt = "excludeESModules";
00910 static char const* const kExcludeESModulesCommandOpt = "excludeESModules,e";
00911 static char const* const kShowAllModulesOpt = "showAllModules";
00912 static char const* const kShowAllModulesCommandOpt = "showAllModules,a";
00913 static char const* const kFindMatchOpt = "findMatch";
00914 static char const* const kFindMatchCommandOpt = "findMatch,f";
00915 static char const* const kShowTopLevelPSetsOpt = "showTopLevelPSets";
00916 static char const* const kShowTopLevelPSetsCommandOpt ="showTopLevelPSets,t";
00917 static char const* const kHelpOpt = "help";
00918 static char const* const kHelpCommandOpt = "help,h";
00919 static char const* const kFileNameOpt = "input-file";
00920 static char const* const kFileNameCommandOpt = "input-file";
00921 
00922 int main(int argc, char* argv[]) {
00923   using namespace boost::program_options;
00924 
00925   std::string descString(argv[0]);
00926   descString += " [options] <filename>";
00927   descString += "\nAllowed options";
00928   options_description desc(descString);
00929   desc.add_options()
00930   (kHelpCommandOpt, "show help message")
00931   (kSortCommandOpt
00932    , "alphabetially sort EventSetup components")
00933   (kDependenciesCommandOpt
00934    , "print what data each EDProducer is dependent upon")
00935   (kExcludeESModulesCommandOpt
00936    , "do not print ES module information")
00937   (kShowAllModulesCommandOpt
00938    , "show all modules (not just those that created data in the file)")
00939   (kShowTopLevelPSetsCommandOpt,"show all top level PSets")
00940   (kFindMatchCommandOpt, boost::program_options::value<std::string>(),
00941     "show only modules whose information contains the matching string")
00942   ;
00943   //we don't want users to see these in the help messages since this
00944   // name only exists since the parser needs it
00945   options_description hidden;
00946   hidden.add_options()(kFileNameOpt, value<std::string>(), "file name");
00947 
00948   //full list of options for the parser
00949   options_description cmdline_options;
00950   cmdline_options.add(desc).add(hidden);
00951 
00952   positional_options_description p;
00953   p.add(kFileNameOpt, -1);
00954 
00955   variables_map vm;
00956   try {
00957     store(command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm);
00958     notify(vm);
00959   } catch(error const& iException) {
00960     std::cerr << iException.what();
00961     return 1;
00962   }
00963 
00964   if(vm.count(kHelpOpt)) {
00965     std::cout << desc << std::endl;
00966     return 0;
00967   }
00968 
00969   if(vm.count(kSortOpt)) {
00970     HistoryNode::sort_ = true;
00971   }
00972 
00973   bool showDependencies = false;
00974   if(vm.count(kDependenciesOpt)) {
00975     showDependencies = true;
00976   }
00977 
00978   bool excludeESModules = false;
00979   if(vm.count(kExcludeESModulesOpt)) {
00980     excludeESModules = true;
00981   }
00982 
00983   bool showAllModules = false;
00984   if(vm.count(kShowAllModulesOpt)) {
00985     showAllModules = true;
00986   }
00987   
00988   bool showTopLevelPSets = false;
00989   if(vm.count(kShowTopLevelPSetsOpt)) {
00990     showTopLevelPSets=true;
00991   }
00992 
00993   std::string fileName;
00994   if(vm.count(kFileNameOpt)) {
00995     try {
00996       fileName = vm[kFileNameOpt].as<std::string>();
00997     } catch(boost::bad_any_cast const& e) {
00998       std::cout << e.what() << std::endl;
00999       return 2;
01000     }
01001   } else {
01002     std::cout << "Data file not specified." << std::endl;
01003     std::cout << desc << std::endl;
01004     return 2;
01005   }
01006 
01007   std::string findMatch;
01008   if(vm.count(kFindMatchOpt)) {
01009     try {
01010       findMatch = vm[kFindMatchOpt].as<std::string>();
01011     } catch(boost::bad_any_cast const& e) {
01012       std::cout << e.what() << std::endl;
01013       return 2;
01014     }
01015   }
01016 
01017   //silence ROOT warnings about missing dictionaries
01018   gErrorIgnoreLevel = kError;
01019 
01020   //make sure dictionaries can be used for reading
01021   ROOT::Cintex::Cintex::Enable();
01022 
01023   ProvenanceDumper dumper(fileName, showDependencies, excludeESModules, showAllModules, showTopLevelPSets, findMatch);
01024   int exitCode(0);
01025   try {
01026     dumper.dump();
01027     exitCode = dumper.exitCode();
01028   }
01029   catch (cms::Exception const& x) {
01030     std::cerr << "cms::Exception caught\n";
01031     std::cerr << x.what() << '\n';
01032     exitCode = 2;
01033   }
01034   catch (std::exception& x) {
01035     std::cerr << "std::exception caught\n";
01036     std::cerr << x.what() << '\n';
01037     exitCode = 3;
01038   }
01039   catch (...) {
01040     std::cerr << "Unknown exception caught\n";
01041     exitCode = 4;
01042   }
01043 
01044   dumper.printErrors(std::cerr);
01045   return exitCode;
01046 }