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