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