CMS 3D CMS Logo

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