diff --git a/FWCore/Framework/interface/OutputModule.h b/FWCore/Framework/interface/OutputModule.h index 497ec6c8ba914..5119fb08d5947 100644 --- a/FWCore/Framework/interface/OutputModule.h +++ b/FWCore/Framework/interface/OutputModule.h @@ -82,7 +82,7 @@ namespace edm { bool wantAllEvents() const {return wantAllEvents_;} - BranchIDLists const* branchIDLists() const; + BranchIDLists const* branchIDLists(); ThinnedAssociationsHelper const* thinnedAssociationsHelper() const; diff --git a/FWCore/Framework/interface/global/OutputModule.h b/FWCore/Framework/interface/global/OutputModule.h new file mode 100644 index 0000000000000..f40d671fd355c --- /dev/null +++ b/FWCore/Framework/interface/global/OutputModule.h @@ -0,0 +1,61 @@ +#ifndef FWCore_Framework_global_OutputModule_h +#define FWCore_Framework_global_OutputModule_h +// -*- C++ -*- +// +// Package: FWCore/Framework +// Class : edm::global::OutputModule +// +/**\class edm::global::OutputModule OutputModule.h "FWCore/Framework/interface/global/OutputModule.h" + + Description: [one line class summary] + + Usage: + + +*/ +// +// + +// system include files + +// user include files +#include "FWCore/Framework/interface/global/outputmoduleAbilityToImplementor.h" + +// forward declarations +namespace edm { + namespace global { + template< typename... T> + class OutputModule : public virtual OutputModuleBase, + public outputmodule::AbilityToImplementor::Type... + { + + public: + OutputModule(edm::ParameterSet const& iPSet): OutputModuleBase(iPSet), + outputmodule::AbilityToImplementor::Type(iPSet)... + {} + // Required to work around ICC bug, but possible source of bloat in gcc. + // We do this only in the case of the intel compiler as this might end up + // creating a lot of code bloat due to inline symbols being generated in + // each DSO which uses this header. +#ifdef __INTEL_COMPILER + virtual ~OutputModule() = default; +#endif + + // ---------- const member functions --------------------- + + // ---------- static member functions -------------------- + + // ---------- member functions --------------------------- + + private: + OutputModule(const OutputModule&) = delete; // stop default + + const OutputModule& operator=(const OutputModule&) =delete; // stop default + + // ---------- member data -------------------------------- + + }; + } +} + +#endif diff --git a/FWCore/Framework/interface/global/OutputModuleBase.h b/FWCore/Framework/interface/global/OutputModuleBase.h new file mode 100644 index 0000000000000..d90c4422ea0d0 --- /dev/null +++ b/FWCore/Framework/interface/global/OutputModuleBase.h @@ -0,0 +1,276 @@ +#ifndef FWCore_Framework_global_OutputModuleBase_h +#define FWCore_Framework_global_OutputModuleBase_h +// -*- C++ -*- +// +// Package: FWCore/Framework +// Class : OutputModuleBase +// +/**\class OutputModuleBase OutputModuleBase.h "FWCore/Framework/interface/global/OutputModuleBase.h" + + Description: Base class for all 'global' OutputModules + + Usage: + + +*/ +// +// + +// system include files +#include +#include +#include +#include +#include +#include +#include + +// user include files +#include "DataFormats/Provenance/interface/BranchID.h" +#include "DataFormats/Provenance/interface/BranchIDList.h" +#include "DataFormats/Provenance/interface/ModuleDescription.h" +#include "DataFormats/Provenance/interface/SelectedProducts.h" + +#include "FWCore/Framework/interface/TriggerResultsBasedEventSelector.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/ProductSelectorRules.h" +#include "FWCore/Framework/interface/ProductSelector.h" +#include "FWCore/Framework/interface/EDConsumerBase.h" +#include "FWCore/Framework/interface/getAllTriggerNames.h" +#include "FWCore/ParameterSet/interface/ParameterSetfwd.h" + +// forward declarations +namespace edm { + + class ModuleCallingContext; + class PreallocationConfiguration; + class ActivityRegistry; + class ProductRegistry; + class ThinnedAssociationsHelper; + + template class OutputModuleCommunicatorT; + + namespace maker { + template class ModuleHolderT; + } + + namespace global { + + class OutputModuleBase : public EDConsumerBase { + public: + template friend class edm::maker::ModuleHolderT; + template friend class ::edm::WorkerT; + template friend class ::edm::OutputModuleCommunicatorT; + typedef OutputModuleBase ModuleType; + + explicit OutputModuleBase(ParameterSet const& pset); + virtual ~OutputModuleBase(); + + OutputModuleBase(OutputModuleBase const&) = delete; // Disallow copying and moving + OutputModuleBase& operator=(OutputModuleBase const&) = delete; // Disallow copying and moving + + /// Accessor for maximum number of events to be written. + /// -1 is used for unlimited. + int maxEvents() const {return maxEvents_;} + + /// Accessor for remaining number of events to be written. + /// -1 is used for unlimited. + int remainingEvents() const {return remainingEvents_;} + + bool selected(BranchDescription const& desc) const; + + void selectProducts(ProductRegistry const& preg, ThinnedAssociationsHelper const&); + std::string const& processName() const {return process_name_;} + SelectedProductsForBranchType const& keptProducts() const {return keptProducts_;} + std::array const& hasNewlyDroppedBranch() const {return hasNewlyDroppedBranch_;} + + static void fillDescription(ParameterSetDescription & desc); + static void fillDescriptions(ConfigurationDescriptions& descriptions); + static const std::string& baseType(); + static void prevalidate(ConfigurationDescriptions& ); + + bool wantAllEvents() const {return wantAllEvents_;} + + BranchIDLists const* branchIDLists(); + + ThinnedAssociationsHelper const* thinnedAssociationsHelper() const; + + const ModuleDescription& moduleDescription() const { + return moduleDescription_; + } + protected: + + ModuleDescription const& description() const; + + ParameterSetID selectorConfig() const { return selector_config_id_; } + + void doPreallocate(PreallocationConfiguration const&); + + void doBeginJob(); + void doEndJob(); + + void doBeginStream(StreamID id); + void doEndStream(StreamID id); + void doStreamBeginRun(StreamID id, + RunPrincipal& ep, + EventSetup const& c, + ModuleCallingContext const*); + void doStreamEndRun(StreamID id, + RunPrincipal& ep, + EventSetup const& c, + ModuleCallingContext const*); + void doStreamBeginLuminosityBlock(StreamID id, + LuminosityBlockPrincipal& ep, + EventSetup const& c, + ModuleCallingContext const*); + void doStreamEndLuminosityBlock(StreamID id, + LuminosityBlockPrincipal& ep, + EventSetup const& c, + ModuleCallingContext const*); + + bool doEvent(EventPrincipal const& ep, EventSetup const& c, + ActivityRegistry*, + ModuleCallingContext const*); + bool doBeginRun(RunPrincipal const& rp, EventSetup const& c, + ModuleCallingContext const*); + bool doEndRun(RunPrincipal const& rp, EventSetup const& c, + ModuleCallingContext const*); + bool doBeginLuminosityBlock(LuminosityBlockPrincipal const& lbp, EventSetup const& c, + ModuleCallingContext const*); + bool doEndLuminosityBlock(LuminosityBlockPrincipal const& lbp, EventSetup const& c, + ModuleCallingContext const*); + + void setEventSelectionInfo(std::map > > const& outputModulePathPositions, + bool anyProductProduced); + + void configure(OutputModuleDescription const& desc); + + std::map const& droppedBranchIDToKeptBranchID() { + return droppedBranchIDToKeptBranchID_; + } + + private: + + int maxEvents_; + std::atomic remainingEvents_; + + // TODO: Give OutputModule + // an interface (protected?) that supplies client code with the + // needed functionality *without* giving away implementation + // details ... don't just return a reference to keptProducts_, because + // we are looking to have the flexibility to change the + // implementation of keptProducts_ without modifying clients. When this + // change is made, we'll have a one-time-only task of modifying + // clients (classes derived from OutputModule) to use the + // newly-introduced interface. + // TODO: Consider using shared pointers here? + + // keptProducts_ are pointers to the BranchDescription objects describing + // the branches we are to write. + // + // We do not own the BranchDescriptions to which we point. + SelectedProductsForBranchType keptProducts_; + std::array hasNewlyDroppedBranch_; + + std::string process_name_; + ProductSelectorRules productSelectorRules_; + ProductSelector productSelector_; + ModuleDescription moduleDescription_; + + bool wantAllEvents_; + std::vector selectors_; + ParameterSet selectEvents_; + // ID of the ParameterSet that configured the event selector + // subsystem. + ParameterSetID selector_config_id_; + + // needed because of possible EDAliases. + // filled in only if key and value are different. + std::map droppedBranchIDToKeptBranchID_; + std::unique_ptr branchIDLists_; + BranchIDLists const* origBranchIDLists_; + + std::unique_ptr thinnedAssociationsHelper_; + std::map keepAssociation_; + + //------------------------------------------------------------------ + // private member functions + //------------------------------------------------------------------ + + void doWriteRun(RunPrincipal const& rp, ModuleCallingContext const*); + void doWriteLuminosityBlock(LuminosityBlockPrincipal const& lbp, ModuleCallingContext const*); + void doOpenFile(FileBlock const& fb); + void doRespondToOpenInputFile(FileBlock const& fb); + void doRespondToCloseInputFile(FileBlock const& fb); + void doPreForkReleaseResources(); + void doPostForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren); + void doRegisterThinnedAssociations(ProductRegistry const&, + ThinnedAssociationsHelper&) { } + + std::string workerType() const {return "WorkerT";} + + /// Tell the OutputModule that is must end the current file. + void doCloseFile(); + + /// Tell the OutputModule to open an output file, if one is not + /// already open. + void maybeOpenFile(); + + void registerProductsAndCallbacks(OutputModuleBase const*, ProductRegistry const*) {} + + bool prePrefetchSelection(StreamID id, EventPrincipal const&, ModuleCallingContext const*); + + // Do the end-of-file tasks; this is only called internally, after + // the appropriate tests have been done. + virtual void reallyCloseFile(); + + + /// Ask the OutputModule if we should end the current file. + virtual bool shouldWeCloseFile() const {return false;} + + virtual void write(EventPrincipal const& e, ModuleCallingContext const*) = 0; + virtual void beginJob(){} + virtual void endJob(){} + virtual void writeLuminosityBlock(LuminosityBlockPrincipal const&, ModuleCallingContext const*) = 0; + virtual void writeRun(RunPrincipal const&, ModuleCallingContext const*) = 0; + virtual void openFile(FileBlock const&) {} + virtual bool isFileOpen() const { return true; } + virtual void reallyOpenFile() {} + + virtual void preForkReleaseResources(); + virtual void postForkReacquireResources(unsigned int /*iChildIndex*/, unsigned int /*iNumberOfChildren*/); + + virtual void preallocStreams(unsigned int){} + virtual void doBeginStream_(StreamID){} + virtual void doEndStream_(StreamID){} + virtual void doStreamBeginRun_(StreamID, Run const&, EventSetup const&){} + virtual void doStreamEndRun_(StreamID, Run const&, EventSetup const&){} + virtual void doStreamEndRunSummary_(StreamID, Run const&, EventSetup const&){} + virtual void doStreamBeginLuminosityBlock_(StreamID, LuminosityBlock const&, EventSetup const&){} + virtual void doStreamEndLuminosityBlock_(StreamID, LuminosityBlock const&, EventSetup const&){} + virtual void doStreamEndLuminosityBlockSummary_(StreamID, LuminosityBlock const&, EventSetup const&){} + + virtual void doBeginRun_(RunPrincipal const&, ModuleCallingContext const*){} + virtual void doBeginRunSummary_(Run const&, EventSetup const&){} + virtual void doEndRun_(RunPrincipal const&, ModuleCallingContext const*){} + virtual void doEndRunSummary_(Run const&, EventSetup const&){} + virtual void doBeginLuminosityBlock_(LuminosityBlockPrincipal const&, ModuleCallingContext const*){} + virtual void doBeginLuminosityBlockSummary_(LuminosityBlock const&, EventSetup const&){} + virtual void doEndLuminosityBlock_(LuminosityBlockPrincipal const&, ModuleCallingContext const*){} + virtual void doEndLuminosityBlockSummary_(LuminosityBlock const&, EventSetup const&){} + virtual void doRespondToOpenInputFile_(FileBlock const&) {} + virtual void doRespondToCloseInputFile_(FileBlock const&) {} + + void keepThisBranch(BranchDescription const& desc, + std::map& trueBranchIDToKeptBranchDesc, + std::set& keptProductsInEvent); + + void setModuleDescription(ModuleDescription const& md) { + moduleDescription_ = md; + } + + bool limitReached() const {return remainingEvents_ == 0;} + }; + } +} +#endif diff --git a/FWCore/Framework/interface/global/outputmoduleAbilityToImplementor.h b/FWCore/Framework/interface/global/outputmoduleAbilityToImplementor.h new file mode 100644 index 0000000000000..f74d99edf9289 --- /dev/null +++ b/FWCore/Framework/interface/global/outputmoduleAbilityToImplementor.h @@ -0,0 +1,85 @@ +#ifndef FWCore_Framework_global_outputmoduleAbilityToImplementor_h +#define FWCore_Framework_global_outputmoduleAbilityToImplementor_h +// -*- C++ -*- +// +// Package: FWCore/Framework +// Class : outputmodule::AbilityToImplementor +// +/**\class outputmodule::AbilityToImplementor outputmoduleAbilityToImplementor.h "FWCore/Framework/interface/global/outputmoduleAbilityToImplementor.h" + + Description: [one line class summary] + + Usage: + + +*/ +// +// + +// system include files + +// user include files +#include "FWCore/Framework/interface/moduleAbilities.h" +#include "FWCore/Framework/interface/global/implementors.h" +#include "FWCore/Framework/interface/global/OutputModuleBase.h" + +// forward declarations + +namespace edm { + class FileBlock; + class ModuleCallingContext; + + namespace global { + namespace outputmodule { + class InputFileWatcher : public virtual OutputModuleBase { + public: + InputFileWatcher(edm::ParameterSet const&iPSet): OutputModuleBase(iPSet) {} + InputFileWatcher(InputFileWatcher const&) = delete; + InputFileWatcher& operator=(InputFileWatcher const&) = delete; + + private: + void doRespondToOpenInputFile_(FileBlock const&) override final; + void doRespondToCloseInputFile_(FileBlock const&) override final; + + virtual void respondToOpenInputFile(FileBlock const&) = 0; + virtual void respondToCloseInputFile(FileBlock const&) = 0; + }; + + template struct AbilityToImplementor; + + template<> + struct AbilityToImplementor { + typedef edm::global::outputmodule::InputFileWatcher Type; + }; + + template + struct AbilityToImplementor> { + typedef edm::global::impl::StreamCacheHolder Type; + }; + + template + struct AbilityToImplementor> { + typedef edm::global::impl::RunCacheHolder Type; + }; + + template + struct AbilityToImplementor> { + typedef edm::global::impl::RunSummaryCacheHolder Type; + }; + + template + struct AbilityToImplementor> { + typedef edm::global::impl::LuminosityBlockCacheHolder Type; + }; + + template + struct AbilityToImplementor> { + typedef edm::global::impl::LuminosityBlockSummaryCacheHolder Type; + }; + + } + } +} + + +#endif diff --git a/FWCore/Framework/interface/one/OutputModuleBase.h b/FWCore/Framework/interface/one/OutputModuleBase.h index 2d4a46fcb03ef..129b642a338ca 100644 --- a/FWCore/Framework/interface/one/OutputModuleBase.h +++ b/FWCore/Framework/interface/one/OutputModuleBase.h @@ -94,7 +94,7 @@ namespace edm { bool wantAllEvents() const {return wantAllEvents_;} - BranchIDLists const* branchIDLists() const; + BranchIDLists const* branchIDLists(); ThinnedAssociationsHelper const* thinnedAssociationsHelper() const; diff --git a/FWCore/Framework/src/OutputModule.cc b/FWCore/Framework/src/OutputModule.cc index 125a3f0496e12..a09faf70422bb 100644 --- a/FWCore/Framework/src/OutputModule.cc +++ b/FWCore/Framework/src/OutputModule.cc @@ -342,7 +342,7 @@ namespace edm { } BranchIDLists const* - OutputModule::branchIDLists() const { + OutputModule::branchIDLists() { if(!droppedBranchIDToKeptBranchID_.empty()) { // Make a private copy of the BranchIDLists. *branchIDLists_ = *origBranchIDLists_; diff --git a/FWCore/Framework/src/OutputModuleCommunicatorT.cc b/FWCore/Framework/src/OutputModuleCommunicatorT.cc index 747829e617e44..755955816ca56 100644 --- a/FWCore/Framework/src/OutputModuleCommunicatorT.cc +++ b/FWCore/Framework/src/OutputModuleCommunicatorT.cc @@ -106,6 +106,9 @@ namespace edm { std::unique_ptr createCommunicatorIfNeeded(::edm::OutputModule * iMod){ return std::move(std::unique_ptr{ new OutputModuleCommunicatorT(iMod) }); } + std::unique_ptr createCommunicatorIfNeeded(::edm::global::OutputModuleBase * iMod){ + return std::move(std::unique_ptr{ new OutputModuleCommunicatorT(iMod) }); + } std::unique_ptr createCommunicatorIfNeeded(::edm::one::OutputModuleBase * iMod){ return std::move(std::unique_ptr{ new OutputModuleCommunicatorT(iMod) }); } @@ -113,9 +116,11 @@ namespace edm { } #include "FWCore/Framework/interface/OutputModule.h" +#include "FWCore/Framework/interface/global/OutputModuleBase.h" #include "FWCore/Framework/interface/one/OutputModuleBase.h" namespace edm { template class OutputModuleCommunicatorT; template class OutputModuleCommunicatorT; + template class OutputModuleCommunicatorT; } diff --git a/FWCore/Framework/src/OutputModuleCommunicatorT.h b/FWCore/Framework/src/OutputModuleCommunicatorT.h index a55583140e30e..f2ed93598b5b4 100644 --- a/FWCore/Framework/src/OutputModuleCommunicatorT.h +++ b/FWCore/Framework/src/OutputModuleCommunicatorT.h @@ -13,10 +13,14 @@ namespace edm { namespace one { class OutputModuleBase; } + namespace global { + class OutputModuleBase; + } namespace impl { std::unique_ptr createCommunicatorIfNeeded(void *); std::unique_ptr createCommunicatorIfNeeded(::edm::OutputModule *); std::unique_ptr createCommunicatorIfNeeded(::edm::one::OutputModuleBase *); + std::unique_ptr createCommunicatorIfNeeded(::edm::global::OutputModuleBase *); } template diff --git a/FWCore/Framework/src/WorkerT.cc b/FWCore/Framework/src/WorkerT.cc index 8f1382ad85fff..a538baa45a573 100644 --- a/FWCore/Framework/src/WorkerT.cc +++ b/FWCore/Framework/src/WorkerT.cc @@ -14,6 +14,7 @@ #include "FWCore/Framework/interface/global/EDProducerBase.h" #include "FWCore/Framework/interface/global/EDFilterBase.h" #include "FWCore/Framework/interface/global/EDAnalyzerBase.h" +#include "FWCore/Framework/interface/global/OutputModuleBase.h" #include "FWCore/Framework/interface/stream/EDProducerAdaptorBase.h" #include "FWCore/Framework/interface/stream/EDFilterAdaptorBase.h" @@ -146,6 +147,15 @@ namespace edm{ return module_->prePrefetchSelection(id,ep,mcc); } + template<> + inline + bool + WorkerT::implDoPrePrefetchSelection(StreamID id, + EventPrincipal& ep, + ModuleCallingContext const* mcc) { + return module_->prePrefetchSelection(id,ep,mcc); + } + template inline bool @@ -388,6 +398,8 @@ namespace edm{ Worker::Types WorkerT::moduleType() const { return Worker::kFilter;} template<> Worker::Types WorkerT::moduleType() const { return Worker::kAnalyzer;} + template<> + Worker::Types WorkerT::moduleType() const { return Worker::kOutputModule;} template<> @@ -410,6 +422,7 @@ namespace edm{ template class WorkerT; template class WorkerT; template class WorkerT; + template class WorkerT; template class WorkerT; template class WorkerT; template class WorkerT; diff --git a/FWCore/Framework/src/global/OutputModuleBase.cc b/FWCore/Framework/src/global/OutputModuleBase.cc new file mode 100644 index 0000000000000..75fcb490a3448 --- /dev/null +++ b/FWCore/Framework/src/global/OutputModuleBase.cc @@ -0,0 +1,389 @@ +// -*- C++ -*- +// +// Package: FWCore/Framework +// Class : OutputModuleBase +// +// Implementation: +// [Notes on implementation] +// +// + +// system include files +#include + +// user include files +#include "FWCore/Framework/interface/global/OutputModuleBase.h" + +#include "DataFormats/Common/interface/Handle.h" +#include "DataFormats/Common/interface/ThinnedAssociation.h" +#include "DataFormats/Provenance/interface/BranchDescription.h" +#include "DataFormats/Provenance/interface/BranchKey.h" +#include "DataFormats/Provenance/interface/ProductRegistry.h" +#include "DataFormats/Provenance/interface/ThinnedAssociationsHelper.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventPrincipal.h" +#include "FWCore/Framework/interface/OutputModuleDescription.h" +#include "FWCore/Framework/interface/TriggerNamesService.h" +#include "FWCore/Framework/src/EventSignalsSentry.h" +#include "FWCore/Framework/src/PreallocationConfiguration.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Utilities/interface/DebugMacros.h" + + +namespace edm { + namespace global { + + // ------------------------------------------------------- + OutputModuleBase::OutputModuleBase(ParameterSet const& pset) : + maxEvents_(-1), + remainingEvents_(maxEvents_), + keptProducts_(), + hasNewlyDroppedBranch_(), + process_name_(), + productSelectorRules_(pset, "outputCommands", "OutputModule"), + productSelector_(), + moduleDescription_(), + wantAllEvents_(false), + selectors_(), + selector_config_id_(), + droppedBranchIDToKeptBranchID_(), + branchIDLists_(new BranchIDLists), + origBranchIDLists_(nullptr), + thinnedAssociationsHelper_(new ThinnedAssociationsHelper) { + + hasNewlyDroppedBranch_.fill(false); + + Service tns; + process_name_ = tns->getProcessName(); + + selectEvents_ = + pset.getUntrackedParameterSet("SelectEvents", ParameterSet()); + + selectEvents_.registerIt(); // Just in case this PSet is not registered + + selector_config_id_ = selectEvents_.id(); + + //need to set wantAllEvents_ in constructor + // we will make the remaining selectors once we know how many streams + selectors_.resize(1); + wantAllEvents_ = detail::configureEventSelector(selectEvents_, + process_name_, + getAllTriggerNames(), + selectors_[0]); + + } + + void OutputModuleBase::configure(OutputModuleDescription const& desc) { + remainingEvents_ = maxEvents_ = desc.maxEvents_; + origBranchIDLists_ = desc.branchIDLists_; + } + + void OutputModuleBase::selectProducts(ProductRegistry const& preg, + ThinnedAssociationsHelper const& thinnedAssociationsHelper) { + if(productSelector_.initialized()) return; + productSelector_.initialize(productSelectorRules_, preg.allBranchDescriptions()); + + // TODO: See if we can collapse keptProducts_ and productSelector_ into a + // single object. See the notes in the header for ProductSelector + // for more information. + + std::map trueBranchIDToKeptBranchDesc; + std::vector associationDescriptions; + std::set keptProductsInEvent; + + for(auto const& it : preg.productList()) { + BranchDescription const& desc = it.second; + if(desc.transient()) { + // if the class of the branch is marked transient, output nothing + } else if(!desc.present() && !desc.produced()) { + // else if the branch containing the product has been previously dropped, + // output nothing + } else if(desc.unwrappedType() == typeid(ThinnedAssociation)) { + associationDescriptions.push_back(&desc); + } else if(selected(desc)) { + keepThisBranch(desc, trueBranchIDToKeptBranchDesc, keptProductsInEvent); + } else { + // otherwise, output nothing, + // and mark the fact that there is a newly dropped branch of this type. + hasNewlyDroppedBranch_[desc.branchType()] = true; + } + } + + thinnedAssociationsHelper.selectAssociationProducts(associationDescriptions, + keptProductsInEvent, + keepAssociation_); + + for(auto association : associationDescriptions) { + if(keepAssociation_[association->branchID()]) { + keepThisBranch(*association, trueBranchIDToKeptBranchDesc, keptProductsInEvent); + } else { + hasNewlyDroppedBranch_[association->branchType()] = true; + } + } + + // Now fill in a mapping needed in the case that a branch was dropped while its EDAlias was kept. + ProductSelector::fillDroppedToKept(preg, trueBranchIDToKeptBranchDesc, droppedBranchIDToKeptBranchID_); + + thinnedAssociationsHelper_->updateFromParentProcess(thinnedAssociationsHelper, keepAssociation_, droppedBranchIDToKeptBranchID_); + } + + void OutputModuleBase::keepThisBranch(BranchDescription const& desc, + std::map& trueBranchIDToKeptBranchDesc, + std::set& keptProductsInEvent) { + + ProductSelector::checkForDuplicateKeptBranch(desc, + trueBranchIDToKeptBranchDesc); + + switch (desc.branchType()) { + case InEvent: + { + if(desc.produced()) { + keptProductsInEvent.insert(desc.originalBranchID()); + } else { + keptProductsInEvent.insert(desc.branchID()); + } + consumes(TypeToGet{desc.unwrappedTypeID(),PRODUCT_TYPE}, + InputTag{desc.moduleLabel(), + desc.productInstanceName(), + desc.processName()}); + break; + } + case InLumi: + { + consumes(TypeToGet{desc.unwrappedTypeID(),PRODUCT_TYPE}, + InputTag(desc.moduleLabel(), + desc.productInstanceName(), + desc.processName())); + break; + } + case InRun: + { + consumes(TypeToGet{desc.unwrappedTypeID(),PRODUCT_TYPE}, + InputTag(desc.moduleLabel(), + desc.productInstanceName(), + desc.processName())); + break; + } + default: + assert(false); + break; + } + // Now put it in the list of selected branches. + keptProducts_[desc.branchType()].push_back(&desc); + } + + OutputModuleBase::~OutputModuleBase() { } + + void OutputModuleBase::doPreallocate(PreallocationConfiguration const& iPC) { + auto nstreams = iPC.numberOfStreams(); + selectors_.resize(nstreams); + + bool seenFirst = false; + for(auto& s : selectors_) { + if(seenFirst) { + detail::configureEventSelector(selectEvents_, + process_name_, + getAllTriggerNames(), + s); + } else { + seenFirst = true; + } + } + } + + void OutputModuleBase::doBeginJob() { + this->beginJob(); + } + + void OutputModuleBase::doEndJob() { + endJob(); + } + + bool OutputModuleBase::prePrefetchSelection(StreamID id, EventPrincipal const& ep, ModuleCallingContext const* mcc) { + + auto& s = selectors_[id.value()]; + return wantAllEvents_ or s.wantEvent(ep,mcc); + } + + bool + OutputModuleBase::doEvent(EventPrincipal const& ep, + EventSetup const&, + ActivityRegistry* act, + ModuleCallingContext const* mcc) { + + { + EventSignalsSentry sentry(act,mcc); + write(ep, mcc); + } + + auto remainingEvents = remainingEvents_.load(); + bool keepTrying = remainingEvents > 0; + while(keepTrying) { + auto newValue = remainingEvents - 1; + keepTrying = !remainingEvents_.compare_exchange_strong(remainingEvents, newValue); + if(keepTrying) { + // the exchange failed because the value was changed by another thread. + // remainingEvents was changed to be the new value of remainingEvents_; + keepTrying = remainingEvents > 0; + } + } + return true; + } + + bool + OutputModuleBase::doBeginRun(RunPrincipal const& rp, + EventSetup const&, + ModuleCallingContext const* mcc) { + doBeginRun_(rp, mcc); + return true; + } + + bool + OutputModuleBase::doEndRun(RunPrincipal const& rp, + EventSetup const&, + ModuleCallingContext const* mcc) { + doEndRun_(rp, mcc); + return true; + } + + void + OutputModuleBase::doWriteRun(RunPrincipal const& rp, + ModuleCallingContext const* mcc) { + writeRun(rp, mcc); + } + + bool + OutputModuleBase::doBeginLuminosityBlock(LuminosityBlockPrincipal const& lbp, + EventSetup const&, + ModuleCallingContext const* mcc) { + doBeginLuminosityBlock_(lbp, mcc); + return true; + } + + bool + OutputModuleBase::doEndLuminosityBlock(LuminosityBlockPrincipal const& lbp, + EventSetup const&, + ModuleCallingContext const* mcc) { + doEndLuminosityBlock_(lbp, mcc); + return true; + } + + void OutputModuleBase::doWriteLuminosityBlock(LuminosityBlockPrincipal const& lbp, + ModuleCallingContext const* mcc) { + writeLuminosityBlock(lbp, mcc); + } + + void OutputModuleBase::doOpenFile(FileBlock const& fb) { + openFile(fb); + } + + void OutputModuleBase::doRespondToOpenInputFile(FileBlock const& fb) { + doRespondToOpenInputFile_(fb); + } + + void OutputModuleBase::doRespondToCloseInputFile(FileBlock const& fb) { + doRespondToCloseInputFile_(fb); + } + + void + OutputModuleBase::doPreForkReleaseResources() { + preForkReleaseResources(); + } + + void + OutputModuleBase::doPostForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren) { + postForkReacquireResources(iChildIndex, iNumberOfChildren); + } + + void + OutputModuleBase::preForkReleaseResources() {} + + void + OutputModuleBase::postForkReacquireResources(unsigned int /*iChildIndex*/, unsigned int /*iNumberOfChildren*/) {} + + + void OutputModuleBase::maybeOpenFile() { + if(!isFileOpen()) reallyOpenFile(); + } + + void OutputModuleBase::doCloseFile() { + if(isFileOpen()) { + reallyCloseFile(); + } + } + + void OutputModuleBase::reallyCloseFile() { + } + + BranchIDLists const* + OutputModuleBase::branchIDLists() { + if(!droppedBranchIDToKeptBranchID_.empty()) { + // Make a private copy of the BranchIDLists. + *branchIDLists_ = *origBranchIDLists_; + // Check for branches dropped while an EDAlias was kept. + for(BranchIDList& branchIDList : *branchIDLists_) { + for(BranchID::value_type& branchID : branchIDList) { + // Replace BranchID of each dropped branch with that of the kept alias, so the alias branch will have the product ID of the original branch. + std::map::const_iterator iter = droppedBranchIDToKeptBranchID_.find(branchID); + if(iter != droppedBranchIDToKeptBranchID_.end()) { + branchID = iter->second; + } + } + } + return branchIDLists_.get(); + } + return origBranchIDLists_; + } + + ThinnedAssociationsHelper const* + OutputModuleBase::thinnedAssociationsHelper() const { + return thinnedAssociationsHelper_.get(); + } + + ModuleDescription const& + OutputModuleBase::description() const { + return moduleDescription_; + } + + bool + OutputModuleBase::selected(BranchDescription const& desc) const { + return productSelector_.selected(desc); + } + + void + OutputModuleBase::fillDescriptions(ConfigurationDescriptions& descriptions) { + ParameterSetDescription desc; + desc.setUnknown(); + descriptions.addDefault(desc); + } + + void + OutputModuleBase::fillDescription(ParameterSetDescription& desc) { + ProductSelectorRules::fillDescription(desc, "outputCommands"); + EventSelector::fillDescription(desc); + } + + void + OutputModuleBase::prevalidate(ConfigurationDescriptions& ) { + } + + + static const std::string kBaseType("OutputModule"); + const std::string& + OutputModuleBase::baseType() { + return kBaseType; + } + + void + OutputModuleBase::setEventSelectionInfo(std::map > > const& outputModulePathPositions, + bool anyProductProduced) { + selector_config_id_ = detail::registerProperSelectionInfo(getParameterSet(selector_config_id_), + description().moduleLabel(), + outputModulePathPositions, + anyProductProduced); + } + } +} diff --git a/FWCore/Framework/src/global/outputmoduleImplementors.cc b/FWCore/Framework/src/global/outputmoduleImplementors.cc new file mode 100644 index 0000000000000..0a5f2f9091440 --- /dev/null +++ b/FWCore/Framework/src/global/outputmoduleImplementors.cc @@ -0,0 +1,33 @@ +// -*- C++ -*- +// +// Package: FWCore/Framework +// Class : outputmoduleImplementors +// +// Implementation: +// Explicitly instantiate implementor templates for OutputModuleBase +// +// + +// system include files + +// user include files +#include "FWCore/Framework/src/global/implementorsMethods.h" +#include "FWCore/Framework/interface/global/OutputModule.h" + +namespace edm { + + class ModuleCallingContext; + + namespace global { + namespace outputmodule { + void InputFileWatcher::doRespondToOpenInputFile_(FileBlock const& iB) + { + respondToOpenInputFile(iB); + } + void InputFileWatcher::doRespondToCloseInputFile_(FileBlock const& iB) + { + respondToCloseInputFile(iB); + } + } + } +} diff --git a/FWCore/Framework/src/one/OutputModuleBase.cc b/FWCore/Framework/src/one/OutputModuleBase.cc index 2785a0d3543c3..8cf05b9abf0ff 100644 --- a/FWCore/Framework/src/one/OutputModuleBase.cc +++ b/FWCore/Framework/src/one/OutputModuleBase.cc @@ -321,7 +321,7 @@ namespace edm { } BranchIDLists const* - OutputModuleBase::branchIDLists() const { + OutputModuleBase::branchIDLists() { if(!droppedBranchIDToKeptBranchID_.empty()) { // Make a private copy of the BranchIDLists. *branchIDLists_ = *origBranchIDLists_; diff --git a/FWCore/Framework/test/BuildFile.xml b/FWCore/Framework/test/BuildFile.xml index 6e76d04414b09..582fe2c0455ee 100644 --- a/FWCore/Framework/test/BuildFile.xml +++ b/FWCore/Framework/test/BuildFile.xml @@ -148,7 +148,7 @@ - + diff --git a/FWCore/Framework/test/global_outputmodule_t.cppunit.cc b/FWCore/Framework/test/global_outputmodule_t.cppunit.cc new file mode 100644 index 0000000000000..a28a330df0979 --- /dev/null +++ b/FWCore/Framework/test/global_outputmodule_t.cppunit.cc @@ -0,0 +1,311 @@ +/* + * proxyfactoryproducer_t.cc + * EDMProto + * + */ +#include +#include +#include +#include +#include +#include "FWCore/Framework/interface/global/OutputModule.h" +#include "FWCore/Framework/src/OutputModuleCommunicatorT.h" +#include "FWCore/Framework/src/WorkerT.h" +#include "FWCore/Framework/interface/OccurrenceTraits.h" +#include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h" +#include "DataFormats/Provenance/interface/ProductRegistry.h" +#include "DataFormats/Provenance/interface/BranchIDListHelper.h" +#include "DataFormats/Provenance/interface/ThinnedAssociationsHelper.h" +#include "FWCore/Framework/interface/HistoryAppender.h" +#include "FWCore/Utilities/interface/GlobalIdentifier.h" +#include "FWCore/Framework/interface/TriggerNamesService.h" +#include "FWCore/ServiceRegistry/interface/ParentContext.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" +#include "FWCore/Framework/interface/FileBlock.h" +#include "FWCore/Framework/src/PreallocationConfiguration.h" + + +#include "FWCore/Utilities/interface/Exception.h" + +#include "cppunit/extensions/HelperMacros.h" + +namespace edm { + class ModuleCallingContext; +} + +class testGlobalOutputModule: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(testGlobalOutputModule); + + CPPUNIT_TEST(basicTest); + CPPUNIT_TEST(fileTest); + + CPPUNIT_TEST_SUITE_END(); +public: + testGlobalOutputModule(); + + void setUp(){} + void tearDown(){} + + void basicTest(); + void fileTest(); + + enum class Trans { + kBeginJob, + kGlobalOpenInputFile, + kGlobalBeginRun, + kGlobalBeginRunProduce, + kGlobalBeginLuminosityBlock, + kEvent, + kGlobalEndLuminosityBlock, + kGlobalEndRun, + kGlobalCloseInputFile, + kEndJob + }; + + typedef std::vector Expectations; + +private: + + std::map> m_transToFunc; + + edm::ProcessConfiguration m_procConfig; + edm::PreallocationConfiguration m_preallocConfig; + std::shared_ptr m_prodReg; + std::shared_ptr m_idHelper; + std::shared_ptr m_associationsHelper; + std::unique_ptr m_ep; + edm::HistoryAppender historyAppender_; + std::shared_ptr m_lbp; + std::shared_ptr m_rp; + std::shared_ptr m_actReg; + edm::EventSetup* m_es = nullptr; + edm::ModuleDescription m_desc = {"Dummy","dummy"}; + edm::WorkerParams m_params; + + typedef edm::service::TriggerNamesService TNS; + typedef edm::serviceregistry::ServiceWrapper w_TNS; + std::shared_ptr tnsptr_; + edm::ServiceToken serviceToken_; + + template + void testTransitions(std::shared_ptr iMod, Expectations const& iExpect); + + class BasicOutputModule : public edm::global::OutputModule<> { + public: + using edm::global::OutputModuleBase::doPreallocate; + BasicOutputModule(edm::ParameterSet const& iPSet): edm::global::OutputModuleBase(iPSet),edm::global::OutputModule<>(iPSet){} + unsigned int m_count = 0; + + void write(edm::EventPrincipal const&, edm::ModuleCallingContext const*) override { + ++m_count; + } + void writeRun(edm::RunPrincipal const&, edm::ModuleCallingContext const*) override { + ++m_count; + } + void writeLuminosityBlock(edm::LuminosityBlockPrincipal const&, edm::ModuleCallingContext const*) override { + ++m_count; + } + + }; + + class FileOutputModule : public edm::global::OutputModule { + public: + using edm::global::OutputModuleBase::doPreallocate; + FileOutputModule(edm::ParameterSet const& iPSet) : edm::global::OutputModuleBase(iPSet), edm::global::OutputModule(iPSet) {} + unsigned int m_count = 0; + void write(edm::EventPrincipal const&, edm::ModuleCallingContext const*) override { + ++m_count; + } + void writeRun(edm::RunPrincipal const&, edm::ModuleCallingContext const*) override { + ++m_count; + } + void writeLuminosityBlock(edm::LuminosityBlockPrincipal const&, edm::ModuleCallingContext const*) override { + ++m_count; + } + + void respondToOpenInputFile(edm::FileBlock const&) override { + ++m_count; + } + + void respondToCloseInputFile(edm::FileBlock const&) override { + ++m_count; + } + }; + +}; + +namespace { + struct ShadowStreamID { + constexpr ShadowStreamID():value(0){} + unsigned int value; + }; + + union IDUnion { + IDUnion(): m_shadow() {} + ShadowStreamID m_shadow; + edm::StreamID m_id; + }; +} +static edm::StreamID makeID() { + IDUnion u; + assert(u.m_id.value() == 0); + return u.m_id; +} +static const edm::StreamID s_streamID0 = makeID(); + +///registration of the test so that the runner can find it +CPPUNIT_TEST_SUITE_REGISTRATION(testGlobalOutputModule); + +testGlobalOutputModule::testGlobalOutputModule(): +m_prodReg(new edm::ProductRegistry{}), +m_idHelper(new edm::BranchIDListHelper{}), +m_associationsHelper(new edm::ThinnedAssociationsHelper{}), +m_ep() +{ + //Setup the principals + m_prodReg->setFrozen(); + m_idHelper->updateFromRegistry(*m_prodReg); + edm::EventID eventID = edm::EventID::firstValidEvent(); + + std::string uuid = edm::createGlobalIdentifier(); + edm::Timestamp now(1234567UL); + auto runAux = std::make_shared(eventID.run(), now, now); + m_rp.reset(new edm::RunPrincipal(runAux, m_prodReg, m_procConfig, &historyAppender_,0)); + auto lumiAux = std::make_shared(m_rp->run(), 1, now, now); + m_lbp.reset(new edm::LuminosityBlockPrincipal(lumiAux, m_prodReg, m_procConfig, &historyAppender_,0)); + m_lbp->setRunPrincipal(m_rp); + edm::EventAuxiliary eventAux(eventID, uuid, now, true); + + m_ep.reset(new edm::EventPrincipal(m_prodReg, + m_idHelper, + m_associationsHelper, + m_procConfig,nullptr)); + edm::ProcessHistoryRegistry phr; + m_ep->fillEventPrincipal(eventAux, phr); + m_ep->setLuminosityBlockPrincipal(m_lbp); + m_actReg.reset(new edm::ActivityRegistry); + + //For each transition, bind a lambda which will call the proper method of the Worker + m_transToFunc[Trans::kGlobalOpenInputFile] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator*) { + edm::FileBlock fb; + iBase->respondToOpenInputFile(fb); + }; + + + m_transToFunc[Trans::kGlobalBeginRun] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator*) { + typedef edm::OccurrenceTraits Traits; + edm::ParentContext parentContext; + iBase->doWork(*m_rp,*m_es, edm::StreamID::invalidStreamID(), parentContext, nullptr); }; + + m_transToFunc[Trans::kGlobalBeginLuminosityBlock] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator*) { + typedef edm::OccurrenceTraits Traits; + edm::ParentContext parentContext; + iBase->doWork(*m_lbp,*m_es, edm::StreamID::invalidStreamID(), parentContext, nullptr); }; + + m_transToFunc[Trans::kEvent] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator*) { + typedef edm::OccurrenceTraits Traits; + edm::StreamContext streamContext(s_streamID0, nullptr); + edm::ParentContext parentContext(&streamContext); + iBase->setActivityRegistry(m_actReg); + iBase->doWork(*m_ep,*m_es, s_streamID0, parentContext, nullptr); }; + + m_transToFunc[Trans::kGlobalEndLuminosityBlock] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator* iComm) { + typedef edm::OccurrenceTraits Traits; + edm::ParentContext parentContext; + iBase->doWork(*m_lbp,*m_es, edm::StreamID::invalidStreamID(), parentContext, nullptr); + iComm->writeLumi(*m_lbp, nullptr); + }; + + m_transToFunc[Trans::kGlobalEndRun] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator* iComm) { + typedef edm::OccurrenceTraits Traits; + edm::ParentContext parentContext; + iBase->doWork(*m_rp,*m_es, edm::StreamID::invalidStreamID(), parentContext, nullptr); + iComm->writeRun(*m_rp, nullptr); + }; + + m_transToFunc[Trans::kGlobalCloseInputFile] = [this](edm::Worker* iBase, edm::OutputModuleCommunicator*) { + edm::FileBlock fb; + iBase->respondToCloseInputFile(fb); + }; + + + // We want to create the TriggerNamesService because it is used in + // the tests. We do that here, but first we need to build a minimal + // parameter set to pass to its constructor. Then we build the + // service and setup the service system. + edm::ParameterSet proc_pset; + + std::string processName("HLT"); + proc_pset.addParameter("@process_name", processName); + + std::vector paths; + edm::ParameterSet trigPaths; + trigPaths.addParameter>("@trigger_paths", paths); + proc_pset.addParameter("@trigger_paths", trigPaths); + + std::vector endPaths; + proc_pset.addParameter>("@end_paths", endPaths); + + // Now create and setup the service + tnsptr_.reset(new w_TNS(std::auto_ptr(new TNS(proc_pset)))); + + serviceToken_ = edm::ServiceRegistry::createContaining(tnsptr_); + + +} + + +namespace { + template + void + testTransition(std::shared_ptr iMod, edm::Worker* iWorker, edm::OutputModuleCommunicator* iComm, testGlobalOutputModule::Trans iTrans, testGlobalOutputModule::Expectations const& iExpect, std::function iFunc) { + assert(0==iMod->m_count); + iFunc(iWorker,iComm); + auto count = std::count(iExpect.begin(),iExpect.end(),iTrans); + if(count != iMod->m_count) { + std::cout<<"For trans " <::type >(iTrans)<< " expected "<m_count<m_count == count); + iMod->m_count = 0; + iWorker->reset(); + } +} + +template +void +testGlobalOutputModule::testTransitions(std::shared_ptr iMod, Expectations const& iExpect) { + iMod->doPreallocate(m_preallocConfig); + edm::WorkerT w{iMod,m_desc,m_params.actions_}; + edm::OutputModuleCommunicatorT comm(iMod.get()); + for(auto& keyVal: m_transToFunc) { + testTransition(iMod,&w,&comm,keyVal.first,iExpect,keyVal.second); + } +} + + +void testGlobalOutputModule::basicTest() +{ + //make the services available + edm::ServiceRegistry::Operate operate(serviceToken_); + + edm::ParameterSet pset; + std::shared_ptr testProd{ new BasicOutputModule(pset) }; + + CPPUNIT_ASSERT(0 == testProd->m_count); + testTransitions(testProd, {Trans::kEvent,Trans::kGlobalEndLuminosityBlock, Trans::kGlobalEndRun}); +} + +void testGlobalOutputModule::fileTest() +{ + //make the services available + edm::ServiceRegistry::Operate operate(serviceToken_); + + edm::ParameterSet pset; + std::shared_ptr testProd{ new FileOutputModule(pset) }; + + CPPUNIT_ASSERT(0 == testProd->m_count); + testTransitions(testProd, {Trans::kGlobalOpenInputFile, Trans::kEvent, Trans::kGlobalEndLuminosityBlock, Trans::kGlobalEndRun, Trans::kGlobalCloseInputFile}); +} + diff --git a/FWCore/Modules/src/AsciiOutputModule.cc b/FWCore/Modules/src/AsciiOutputModule.cc index 4919dd126abe9..ee455e452389b 100644 --- a/FWCore/Modules/src/AsciiOutputModule.cc +++ b/FWCore/Modules/src/AsciiOutputModule.cc @@ -6,7 +6,7 @@ #include #include #include -#include "FWCore/Framework/interface/OutputModule.h" +#include "FWCore/Framework/interface/global/OutputModule.h" #include "FWCore/Framework/interface/EventPrincipal.h" #include "FWCore/Framework/interface/MakerMacros.h" #include "DataFormats/Provenance/interface/Provenance.h" @@ -19,7 +19,7 @@ namespace edm { class ModuleCallingContext; - class AsciiOutputModule : public OutputModule { + class AsciiOutputModule : public global::OutputModule<> { public: // We do not take ownership of passed stream. explicit AsciiOutputModule(ParameterSet const& pset); @@ -36,7 +36,8 @@ namespace edm { }; AsciiOutputModule::AsciiOutputModule(ParameterSet const& pset) : - OutputModule(pset), + global::OutputModuleBase(pset), + global::OutputModule<>(pset), prescale_(pset.getUntrackedParameter("prescale")), verbosity_(pset.getUntrackedParameter("verbosity")), counter_(0) { diff --git a/FWCore/ParameterSet/interface/ParameterSetDescriptionFiller.h b/FWCore/ParameterSet/interface/ParameterSetDescriptionFiller.h index a3afd12beaca3..9d800f65698ba 100644 --- a/FWCore/ParameterSet/interface/ParameterSetDescriptionFiller.h +++ b/FWCore/ParameterSet/interface/ParameterSetDescriptionFiller.h @@ -42,6 +42,7 @@ method of the templated argument. This allows the ParameterSetDescriptionFiller #include "FWCore/Framework/interface/global/EDAnalyzer.h" #include "FWCore/Framework/interface/global/EDProducer.h" #include "FWCore/Framework/interface/global/EDFilter.h" +#include "FWCore/Framework/interface/global/OutputModule.h" namespace edm { template< typename T> @@ -88,6 +89,8 @@ namespace edm { return kExtendedBaseForGlobalEDProducer; if (std::is_base_of::value) return kExtendedBaseForGlobalEDFilter; + if (std::is_base_of::value) + return kExtendedBaseForGlobalOutputModule; return kEmpty; } diff --git a/FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h b/FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h index c128b8e7a91f5..2b37cc3c08c3b 100644 --- a/FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h +++ b/FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h @@ -65,6 +65,7 @@ class ParameterSetDescriptionFillerBase static const std::string kExtendedBaseForGlobalEDAnalyzer; static const std::string kExtendedBaseForGlobalEDProducer; static const std::string kExtendedBaseForGlobalEDFilter; + static const std::string kExtendedBaseForGlobalOutputModule; private: ParameterSetDescriptionFillerBase(const ParameterSetDescriptionFillerBase&); // stop default diff --git a/FWCore/ParameterSet/src/ParameterSetDescriptionFillerBase.cc b/FWCore/ParameterSet/src/ParameterSetDescriptionFillerBase.cc index 49a6a6bc82860..26ab0de15cd88 100644 --- a/FWCore/ParameterSet/src/ParameterSetDescriptionFillerBase.cc +++ b/FWCore/ParameterSet/src/ParameterSetDescriptionFillerBase.cc @@ -37,6 +37,7 @@ const std::string edm::ParameterSetDescriptionFillerBase::kExtendedBaseForStream const std::string edm::ParameterSetDescriptionFillerBase::kExtendedBaseForGlobalEDAnalyzer("global::EDAnalyzer"); const std::string edm::ParameterSetDescriptionFillerBase::kExtendedBaseForGlobalEDProducer("global::EDProducer"); const std::string edm::ParameterSetDescriptionFillerBase::kExtendedBaseForGlobalEDFilter("global::EDFilter"); +const std::string edm::ParameterSetDescriptionFillerBase::kExtendedBaseForGlobalOutputModule("global::OutputModule"); // // static data member definitions diff --git a/IOPool/Output/src/RootOutputFile.h b/IOPool/Output/src/RootOutputFile.h index f60d25e65630e..5b4d4efd43b16 100644 --- a/IOPool/Output/src/RootOutputFile.h +++ b/IOPool/Output/src/RootOutputFile.h @@ -101,7 +101,7 @@ namespace edm { std::string file_; std::string logicalFile_; JobReport::Token reportToken_; - PoolOutputModule const* om_; + PoolOutputModule* om_; int whyNotFastClonable_; bool canFastCloneAux_; std::shared_ptr filePtr_;