Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-11 03:34:24

0001 #include "IOPool/Output/interface/PoolOutputModule.h"
0002 
0003 #include "IOPool/Output/src/RootOutputFile.h"
0004 
0005 #include "FWCore/Framework/interface/ConstProductRegistry.h"
0006 #include "FWCore/Framework/interface/EventForOutput.h"
0007 #include "FWCore/Framework/interface/LuminosityBlockForOutput.h"
0008 #include "FWCore/Framework/interface/RunForOutput.h"
0009 #include "FWCore/Framework/interface/FileBlock.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0013 #include "FWCore/ServiceRegistry/interface/Service.h"
0014 #include "DataFormats/Provenance/interface/BranchDescription.h"
0015 #include "DataFormats/Provenance/interface/Parentage.h"
0016 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
0017 #include "DataFormats/Provenance/interface/ProductProvenance.h"
0018 #include "FWCore/Framework/interface/ProductProvenanceRetriever.h"
0019 #include "DataFormats/Provenance/interface/SubProcessParentageHelper.h"
0020 #include "FWCore/Utilities/interface/Algorithms.h"
0021 #include "FWCore/Utilities/interface/EDMException.h"
0022 #include "FWCore/Utilities/interface/TimeOfDay.h"
0023 #include "FWCore/Utilities/interface/WrappedClassName.h"
0024 
0025 #include "TTree.h"
0026 #include "TBranchElement.h"
0027 #include "TObjArray.h"
0028 #include "RVersion.h"
0029 
0030 #include <fstream>
0031 #include <iomanip>
0032 #include <sstream>
0033 #include "boost/algorithm/string.hpp"
0034 
0035 namespace edm {
0036   PoolOutputModule::PoolOutputModule(ParameterSet const& pset)
0037       : edm::one::OutputModuleBase::OutputModuleBase(pset),
0038         one::OutputModule<WatchInputFiles>(pset),
0039         rootServiceChecker_(),
0040         auxItems_(),
0041         selectedOutputItemList_(),
0042         fileName_(pset.getUntrackedParameter<std::string>("fileName")),
0043         logicalFileName_(pset.getUntrackedParameter<std::string>("logicalFileName")),
0044         catalog_(pset.getUntrackedParameter<std::string>("catalog")),
0045         maxFileSize_(pset.getUntrackedParameter<int>("maxSize")),
0046         compressionLevel_(pset.getUntrackedParameter<int>("compressionLevel")),
0047         compressionAlgorithm_(pset.getUntrackedParameter<std::string>("compressionAlgorithm")),
0048         basketSize_(pset.getUntrackedParameter<int>("basketSize")),
0049         eventAuxBasketSize_(pset.getUntrackedParameter<int>("eventAuxiliaryBasketSize")),
0050         eventAutoFlushSize_(pset.getUntrackedParameter<int>("eventAutoFlushCompressedSize")),
0051         splitLevel_(std::min<int>(pset.getUntrackedParameter<int>("splitLevel") + 1, 99)),
0052         basketOrder_(pset.getUntrackedParameter<std::string>("sortBaskets")),
0053         treeMaxVirtualSize_(pset.getUntrackedParameter<int>("treeMaxVirtualSize")),
0054         whyNotFastClonable_(pset.getUntrackedParameter<bool>("fastCloning") ? FileBlock::CanFastClone
0055                                                                             : FileBlock::DisabledInConfigFile),
0056         dropMetaData_(DropNone),
0057         moduleLabel_(pset.getParameter<std::string>("@module_label")),
0058         initializedFromInput_(false),
0059         outputFileCount_(0),
0060         inputFileCount_(0),
0061         branchParents_(),
0062         branchChildren_(),
0063         overrideInputFileSplitLevels_(pset.getUntrackedParameter<bool>("overrideInputFileSplitLevels")),
0064         compactEventAuxiliary_(pset.getUntrackedParameter<bool>("compactEventAuxiliary")),
0065         mergeJob_(pset.getUntrackedParameter<bool>("mergeJob")),
0066         rootOutputFile_(),
0067         statusFileName_(),
0068         overrideGUID_(pset.getUntrackedParameter<std::string>("overrideGUID")) {
0069     if (pset.getUntrackedParameter<bool>("writeStatusFile")) {
0070       std::ostringstream statusfilename;
0071       statusfilename << moduleLabel_ << '_' << getpid();
0072       statusFileName_ = statusfilename.str();
0073     }
0074 
0075     std::string dropMetaData(pset.getUntrackedParameter<std::string>("dropMetaData"));
0076     if (dropMetaData.empty())
0077       dropMetaData_ = DropNone;
0078     else if (dropMetaData == std::string("NONE"))
0079       dropMetaData_ = DropNone;
0080     else if (dropMetaData == std::string("DROPPED"))
0081       dropMetaData_ = DropDroppedPrior;
0082     else if (dropMetaData == std::string("PRIOR"))
0083       dropMetaData_ = DropPrior;
0084     else if (dropMetaData == std::string("ALL"))
0085       dropMetaData_ = DropAll;
0086     else {
0087       throw edm::Exception(errors::Configuration, "Illegal dropMetaData parameter value: ")
0088           << dropMetaData << ".\n"
0089           << "Legal values are 'NONE', 'DROPPED', 'PRIOR', and 'ALL'.\n";
0090     }
0091 
0092     if (!wantAllEvents()) {
0093       whyNotFastClonable_ += FileBlock::EventSelectionUsed;
0094     }
0095 
0096     auto const& specialSplit{pset.getUntrackedParameterSetVector("overrideBranchesSplitLevel")};
0097 
0098     specialSplitLevelForBranches_.reserve(specialSplit.size());
0099     for (auto const& s : specialSplit) {
0100       specialSplitLevelForBranches_.emplace_back(s.getUntrackedParameter<std::string>("branch"),
0101                                                  s.getUntrackedParameter<int>("splitLevel"));
0102     }
0103 
0104     // We don't use this next parameter, but we read it anyway because it is part
0105     // of the configuration of this module.  An external parser creates the
0106     // configuration by reading this source code.
0107     pset.getUntrackedParameterSet("dataset");
0108   }
0109 
0110   void PoolOutputModule::beginJob() {
0111     Service<ConstProductRegistry> reg;
0112     for (auto const& prod : reg->productList()) {
0113       BranchDescription const& desc = prod.second;
0114       if (desc.produced() && desc.branchType() == InEvent && !desc.isAlias()) {
0115         producedBranches_.emplace_back(desc.branchID());
0116       }
0117     }
0118   }
0119 
0120   std::string const& PoolOutputModule::currentFileName() const { return rootOutputFile_->fileName(); }
0121 
0122   PoolOutputModule::AuxItem::AuxItem() : basketSize_(BranchDescription::invalidBasketSize) {}
0123 
0124   PoolOutputModule::OutputItem::OutputItem(BranchDescription const* bd,
0125                                            EDGetToken const& token,
0126                                            int splitLevel,
0127                                            int basketSize)
0128       : branchDescription_(bd), token_(token), product_(nullptr), splitLevel_(splitLevel), basketSize_(basketSize) {}
0129 
0130   PoolOutputModule::OutputItem::Sorter::Sorter(TTree* tree) : treeMap_(new std::map<std::string, int>) {
0131     // Fill a map mapping branch names to an index specifying the order in the tree.
0132     if (tree != nullptr) {
0133       TObjArray* branches = tree->GetListOfBranches();
0134       for (int i = 0; i < branches->GetEntries(); ++i) {
0135         TBranchElement* br = (TBranchElement*)branches->At(i);
0136         treeMap_->insert(std::make_pair(std::string(br->GetName()), i));
0137       }
0138     }
0139   }
0140 
0141   bool PoolOutputModule::OutputItem::Sorter::operator()(OutputItem const& lh, OutputItem const& rh) const {
0142     // Provides a comparison for sorting branches according to the index values in treeMap_.
0143     // Branches not found are always put at the end (i.e. not found > found).
0144     if (treeMap_->empty())
0145       return lh < rh;
0146     std::string const& lstring = lh.branchDescription_->branchName();
0147     std::string const& rstring = rh.branchDescription_->branchName();
0148     std::map<std::string, int>::const_iterator lit = treeMap_->find(lstring);
0149     std::map<std::string, int>::const_iterator rit = treeMap_->find(rstring);
0150     bool lfound = (lit != treeMap_->end());
0151     bool rfound = (rit != treeMap_->end());
0152     if (lfound && rfound) {
0153       return lit->second < rit->second;
0154     } else if (lfound) {
0155       return true;
0156     } else if (rfound) {
0157       return false;
0158     }
0159     return lh < rh;
0160   }
0161 
0162   inline bool PoolOutputModule::SpecialSplitLevelForBranch::match(std::string const& iBranchName) const {
0163     return std::regex_match(iBranchName, branch_);
0164   }
0165 
0166   std::regex PoolOutputModule::SpecialSplitLevelForBranch::convert(std::string const& iGlobBranchExpression) const {
0167     std::string tmp(iGlobBranchExpression);
0168     boost::replace_all(tmp, "*", ".*");
0169     boost::replace_all(tmp, "?", ".");
0170     return std::regex(tmp);
0171   }
0172 
0173   void PoolOutputModule::fillSelectedItemList(BranchType branchType,
0174                                               std::string const& processName,
0175                                               TTree* theInputTree,
0176                                               OutputItemList& outputItemList) {
0177     SelectedProducts const& keptVector = keptProducts()[branchType];
0178 
0179     if (branchType != InProcess) {
0180       AuxItem& auxItem = auxItems_[branchType];
0181 
0182       auto basketSize = (InEvent == branchType) ? eventAuxBasketSize_ : basketSize_;
0183 
0184       // Fill AuxItem
0185       if (theInputTree != nullptr && !overrideInputFileSplitLevels_) {
0186         TBranch* auxBranch = theInputTree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
0187         if (auxBranch) {
0188           auxItem.basketSize_ = auxBranch->GetBasketSize();
0189         } else {
0190           auxItem.basketSize_ = basketSize;
0191         }
0192       } else {
0193         auxItem.basketSize_ = basketSize;
0194       }
0195     }
0196 
0197     // Fill outputItemList with an entry for each branch.
0198     for (auto const& kept : keptVector) {
0199       int splitLevel = BranchDescription::invalidSplitLevel;
0200       int basketSize = BranchDescription::invalidBasketSize;
0201 
0202       BranchDescription const& prod = *kept.first;
0203       if (branchType == InProcess && processName != prod.processName()) {
0204         continue;
0205       }
0206       TBranch* theBranch = ((!prod.produced() && theInputTree != nullptr && !overrideInputFileSplitLevels_)
0207                                 ? theInputTree->GetBranch(prod.branchName().c_str())
0208                                 : nullptr);
0209 
0210       if (theBranch != nullptr) {
0211         splitLevel = theBranch->GetSplitLevel();
0212         basketSize = theBranch->GetBasketSize();
0213       } else {
0214         splitLevel = (prod.splitLevel() == BranchDescription::invalidSplitLevel ? splitLevel_ : prod.splitLevel());
0215         for (auto const& b : specialSplitLevelForBranches_) {
0216           if (b.match(prod.branchName())) {
0217             splitLevel = b.splitLevel_;
0218           }
0219         }
0220         basketSize = (prod.basketSize() == BranchDescription::invalidBasketSize ? basketSize_ : prod.basketSize());
0221       }
0222       outputItemList.emplace_back(&prod, kept.second, splitLevel, basketSize);
0223     }
0224 
0225     // Sort outputItemList to allow fast copying.
0226     // The branches in outputItemList must be in the same order as in the input tree, with all new branches at the end.
0227     sort_all(outputItemList, OutputItem::Sorter(theInputTree));
0228   }
0229 
0230   void PoolOutputModule::beginInputFile(FileBlock const& fb) {
0231     if (isFileOpen()) {
0232       //Faster to read ChildrenBranches directly from input
0233       // file than to build it every event
0234       auto const& branchToChildMap = fb.branchChildren().childLookup();
0235       for (auto const& parentToChildren : branchToChildMap) {
0236         for (auto const& child : parentToChildren.second) {
0237           branchChildren_.insertChild(parentToChildren.first, child);
0238         }
0239       }
0240       rootOutputFile_->beginInputFile(fb, remainingEvents());
0241     }
0242   }
0243 
0244   void PoolOutputModule::openFile(FileBlock const& fb) {
0245     if (!isFileOpen()) {
0246       reallyOpenFile();
0247       beginInputFile(fb);
0248     }
0249   }
0250 
0251   void PoolOutputModule::respondToOpenInputFile(FileBlock const& fb) {
0252     if (!initializedFromInput_) {
0253       std::vector<std::string> const& processesWithProcessBlockProducts =
0254           outputProcessBlockHelper().processesWithProcessBlockProducts();
0255       unsigned int numberOfProcessesWithProcessBlockProducts = processesWithProcessBlockProducts.size();
0256       unsigned int numberOfTTrees = numberOfRunLumiEventProductTrees + numberOfProcessesWithProcessBlockProducts;
0257       selectedOutputItemList_.resize(numberOfTTrees);
0258 
0259       for (unsigned int i = InEvent; i < NumBranchTypes; ++i) {
0260         BranchType branchType = static_cast<BranchType>(i);
0261         if (branchType != InProcess) {
0262           std::string processName;
0263           TTree* theInputTree =
0264               (branchType == InEvent ? fb.tree() : (branchType == InLumi ? fb.lumiTree() : fb.runTree()));
0265           OutputItemList& outputItemList = selectedOutputItemList_[branchType];
0266           fillSelectedItemList(branchType, processName, theInputTree, outputItemList);
0267         } else {
0268           // Handle output items in ProcessBlocks
0269           for (unsigned int k = InProcess; k < numberOfTTrees; ++k) {
0270             OutputItemList& outputItemList = selectedOutputItemList_[k];
0271             std::string const& processName = processesWithProcessBlockProducts[k - InProcess];
0272             TTree* theInputTree = fb.processBlockTree(processName);
0273             fillSelectedItemList(branchType, processName, theInputTree, outputItemList);
0274           }
0275         }
0276       }
0277       initializedFromInput_ = true;
0278     }
0279     ++inputFileCount_;
0280     beginInputFile(fb);
0281   }
0282 
0283   void PoolOutputModule::respondToCloseInputFile(FileBlock const& fb) {
0284     if (rootOutputFile_)
0285       rootOutputFile_->respondToCloseInputFile(fb);
0286   }
0287 
0288   void PoolOutputModule::setProcessesWithSelectedMergeableRunProducts(std::set<std::string> const& processes) {
0289     processesWithSelectedMergeableRunProducts_.assign(processes.begin(), processes.end());
0290   }
0291 
0292   PoolOutputModule::~PoolOutputModule() {}
0293 
0294   void PoolOutputModule::write(EventForOutput const& e) {
0295     updateBranchParents(e);
0296     rootOutputFile_->writeOne(e);
0297     if (!statusFileName_.empty()) {
0298       std::ofstream statusFile(statusFileName_.c_str());
0299       statusFile << e.id() << " time: " << std::setprecision(3) << TimeOfDay() << '\n';
0300       statusFile.close();
0301     }
0302   }
0303 
0304   void PoolOutputModule::writeLuminosityBlock(LuminosityBlockForOutput const& lb) {
0305     rootOutputFile_->writeLuminosityBlock(lb);
0306   }
0307 
0308   void PoolOutputModule::writeRun(RunForOutput const& r) { rootOutputFile_->writeRun(r); }
0309 
0310   void PoolOutputModule::writeProcessBlock(ProcessBlockForOutput const& pb) { rootOutputFile_->writeProcessBlock(pb); }
0311 
0312   void PoolOutputModule::reallyCloseFile() {
0313     writeEventAuxiliary();
0314     fillDependencyGraph();
0315     branchParents_.clear();
0316     startEndFile();
0317     writeFileFormatVersion();
0318     writeFileIdentifier();
0319     writeIndexIntoFile();
0320     writeStoredMergeableRunProductMetadata();
0321     writeProcessHistoryRegistry();
0322     writeParameterSetRegistry();
0323     writeProductDescriptionRegistry();
0324     writeParentageRegistry();
0325     writeBranchIDListRegistry();
0326     writeThinnedAssociationsHelper();
0327     writeProductDependencies();  //branchChildren used here
0328     writeProcessBlockHelper();
0329     branchChildren_.clear();
0330     finishEndFile();
0331 
0332     doExtrasAfterCloseFile();
0333   }
0334 
0335   // At some later date, we may move functionality from finishEndFile() to here.
0336   void PoolOutputModule::startEndFile() {}
0337 
0338   void PoolOutputModule::writeFileFormatVersion() { rootOutputFile_->writeFileFormatVersion(); }
0339   void PoolOutputModule::writeFileIdentifier() { rootOutputFile_->writeFileIdentifier(); }
0340   void PoolOutputModule::writeIndexIntoFile() { rootOutputFile_->writeIndexIntoFile(); }
0341   void PoolOutputModule::writeStoredMergeableRunProductMetadata() {
0342     rootOutputFile_->writeStoredMergeableRunProductMetadata();
0343   }
0344   void PoolOutputModule::writeProcessHistoryRegistry() { rootOutputFile_->writeProcessHistoryRegistry(); }
0345   void PoolOutputModule::writeParameterSetRegistry() { rootOutputFile_->writeParameterSetRegistry(); }
0346   void PoolOutputModule::writeProductDescriptionRegistry() { rootOutputFile_->writeProductDescriptionRegistry(); }
0347   void PoolOutputModule::writeParentageRegistry() { rootOutputFile_->writeParentageRegistry(); }
0348   void PoolOutputModule::writeBranchIDListRegistry() { rootOutputFile_->writeBranchIDListRegistry(); }
0349   void PoolOutputModule::writeThinnedAssociationsHelper() { rootOutputFile_->writeThinnedAssociationsHelper(); }
0350   void PoolOutputModule::writeProductDependencies() { rootOutputFile_->writeProductDependencies(); }
0351   void PoolOutputModule::writeEventAuxiliary() { rootOutputFile_->writeEventAuxiliary(); }
0352   void PoolOutputModule::writeProcessBlockHelper() { rootOutputFile_->writeProcessBlockHelper(); }
0353   void PoolOutputModule::finishEndFile() {
0354     rootOutputFile_->finishEndFile();
0355     rootOutputFile_ = nullptr;
0356   }  // propagate_const<T> has no reset() function
0357   void PoolOutputModule::doExtrasAfterCloseFile() {}
0358   bool PoolOutputModule::isFileOpen() const { return rootOutputFile_.get() != nullptr; }
0359   bool PoolOutputModule::shouldWeCloseFile() const { return rootOutputFile_->shouldWeCloseFile(); }
0360 
0361   std::pair<std::string, std::string> PoolOutputModule::physicalAndLogicalNameForNewFile() {
0362     if (inputFileCount_ == 0) {
0363       throw edm::Exception(errors::LogicError) << "Attempt to open output file before input file. "
0364                                                << "Please report this to the core framework developers.\n";
0365     }
0366     std::string suffix(".root");
0367     std::string::size_type offset = fileName().rfind(suffix);
0368     bool ext = (offset == fileName().size() - suffix.size());
0369     if (!ext)
0370       suffix.clear();
0371     std::string fileBase(ext ? fileName().substr(0, offset) : fileName());
0372     std::ostringstream ofilename;
0373     std::ostringstream lfilename;
0374     ofilename << fileBase;
0375     lfilename << logicalFileName();
0376     if (outputFileCount_) {
0377       ofilename << std::setw(3) << std::setfill('0') << outputFileCount_;
0378       if (!logicalFileName().empty()) {
0379         lfilename << std::setw(3) << std::setfill('0') << outputFileCount_;
0380       }
0381     }
0382     ofilename << suffix;
0383     ++outputFileCount_;
0384 
0385     return std::make_pair(ofilename.str(), lfilename.str());
0386   }
0387 
0388   void PoolOutputModule::reallyOpenFile() {
0389     auto names = physicalAndLogicalNameForNewFile();
0390     rootOutputFile_ = std::make_unique<RootOutputFile>(this,
0391                                                        names.first,
0392                                                        names.second,
0393                                                        processesWithSelectedMergeableRunProducts_,
0394                                                        overrideGUID_);  // propagate_const<T> has no reset() function
0395     // Override the GUID of the first file only, in order to avoid two
0396     // output files from one Output Module to have identical GUID.
0397     overrideGUID_.clear();
0398   }
0399 
0400   void PoolOutputModule::updateBranchParentsForOneBranch(ProductProvenanceRetriever const* provRetriever,
0401                                                          BranchID const& branchID) {
0402     ProductProvenance const* provenance = provRetriever->branchIDToProvenanceForProducedOnly(branchID);
0403     if (provenance != nullptr) {
0404       BranchParents::iterator it = branchParents_.find(branchID);
0405       if (it == branchParents_.end()) {
0406         it = branchParents_.insert(std::make_pair(branchID, std::set<ParentageID>())).first;
0407       }
0408       it->second.insert(provenance->parentageID());
0409     }
0410   }
0411 
0412   void PoolOutputModule::updateBranchParents(EventForOutput const& e) {
0413     ProductProvenanceRetriever const* provRetriever = e.productProvenanceRetrieverPtr();
0414     for (auto const& bid : producedBranches_) {
0415       updateBranchParentsForOneBranch(provRetriever, bid);
0416     }
0417     SubProcessParentageHelper const* helper = subProcessParentageHelper();
0418     if (helper) {
0419       for (auto const& bid : subProcessParentageHelper()->producedProducts()) {
0420         updateBranchParentsForOneBranch(provRetriever, bid);
0421       }
0422     }
0423   }
0424 
0425   void PoolOutputModule::preActionBeforeRunEventAsync(WaitingTaskHolder iTask,
0426                                                       ModuleCallingContext const& iModuleCallingContext,
0427                                                       Principal const& iPrincipal) const noexcept {
0428     if (DropAll != dropMetaData_) {
0429       auto const* ep = dynamic_cast<EventPrincipal const*>(&iPrincipal);
0430       if (ep) {
0431         auto pr = ep->productProvenanceRetrieverPtr();
0432         if (pr) {
0433           pr->readProvenanceAsync(iTask, &iModuleCallingContext);
0434         }
0435       }
0436     }
0437   }
0438 
0439   void PoolOutputModule::fillDependencyGraph() {
0440     for (auto const& branchParent : branchParents_) {
0441       BranchID const& child = branchParent.first;
0442       std::set<ParentageID> const& eIds = branchParent.second;
0443       for (auto const& eId : eIds) {
0444         Parentage entryDesc;
0445         ParentageRegistry::instance()->getMapped(eId, entryDesc);
0446         std::vector<BranchID> const& parents = entryDesc.parents();
0447         for (auto const& parent : parents) {
0448           branchChildren_.insertChild(parent, child);
0449         }
0450       }
0451     }
0452   }
0453 
0454   void PoolOutputModule::fillDescription(ParameterSetDescription& desc) {
0455     std::string defaultString;
0456 
0457     desc.setComment("Writes runs, lumis, and events into EDM/ROOT files.");
0458     desc.addUntracked<std::string>("fileName")->setComment("Name of output file.");
0459     desc.addUntracked<std::string>("logicalFileName", defaultString)
0460         ->setComment("Passed to job report. Otherwise unused by module.");
0461     desc.addUntracked<std::string>("catalog", defaultString)
0462         ->setComment("Passed to job report. Otherwise unused by module.");
0463     desc.addUntracked<int>("maxSize", 0x7f000000)
0464         ->setComment(
0465             "Maximum output file size, in kB.\n"
0466             "If over maximum, new output file will be started at next input file transition.");
0467     desc.addUntracked<int>("compressionLevel", 4)->setComment("ROOT compression level of output file.");
0468     desc.addUntracked<std::string>("compressionAlgorithm", "ZSTD")
0469         ->setComment(
0470             "Algorithm used to compress data in the ROOT output file, allowed values are ZLIB, LZMA, LZ4, and ZSTD");
0471     desc.addUntracked<int>("basketSize", 16384)->setComment("Default ROOT basket size in output file.");
0472     desc.addUntracked<int>("eventAuxiliaryBasketSize", 16384)
0473         ->setComment("Default ROOT basket size in output file for EventAuxiliary branch.");
0474     desc.addUntracked<int>("eventAutoFlushCompressedSize", 20 * 1024 * 1024)
0475         ->setComment(
0476             "Set ROOT auto flush stored data size (in bytes) for event TTree. The value sets how large the compressed "
0477             "buffer is allowed to get. The uncompressed buffer can be quite a bit larger than this depending on the "
0478             "average compression ratio. The value of -1 just uses ROOT's default value. The value of 0 turns off this "
0479             "feature. A value of -N changes the behavior to flush after every Nth event.");
0480     desc.addUntracked<int>("splitLevel", 99)->setComment("Default ROOT branch split level in output file.");
0481     desc.addUntracked<std::string>("sortBaskets", std::string("sortbasketsbyoffset"))
0482         ->setComment(
0483             "Legal values: 'sortbasketsbyoffset', 'sortbasketsbybranch', 'sortbasketsbyentry'.\n"
0484             "Used by ROOT when fast copying. Affects performance.");
0485     desc.addUntracked<int>("treeMaxVirtualSize", -1)
0486         ->setComment("Size of ROOT TTree TBasket cache.  Affects performance.");
0487     desc.addUntracked<bool>("fastCloning", true)
0488         ->setComment(
0489             "True:  Allow fast copying, if possible.\n"
0490             "False: Disable fast copying.");
0491     desc.addUntracked("mergeJob", false)
0492         ->setComment(
0493             "If set to true and fast copying is disabled, copy input file compression and basket sizes to the output "
0494             "file.");
0495     desc.addUntracked<bool>("compactEventAuxiliary", false)
0496         ->setComment(
0497             "False: Write EventAuxiliary as we go like any other event metadata branch.\n"
0498             "True:  Optimize the file layout by deferring writing the EventAuxiliary branch until the output file is "
0499             "closed.");
0500     desc.addUntracked<bool>("overrideInputFileSplitLevels", false)
0501         ->setComment(
0502             "False: Use branch split levels and basket sizes from input file, if possible.\n"
0503             "True:  Always use specified or default split levels and basket sizes.");
0504     desc.addUntracked<bool>("writeStatusFile", false)
0505         ->setComment("Write a status file. Intended for use by workflow management.");
0506     desc.addUntracked<std::string>("dropMetaData", defaultString)
0507         ->setComment(
0508             "Determines handling of per product per event metadata.  Options are:\n"
0509             "'NONE':    Keep all of it.\n"
0510             "'DROPPED': Keep it for products produced in current process and all kept products. Drop it for dropped "
0511             "products produced in prior processes.\n"
0512             "'PRIOR':   Keep it for products produced in current process. Drop it for products produced in prior "
0513             "processes.\n"
0514             "'ALL':     Drop all of it.");
0515     desc.addUntracked<std::string>("overrideGUID", defaultString)
0516         ->setComment(
0517             "Allows to override the GUID of the file. Intended to be used only in Tier0 for re-creating files.\n"
0518             "The GUID needs to be of the proper format. If a new output file is started (see maxSize), the GUID of\n"
0519             "the first file only is overridden, i.e. the subsequent output files have different, generated GUID.");
0520     {
0521       ParameterSetDescription dataSet;
0522       dataSet.setAllowAnything();
0523       desc.addUntracked<ParameterSetDescription>("dataset", dataSet)
0524           ->setComment("PSet is only used by Data Operations and not by this module.");
0525     }
0526     {
0527       ParameterSetDescription specialSplit;
0528       specialSplit.addUntracked<std::string>("branch")->setComment(
0529           "Name of branch needing a special split level. The name can contain wildcards '*' and '?'");
0530       specialSplit.addUntracked<int>("splitLevel")->setComment("The special split level for the branch");
0531       desc.addVPSetUntracked("overrideBranchesSplitLevel", specialSplit, std::vector<ParameterSet>());
0532     }
0533     OutputModule::fillDescription(desc);
0534   }
0535 
0536   void PoolOutputModule::fillDescriptions(ConfigurationDescriptions& descriptions) {
0537     ParameterSetDescription desc;
0538     PoolOutputModule::fillDescription(desc);
0539     descriptions.add("edmOutput", desc);
0540   }
0541 }  // namespace edm