CMS 3D CMS Logo

RootOutputFile.cc
Go to the documentation of this file.
1 
3 
5 
6 
38 
39 #include "TTree.h"
40 #include "TFile.h"
41 #include "TClass.h"
42 #include "Rtypes.h"
43 #include "RVersion.h"
44 
45 #include "Compression.h"
46 
47 #include <algorithm>
48 #include <iomanip>
49 #include <sstream>
50 
51 namespace edm {
52 
53  namespace {
54  bool
55  sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
56  return
57  lh->fullClassName() < rh->fullClassName() ? true :
58  lh->fullClassName() > rh->fullClassName() ? false :
59  lh->moduleLabel() < rh->moduleLabel() ? true :
60  lh->moduleLabel() > rh->moduleLabel() ? false :
61  lh->productInstanceName() < rh->productInstanceName() ? true :
62  lh->productInstanceName() > rh->productInstanceName() ? false :
63  lh->processName() < rh->processName() ? true :
64  false;
65  }
66 
67  TFile*
68  openTFile(char const* name, int compressionLevel) {
69  TFile* file = TFile::Open(name, "recreate", "", compressionLevel);
70  std::exception_ptr e = edm::threadLocalException::getException();
71  if(e != std::exception_ptr()) {
72  edm::threadLocalException::setException(std::exception_ptr());
73  std::rethrow_exception(e);
74  }
75  return file;
76  }
77  }
78 
80  file_(fileName),
81  logicalFile_(logicalFileName),
82  reportToken_(0),
83  om_(om),
84  whyNotFastClonable_(om_->whyNotFastClonable()),
85  canFastCloneAux_(false),
86  filePtr_(openTFile(file_.c_str(), om_->compressionLevel())),
87  fid_(),
88  eventEntryNumber_(0LL),
89  lumiEntryNumber_(0LL),
90  runEntryNumber_(0LL),
91  indexIntoFile_(),
92  nEventsInLumi_(0),
93  metaDataTree_(nullptr),
94  parameterSetsTree_(nullptr),
95  parentageTree_(nullptr),
96  lumiAux_(),
97  runAux_(),
98  pEventAux_(nullptr),
99  pLumiAux_(&lumiAux_),
100  pRunAux_(&runAux_),
101  eventEntryInfoVector_(),
102  pEventEntryInfoVector_(&eventEntryInfoVector_),
103  pBranchListIndexes_(nullptr),
104  pEventSelectionIDs_(nullptr),
105  eventTree_(filePtr(), InEvent, om_->splitLevel(), om_->treeMaxVirtualSize()),
106  lumiTree_(filePtr(), InLumi, om_->splitLevel(), om_->treeMaxVirtualSize()),
107  runTree_(filePtr(), InRun, om_->splitLevel(), om_->treeMaxVirtualSize()),
108  treePointers_(),
109  dataTypeReported_(false),
110  processHistoryRegistry_(),
111  parentageIDs_(),
112  branchesWithStoredHistory_(),
113  wrapperBaseTClass_(TClass::GetClass("edm::WrapperBase")) {
114  if (om_->compressionAlgorithm() == std::string("ZLIB")) {
115  filePtr_->SetCompressionAlgorithm(ROOT::kZLIB);
116  } else if (om_->compressionAlgorithm() == std::string("LZMA")) {
117  filePtr_->SetCompressionAlgorithm(ROOT::kLZMA);
118  } else {
119  throw Exception(errors::Configuration) << "PoolOutputModule configured with unknown compression algorithm '" << om_->compressionAlgorithm() << "'\n"
120  << "Allowed compression algorithms are ZLIB and LZMA\n";
121  }
122  if (-1 != om->eventAutoFlushSize()) {
124  }
126  pEventAux_, om_->auxItems()[InEvent].basketSize_);
128  pEventEntryInfoVector(), om_->auxItems()[InEvent].basketSize_);
130  pEventSelectionIDs_, om_->auxItems()[InEvent].basketSize_,false);
132  pBranchListIndexes_, om_->auxItems()[InEvent].basketSize_);
133 
135  pLumiAux_, om_->auxItems()[InLumi].basketSize_);
136 
138  pRunAux_, om_->auxItems()[InRun].basketSize_);
139 
141  treePointers_[InLumi] = &lumiTree_;
142  treePointers_[InRun] = &runTree_;
143 
144  for(int i = InEvent; i < NumBranchTypes; ++i) {
145  BranchType branchType = static_cast<BranchType>(i);
146  RootOutputTree *theTree = treePointers_[branchType];
147  for(auto const& item : om_->selectedOutputItemList()[branchType]) {
148  item.product_ = nullptr;
149  BranchDescription const& desc = *item.branchDescription_;
150  theTree->addBranch(desc.branchName(),
151  desc.wrappedName(),
152  item.product_,
153  item.splitLevel_,
154  item.basketSize_,
155  item.branchDescription_->produced());
156  //make sure we always store product registry info for all branches we create
157  branchesWithStoredHistory_.insert(item.branchID());
158  }
159  }
160  // Don't split metadata tree or event description tree
164 
166 
167  // For the Job Report, get a vector of branch names in the "Events" tree.
168  // Also create a hash of all the branch names in the "Events" tree
169  // in a deterministic order, except use the full class name instead of the friendly class name.
170  // To avoid extra string copies, we create a vector of pointers into the product registry,
171  // and use a custom comparison operator for sorting.
172  std::vector<std::string> branchNames;
173  std::vector<BranchDescription const*> branches;
174  branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
175  branches.reserve(om->selectedOutputItemList()[InEvent].size());
176  for(auto const& item : om_->selectedOutputItemList()[InEvent]) {
177  branchNames.push_back(item.branchDescription_->branchName());
178  branches.push_back(item.branchDescription_);
179  }
180  // Now sort the branches for the hash.
181  sort_all(branches, sorterForJobReportHash);
182  // Now, make a concatenated string.
183  std::ostringstream oss;
184  char const underscore = '_';
185  for(auto const& branch : branches) {
186  BranchDescription const& bd = *branch;
187  oss << bd.fullClassName() << underscore
188  << bd.moduleLabel() << underscore
189  << bd.productInstanceName() << underscore
190  << bd.processName() << underscore;
191  }
192  std::string stringrep = oss.str();
193  cms::Digest md5alg(stringrep);
194 
195  // Register the output file with the JobReport service
196  // and get back the token for it.
197  std::string moduleName = "PoolOutputModule";
198  Service<JobReport> reportSvc;
199  reportToken_ = reportSvc->outputFileOpened(
200  file_, logicalFile_, // PFN and LFN
201  om_->catalog(), // catalog
202  moduleName, // module class name
203  om_->moduleLabel(), // module label
204  fid_.fid(), // file id (guid)
205  std::string(), // data type (not yet known, so string is empty).
206  md5alg.digest().toString(), // branch hash
207  branchNames); // branch names being written
208  }
209 
210  namespace {
211  void
212  maybeIssueWarning(int whyNotFastClonable, std::string const& ifileName, std::string const& ofileName) {
213 
214  // No message if fast cloning was deliberately disabled, or if there are no events to copy anyway.
215  if ((whyNotFastClonable &
217  return;
218  }
219 
220  // There will be a message stating every reason that fast cloning was not possible.
221  // If at one or more of the reasons was because of something the user explicitly specified (e.g. event selection, skipping events),
222  // or if the input file was in an old format, the message will be informational. Otherwise, the message will be a warning.
223  bool isWarning = true;
224  std::ostringstream message;
225  message << "Fast copying of file " << ifileName << " to file " << ofileName << " is disabled because:\n";
226  if((whyNotFastClonable & FileBlock::HasSecondaryFileSequence) != 0) {
227  message << "a SecondaryFileSequence was specified.\n";
228  whyNotFastClonable &= ~(FileBlock::HasSecondaryFileSequence);
229  isWarning = false;
230  }
231  if((whyNotFastClonable & FileBlock::FileTooOld) != 0) {
232  message << "the input file is in an old format.\n";
233  whyNotFastClonable &= ~(FileBlock::FileTooOld);
234  isWarning = false;
235  }
236  if((whyNotFastClonable & FileBlock::EventsToBeSorted) != 0) {
237  message << "events need to be sorted.\n";
238  whyNotFastClonable &= ~(FileBlock::EventsToBeSorted);
239  }
240  if((whyNotFastClonable & FileBlock::RunOrLumiNotContiguous) != 0) {
241  message << "a run or a lumi is not contiguous in the input file.\n";
242  whyNotFastClonable &= ~(FileBlock::RunOrLumiNotContiguous);
243  }
244  if((whyNotFastClonable & FileBlock::EventsOrLumisSelectedByID) != 0) {
245  message << "events or lumis were selected or skipped by ID.\n";
246  whyNotFastClonable &= ~(FileBlock::EventsOrLumisSelectedByID);
247  isWarning = false;
248  }
249  if((whyNotFastClonable & FileBlock::InitialEventsSkipped) != 0) {
250  message << "initial events, lumis or runs were skipped.\n";
251  whyNotFastClonable &= ~(FileBlock::InitialEventsSkipped);
252  isWarning = false;
253  }
254  if((whyNotFastClonable & FileBlock::DuplicateEventsRemoved) != 0) {
255  message << "some events were skipped because of duplicate checking.\n";
256  whyNotFastClonable &= ~(FileBlock::DuplicateEventsRemoved);
257  }
258  if((whyNotFastClonable & FileBlock::MaxEventsTooSmall) != 0) {
259  message << "some events were not copied because of maxEvents limit.\n";
260  whyNotFastClonable &= ~(FileBlock::MaxEventsTooSmall);
261  isWarning = false;
262  }
263  if((whyNotFastClonable & FileBlock::MaxLumisTooSmall) != 0) {
264  message << "some events were not copied because of maxLumis limit.\n";
265  whyNotFastClonable &= ~(FileBlock::MaxLumisTooSmall);
266  isWarning = false;
267  }
268  if((whyNotFastClonable & FileBlock::ParallelProcesses) != 0) {
269  message << "parallel processing was specified.\n";
270  whyNotFastClonable &= ~(FileBlock::ParallelProcesses);
271  isWarning = false;
272  }
273  if((whyNotFastClonable & FileBlock::EventSelectionUsed) != 0) {
274  message << "an EventSelector was specified.\n";
275  whyNotFastClonable &= ~(FileBlock::EventSelectionUsed);
276  isWarning = false;
277  }
278  if((whyNotFastClonable & FileBlock::OutputMaxEventsTooSmall) != 0) {
279  message << "some events were not copied because of maxEvents output limit.\n";
280  whyNotFastClonable &= ~(FileBlock::OutputMaxEventsTooSmall);
281  isWarning = false;
282  }
283  if((whyNotFastClonable & FileBlock::SplitLevelMismatch) != 0) {
284  message << "the split level or basket size of a branch or branches was modified.\n";
285  whyNotFastClonable &= ~(FileBlock::SplitLevelMismatch);
286  }
287  if((whyNotFastClonable & FileBlock::BranchMismatch) != 0) {
288  message << "The format of a data product has changed.\n";
289  whyNotFastClonable &= ~(FileBlock::BranchMismatch);
290  }
291  assert(whyNotFastClonable == FileBlock::CanFastClone);
292  if (isWarning) {
293  LogWarning("FastCloningDisabled") << message.str();
294  } else {
295  LogInfo("FastCloningDisabled") << message.str();
296  }
297  }
298  }
299 
300  void RootOutputFile::beginInputFile(FileBlock const& fb, int remainingEvents) {
301 
302  // Reset per input file information
303  whyNotFastClonable_ = om_->whyNotFastClonable();
304  canFastCloneAux_ = false;
305 
306  if(fb.tree() != nullptr) {
307 
309 
310  if(remainingEvents >= 0 && remainingEvents < fb.tree()->GetEntries()) {
312  }
313 
315  if(!match) {
316  if(om_->overrideInputFileSplitLevels()) {
317  // We may be fast copying. We must disable fast copying if the split levels
318  // or basket sizes do not match.
320  } else {
321  // We are using the input split levels and basket sizes from the first input file
322  // for copied output branches. In this case, we throw an exception if any branches
323  // have different split levels or basket sizes in a subsequent input file.
324  // If the mismatch is in the first file, there is a bug somewhere, so we assert.
325  assert(om_->inputFileCount() > 1);
326  throw Exception(errors::MismatchedInputFiles, "RootOutputFile::beginInputFile()") <<
327  "Merge failure because input file " << file_ << " has different ROOT split levels or basket sizes\n" <<
328  "than previous files. To allow merging in splite of this, use the configuration parameter\n" <<
329  "overrideInputFileSplitLevels=cms.untracked.bool(True)\n" <<
330  "in every PoolOutputModule.\n";
331  }
332  }
333 
334  // Since this check can be time consuming, we do it only if we would otherwise fast clone.
336  if(!eventTree_.checkIfFastClonable(fb.tree())) {
338  }
339  }
340  // We now check if we can fast copy the auxiliary branches.
341  // We can do so only if we can otherwise fast copy,
342  // the input file has the current format (these branches are in the Events Tree),
343  // there are no newly dropped or produced products,
344  // no metadata has been dropped,
345  // ID's have not been modified,
346  // and the branch list indexes do not need modification.
347 
348  // Note: Fast copy of the EventProductProvenance branch is unsafe
349  // unless we can enforce that the parentage information for a fully copied
350  // output file will be the same as for the input file, with nothing dropped.
351  // This has never been enforced, and, withthe EDAlias feature, it may no longer
352  // work by accident.
353  // So, for now, we do not enable fast cloning of the non-product branches.
354 /*
355  Service<ConstProductRegistry> reg;
356  canFastCloneAux_ = (whyNotFastClonable_ == FileBlock::CanFastClone) &&
357  fb.fileFormatVersion().noMetaDataTrees() &&
358  !om_->hasNewlyDroppedBranch()[InEvent] &&
359  !fb.hasNewlyDroppedBranch()[InEvent] &&
360  om_->dropMetaData() == PoolOutputModule::DropNone &&
361  !reg->anyProductProduced() &&
362  !fb.modifiedIDs() &&
363  fb.branchListIndexesUnchanged();
364 */
365 
366  // Report the fast copying status.
367  Service<JobReport> reportSvc;
368  reportSvc->reportFastCopyingStatus(reportToken_, fb.fileName(), whyNotFastClonable_ == FileBlock::CanFastClone);
369  } else {
371  }
372 
374 
375  // Possibly issue warning or informational message if we haven't fast cloned.
376  if(fb.tree() != nullptr && whyNotFastClonable_ != FileBlock::CanFastClone) {
377  maybeIssueWarning(whyNotFastClonable_, fb.fileName(), file_);
378  }
379  }
380 
385  }
386 
388  unsigned int const oneK = 1024;
389  Long64_t size = filePtr_->GetSize()/oneK;
390  return(size >= om_->maxFileSize());
391  }
392 
394  // Auxiliary branch
395  pEventAux_ = &e.eventAuxiliary();
396 
397  // Because getting the data may cause an exception to be thrown we want to do that
398  // first before writing anything to the file about this event
399  // NOTE: pEventAux_, pBranchListIndexes_, pEventSelectionIDs_, and pEventEntryInfoVector_
400  // must be set before calling fillBranches since they get written out in that routine.
401  assert(pEventAux_->processHistoryID() == e.processHistoryID());
403 
404  // Note: The EventSelectionIDVector should have a one to one correspondence with the processes in the process history.
405  // Therefore, a new entry should be added if and only if the current process has been added to the process history,
406  // which is done if and only if there is a produced product.
409  if (reg->anyProductProduced() || !om_->wantAllEvents()) {
410  esids.push_back(om_->selectorConfig());
411  }
412  pEventSelectionIDs_ = &esids;
414  assert(provRetriever);
415  fillBranches(InEvent, e, pEventEntryInfoVector_, provRetriever);
416 
417  // Add the dataType to the job report if it hasn't already been done
418  if(!dataTypeReported_) {
419  Service<JobReport> reportSvc;
420  std::string dataType("MC");
421  if(pEventAux_->isRealData()) dataType = "Data";
422  reportSvc->reportDataType(reportToken_, dataType);
423  dataTypeReported_ = true;
424  }
425 
426  // Store the process history.
428  // Store the reduced ID in the IndexIntoFile
430  // Add event to index
433 
434  // Report event written
435  Service<JobReport> reportSvc;
436  reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
437  ++nEventsInLumi_;
438  }
439 
441  // Auxiliary branch
442  // NOTE: lumiAux_ must be filled before calling fillBranches since it gets written out in that routine.
444  // Use the updated process historyID
446  // Store the process history.
448  // Store the reduced ID in the IndexIntoFile
450  // Add lumi to index.
453  fillBranches(InLumi, lb);
454  lumiTree_.optimizeBaskets(10ULL*1024*1024);
455 
456  Service<JobReport> reportSvc;
457  reportSvc->reportLumiSection(reportToken_, lb.id().run(), lb.id().luminosityBlock(),nEventsInLumi_);
458  nEventsInLumi_ = 0;
459  }
460 
462  // Auxiliary branch
463  // NOTE: runAux_ must be filled before calling fillBranches since it gets written out in that routine.
464  runAux_ = r.runAuxiliary();
465  // Use the updated process historyID
467  // Store the process history.
469  // Store the reduced ID in the IndexIntoFile
471  // Add run to index.
472  indexIntoFile_.addEntry(reducedPHID, runAux_.run(), 0U, 0U, runEntryNumber_);
473  ++runEntryNumber_;
474  fillBranches(InRun, r);
475  runTree_.optimizeBaskets(10ULL*1024*1024);
476 
477  Service<JobReport> reportSvc;
478  reportSvc->reportRunNumber(reportToken_, r.run());
479  }
480 
482  Parentage const* desc(nullptr);
483 
484  if(!parentageTree_->Branch(poolNames::parentageBranchName().c_str(),
485  &desc, om_->basketSize(), 0))
487  << "Failed to create a branch for Parentages in the output file";
488 
490 
491  std::vector<ParentageID> orderedIDs(parentageIDs_.size());
492  for(auto const& parentageID : parentageIDs_) {
493  orderedIDs[parentageID.second] = parentageID.first;
494  }
495  //now put them into the TTree in the correct order
496  for(auto const& orderedID : orderedIDs) {
497  desc = ptReg.getMapped(orderedID);
498  //NOTE: some old format files have missing Parentage info
499  // so a null value of desc can't be fatal.
500  // Root will default construct an object in that case.
501  parentageTree_->Fill();
502  }
503  }
504 
506  FileFormatVersion fileFormatVersion(getFileFormatVersion());
507  FileFormatVersion* pFileFmtVsn = &fileFormatVersion;
508  TBranch* b = metaDataTree_->Branch(poolNames::fileFormatVersionBranchName().c_str(), &pFileFmtVsn, om_->basketSize(), 0);
509  assert(b);
510  b->Fill();
511  }
512 
514  FileID* fidPtr = &fid_;
515  TBranch* b = metaDataTree_->Branch(poolNames::fileIdentifierBranchName().c_str(), &fidPtr, om_->basketSize(), 0);
516  assert(b);
517  b->Fill();
518  }
519 
523  ex << "The number of entries in at least one output TBranch whose entries\n"
524  "were copied from the input does not match the number of events\n"
525  "recorded in IndexIntoFile. This might (or might not) indicate a\n"
526  "problem related to fast copy.";
527  ex.addContext("Calling RootOutputFile::writeIndexIntoFile");
528  throw ex;
529  }
531  IndexIntoFile* iifPtr = &indexIntoFile_;
532  TBranch* b = metaDataTree_->Branch(poolNames::indexIntoFileBranchName().c_str(), &iifPtr, om_->basketSize(), 0);
533  assert(b);
534  b->Fill();
535  }
536 
539  }
540 
542  BranchIDLists const* p = om_->branchIDLists();
543  TBranch* b = metaDataTree_->Branch(poolNames::branchIDListBranchName().c_str(), &p, om_->basketSize(), 0);
544  assert(b);
545  b->Fill();
546  }
547 
549  ThinnedAssociationsHelper const* p = om_->thinnedAssociationsHelper();
550  TBranch* b = metaDataTree_->Branch(poolNames::thinnedAssociationsHelperBranchName().c_str(), &p, om_->basketSize(), 0);
551  assert(b);
552  b->Fill();
553  }
554 
557  }
558 
560  // Make a local copy of the ProductRegistry, removing any transient or pruned products.
561  typedef ProductRegistry::ProductList ProductList;
563  ProductRegistry pReg(reg->productList());
564  ProductList& pList = const_cast<ProductList &>(pReg.productList());
565  for(auto const& prod : pList) {
566  if(prod.second.branchID() != prod.second.originalBranchID()) {
567  if(branchesWithStoredHistory_.find(prod.second.branchID()) != branchesWithStoredHistory_.end()) {
568  branchesWithStoredHistory_.insert(prod.second.originalBranchID());
569  }
570  }
571  }
572  std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
573  for(ProductList::iterator it = pList.begin(); it != pList.end();) {
574  if(branchesWithStoredHistory_.find(it->second.branchID()) == end) {
575  // avoid invalidating iterator on deletion
576  ProductList::iterator itCopy = it;
577  ++it;
578  pList.erase(itCopy);
579 
580  } else {
581  ++it;
582  }
583  }
584 
585  ProductRegistry* ppReg = &pReg;
586  TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
587  assert(b);
588  b->Fill();
589  }
591  BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
592  BranchChildren* ppDeps = &pDeps;
593  TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
594  assert(b);
595  b->Fill();
596  }
597 
599  metaDataTree_->SetEntries(-1);
602 
604 
605  // Create branch aliases for all the branches in the
606  // events/lumis/runs trees. The loop is over all types of data
607  // products.
608  for(int i = InEvent; i < NumBranchTypes; ++i) {
609  BranchType branchType = static_cast<BranchType>(i);
610  setBranchAliases(treePointers_[branchType]->tree(), om_->keptProducts()[branchType]);
611  treePointers_[branchType]->writeTree();
612  }
613 
614  // close the file -- mfp
615  // Just to play it safe, zero all pointers to objects in the TFile to be closed.
616  metaDataTree_ = parentageTree_ = nullptr;
617  for(auto& treePointer : treePointers_) {
618  treePointer->close();
619  treePointer = nullptr;
620  }
621  filePtr_->Close();
622  filePtr_ = nullptr; // propagate_const<T> has no reset() function
623 
624  // report that file has been closed
625  Service<JobReport> reportSvc;
626  reportSvc->outputFileClosed(reportToken_);
627 
628  }
629 
630  void
631  RootOutputFile::setBranchAliases(TTree* tree, SelectedProducts const& branches) const {
632  if(tree && tree->GetNbranches() != 0) {
633  for(auto const& selection : branches) {
634  BranchDescription const& pd = *selection.first;
635  std::string const& full = pd.branchName() + "obj";
636  if(pd.branchAliases().empty()) {
637  std::string const& alias =
638  (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
639  tree->SetAlias(alias.c_str(), full.c_str());
640  } else {
641  for(auto const& alias : pd.branchAliases()) {
642  tree->SetAlias(alias.c_str(), full.c_str());
643  }
644  }
645  }
646  }
647  }
648 
649  void
651  ProductProvenanceRetriever const* iMapper,
652  bool produced,
653  std::set<BranchID> const &iProducedIDs,
654  std::set<StoredProductProvenance>& oToFill) {
655  assert(om_->dropMetaData() != PoolOutputModule::DropAll);
656  assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
657  if(om_->dropMetaData() == PoolOutputModule::DropDroppedPrior && !produced) return;
658  std::vector<BranchID> const& parentIDs = iGetParents.parentage().parents();
659  for(auto const& parentID : parentIDs) {
660  branchesWithStoredHistory_.insert(parentID);
661  ProductProvenance const* info = iMapper->branchIDToProvenance(parentID);
662  if(info) {
663  if(om_->dropMetaData() == PoolOutputModule::DropNone || (iProducedIDs.end() != iProducedIDs.find(info->branchID()) ) ) {
664  if(insertProductProvenance(*info,oToFill) ) {
665  //haven't seen this one yet
666  insertAncestors(*info, iMapper, produced, iProducedIDs, oToFill);
667  }
668  }
669  }
670  }
671  }
672 
674  BranchType const& branchType,
675  OccurrenceForOutput const& occurrence,
676  StoredProductProvenanceVector* productProvenanceVecPtr,
677  ProductProvenanceRetriever const* provRetriever) {
678 
679  std::vector<std::unique_ptr<WrapperBase> > dummies;
680 
681  OutputItemList const& items = om_->selectedOutputItemList()[branchType];
682 
683  bool const doProvenance = (productProvenanceVecPtr != nullptr) && (om_->dropMetaData() != PoolOutputModule::DropAll);
684  bool const keepProvenanceForPrior = doProvenance && om_->dropMetaData() != PoolOutputModule::DropPrior;
685 
686  bool const fastCloning = (branchType == InEvent) && (whyNotFastClonable_ == FileBlock::CanFastClone);
687  std::set<StoredProductProvenance> provenanceToKeep;
688  //
689  //If we are dropping some of the meta data we need to know
690  // which BranchIDs were produced in this process because
691  // we may be storing meta data for only those products
692  // We do this only for event products.
693  std::set<BranchID> producedBranches;
694  if(doProvenance && branchType == InEvent && om_->dropMetaData() != PoolOutputModule::DropNone) {
696  for(auto bd : preg->allBranchDescriptions()) {
697  if(bd->produced() && bd->branchType() == InEvent) {
698  producedBranches.insert(bd->branchID());
699  }
700  }
701  }
702 
703  // Loop over EDProduct branches, possibly fill the provenance, and write the branch.
704  for(auto const& item : items) {
705 
706  BranchID const& id = item.branchDescription_->branchID();
707  branchesWithStoredHistory_.insert(id);
708 
709  bool produced = item.branchDescription_->produced();
710  bool getProd = (produced || !fastCloning || treePointers_[branchType]->uncloned(item.branchDescription_->branchName()));
711  bool keepProvenance = doProvenance && (produced || keepProvenanceForPrior);
712 
713  WrapperBase const* product = nullptr;
714  ProductProvenance const* productProvenance = nullptr;
716  if(getProd) {
717  bool found = occurrence.getByToken(item.token_, item.branchDescription_->unwrappedTypeID(), result);
718  product = result.wrapper();
719  if(found && keepProvenance) {
720  productProvenance = result.provenance()->productProvenance();
721  }
722  if(product == nullptr) {
723  // No product with this ID is in the event.
724  // Add a null product.
725  TClass* cp = item.branchDescription_->wrappedType().getClass();
726  assert(cp != nullptr);
727  int offset = cp->GetBaseClassOffset(wrapperBaseTClass_);
728  void* p = cp->New();
729  std::unique_ptr<WrapperBase> dummy = getWrapperBasePtr(p, offset);
730  product = dummy.get();
731  dummies.emplace_back(std::move(dummy));
732  }
733  item.product_ = product;
734  }
735  if (keepProvenance && productProvenance == nullptr) {
736  productProvenance = provRetriever->branchIDToProvenance(item.branchDescription_->originalBranchID());
737  }
738  if(productProvenance) {
739  insertProductProvenance(*productProvenance,provenanceToKeep);
740  insertAncestors(*productProvenance, provRetriever, produced, producedBranches, provenanceToKeep);
741  }
742  }
743 
744  if(doProvenance) productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
745  treePointers_[branchType]->fillTree();
746  if(doProvenance) productProvenanceVecPtr->clear();
747  }
748 
749  bool
751  std::set<edm::StoredProductProvenance>& oToInsert) {
752  StoredProductProvenance toStore;
753  toStore.branchID_ = iProv.branchID().id();
754  std::set<edm::StoredProductProvenance>::iterator itFound = oToInsert.find(toStore);
755  if(itFound == oToInsert.end()) {
756  //get the index to the ParentageID or insert a new value if not already present
757  std::pair<std::map<edm::ParentageID,unsigned int>::iterator,bool> i = parentageIDs_.insert(std::make_pair(iProv.parentageID(),static_cast<unsigned int>(parentageIDs_.size())));
758  toStore.parentageIDIndex_ = i.first->second;
759  if(toStore.parentageIDIndex_ >= parentageIDs_.size()) {
761  << "RootOutputFile::insertProductProvenance\n"
762  << "The parentage ID index value " << toStore.parentageIDIndex_ << " is out of bounds. The maximum value is currently " << parentageIDs_.size()-1 << ".\n"
763  << "This should never happen.\n"
764  << "Please report this to the framework hypernews forum 'hn-cms-edmFramework@cern.ch'.\n";
765  }
766 
767  oToInsert.insert(toStore);
768  return true;
769  }
770  return false;
771  }
772 }
RunNumber_t run() const
Definition: EventID.h:39
size
Write out results.
EventNumber_t event() const
Definition: EventID.h:41
std::string const & branchName() const
bool isRealData() const
void beginInputFile(FileBlock const &fb, int remainingEvents)
BranchID const & branchID() const
virtual ProcessHistory const & processHistory() const
LuminosityBlockAuxiliary lumiAux_
std::string const & BranchTypeToAuxiliaryBranchName(BranchType const &branchType)
Definition: BranchType.cc:115
EventID const & id() const
static const TGPicture * info(bool iBackgroundIsBlack)
std::string const & parentageTreeName()
Definition: BranchType.cc:159
std::vector< BranchIDList > BranchIDLists
Definition: BranchIDList.h:19
int eventAutoFlushSize() const
EventAuxiliary const & eventAuxiliary() const
void writeProcessHistoryRegistry()
void insertAncestors(ProductProvenance const &iGetParents, ProductProvenanceRetriever const *iMapper, bool produced, std::set< BranchID > const &producedBranches, std::set< StoredProductProvenance > &oToFill)
void fillParameterSetBranch(TTree *parameterSetsTree, int basketSize)
std::map< BranchKey, BranchDescription > ProductList
bool checkSplitLevelsAndBasketSizes(TTree *inputTree) const
bool registerProcessHistory(ProcessHistory const &processHistory)
selection
main part
Definition: corrVsCorr.py:98
void fillProcessHistoryBranch(TTree *metaDataTree, int basketSize, ProcessHistoryRegistry const &processHistoryRegistry)
int whyNotFastClonable() const
Definition: FileBlock.h:104
RunNumber_t run() const
std::string const & fileFormatVersionBranchName()
Definition: BranchType.cc:218
edm::propagate_const< TTree * > metaDataTree_
unsigned long nEventsInLumi_
OutputItemListArray const & selectedOutputItemList() const
ProcessHistoryRegistry processHistoryRegistry_
std::string const & processName() const
BranchListIndexes const & branchListIndexes() const
ProductProvenance const * productProvenance() const
Definition: Provenance.cc:31
std::string const & eventSelectionsBranchName()
Definition: BranchType.cc:243
bool int lh
Definition: SIMDVec.h:21
MD5Result digest() const
Definition: Digest.cc:194
void writeLuminosityBlock(LuminosityBlockForOutput const &lb)
void setAutoFlush(Long64_t size)
#define nullptr
bool shouldWeCloseFile() const
unsigned int id() const
Definition: BranchID.h:23
LuminosityBlockAuxiliary const & luminosityBlockAuxiliary() const
bool checkIfFastClonable(TTree *inputTree) const
BranchType
Definition: BranchType.h:11
std::set< BranchID > branchesWithStoredHistory_
std::vector< EventSelectionID > EventSelectionIDVector
void sortVector_Run_Or_Lumi_Entries()
LuminosityBlockNumber_t luminosityBlock() const
std::string const & parameterSetsTreeName()
Definition: BranchType.cc:251
std::vector< std::pair< BranchDescription const *, EDGetToken > > SelectedProducts
std::vector< BranchID > const & parents() const
Definition: Parentage.h:44
void writeThinnedAssociationsHelper()
std::map< ParentageID, unsigned int > parentageIDs_
bool getByToken(EDGetToken token, TypeID const &typeID, BasicHandle &result) const
RootOutputTree eventTree_
EventSelectionIDVector const & eventSelectionIDs() const
Provenance const * provenance() const
Definition: BasicHandle.h:94
std::vector< BranchListIndex > BranchListIndexes
std::string moduleName(Provenance const &provenance)
Definition: Provenance.cc:27
bool getMapped(key_type const &k, value_type &result) const
void addBranch(std::string const &branchName, std::string const &className, void const *&pProd, int splitLevel, int basketSize, bool produced)
edm::propagate_const< PoolOutputModule * > om_
std::string const & moduleLabel() const
IndexIntoFile::EntryNumber_t eventEntryNumber_
std::string const & productInstanceName() const
LuminosityBlockAuxiliary const * pLumiAux_
std::string const & indexIntoFileBranchName()
Definition: BranchType.cc:233
edm::propagate_const< std::shared_ptr< TFile > > filePtr_
Definition: GenABIO.cc:180
void writeOne(EventForOutput const &e)
WrapperBase const * wrapper() const
Definition: BasicHandle.h:90
ProductProvenanceRetriever const * productProvenanceRetrieverPtr() const
RunNumber_t run() const
int getFileFormatVersion()
std::string logicalFile_
bool checkEntriesInReadBranches(Long64_t expectedNumberOfEntries) const
ProcessHistoryID const & reducedProcessHistoryID(ProcessHistoryID const &fullID) const
void setProcessHistoryID(ProcessHistoryID const &phid)
#define end
Definition: vmac.h:39
std::string const & metaDataTreeName()
Definition: BranchType.cc:168
PoolOutputModule::OutputItemList OutputItemList
LuminosityBlockNumber_t luminosityBlock() const
void addEntry(ProcessHistoryID const &processHistoryID, RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event, EntryNumber_t entry)
edm::propagate_const< TClass * > wrapperBaseTClass_
static TTree * makeTTree(TFile *filePtr, std::string const &name, int splitLevel)
element_type const * get() const
std::string const & fullClassName() const
EventSelectionIDVector const * pEventSelectionIDs_
edm::propagate_const< TTree * > parameterSetsTree_
RunAuxiliary const & runAuxiliary() const
Definition: RunForOutput.h:44
void sort_all(RandomAccessSequence &s)
wrappers for std::sort
Definition: Algorithms.h:120
edm::propagate_const< StoredProductProvenanceVector * > pEventEntryInfoVector_
void setBranchAliases(TTree *tree, SelectedProducts const &branches) const
RootOutputTree runTree_
std::string toString() const
Definition: Digest.cc:87
std::string const & parentageBranchName()
Definition: BranchType.cc:163
double b
Definition: hdecay.h:120
LuminosityBlockNumber_t luminosityBlock() const
void addContext(std::string const &context)
Definition: Exception.cc:227
edm::propagate_const< TTree * > parentageTree_
std::set< std::string > const & branchAliases() const
bool insertProductProvenance(const ProductProvenance &, std::set< StoredProductProvenance > &oToInsert)
void setException(std::exception_ptr e)
void addAuxiliary(std::string const &branchName, T const *&pAux, int bufSize, bool allowCloning=true)
std::vector< StoredProductProvenance > StoredProductProvenanceVector
void respondToCloseInputFile(FileBlock const &fb)
IndexIntoFile indexIntoFile_
std::string const & productDescriptionBranchName()
Definition: BranchType.cc:173
IndexIntoFile::EntryNumber_t runEntryNumber_
ParentageID const & parentageID() const
static void writeTTree(TTree *tree)
ProcessHistoryID const & processHistoryID() const
EventAuxiliary const * pEventAux_
HLT enums.
RunAuxiliary runAux_
ProcessHistoryID const & processHistoryID() const
ProductProvenance const * branchIDToProvenance(BranchID const &bid) const
std::exception_ptr getException()
void writeProductDescriptionRegistry()
std::string const & BranchTypeToProductProvenanceBranchName(BranchType const &BranchType)
Definition: BranchType.cc:131
std::string const & productDependenciesBranchName()
Definition: BranchType.cc:178
StoredProductProvenanceVector const * pEventEntryInfoVector() const
RootOutputFile(PoolOutputModule *om, std::string const &fileName, std::string const &logicalFileName)
std::string const & thinnedAssociationsHelperBranchName()
Definition: BranchType.cc:213
std::unique_ptr< WrapperBase > getWrapperBasePtr(void *p, int offset)
std::string const & branchIDListBranchName()
Definition: BranchType.cc:208
void setProcessHistoryID(ProcessHistoryID const &phid)
Definition: RunAuxiliary.h:36
std::string const & branchListIndexesBranchName()
Definition: BranchType.cc:247
Parentage const & parentage() const
RootOutputTreePtrArray treePointers_
Definition: tree.py:1
BranchListIndexes const * pBranchListIndexes_
void maybeFastCloneTree(bool canFastClone, bool canFastCloneAux, TTree *tree, std::string const &option)
LuminosityBlockID const & id() const
const eventsetup::produce::Produce produced
Definition: ESProducts.cc:20
static ParentageRegistry * instance()
IndexIntoFile::EntryNumber_t lumiEntryNumber_
RootOutputTree lumiTree_
void optimizeBaskets(ULong64_t size)
void writeRun(RunForOutput const &r)
TTree * tree() const
Definition: FileBlock.h:97
std::string const & fileIdentifierBranchName()
Definition: BranchType.cc:223
RunAuxiliary const * pRunAux_
std::string const & wrappedName() const
EventNumber_t event() const
RunNumber_t run() const
Definition: RunAuxiliary.h:41
RunNumber_t run() const
Definition: RunForOutput.h:46
def move(src, dest)
Definition: eostools.py:510
def branchType(schema, name)
Definition: revisionDML.py:112
JobReport::Token reportToken_
std::string createGlobalIdentifier()
void fillBranches(BranchType const &branchType, OccurrenceForOutput const &occurrence, StoredProductProvenanceVector *productProvenanceVecPtr=0, ProductProvenanceRetriever const *provRetriever=0)
std::string const & fileName() const
Definition: FileBlock.h:106
std::string match(BranchDescription const &a, BranchDescription const &b, std::string const &fileName)