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 std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
00578 for(ProductList::iterator it = pList.begin(); it != pList.end();) {
00579 if(branchesWithStoredHistory_.find(it->second.branchID()) == end) {
00580
00581 ProductList::iterator itCopy = it;
00582 ++it;
00583 pList.erase(itCopy);
00584
00585 } else {
00586 ++it;
00587 }
00588 }
00589
00590 ProductRegistry* ppReg = &pReg;
00591 TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
00592 assert(b);
00593 b->Fill();
00594 }
00595 void RootOutputFile::writeProductDependencies() {
00596 BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
00597 BranchChildren* ppDeps = &pDeps;
00598 TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
00599 assert(b);
00600 b->Fill();
00601 }
00602
00603 void RootOutputFile::finishEndFile() {
00604 metaDataTree_->SetEntries(-1);
00605 RootOutputTree::writeTTree(metaDataTree_);
00606 RootOutputTree::writeTTree(parameterSetsTree_);
00607
00608 RootOutputTree::writeTTree(parentageTree_);
00609
00610
00611
00612
00613 for(int i = InEvent; i < NumBranchTypes; ++i) {
00614 BranchType branchType = static_cast<BranchType>(i);
00615 setBranchAliases(treePointers_[branchType]->tree(), om_->keptProducts()[branchType]);
00616 treePointers_[branchType]->writeTree();
00617 }
00618
00619
00620
00621 metaDataTree_ = parentageTree_ = 0;
00622 for(RootOutputTreePtrArray::iterator it = treePointers_.begin(), itEnd = treePointers_.end(); it != itEnd; ++it) {
00623 (*it)->close();
00624 (*it) = 0;
00625 }
00626 filePtr_->Close();
00627 filePtr_.reset();
00628
00629
00630 Service<JobReport> reportSvc;
00631 reportSvc->outputFileClosed(reportToken_);
00632
00633 }
00634
00635 void
00636 RootOutputFile::setBranchAliases(TTree* tree, Selections const& branches) const {
00637 if(tree && tree->GetNbranches() != 0) {
00638 for(Selections::const_iterator i = branches.begin(), iEnd = branches.end();
00639 i != iEnd; ++i) {
00640 BranchDescription const& pd = **i;
00641 std::string const& full = pd.branchName() + "obj";
00642 if(pd.branchAliases().empty()) {
00643 std::string const& alias =
00644 (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
00645 tree->SetAlias(alias.c_str(), full.c_str());
00646 } else {
00647 std::set<std::string>::const_iterator it = pd.branchAliases().begin(), itEnd = pd.branchAliases().end();
00648 for(; it != itEnd; ++it) {
00649 tree->SetAlias((*it).c_str(), full.c_str());
00650 }
00651 }
00652 }
00653 }
00654 }
00655
00656 void
00657 RootOutputFile::insertAncestors(ProductProvenance const& iGetParents,
00658 EventPrincipal const& principal,
00659 bool produced,
00660 std::set<StoredProductProvenance>& oToFill) {
00661 assert(om_->dropMetaData() != PoolOutputModule::DropAll);
00662 assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
00663 if(om_->dropMetaData() == PoolOutputModule::DropDroppedPrior && !produced) return;
00664 BranchMapper const& iMapper = *principal.branchMapperPtr();
00665 std::vector<BranchID> const& parentIDs = iGetParents.parentage().parents();
00666 for(std::vector<BranchID>::const_iterator it = parentIDs.begin(), itEnd = parentIDs.end();
00667 it != itEnd; ++it) {
00668 branchesWithStoredHistory_.insert(*it);
00669 ProductProvenance const* info = iMapper.branchIDToProvenance(*it);
00670 if(info) {
00671 if(om_->dropMetaData() == PoolOutputModule::DropNone ||
00672 principal.getProvenance(info->branchID()).product().produced()) {
00673 if(insertProductProvenance(*info,oToFill) ) {
00674
00675 insertAncestors(*info, principal, produced, oToFill);
00676 }
00677 }
00678 }
00679 }
00680 }
00681
00682 void RootOutputFile::fillBranches(
00683 BranchType const& branchType,
00684 Principal const& principal,
00685 StoredProductProvenanceVector* productProvenanceVecPtr) {
00686
00687 typedef std::vector<std::pair<TClass*, void const*> > Dummies;
00688 Dummies dummies;
00689
00690 bool const fastCloning = (branchType == InEvent) && (whyNotFastClonable_ == FileBlock::CanFastClone);
00691
00692 OutputItemList const& items = om_->selectedOutputItemList()[branchType];
00693
00694 std::set<StoredProductProvenance> provenanceToKeep;
00695
00696
00697 for(OutputItemList::const_iterator i = items.begin(), iEnd = items.end(); i != iEnd; ++i) {
00698
00699 BranchID const& id = i->branchDescription_->branchID();
00700 branchesWithStoredHistory_.insert(id);
00701 if(i->branchDescription_->isAlias()) {
00702
00703 branchesWithStoredHistory_.insert(i->branchDescription_->originalBranchID());
00704 }
00705
00706 bool produced = i->branchDescription_->produced();
00707 bool keepProvenance = productProvenanceVecPtr != 0 &&
00708 (om_->dropMetaData() == PoolOutputModule::DropNone ||
00709 om_->dropMetaData() == PoolOutputModule::DropDroppedPrior ||
00710 (om_->dropMetaData() == PoolOutputModule::DropPrior && produced));
00711 bool getProd = (produced || !fastCloning ||
00712 treePointers_[branchType]->uncloned(i->branchDescription_->branchName()));
00713
00714 void const* product = 0;
00715 OutputHandle const oh = principal.getForOutput(id, getProd);
00716 if(keepProvenance && oh.productProvenance()) {
00717 insertProductProvenance(*oh.productProvenance(),provenanceToKeep);
00718
00719 EventPrincipal const& eventPrincipal = dynamic_cast<EventPrincipal const&>(principal);
00720 assert(eventPrincipal.branchMapperPtr());
00721 insertAncestors(*oh.productProvenance(), eventPrincipal, produced, provenanceToKeep);
00722 }
00723 product = oh.wrapper();
00724 if(getProd) {
00725 if(product == 0) {
00726
00727
00728 TClass* cp = gROOT->GetClass(i->branchDescription_->wrappedName().c_str());
00729 product = cp->New();
00730 dummies.emplace_back(cp, product);
00731 }
00732 i->product_ = product;
00733 }
00734 }
00735
00736 if(productProvenanceVecPtr != 0) productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
00737 treePointers_[branchType]->fillTree();
00738 if(productProvenanceVecPtr != 0) productProvenanceVecPtr->clear();
00739 for(Dummies::iterator it = dummies.begin(), itEnd = dummies.end(); it != itEnd; ++it) {
00740 it->first->Destructor(const_cast<void *>(it->second));
00741 }
00742 }
00743
00744 bool
00745 RootOutputFile::insertProductProvenance(const edm::ProductProvenance& iProv,
00746 std::set<edm::StoredProductProvenance>& oToInsert) {
00747 StoredProductProvenance toStore;
00748 toStore.branchID_ = iProv.branchID().id();
00749 std::set<edm::StoredProductProvenance>::iterator itFound = oToInsert.find(toStore);
00750 if(itFound == oToInsert.end()) {
00751
00752 std::pair<std::map<edm::ParentageID,unsigned int>::iterator,bool> i = parentageIDs_.insert(std::make_pair(iProv.parentageID(),static_cast<unsigned int>(parentageIDs_.size())));
00753 toStore.parentageIDIndex_ = i.first->second;
00754 if(toStore.parentageIDIndex_ >= parentageIDs_.size()) {
00755 throw edm::Exception(errors::LogicError)
00756 << "RootOutputFile::insertProductProvenance\n"
00757 << "The parentage ID index value " << toStore.parentageIDIndex_ << " is out of bounds. The maximum value is currently " << parentageIDs_.size()-1 << ".\n"
00758 << "This should never happen.\n"
00759 << "Please report this to the framework hypernews forum 'hn-cms-edmFramework@cern.ch'.\n";
00760 }
00761
00762 oToInsert.insert(toStore);
00763 return true;
00764 }
00765 return false;
00766 }
00767 }