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 "FWCore/Version/interface/GetFileFormatVersion.h"
00008 #include "DataFormats/Provenance/interface/FileFormatVersion.h"
00009 #include "FWCore/Utilities/interface/EDMException.h"
00010 #include "FWCore/Utilities/interface/Algorithms.h"
00011 #include "FWCore/Utilities/interface/Digest.h"
00012 #include "FWCore/Framework/interface/FileBlock.h"
00013 #include "FWCore/Framework/interface/EventPrincipal.h"
00014 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00015 #include "FWCore/Framework/interface/RunPrincipal.h"
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 #include "DataFormats/Common/interface/OutputHandle.h"
00018 #include "DataFormats/Provenance/interface/BranchChildren.h"
00019 #include "DataFormats/Provenance/interface/BranchIDList.h"
00020 #include "DataFormats/Provenance/interface/Parentage.h"
00021 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
00022 #include "DataFormats/Provenance/interface/EventID.h"
00023 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00024 #include "DataFormats/Provenance/interface/ParameterSetID.h"
00025 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00026 #include "DataFormats/Provenance/interface/ProcessHistoryID.h"
00027 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00028 #include "FWCore/Framework/interface/ConstProductRegistry.h"
00029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00030 #include "FWCore/ParameterSet/interface/Registry.h"
00031 #include "FWCore/ServiceRegistry/interface/Service.h"
00032
00033 #include "TROOT.h"
00034 #include "TTree.h"
00035 #include "TFile.h"
00036 #include "TClass.h"
00037 #include "Rtypes.h"
00038 #include "RVersion.h"
00039
00040 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
00041 #include "Compression.h"
00042 #endif
00043
00044 #include <algorithm>
00045 #include <iomanip>
00046 #include <sstream>
00047
00048 namespace edm {
00049
00050 namespace {
00051 bool
00052 sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
00053 return
00054 lh->fullClassName() < rh->fullClassName() ? true :
00055 lh->fullClassName() > rh->fullClassName() ? false :
00056 lh->moduleLabel() < rh->moduleLabel() ? true :
00057 lh->moduleLabel() > rh->moduleLabel() ? false :
00058 lh->productInstanceName() < rh->productInstanceName() ? true :
00059 lh->productInstanceName() > rh->productInstanceName() ? false :
00060 lh->processName() < rh->processName() ? true :
00061 false;
00062 }
00063 }
00064
00065 RootOutputFile::RootOutputFile(PoolOutputModule* om, std::string const& fileName, std::string const& logicalFileName) :
00066 file_(fileName),
00067 logicalFile_(logicalFileName),
00068 reportToken_(0),
00069 om_(om),
00070 whyNotFastClonable_(om_->whyNotFastClonable()),
00071 canFastCloneAux_(false),
00072 filePtr_(TFile::Open(file_.c_str(), "recreate", "", om_->compressionLevel())),
00073 fid_(),
00074 eventEntryNumber_(0LL),
00075 lumiEntryNumber_(0LL),
00076 runEntryNumber_(0LL),
00077 indexIntoFile_(),
00078 metaDataTree_(0),
00079 parameterSetsTree_(0),
00080 parentageTree_(0),
00081 lumiAux_(),
00082 runAux_(),
00083 pEventAux_(0),
00084 pLumiAux_(&lumiAux_),
00085 pRunAux_(&runAux_),
00086 eventEntryInfoVector_(),
00087 pEventEntryInfoVector_(&eventEntryInfoVector_),
00088 pBranchListIndexes_(0),
00089 pEventSelectionIDs_(0),
00090 eventTree_(filePtr_, InEvent, om_->splitLevel(), om_->treeMaxVirtualSize()),
00091 lumiTree_(filePtr_, InLumi, om_->splitLevel(), om_->treeMaxVirtualSize()),
00092 runTree_(filePtr_, InRun, om_->splitLevel(), om_->treeMaxVirtualSize()),
00093 treePointers_(),
00094 dataTypeReported_(false),
00095 parentageIDs_(),
00096 branchesWithStoredHistory_() {
00097 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
00098 if (om_->compressionAlgorithm() == std::string("ZLIB")) {
00099 filePtr_->SetCompressionAlgorithm(ROOT::kZLIB);
00100 } else if (om_->compressionAlgorithm() == std::string("LZMA")) {
00101 filePtr_->SetCompressionAlgorithm(ROOT::kLZMA);
00102 } else {
00103 throw Exception(errors::Configuration) << "PoolOutputModule configured with unknown compression algorithm '" << om_->compressionAlgorithm() << "'\n"
00104 << "Allowed compression algorithms are ZLIB and LZMA\n";
00105 }
00106 #endif
00107 if (-1 != om->eventAutoFlushSize()) {
00108 eventTree_.setAutoFlush(-1*om->eventAutoFlushSize());
00109 }
00110 eventTree_.addAuxiliary<EventAuxiliary>(BranchTypeToAuxiliaryBranchName(InEvent),
00111 pEventAux_, om_->auxItems()[InEvent].basketSize_);
00112 eventTree_.addAuxiliary<StoredProductProvenanceVector>(BranchTypeToProductProvenanceBranchName(InEvent),
00113 pEventEntryInfoVector_, om_->auxItems()[InEvent].basketSize_);
00114 eventTree_.addAuxiliary<EventSelectionIDVector>(poolNames::eventSelectionsBranchName(),
00115 pEventSelectionIDs_, om_->auxItems()[InEvent].basketSize_,false);
00116 eventTree_.addAuxiliary<BranchListIndexes>(poolNames::branchListIndexesBranchName(),
00117 pBranchListIndexes_, om_->auxItems()[InEvent].basketSize_);
00118
00119 lumiTree_.addAuxiliary<LuminosityBlockAuxiliary>(BranchTypeToAuxiliaryBranchName(InLumi),
00120 pLumiAux_, om_->auxItems()[InLumi].basketSize_);
00121
00122 runTree_.addAuxiliary<RunAuxiliary>(BranchTypeToAuxiliaryBranchName(InRun),
00123 pRunAux_, om_->auxItems()[InRun].basketSize_);
00124
00125 treePointers_[InEvent] = &eventTree_;
00126 treePointers_[InLumi] = &lumiTree_;
00127 treePointers_[InRun] = &runTree_;
00128
00129 for(int i = InEvent; i < NumBranchTypes; ++i) {
00130 BranchType branchType = static_cast<BranchType>(i);
00131 RootOutputTree *theTree = treePointers_[branchType];
00132 for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[branchType].begin(),
00133 itEnd = om_->selectedOutputItemList()[branchType].end();
00134 it != itEnd; ++it) {
00135 it->product_ = 0;
00136 BranchDescription const& desc = *it->branchDescription_;
00137 desc.init();
00138 theTree->addBranch(desc.branchName(),
00139 desc.wrappedName(),
00140 desc.getInterface(),
00141 it->product_,
00142 it->splitLevel_,
00143 it->basketSize_,
00144 it->branchDescription_->produced());
00145
00146 branchesWithStoredHistory_.insert(it->branchID());
00147 }
00148 }
00149
00150 metaDataTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::metaDataTreeName(), 0);
00151 parentageTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::parentageTreeName(), 0);
00152 parameterSetsTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::parameterSetsTreeName(), 0);
00153
00154 fid_ = FileID(createGlobalIdentifier());
00155
00156
00157
00158
00159
00160
00161 std::vector<std::string> branchNames;
00162 std::vector<BranchDescription const*> branches;
00163 branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
00164 branches.reserve(om->selectedOutputItemList()[InEvent].size());
00165 for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[InEvent].begin(),
00166 itEnd = om_->selectedOutputItemList()[InEvent].end();
00167 it != itEnd; ++it) {
00168 branchNames.push_back(it->branchDescription_->branchName());
00169 branches.push_back(it->branchDescription_);
00170 }
00171
00172 sort_all(branches, sorterForJobReportHash);
00173
00174 std::ostringstream oss;
00175 char const underscore = '_';
00176 for(std::vector<BranchDescription const*>::const_iterator it = branches.begin(), itEnd = branches.end(); it != itEnd; ++it) {
00177 BranchDescription const& bd = **it;
00178 oss << bd.fullClassName() << underscore
00179 << bd.moduleLabel() << underscore
00180 << bd.productInstanceName() << underscore
00181 << bd.processName() << underscore;
00182 }
00183 std::string stringrep = oss.str();
00184 cms::Digest md5alg(stringrep);
00185
00186
00187
00188 std::string moduleName = "PoolOutputModule";
00189 Service<JobReport> reportSvc;
00190 reportToken_ = reportSvc->outputFileOpened(
00191 file_, logicalFile_,
00192 om_->catalog(),
00193 moduleName,
00194 om_->moduleLabel(),
00195 fid_.fid(),
00196 std::string(),
00197 md5alg.digest().toString(),
00198 branchNames);
00199 }
00200
00201 namespace {
00202 void
00203 maybeIssueWarning(int whyNotFastClonable, std::string const& ifileName, std::string const& ofileName) {
00204
00205
00206 if ((whyNotFastClonable &
00207 (FileBlock::DisabledInConfigFile | FileBlock::NoRootInputSource | FileBlock::NotProcessingEvents | FileBlock::NoEventsInFile)) != 0) {
00208 return;
00209 }
00210
00211
00212
00213
00214 bool isWarning = true;
00215 std::ostringstream message;
00216 message << "Fast copying of file " << ifileName << " to file " << ofileName << " is disabled because:\n";
00217 if((whyNotFastClonable & FileBlock::HasSecondaryFileSequence) != 0) {
00218 message << "a SecondaryFileSequence was specified.\n";
00219 whyNotFastClonable &= ~(FileBlock::HasSecondaryFileSequence);
00220 isWarning = false;
00221 }
00222 if((whyNotFastClonable & FileBlock::FileTooOld) != 0) {
00223 message << "the input file is in an old format.\n";
00224 whyNotFastClonable &= ~(FileBlock::FileTooOld);
00225 isWarning = false;
00226 }
00227 if((whyNotFastClonable & FileBlock::EventsToBeSorted) != 0) {
00228 message << "events need to be sorted.\n";
00229 whyNotFastClonable &= ~(FileBlock::EventsToBeSorted);
00230 }
00231 if((whyNotFastClonable & FileBlock::RunOrLumiNotContiguous) != 0) {
00232 message << "a run or a lumi is not contiguous in the input file.\n";
00233 whyNotFastClonable &= ~(FileBlock::RunOrLumiNotContiguous);
00234 }
00235 if((whyNotFastClonable & FileBlock::EventsOrLumisSelectedByID) != 0) {
00236 message << "events or lumis were selected or skipped by ID.\n";
00237 whyNotFastClonable &= ~(FileBlock::EventsOrLumisSelectedByID);
00238 isWarning = false;
00239 }
00240 if((whyNotFastClonable & FileBlock::InitialEventsSkipped) != 0) {
00241 message << "initial events, lumis or runs were skipped.\n";
00242 whyNotFastClonable &= ~(FileBlock::InitialEventsSkipped);
00243 isWarning = false;
00244 }
00245 if((whyNotFastClonable & FileBlock::DuplicateEventsRemoved) != 0) {
00246 message << "some events were skipped because of duplicate checking.\n";
00247 whyNotFastClonable &= ~(FileBlock::DuplicateEventsRemoved);
00248 }
00249 if((whyNotFastClonable & FileBlock::MaxEventsTooSmall) != 0) {
00250 message << "some events were not copied because of maxEvents limit.\n";
00251 whyNotFastClonable &= ~(FileBlock::MaxEventsTooSmall);
00252 isWarning = false;
00253 }
00254 if((whyNotFastClonable & FileBlock::MaxLumisTooSmall) != 0) {
00255 message << "some events were not copied because of maxLumis limit.\n";
00256 whyNotFastClonable &= ~(FileBlock::MaxLumisTooSmall);
00257 isWarning = false;
00258 }
00259 if((whyNotFastClonable & FileBlock::ParallelProcesses) != 0) {
00260 message << "parallel processing was specified.\n";
00261 whyNotFastClonable &= ~(FileBlock::ParallelProcesses);
00262 isWarning = false;
00263 }
00264 if((whyNotFastClonable & FileBlock::EventSelectionUsed) != 0) {
00265 message << "an EventSelector was specified.\n";
00266 whyNotFastClonable &= ~(FileBlock::EventSelectionUsed);
00267 isWarning = false;
00268 }
00269 if((whyNotFastClonable & FileBlock::OutputMaxEventsTooSmall) != 0) {
00270 message << "some events were not copied because of maxEvents output limit.\n";
00271 whyNotFastClonable &= ~(FileBlock::OutputMaxEventsTooSmall);
00272 isWarning = false;
00273 }
00274 if((whyNotFastClonable & FileBlock::SplitLevelMismatch) != 0) {
00275 message << "the split level or basket size of a branch or branches was modified.\n";
00276 whyNotFastClonable &= ~(FileBlock::SplitLevelMismatch);
00277 }
00278 if((whyNotFastClonable & FileBlock::BranchMismatch) != 0) {
00279 message << "The format of a data product has changed.\n";
00280 whyNotFastClonable &= ~(FileBlock::BranchMismatch);
00281 }
00282 assert(whyNotFastClonable == FileBlock::CanFastClone);
00283 if (isWarning) {
00284 LogWarning("FastCloningDisabled") << message.str();
00285 } else {
00286 LogInfo("FastCloningDisabled") << message.str();
00287 }
00288 }
00289 }
00290
00291 void RootOutputFile::beginInputFile(FileBlock const& fb, int remainingEvents) {
00292
00293
00294 whyNotFastClonable_ = om_->whyNotFastClonable();
00295 canFastCloneAux_ = false;
00296
00297 if(fb.tree() != 0) {
00298
00299 whyNotFastClonable_ |= fb.whyNotFastClonable();
00300
00301 if(remainingEvents >= 0 && remainingEvents < fb.tree()->GetEntries()) {
00302 whyNotFastClonable_ |= FileBlock::OutputMaxEventsTooSmall;
00303 }
00304
00305 bool match = eventTree_.checkSplitLevelsAndBasketSizes(fb.tree());
00306 if(!match) {
00307 if(om_->overrideInputFileSplitLevels()) {
00308
00309
00310 whyNotFastClonable_ |= FileBlock::SplitLevelMismatch;
00311 } else {
00312
00313
00314
00315
00316 assert(om_->inputFileCount() > 1);
00317 throw Exception(errors::MismatchedInputFiles, "RootOutputFile::beginInputFile()") <<
00318 "Merge failure because input file " << file_ << " has different ROOT split levels or basket sizes\n" <<
00319 "than previous files. To allow merging in splite of this, use the configuration parameter\n" <<
00320 "overrideInputFileSplitLevels=cms.untracked.bool(True)\n" <<
00321 "in every PoolOutputModule.\n";
00322 }
00323 }
00324
00325
00326 if(whyNotFastClonable_ == FileBlock::CanFastClone) {
00327 if(!eventTree_.checkIfFastClonable(fb.tree())) {
00328 whyNotFastClonable_ |= FileBlock::BranchMismatch;
00329 }
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 Service<JobReport> reportSvc;
00359 reportSvc->reportFastCopyingStatus(reportToken_, fb.fileName(), whyNotFastClonable_ == FileBlock::CanFastClone);
00360 } else {
00361 whyNotFastClonable_ |= FileBlock::NoRootInputSource;
00362 }
00363
00364 eventTree_.maybeFastCloneTree(whyNotFastClonable_ == FileBlock::CanFastClone, canFastCloneAux_, fb.tree(), om_->basketOrder());
00365
00366
00367 if(fb.tree() != 0 && whyNotFastClonable_ != FileBlock::CanFastClone) {
00368 maybeIssueWarning(whyNotFastClonable_, fb.fileName(), file_);
00369 }
00370 }
00371
00372 void RootOutputFile::respondToCloseInputFile(FileBlock const&) {
00373 eventTree_.setEntries();
00374 lumiTree_.setEntries();
00375 runTree_.setEntries();
00376 }
00377
00378 bool RootOutputFile::shouldWeCloseFile() const {
00379 unsigned int const oneK = 1024;
00380 Long64_t size = filePtr_->GetSize()/oneK;
00381 return(size >= om_->maxFileSize());
00382 }
00383
00384 void RootOutputFile::writeOne(EventPrincipal const& e) {
00385
00386 pEventAux_ = &e.aux();
00387
00388
00389
00390
00391
00392 assert(pEventAux_->processHistoryID() == e.processHistoryID());
00393 pBranchListIndexes_ = &e.branchListIndexes();
00394
00395
00396
00397
00398 Service<ConstProductRegistry> reg;
00399 EventSelectionIDVector esids = e.eventSelectionIDs();
00400 if (reg->anyProductProduced() || !om_->wantAllEvents()) {
00401 esids.push_back(om_->selectorConfig());
00402 }
00403 pEventSelectionIDs_ = &esids;
00404 fillBranches(InEvent, e, pEventEntryInfoVector_);
00405
00406
00407 if(!dataTypeReported_) {
00408 Service<JobReport> reportSvc;
00409 std::string dataType("MC");
00410 if(pEventAux_->isRealData()) dataType = "Data";
00411 reportSvc->reportDataType(reportToken_, dataType);
00412 dataTypeReported_ = true;
00413 }
00414
00415
00416 ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(e.processHistoryID());
00417
00418 indexIntoFile_.addEntry(reducedPHID, pEventAux_->run(), pEventAux_->luminosityBlock(), pEventAux_->event(), eventEntryNumber_);
00419 ++eventEntryNumber_;
00420
00421
00422 Service<JobReport> reportSvc;
00423 reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
00424 }
00425
00426 void RootOutputFile::writeLuminosityBlock(LuminosityBlockPrincipal const& lb) {
00427
00428
00429 lumiAux_ = lb.aux();
00430
00431 lumiAux_.setProcessHistoryID(lb.processHistoryID());
00432
00433 ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(lb.processHistoryID());
00434
00435 indexIntoFile_.addEntry(reducedPHID, lumiAux_.run(), lumiAux_.luminosityBlock(), 0U, lumiEntryNumber_);
00436 ++lumiEntryNumber_;
00437 fillBranches(InLumi, lb, 0);
00438 lumiTree_.optimizeBaskets(10ULL*1024*1024);
00439 }
00440
00441 void RootOutputFile::writeRun(RunPrincipal const& r) {
00442
00443
00444 runAux_ = r.aux();
00445
00446 runAux_.setProcessHistoryID(r.processHistoryID());
00447
00448 ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(r.processHistoryID());
00449
00450 indexIntoFile_.addEntry(reducedPHID, runAux_.run(), 0U, 0U, runEntryNumber_);
00451 ++runEntryNumber_;
00452 fillBranches(InRun, r, 0);
00453 runTree_.optimizeBaskets(10ULL*1024*1024);
00454 }
00455
00456 void RootOutputFile::writeParentageRegistry() {
00457 Parentage const* desc(0);
00458
00459 if(!parentageTree_->Branch(poolNames::parentageBranchName().c_str(),
00460 &desc, om_->basketSize(), 0))
00461 throw Exception(errors::FatalRootError)
00462 << "Failed to create a branch for Parentages in the output file";
00463
00464
00465
00466 ParentageRegistry& ptReg = *ParentageRegistry::instance();
00467 ptReg.insertMapped(Parentage());
00468
00469 std::vector<ParentageID> orderedIDs(parentageIDs_.size());
00470 for(std::map<ParentageID,unsigned int>::const_iterator it = parentageIDs_.begin(),
00471 itEnd = parentageIDs_.end();
00472 it != itEnd;
00473 ++it) {
00474 orderedIDs[it->second]=it->first;
00475 }
00476
00477 for(std::vector<ParentageID>::const_iterator it = orderedIDs.begin(),
00478 itEnd = orderedIDs.end();
00479 it != itEnd;
00480 ++it) {
00481 desc = ptReg.getMapped(*it);
00482
00483
00484
00485 parentageTree_->Fill();
00486 }
00487 }
00488
00489 void RootOutputFile::writeFileFormatVersion() {
00490 FileFormatVersion fileFormatVersion(getFileFormatVersion());
00491 FileFormatVersion* pFileFmtVsn = &fileFormatVersion;
00492 TBranch* b = metaDataTree_->Branch(poolNames::fileFormatVersionBranchName().c_str(), &pFileFmtVsn, om_->basketSize(), 0);
00493 assert(b);
00494 b->Fill();
00495 }
00496
00497 void RootOutputFile::writeFileIdentifier() {
00498 FileID* fidPtr = &fid_;
00499 TBranch* b = metaDataTree_->Branch(poolNames::fileIdentifierBranchName().c_str(), &fidPtr, om_->basketSize(), 0);
00500 assert(b);
00501 b->Fill();
00502 }
00503
00504 void RootOutputFile::writeIndexIntoFile() {
00505 if (eventTree_.checkEntriesInReadBranches(eventEntryNumber_) == false) {
00506 Exception ex(errors::OtherCMS);
00507 ex << "The number of entries in at least one output TBranch whose entries\n"
00508 "were copied from the input does not match the number of events\n"
00509 "recorded in IndexIntoFile. This might (or might not) indicate a\n"
00510 "problem related to fast copy.";
00511 ex.addContext("Calling RootOutputFile::writeIndexIntoFile");
00512 throw ex;
00513 }
00514 indexIntoFile_.sortVector_Run_Or_Lumi_Entries();
00515 IndexIntoFile* iifPtr = &indexIntoFile_;
00516 TBranch* b = metaDataTree_->Branch(poolNames::indexIntoFileBranchName().c_str(), &iifPtr, om_->basketSize(), 0);
00517 assert(b);
00518 b->Fill();
00519 }
00520
00521 void RootOutputFile::writeProcessConfigurationRegistry() {
00522 typedef ProcessConfigurationRegistry::collection_type Map;
00523 Map const& procConfigMap = ProcessConfigurationRegistry::instance()->data();
00524 ProcessConfigurationVector procConfigVector;
00525 for(Map::const_iterator i = procConfigMap.begin(), e = procConfigMap.end(); i != e; ++i) {
00526 procConfigVector.push_back(i->second);
00527 }
00528 sort_all(procConfigVector);
00529 ProcessConfigurationVector* p = &procConfigVector;
00530 TBranch* b = metaDataTree_->Branch(poolNames::processConfigurationBranchName().c_str(), &p, om_->basketSize(), 0);
00531 assert(b);
00532 b->Fill();
00533 }
00534
00535 void RootOutputFile::writeProcessHistoryRegistry() {
00536 typedef ProcessHistoryRegistry::collection_type Map;
00537 Map const& procHistoryMap = ProcessHistoryRegistry::instance()->data();
00538 ProcessHistoryVector procHistoryVector;
00539 for(Map::const_iterator i = procHistoryMap.begin(), e = procHistoryMap.end(); i != e; ++i) {
00540 procHistoryVector.push_back(i->second);
00541 }
00542 ProcessHistoryVector* p = &procHistoryVector;
00543 TBranch* b = metaDataTree_->Branch(poolNames::processHistoryBranchName().c_str(), &p, om_->basketSize(), 0);
00544 assert(b);
00545 b->Fill();
00546 }
00547
00548 void RootOutputFile::writeBranchIDListRegistry() {
00549 BranchIDLists const* p = om_->branchIDLists();
00550 TBranch* b = metaDataTree_->Branch(poolNames::branchIDListBranchName().c_str(), &p, om_->basketSize(), 0);
00551 assert(b);
00552 b->Fill();
00553 }
00554
00555 void RootOutputFile::writeParameterSetRegistry() {
00556 std::pair<ParameterSetID, ParameterSetBlob> idToBlob;
00557 std::pair<ParameterSetID, ParameterSetBlob>* pIdToBlob = &idToBlob;
00558 TBranch* b = parameterSetsTree_->Branch(poolNames::idToParameterSetBlobsBranchName().c_str(),&pIdToBlob,om_->basketSize(), 0);
00559
00560 for(pset::Registry::const_iterator it = pset::Registry::instance()->begin(),
00561 itEnd = pset::Registry::instance()->end();
00562 it != itEnd;
00563 ++it) {
00564 idToBlob.first = it->first;
00565 idToBlob.second.pset() = it->second.toString();
00566
00567 b->Fill();
00568 }
00569 }
00570
00571 void RootOutputFile::writeProductDescriptionRegistry() {
00572
00573 typedef ProductRegistry::ProductList ProductList;
00574 Service<ConstProductRegistry> reg;
00575 ProductRegistry pReg(reg->productList());
00576 ProductList& pList = const_cast<ProductList &>(pReg.productList());
00577 for(auto const& prod : pList) {
00578 if(prod.second.branchID() != prod.second.originalBranchID()) {
00579 if(branchesWithStoredHistory_.find(prod.second.branchID()) != branchesWithStoredHistory_.end()) {
00580 branchesWithStoredHistory_.insert(prod.second.originalBranchID());
00581 }
00582 }
00583 }
00584 std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
00585 for(ProductList::iterator it = pList.begin(); it != pList.end();) {
00586 if(branchesWithStoredHistory_.find(it->second.branchID()) == end) {
00587
00588 ProductList::iterator itCopy = it;
00589 ++it;
00590 pList.erase(itCopy);
00591
00592 } else {
00593 ++it;
00594 }
00595 }
00596
00597 ProductRegistry* ppReg = &pReg;
00598 TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
00599 assert(b);
00600 b->Fill();
00601 }
00602 void RootOutputFile::writeProductDependencies() {
00603 BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
00604 BranchChildren* ppDeps = &pDeps;
00605 TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
00606 assert(b);
00607 b->Fill();
00608 }
00609
00610 void RootOutputFile::finishEndFile() {
00611 metaDataTree_->SetEntries(-1);
00612 RootOutputTree::writeTTree(metaDataTree_);
00613 RootOutputTree::writeTTree(parameterSetsTree_);
00614
00615 RootOutputTree::writeTTree(parentageTree_);
00616
00617
00618
00619
00620 for(int i = InEvent; i < NumBranchTypes; ++i) {
00621 BranchType branchType = static_cast<BranchType>(i);
00622 setBranchAliases(treePointers_[branchType]->tree(), om_->keptProducts()[branchType]);
00623 treePointers_[branchType]->writeTree();
00624 }
00625
00626
00627
00628 metaDataTree_ = parentageTree_ = 0;
00629 for(RootOutputTreePtrArray::iterator it = treePointers_.begin(), itEnd = treePointers_.end(); it != itEnd; ++it) {
00630 (*it)->close();
00631 (*it) = 0;
00632 }
00633 filePtr_->Close();
00634 filePtr_.reset();
00635
00636
00637 Service<JobReport> reportSvc;
00638 reportSvc->outputFileClosed(reportToken_);
00639
00640 }
00641
00642 void
00643 RootOutputFile::setBranchAliases(TTree* tree, Selections const& branches) const {
00644 if(tree && tree->GetNbranches() != 0) {
00645 for(Selections::const_iterator i = branches.begin(), iEnd = branches.end();
00646 i != iEnd; ++i) {
00647 BranchDescription const& pd = **i;
00648 std::string const& full = pd.branchName() + "obj";
00649 if(pd.branchAliases().empty()) {
00650 std::string const& alias =
00651 (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
00652 tree->SetAlias(alias.c_str(), full.c_str());
00653 } else {
00654 std::set<std::string>::const_iterator it = pd.branchAliases().begin(), itEnd = pd.branchAliases().end();
00655 for(; it != itEnd; ++it) {
00656 tree->SetAlias((*it).c_str(), full.c_str());
00657 }
00658 }
00659 }
00660 }
00661 }
00662
00663 void
00664 RootOutputFile::insertAncestors(ProductProvenance const& iGetParents,
00665 EventPrincipal const& principal,
00666 bool produced,
00667 std::set<StoredProductProvenance>& oToFill) {
00668 assert(om_->dropMetaData() != PoolOutputModule::DropAll);
00669 assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
00670 if(om_->dropMetaData() == PoolOutputModule::DropDroppedPrior && !produced) return;
00671 BranchMapper const& iMapper = *principal.branchMapperPtr();
00672 std::vector<BranchID> const& parentIDs = iGetParents.parentage().parents();
00673 for(std::vector<BranchID>::const_iterator it = parentIDs.begin(), itEnd = parentIDs.end();
00674 it != itEnd; ++it) {
00675 branchesWithStoredHistory_.insert(*it);
00676 ProductProvenance const* info = iMapper.branchIDToProvenance(*it);
00677 if(info) {
00678 if(om_->dropMetaData() == PoolOutputModule::DropNone ||
00679 principal.getProvenance(info->branchID()).product().produced()) {
00680 if(insertProductProvenance(*info,oToFill) ) {
00681
00682 insertAncestors(*info, principal, produced, oToFill);
00683 }
00684 }
00685 }
00686 }
00687 }
00688
00689 void RootOutputFile::fillBranches(
00690 BranchType const& branchType,
00691 Principal const& principal,
00692 StoredProductProvenanceVector* productProvenanceVecPtr) {
00693
00694 typedef std::vector<std::pair<TClass*, void const*> > Dummies;
00695 Dummies dummies;
00696
00697 bool const fastCloning = (branchType == InEvent) && (whyNotFastClonable_ == FileBlock::CanFastClone);
00698
00699 OutputItemList const& items = om_->selectedOutputItemList()[branchType];
00700
00701 std::set<StoredProductProvenance> provenanceToKeep;
00702
00703
00704 for(OutputItemList::const_iterator i = items.begin(), iEnd = items.end(); i != iEnd; ++i) {
00705
00706 BranchID const& id = i->branchDescription_->branchID();
00707 branchesWithStoredHistory_.insert(id);
00708
00709 bool produced = i->branchDescription_->produced();
00710 bool keepProvenance = productProvenanceVecPtr != 0 &&
00711 (om_->dropMetaData() == PoolOutputModule::DropNone ||
00712 om_->dropMetaData() == PoolOutputModule::DropDroppedPrior ||
00713 (om_->dropMetaData() == PoolOutputModule::DropPrior && produced));
00714 bool getProd = (produced || !fastCloning ||
00715 treePointers_[branchType]->uncloned(i->branchDescription_->branchName()));
00716
00717 void const* product = 0;
00718 OutputHandle const oh = principal.getForOutput(id, getProd);
00719 if(keepProvenance && oh.productProvenance()) {
00720 insertProductProvenance(*oh.productProvenance(),provenanceToKeep);
00721
00722 EventPrincipal const& eventPrincipal = dynamic_cast<EventPrincipal const&>(principal);
00723 assert(eventPrincipal.branchMapperPtr());
00724 insertAncestors(*oh.productProvenance(), eventPrincipal, produced, provenanceToKeep);
00725 }
00726 product = oh.wrapper();
00727 if(getProd) {
00728 if(product == 0) {
00729
00730
00731 TClass* cp = gROOT->GetClass(i->branchDescription_->wrappedName().c_str());
00732 product = cp->New();
00733 dummies.emplace_back(cp, product);
00734 }
00735 i->product_ = product;
00736 }
00737 }
00738
00739 if(productProvenanceVecPtr != 0) productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
00740 treePointers_[branchType]->fillTree();
00741 if(productProvenanceVecPtr != 0) productProvenanceVecPtr->clear();
00742 for(Dummies::iterator it = dummies.begin(), itEnd = dummies.end(); it != itEnd; ++it) {
00743 it->first->Destructor(const_cast<void *>(it->second));
00744 }
00745 }
00746
00747 bool
00748 RootOutputFile::insertProductProvenance(const edm::ProductProvenance& iProv,
00749 std::set<edm::StoredProductProvenance>& oToInsert) {
00750 StoredProductProvenance toStore;
00751 toStore.branchID_ = iProv.branchID().id();
00752 std::set<edm::StoredProductProvenance>::iterator itFound = oToInsert.find(toStore);
00753 if(itFound == oToInsert.end()) {
00754
00755 std::pair<std::map<edm::ParentageID,unsigned int>::iterator,bool> i = parentageIDs_.insert(std::make_pair(iProv.parentageID(),static_cast<unsigned int>(parentageIDs_.size())));
00756 toStore.parentageIDIndex_ = i.first->second;
00757 if(toStore.parentageIDIndex_ >= parentageIDs_.size()) {
00758 throw edm::Exception(errors::LogicError)
00759 << "RootOutputFile::insertProductProvenance\n"
00760 << "The parentage ID index value " << toStore.parentageIDIndex_ << " is out of bounds. The maximum value is currently " << parentageIDs_.size()-1 << ".\n"
00761 << "This should never happen.\n"
00762 << "Please report this to the framework hypernews forum 'hn-cms-edmFramework@cern.ch'.\n";
00763 }
00764
00765 oToInsert.insert(toStore);
00766 return true;
00767 }
00768 return false;
00769 }
00770 }