CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PoolOutputModule.cc
Go to the documentation of this file.
2 
4 
19 
20 #include "TTree.h"
21 #include "TBranchElement.h"
22 #include "TObjArray.h"
23 #include "RVersion.h"
24 
25 #include <fstream>
26 #include <iomanip>
27 #include <sstream>
28 
29 namespace edm {
31  edm::one::OutputModuleBase::OutputModuleBase(pset),
32  one::OutputModule<WatchInputFiles>(pset),
33  rootServiceChecker_(),
34  auxItems_(),
35  selectedOutputItemList_(),
36  fileName_(pset.getUntrackedParameter<std::string>("fileName")),
37  logicalFileName_(pset.getUntrackedParameter<std::string>("logicalFileName")),
38  catalog_(pset.getUntrackedParameter<std::string>("catalog")),
39  maxFileSize_(pset.getUntrackedParameter<int>("maxSize")),
40  compressionLevel_(pset.getUntrackedParameter<int>("compressionLevel")),
41 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
42  compressionAlgorithm_(pset.getUntrackedParameter<std::string>("compressionAlgorithm")),
43 #else
44  compressionAlgorithm_("ZLIB"),
45 #endif
46  basketSize_(pset.getUntrackedParameter<int>("basketSize")),
47  eventAutoFlushSize_(pset.getUntrackedParameter<int>("eventAutoFlushCompressedSize")),
48  splitLevel_(std::min<int>(pset.getUntrackedParameter<int>("splitLevel") + 1, 99)),
49  basketOrder_(pset.getUntrackedParameter<std::string>("sortBaskets")),
50  treeMaxVirtualSize_(pset.getUntrackedParameter<int>("treeMaxVirtualSize")),
51  whyNotFastClonable_(pset.getUntrackedParameter<bool>("fastCloning") ? FileBlock::CanFastClone : FileBlock::DisabledInConfigFile),
52  dropMetaData_(DropNone),
53  moduleLabel_(pset.getParameter<std::string>("@module_label")),
54  initializedFromInput_(false),
55  outputFileCount_(0),
56  inputFileCount_(0),
57  childIndex_(0U),
58  numberOfDigitsInIndex_(0U),
59  overrideInputFileSplitLevels_(pset.getUntrackedParameter<bool>("overrideInputFileSplitLevels")),
60  rootOutputFile_(),
61  statusFileName_() {
62 
63  if (pset.getUntrackedParameter<bool>("writeStatusFile")) {
64  std::ostringstream statusfilename;
65  statusfilename << moduleLabel_ << '_' << getpid();
66  statusFileName_ = statusfilename.str();
67  }
68 
70  if(dropMetaData.empty()) dropMetaData_ = DropNone;
71  else if(dropMetaData == std::string("NONE")) dropMetaData_ = DropNone;
72  else if(dropMetaData == std::string("DROPPED")) dropMetaData_ = DropDroppedPrior;
73  else if(dropMetaData == std::string("PRIOR")) dropMetaData_ = DropPrior;
74  else if(dropMetaData == std::string("ALL")) dropMetaData_ = DropAll;
75  else {
76  throw edm::Exception(errors::Configuration, "Illegal dropMetaData parameter value: ")
77  << dropMetaData << ".\n"
78  << "Legal values are 'NONE', 'DROPPED', 'PRIOR', and 'ALL'.\n";
79  }
80 
81  if (!wantAllEvents()) {
83  }
84 
85  // We don't use this next parameter, but we read it anyway because it is part
86  // of the configuration of this module. An external parser creates the
87  // configuration by reading this source code.
88  pset.getUntrackedParameterSet("dataset");
89  }
90 
92  for(int i = InEvent; i < NumBranchTypes; ++i) {
93  BranchType branchType = static_cast<BranchType>(i);
94  SelectedProducts const& keptVector = keptProducts()[branchType];
95  for(SelectedProducts::const_iterator it = keptVector.begin(), itEnd = keptVector.end(); it != itEnd; ++it) {
96  BranchDescription const& prod = **it;
97  checkDictionaries(prod.fullClassName(), true);
99  }
100  }
101  }
102 
104  return rootOutputFile_->fileName();
105  }
106 
108  basketSize_(BranchDescription::invalidBasketSize) {}
109 
111  branchDescription_(0),
112  product_(0),
113  splitLevel_(BranchDescription::invalidSplitLevel),
114  basketSize_(BranchDescription::invalidBasketSize) {}
115 
117  branchDescription_(bd),
118  product_(0),
119  splitLevel_(splitLevel),
120  basketSize_(basketSize) {}
121 
122 
123  PoolOutputModule::OutputItem::Sorter::Sorter(TTree* tree) : treeMap_(new std::map<std::string, int>) {
124  // Fill a map mapping branch names to an index specifying the order in the tree.
125  if(tree != 0) {
126  TObjArray* branches = tree->GetListOfBranches();
127  for(int i = 0; i < branches->GetEntries(); ++i) {
128  TBranchElement* br = (TBranchElement*)branches->At(i);
129  treeMap_->insert(std::make_pair(std::string(br->GetName()), i));
130  }
131  }
132  }
133 
134  bool
136  // Provides a comparison for sorting branches according to the index values in treeMap_.
137  // Branches not found are always put at the end (i.e. not found > found).
138  if(treeMap_->empty()) return lh < rh;
139  std::string const& lstring = lh.branchDescription_->branchName();
140  std::string const& rstring = rh.branchDescription_->branchName();
141  std::map<std::string, int>::const_iterator lit = treeMap_->find(lstring);
142  std::map<std::string, int>::const_iterator rit = treeMap_->find(rstring);
143  bool lfound = (lit != treeMap_->end());
144  bool rfound = (rit != treeMap_->end());
145  if(lfound && rfound) {
146  return lit->second < rit->second;
147  } else if(lfound) {
148  return true;
149  } else if(rfound) {
150  return false;
151  }
152  return lh < rh;
153  }
154 
156 
157  SelectedProducts const& keptVector = keptProducts()[branchType];
159  AuxItem& auxItem = auxItems_[branchType];
160 
161  // Fill AuxItem
162  if (theInputTree != 0 && !overrideInputFileSplitLevels_) {
163  TBranch* auxBranch = theInputTree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
164  if (auxBranch) {
165  auxItem.basketSize_ = auxBranch->GetBasketSize();
166  } else {
167  auxItem.basketSize_ = basketSize_;
168  }
169  } else {
170  auxItem.basketSize_ = basketSize_;
171  }
172 
173  // Fill outputItemList with an entry for each branch.
174  for(SelectedProducts::const_iterator it = keptVector.begin(), itEnd = keptVector.end(); it != itEnd; ++it) {
177 
178  BranchDescription const& prod = **it;
179  TBranch* theBranch = ((!prod.produced() && theInputTree != 0 && !overrideInputFileSplitLevels_) ? theInputTree->GetBranch(prod.branchName().c_str()) : 0);
180 
181  if(theBranch != 0) {
182  splitLevel = theBranch->GetSplitLevel();
183  basketSize = theBranch->GetBasketSize();
184  } else {
185  splitLevel = (prod.splitLevel() == BranchDescription::invalidSplitLevel ? splitLevel_ : prod.splitLevel());
186  basketSize = (prod.basketSize() == BranchDescription::invalidBasketSize ? basketSize_ : prod.basketSize());
187  }
188  outputItemList.emplace_back(&prod, splitLevel, basketSize);
189  }
190 
191  // Sort outputItemList to allow fast copying.
192  // The branches in outputItemList must be in the same order as in the input tree, with all new branches at the end.
193  sort_all(outputItemList, OutputItem::Sorter(theInputTree));
194  }
195 
197  if(isFileOpen()) {
198  rootOutputFile_->beginInputFile(fb, remainingEvents());
199  }
200  }
201 
203  if(!isFileOpen()) {
204  reallyOpenFile();
205  beginInputFile(fb);
206  }
207  }
208 
210  if(!initializedFromInput_) {
211  for(int i = InEvent; i < NumBranchTypes; ++i) {
212  BranchType branchType = static_cast<BranchType>(i);
213  TTree* theInputTree = (branchType == InEvent ? fb.tree() :
214  (branchType == InLumi ? fb.lumiTree() :
215  fb.runTree()));
216  fillSelectedItemList(branchType, theInputTree);
217  }
218  initializedFromInput_ = true;
219  }
220  ++inputFileCount_;
221  beginInputFile(fb);
222  }
223 
225  if(rootOutputFile_) rootOutputFile_->respondToCloseInputFile(fb);
226  }
227 
228  void PoolOutputModule::postForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren) {
229  childIndex_ = iChildIndex;
230  while (iNumberOfChildren != 0) {
232  iNumberOfChildren /= 10;
233  }
234  if (numberOfDigitsInIndex_ == 0) {
235  numberOfDigitsInIndex_ = 3; // Protect against zero iNumberOfChildren
236  }
237  }
238 
240  }
241 
243  rootOutputFile_->writeOne(e, mcc);
244  if (!statusFileName_.empty()) {
245  std::ofstream statusFile(statusFileName_.c_str());
246  statusFile << e.id() << " time: " << std::setprecision(3) << TimeOfDay() << '\n';
247  statusFile.close();
248  }
249  }
250 
252  rootOutputFile_->writeLuminosityBlock(lb, mcc);
253  }
254 
256  rootOutputFile_->writeRun(r, mcc);
257  }
258 
260  startEndFile();
270  finishEndFile();
271 
273  }
274 
275 
276  // At some later date, we may move functionality from finishEndFile() to here.
278 
279  void PoolOutputModule::writeFileFormatVersion() { rootOutputFile_->writeFileFormatVersion(); }
280  void PoolOutputModule::writeFileIdentifier() { rootOutputFile_->writeFileIdentifier(); }
281  void PoolOutputModule::writeIndexIntoFile() { rootOutputFile_->writeIndexIntoFile(); }
282  void PoolOutputModule::writeProcessHistoryRegistry() { rootOutputFile_->writeProcessHistoryRegistry(); }
283  void PoolOutputModule::writeParameterSetRegistry() { rootOutputFile_->writeParameterSetRegistry(); }
284  void PoolOutputModule::writeProductDescriptionRegistry() { rootOutputFile_->writeProductDescriptionRegistry(); }
285  void PoolOutputModule::writeParentageRegistry() { rootOutputFile_->writeParentageRegistry(); }
286  void PoolOutputModule::writeBranchIDListRegistry() { rootOutputFile_->writeBranchIDListRegistry(); }
287  void PoolOutputModule::writeProductDependencies() { rootOutputFile_->writeProductDependencies(); }
290  bool PoolOutputModule::isFileOpen() const { return rootOutputFile_.get() != 0; }
291  bool PoolOutputModule::shouldWeCloseFile() const { return rootOutputFile_->shouldWeCloseFile(); }
292 
293  std::pair<std::string, std::string>
295  if(inputFileCount_ == 0) {
297  << "Attempt to open output file before input file. "
298  << "Please report this to the core framework developers.\n";
299  }
300  std::string suffix(".root");
301  std::string::size_type offset = fileName().rfind(suffix);
302  bool ext = (offset == fileName().size() - suffix.size());
303  if(!ext) suffix.clear();
304  std::string fileBase(ext ? fileName().substr(0, offset) : fileName());
305  std::ostringstream ofilename;
306  std::ostringstream lfilename;
307  ofilename << fileBase;
308  lfilename << logicalFileName();
310  ofilename << '_' << std::setw(numberOfDigitsInIndex_) << std::setfill('0') << childIndex_;
311  if(!logicalFileName().empty()) {
312  lfilename << '_' << std::setw(numberOfDigitsInIndex_) << std::setfill('0') << childIndex_;
313  }
314  }
315  if(outputFileCount_) {
316  ofilename << std::setw(3) << std::setfill('0') << outputFileCount_;
317  if(!logicalFileName().empty()) {
318  lfilename << std::setw(3) << std::setfill('0') << outputFileCount_;
319  }
320  }
321  ofilename << suffix;
323 
324  return std::make_pair(ofilename.str(), lfilename.str());
325  }
326 
329  rootOutputFile_.reset( new RootOutputFile(this, names.first, names.second));
330  }
331 
332  void
334  std::string defaultString;
335 
336  desc.setComment("Writes runs, lumis, and events into EDM/ROOT files.");
337  desc.addUntracked<std::string>("fileName")
338  ->setComment("Name of output file.");
339  desc.addUntracked<std::string>("logicalFileName", defaultString)
340  ->setComment("Passed to job report. Otherwise unused by module.");
341  desc.addUntracked<std::string>("catalog", defaultString)
342  ->setComment("Passed to job report. Otherwise unused by module.");
343  desc.addUntracked<int>("maxSize", 0x7f000000)
344  ->setComment("Maximum output file size, in kB.\n"
345  "If over maximum, new output file will be started at next input file transition.");
346  desc.addUntracked<int>("compressionLevel", 7)
347  ->setComment("ROOT compression level of output file.");
348 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,30,0)
349  desc.addUntracked<std::string>("compressionAlgorithm", "ZLIB")
350  ->setComment("Algorithm used to compress data in the ROOT output file, allowed values are ZLIB and LZMA");
351 #endif
352  desc.addUntracked<int>("basketSize", 16384)
353  ->setComment("Default ROOT basket size in output file.");
354  desc.addUntracked<int>("eventAutoFlushCompressedSize",-1)->setComment("Set ROOT auto flush stored data size (in bytes) for event TTree. The value sets how large the compressed buffer is allowed to get. The uncompressed buffer can be quite a bit larger than this depending on the average compression ratio. The value of -1 just uses ROOT's default value. The value of 0 turns off this feature.");
355  desc.addUntracked<int>("splitLevel", 99)
356  ->setComment("Default ROOT branch split level in output file.");
357  desc.addUntracked<std::string>("sortBaskets", std::string("sortbasketsbyoffset"))
358  ->setComment("Legal values: 'sortbasketsbyoffset', 'sortbasketsbybranch', 'sortbasketsbyentry'.\n"
359  "Used by ROOT when fast copying. Affects performance.");
360  desc.addUntracked<int>("treeMaxVirtualSize", -1)
361  ->setComment("Size of ROOT TTree TBasket cache. Affects performance.");
362  desc.addUntracked<bool>("fastCloning", true)
363  ->setComment("True: Allow fast copying, if possible.\n"
364  "False: Disable fast copying.");
365  desc.addUntracked<bool>("overrideInputFileSplitLevels", false)
366  ->setComment("False: Use branch split levels and basket sizes from input file, if possible.\n"
367  "True: Always use specified or default split levels and basket sizes.");
368  desc.addUntracked<bool>("writeStatusFile", false)
369  ->setComment("Write a status file. Intended for use by workflow management.");
370  desc.addUntracked<std::string>("dropMetaData", defaultString)
371  ->setComment("Determines handling of per product per event metadata. Options are:\n"
372  "'NONE': Keep all of it.\n"
373  "'DROPPED': Keep it for products produced in current process and all kept products. Drop it for dropped products produced in prior processes.\n"
374  "'PRIOR': Keep it for products produced in current process. Drop it for products produced in prior processes.\n"
375  "'ALL': Drop all of it.");
376  ParameterSetDescription dataSet;
377  dataSet.setAllowAnything();
378  desc.addUntracked<ParameterSetDescription>("dataset", dataSet)
379  ->setComment("PSet is only used by Data Operations and not by this module.");
380 
382  }
383 
384  void
388  descriptions.add("edmOutput", desc);
389  }
390 }
virtual void openFile(FileBlock const &fb) override
virtual std::pair< std::string, std::string > physicalAndLogicalNameForNewFile()
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
std::string const & branchName() const
std::string const & BranchTypeToAuxiliaryBranchName(BranchType const &branchType)
Definition: BranchType.cc:114
virtual void writeRun(RunPrincipal const &r, ModuleCallingContext const *) override
BranchDescription const * branchDescription_
int const & basketSize() const
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
static const HistoName names[]
static int const invalidSplitLevel
void setAllowAnything()
allow any parameter label/value pairs
static int const invalidBasketSize
DropMetaData const & dropMetaData() const
EventID const & id() const
std::vector< OutputItem > OutputItemList
std::string const & fileName() const
std::string const moduleLabel_
ParameterSet getUntrackedParameterSet(std::string const &name, ParameterSet const &defaultValue) const
bool int lh
Definition: SIMDVec.h:19
uint16_t size_type
virtual void doExtrasAfterCloseFile()
std::string const & logicalFileName() const
BranchType
Definition: BranchType.h:11
void fillSelectedItemList(BranchType branchtype, TTree *theInputTree)
PoolOutputModule(ParameterSet const &ps)
void setComment(std::string const &value)
bool operator()(OutputItem const &lh, OutputItem const &rh) const
std::string const & currentFileName() const
OutputItemListArray selectedOutputItemList_
void checkDictionaries(std::string const &name, bool noComponents=false)
SelectedProductsForBranchType const & keptProducts() const
int const & splitLevel() const
EventID const & min(EventID const &lh, EventID const &rh)
Definition: EventID.h:129
virtual void reallyOpenFile() override
std::unique_ptr< RootOutputFile > rootOutputFile_
unsigned int offset(bool)
unsigned int numberOfDigitsInIndex_
std::string const & fullClassName() const
void sort_all(RandomAccessSequence &s)
wrappers for std::sort
Definition: Algorithms.h:120
TTree * lumiTree() const
Definition: FileBlock.h:99
virtual bool shouldWeCloseFile() const override
allow inheriting classes to override but still be able to call this method in the overridden version ...
virtual void respondToCloseInputFile(FileBlock const &fb) override
std::string wrappedClassName(std::string const &iFullName)
virtual bool isFileOpen() const override
virtual void write(EventPrincipal const &e, ModuleCallingContext const *) override
virtual void beginJob() override
virtual void reallyCloseFile() override
void add(std::string const &label, ParameterSetDescription const &psetDescription)
virtual void writeLuminosityBlock(LuminosityBlockPrincipal const &lb, ModuleCallingContext const *) override
static void fillDescription(ParameterSetDescription &desc)
virtual void postForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren) override
std::shared_ptr< std::map< std::string, int > > treeMap_
if(dp >Float(M_PI)) dp-
std::vector< BranchDescription const * > SelectedProducts
void beginInputFile(FileBlock const &fb)
volatile std::atomic< bool > shutdown_flag false
virtual void respondToOpenInputFile(FileBlock const &fb) override
static void fillDescriptions(ConfigurationDescriptions &descriptions)
static void fillDescription(ParameterSetDescription &desc)
moduleLabel_(iConfig.getParameter< string >("@module_label"))
TTree * runTree() const
Definition: FileBlock.h:101
TTree * tree() const
Definition: FileBlock.h:97