00001 #include "TFile.h"
00002 #include "TTree.h"
00003 #include "Cintex/Cintex.h"
00004
00005 #include "DataFormats/Provenance/interface/BranchType.h"
00006 #include "DataFormats/Provenance/interface/EventSelectionID.h"
00007 #include "DataFormats/Provenance/interface/History.h"
00008 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00009 #include "DataFormats/Provenance/interface/ParameterSetID.h"
00010 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00011 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00013 #include "FWCore/Utilities/interface/Exception.h"
00014
00015 #include <assert.h>
00016 #include <iostream>
00017 #include <memory>
00018 #include <sstream>
00019
00020 #include "boost/utility.hpp"
00021 #include "boost/scoped_ptr.hpp"
00022
00023 namespace {
00024 typedef std::map<edm::ParameterSetID, edm::ParameterSetBlob> ParameterSetMap;
00025
00026 class HistoryNode {
00027 public:
00028 HistoryNode() :
00029 config_(),
00030 simpleId_(0)
00031 { }
00032
00033 HistoryNode(const edm::ProcessConfiguration& iConfig, unsigned int iSimpleId) :
00034 config_(iConfig),
00035 simpleId_(iSimpleId)
00036 { }
00037
00038 void addChild(HistoryNode const& child) {
00039 children_.push_back(child);
00040 }
00041
00042 edm::ParameterSetID const&
00043 parameterSetID() const {
00044 return config_.parameterSetID();
00045 }
00046
00047 std::string const&
00048 processName() const {
00049 return config_.processName();
00050 }
00051
00052 std::size_t
00053 size() const {
00054 return children_.size();
00055 }
00056
00057 HistoryNode *
00058 lastChildAddress() {
00059 return &children_.back();
00060 }
00061
00062 typedef std::vector<HistoryNode>::const_iterator const_iterator;
00063 typedef std::vector<HistoryNode>::iterator iterator;
00064
00065 iterator begin() { return children_.begin();}
00066 iterator end() { return children_.end();}
00067
00068 const_iterator begin() const { return children_.begin();}
00069 const_iterator end() const { return children_.end();}
00070
00071 void print(std::ostream& os) const {
00072 os << config_.processName()
00073 << " '" << config_.passID() << "' '"
00074 << config_.releaseVersion() << "' ["
00075 << simpleId_<<"] ("
00076 << config_.parameterSetID() << ")"
00077 << std::endl;
00078 }
00079
00080 void printHistory(const std::string& iIndent = std::string(" ")) const;
00081 void printEventSetupHistory(const ParameterSetMap& iPSM, std::ostream& oErrorLog) const;
00082
00083 edm::ProcessConfigurationID
00084 configurationID() const {
00085 return config_.id();
00086 }
00087
00088 static bool sort_;
00089 private:
00090 edm::ProcessConfiguration config_;
00091 std::vector<HistoryNode> children_;
00092 unsigned int simpleId_;
00093 };
00094
00095 std::ostream& operator<<(std::ostream& os, const HistoryNode& node) {
00096 node.print(os);
00097 return os;
00098 }
00099 bool HistoryNode::sort_ = false;
00100 }
00101
00102
00103 std::ostream&
00104 operator<< (std::ostream& os, edm::ProcessHistory& iHist)
00105 {
00106 const std::string indentDelta(" ");
00107 std::string indent = indentDelta;
00108 for (edm::ProcessHistory::const_iterator i = iHist.begin(), e = iHist.end();
00109 i != e;
00110 ++i) {
00111 os << indent
00112 <<i->processName() <<" '"
00113 <<i->passID() <<"' '"
00114 <<i->releaseVersion() << "' ("
00115 <<i->parameterSetID()<<")"
00116 << std::endl;
00117 indent += indentDelta;
00118 }
00119 return os;
00120 }
00121
00122 void HistoryNode::printHistory(const std::string& iIndent) const
00123 {
00124 const std::string indentDelta(" ");
00125 std::string indent = iIndent;
00126 for (const_iterator i = begin(), e = end();
00127 i != e;
00128 ++i) {
00129 std::cout << indent << *i;
00130 i->printHistory(indent+indentDelta);
00131 }
00132 }
00133
00134 std::string eventSetupComponent(const char* iType, const std::string& iCompName, const edm::ParameterSet& iProcessConfig, const std::string& iProcessName) {
00135 std::ostringstream result;
00136 const edm::ParameterSet& pset = iProcessConfig.getParameter<edm::ParameterSet>(iCompName);
00137 std::string name( pset.getParameter<std::string>("@module_label") );
00138 if(0 == name.size() ) {
00139 name = pset.getParameter<std::string>("@module_type");
00140 }
00141
00142 result <<iType<<": "<< name<<" "<<iProcessName << "\n"
00143 <<" parameters: "<<pset;
00144 return result.str();
00145 }
00146
00147 void HistoryNode::printEventSetupHistory(const ParameterSetMap& iPSM, ostream& oErrorLog) const
00148 {
00149 for (const_iterator itH = begin(), e = end();
00150 itH != e;
00151 ++itH) {
00152
00153 ParameterSetMap::const_iterator itFind = iPSM.find(itH->parameterSetID());
00154 if(itFind == iPSM.end()){
00155 oErrorLog << "No ParameterSetID for " << itH->parameterSetID() << std::endl;
00156 } else {
00157 edm::ParameterSet processConfig(itFind->second.pset_);
00158 std::vector<std::string> sourceStrings, moduleStrings;
00159
00160 std::vector<std::string> sources = processConfig.getParameter<std::vector<std::string> >("@all_essources");
00161 for(std::vector<std::string>::iterator itM = sources.begin(); itM != sources.end(); ++itM) {
00162 sourceStrings.push_back(eventSetupComponent("ESSource",
00163 *itM,
00164 processConfig,
00165 itH->processName()) );
00166 }
00167
00168 std::vector<std::string> modules = processConfig.getParameter<std::vector<std::string> >("@all_esmodules");
00169 for(std::vector<std::string>::iterator itM = modules.begin(); itM != modules.end(); ++itM) {
00170 moduleStrings.push_back(eventSetupComponent("ESModule",
00171 *itM,
00172 processConfig,
00173 itH->processName()));
00174 }
00175 if(sort_)
00176 {
00177 std::sort(sourceStrings.begin(), sourceStrings.end());
00178 std::sort(moduleStrings.begin(), moduleStrings.end());
00179 }
00180 std::copy(sourceStrings.begin(), sourceStrings.end(),
00181 std::ostream_iterator<std::string>(std::cout,"\n"));
00182 std::copy(moduleStrings.begin(), moduleStrings.end(),
00183 std::ostream_iterator<std::string>(std::cout,"\n"));
00184
00185 }
00186 itH->printEventSetupHistory(iPSM, oErrorLog);
00187 }
00188 }
00189
00190 namespace {
00191
00192
00193
00194
00195 std::auto_ptr<TFile>
00196 makeTFile(const char* filename)
00197 {
00198 std::auto_ptr<TFile> result(TFile::Open(filename));
00199 if (!result.get()) {
00200 throw cms::Exception("FileNotFound","RootFile::RootFile()")
00201 << "File " << filename << " was not found or could not be opened.\n";
00202 }
00203 return result;
00204 }
00205
00206 }
00207
00208
00209
00210 class ProvenanceDumper : boost::noncopyable
00211 {
00212 public:
00213
00214
00215 explicit ProvenanceDumper(const char* filename);
00216
00217
00218 void dump(std::ostream& os);
00219 void printErrors(std::ostream& os);
00220 int exitCode() const;
00221
00222 private:
00223 std::string filename_;
00224 boost::scoped_ptr<TFile> inputFile_;
00225 int exitCode_;
00226 std::stringstream errorLog_;
00227 int errorCount_;
00228 edm::ProductRegistry reg_;
00229 edm::ProcessHistoryMap phm_;
00230 ParameterSetMap psm_;
00231 HistoryNode historyGraph_;
00232
00233 void work_();
00234 void dumpProcessHistory_(TTree& history);
00235 void dumpEventFilteringParameterSets_(TTree& history);
00236 void dumpParameterSetForID_(edm::ParameterSetID const& id);
00237 };
00238
00239 ProvenanceDumper::ProvenanceDumper(const char* filename) :
00240 filename_( filename),
00241 inputFile_(makeTFile(filename)),
00242 exitCode_(0),
00243 errorLog_(),
00244 errorCount_(0)
00245 {
00246 }
00247
00248 void
00249 ProvenanceDumper::dump(std::ostream& os)
00250 {
00251 work_();
00252 }
00253
00254 void
00255 ProvenanceDumper::printErrors(std::ostream& os)
00256 {
00257 if (errorCount_ > 0) os << errorLog_.str() << std::endl;
00258 }
00259
00260 int
00261 ProvenanceDumper::exitCode() const
00262 {
00263 return exitCode_;
00264 }
00265
00266 void
00267 ProvenanceDumper::dumpEventFilteringParameterSets_(TTree& history)
00268 {
00269
00270 edm::History h;
00271 edm::History* ph = &h;
00272
00273 history.SetBranchAddress(edm::poolNames::eventHistoryBranchName().c_str(), &ph);
00274 if (history.GetEntry(0) <= 0)
00275 {
00276 std::cout << "No event filtering information is available; the event history tree has no entries\n";
00277 }
00278 else
00279 {
00280 edm::EventSelectionIDVector const& ids = h.eventSelectionIDs();
00281 edm::EventSelectionIDVector::size_type num_ids = ids.size();
00282 if ( num_ids == 0)
00283 {
00284 std::cout << "No event filtering information is available.\n";
00285 std::cout << "------------------------------\n";
00286 }
00287 else
00288 {
00289 std::cout << "Event filtering information for "
00290 << num_ids
00291 << " processing steps is available.\n"
00292 << "The ParameterSets will be printed out, "
00293 << "with the oldest printed first.\n";
00294 for (edm::EventSelectionIDVector::size_type i = 0; i != num_ids; ++i)
00295 dumpParameterSetForID_(ids[i]);
00296 }
00297 }
00298 }
00299
00300 void
00301 ProvenanceDumper::dumpParameterSetForID_(edm::ParameterSetID const& id)
00302 {
00303 std::cout << "ParameterSetID: " << id << '\n';
00304 if (id.isValid())
00305 {
00306 ParameterSetMap::const_iterator i = psm_.find(id);
00307 if (i == psm_.end())
00308 {
00309 std::cout << "We are unable to find the corresponding ParameterSet\n";
00310 edm::ParameterSet empty;
00311 if (id == empty.id())
00312 {
00313 std::cout << "But it would have been empty anyway\n";
00314 }
00315 }
00316 else
00317 {
00318 edm::ParameterSet ps(i->second.pset_);
00319 std::cout << ps << '\n';
00320 }
00321 }
00322 else
00323 {
00324 std::cout << "This ID is not valid\n";
00325 }
00326 std::cout << " -------------------------\n";
00327 }
00328
00329 void
00330 ProvenanceDumper::dumpProcessHistory_(TTree& history)
00331 {
00332 dumpEventFilteringParameterSets_(history);
00333 std::cout << "Processing History:"<<std::endl;
00334 if (1 == phm_.size()) {
00335 std::cout << phm_.begin()->second;
00336 historyGraph_.addChild(HistoryNode(*(phm_.begin()->second.begin()), 1));
00337 } else {
00338 bool multipleHistories =false;
00339 std::map<edm::ProcessConfigurationID, unsigned int> simpleIDs;
00340 for (edm::ProcessHistoryMap::const_iterator it = phm_.begin(), itEnd = phm_.end();
00341 it != itEnd;
00342 ++it) {
00343
00344 HistoryNode* parent = &historyGraph_;
00345 for (edm::ProcessHistory::const_iterator itH = it->second.begin(), e = it->second.end();
00346 itH != e;
00347 ++itH) {
00348 if (parent->size() == 0) {
00349 unsigned int id = simpleIDs[itH->id()];
00350 if (0 == id) {
00351 id = 1;
00352 simpleIDs[itH->id()] = id;
00353 }
00354 parent->addChild(HistoryNode(*itH,id));
00355 parent = parent->lastChildAddress();
00356 } else {
00357
00358 bool unique = true;
00359 for (HistoryNode::iterator itChild = parent->begin(), itChildEnd = parent->end();
00360 itChild != itChildEnd;
00361 ++itChild) {
00362 if (itChild->configurationID() == itH->id()) {
00363 unique = false;
00364 parent = &(*itChild);
00365 break;
00366 }
00367 }
00368 if (unique) {
00369 multipleHistories = true;
00370 simpleIDs[itH->id()]=parent->size()+1;
00371 parent->addChild(HistoryNode(*itH,simpleIDs[itH->id()]));
00372 parent = parent->lastChildAddress();
00373 }
00374 }
00375 }
00376 }
00377 historyGraph_.printHistory();
00378 }
00379 }
00380
00381 void
00382 ProvenanceDumper::work_() {
00383
00384 std::auto_ptr<TFile> f = makeTFile(filename_.c_str());
00385
00386 TTree* history = dynamic_cast<TTree*>(f->Get(edm::poolNames::eventHistoryTreeName().c_str()));
00387 assert(0!=history);
00388
00389 TTree* meta = dynamic_cast<TTree*>(f->Get(edm::poolNames::metaDataTreeName().c_str()));
00390 assert(0!=meta);
00391
00392 edm::ProductRegistry* pReg=®_;
00393 meta->SetBranchAddress(edm::poolNames::productDescriptionBranchName().c_str(),&pReg);
00394
00395 ParameterSetMap* pPsm =&psm_;
00396 meta->SetBranchAddress(edm::poolNames::parameterSetMapBranchName().c_str(),&pPsm);
00397
00398 edm::ProcessHistoryMap* pPhm=&phm_;
00399 meta->SetBranchAddress(edm::poolNames::processHistoryMapBranchName().c_str(),&pPhm);
00400
00401 meta->GetEntry(0);
00402 assert(0!=pReg);
00403 pReg->setFrozen();
00404
00405 dumpProcessHistory_(*history);
00406
00407 std::cout <<"---------Event---------"<<std::endl;
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 typedef std::map<std::string,std::vector<edm::BranchDescription> > IdToBranches;
00424 typedef std::map<std::pair<std::string,std::string>,IdToBranches> ModuleToIdBranches;
00425 ModuleToIdBranches moduleToIdBranches;
00426
00427 for (edm::ProductRegistry::ProductList::const_iterator it =
00428 reg_.productList().begin(), itEnd = reg_.productList().end();
00429 it != itEnd;
00430 ++it) {
00431
00432 it->second.init();
00433
00434
00435
00436
00437
00438 for (std::set<edm::ParameterSetID>::const_iterator itId = it->second.psetIDs().begin(),
00439 itIdEnd = it->second.psetIDs().end();
00440 itId != itIdEnd;
00441 ++itId) {
00442
00443 std::stringstream s;
00444 s <<*itId;
00445 moduleToIdBranches[std::make_pair(it->second.processName(),it->second.moduleLabel())][s.str()].push_back(it->second);
00446
00447 }
00448 }
00449 for (ModuleToIdBranches::const_iterator it = moduleToIdBranches.begin(),
00450 itEnd = moduleToIdBranches.end();
00451 it != itEnd;
00452 ++it) {
00453 std::cout <<"Module: "<<it->first.second<<" "<<it->first.first<<std::endl;
00454 const IdToBranches& idToBranches = it->second;
00455 for (IdToBranches::const_iterator itIdBranch = idToBranches.begin(),
00456 itIdBranchEnd = idToBranches.end();
00457 itIdBranch != itIdBranchEnd;
00458 ++itIdBranch) {
00459 std::cout <<" PSet id:"<<itIdBranch->first<<std::endl;
00460 std::cout <<" products: {"<<std::endl;
00461 for (std::vector<edm::BranchDescription>::const_iterator itBranch = itIdBranch->second.begin(),
00462 itBranchEnd = itIdBranch->second.end();
00463 itBranch != itBranchEnd;
00464 ++itBranch) {
00465 std::cout << " "<< itBranch->branchName()<<std::endl;
00466 }
00467 std::cout <<"}"<<std::endl;
00468 edm::ParameterSetID psid(itIdBranch->first);
00469 ParameterSetMap::const_iterator itpsm = psm_.find(psid);
00470 if (psm_.end() == itpsm) {
00471 ++errorCount_;
00472 errorLog_ << "No ParameterSetID for " << psid << std::endl;
00473 exitCode_ = 1;
00474 } else {
00475 std::cout <<" parameters: "<<
00476 edm::ParameterSet((*itpsm).second.pset_)<<std::endl;
00477 }
00478 std::cout << std::endl;
00479 }
00480 }
00481 std::cout <<"---------EventSetup---------"<<std::endl;
00482 historyGraph_.printEventSetupHistory(psm_, errorLog_);
00483 if (errorCount_ != 0) {
00484 exitCode_ = 1;
00485 }
00486 }
00487
00488
00489 int main(int argc, char* argv[])
00490 {
00491
00492 std::string fileName;
00493 if(argc == 3 && std::string(argv[1]) == "--sort")
00494 {
00495 HistoryNode::sort_ = true;
00496 fileName = argv[2];
00497 }
00498 else if (argc == 2)
00499 {
00500 fileName = argv[1];
00501 }
00502 else
00503 {
00504 std::cerr << "Usage: " << argv[0] << " [--sort] <filename> \n";
00505 return 2;
00506 }
00507
00508 ROOT::Cintex::Cintex::Enable();
00509 ProvenanceDumper dumper(fileName.c_str());
00510 int exitCode(0);
00511 try
00512 {
00513 dumper.dump(std::cout);
00514 }
00515
00516 catch (cms::Exception const& x)
00517 {
00518 std::cerr << "cms::Exception caught\n";
00519 std::cerr << x.what() << '\n';
00520 exitCode = 2;
00521 }
00522 catch (std::exception& x)
00523 {
00524 std::cerr << "std::exception caught\n";
00525 std::cerr << x.what() << '\n';
00526 exitCode = 3;
00527 }
00528 catch (...)
00529 {
00530 std::cerr << "Unknown exception caught\n";
00531 exitCode = 4;
00532 }
00533
00534 dumper.printErrors(std::cerr);
00535 return dumper.exitCode();
00536 }