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 
32 
33 #include "TROOT.h"
34 #include "TTree.h"
35 #include "TFile.h"
36 #include "TClass.h"
37 #include "Rtypes.h"
38 #include "RVersion.h"
39 
40 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
41 #include "Compression.h"
42 #endif
43 
44 #include <algorithm>
45 #include <iomanip>
46 #include <sstream>
47 
48 namespace edm {
49 
50  namespace {
51  bool
52  sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
53  return
54  lh->fullClassName() < rh->fullClassName() ? true :
55  lh->fullClassName() > rh->fullClassName() ? false :
56  lh->moduleLabel() < rh->moduleLabel() ? true :
57  lh->moduleLabel() > rh->moduleLabel() ? false :
58  lh->productInstanceName() < rh->productInstanceName() ? true :
59  lh->productInstanceName() > rh->productInstanceName() ? false :
60  lh->processName() < rh->processName() ? true :
61  false;
62  }
63  }
64 
66  file_(fileName),
67  logicalFile_(logicalFileName),
68  reportToken_(0),
69  om_(om),
70  whyNotFastClonable_(om_->whyNotFastClonable()),
71  canFastCloneAux_(false),
72  filePtr_(TFile::Open(file_.c_str(), "recreate", "", om_->compressionLevel())),
73  fid_(),
74  eventEntryNumber_(0LL),
75  lumiEntryNumber_(0LL),
76  runEntryNumber_(0LL),
77  indexIntoFile_(),
78  metaDataTree_(0),
79  parameterSetsTree_(0),
80  parentageTree_(0),
81  lumiAux_(),
82  runAux_(),
83  pEventAux_(0),
84  pLumiAux_(&lumiAux_),
85  pRunAux_(&runAux_),
86  eventEntryInfoVector_(),
87  pEventEntryInfoVector_(&eventEntryInfoVector_),
88  pBranchListIndexes_(0),
89  pEventSelectionIDs_(0),
90  eventTree_(filePtr_, InEvent, om_->splitLevel(), om_->treeMaxVirtualSize()),
91  lumiTree_(filePtr_, InLumi, om_->splitLevel(), om_->treeMaxVirtualSize()),
92  runTree_(filePtr_, InRun, om_->splitLevel(), om_->treeMaxVirtualSize()),
93  treePointers_(),
94  dataTypeReported_(false),
95  parentageIDs_(),
96  branchesWithStoredHistory_() {
97 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
98  if (om_->compressionAlgorithm() == std::string("ZLIB")) {
99  filePtr_->SetCompressionAlgorithm(ROOT::kZLIB);
100  } else if (om_->compressionAlgorithm() == std::string("LZMA")) {
101  filePtr_->SetCompressionAlgorithm(ROOT::kLZMA);
102  } else {
103  throw Exception(errors::Configuration) << "PoolOutputModule configured with unknown compression algorithm '" << om_->compressionAlgorithm() << "'\n"
104  << "Allowed compression algorithms are ZLIB and LZMA\n";
105  }
106 #endif
107  if (-1 != om->eventAutoFlushSize()) {
109  }
111  pEventAux_, om_->auxItems()[InEvent].basketSize_);
113  pEventEntryInfoVector_, om_->auxItems()[InEvent].basketSize_);
115  pEventSelectionIDs_, om_->auxItems()[InEvent].basketSize_,false);
117  pBranchListIndexes_, om_->auxItems()[InEvent].basketSize_);
118 
120  pLumiAux_, om_->auxItems()[InLumi].basketSize_);
121 
123  pRunAux_, om_->auxItems()[InRun].basketSize_);
124 
126  treePointers_[InLumi] = &lumiTree_;
127  treePointers_[InRun] = &runTree_;
128 
129  for(int i = InEvent; i < NumBranchTypes; ++i) {
130  BranchType branchType = static_cast<BranchType>(i);
131  RootOutputTree *theTree = treePointers_[branchType];
132  for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[branchType].begin(),
133  itEnd = om_->selectedOutputItemList()[branchType].end();
134  it != itEnd; ++it) {
135  it->product_ = 0;
136  BranchDescription const& desc = *it->branchDescription_;
137  desc.init();
138  theTree->addBranch(desc.branchName(),
139  desc.wrappedName(),
140  desc.getInterface(),
141  it->product_,
142  it->splitLevel_,
143  it->basketSize_,
144  it->branchDescription_->produced());
145  //make sure we always store product registry info for all branches we create
146  branchesWithStoredHistory_.insert(it->branchID());
147  }
148  }
149  // Don't split metadata tree or event description tree
153 
155 
156  // For the Job Report, get a vector of branch names in the "Events" tree.
157  // Also create a hash of all the branch names in the "Events" tree
158  // in a deterministic order, except use the full class name instead of the friendly class name.
159  // To avoid extra string copies, we create a vector of pointers into the product registry,
160  // and use a custom comparison operator for sorting.
161  std::vector<std::string> branchNames;
162  std::vector<BranchDescription const*> branches;
163  branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
164  branches.reserve(om->selectedOutputItemList()[InEvent].size());
165  for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[InEvent].begin(),
166  itEnd = om_->selectedOutputItemList()[InEvent].end();
167  it != itEnd; ++it) {
168  branchNames.push_back(it->branchDescription_->branchName());
169  branches.push_back(it->branchDescription_);
170  }
171  // Now sort the branches for the hash.
172  sort_all(branches, sorterForJobReportHash);
173  // Now, make a concatenated string.
174  std::ostringstream oss;
175  char const underscore = '_';
176  for(std::vector<BranchDescription const*>::const_iterator it = branches.begin(), itEnd = branches.end(); it != itEnd; ++it) {
177  BranchDescription const& bd = **it;
178  oss << bd.fullClassName() << underscore
179  << bd.moduleLabel() << underscore
180  << bd.productInstanceName() << underscore
181  << bd.processName() << underscore;
182  }
183  std::string stringrep = oss.str();
184  cms::Digest md5alg(stringrep);
185 
186  // Register the output file with the JobReport service
187  // and get back the token for it.
188  std::string moduleName = "PoolOutputModule";
189  Service<JobReport> reportSvc;
190  reportToken_ = reportSvc->outputFileOpened(
191  file_, logicalFile_, // PFN and LFN
192  om_->catalog(), // catalog
193  moduleName, // module class name
194  om_->moduleLabel(), // module label
195  fid_.fid(), // file id (guid)
196  std::string(), // data type (not yet known, so string is empty).
197  md5alg.digest().toString(), // branch hash
198  branchNames); // branch names being written
199  }
200 
201  namespace {
202  void
203  maybeIssueWarning(int whyNotFastClonable, std::string const& ifileName, std::string const& ofileName) {
204 
205  // No message if fast cloning was deliberately disabled, or if there are no events to copy anyway.
206  if ((whyNotFastClonable &
208  return;
209  }
210 
211  // There will be a message stating every reason that fast cloning was not possible.
212  // If at one or more of the reasons was because of something the user explicitly specified (e.g. event selection, skipping events),
213  // or if the input file was in an old format, the message will be informational. Otherwise, the message will be a warning.
214  bool isWarning = true;
215  std::ostringstream message;
216  message << "Fast copying of file " << ifileName << " to file " << ofileName << " is disabled because:\n";
217  if((whyNotFastClonable & FileBlock::HasSecondaryFileSequence) != 0) {
218  message << "a SecondaryFileSequence was specified.\n";
219  whyNotFastClonable &= ~(FileBlock::HasSecondaryFileSequence);
220  isWarning = false;
221  }
222  if((whyNotFastClonable & FileBlock::FileTooOld) != 0) {
223  message << "the input file is in an old format.\n";
224  whyNotFastClonable &= ~(FileBlock::FileTooOld);
225  isWarning = false;
226  }
227  if((whyNotFastClonable & FileBlock::EventsToBeSorted) != 0) {
228  message << "events need to be sorted.\n";
229  whyNotFastClonable &= ~(FileBlock::EventsToBeSorted);
230  }
231  if((whyNotFastClonable & FileBlock::RunOrLumiNotContiguous) != 0) {
232  message << "a run or a lumi is not contiguous in the input file.\n";
233  whyNotFastClonable &= ~(FileBlock::RunOrLumiNotContiguous);
234  }
235  if((whyNotFastClonable & FileBlock::EventsOrLumisSelectedByID) != 0) {
236  message << "events or lumis were selected or skipped by ID.\n";
237  whyNotFastClonable &= ~(FileBlock::EventsOrLumisSelectedByID);
238  isWarning = false;
239  }
240  if((whyNotFastClonable & FileBlock::InitialEventsSkipped) != 0) {
241  message << "initial events, lumis or runs were skipped.\n";
242  whyNotFastClonable &= ~(FileBlock::InitialEventsSkipped);
243  isWarning = false;
244  }
245  if((whyNotFastClonable & FileBlock::DuplicateEventsRemoved) != 0) {
246  message << "some events were skipped because of duplicate checking.\n";
247  whyNotFastClonable &= ~(FileBlock::DuplicateEventsRemoved);
248  }
249  if((whyNotFastClonable & FileBlock::MaxEventsTooSmall) != 0) {
250  message << "some events were not copied because of maxEvents limit.\n";
251  whyNotFastClonable &= ~(FileBlock::MaxEventsTooSmall);
252  isWarning = false;
253  }
254  if((whyNotFastClonable & FileBlock::MaxLumisTooSmall) != 0) {
255  message << "some events were not copied because of maxLumis limit.\n";
256  whyNotFastClonable &= ~(FileBlock::MaxLumisTooSmall);
257  isWarning = false;
258  }
259  if((whyNotFastClonable & FileBlock::ParallelProcesses) != 0) {
260  message << "parallel processing was specified.\n";
261  whyNotFastClonable &= ~(FileBlock::ParallelProcesses);
262  isWarning = false;
263  }
264  if((whyNotFastClonable & FileBlock::EventSelectionUsed) != 0) {
265  message << "an EventSelector was specified.\n";
266  whyNotFastClonable &= ~(FileBlock::EventSelectionUsed);
267  isWarning = false;
268  }
269  if((whyNotFastClonable & FileBlock::OutputMaxEventsTooSmall) != 0) {
270  message << "some events were not copied because of maxEvents output limit.\n";
271  whyNotFastClonable &= ~(FileBlock::OutputMaxEventsTooSmall);
272  isWarning = false;
273  }
274  if((whyNotFastClonable & FileBlock::SplitLevelMismatch) != 0) {
275  message << "the split level or basket size of a branch or branches was modified.\n";
276  whyNotFastClonable &= ~(FileBlock::SplitLevelMismatch);
277  }
278  if((whyNotFastClonable & FileBlock::BranchMismatch) != 0) {
279  message << "The format of a data product has changed.\n";
280  whyNotFastClonable &= ~(FileBlock::BranchMismatch);
281  }
282  assert(whyNotFastClonable == FileBlock::CanFastClone);
283  if (isWarning) {
284  LogWarning("FastCloningDisabled") << message.str();
285  } else {
286  LogInfo("FastCloningDisabled") << message.str();
287  }
288  }
289  }
290 
291  void RootOutputFile::beginInputFile(FileBlock const& fb, int remainingEvents) {
292 
293  // Reset per input file information
295  canFastCloneAux_ = false;
296 
297  if(fb.tree() != 0) {
298 
300 
301  if(remainingEvents >= 0 && remainingEvents < fb.tree()->GetEntries()) {
303  }
304 
306  if(!match) {
308  // We may be fast copying. We must disable fast copying if the split levels
309  // or basket sizes do not match.
311  } else {
312  // We are using the input split levels and basket sizes from the first input file
313  // for copied output branches. In this case, we throw an exception if any branches
314  // have different split levels or basket sizes in a subsequent input file.
315  // If the mismatch is in the first file, there is a bug somewhere, so we assert.
316  assert(om_->inputFileCount() > 1);
317  throw Exception(errors::MismatchedInputFiles, "RootOutputFile::beginInputFile()") <<
318  "Merge failure because input file " << file_ << " has different ROOT split levels or basket sizes\n" <<
319  "than previous files. To allow merging in splite of this, use the configuration parameter\n" <<
320  "overrideInputFileSplitLevels=cms.untracked.bool(True)\n" <<
321  "in every PoolOutputModule.\n";
322  }
323  }
324 
325  // Since this check can be time consuming, we do it only if we would otherwise fast clone.
327  if(!eventTree_.checkIfFastClonable(fb.tree())) {
329  }
330  }
331  // We now check if we can fast copy the auxiliary branches.
332  // We can do so only if we can otherwise fast copy,
333  // the input file has the current format (these branches are in the Events Tree),
334  // there are no newly dropped or produced products,
335  // no metadata has been dropped,
336  // ID's have not been modified,
337  // and the branch list indexes do not need modification.
338 
339  // Note: Fast copy of the EventProductProvenance branch is unsafe
340  // unless we can enforce that the parentage information for a fully copied
341  // output file will be the same as for the input file, with nothing dropped.
342  // This has never been enforced, and, withthe EDAlias feature, it may no longer
343  // work by accident.
344  // So, for now, we do not enable fast cloning of the non-product branches.
345 /*
346  Service<ConstProductRegistry> reg;
347  canFastCloneAux_ = (whyNotFastClonable_ == FileBlock::CanFastClone) &&
348  fb.fileFormatVersion().noMetaDataTrees() &&
349  !om_->hasNewlyDroppedBranch()[InEvent] &&
350  !fb.hasNewlyDroppedBranch()[InEvent] &&
351  om_->dropMetaData() == PoolOutputModule::DropNone &&
352  !reg->anyProductProduced() &&
353  !fb.modifiedIDs() &&
354  fb.branchListIndexesUnchanged();
355 */
356 
357  // Report the fast copying status.
358  Service<JobReport> reportSvc;
359  reportSvc->reportFastCopyingStatus(reportToken_, fb.fileName(), whyNotFastClonable_ == FileBlock::CanFastClone);
360  } else {
362  }
363 
365 
366  // Possibly issue warning or informational message if we haven't fast cloned.
367  if(fb.tree() != 0 && whyNotFastClonable_ != FileBlock::CanFastClone) {
368  maybeIssueWarning(whyNotFastClonable_, fb.fileName(), file_);
369  }
370  }
371 
376  }
377 
379  unsigned int const oneK = 1024;
380  Long64_t size = filePtr_->GetSize()/oneK;
381  return(size >= om_->maxFileSize());
382  }
383 
385  // Auxiliary branch
386  pEventAux_ = &e.aux();
387 
388  // Because getting the data may cause an exception to be thrown we want to do that
389  // first before writing anything to the file about this event
390  // NOTE: pEventAux_, pBranchListIndexes_, pEventSelectionIDs_, and pEventEntryInfoVector_
391  // must be set before calling fillBranches since they get written out in that routine.
392  assert(pEventAux_->processHistoryID() == e.processHistoryID());
394 
395  // Note: The EventSelectionIDVector should have a one to one correspondence with the processes in the process history.
396  // Therefore, a new entry should be added if and only if the current process has been added to the process history,
397  // which is done if and only if there is a produced product.
400  if (reg->anyProductProduced() || !om_->wantAllEvents()) {
401  esids.push_back(om_->selectorConfig());
402  }
403  pEventSelectionIDs_ = &esids;
405 
406  // Add the dataType to the job report if it hasn't already been done
407  if(!dataTypeReported_) {
408  Service<JobReport> reportSvc;
409  std::string dataType("MC");
410  if(pEventAux_->isRealData()) dataType = "Data";
411  reportSvc->reportDataType(reportToken_, dataType);
412  dataTypeReported_ = true;
413  }
414 
415  // Store the reduced ID in the IndexIntoFile
416  ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(e.processHistoryID());
417  // Add event to index
420 
421  // Report event written
422  Service<JobReport> reportSvc;
423  reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
424  }
425 
427  // Auxiliary branch
428  // NOTE: lumiAux_ must be filled before calling fillBranches since it gets written out in that routine.
429  lumiAux_ = lb.aux();
430  // Use the updated process historyID
432  // Store the reduced ID in the IndexIntoFile
433  ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(lb.processHistoryID());
434  // Add lumi to index.
437  fillBranches(InLumi, lb, 0);
438  lumiTree_.optimizeBaskets(10ULL*1024*1024);
439  }
440 
442  // Auxiliary branch
443  // NOTE: runAux_ must be filled before calling fillBranches since it gets written out in that routine.
444  runAux_ = r.aux();
445  // Use the updated process historyID
447  // Store the reduced ID in the IndexIntoFile
448  ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(r.processHistoryID());
449  // Add run to index.
450  indexIntoFile_.addEntry(reducedPHID, runAux_.run(), 0U, 0U, runEntryNumber_);
451  ++runEntryNumber_;
452  fillBranches(InRun, r, 0);
453  runTree_.optimizeBaskets(10ULL*1024*1024);
454  }
455 
457  Parentage const* desc(0);
458 
459  if(!parentageTree_->Branch(poolNames::parentageBranchName().c_str(),
460  &desc, om_->basketSize(), 0))
462  << "Failed to create a branch for Parentages in the output file";
463 
464 
465  //NOTE: for some reason the empty Parentage is not added to the registry some of the time
467  ptReg.insertMapped(Parentage());
468 
469  std::vector<ParentageID> orderedIDs(parentageIDs_.size());
470  for(std::map<ParentageID,unsigned int>::const_iterator it = parentageIDs_.begin(),
471  itEnd = parentageIDs_.end();
472  it != itEnd;
473  ++it) {
474  orderedIDs[it->second]=it->first;
475  }
476  //now put them into the TTree in the correct order
477  for(std::vector<ParentageID>::const_iterator it = orderedIDs.begin(),
478  itEnd = orderedIDs.end();
479  it != itEnd;
480  ++it) {
481  desc = ptReg.getMapped(*it);
482  //NOTE: some old format files have missing Parentage info
483  // so a null value of desc can't be fatal.
484  // Root will default construct an object in that case.
485  parentageTree_->Fill();
486  }
487  }
488 
490  FileFormatVersion fileFormatVersion(getFileFormatVersion());
491  FileFormatVersion* pFileFmtVsn = &fileFormatVersion;
492  TBranch* b = metaDataTree_->Branch(poolNames::fileFormatVersionBranchName().c_str(), &pFileFmtVsn, om_->basketSize(), 0);
493  assert(b);
494  b->Fill();
495  }
496 
498  FileID* fidPtr = &fid_;
499  TBranch* b = metaDataTree_->Branch(poolNames::fileIdentifierBranchName().c_str(), &fidPtr, om_->basketSize(), 0);
500  assert(b);
501  b->Fill();
502  }
503 
507  ex << "The number of entries in at least one output TBranch whose entries\n"
508  "were copied from the input does not match the number of events\n"
509  "recorded in IndexIntoFile. This might (or might not) indicate a\n"
510  "problem related to fast copy.";
511  ex.addContext("Calling RootOutputFile::writeIndexIntoFile");
512  throw ex;
513  }
515  IndexIntoFile* iifPtr = &indexIntoFile_;
516  TBranch* b = metaDataTree_->Branch(poolNames::indexIntoFileBranchName().c_str(), &iifPtr, om_->basketSize(), 0);
517  assert(b);
518  b->Fill();
519  }
520 
523  Map const& procConfigMap = ProcessConfigurationRegistry::instance()->data();
524  ProcessConfigurationVector procConfigVector;
525  for(Map::const_iterator i = procConfigMap.begin(), e = procConfigMap.end(); i != e; ++i) {
526  procConfigVector.push_back(i->second);
527  }
528  sort_all(procConfigVector);
529  ProcessConfigurationVector* p = &procConfigVector;
530  TBranch* b = metaDataTree_->Branch(poolNames::processConfigurationBranchName().c_str(), &p, om_->basketSize(), 0);
531  assert(b);
532  b->Fill();
533  }
534 
537  Map const& procHistoryMap = ProcessHistoryRegistry::instance()->data();
538  ProcessHistoryVector procHistoryVector;
539  for(Map::const_iterator i = procHistoryMap.begin(), e = procHistoryMap.end(); i != e; ++i) {
540  procHistoryVector.push_back(i->second);
541  }
542  ProcessHistoryVector* p = &procHistoryVector;
543  TBranch* b = metaDataTree_->Branch(poolNames::processHistoryBranchName().c_str(), &p, om_->basketSize(), 0);
544  assert(b);
545  b->Fill();
546  }
547 
549  BranchIDLists const* p = om_->branchIDLists();
550  TBranch* b = metaDataTree_->Branch(poolNames::branchIDListBranchName().c_str(), &p, om_->basketSize(), 0);
551  assert(b);
552  b->Fill();
553  }
554 
556  std::pair<ParameterSetID, ParameterSetBlob> idToBlob;
557  std::pair<ParameterSetID, ParameterSetBlob>* pIdToBlob = &idToBlob;
558  TBranch* b = parameterSetsTree_->Branch(poolNames::idToParameterSetBlobsBranchName().c_str(),&pIdToBlob,om_->basketSize(), 0);
559 
561  itEnd = pset::Registry::instance()->end();
562  it != itEnd;
563  ++it) {
564  idToBlob.first = it->first;
565  idToBlob.second.pset() = it->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);
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.
629  for(RootOutputTreePtrArray::iterator it = treePointers_.begin(), itEnd = treePointers_.end(); it != itEnd; ++it) {
630  (*it)->close();
631  (*it) = 0;
632  }
633  filePtr_->Close();
634  filePtr_.reset();
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, Selections const& branches) const {
644  if(tree && tree->GetNbranches() != 0) {
645  for(Selections::const_iterator i = branches.begin(), iEnd = branches.end();
646  i != iEnd; ++i) {
647  BranchDescription const& pd = **i;
648  std::string const& full = pd.branchName() + "obj";
649  if(pd.branchAliases().empty()) {
650  std::string const& alias =
651  (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
652  tree->SetAlias(alias.c_str(), full.c_str());
653  } else {
654  std::set<std::string>::const_iterator it = pd.branchAliases().begin(), itEnd = pd.branchAliases().end();
655  for(; it != itEnd; ++it) {
656  tree->SetAlias((*it).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) {
669  assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
671  BranchMapper const& iMapper = *principal.branchMapperPtr();
672  std::vector<BranchID> const& parentIDs = iGetParents.parentage().parents();
673  for(std::vector<BranchID>::const_iterator it = parentIDs.begin(), itEnd = parentIDs.end();
674  it != itEnd; ++it) {
675  branchesWithStoredHistory_.insert(*it);
676  ProductProvenance const* info = iMapper.branchIDToProvenance(*it);
677  if(info) {
679  principal.getProvenance(info->branchID()).product().produced()) {
680  if(insertProductProvenance(*info,oToFill) ) {
681  //haven't seen this one yet
682  insertAncestors(*info, principal, produced, oToFill);
683  }
684  }
685  }
686  }
687  }
688 
690  BranchType const& branchType,
691  Principal const& principal,
692  StoredProductProvenanceVector* productProvenanceVecPtr) {
693 
694  typedef std::vector<std::pair<TClass*, void const*> > Dummies;
695  Dummies 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(OutputItemList::const_iterator i = items.begin(), iEnd = items.end(); i != iEnd; ++i) {
705 
706  BranchID const& id = i->branchDescription_->branchID();
707  branchesWithStoredHistory_.insert(id);
708 
709  bool produced = i->branchDescription_->produced();
710  bool keepProvenance = productProvenanceVecPtr != 0 &&
714  bool getProd = (produced || !fastCloning ||
715  treePointers_[branchType]->uncloned(i->branchDescription_->branchName()));
716 
717  void const* product = 0;
718  OutputHandle const oh = principal.getForOutput(id, getProd);
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.branchMapperPtr());
724  insertAncestors(*oh.productProvenance(), eventPrincipal, produced, provenanceToKeep);
725  }
726  product = oh.wrapper();
727  if(getProd) {
728  if(product == 0) {
729  // No product with this ID is in the event.
730  // Add a null product.
731  TClass* cp = gROOT->GetClass(i->branchDescription_->wrappedName().c_str());
732  product = cp->New();
733  dummies.emplace_back(cp, product);
734  }
735  i->product_ = product;
736  }
737  }
738 
739  if(productProvenanceVecPtr != 0) productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
740  treePointers_[branchType]->fillTree();
741  if(productProvenanceVecPtr != 0) productProvenanceVecPtr->clear();
742  for(Dummies::iterator it = dummies.begin(), itEnd = dummies.end(); it != itEnd; ++it) {
743  it->first->Destructor(const_cast<void *>(it->second));
744  }
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 }
RunNumber_t run() const
Definition: EventID.h:42
ProductProvenance const * branchIDToProvenance(BranchID const &bid) const
Definition: BranchMapper.cc:58
EventNumber_t event() const
Definition: EventID.h:44
std::string const & idToParameterSetBlobsBranchName()
Definition: BranchType.cc:249
int i
Definition: DBlmapReader.cc:9
bool isRealData() const
void beginInputFile(FileBlock const &fb, int remainingEvents)
BranchID const & branchID() const
LuminosityBlockAuxiliary lumiAux_
std::string const & BranchTypeToAuxiliaryBranchName(BranchType const &branchType)
Definition: BranchType.cc:114
int const & basketSize() const
SelectionsArray const & keptProducts() const
Definition: OutputModule.h:61
EventSelectionIDVector const & eventSelectionIDs() const
bool const & overrideInputFileSplitLevels() const
std::string const & parentageTreeName()
Definition: BranchType.cc:158
std::vector< BranchIDList > BranchIDLists
Definition: BranchIDList.h:19
int eventAutoFlushSize() const
std::string const & catalog() const
void writeProcessHistoryRegistry()
void writeOne(EventPrincipal const &e)
std::string & branchName() const
static ThreadSafeRegistry * instance()
std::string const & moduleLabel() const
DropMetaData const & dropMetaData() const
void writeProcessConfigurationRegistry()
std::map< BranchKey, BranchDescription > ProductList
bool checkSplitLevelsAndBasketSizes(TTree *inputTree) const
EventID const & id() const
ProductProvenance const * productProvenance() const
Definition: OutputHandle.h:101
int whyNotFastClonable() const
Definition: FileBlock.h:108
RunNumber_t run() const
bool getMapped(key_type const &k, value_type &result) const
void insertAncestors(ProductProvenance const &iGetParents, EventPrincipal const &principal, bool produced, std::set< StoredProductProvenance > &oToFill)
LuminosityBlockAuxiliary const & aux() const
std::string const & fileFormatVersionBranchName()
Definition: BranchType.cc:212
OutputItemListArray const & selectedOutputItemList() const
std::string const & processName() const
std::string match(BranchDescription const &a, BranchDescription const &b, std::string const &fileName, BranchDescription::MatchMode m)
std::string const & eventSelectionsBranchName()
Definition: BranchType.cc:237
bool int lh
Definition: SIMDVec.h:19
unsigned int const & maxFileSize() const
void setBranchAliases(TTree *tree, Selections const &branches) const
MD5Result digest() const
Definition: Digest.cc:194
void setAutoFlush(Long64_t size)
bool insertMapped(value_type const &v)
BranchListIndexes const & branchListIndexes() const
bool shouldWeCloseFile() const
unsigned int id() const
Definition: BranchID.h:23
bool checkIfFastClonable(TTree *inputTree) const
void addBranch(std::string const &branchName, std::string const &className, WrapperInterfaceBase const *interface, void const *&pProd, int splitLevel, int basketSize, bool produced)
BranchType
Definition: BranchType.h:11
std::set< BranchID > branchesWithStoredHistory_
std::vector< EventSelectionID > EventSelectionIDVector
void sortVector_Run_Or_Lumi_Entries()
LuminosityBlockNumber_t luminosityBlock() const
std::string const & parameterSetsTreeName()
Definition: BranchType.cc:245
ProcessConfigurationRegistry::vector_type ProcessConfigurationVector
bool wantAllEvents() const
Definition: OutputModule.h:71
std::vector< BranchID > const & parents() const
Definition: Parentage.h:38
std::map< ParentageID, unsigned int > parentageIDs_
RootOutputTree eventTree_
std::map< key_type, value_type > collection_type
std::vector< BranchListIndex > BranchListIndexes
void writeRun(RunPrincipal const &r)
PoolOutputModule const * om_
std::string const & compressionAlgorithm() const
std::string const & moduleLabel() const
boost::shared_ptr< BranchMapper > branchMapperPtr() const
IndexIntoFile::EntryNumber_t eventEntryNumber_
std::string const & productInstanceName() const
ProcessHistoryID const & processHistoryID() const
Definition: Principal.h:129
iterator end()
Definition: Selections.h:367
LuminosityBlockAuxiliary const * pLumiAux_
std::string const & indexIntoFileBranchName()
Definition: BranchType.cc:227
collection_type::const_iterator const_iterator
std::string const & basketOrder() const
void fillBranches(BranchType const &branchType, Principal const &principal, StoredProductProvenanceVector *productProvenanceVecPtr)
Definition: GenABIO.cc:193
int getFileFormatVersion()
void const * wrapper() const
Definition: OutputHandle.h:89
std::string logicalFile_
bool checkEntriesInReadBranches(Long64_t expectedNumberOfEntries) const
OutputHandle getForOutput(BranchID const &bid, bool getProd) const
Definition: Principal.cc:673
ProcessHistoryRegistry::vector_type ProcessHistoryVector
iterator begin()
Definition: Selections.h:366
WrapperInterfaceBase const * getInterface() const
RunAuxiliary const & aux() const
Definition: RunPrincipal.h:42
void setProcessHistoryID(ProcessHistoryID const &phid)
#define end
Definition: vmac.h:38
std::string const & metaDataTreeName()
Definition: BranchType.cc:167
std::string & wrappedName() const
PoolOutputModule::OutputItemList OutputItemList
LuminosityBlockNumber_t luminosityBlock() const
void addEntry(ProcessHistoryID const &processHistoryID, RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event, EntryNumber_t entry)
static TTree * makeTTree(TFile *filePtr, std::string const &name, int splitLevel)
int const & whyNotFastClonable() const
std::string const & fullClassName() const
std::string const & processHistoryBranchName()
Definition: BranchType.cc:197
EventSelectionIDVector const * pEventSelectionIDs_
StoredProductProvenanceVector * pEventEntryInfoVector_
eventsetup::produce::Produce produced
Definition: ESProducts.cc:21
BranchChildren const & branchChildren() const
Definition: OutputModule.h:69
Provenance getProvenance(ProductID const &pid) const
void sort_all(RandomAccessSequence &s)
wrappers for std::sort
Definition: Algorithms.h:120
RootOutputTree runTree_
std::string toString() const
Definition: Digest.cc:87
std::string const & parentageBranchName()
Definition: BranchType.cc:162
double b
Definition: hdecay.h:120
string const
Definition: compareJSON.py:14
void addContext(std::string const &context)
Definition: Exception.cc:227
AuxItemArray const & auxItems() const
std::set< std::string > const & branchAliases() const
bool insertProductProvenance(const ProductProvenance &, std::set< StoredProductProvenance > &oToInsert)
void addAuxiliary(std::string const &branchName, T const *&pAux, int bufSize, bool allowCloning=true)
std::vector< StoredProductProvenance > StoredProductProvenanceVector
void respondToCloseInputFile(FileBlock const &fb)
IndexIntoFile indexIntoFile_
std::string const & productDescriptionBranchName()
Definition: BranchType.cc:172
IndexIntoFile::EntryNumber_t runEntryNumber_
std::string const & processConfigurationBranchName()
Definition: BranchType.cc:202
void writeLuminosityBlock(LuminosityBlockPrincipal const &lb)
ParentageID const & parentageID() const
static void writeTTree(TTree *tree)
ProcessHistoryID const & processHistoryID() const
EventAuxiliary const * pEventAux_
RunAuxiliary runAux_
BranchIDLists const * branchIDLists() const
void writeProductDescriptionRegistry()
std::string const & BranchTypeToProductProvenanceBranchName(BranchType const &BranchType)
Definition: BranchType.cc:130
std::string const & productDependenciesBranchName()
Definition: BranchType.cc:177
RootOutputFile(PoolOutputModule *om, std::string const &fileName, std::string const &logicalFileName)
std::string const & branchIDListBranchName()
Definition: BranchType.cc:207
void setProcessHistoryID(ProcessHistoryID const &phid)
Definition: RunAuxiliary.h:36
std::string const & branchListIndexesBranchName()
Definition: BranchType.cc:241
Parentage const & parentage() const
RootOutputTreePtrArray treePointers_
BranchListIndexes const * pBranchListIndexes_
collection_type & data()
Provide access to the contained collection.
void maybeFastCloneTree(bool canFastClone, bool canFastCloneAux, TTree *tree, std::string const &option)
IndexIntoFile::EntryNumber_t lumiEntryNumber_
RootOutputTree lumiTree_
boost::shared_ptr< TFile > filePtr_
void optimizeBaskets(ULong64_t size)
EventAuxiliary const & aux() const
TTree * tree() const
Definition: FileBlock.h:101
std::string const & fileIdentifierBranchName()
Definition: BranchType.cc:217
RunAuxiliary const * pRunAux_
tuple size
Write out results.
EventNumber_t event() const
RunNumber_t run() const
Definition: RunAuxiliary.h:41
int const & inputFileCount() const
JobReport::Token reportToken_
std::string createGlobalIdentifier()
std::string const & fileName() const
Definition: FileBlock.h:110
ParameterSetID selectorConfig() const
Definition: OutputModule.h:92