Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-07-03 23:08:15

0001 #ifndef DQMServices_Core_DQMStore_h
0002 #define DQMServices_Core_DQMStore_h
0003 
0004 #include "DQMServices/Core/interface/MonitorElement.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006 
0007 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0008 
0009 #include <type_traits>
0010 #include <functional>
0011 #include <mutex>
0012 
0013 // TODO: Remove at some point:
0014 #define TRACE(msg) \
0015   std::cout << "TRACE: " << __FILE__ << ":" << __LINE__ << "(" << __FUNCTION__ << ") " << msg << std::endl;
0016 #define TRACE_ TRACE("");
0017 
0018 namespace dqm {
0019   namespace implementation {
0020     using MonitorElement = dqm::legacy::MonitorElement;
0021     class DQMStore;
0022 
0023     // The common implementation to change folders
0024     class NavigatorBase {
0025     public:
0026       virtual void cd();
0027       // cd is identical to setCurrentFolder!
0028       DQM_DEPRECATED
0029       virtual void cd(std::string const& dir);
0030       // This is the only method that is allowed to change cwd_ value
0031       virtual void setCurrentFolder(std::string const& fullpath);
0032       virtual void goUp();
0033       // returns the current directory without (!) trailing slash or empty string.
0034       virtual std::string pwd();
0035 
0036       virtual ~NavigatorBase() {}
0037 
0038     protected:
0039       NavigatorBase(){};
0040       std::string cwd_ = "";
0041     };
0042 
0043     class IBooker : public dqm::implementation::NavigatorBase {
0044     public:
0045       // DQMStore configures the IBooker in bookTransaction.
0046       friend class DQMStore;
0047 
0048       // functor to be passed as a default argument that does not do anything.
0049       struct NOOP {
0050         void operator()(TH1*) const {};
0051         void operator()() const {};
0052       };
0053 
0054       //
0055       // Booking Methods, templated to allow passing in lambdas.
0056       // The variations taking ROOT object pointers do NOT take ownership of
0057       // the object; it will be clone'd.
0058       //
0059 
0060       // The function argument as an optional template parameter adds a lot of
0061       // ambiguity to the overload resolution, since it accepts *anything* by
0062       // default (and it does not help that we rely on implicit conversions for
0063       // almost all of the arguments in many cases, converting string literal
0064       // to TString and ints to floats, and 0 also prefers to convert to float*
0065       // and so on ...).
0066       // So, we use SFINAE to restrict the template parameter type, but that is
0067       // also not that easy: there is no way to check for sth. callable in
0068       // type_traits (`is_function` is not the right thing!), so instead we
0069       // check for not-numeric things, which works most of the time (though e.g.
0070       // enum constants somehow still pass as not arithmetic and need an
0071       // explicit cast to resolve the ambiguity).
0072       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0073       MonitorElement* bookInt(TString const& name, FUNC onbooking = NOOP()) {
0074         return bookME(name, MonitorElementData::Kind::INT, [=]() {
0075           onbooking();
0076           return nullptr;
0077         });
0078       }
0079       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0080       MonitorElement* bookFloat(TString const& name, FUNC onbooking = NOOP()) {
0081         return bookME(name, MonitorElementData::Kind ::REAL, [=]() {
0082           onbooking();
0083           return nullptr;
0084         });
0085       }
0086       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0087       MonitorElement* bookString(TString const& name, TString const& value, FUNC onbooking = NOOP()) {
0088         std::string initial_value(value);
0089         auto me = bookME(name, MonitorElementData::Kind::STRING, [=]() {
0090           onbooking();
0091           return nullptr;
0092         });
0093         me->Fill(initial_value);
0094         return me;
0095       }
0096 
0097       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0098       MonitorElement* book1D(TString const& name,
0099                              TString const& title,
0100                              int const nchX,
0101                              double const lowX,
0102                              double const highX,
0103                              FUNC onbooking = NOOP()) {
0104         return bookME(name, MonitorElementData::Kind::TH1F, [=]() {
0105           auto th1 = new TH1F(name, title, nchX, lowX, highX);
0106           onbooking(th1);
0107           return th1;
0108         });
0109       }
0110       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0111       MonitorElement* book1D(
0112           TString const& name, TString const& title, int nchX, float const* xbinsize, FUNC onbooking = NOOP()) {
0113         return bookME(name, MonitorElementData::Kind::TH1F, [=]() {
0114           auto th1 = new TH1F(name, title, nchX, xbinsize);
0115           onbooking(th1);
0116           return th1;
0117         });
0118       }
0119       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0120       MonitorElement* book1D(TString const& name, TH1F* object, FUNC onbooking = NOOP()) {
0121         return bookME(
0122             name,
0123             MonitorElementData::Kind::TH1F,
0124             [=]() {
0125               auto th1 = static_cast<TH1F*>(object->Clone(name));
0126               onbooking(th1);
0127               return th1;
0128             },
0129             /* forceReplace */ true);
0130       }
0131 
0132       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0133       MonitorElement* book1S(
0134           TString const& name, TString const& title, int nchX, double lowX, double highX, FUNC onbooking = NOOP()) {
0135         return bookME(name, MonitorElementData::Kind::TH1S, [=]() {
0136           auto th1 = new TH1S(name, title, nchX, lowX, highX);
0137           onbooking(th1);
0138           return th1;
0139         });
0140       }
0141       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0142       MonitorElement* book1S(TString const& name, TH1S* object, FUNC onbooking = NOOP()) {
0143         return bookME(
0144             name,
0145             MonitorElementData::Kind::TH1S,
0146             [=]() {
0147               auto th1 = static_cast<TH1S*>(object->Clone(name));
0148               onbooking(th1);
0149               return th1;
0150             },
0151             /* forceReplace */ true);
0152       }
0153 
0154       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0155       MonitorElement* book1DD(
0156           TString const& name, TString const& title, int nchX, double lowX, double highX, FUNC onbooking = NOOP()) {
0157         return bookME(name, MonitorElementData::Kind::TH1D, [=]() {
0158           auto th1 = new TH1D(name, title, nchX, lowX, highX);
0159           onbooking(th1);
0160           return th1;
0161         });
0162       }
0163       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0164       MonitorElement* book1DD(
0165           TString const& name, TString const& title, int nchX, float const* xbinsize, FUNC onbooking = NOOP()) {
0166         return bookME(name, MonitorElementData::Kind::TH1D, [=]() {
0167           auto th1 = new TH1D(name, title, nchX, xbinsize);
0168           onbooking(th1);
0169           return th1;
0170         });
0171       }
0172       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0173       MonitorElement* book1DD(TString const& name, TH1D* object, FUNC onbooking = NOOP()) {
0174         return bookME(
0175             name,
0176             MonitorElementData::Kind::TH1D,
0177             [=]() {
0178               auto th1 = static_cast<TH1D*>(object->Clone(name));
0179               onbooking(th1);
0180               return th1;
0181             },
0182             /* forceReplace */ true);
0183       }
0184 
0185       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0186       MonitorElement* book1I(TString const& name,
0187                              TString const& title,
0188                              int const nchX,
0189                              double const lowX,
0190                              double const highX,
0191                              FUNC onbooking = NOOP()) {
0192         return bookME(name, MonitorElementData::Kind::TH1I, [=]() {
0193           auto th1 = new TH1I(name, title, nchX, lowX, highX);
0194           onbooking(th1);
0195           return th1;
0196         });
0197       }
0198       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0199       MonitorElement* book1I(
0200           TString const& name, TString const& title, int nchX, float const* xbinsize, FUNC onbooking = NOOP()) {
0201         return bookME(name, MonitorElementData::Kind::TH1I, [=]() {
0202           auto th1 = new TH1I(name, title, nchX, xbinsize);
0203           onbooking(th1);
0204           return th1;
0205         });
0206       }
0207       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0208       MonitorElement* book1I(TString const& name, TH1I* object, FUNC onbooking = NOOP()) {
0209         return bookME(
0210             name,
0211             MonitorElementData::Kind::TH1I,
0212             [=]() {
0213               auto th1 = static_cast<TH1I*>(object->Clone(name));
0214               onbooking(th1);
0215               return th1;
0216             },
0217             /* forceReplace */ true);
0218       }
0219 
0220       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0221       MonitorElement* book2D(TString const& name,
0222                              TString const& title,
0223                              int nchX,
0224                              double lowX,
0225                              double highX,
0226                              int nchY,
0227                              double lowY,
0228                              double highY,
0229                              FUNC onbooking = NOOP()) {
0230         return bookME(name, MonitorElementData::Kind::TH2F, [=]() {
0231           auto th2 = new TH2F(name, title, nchX, lowX, highX, nchY, lowY, highY);
0232           onbooking(th2);
0233           return th2;
0234         });
0235       }
0236       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0237       MonitorElement* book2D(TString const& name,
0238                              TString const& title,
0239                              int nchX,
0240                              float const* xbinsize,
0241                              int nchY,
0242                              float const* ybinsize,
0243                              FUNC onbooking = NOOP()) {
0244         return bookME(name, MonitorElementData::Kind::TH2F, [=]() {
0245           auto th2 = new TH2F(name, title, nchX, xbinsize, nchY, ybinsize);
0246           onbooking(th2);
0247           return th2;
0248         });
0249       }
0250       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0251       MonitorElement* book2D(TString const& name, TH2F* object, FUNC onbooking = NOOP()) {
0252         return bookME(
0253             name,
0254             MonitorElementData::Kind::TH2F,
0255             [=]() {
0256               auto th2 = static_cast<TH2F*>(object->Clone(name));
0257               onbooking(th2);
0258               return th2;
0259             },
0260             /* forceReplace */ true);
0261       }
0262       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0263       MonitorElement* book2S(TString const& name,
0264                              TString const& title,
0265                              int nchX,
0266                              double lowX,
0267                              double highX,
0268                              int nchY,
0269                              double lowY,
0270                              double highY,
0271                              FUNC onbooking = NOOP()) {
0272         return bookME(name, MonitorElementData::Kind::TH2S, [=]() {
0273           auto th2 = new TH2S(name, title, nchX, lowX, highX, nchY, lowY, highY);
0274           onbooking(th2);
0275           return th2;
0276         });
0277       }
0278       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0279       MonitorElement* book2S(TString const& name,
0280                              TString const& title,
0281                              int nchX,
0282                              float const* xbinsize,
0283                              int nchY,
0284                              float const* ybinsize,
0285                              FUNC onbooking = NOOP()) {
0286         return bookME(name, MonitorElementData::Kind::TH2S, [=]() {
0287           auto th2 = new TH2S(name, title, nchX, xbinsize, nchY, ybinsize);
0288           onbooking(th2);
0289           return th2;
0290         });
0291       }
0292       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0293       MonitorElement* book2S(TString const& name, TH2S* object, FUNC onbooking = NOOP()) {
0294         return bookME(
0295             name,
0296             MonitorElementData::Kind::TH2S,
0297             [=]() {
0298               auto th2 = static_cast<TH2S*>(object->Clone(name));
0299               onbooking(th2);
0300               return th2;
0301             },
0302             /* forceReplace */ true);
0303       }
0304       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0305       MonitorElement* book2I(TString const& name,
0306                              TString const& title,
0307                              int nchX,
0308                              double lowX,
0309                              double highX,
0310                              int nchY,
0311                              double lowY,
0312                              double highY,
0313                              FUNC onbooking = NOOP()) {
0314         return bookME(name, MonitorElementData::Kind::TH2I, [=]() {
0315           auto th2 = new TH2I(name, title, nchX, lowX, highX, nchY, lowY, highY);
0316           onbooking(th2);
0317           return th2;
0318         });
0319       }
0320       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0321       MonitorElement* book2I(TString const& name,
0322                              TString const& title,
0323                              int nchX,
0324                              float const* xbinsize,
0325                              int nchY,
0326                              float const* ybinsize,
0327                              FUNC onbooking = NOOP()) {
0328         return bookME(name, MonitorElementData::Kind::TH2I, [=]() {
0329           auto th2 = new TH2I(name, title, nchX, xbinsize, nchY, ybinsize);
0330           onbooking(th2);
0331           return th2;
0332         });
0333       }
0334       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0335       MonitorElement* book2I(TString const& name, TH2I* object, FUNC onbooking = NOOP()) {
0336         return bookME(
0337             name,
0338             MonitorElementData::Kind::TH2I,
0339             [=]() {
0340               auto th2 = static_cast<TH2I*>(object->Clone(name));
0341               onbooking(th2);
0342               return th2;
0343             },
0344             /* forceReplace */ true);
0345       }
0346       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0347       MonitorElement* book2DD(TString const& name,
0348                               TString const& title,
0349                               int nchX,
0350                               double lowX,
0351                               double highX,
0352                               int nchY,
0353                               double lowY,
0354                               double highY,
0355                               FUNC onbooking = NOOP()) {
0356         return bookME(name, MonitorElementData::Kind::TH2D, [=]() {
0357           auto th2 = new TH2D(name, title, nchX, lowX, highX, nchY, lowY, highY);
0358           onbooking(th2);
0359           return th2;
0360         });
0361       }
0362       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0363       MonitorElement* book2DD(TString const& name, TH2D* object, FUNC onbooking = NOOP()) {
0364         return bookME(
0365             name,
0366             MonitorElementData::Kind::TH2D,
0367             [=]() {
0368               auto th2 = static_cast<TH2D*>(object->Clone(name));
0369               onbooking(th2);
0370               return th2;
0371             },
0372             /* forceReplace */ true);
0373       }
0374 
0375       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0376       MonitorElement* book3D(TString const& name,
0377                              TString const& title,
0378                              int nchX,
0379                              double lowX,
0380                              double highX,
0381                              int nchY,
0382                              double lowY,
0383                              double highY,
0384                              int nchZ,
0385                              double lowZ,
0386                              double highZ,
0387                              FUNC onbooking = NOOP()) {
0388         return bookME(name, MonitorElementData::Kind::TH3F, [=]() {
0389           auto th3 = new TH3F(name, title, nchX, lowX, highX, nchY, lowY, highY, nchZ, lowZ, highZ);
0390           onbooking(th3);
0391           return th3;
0392         });
0393       }
0394       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0395       MonitorElement* book3D(TString const& name, TH3F* object, FUNC onbooking = NOOP()) {
0396         return bookME(
0397             name,
0398             MonitorElementData::Kind::TH3F,
0399             [=]() {
0400               auto th3 = static_cast<TH3F*>(object->Clone(name));
0401               onbooking(th3);
0402               return th3;
0403             },
0404             /* forceReplace */ true);
0405       }
0406 
0407       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0408       MonitorElement* bookProfile(TString const& name,
0409                                   TString const& title,
0410                                   int nchX,
0411                                   double lowX,
0412                                   double highX,
0413                                   int /* nchY */,
0414                                   double lowY,
0415                                   double highY,
0416                                   char const* option = "s",
0417                                   FUNC onbooking = NOOP()) {
0418         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0419           auto tprofile = new TProfile(name, title, nchX, lowX, highX, lowY, highY, option);
0420           onbooking(tprofile);
0421           return tprofile;
0422         });
0423       }
0424       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0425       MonitorElement* bookProfile(TString const& name,
0426                                   TString const& title,
0427                                   int nchX,
0428                                   double lowX,
0429                                   double highX,
0430                                   double lowY,
0431                                   double highY,
0432                                   char const* option = "s",
0433                                   FUNC onbooking = NOOP()) {
0434         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0435           auto tprofile = new TProfile(name, title, nchX, lowX, highX, lowY, highY, option);
0436           onbooking(tprofile);
0437           return tprofile;
0438         });
0439       }
0440       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0441       MonitorElement* bookProfile(TString const& name,
0442                                   TString const& title,
0443                                   int nchX,
0444                                   double const* xbinsize,
0445                                   int /* nchY */,
0446                                   double lowY,
0447                                   double highY,
0448                                   char const* option = "s",
0449                                   FUNC onbooking = NOOP()) {
0450         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0451           auto tprofile = new TProfile(name, title, nchX, xbinsize, lowY, highY, option);
0452           onbooking(tprofile);
0453           return tprofile;
0454         });
0455       }
0456       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0457       MonitorElement* bookProfile(TString const& name,
0458                                   TString const& title,
0459                                   int nchX,
0460                                   double const* xbinsize,
0461                                   double lowY,
0462                                   double highY,
0463                                   char const* option = "s",
0464                                   FUNC onbooking = NOOP()) {
0465         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0466           auto tprofile = new TProfile(name, title, nchX, xbinsize, lowY, highY, option);
0467           onbooking(tprofile);
0468           return tprofile;
0469         });
0470       }
0471       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0472       MonitorElement* bookProfile(TString const& name, TProfile* object, FUNC onbooking = NOOP()) {
0473         return bookME(
0474             name,
0475             MonitorElementData::Kind::TPROFILE,
0476             [=]() {
0477               auto tprofile = static_cast<TProfile*>(object->Clone(name));
0478               onbooking(tprofile);
0479               return tprofile;
0480             },
0481             /* forceReplace */ true);
0482       }
0483 
0484       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0485       MonitorElement* bookProfile2D(TString const& name,
0486                                     TString const& title,
0487                                     int nchX,
0488                                     double lowX,
0489                                     double highX,
0490                                     int nchY,
0491                                     double lowY,
0492                                     double highY,
0493                                     double lowZ,
0494                                     double highZ,
0495                                     char const* option = "s",
0496                                     FUNC onbooking = NOOP()) {
0497         return bookME(name, MonitorElementData::Kind::TPROFILE2D, [=]() {
0498           auto tprofile = new TProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option);
0499           onbooking(tprofile);
0500           return tprofile;
0501         });
0502       }
0503       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0504       MonitorElement* bookProfile2D(TString const& name,
0505                                     TString const& title,
0506                                     int nchX,
0507                                     double lowX,
0508                                     double highX,
0509                                     int nchY,
0510                                     double lowY,
0511                                     double highY,
0512                                     int /* nchZ */,
0513                                     double lowZ,
0514                                     double highZ,
0515                                     char const* option = "s",
0516                                     FUNC onbooking = NOOP()) {
0517         return bookME(name, MonitorElementData::Kind::TPROFILE2D, [=]() {
0518           auto tprofile = new TProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option);
0519           onbooking(tprofile);
0520           return tprofile;
0521         });
0522       }
0523       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0524       MonitorElement* bookProfile2D(TString const& name, TProfile2D* object, FUNC onbooking = NOOP()) {
0525         return bookME(
0526             name,
0527             MonitorElementData::Kind::TPROFILE2D,
0528             [=]() {
0529               auto tprofile = static_cast<TProfile2D*>(object->Clone(name));
0530               onbooking(tprofile);
0531               return tprofile;
0532             },
0533             /* forceReplace */ true);
0534       }
0535 
0536       //
0537       // all non-template interfaces are virtual.
0538       //
0539 
0540       virtual MonitorElementData::Scope setScope(MonitorElementData::Scope newscope);
0541       // RAII-Style guard to set and reset the Scope.
0542       template <MonitorElementData::Scope SCOPE>
0543       struct UseScope {
0544         IBooker& parent;
0545         MonitorElementData::Scope oldscope;
0546         UseScope(IBooker& booker) : parent(booker) { oldscope = parent.setScope(SCOPE); }
0547         ~UseScope() { parent.setScope(oldscope); }
0548       };
0549       using UseLumiScope = UseScope<MonitorElementData::Scope::LUMI>;
0550       using UseRunScope = UseScope<MonitorElementData::Scope::RUN>;
0551       using UseJobScope = UseScope<MonitorElementData::Scope::JOB>;
0552 
0553       ~IBooker() override;
0554 
0555     private:
0556       IBooker(DQMStore* store);
0557       virtual uint64_t setModuleID(uint64_t moduleID);
0558       virtual edm::LuminosityBlockID setRunLumi(edm::LuminosityBlockID runlumi);
0559       virtual MonitorElement* bookME(TString const& name,
0560                                      MonitorElementData::Kind kind,
0561                                      std::function<TH1*()> makeobject,
0562                                      bool forceReplace = false);
0563 
0564       DQMStore* store_ = nullptr;
0565       MonitorElementData::Scope scope_ = MonitorElementData::Scope::JOB;
0566       static constexpr uint64_t kInvalidModuleID = std::numeric_limits<uint64_t>::max();
0567       uint64_t moduleID_ = kInvalidModuleID;
0568       edm::LuminosityBlockID runlumi_ = edm::LuminosityBlockID();
0569     };
0570 
0571     class IGetter : public dqm::implementation::NavigatorBase {
0572     public:
0573       // The IGetter interface is not really suitable for concurrent lumis/runs,
0574       // so we don't even try much to get it right. Harvesting needs to run
0575       // sequentially for now. Therefore, the methods just return the next-best
0576       // global MEs that they find, ignoring Scope and run/lumi.
0577       // Since these are global MEs, they may be deleted at some point; don't
0578       // store the pointers!
0579       // They are also shared with other modules. That is save when running
0580       // multi-threaded as long as getTH1() etc. are not used, but of course
0581       // all dependencies need to be properly declared to get correct results.
0582 
0583       // TODO: review and possibly rename the all methods below:
0584       // get MEs that are direct children of full path `path`
0585       virtual std::vector<dqm::harvesting::MonitorElement*> getContents(std::string const& path) const;
0586 
0587       // get all elements below full path `path`
0588       // we have to discuss semantics here -- are run/lumi ever used?
0589       virtual std::vector<dqm::harvesting::MonitorElement*> getAllContents(std::string const& path) const;
0590       DQM_DEPRECATED
0591       virtual std::vector<dqm::harvesting::MonitorElement*> getAllContents(std::string const& path,
0592                                                                            uint32_t runNumber,
0593                                                                            uint32_t lumi) const;
0594       // TODO: rename to reflect the fact that it requires full path
0595       // return ME identified by full path `path`, or nullptr
0596       virtual MonitorElement* get(std::string const& fullpath) const;
0597 
0598       // This is the most specific way to get a ME, specifying also run and
0599       // lumi in the key. Primarily for internal use.
0600       virtual MonitorElement* get(MonitorElementData::Key const& key) const;
0601 
0602       // same as get, throws an exception if histogram not found
0603       // Deprecated simply because it is barely used.
0604       DQM_DEPRECATED
0605       virtual MonitorElement* getElement(std::string const& path) const;
0606 
0607       // return sub-directories of current directory
0608       // Deprecated because the current implementation is very slow and barely
0609       // used, use getAllContents instead.
0610       DQM_DEPRECATED
0611       virtual std::vector<std::string> getSubdirs() const;
0612       // return element names of direct children of current directory
0613       virtual std::vector<std::string> getMEs() const;
0614       // returns whether there are objects at full path `path`
0615       virtual bool dirExists(std::string const& path) const;
0616 
0617       ~IGetter() override;
0618 
0619     protected:
0620       IGetter(DQMStore* store);
0621 
0622       DQMStore* store_;
0623     };
0624 
0625     class DQMStore : public IGetter, public IBooker {
0626     public:
0627       // IGetter uses the globalMEs_ directly.
0628       friend IGetter;
0629       enum OpenRunDirs { KeepRunDirs, StripRunDirs };
0630 
0631       DQMStore(edm::ParameterSet const& pset, edm::ActivityRegistry&);
0632       DQMStore(DQMStore const&) = delete;
0633       DQMStore(DQMStore&&) = delete;
0634       DQMStore& operator=(DQMStore const&) = delete;
0635       ~DQMStore() override;
0636 
0637       // ------------------------------------------------------------------------
0638       // ---------------------- public I/O --------------------------------------
0639       DQM_DEPRECATED
0640       void save(std::string const& filename, std::string const& path = "");
0641       DQM_DEPRECATED
0642       bool open(std::string const& filename,
0643                 bool overwrite = false,
0644                 std::string const& path = "",
0645                 std::string const& prepend = "",
0646                 OpenRunDirs stripdirs = KeepRunDirs,
0647                 bool fileMustExist = true);
0648 
0649       // ------------------------------------------------------------------------
0650       // ------------ IBooker/IGetter overrides to prevent ambiguity ------------
0651       void cd() override { this->IBooker::cd(); }
0652       void cd(std::string const& dir) override { this->IBooker::cd(dir); }
0653       void goUp() override { this->IBooker::goUp(); }
0654       std::string pwd() override { return this->IBooker::pwd(); }
0655 
0656       void setCurrentFolder(std::string const& fullpath) override {
0657         // only here we keep the two in sync -- all the others call this in the end!
0658         this->IBooker::setCurrentFolder(fullpath);
0659         this->IGetter::setCurrentFolder(fullpath);
0660       }
0661 
0662     public:
0663       // internal -- figure out better protection.
0664       template <typename iFunc>
0665       void bookTransaction(iFunc f, uint64_t moduleId, bool canSaveByLumi) {
0666         // taking the lock here only to protect the single, global IBooker (as
0667         // base class of DQMStore). We could avoid taking this lock by making a
0668         // new IBooker instance for each transaction, and the DQMStore itself
0669         // takes the lock before touching any data structures.
0670         // There is a race in bookME when we don't take this lock, where two
0671         // modules might prepare a global ME for the same name at the same time
0672         // and only one of them succeeds in putME: this is is safe, but we need
0673         // to remove the assertion over there and subsystem code has to be
0674         // aware that the booking callback *can* run multiple times.
0675         // Additionally, this lock is what keeps usage of getTH1() safe during
0676         // booking... all code needs to be migrated to callbacks before this can
0677         // be removed.
0678         auto lock = std::scoped_lock(this->booking_mutex_);
0679 
0680         // This is to make sure everything gets reset in case of an exception.
0681         // That is not really required (an exception here will crash the job
0682         // anyways, and it is technically not required to reset everything), but
0683         // it prevents misleading error messages in other threads.
0684         struct ModuleIdScope {
0685           IBooker& booker_;
0686           uint64_t oldid_;
0687           MonitorElementData::Scope oldscope_;
0688           edm::LuminosityBlockID oldrunlumi_;
0689           ModuleIdScope(IBooker& booker,
0690                         uint64_t newid,
0691                         MonitorElementData::Scope newscope,
0692                         edm::LuminosityBlockID newrunlumi)
0693               : booker_(booker) {
0694             oldid_ = booker_.setModuleID(newid);
0695             oldscope_ = booker_.setScope(newscope);
0696             oldrunlumi_ = booker_.setRunLumi(newrunlumi);
0697             assert(newid != kInvalidModuleID || !"moduleID must be set for normal booking transaction");
0698             assert(oldid_ == kInvalidModuleID || !"Nested booking transaction?");
0699           }
0700           ~ModuleIdScope() {
0701             booker_.setModuleID(oldid_);
0702             booker_.setScope(oldscope_);
0703             booker_.setRunLumi(oldrunlumi_);
0704           }
0705         };
0706 
0707         ModuleIdScope booker(
0708             *this,
0709             moduleId,
0710             // enable per-lumi-by-default here
0711             canSaveByLumi && this->doSaveByLumi_ ? MonitorElementData::Scope::LUMI : MonitorElementData::Scope::RUN,
0712             // always book prototypes
0713             edm::LuminosityBlockID());
0714 
0715         f(booker.booker_);
0716       };
0717 
0718       template <typename iFunc>
0719       void meBookerGetter(iFunc f) {
0720         auto lock = std::scoped_lock(this->booking_mutex_);
0721         // here, we make much less assumptions compared to bookTransaction.
0722         // This is essentially legacy semantics except we actually take the lock.
0723         f(*this, *this);
0724         // TODO: we should maybe make sure that Scope changes are reset here,
0725         // but also it makes sense to inherit the Scope from the environement
0726         // (e.g. when meBookerGetter is called *inside* a booking transaction).
0727       };
0728 
0729       // For input modules: trigger recycling without local ME/enterLumi/moduleID.
0730       MonitorElement* findOrRecycle(MonitorElementData::Key const&);
0731 
0732       // this creates local all needed global MEs for the given run/lumi (and
0733       // module), potentially cloning them if there are concurrent runs/lumis.
0734       // Symmetrical to cleanupLumi, this is called from a framwork hook, to
0735       // make sure it also runs when the module does not call anything.
0736       void initLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi);
0737       void initLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0738 
0739       // modules are expected to call these callbacks when they change run/lumi.
0740       // The DQMStore then updates the module's MEs local MEs to point to the
0741       // new run/lumi.
0742       void enterLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0743       void leaveLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0744 
0745       // this is triggered by a framework hook to remove/recycle MEs after a
0746       // run/lumi is saved. We do this via the edm::Service interface to make
0747       // sure it runs after *all* output modules, even if there are multiple.
0748       void cleanupLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi);
0749 
0750       // Add ME to DQMStore datastructures. The object will be deleted if a
0751       // similar object is already present.
0752       // For global ME
0753       MonitorElement* putME(MonitorElement* me);
0754       // For local ME
0755       MonitorElement* putME(MonitorElement* me, uint64_t moduleID);
0756       // Find a global ME of matching name, in any state.
0757       // MELIKE can be a MonitorElementData::Path or MonitorElement*.
0758       template <typename MELIKE>
0759       MonitorElement* findME(MELIKE const& path);
0760       // Log a backtrace on booking.
0761       void printTrace(std::string const& message);
0762       // print a log message if ME matches trackME_.
0763       void debugTrackME(const char* message, MonitorElement* me_local, MonitorElement* me_global) const;
0764       // accesor to keep MEsToSave_ private
0765       const auto& getMEsToSave() const { return MEsToSave_; }
0766       // accesor to keep onlineMode_ private
0767       const bool& getMode() const { return onlineMode_; }
0768 
0769     private:
0770       // MEComparison is a name-only comparison on MEs and Paths, allowing
0771       // heterogeneous lookup.
0772       // The ME objects here are lightweight, all the important stuff is in the
0773       // MEData. However we never handle MEData directly, but always keep it
0774       // wrapped in MEs (created as needed). MEs can share MEData.
0775       // ME objects must never appear more than once in these sets. ME objects
0776       // in localMEs_ cannot be deleted, since the module might hold pointers.
0777       // MEs in globalMEs_ can be deleted/recycled at the end of their scope,
0778       // if there are no local MEs left that share the data.
0779       // MEs can be _protoype MEs_ if their scope is not yet known (after
0780       // booking, after leaveLumi). A prototype is kept if and only if there is
0781       // no other global instance of the same ME. Prototype MEs have
0782       // run = lumi = 0 and scope != JOB. If scope == JOB, a prototype is never
0783       // required. Prototype MEs are reset *before* inserting, so fill calls
0784       // can go into prototype MEs and not be lost.
0785       // Key is (run, lumi), potentially one or both 0 for SCOPE::RUN or SCOPE::JOB
0786       // NEVER modify the key_ of a ME in these datastructures. Since we use
0787       // pointers, this may be possible (not everything is const), but it could
0788       // still corrupt the datastructure.
0789       std::map<edm::LuminosityBlockID, std::set<MonitorElement*, MonitorElement::MEComparison>> globalMEs_;
0790       // Key is (moduleID [, run | , stream]), run is only needed for
0791       // edm::global, stream only for edm::stream.
0792       // Legacy MEs have moduleID 0.
0793       std::map<uint64_t, std::set<MonitorElement*, MonitorElement::MEComparison>> localMEs_;
0794       // Whenever modifying these sets, take this  mutex. It's recursive, so we
0795       // can be liberal -- lock on any access, but also lock on the full booking
0796       // transaction.
0797       std::recursive_mutex booking_mutex_;
0798 
0799       // Universal verbose flag.
0800       // Only very few usages remain, the main debugging tool is trackME_.
0801       int verbose_;
0802 
0803       // If set to true, error out whenever things happen that are not safe for
0804       // legacy modules.
0805       bool assertLegacySafe_;
0806 
0807       // Book MEs by lumi by default whenever possible.
0808       bool doSaveByLumi_;
0809       // Book MEs by lumi from list in DQMServices/Core/python/DQMStore_cfi.py
0810       std::vector<std::string> MEsToSave_;  //just if perLS is ON
0811 
0812       // if non-empty, debugTrackME calls will log some information whenever a
0813       // ME path contains this string.
0814       std::string trackME_;
0815 
0816       // Online mode
0817       bool onlineMode_;
0818     };
0819   }  // namespace implementation
0820 
0821   // Since we still use a single, edm::Serivce instance of a DQMStore, these are all the same.
0822   namespace legacy {
0823     class DQMStore : public dqm::implementation::DQMStore {
0824     public:
0825       using IBooker = dqm::implementation::IBooker;
0826       using IGetter = dqm::implementation::IGetter;
0827       // import constructors.
0828       using dqm::implementation::DQMStore::DQMStore;
0829     };
0830   }  // namespace legacy
0831   namespace reco {
0832     using DQMStore = dqm::legacy::DQMStore;
0833   }  // namespace reco
0834   namespace harvesting {
0835     using DQMStore = dqm::legacy::DQMStore;
0836   }  // namespace harvesting
0837 }  // namespace dqm
0838 
0839 #endif