CMS 3D CMS Logo

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