CMS 3D CMS Logo

RootOutputFile.cc
Go to the documentation of this file.
1 
3 
5 
6 
39 
40 #include "TTree.h"
41 #include "TFile.h"
42 #include "TClass.h"
43 #include "Rtypes.h"
44 #include "RVersion.h"
45 
46 #include "Compression.h"
47 
48 #include <algorithm>
49 #include <iomanip>
50 #include <sstream>
51 
52 namespace edm {
53 
54  namespace {
55  bool
56  sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
57  return
58  lh->fullClassName() < rh->fullClassName() ? true :
59  lh->fullClassName() > rh->fullClassName() ? false :
60  lh->moduleLabel() < rh->moduleLabel() ? true :
61  lh->moduleLabel() > rh->moduleLabel() ? false :
62  lh->productInstanceName() < rh->productInstanceName() ? true :
63  lh->productInstanceName() > rh->productInstanceName() ? false :
64  lh->processName() < rh->processName() ? true :
65  false;
66  }
67 
68  TFile*
69  openTFile(char const* name, int compressionLevel) {
70  TFile* file = TFile::Open(name, "recreate", "", compressionLevel);
71  std::exception_ptr e = edm::threadLocalException::getException();
72  if(e != std::exception_ptr()) {
73  edm::threadLocalException::setException(std::exception_ptr());
74  std::rethrow_exception(e);
75  }
76  return file;
77  }
78  }
79 
81  std::string const& logicalFileName,
82  std::vector<std::string> const& processesWithSelectedMergeableRunProducts) :
83  file_(fileName),
84  logicalFile_(logicalFileName),
85  reportToken_(0),
86  om_(om),
87  whyNotFastClonable_(om_->whyNotFastClonable()),
88  canFastCloneAux_(false),
89  filePtr_(openTFile(file_.c_str(), om_->compressionLevel())),
90  fid_(),
91  eventEntryNumber_(0LL),
92  lumiEntryNumber_(0LL),
93  runEntryNumber_(0LL),
94  indexIntoFile_(),
95  storedMergeableRunProductMetadata_(processesWithSelectedMergeableRunProducts),
96  nEventsInLumi_(0),
97  metaDataTree_(nullptr),
98  parameterSetsTree_(nullptr),
99  parentageTree_(nullptr),
100  lumiAux_(),
101  runAux_(),
102  pEventAux_(nullptr),
103  pLumiAux_(&lumiAux_),
104  pRunAux_(&runAux_),
105  eventEntryInfoVector_(),
106  pEventEntryInfoVector_(&eventEntryInfoVector_),
107  pBranchListIndexes_(nullptr),
108  pEventSelectionIDs_(nullptr),
109  eventTree_(filePtr(), InEvent, om_->splitLevel(), om_->treeMaxVirtualSize()),
110  lumiTree_(filePtr(), InLumi, om_->splitLevel(), om_->treeMaxVirtualSize()),
111  runTree_(filePtr(), InRun, om_->splitLevel(), om_->treeMaxVirtualSize()),
112  treePointers_(),
113  dataTypeReported_(false),
114  processHistoryRegistry_(),
115  parentageIDs_(),
116  branchesWithStoredHistory_(),
117  wrapperBaseTClass_(TClass::GetClass("edm::WrapperBase")) {
118  if (om_->compressionAlgorithm() == std::string("ZLIB")) {
119  filePtr_->SetCompressionAlgorithm(ROOT::kZLIB);
120  } else if (om_->compressionAlgorithm() == std::string("LZMA")) {
121  filePtr_->SetCompressionAlgorithm(ROOT::kLZMA);
122  } else {
123  throw Exception(errors::Configuration) << "PoolOutputModule configured with unknown compression algorithm '" << om_->compressionAlgorithm() << "'\n"
124  << "Allowed compression algorithms are ZLIB and LZMA\n";
125  }
126  if (-1 != om->eventAutoFlushSize()) {
128  }
130  pEventAux_, om_->auxItems()[InEvent].basketSize_);
132  pEventEntryInfoVector(), om_->auxItems()[InEvent].basketSize_);
134  pEventSelectionIDs_, om_->auxItems()[InEvent].basketSize_,false);
136  pBranchListIndexes_, om_->auxItems()[InEvent].basketSize_);
137 
139  pLumiAux_, om_->auxItems()[InLumi].basketSize_);
140 
142  pRunAux_, om_->auxItems()[InRun].basketSize_);
143 
145  treePointers_[InLumi] = &lumiTree_;
146  treePointers_[InRun] = &runTree_;
147 
148  for(int i = InEvent; i < NumBranchTypes; ++i) {
149  BranchType branchType = static_cast<BranchType>(i);
150  RootOutputTree *theTree = treePointers_[branchType];
151  for(auto const& item : om_->selectedOutputItemList()[branchType]) {
152  item.product_ = nullptr;
153  BranchDescription const& desc = *item.branchDescription_;
154  theTree->addBranch(desc.branchName(),
155  desc.wrappedName(),
156  item.product_,
157  item.splitLevel_,
158  item.basketSize_,
159  item.branchDescription_->produced());
160  //make sure we always store product registry info for all branches we create
161  branchesWithStoredHistory_.insert(item.branchID());
162  }
163  }
164  // Don't split metadata tree or event description tree
168 
170 
171  // For the Job Report, get a vector of branch names in the "Events" tree.
172  // Also create a hash of all the branch names in the "Events" tree
173  // in a deterministic order, except use the full class name instead of the friendly class name.
174  // To avoid extra string copies, we create a vector of pointers into the product registry,
175  // and use a custom comparison operator for sorting.
176  std::vector<std::string> branchNames;
177  std::vector<BranchDescription const*> branches;
178  branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
179  branches.reserve(om->selectedOutputItemList()[InEvent].size());
180  for(auto const& item : om_->selectedOutputItemList()[InEvent]) {
181  branchNames.push_back(item.branchDescription_->branchName());
182  branches.push_back(item.branchDescription_);
183  }
184  // Now sort the branches for the hash.
185  sort_all(branches, sorterForJobReportHash);
186  // Now, make a concatenated string.
187  std::ostringstream oss;
188  char const underscore = '_';
189  for(auto const& branch : branches) {
190  BranchDescription const& bd = *branch;
191  oss << bd.fullClassName() << underscore
192  << bd.moduleLabel() << underscore
193  << bd.productInstanceName() << underscore
194  << bd.processName() << underscore;
195  }
196  std::string stringrep = oss.str();
197  cms::Digest md5alg(stringrep);
198 
199  // Register the output file with the JobReport service
200  // and get back the token for it.
201  std::string moduleName = "PoolOutputModule";
202  Service<JobReport> reportSvc;
203  reportToken_ = reportSvc->outputFileOpened(
204  file_, logicalFile_, // PFN and LFN
205  om_->catalog(), // catalog
206  moduleName, // module class name
207  om_->moduleLabel(), // module label
208  fid_.fid(), // file id (guid)
209  std::string(), // data type (not yet known, so string is empty).
210  md5alg.digest().toString(), // branch hash
211  branchNames); // branch names being written
212  }
213 
214  namespace {
215  void
216  maybeIssueWarning(int whyNotFastClonable, std::string const& ifileName, std::string const& ofileName) {
217 
218  // No message if fast cloning was deliberately disabled, or if there are no events to copy anyway.
219  if ((whyNotFastClonable &
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  }
303 
304  void RootOutputFile::beginInputFile(FileBlock const& fb, int remainingEvents) {
305 
306  // Reset per input file information
307  whyNotFastClonable_ = om_->whyNotFastClonable();
308  canFastCloneAux_ = false;
309 
310  if(fb.tree() != nullptr) {
311 
313 
314  if(remainingEvents >= 0 && remainingEvents < fb.tree()->GetEntries()) {
316  }
317 
319  if(!match) {
320  if(om_->overrideInputFileSplitLevels()) {
321  // We may be fast copying. We must disable fast copying if the split levels
322  // or basket sizes do not match.
324  } else {
325  // We are using the input split levels and basket sizes from the first input file
326  // for copied output branches. In this case, we throw an exception if any branches
327  // have different split levels or basket sizes in a subsequent input file.
328  // If the mismatch is in the first file, there is a bug somewhere, so we assert.
329  assert(om_->inputFileCount() > 1);
330  throw Exception(errors::MismatchedInputFiles, "RootOutputFile::beginInputFile()") <<
331  "Merge failure because input file " << file_ << " has different ROOT split levels or basket sizes\n" <<
332  "than previous files. To allow merging in splite of this, use the configuration parameter\n" <<
333  "overrideInputFileSplitLevels=cms.untracked.bool(True)\n" <<
334  "in every PoolOutputModule.\n";
335  }
336  }
337 
338  // Since this check can be time consuming, we do it only if we would otherwise fast clone.
340  if(!eventTree_.checkIfFastClonable(fb.tree())) {
342  }
343  }
344  // We now check if we can fast copy the auxiliary branches.
345  // We can do so only if we can otherwise fast copy,
346  // the input file has the current format (these branches are in the Events Tree),
347  // there are no newly dropped or produced products,
348  // no metadata has been dropped,
349  // ID's have not been modified,
350  // and the branch list indexes do not need modification.
351 
352  // Note: Fast copy of the EventProductProvenance branch is unsafe
353  // unless we can enforce that the parentage information for a fully copied
354  // output file will be the same as for the input file, with nothing dropped.
355  // This has never been enforced, and, withthe EDAlias feature, it may no longer
356  // work by accident.
357  // So, for now, we do not enable fast cloning of the non-product branches.
358 /*
359  Service<ConstProductRegistry> reg;
360  canFastCloneAux_ = (whyNotFastClonable_ == FileBlock::CanFastClone) &&
361  fb.fileFormatVersion().noMetaDataTrees() &&
362  !om_->hasNewlyDroppedBranch()[InEvent] &&
363  !fb.hasNewlyDroppedBranch()[InEvent] &&
364  om_->dropMetaData() == PoolOutputModule::DropNone &&
365  !reg->anyProductProduced() &&
366  !fb.modifiedIDs() &&
367  fb.branchListIndexesUnchanged();
368 */
369 
370  // Report the fast copying status.
371  Service<JobReport> reportSvc;
372  reportSvc->reportFastCopyingStatus(reportToken_, fb.fileName(), whyNotFastClonable_ == FileBlock::CanFastClone);
373  } else {
375  }
376 
378 
379  // Possibly issue warning or informational message if we haven't fast cloned.
380  if(fb.tree() != nullptr && whyNotFastClonable_ != FileBlock::CanFastClone) {
381  maybeIssueWarning(whyNotFastClonable_, fb.fileName(), file_);
382  }
383  }
384 
389  }
390 
392  unsigned int const oneK = 1024;
393  Long64_t size = filePtr_->GetSize()/oneK;
394  return(size >= om_->maxFileSize());
395  }
396 
398  // Auxiliary branch
399  pEventAux_ = &e.eventAuxiliary();
400 
401  // Because getting the data may cause an exception to be thrown we want to do that
402  // first before writing anything to the file about this event
403  // NOTE: pEventAux_, pBranchListIndexes_, pEventSelectionIDs_, and pEventEntryInfoVector_
404  // must be set before calling fillBranches since they get written out in that routine.
405  assert(pEventAux_->processHistoryID() == e.processHistoryID());
407 
408  // Note: The EventSelectionIDVector should have a one to one correspondence with the processes in the process history.
409  // Therefore, a new entry should be added if and only if the current process has been added to the process history,
410  // which is done if and only if there is a produced product.
413  if (reg->anyProductProduced() || !om_->wantAllEvents()) {
414  esids.push_back(om_->selectorConfig());
415  }
416  pEventSelectionIDs_ = &esids;
418  assert(provRetriever);
419  fillBranches(InEvent, e, pEventEntryInfoVector_, provRetriever);
420 
421  // Add the dataType to the job report if it hasn't already been done
422  if(!dataTypeReported_) {
423  Service<JobReport> reportSvc;
424  std::string dataType("MC");
425  if(pEventAux_->isRealData()) 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
437 
438  // Report event written
439  Service<JobReport> reportSvc;
440  reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
441  ++nEventsInLumi_;
442  }
443 
445  // Auxiliary branch
446  // NOTE: lumiAux_ must be filled before calling fillBranches since it gets written out in that routine.
448  // Use the updated process historyID
450  // Store the process history.
452  // Store the reduced ID in the IndexIntoFile
454  // Add lumi to index.
457  fillBranches(InLumi, lb);
458  lumiTree_.optimizeBaskets(10ULL*1024*1024);
459 
460  Service<JobReport> reportSvc;
461  reportSvc->reportLumiSection(reportToken_, lb.id().run(), lb.id().luminosityBlock(),nEventsInLumi_);
462  nEventsInLumi_ = 0;
463  }
464 
466  // Auxiliary branch
467  // NOTE: runAux_ must be filled before calling fillBranches since it gets written out in that routine.
468  runAux_ = r.runAuxiliary();
469  // Use the updated process historyID
471  // Store the process history.
473  // Store the reduced ID in the IndexIntoFile
475  // Add run to index.
476  indexIntoFile_.addEntry(reducedPHID, runAux_.run(), 0U, 0U, runEntryNumber_);
478  ++runEntryNumber_;
479  fillBranches(InRun, r);
480  runTree_.optimizeBaskets(10ULL*1024*1024);
481 
482  Service<JobReport> reportSvc;
483  reportSvc->reportRunNumber(reportToken_, r.run());
484  }
485 
487  Parentage const* desc(nullptr);
488 
489  if(!parentageTree_->Branch(poolNames::parentageBranchName().c_str(),
490  &desc, om_->basketSize(), 0))
492  << "Failed to create a branch for Parentages in the output file";
493 
495 
496  std::vector<ParentageID> orderedIDs(parentageIDs_.size());
497  for(auto const& parentageID : parentageIDs_) {
498  orderedIDs[parentageID.second] = parentageID.first;
499  }
500  //now put them into the TTree in the correct order
501  for(auto const& orderedID : orderedIDs) {
502  desc = ptReg.getMapped(orderedID);
503  //NOTE: some old format files have missing Parentage info
504  // so a null value of desc can't be fatal.
505  // Root will default construct an object in that case.
506  parentageTree_->Fill();
507  }
508  }
509 
511  FileFormatVersion fileFormatVersion(getFileFormatVersion());
512  FileFormatVersion* pFileFmtVsn = &fileFormatVersion;
513  TBranch* b = 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 = metaDataTree_->Branch(poolNames::mergeableRunProductMetadataBranchName().c_str(), &ptr, om_->basketSize(), 0);
546  assert(b);
547  b->Fill();
548  }
549 
552  }
553 
555  BranchIDLists const* p = om_->branchIDLists();
556  TBranch* b = metaDataTree_->Branch(poolNames::branchIDListBranchName().c_str(), &p, om_->basketSize(), 0);
557  assert(b);
558  b->Fill();
559  }
560 
562  ThinnedAssociationsHelper const* p = om_->thinnedAssociationsHelper();
563  TBranch* b = metaDataTree_->Branch(poolNames::thinnedAssociationsHelperBranchName().c_str(), &p, om_->basketSize(), 0);
564  assert(b);
565  b->Fill();
566  }
567 
570  }
571 
573  // Make a local copy of the ProductRegistry, removing any transient or pruned products.
574  typedef ProductRegistry::ProductList ProductList;
576  ProductRegistry pReg(reg->productList());
577  ProductList& pList = const_cast<ProductList &>(pReg.productList());
578  for(auto const& prod : pList) {
579  if(prod.second.branchID() != prod.second.originalBranchID()) {
580  if(branchesWithStoredHistory_.find(prod.second.branchID()) != branchesWithStoredHistory_.end()) {
581  branchesWithStoredHistory_.insert(prod.second.originalBranchID());
582  }
583  }
584  }
585  std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
586  for(ProductList::iterator it = pList.begin(); it != pList.end();) {
587  if(branchesWithStoredHistory_.find(it->second.branchID()) == end) {
588  // avoid invalidating iterator on deletion
589  ProductList::iterator itCopy = it;
590  ++it;
591  pList.erase(itCopy);
592 
593  } else {
594  ++it;
595  }
596  }
597 
598  ProductRegistry* ppReg = &pReg;
599  TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
600  assert(b);
601  b->Fill();
602  }
604  BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
605  BranchChildren* ppDeps = &pDeps;
606  TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
607  assert(b);
608  b->Fill();
609  }
610 
612  metaDataTree_->SetEntries(-1);
615 
617 
618  // Create branch aliases for all the branches in the
619  // events/lumis/runs trees. The loop is over all types of data
620  // products.
621  for(int i = InEvent; i < NumBranchTypes; ++i) {
622  BranchType branchType = static_cast<BranchType>(i);
623  setBranchAliases(treePointers_[branchType]->tree(), om_->keptProducts()[branchType]);
624  treePointers_[branchType]->writeTree();
625  }
626 
627  // close the file -- mfp
628  // Just to play it safe, zero all pointers to objects in the TFile to be closed.
629  metaDataTree_ = parentageTree_ = nullptr;
630  for(auto& treePointer : treePointers_) {
631  treePointer->close();
632  treePointer = nullptr;
633  }
634  filePtr_->Close();
635  filePtr_ = nullptr; // propagate_const<T> has no reset() function
636 
637  // report that file has been closed
638  Service<JobReport> reportSvc;
639  reportSvc->outputFileClosed(reportToken_);
640 
641  }
642 
643  void
644  RootOutputFile::setBranchAliases(TTree* tree, SelectedProducts const& branches) const {
645  if(tree && tree->GetNbranches() != 0) {
646  for(auto const& selection : branches) {
647  BranchDescription const& pd = *selection.first;
648  std::string const& full = pd.branchName() + "obj";
649  if(pd.branchAliases().empty()) {
650  std::string const& alias =
651  (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 
662  void
664  ProductProvenanceRetriever const* iMapper,
665  bool produced,
666  std::set<BranchID> const &iProducedIDs,
667  std::set<StoredProductProvenance>& oToFill) {
668  assert(om_->dropMetaData() != PoolOutputModule::DropAll);
669  assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
670  if(om_->dropMetaData() == PoolOutputModule::DropDroppedPrior && !produced) 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 || (iProducedIDs.end() != iProducedIDs.find(info->branchID()) ) ) {
677  if(insertProductProvenance(*info,oToFill) ) {
678  //haven't seen this one yet
679  insertAncestors(*info, iMapper, produced, iProducedIDs, oToFill);
680  }
681  }
682  }
683  }
684  }
685 
687  BranchType const& branchType,
688  OccurrenceForOutput const& occurrence,
689  StoredProductProvenanceVector* productProvenanceVecPtr,
690  ProductProvenanceRetriever const* provRetriever) {
691 
692  std::vector<std::unique_ptr<WrapperBase> > dummies;
693 
694  OutputItemList const& items = om_->selectedOutputItemList()[branchType];
695 
696  bool const doProvenance = (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 
719  BranchID const& id = item.branchDescription_->branchID();
720  branchesWithStoredHistory_.insert(id);
721 
722  bool produced = item.branchDescription_->produced();
723  bool getProd = (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;
729  if(getProd) {
730  bool found = occurrence.getByToken(item.token_, item.branchDescription_->unwrappedTypeID(), result);
731  product = result.wrapper();
732  if(found && keepProvenance) {
733  productProvenance = result.provenance()->productProvenance();
734  }
735  if(product == nullptr) {
736  // No product with this ID is in the event.
737  // Add a null product.
738  TClass* cp = item.branchDescription_->wrappedType().getClass();
739  assert(cp != nullptr);
740  int offset = cp->GetBaseClassOffset(wrapperBaseTClass_);
741  void* p = cp->New();
742  std::unique_ptr<WrapperBase> dummy = getWrapperBasePtr(p, offset);
743  product = dummy.get();
744  dummies.emplace_back(std::move(dummy));
745  }
746  item.product_ = product;
747  }
748  if (keepProvenance && productProvenance == nullptr) {
749  productProvenance = provRetriever->branchIDToProvenance(item.branchDescription_->originalBranchID());
750  }
751  if(productProvenance) {
752  insertProductProvenance(*productProvenance,provenanceToKeep);
753  insertAncestors(*productProvenance, provRetriever, produced, producedBranches, provenanceToKeep);
754  }
755  }
756 
757  if(doProvenance) productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
758  treePointers_[branchType]->fillTree();
759  if(doProvenance) productProvenanceVecPtr->clear();
760  }
761 
762  bool
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 = parentageIDs_.insert(std::make_pair(iProv.parentageID(),static_cast<unsigned int>(parentageIDs_.size())));
771  toStore.parentageIDIndex_ = i.first->second;
772  if(toStore.parentageIDIndex_ >= parentageIDs_.size()) {
774  << "RootOutputFile::insertProductProvenance\n"
775  << "The parentage ID index value " << toStore.parentageIDIndex_ << " is out of bounds. The maximum value is currently " << parentageIDs_.size()-1 << ".\n"
776  << "This should never happen.\n"
777  << "Please report this to the framework hypernews forum 'hn-cms-edmFramework@cern.ch'.\n";
778  }
779 
780  oToInsert.insert(toStore);
781  return true;
782  }
783  return false;
784  }
785 }
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
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
void writeProcessHistoryRegistry()
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
bool registerProcessHistory(ProcessHistory const &processHistory)
selection
main part
Definition: corrVsCorr.py:99
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:219
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:35
std::string const & eventSelectionsBranchName()
Definition: BranchType.cc:249
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: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()
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
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: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: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:46
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:164
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: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
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:224
MergeableRunProductMetadata const * mergeableRunProductMetadata() const
Definition: RunForOutput.h:51
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:48
def move(src, dest)
Definition: eostools.py:511
def branchType(schema, name)
Definition: revisionDML.py:113
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)