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
00115 branchesWithStoredHistory_.insert(it->branchID());
00116 }
00117 }
00118
00119 metaDataTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::metaDataTreeName(), 0);
00120 entryDescriptionTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::entryDescriptionTreeName(), 0);
00121
00122
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
00135
00136
00137
00138
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
00150 sort_all(branches, sorterForJobReportHash);
00151
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
00165
00166 std::string moduleName = "PoolOutputModule";
00167 Service<JobReport> reportSvc;
00168 reportToken_ = reportSvc->outputFileOpened(
00169 file_, logicalFile_,
00170 om_->catalog_,
00171 moduleName,
00172 om_->moduleLabel_,
00173 fid_.fid(),
00174 std::string(),
00175 md5alg.digest().toString(),
00176 branchNames);
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
00202 pEventAux_ = &e.aux();
00203
00204
00205 pEventAux_->processHistoryID_ = ProcessHistoryID();
00206
00207
00208
00209
00210
00211 fillBranches(InEvent, e, pEventEntryInfoVector_);
00212
00213
00214 History historyForOutput(e.history());
00215 historyForOutput.addEntry(om_->selectorConfig());
00216
00217
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
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
00238 fileIndex_.addEntry(pEventAux_->run(), pEventAux_->luminosityBlock(), pEventAux_->event(), eventEntryNumber_);
00239 ++eventEntryNumber_;
00240
00241
00242 Service<JobReport> reportSvc;
00243 reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
00244 }
00245
00246 void RootOutputFile::writeLuminosityBlock(LuminosityBlockPrincipal const& lb) {
00247
00248 pLumiAux_ = &lb.aux();
00249
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
00257 pRunAux_ = &r.aux();
00258
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));
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
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
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
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
00384
00385
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
00393 filePtr_->Close();
00394 filePtr_.reset();
00395
00396
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
00434 insertAncestors(*info, iMapper, oToFill);
00435 }
00436 }
00437 }
00438 }
00439 }