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 
33 
34 #include "TROOT.h"
35 #include "TTree.h"
36 #include "TFile.h"
37 #include "TClass.h"
38 #include "Rtypes.h"
39 #include "RVersion.h"
40 
41 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
42 #include "Compression.h"
43 #endif
44 
45 #include <algorithm>
46 #include <iomanip>
47 #include <sstream>
48 
49 namespace edm {
50 
51  namespace {
52  bool
53  sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
54  return
55  lh->fullClassName() < rh->fullClassName() ? true :
56  lh->fullClassName() > rh->fullClassName() ? false :
57  lh->moduleLabel() < rh->moduleLabel() ? true :
58  lh->moduleLabel() > rh->moduleLabel() ? false :
59  lh->productInstanceName() < rh->productInstanceName() ? true :
60  lh->productInstanceName() > rh->productInstanceName() ? false :
61  lh->processName() < rh->processName() ? true :
62  false;
63  }
64  }
65 
66  RootOutputFile::RootOutputFile(PoolOutputModule* om, std::string const& fileName, std::string const& logicalFileName) :
67  file_(fileName),
68  logicalFile_(logicalFileName),
69  reportToken_(0),
70  om_(om),
71  whyNotFastClonable_(om_->whyNotFastClonable()),
72  canFastCloneAux_(false),
73  filePtr_(TFile::Open(file_.c_str(), "recreate", "", om_->compressionLevel())),
74  fid_(),
75  eventEntryNumber_(0LL),
76  lumiEntryNumber_(0LL),
77  runEntryNumber_(0LL),
78  indexIntoFile_(),
79  metaDataTree_(0),
80  parameterSetsTree_(0),
81  parentageTree_(0),
82  lumiAux_(),
83  runAux_(),
84  pEventAux_(0),
85  pLumiAux_(&lumiAux_),
86  pRunAux_(&runAux_),
87  eventEntryInfoVector_(),
88  pEventEntryInfoVector_(&eventEntryInfoVector_),
89  pBranchListIndexes_(0),
90  pEventSelectionIDs_(0),
91  eventTree_(filePtr_, InEvent, om_->splitLevel(), om_->treeMaxVirtualSize()),
92  lumiTree_(filePtr_, InLumi, om_->splitLevel(), om_->treeMaxVirtualSize()),
93  runTree_(filePtr_, InRun, om_->splitLevel(), om_->treeMaxVirtualSize()),
94  treePointers_(),
95  dataTypeReported_(false),
96  parentageIDs_(),
97  branchesWithStoredHistory_() {
98 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
99  if (om_->compressionAlgorithm() == std::string("ZLIB")) {
100  filePtr_->SetCompressionAlgorithm(ROOT::kZLIB);
101  } else if (om_->compressionAlgorithm() == std::string("LZMA")) {
102  filePtr_->SetCompressionAlgorithm(ROOT::kLZMA);
103  } else {
104  throw Exception(errors::Configuration) << "PoolOutputModule configured with unknown compression algorithm '" << om_->compressionAlgorithm() << "'\n"
105  << "Allowed compression algorithms are ZLIB and LZMA\n";
106  }
107 #endif
108  if (-1 != om->eventAutoFlushSize()) {
110  }
112  pEventAux_, om_->auxItems()[InEvent].basketSize_);
114  pEventEntryInfoVector_, om_->auxItems()[InEvent].basketSize_);
116  pEventSelectionIDs_, om_->auxItems()[InEvent].basketSize_,false);
118  pBranchListIndexes_, om_->auxItems()[InEvent].basketSize_);
119 
121  pLumiAux_, om_->auxItems()[InLumi].basketSize_);
122 
124  pRunAux_, om_->auxItems()[InRun].basketSize_);
125 
127  treePointers_[InLumi] = &lumiTree_;
128  treePointers_[InRun] = &runTree_;
129 
130  for(int i = InEvent; i < NumBranchTypes; ++i) {
131  BranchType branchType = static_cast<BranchType>(i);
132  RootOutputTree *theTree = treePointers_[branchType];
133  for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[branchType].begin(),
134  itEnd = om_->selectedOutputItemList()[branchType].end();
135  it != itEnd; ++it) {
136  it->product_ = 0;
137  BranchDescription const& desc = *it->branchDescription_;
138  desc.init();
139  theTree->addBranch(desc.branchName(),
140  desc.wrappedName(),
141  desc.getInterface(),
142  it->product_,
143  it->splitLevel_,
144  it->basketSize_,
145  it->branchDescription_->produced());
146  //make sure we always store product registry info for all branches we create
147  branchesWithStoredHistory_.insert(it->branchID());
148  }
149  }
150  // Don't split metadata tree or event description tree
154 
156 
157  // For the Job Report, get a vector of branch names in the "Events" tree.
158  // Also create a hash of all the branch names in the "Events" tree
159  // in a deterministic order, except use the full class name instead of the friendly class name.
160  // To avoid extra string copies, we create a vector of pointers into the product registry,
161  // and use a custom comparison operator for sorting.
162  std::vector<std::string> branchNames;
163  std::vector<BranchDescription const*> branches;
164  branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
165  branches.reserve(om->selectedOutputItemList()[InEvent].size());
166  for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[InEvent].begin(),
167  itEnd = om_->selectedOutputItemList()[InEvent].end();
168  it != itEnd; ++it) {
169  branchNames.push_back(it->branchDescription_->branchName());
170  branches.push_back(it->branchDescription_);
171  }
172  // Now sort the branches for the hash.
173  sort_all(branches, sorterForJobReportHash);
174  // Now, make a concatenated string.
175  std::ostringstream oss;
176  char const underscore = '_';
177  for(std::vector<BranchDescription const*>::const_iterator it = branches.begin(), itEnd = branches.end(); it != itEnd; ++it) {
178  BranchDescription const& bd = **it;
179  oss << bd.fullClassName() << underscore
180  << bd.moduleLabel() << underscore
181  << bd.productInstanceName() << underscore
182  << bd.processName() << underscore;
183  }
184  std::string stringrep = oss.str();
185  cms::Digest md5alg(stringrep);
186 
187  // Register the output file with the JobReport service
188  // and get back the token for it.
189  std::string moduleName = "PoolOutputModule";
190  Service<JobReport> reportSvc;
191  reportToken_ = reportSvc->outputFileOpened(
192  file_, logicalFile_, // PFN and LFN
193  om_->catalog(), // catalog
194  moduleName, // module class name
195  om_->moduleLabel(), // module label
196  fid_.fid(), // file id (guid)
197  std::string(), // data type (not yet known, so string is empty).
198  md5alg.digest().toString(), // branch hash
199  branchNames); // branch names being written
200  }
201 
202  namespace {
203  void
204  maybeIssueWarning(int whyNotFastClonable, std::string const& ifileName, std::string const& ofileName) {
205 
206  // No message if fast cloning was deliberately disabled, or if there are no events to copy anyway.
207  if ((whyNotFastClonable &
209  return;
210  }
211 
212  // There will be a message stating every reason that fast cloning was not possible.
213  // If at one or more of the reasons was because of something the user explicitly specified (e.g. event selection, skipping events),
214  // or if the input file was in an old format, the message will be informational. Otherwise, the message will be a warning.
215  bool isWarning = true;
216  std::ostringstream message;
217  message << "Fast copying of file " << ifileName << " to file " << ofileName << " is disabled because:\n";
218  if((whyNotFastClonable & FileBlock::HasSecondaryFileSequence) != 0) {
219  message << "a SecondaryFileSequence was specified.\n";
220  whyNotFastClonable &= ~(FileBlock::HasSecondaryFileSequence);
221  isWarning = false;
222  }
223  if((whyNotFastClonable & FileBlock::FileTooOld) != 0) {
224  message << "the input file is in an old format.\n";
225  whyNotFastClonable &= ~(FileBlock::FileTooOld);
226  isWarning = false;
227  }
228  if((whyNotFastClonable & FileBlock::EventsToBeSorted) != 0) {
229  message << "events need to be sorted.\n";
230  whyNotFastClonable &= ~(FileBlock::EventsToBeSorted);
231  }
232  if((whyNotFastClonable & FileBlock::RunOrLumiNotContiguous) != 0) {
233  message << "a run or a lumi is not contiguous in the input file.\n";
234  whyNotFastClonable &= ~(FileBlock::RunOrLumiNotContiguous);
235  }
236  if((whyNotFastClonable & FileBlock::EventsOrLumisSelectedByID) != 0) {
237  message << "events or lumis were selected or skipped by ID.\n";
238  whyNotFastClonable &= ~(FileBlock::EventsOrLumisSelectedByID);
239  isWarning = false;
240  }
241  if((whyNotFastClonable & FileBlock::InitialEventsSkipped) != 0) {
242  message << "initial events, lumis or runs were skipped.\n";
243  whyNotFastClonable &= ~(FileBlock::InitialEventsSkipped);
244  isWarning = false;
245  }
246  if((whyNotFastClonable & FileBlock::DuplicateEventsRemoved) != 0) {
247  message << "some events were skipped because of duplicate checking.\n";
248  whyNotFastClonable &= ~(FileBlock::DuplicateEventsRemoved);
249  }
250  if((whyNotFastClonable & FileBlock::MaxEventsTooSmall) != 0) {
251  message << "some events were not copied because of maxEvents limit.\n";
252  whyNotFastClonable &= ~(FileBlock::MaxEventsTooSmall);
253  isWarning = false;
254  }
255  if((whyNotFastClonable & FileBlock::MaxLumisTooSmall) != 0) {
256  message << "some events were not copied because of maxLumis limit.\n";
257  whyNotFastClonable &= ~(FileBlock::MaxLumisTooSmall);
258  isWarning = false;
259  }
260  if((whyNotFastClonable & FileBlock::ParallelProcesses) != 0) {
261  message << "parallel processing was specified.\n";
262  whyNotFastClonable &= ~(FileBlock::ParallelProcesses);
263  isWarning = false;
264  }
265  if((whyNotFastClonable & FileBlock::EventSelectionUsed) != 0) {
266  message << "an EventSelector was specified.\n";
267  whyNotFastClonable &= ~(FileBlock::EventSelectionUsed);
268  isWarning = false;
269  }
270  if((whyNotFastClonable & FileBlock::OutputMaxEventsTooSmall) != 0) {
271  message << "some events were not copied because of maxEvents output limit.\n";
272  whyNotFastClonable &= ~(FileBlock::OutputMaxEventsTooSmall);
273  isWarning = false;
274  }
275  if((whyNotFastClonable & FileBlock::SplitLevelMismatch) != 0) {
276  message << "the split level or basket size of a branch or branches was modified.\n";
277  whyNotFastClonable &= ~(FileBlock::SplitLevelMismatch);
278  }
279  if((whyNotFastClonable & FileBlock::BranchMismatch) != 0) {
280  message << "The format of a data product has changed.\n";
281  whyNotFastClonable &= ~(FileBlock::BranchMismatch);
282  }
283  assert(whyNotFastClonable == FileBlock::CanFastClone);
284  if (isWarning) {
285  LogWarning("FastCloningDisabled") << message.str();
286  } else {
287  LogInfo("FastCloningDisabled") << message.str();
288  }
289  }
290  }
291 
292  void RootOutputFile::beginInputFile(FileBlock const& fb, int remainingEvents) {
293 
294  // Reset per input file information
296  canFastCloneAux_ = false;
297 
298  if(fb.tree() != 0) {
299 
301 
302  if(remainingEvents >= 0 && remainingEvents < fb.tree()->GetEntries()) {
304  }
305 
307  if(!match) {
309  // We may be fast copying. We must disable fast copying if the split levels
310  // or basket sizes do not match.
312  } else {
313  // We are using the input split levels and basket sizes from the first input file
314  // for copied output branches. In this case, we throw an exception if any branches
315  // have different split levels or basket sizes in a subsequent input file.
316  // If the mismatch is in the first file, there is a bug somewhere, so we assert.
317  assert(om_->inputFileCount() > 1);
318  throw Exception(errors::MismatchedInputFiles, "RootOutputFile::beginInputFile()") <<
319  "Merge failure because input file " << file_ << " has different ROOT split levels or basket sizes\n" <<
320  "than previous files. To allow merging in splite of this, use the configuration parameter\n" <<
321  "overrideInputFileSplitLevels=cms.untracked.bool(True)\n" <<
322  "in every PoolOutputModule.\n";
323  }
324  }
325 
326  // Since this check can be time consuming, we do it only if we would otherwise fast clone.
328  if(!eventTree_.checkIfFastClonable(fb.tree())) {
330  }
331  }
332  // We now check if we can fast copy the auxiliary branches.
333  // We can do so only if we can otherwise fast copy,
334  // the input file has the current format (these branches are in the Events Tree),
335  // there are no newly dropped or produced products,
336  // no metadata has been dropped,
337  // ID's have not been modified,
338  // and the branch list indexes do not need modification.
345  !reg->anyProductProduced() &&
346  !fb.modifiedIDs() &&
348 
349  // Report the fast copying status.
350  Service<JobReport> reportSvc;
351  reportSvc->reportFastCopyingStatus(reportToken_, fb.fileName(), whyNotFastClonable_ == FileBlock::CanFastClone);
352  } else {
354  }
355 
357 
358  // Possibly issue warning or informational message if we haven't fast cloned.
359  if(fb.tree() != 0 && whyNotFastClonable_ != FileBlock::CanFastClone) {
360  maybeIssueWarning(whyNotFastClonable_, fb.fileName(), file_);
361  }
362  }
363 
368  }
369 
371  unsigned int const oneK = 1024;
372  Long64_t size = filePtr_->GetSize()/oneK;
373  return(size >= om_->maxFileSize());
374  }
375 
377  // Auxiliary branch
378  pEventAux_ = &e.aux();
379 
380  // Because getting the data may cause an exception to be thrown we want to do that
381  // first before writing anything to the file about this event
382  // NOTE: pEventAux_, pBranchListIndexes_, pEventSelectionIDs_, and pEventEntryInfoVector_
383  // must be set before calling fillBranches since they get written out in that routine.
384  assert(pEventAux_->processHistoryID() == e.processHistoryID());
386 
387  // Note: The EventSelectionIDVector should have a one to one correspondence with the processes in the process history.
388  // Therefore, a new entry should be added if and only if the current process has been added to the process history,
389  // which is done if and only if there is a produced product.
392  if (reg->anyProductProduced() || !om_->wantAllEvents()) {
393  esids.push_back(om_->selectorConfig());
394  }
395  pEventSelectionIDs_ = &esids;
397 
398  // Add the dataType to the job report if it hasn't already been done
399  if(!dataTypeReported_) {
400  Service<JobReport> reportSvc;
401  std::string dataType("MC");
402  if(pEventAux_->isRealData()) dataType = "Data";
403  reportSvc->reportDataType(reportToken_, dataType);
404  dataTypeReported_ = true;
405  }
406 
407  // Store the reduced ID in the IndexIntoFile
408  ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(e.processHistoryID());
409  // Add event to index
412 
413  // Report event written
414  Service<JobReport> reportSvc;
415  reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
416  }
417 
419  // Auxiliary branch
420  // NOTE: lumiAux_ must be filled before calling fillBranches since it gets written out in that routine.
421  lumiAux_ = lb.aux();
422  // Use the updated process historyID
424  // Store the reduced ID in the IndexIntoFile
425  ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(lb.processHistoryID());
426  // Add lumi to index.
429  fillBranches(InLumi, lb, 0);
430  lumiTree_.optimizeBaskets(10ULL*1024*1024);
431  }
432 
434  // Auxiliary branch
435  // NOTE: runAux_ must be filled before calling fillBranches since it gets written out in that routine.
436  runAux_ = r.aux();
437  // Use the updated process historyID
439  // Store the reduced ID in the IndexIntoFile
440  ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(r.processHistoryID());
441  // Add run to index.
442  indexIntoFile_.addEntry(reducedPHID, runAux_.run(), 0U, 0U, runEntryNumber_);
443  ++runEntryNumber_;
444  fillBranches(InRun, r, 0);
445  runTree_.optimizeBaskets(10ULL*1024*1024);
446  }
447 
449  Parentage const* desc(0);
450 
451  if(!parentageTree_->Branch(poolNames::parentageBranchName().c_str(),
452  &desc, om_->basketSize(), 0))
454  << "Failed to create a branch for Parentages in the output file";
455 
456 
457  //NOTE: for some reason the empty Parentage is not added to the registry some of the time
459  ptReg.insertMapped(Parentage());
460 
461  std::vector<ParentageID> orderedIDs(parentageIDs_.size());
462  for(std::map<ParentageID,unsigned int>::const_iterator it = parentageIDs_.begin(),
463  itEnd = parentageIDs_.end();
464  it != itEnd;
465  ++it) {
466  orderedIDs[it->second]=it->first;
467  }
468  //now put them into the TTree in the correct order
469  for(std::vector<ParentageID>::const_iterator it = orderedIDs.begin(),
470  itEnd = orderedIDs.end();
471  it != itEnd;
472  ++it) {
473  desc = ptReg.getMapped(*it);
474  if (0!=desc) {
475  //NOTE: some old format files have missing Parentage info
476  // so this can't be fatal.
477  parentageTree_->Fill();
478  }
479  }
480  }
481 
483  FileFormatVersion fileFormatVersion(getFileFormatVersion());
484  FileFormatVersion* pFileFmtVsn = &fileFormatVersion;
485  TBranch* b = metaDataTree_->Branch(poolNames::fileFormatVersionBranchName().c_str(), &pFileFmtVsn, om_->basketSize(), 0);
486  assert(b);
487  b->Fill();
488  }
489 
491  FileID* fidPtr = &fid_;
492  TBranch* b = metaDataTree_->Branch(poolNames::fileIdentifierBranchName().c_str(), &fidPtr, om_->basketSize(), 0);
493  assert(b);
494  b->Fill();
495  }
496 
500  ex << "The number of entries in at least one output TBranch whose entries\n"
501  "were copied from the input does not match the number of events\n"
502  "recorded in IndexIntoFile. This might (or might not) indicate a\n"
503  "problem related to fast copy.";
504  ex.addContext("Calling RootOutputFile::writeIndexIntoFile");
505  throw ex;
506  }
508  IndexIntoFile* iifPtr = &indexIntoFile_;
509  TBranch* b = metaDataTree_->Branch(poolNames::indexIntoFileBranchName().c_str(), &iifPtr, om_->basketSize(), 0);
510  assert(b);
511  b->Fill();
512  }
513 
516  Map const& procConfigMap = ProcessConfigurationRegistry::instance()->data();
517  ProcessConfigurationVector procConfigVector;
518  for(Map::const_iterator i = procConfigMap.begin(), e = procConfigMap.end(); i != e; ++i) {
519  procConfigVector.push_back(i->second);
520  }
521  sort_all(procConfigVector);
522  ProcessConfigurationVector* p = &procConfigVector;
523  TBranch* b = metaDataTree_->Branch(poolNames::processConfigurationBranchName().c_str(), &p, om_->basketSize(), 0);
524  assert(b);
525  b->Fill();
526  }
527 
530  Map const& procHistoryMap = ProcessHistoryRegistry::instance()->data();
531  ProcessHistoryVector procHistoryVector;
532  for(Map::const_iterator i = procHistoryMap.begin(), e = procHistoryMap.end(); i != e; ++i) {
533  procHistoryVector.push_back(i->second);
534  }
535  ProcessHistoryVector* p = &procHistoryVector;
536  TBranch* b = metaDataTree_->Branch(poolNames::processHistoryBranchName().c_str(), &p, om_->basketSize(), 0);
537  assert(b);
538  b->Fill();
539  }
540 
543  TBranch* b = metaDataTree_->Branch(poolNames::branchIDListBranchName().c_str(), &p, om_->basketSize(), 0);
544  assert(b);
545  b->Fill();
546  }
547 
549  std::pair<ParameterSetID, ParameterSetBlob> idToBlob;
550  std::pair<ParameterSetID, ParameterSetBlob>* pIdToBlob = &idToBlob;
551  TBranch* b = parameterSetsTree_->Branch(poolNames::idToParameterSetBlobsBranchName().c_str(),&pIdToBlob,om_->basketSize(), 0);
552 
554  itEnd = pset::Registry::instance()->end();
555  it != itEnd;
556  ++it) {
557  idToBlob.first = it->first;
558  idToBlob.second.pset() = it->second.toString();
559 
560  b->Fill();
561  }
562  }
563 
565  // Make a local copy of the ProductRegistry, removing any transient or pruned products.
566  typedef ProductRegistry::ProductList ProductList;
568  ProductRegistry pReg(reg->productList());
569  ProductList& pList = const_cast<ProductList &>(pReg.productList());
570  std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
571  for(ProductList::iterator it = pList.begin(); it != pList.end();) {
572  if(branchesWithStoredHistory_.find(it->second.branchID()) == end) {
573  // avoid invalidating iterator on deletion
574  ProductList::iterator itCopy = it;
575  ++it;
576  pList.erase(itCopy);
577 
578  } else {
579  ++it;
580  }
581  }
582 
583  ProductRegistry* ppReg = &pReg;
584  TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
585  assert(b);
586  b->Fill();
587  }
589  BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
590  BranchChildren* ppDeps = &pDeps;
591  TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
592  assert(b);
593  b->Fill();
594  }
595 
597  metaDataTree_->SetEntries(-1);
600 
602 
603  // Create branch aliases for all the branches in the
604  // events/lumis/runs trees. The loop is over all types of data
605  // products.
606  for(int i = InEvent; i < NumBranchTypes; ++i) {
607  BranchType branchType = static_cast<BranchType>(i);
609  treePointers_[branchType]->writeTree();
610  }
611 
612  // close the file -- mfp
613  // Just to play it safe, zero all pointers to objects in the TFile to be closed.
615  for(RootOutputTreePtrArray::iterator it = treePointers_.begin(), itEnd = treePointers_.end(); it != itEnd; ++it) {
616  (*it)->close();
617  (*it) = 0;
618  }
619  filePtr_->Close();
620  filePtr_.reset();
621 
622  // report that file has been closed
623  Service<JobReport> reportSvc;
624  reportSvc->outputFileClosed(reportToken_);
625 
626  }
627 
628  void
629  RootOutputFile::setBranchAliases(TTree* tree, Selections const& branches) const {
630  if(tree && tree->GetNbranches() != 0) {
631  for(Selections::const_iterator i = branches.begin(), iEnd = branches.end();
632  i != iEnd; ++i) {
633  BranchDescription const& pd = **i;
634  std::string const& full = pd.branchName() + "obj";
635  if(pd.branchAliases().empty()) {
636  std::string const& alias =
637  (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
638  tree->SetAlias(alias.c_str(), full.c_str());
639  } else {
640  std::set<std::string>::const_iterator it = pd.branchAliases().begin(), itEnd = pd.branchAliases().end();
641  for(; it != itEnd; ++it) {
642  tree->SetAlias((*it).c_str(), full.c_str());
643  }
644  }
645  }
646  }
647  }
648 
649  void
651  EventPrincipal const& principal,
652  bool produced,
653  std::set<StoredProductProvenance>& oToFill) {
655  assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
657  BranchMapper const& iMapper = *principal.branchMapperPtr();
658  std::vector<BranchID> const& parentIDs = iGetParents.parentage().parents();
659  for(std::vector<BranchID>::const_iterator it = parentIDs.begin(), itEnd = parentIDs.end();
660  it != itEnd; ++it) {
661  branchesWithStoredHistory_.insert(*it);
662  ProductProvenance const* info = iMapper.branchIDToProvenance(*it);
663  if(info) {
665  principal.getProvenance(info->branchID()).product().produced()) {
666  if(insertProductProvenance(*info,oToFill) ) {
667  //haven't seen this one yet
668  insertAncestors(*info, principal, produced, oToFill);
669  }
670  }
671  }
672  }
673  }
674 
676  BranchType const& branchType,
677  Principal const& principal,
678  StoredProductProvenanceVector* productProvenanceVecPtr) {
679 
680  typedef std::vector<std::pair<TClass*, void const*> > Dummies;
681  Dummies dummies;
682 
683  bool const fastCloning = (branchType == InEvent) && (whyNotFastClonable_ == FileBlock::CanFastClone);
684 
686 
687  std::set<StoredProductProvenance> provenanceToKeep;
688 
689  // Loop over EDProduct branches, fill the provenance, and write the branch.
690  for(OutputItemList::const_iterator i = items.begin(), iEnd = items.end(); i != iEnd; ++i) {
691 
692  BranchID const& id = i->branchDescription_->branchID();
693  branchesWithStoredHistory_.insert(id);
694 
695  bool produced = i->branchDescription_->produced();
696  bool keepProvenance = productProvenanceVecPtr != 0 &&
700  bool getProd = (produced || !fastCloning ||
701  treePointers_[branchType]->uncloned(i->branchDescription_->branchName()));
702 
703  void const* product = 0;
704  OutputHandle const oh = principal.getForOutput(id, getProd);
705  if(keepProvenance && oh.productProvenance()) {
706  insertProductProvenance(*oh.productProvenance(),provenanceToKeep);
707  //provenanceToKeep.insert(*oh.productProvenance());
708  EventPrincipal const& eventPrincipal = dynamic_cast<EventPrincipal const&>(principal);
709  assert(eventPrincipal.branchMapperPtr());
710  insertAncestors(*oh.productProvenance(), eventPrincipal, produced, provenanceToKeep);
711  }
712  product = oh.wrapper();
713  if(getProd) {
714  if(product == 0) {
715  // No product with this ID is in the event.
716  // Add a null product.
717  TClass* cp = gROOT->GetClass(i->branchDescription_->wrappedName().c_str());
718  product = cp->New();
719  dummies.emplace_back(cp, product);
720  }
721  i->product_ = product;
722  }
723  }
724 
725  if(productProvenanceVecPtr != 0) productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
726  treePointers_[branchType]->fillTree();
727  if(productProvenanceVecPtr != 0) productProvenanceVecPtr->clear();
728  for(Dummies::iterator it = dummies.begin(), itEnd = dummies.end(); it != itEnd; ++it) {
729  it->first->Destructor(const_cast<void *>(it->second));
730  }
731  }
732 
733  bool
735  std::set<edm::StoredProductProvenance>& oToInsert) {
736  StoredProductProvenance toStore;
737  toStore.branchID_ = iProv.branchID().id();
738  std::set<edm::StoredProductProvenance>::iterator itFound = oToInsert.find(toStore);
739  if(itFound == oToInsert.end()) {
740  //get the index to the ParentageID or insert a new value if not already present
741  std::pair<std::map<edm::ParentageID,unsigned int>::iterator,bool> i = parentageIDs_.insert(std::make_pair(iProv.parentageID(),static_cast<unsigned int>(parentageIDs_.size())));
742  toStore.parentageIDIndex_ = i.first->second;
743  oToInsert.insert(toStore);
744  return true;
745  }
746  return false;
747  }
748 }
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:56
EventSelectionIDVector const & eventSelectionIDs() const
bool const & overrideInputFileSplitLevels() const
std::string const & parentageTreeName()
Definition: BranchType.cc:158
int eventAutoFlushSize() const
std::string const & catalog() const
void writeProcessHistoryRegistry()
void writeOne(EventPrincipal const &e)
std::string & branchName() const
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
FileFormatVersion const & fileFormatVersion() const
Definition: FileBlock.h:95
ProductProvenance const * productProvenance() const
Definition: OutputHandle.h:101
int whyNotFastClonable() const
Definition: FileBlock.h:103
std::array< bool, NumBranchTypes > const & hasNewlyDroppedBranch() const
Definition: FileBlock.h:104
RunNumber_t run() 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
static ThreadSafeRegistry * instance()
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: SSEVec.h:55
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)
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)
bool modifiedIDs() const
Definition: FileBlock.h:107
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:68
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)
bool getMapped(key_type const &k, value_type &result) const
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:126
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:659
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 ThreadSafeIndexedRegistry * instance()
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:66
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
bool branchListIndexesUnchanged() const
Definition: FileBlock.h:106
boost::array< bool, NumBranchTypes > const & hasNewlyDroppedBranch() const
Definition: OutputModule.h:57
EventAuxiliary const * pEventAux_
author Stefano ARGIRO author Bill Tanenbaum
RunAuxiliary runAux_
void writeProductDescriptionRegistry()
std::string const & BranchTypeToProductProvenanceBranchName(BranchType const &BranchType)
Definition: BranchType.cc:130
collection_type & data()
Provide access to the contained collection.
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)
bool insertMapped(value_type const &v)
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:96
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:105
ParameterSetID selectorConfig() const
Definition: OutputModule.h:86