CMS 3D CMS Logo

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