Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:13:45

0001 #ifndef DQMServices_Core_DQMEDAnalyzer_h
0002 #define DQMServices_Core_DQMEDAnalyzer_h
0003 
0004 #include "FWCore/Framework/interface/stream/makeGlobal.h"
0005 
0006 struct DQMEDAnalyzerGlobalCache;
0007 
0008 // If we declare a global cache (which is not absolutely needed right now, but
0009 // might be in the future), the framework will try to pass it to the
0010 // constructor. But, we don't want to change all subsystem code whenever we
0011 // change that implementation detail, so instead we hack the framework to not
0012 // do that. See issue #27125.
0013 namespace edm::stream::impl {
0014   template <typename T>
0015   T* makeStreamModule(edm::ParameterSet const& iPSet, DQMEDAnalyzerGlobalCache const* global) {
0016     return new T(iPSet);
0017   }
0018 }  // namespace edm::stream::impl
0019 
0020 #include "DQMServices/Core/interface/DQMStore.h"
0021 #include "FWCore/Framework/interface/Event.h"
0022 #include "FWCore/Framework/interface/Run.h"
0023 #include "FWCore/ServiceRegistry/interface/Service.h"
0024 #include "FWCore/Framework/interface/stream/EDProducer.h"
0025 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0026 #include "DataFormats/Histograms/interface/DQMToken.h"
0027 
0028 struct DQMEDAnalyzerGlobalCache {
0029   // slightly overkill for now, but we might want to putt the full DQMStore
0030   // here at some point.
0031   mutable std::mutex master_;
0032   mutable edm::EDPutTokenT<DQMToken> lumiToken_;
0033   mutable edm::EDPutTokenT<DQMToken> runToken_;
0034 };
0035 
0036 /**
0037  * The standard DQM module base.
0038  */
0039 class DQMEDAnalyzer : public edm::stream::EDProducer<edm::GlobalCache<DQMEDAnalyzerGlobalCache>,
0040                                                      edm::EndRunProducer,
0041                                                      edm::EndLuminosityBlockProducer,
0042                                                      edm::Accumulator> {
0043 public:
0044   typedef dqm::reco::DQMStore DQMStore;
0045   typedef dqm::reco::MonitorElement MonitorElement;
0046 
0047   virtual bool getCanSaveByLumi() { return true; }
0048 
0049   // framework calls in the order of invocation
0050 
0051   static std::unique_ptr<DQMEDAnalyzerGlobalCache> initializeGlobalCache(edm::ParameterSet const&) {
0052     return std::make_unique<DQMEDAnalyzerGlobalCache>();
0053   }
0054 
0055   DQMEDAnalyzer() {
0056     // for whatever reason we need the explicit `template` keyword here.
0057     runToken_ = this->template produces<DQMToken, edm::Transition::EndRun>("DQMGenerationRecoRun");
0058     lumiToken_ = this->template produces<DQMToken, edm::Transition::EndLuminosityBlock>("DQMGenerationRecoLumi");
0059     streamId_ = edm::StreamID::invalidStreamID().value();
0060   }
0061 
0062   void beginStream(edm::StreamID id) final {
0063     assert(streamId_ == edm::StreamID::invalidStreamID().value() || streamId_ == id.value());
0064     this->streamId_ = id.value();
0065     // now, since we can't access the global cache in the constructor (we
0066     // blocked that above to not expose the cache to the subsystem code,
0067     // we need to store the tokens here.
0068     // This also requires locking, since the streams will run in parallel.
0069     // See https://github.com/cms-sw/cmssw/issues/27291#issuecomment-505909101
0070     auto lock = std::scoped_lock(globalCache()->master_);
0071     if (globalCache()->runToken_.isUninitialized()) {
0072       globalCache()->lumiToken_ = lumiToken_;
0073       globalCache()->runToken_ = runToken_;
0074     }
0075   }
0076 
0077   void beginRun(edm::Run const& run, edm::EventSetup const& setup) final {
0078     // if we run booking multiple times because there are multiple runs in a
0079     // job, this is needed to make sure all existing MEs are in a valid state
0080     // before the booking code runs.
0081     edm::Service<DQMStore>()->initLumi(run.run(), /* lumi */ 0, meId());
0082     edm::Service<DQMStore>()->enterLumi(run.run(), /* lumi */ 0, meId());
0083     dqmBeginRun(run, setup);
0084     edm::Service<DQMStore>()->bookTransaction(
0085         [this, &run, &setup](DQMStore::IBooker& booker) {
0086           booker.cd();
0087           this->bookHistograms(booker, run, setup);
0088         },
0089         meId(),
0090         this->getCanSaveByLumi());
0091     edm::Service<DQMStore>()->initLumi(run.run(), /* lumi */ 0, meId());
0092     edm::Service<DQMStore>()->enterLumi(run.run(), /* lumi */ 0, meId());
0093   }
0094 
0095   void beginLuminosityBlock(edm::LuminosityBlock const& lumi, edm::EventSetup const& setup) final {
0096     edm::Service<DQMStore>()->enterLumi(lumi.run(), lumi.luminosityBlock(), meId());
0097   }
0098 
0099   void accumulate(edm::Event const& event, edm::EventSetup const& setup) final { analyze(event, setup); }
0100 
0101   void endLuminosityBlock(edm::LuminosityBlock const& lumi, edm::EventSetup const& setup) final {
0102     edm::Service<DQMStore>()->leaveLumi(lumi.run(), lumi.luminosityBlock(), meId());
0103   }
0104 
0105   static void globalEndLuminosityBlockProduce(edm::LuminosityBlock& lumi,
0106                                               edm::EventSetup const& setup,
0107                                               LuminosityBlockContext const* context) {
0108     lumi.emplace(context->global()->lumiToken_);
0109   }
0110 
0111   void endRun(edm::Run const& run, edm::EventSetup const& setup) final {
0112     edm::Service<DQMStore>()->leaveLumi(run.run(), /* lumi */ 0, meId());
0113   }
0114   static void globalEndRunProduce(edm::Run& run, edm::EventSetup const& setup, RunContext const* context) {
0115     run.emplace<DQMToken>(context->global()->runToken_);
0116   }
0117 
0118   static void globalEndJob(DQMEDAnalyzerGlobalCache const*) {}
0119 
0120   // methods to be implemented by the user, in order of invocation
0121   virtual void dqmBeginRun(edm::Run const&, edm::EventSetup const&) {}
0122   virtual void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&) = 0;
0123   virtual void analyze(edm::Event const&, edm::EventSetup const&) {}
0124 
0125 protected:
0126   edm::EDPutTokenT<DQMToken> runToken_;
0127   edm::EDPutTokenT<DQMToken> lumiToken_;
0128   unsigned int streamId_;
0129   uint64_t meId() const { return (((uint64_t)streamId_) << 32) + this->moduleDescription().id(); }
0130 };
0131 
0132 #endif  // DQMServices_Core_DQMEDAnalyzer_h