CMS 3D CMS Logo

RootOutputFile.cc

Go to the documentation of this file.
00001 
00002 #include "IOPool/Output/src/RootOutputFile.h"
00003 
00004 #include "FWCore/Utilities/interface/GlobalIdentifier.h"
00005 
00006 #include "DataFormats/Provenance/interface/EventAuxiliary.h" 
00007 #include "DataFormats/Provenance/interface/LuminosityBlockAuxiliary.h" 
00008 #include "DataFormats/Provenance/interface/RunAuxiliary.h" 
00009 #include "DataFormats/Provenance/interface/FileFormatVersion.h"
00010 #include "FWCore/Utilities/interface/GetFileFormatVersion.h"
00011 #include "FWCore/Utilities/interface/EDMException.h"
00012 #include "FWCore/Utilities/interface/Algorithms.h"
00013 #include "FWCore/Utilities/interface/Digest.h"
00014 #include "FWCore/Framework/interface/FileBlock.h"
00015 #include "FWCore/Framework/interface/EventPrincipal.h"
00016 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00017 #include "FWCore/Framework/interface/RunPrincipal.h"
00018 #include "DataFormats/Provenance/interface/BranchChildren.h"
00019 #include "DataFormats/Provenance/interface/BranchID.h"
00020 #include "DataFormats/Provenance/interface/EventEntryDescription.h"
00021 #include "DataFormats/Provenance/interface/EntryDescriptionRegistry.h"
00022 #include "DataFormats/Provenance/interface/EventID.h"
00023 #include "DataFormats/Provenance/interface/History.h"
00024 #include "DataFormats/Provenance/interface/ModuleDescriptionRegistry.h"
00025 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00026 #include "DataFormats/Provenance/interface/ParameterSetID.h"
00027 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00028 #include "DataFormats/Provenance/interface/ProcessHistoryID.h"
00029 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00030 #include "DataFormats/Provenance/interface/ProductStatus.h"
00031 #include "DataFormats/Common/interface/BasicHandle.h"
00032 #include "FWCore/Framework/interface/ConstProductRegistry.h"
00033 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00034 #include "FWCore/ParameterSet/interface/Registry.h"
00035 #include "FWCore/ServiceRegistry/interface/Service.h"
00036 
00037 #include "TROOT.h"
00038 
00039 #include "TTree.h"
00040 #include "TFile.h"
00041 #include "TClass.h"
00042 #include "Rtypes.h"
00043 
00044 #include <algorithm>
00045 #include <iomanip>
00046 #include <sstream>
00047 
00048 
00049 namespace edm {
00050 
00051   namespace {
00052     bool
00053     sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
00054       return 
00055         lh->fullClassName() < rh->fullClassName() ? true :
00056         lh->fullClassName() > rh->fullClassName() ? false :
00057         lh->moduleLabel() < rh->moduleLabel() ? true :
00058         lh->moduleLabel() > rh->moduleLabel() ? false :
00059         lh->productInstanceName() < rh->productInstanceName() ? true :
00060         lh->productInstanceName() > rh->productInstanceName() ? false :
00061         lh->processName() < rh->processName() ? true :
00062         false;
00063     }
00064   }
00065 
00066   RootOutputFile::RootOutputFile(PoolOutputModule *om, std::string const& fileName, std::string const& logicalFileName) :
00067       file_(fileName),
00068       logicalFile_(logicalFileName),
00069       reportToken_(0),
00070       om_(om),
00071       currentlyFastCloning_(),
00072       filePtr_(TFile::Open(file_.c_str(), "recreate", "", om_->compressionLevel())),
00073       fid_(),
00074       fileIndex_(),
00075       eventEntryNumber_(0LL),
00076       lumiEntryNumber_(0LL),
00077       runEntryNumber_(0LL),
00078       metaDataTree_(0),
00079       entryDescriptionTree_(0),
00080       eventHistoryTree_(0),
00081       pEventAux_(0),
00082       pLumiAux_(0),
00083       pRunAux_(0),
00084       eventEntryInfoVector_(),
00085       lumiEntryInfoVector_(),
00086       runEntryInfoVector_(),
00087       pEventEntryInfoVector_(&eventEntryInfoVector_),
00088       pLumiEntryInfoVector_(&lumiEntryInfoVector_),
00089       pRunEntryInfoVector_(&runEntryInfoVector_),
00090       pHistory_(0),
00091       eventTree_(static_cast<EventPrincipal *>(0),
00092                  filePtr_, InEvent, pEventAux_, pEventEntryInfoVector_,
00093                  om_->basketSize(), om_->splitLevel(), om_->treeMaxVirtualSize()),
00094       lumiTree_(static_cast<LuminosityBlockPrincipal *>(0),
00095                 filePtr_, InLumi, pLumiAux_, pLumiEntryInfoVector_,
00096                 om_->basketSize(), om_->splitLevel(), om_->treeMaxVirtualSize()),
00097       runTree_(static_cast<RunPrincipal *>(0),
00098                filePtr_, InRun, pRunAux_, pRunEntryInfoVector_,
00099                om_->basketSize(), om_->splitLevel(), om_->treeMaxVirtualSize()),
00100       treePointers_(),
00101       dataTypeReported_(false) {
00102     treePointers_[InEvent] = &eventTree_;
00103     treePointers_[InLumi]  = &lumiTree_;
00104     treePointers_[InRun]   = &runTree_;
00105 
00106     for (int i = InEvent; i < NumBranchTypes; ++i) {
00107       BranchType branchType = static_cast<BranchType>(i);
00108       for (OutputItemList::const_iterator it = om_->selectedOutputItemList()[branchType].begin(),
00109           itEnd = om_->selectedOutputItemList()[branchType].end();
00110           it != itEnd; ++it) {
00111         treePointers_[branchType]->addBranch(*it->branchDescription_,
00112                                               it->product_,
00113                                               it->branchDescription_->produced());
00114         //make sure we always store product registry info for all branches we create
00115         branchesWithStoredHistory_.insert(it->branchID());
00116       }
00117     }
00118     // Don't split metadata tree or event description tree
00119     metaDataTree_         = RootOutputTree::makeTTree(filePtr_.get(), poolNames::metaDataTreeName(), 0);
00120     entryDescriptionTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::entryDescriptionTreeName(), 0);
00121 
00122     // Create the tree that will carry (event) History objects.
00123     eventHistoryTree_     = RootOutputTree::makeTTree(filePtr_.get(), poolNames::eventHistoryTreeName(), om_->splitLevel());
00124     if (!eventHistoryTree_)
00125       throw edm::Exception(edm::errors::FatalRootError) 
00126         << "Failed to create the tree for History objects\n";
00127 
00128     if (! eventHistoryTree_->Branch(poolNames::eventHistoryBranchName().c_str(), &pHistory_, om_->basketSize(), 0))
00129       throw edm::Exception(edm::errors::FatalRootError) 
00130         << "Failed to create a branch for Historys in the output file\n";
00131 
00132     fid_ = FileID(createGlobalIdentifier());
00133 
00134     // For the Job Report, get a vector of branch names in the "Events" tree.
00135     // Also create a hash of all the branch names in the "Events" tree
00136     // in a deterministic order, except use the full class name instead of the friendly class name.
00137     // To avoid extra string copies, we create a vector of pointers into the product registry,
00138     // and use a custom comparison operator for sorting.
00139     std::vector<std::string> branchNames;
00140     std::vector<BranchDescription const*> branches;
00141     branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
00142     branches.reserve(om->selectedOutputItemList()[InEvent].size());
00143     for (OutputItemList::const_iterator it = om_->selectedOutputItemList()[InEvent].begin(),
00144           itEnd = om_->selectedOutputItemList()[InEvent].end();
00145           it != itEnd; ++it) {
00146       branchNames.push_back(it->branchDescription_->branchName());
00147       branches.push_back(it->branchDescription_);
00148     }
00149     // Now sort the branches for the hash.
00150     sort_all(branches, sorterForJobReportHash);
00151     // Now, make a concatenated string.
00152     std::ostringstream oss;
00153     char const underscore = '_';
00154     for (std::vector<BranchDescription const*>::const_iterator it = branches.begin(), itEnd = branches.end(); it != itEnd; ++it) {
00155       BranchDescription const& bd = **it;
00156       oss <<  bd.fullClassName() << underscore
00157           << bd.moduleLabel() << underscore
00158           << bd.productInstanceName() << underscore
00159           << bd.processName() << underscore;
00160     }
00161     std::string stringrep = oss.str();
00162     cms::Digest md5alg(stringrep);
00163 
00164     // Register the output file with the JobReport service
00165     // and get back the token for it.
00166     std::string moduleName = "PoolOutputModule";
00167     Service<JobReport> reportSvc;
00168     reportToken_ = reportSvc->outputFileOpened(
00169                       file_, logicalFile_,  // PFN and LFN
00170                       om_->catalog_,  // catalog
00171                       moduleName,   // module class name
00172                       om_->moduleLabel_,  // module label
00173                       fid_.fid(), // file id (guid)
00174                       std::string(), // data type (not yet known, so string is empty).
00175                       md5alg.digest().toString(), // branch hash
00176                       branchNames); // branch names being written
00177   }
00178 
00179   void RootOutputFile::beginInputFile(FileBlock const& fb, bool fastClone) {
00180 
00181     currentlyFastCloning_ = om_->fastCloning() && fb.fastClonable() && fastClone;
00182     if (currentlyFastCloning_) currentlyFastCloning_ = eventTree_.checkSplitLevelAndBasketSize(fb.tree());
00183 
00184     eventTree_.beginInputFile(currentlyFastCloning_);
00185     eventTree_.fastCloneTree(fb.tree());
00186   }
00187 
00188   void RootOutputFile::respondToCloseInputFile(FileBlock const&) {
00189     eventTree_.setEntries();
00190     lumiTree_.setEntries();
00191     runTree_.setEntries();
00192   }
00193 
00194   bool RootOutputFile::shouldWeCloseFile() const {
00195     unsigned int const oneK = 1024;
00196     Long64_t size = filePtr_->GetSize()/oneK;
00197     return(size >= om_->maxFileSize_);
00198   }
00199 
00200   void RootOutputFile::writeOne(EventPrincipal const& e) {
00201     // Auxiliary branch
00202     pEventAux_ = &e.aux();
00203    
00204     // Store an invailid process history ID in EventAuxiliary for obsolete field.
00205     pEventAux_->processHistoryID_ = ProcessHistoryID();
00206     
00207     // Because getting the data may cause an exception to be thrown we want to do that
00208     // first before writing anything to the file about this event
00209     // NOTE: pEventAux_ must be set before calling fillBranches since it gets written out
00210     // in that routine.
00211     fillBranches(InEvent, e, pEventEntryInfoVector_);
00212      
00213     // History branch
00214     History historyForOutput(e.history());
00215     historyForOutput.addEntry(om_->selectorConfig());
00216     //NOTE: EventPrincipal::processHistoryID has the real value since we just injected a dummy
00217     // value for processHistoryID into the EventAuxilliary
00218     historyForOutput.setProcessHistoryID(e.processHistoryID());
00219     pHistory_ = &historyForOutput;
00220     int sz = eventHistoryTree_->Fill();
00221     if ( sz <= 0)
00222       throw edm::Exception(edm::errors::FatalRootError) 
00223         << "Failed to fill the History tree for event: " << e.id()
00224         << "\nTTree::Fill() returned " << sz << " bytes written." << std::endl;
00225 
00226     // Add the dataType to the job report if it hasn't already been done
00227     if(!dataTypeReported_) {
00228       Service<JobReport> reportSvc;
00229       std::string dataType("MC");
00230       if(pEventAux_->isRealData())  dataType = "Data";
00231       reportSvc->reportDataType(reportToken_,dataType);
00232       dataTypeReported_ = true;
00233     }
00234 
00235     pHistory_ = & e.history();
00236 
00237     // Add event to index
00238     fileIndex_.addEntry(pEventAux_->run(), pEventAux_->luminosityBlock(), pEventAux_->event(), eventEntryNumber_);
00239     ++eventEntryNumber_;
00240 
00241     // Report event written 
00242     Service<JobReport> reportSvc;
00243     reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
00244   }
00245 
00246   void RootOutputFile::writeLuminosityBlock(LuminosityBlockPrincipal const& lb) {
00247     // Auxiliary branch
00248     pLumiAux_ = &lb.aux();
00249     // Add lumi to index.
00250     fileIndex_.addEntry(pLumiAux_->run(), pLumiAux_->luminosityBlock(), 0U, lumiEntryNumber_);
00251     ++lumiEntryNumber_;
00252     fillBranches(InLumi, lb, pLumiEntryInfoVector_);
00253   }
00254 
00255   void RootOutputFile::writeRun(RunPrincipal const& r) {
00256     // Auxiliary branch
00257     pRunAux_ = &r.aux();
00258     // Add run to index.
00259     fileIndex_.addEntry(pRunAux_->run(), 0U, 0U, runEntryNumber_);
00260     ++runEntryNumber_;
00261     fillBranches(InRun, r, pRunEntryInfoVector_);
00262   }
00263 
00264   void RootOutputFile::writeEntryDescriptions() {
00265     EntryDescriptionID const* hash(0);
00266     EventEntryDescription const*   desc(0);
00267     
00268     if (!entryDescriptionTree_->Branch(poolNames::entryDescriptionIDBranchName().c_str(), 
00269                                         &hash, om_->basketSize(), 0))
00270       throw edm::Exception(edm::errors::FatalRootError) 
00271         << "Failed to create a branch for EntryDescriptionIDs in the output file";
00272 
00273     if (!entryDescriptionTree_->Branch(poolNames::entryDescriptionBranchName().c_str(), 
00274                                         &desc, om_->basketSize(), 0))
00275       throw edm::Exception(edm::errors::FatalRootError) 
00276         << "Failed to create a branch for EventEntryDescriptions in the output file";
00277 
00278     EntryDescriptionRegistry& edreg = *EntryDescriptionRegistry::instance();
00279     for (EntryDescriptionRegistry::const_iterator
00280            i = edreg.begin(),
00281            e = edreg.end();
00282          i != e;
00283          ++i) {
00284         hash = const_cast<EntryDescriptionID*>(&(i->first)); // cast needed because keys are const
00285         desc = &(i->second);
00286         entryDescriptionTree_->Fill();
00287       }
00288   }
00289 
00290   void RootOutputFile::writeFileFormatVersion() {
00291     FileFormatVersion fileFormatVersion(getFileFormatVersion());
00292     FileFormatVersion * pFileFmtVsn = &fileFormatVersion;
00293     TBranch* b = metaDataTree_->Branch(poolNames::fileFormatVersionBranchName().c_str(), &pFileFmtVsn, om_->basketSize(), 0);
00294     assert(b);
00295     b->Fill();
00296   }
00297 
00298   void RootOutputFile::writeFileIdentifier() {
00299     FileID *fidPtr = &fid_;
00300     TBranch* b = metaDataTree_->Branch(poolNames::fileIdentifierBranchName().c_str(), &fidPtr, om_->basketSize(), 0);
00301     assert(b);
00302     b->Fill();
00303   }
00304 
00305   void RootOutputFile::writeFileIndex() {
00306     fileIndex_.sortBy_Run_Lumi_Event();
00307     FileIndex *findexPtr = &fileIndex_;
00308     TBranch* b = metaDataTree_->Branch(poolNames::fileIndexBranchName().c_str(), &findexPtr, om_->basketSize(), 0);
00309     assert(b);
00310     b->Fill();
00311   }
00312 
00313   void RootOutputFile::writeEventHistory() {
00314     RootOutputTree::writeTTree(eventHistoryTree_);
00315   }
00316 
00317   void RootOutputFile::writeProcessConfigurationRegistry() {
00318     // We don't do this yet; currently we're storing a slightly bloated ProcessHistoryRegistry.
00319   }
00320 
00321   void RootOutputFile::writeProcessHistoryRegistry() { 
00322     ProcessHistoryMap *pProcHistMap = &ProcessHistoryRegistry::instance()->data();
00323     TBranch* b = metaDataTree_->Branch(poolNames::processHistoryMapBranchName().c_str(), &pProcHistMap, om_->basketSize(), 0);
00324     assert(b);
00325     b->Fill();
00326   }
00327 
00328   void RootOutputFile::writeModuleDescriptionRegistry() { 
00329     ModuleDescriptionMap *pModDescMap = &ModuleDescriptionRegistry::instance()->data();
00330     TBranch* b = metaDataTree_->Branch(poolNames::moduleDescriptionMapBranchName().c_str(), &pModDescMap, om_->basketSize(), 0);
00331     assert(b);
00332     b->Fill();
00333   }
00334 
00335   void RootOutputFile::writeParameterSetRegistry() { 
00336     typedef std::map<ParameterSetID, ParameterSetBlob> ParameterSetMap;
00337     ParameterSetMap psetMap;
00338     pset::fill(pset::Registry::instance(), psetMap);
00339     ParameterSetMap *pPsetMap = &psetMap;
00340     TBranch* b = metaDataTree_->Branch(poolNames::parameterSetMapBranchName().c_str(), &pPsetMap, om_->basketSize(), 0);
00341     assert(b);
00342     b->Fill();
00343   }
00344 
00345   void RootOutputFile::writeProductDescriptionRegistry() { 
00346     // Make a local copy of the ProductRegistry, removing any transient or pruned products.
00347     typedef ProductRegistry::ProductList ProductList;
00348     edm::Service<edm::ConstProductRegistry> reg;
00349     ProductRegistry pReg(reg->productList(), reg->nextID());
00350     ProductList & pList  = const_cast<ProductList &>(pReg.productList());
00351     std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
00352     for (ProductList::iterator it = pList.begin(); it != pList.end(); ) {
00353       if (branchesWithStoredHistory_.find(it->second.branchID()) == end) {
00354         // avoid invalidating iterator on deletion
00355         ProductList::iterator itCopy = it;
00356         ++it;
00357         pList.erase(itCopy);
00358         
00359       } else {
00360         ++it;
00361       }
00362     }
00363 
00364     ProductRegistry * ppReg = &pReg;
00365     TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
00366     assert(b);
00367     b->Fill();
00368   } 
00369   void RootOutputFile::writeProductDependencies() { 
00370     BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
00371     BranchChildren * ppDeps = &pDeps;
00372     TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
00373     assert(b);
00374     b->Fill();
00375   }
00376 
00377   void RootOutputFile::finishEndFile() { 
00378     metaDataTree_->SetEntries(-1);
00379     RootOutputTree::writeTTree(metaDataTree_);
00380 
00381     RootOutputTree::writeTTree(entryDescriptionTree_);
00382 
00383     // Create branch aliases for all the branches in the
00384     // events/lumis/runs trees. The loop is over all types of data
00385     // products.
00386     for (int i = InEvent; i < NumBranchTypes; ++i) {
00387       BranchType branchType = static_cast<BranchType>(i);
00388       setBranchAliases(treePointers_[branchType]->tree(), om_->keptProducts()[branchType]);
00389       treePointers_[branchType]->writeTree();
00390     }
00391 
00392     // close the file -- mfp
00393     filePtr_->Close();
00394     filePtr_.reset();
00395 
00396     // report that file has been closed
00397     Service<JobReport> reportSvc;
00398     reportSvc->outputFileClosed(reportToken_);
00399 
00400   }
00401 
00402   void
00403   RootOutputFile::setBranchAliases(TTree *tree, Selections const& branches) const {
00404     if (tree && tree->GetNbranches() != 0) {
00405       for (Selections::const_iterator i = branches.begin(), iEnd = branches.end();
00406           i != iEnd; ++i) {
00407         BranchDescription const& pd = **i;
00408         std::string const& full = pd.branchName() + "obj";
00409         if (pd.branchAliases().empty()) {
00410           std::string const& alias =
00411               (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
00412           tree->SetAlias(alias.c_str(), full.c_str());
00413         } else {
00414           std::set<std::string>::const_iterator it = pd.branchAliases().begin(), itEnd = pd.branchAliases().end();
00415           for (; it != itEnd; ++it) {
00416             tree->SetAlias((*it).c_str(), full.c_str());
00417           }
00418         }
00419       }
00420     }
00421   }
00422    
00423    void RootOutputFile::insertAncestors(const EventEntryInfo& iGetParents,
00424                                         const BranchMapper& iMapper,
00425                                         std::set<EventEntryInfo>& oToFill) {
00426       const std::vector<BranchID>& parentIDs = iGetParents.entryDescription().parents();
00427       for(std::vector<BranchID>::const_iterator it=parentIDs.begin(), itEnd = parentIDs.end();
00428           it != itEnd; ++it) {
00429          branchesWithStoredHistory_.insert(*it);
00430          boost::shared_ptr<EventEntryInfo> info = iMapper.branchToEntryInfo(*it);
00431          if(info) {
00432             if(oToFill.insert(*info).second) {
00433                //haven't seen this one yet
00434                insertAncestors(*info, iMapper, oToFill);
00435             }
00436          }
00437       }
00438    }
00439 }

Generated on Tue Jun 9 17:39:15 2009 for CMSSW by  doxygen 1.5.4