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