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