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