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