Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-10 23:53:31

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* book2DPoly(TString const& name,
0264                                  TString const& title,
0265                                  double lowX,
0266                                  double highX,
0267                                  double lowY,
0268                                  double highY,
0269                                  FUNC onbooking = NOOP()) {
0270         return bookME(name, MonitorElementData::Kind::TH2Poly, [=]() {
0271           auto th2poly = new TH2Poly(name, title, lowX, highX, lowY, highY);
0272           onbooking(th2poly);
0273           return th2poly;
0274         });
0275       }
0276       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0277       MonitorElement* book2DPoly(TString const& name, TH2Poly* object, FUNC onbooking = NOOP()) {
0278         return bookME(
0279             name,
0280             MonitorElementData::Kind::TH2Poly,
0281             [=]() {
0282               auto th2 = static_cast<TH2Poly*>(object->Clone(name));
0283               onbooking(th2);
0284               return th2;
0285             },
0286             /* forceReplace */ true);
0287       }
0288       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0289       MonitorElement* book2S(TString const& name,
0290                              TString const& title,
0291                              int nchX,
0292                              double lowX,
0293                              double highX,
0294                              int nchY,
0295                              double lowY,
0296                              double highY,
0297                              FUNC onbooking = NOOP()) {
0298         return bookME(name, MonitorElementData::Kind::TH2S, [=]() {
0299           auto th2 = new TH2S(name, title, nchX, lowX, highX, nchY, lowY, highY);
0300           onbooking(th2);
0301           return th2;
0302         });
0303       }
0304       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0305       MonitorElement* book2S(TString const& name,
0306                              TString const& title,
0307                              int nchX,
0308                              float const* xbinsize,
0309                              int nchY,
0310                              float const* ybinsize,
0311                              FUNC onbooking = NOOP()) {
0312         return bookME(name, MonitorElementData::Kind::TH2S, [=]() {
0313           auto th2 = new TH2S(name, title, nchX, xbinsize, nchY, ybinsize);
0314           onbooking(th2);
0315           return th2;
0316         });
0317       }
0318       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0319       MonitorElement* book2S(TString const& name, TH2S* object, FUNC onbooking = NOOP()) {
0320         return bookME(
0321             name,
0322             MonitorElementData::Kind::TH2S,
0323             [=]() {
0324               auto th2 = static_cast<TH2S*>(object->Clone(name));
0325               onbooking(th2);
0326               return th2;
0327             },
0328             /* forceReplace */ true);
0329       }
0330       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0331       MonitorElement* book2I(TString const& name,
0332                              TString const& title,
0333                              int nchX,
0334                              double lowX,
0335                              double highX,
0336                              int nchY,
0337                              double lowY,
0338                              double highY,
0339                              FUNC onbooking = NOOP()) {
0340         return bookME(name, MonitorElementData::Kind::TH2I, [=]() {
0341           auto th2 = new TH2I(name, title, nchX, lowX, highX, nchY, lowY, highY);
0342           onbooking(th2);
0343           return th2;
0344         });
0345       }
0346       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0347       MonitorElement* book2I(TString const& name,
0348                              TString const& title,
0349                              int nchX,
0350                              float const* xbinsize,
0351                              int nchY,
0352                              float const* ybinsize,
0353                              FUNC onbooking = NOOP()) {
0354         return bookME(name, MonitorElementData::Kind::TH2I, [=]() {
0355           auto th2 = new TH2I(name, title, nchX, xbinsize, nchY, ybinsize);
0356           onbooking(th2);
0357           return th2;
0358         });
0359       }
0360       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0361       MonitorElement* book2I(TString const& name, TH2I* object, FUNC onbooking = NOOP()) {
0362         return bookME(
0363             name,
0364             MonitorElementData::Kind::TH2I,
0365             [=]() {
0366               auto th2 = static_cast<TH2I*>(object->Clone(name));
0367               onbooking(th2);
0368               return th2;
0369             },
0370             /* forceReplace */ true);
0371       }
0372       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0373       MonitorElement* book2DD(TString const& name,
0374                               TString const& title,
0375                               int nchX,
0376                               double lowX,
0377                               double highX,
0378                               int nchY,
0379                               double lowY,
0380                               double highY,
0381                               FUNC onbooking = NOOP()) {
0382         return bookME(name, MonitorElementData::Kind::TH2D, [=]() {
0383           auto th2 = new TH2D(name, title, nchX, lowX, highX, nchY, lowY, highY);
0384           onbooking(th2);
0385           return th2;
0386         });
0387       }
0388       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0389       MonitorElement* book2DD(TString const& name, TH2D* object, FUNC onbooking = NOOP()) {
0390         return bookME(
0391             name,
0392             MonitorElementData::Kind::TH2D,
0393             [=]() {
0394               auto th2 = static_cast<TH2D*>(object->Clone(name));
0395               onbooking(th2);
0396               return th2;
0397             },
0398             /* forceReplace */ true);
0399       }
0400 
0401       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0402       MonitorElement* book3D(TString const& name,
0403                              TString const& title,
0404                              int nchX,
0405                              double lowX,
0406                              double highX,
0407                              int nchY,
0408                              double lowY,
0409                              double highY,
0410                              int nchZ,
0411                              double lowZ,
0412                              double highZ,
0413                              FUNC onbooking = NOOP()) {
0414         return bookME(name, MonitorElementData::Kind::TH3F, [=]() {
0415           auto th3 = new TH3F(name, title, nchX, lowX, highX, nchY, lowY, highY, nchZ, lowZ, highZ);
0416           onbooking(th3);
0417           return th3;
0418         });
0419       }
0420       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0421       MonitorElement* book3D(TString const& name, TH3F* object, FUNC onbooking = NOOP()) {
0422         return bookME(
0423             name,
0424             MonitorElementData::Kind::TH3F,
0425             [=]() {
0426               auto th3 = static_cast<TH3F*>(object->Clone(name));
0427               onbooking(th3);
0428               return th3;
0429             },
0430             /* forceReplace */ true);
0431       }
0432 
0433       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0434       MonitorElement* bookProfile(TString const& name,
0435                                   TString const& title,
0436                                   int nchX,
0437                                   double lowX,
0438                                   double highX,
0439                                   int /* nchY */,
0440                                   double lowY,
0441                                   double highY,
0442                                   char const* option = "s",
0443                                   FUNC onbooking = NOOP()) {
0444         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0445           auto tprofile = new TProfile(name, title, nchX, lowX, highX, lowY, highY, option);
0446           onbooking(tprofile);
0447           return tprofile;
0448         });
0449       }
0450       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0451       MonitorElement* bookProfile(TString const& name,
0452                                   TString const& title,
0453                                   int nchX,
0454                                   double lowX,
0455                                   double highX,
0456                                   double lowY,
0457                                   double highY,
0458                                   char const* option = "s",
0459                                   FUNC onbooking = NOOP()) {
0460         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0461           auto tprofile = new TProfile(name, title, nchX, lowX, highX, lowY, highY, option);
0462           onbooking(tprofile);
0463           return tprofile;
0464         });
0465       }
0466       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0467       MonitorElement* bookProfile(TString const& name,
0468                                   TString const& title,
0469                                   int nchX,
0470                                   double const* xbinsize,
0471                                   int /* nchY */,
0472                                   double lowY,
0473                                   double highY,
0474                                   char const* option = "s",
0475                                   FUNC onbooking = NOOP()) {
0476         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0477           auto tprofile = new TProfile(name, title, nchX, xbinsize, lowY, highY, option);
0478           onbooking(tprofile);
0479           return tprofile;
0480         });
0481       }
0482       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0483       MonitorElement* bookProfile(TString const& name,
0484                                   TString const& title,
0485                                   int nchX,
0486                                   double const* xbinsize,
0487                                   double lowY,
0488                                   double highY,
0489                                   char const* option = "s",
0490                                   FUNC onbooking = NOOP()) {
0491         return bookME(name, MonitorElementData::Kind::TPROFILE, [=]() {
0492           auto tprofile = new TProfile(name, title, nchX, xbinsize, lowY, highY, option);
0493           onbooking(tprofile);
0494           return tprofile;
0495         });
0496       }
0497       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0498       MonitorElement* bookProfile(TString const& name, TProfile* object, FUNC onbooking = NOOP()) {
0499         return bookME(
0500             name,
0501             MonitorElementData::Kind::TPROFILE,
0502             [=]() {
0503               auto tprofile = static_cast<TProfile*>(object->Clone(name));
0504               onbooking(tprofile);
0505               return tprofile;
0506             },
0507             /* forceReplace */ true);
0508       }
0509 
0510       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0511       MonitorElement* bookProfile2D(TString const& name,
0512                                     TString const& title,
0513                                     int nchX,
0514                                     double lowX,
0515                                     double highX,
0516                                     int nchY,
0517                                     double lowY,
0518                                     double highY,
0519                                     double lowZ,
0520                                     double highZ,
0521                                     char const* option = "s",
0522                                     FUNC onbooking = NOOP()) {
0523         return bookME(name, MonitorElementData::Kind::TPROFILE2D, [=]() {
0524           auto tprofile = new TProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option);
0525           onbooking(tprofile);
0526           return tprofile;
0527         });
0528       }
0529       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0530       MonitorElement* bookProfile2D(TString const& name,
0531                                     TString const& title,
0532                                     int nchX,
0533                                     double lowX,
0534                                     double highX,
0535                                     int nchY,
0536                                     double lowY,
0537                                     double highY,
0538                                     int /* nchZ */,
0539                                     double lowZ,
0540                                     double highZ,
0541                                     char const* option = "s",
0542                                     FUNC onbooking = NOOP()) {
0543         return bookME(name, MonitorElementData::Kind::TPROFILE2D, [=]() {
0544           auto tprofile = new TProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option);
0545           onbooking(tprofile);
0546           return tprofile;
0547         });
0548       }
0549       template <typename FUNC = NOOP, std::enable_if_t<not std::is_arithmetic<FUNC>::value, int> = 0>
0550       MonitorElement* bookProfile2D(TString const& name, TProfile2D* object, FUNC onbooking = NOOP()) {
0551         return bookME(
0552             name,
0553             MonitorElementData::Kind::TPROFILE2D,
0554             [=]() {
0555               auto tprofile = static_cast<TProfile2D*>(object->Clone(name));
0556               onbooking(tprofile);
0557               return tprofile;
0558             },
0559             /* forceReplace */ true);
0560       }
0561 
0562       //
0563       // all non-template interfaces are virtual.
0564       //
0565 
0566       virtual MonitorElementData::Scope setScope(MonitorElementData::Scope newscope);
0567       // RAII-Style guard to set and reset the Scope.
0568       template <MonitorElementData::Scope SCOPE>
0569       struct UseScope {
0570         IBooker& parent;
0571         MonitorElementData::Scope oldscope;
0572         UseScope(IBooker& booker) : parent(booker) { oldscope = parent.setScope(SCOPE); }
0573         ~UseScope() { parent.setScope(oldscope); }
0574       };
0575       using UseLumiScope = UseScope<MonitorElementData::Scope::LUMI>;
0576       using UseRunScope = UseScope<MonitorElementData::Scope::RUN>;
0577       using UseJobScope = UseScope<MonitorElementData::Scope::JOB>;
0578 
0579       ~IBooker() override;
0580 
0581     private:
0582       IBooker(DQMStore* store);
0583       virtual uint64_t setModuleID(uint64_t moduleID);
0584       virtual edm::LuminosityBlockID setRunLumi(edm::LuminosityBlockID runlumi);
0585       virtual MonitorElement* bookME(TString const& name,
0586                                      MonitorElementData::Kind kind,
0587                                      std::function<TH1*()> makeobject,
0588                                      bool forceReplace = false);
0589 
0590       DQMStore* store_ = nullptr;
0591       MonitorElementData::Scope scope_ = MonitorElementData::Scope::JOB;
0592       static constexpr uint64_t kInvalidModuleID = std::numeric_limits<uint64_t>::max();
0593       uint64_t moduleID_ = kInvalidModuleID;
0594       edm::LuminosityBlockID runlumi_ = edm::LuminosityBlockID();
0595     };
0596 
0597     class IGetter : public dqm::implementation::NavigatorBase {
0598     public:
0599       // The IGetter interface is not really suitable for concurrent lumis/runs,
0600       // so we don't even try much to get it right. Harvesting needs to run
0601       // sequentially for now. Therefore, the methods just return the next-best
0602       // global MEs that they find, ignoring Scope and run/lumi.
0603       // Since these are global MEs, they may be deleted at some point; don't
0604       // store the pointers!
0605       // They are also shared with other modules. That is save when running
0606       // multi-threaded as long as getTH1() etc. are not used, but of course
0607       // all dependencies need to be properly declared to get correct results.
0608 
0609       // TODO: review and possibly rename the all methods below:
0610       // get MEs that are direct children of full path `path`
0611       virtual std::vector<dqm::harvesting::MonitorElement*> getContents(std::string const& path) const;
0612 
0613       // get all elements below full path `path`
0614       // we have to discuss semantics here -- are run/lumi ever used?
0615       virtual std::vector<dqm::harvesting::MonitorElement*> getAllContents(std::string const& path) const;
0616       DQM_DEPRECATED
0617       virtual std::vector<dqm::harvesting::MonitorElement*> getAllContents(std::string const& path,
0618                                                                            uint32_t runNumber,
0619                                                                            uint32_t lumi) const;
0620       // TODO: rename to reflect the fact that it requires full path
0621       // return ME identified by full path `path`, or nullptr
0622       virtual MonitorElement* get(std::string const& fullpath) const;
0623 
0624       // This is the most specific way to get a ME, specifying also run and
0625       // lumi in the key. Primarily for internal use.
0626       virtual MonitorElement* get(MonitorElementData::Key const& key) const;
0627 
0628       // same as get, throws an exception if histogram not found
0629       // Deprecated simply because it is barely used.
0630       DQM_DEPRECATED
0631       virtual MonitorElement* getElement(std::string const& path) const;
0632 
0633       // return sub-directories of current directory
0634       // Deprecated because the current implementation is very slow and barely
0635       // used, use getAllContents instead.
0636       DQM_DEPRECATED
0637       virtual std::vector<std::string> getSubdirs() const;
0638       // return element names of direct children of current directory
0639       virtual std::vector<std::string> getMEs() const;
0640       // returns whether there are objects at full path `path`
0641       virtual bool dirExists(std::string const& path) const;
0642 
0643       ~IGetter() override;
0644 
0645     protected:
0646       IGetter(DQMStore* store);
0647 
0648       DQMStore* store_;
0649     };
0650 
0651     class DQMStore : public IGetter, public IBooker {
0652     public:
0653       // IGetter uses the globalMEs_ directly.
0654       friend IGetter;
0655       enum OpenRunDirs { KeepRunDirs, StripRunDirs };
0656 
0657       DQMStore(edm::ParameterSet const& pset, edm::ActivityRegistry&);
0658       DQMStore(DQMStore const&) = delete;
0659       DQMStore(DQMStore&&) = delete;
0660       DQMStore& operator=(DQMStore const&) = delete;
0661       ~DQMStore() override;
0662 
0663       // ------------------------------------------------------------------------
0664       // ---------------------- public I/O --------------------------------------
0665       DQM_DEPRECATED
0666       void save(std::string const& filename, std::string const& path = "");
0667       DQM_DEPRECATED
0668       bool open(std::string const& filename,
0669                 bool overwrite = false,
0670                 std::string const& path = "",
0671                 std::string const& prepend = "",
0672                 OpenRunDirs stripdirs = KeepRunDirs,
0673                 bool fileMustExist = true);
0674 
0675       // ------------------------------------------------------------------------
0676       // ------------ IBooker/IGetter overrides to prevent ambiguity ------------
0677       void cd() override { this->IBooker::cd(); }
0678       void cd(std::string const& dir) override { this->IBooker::cd(dir); }
0679       void goUp() override { this->IBooker::goUp(); }
0680       std::string pwd() override { return this->IBooker::pwd(); }
0681 
0682       void setCurrentFolder(std::string const& fullpath) override {
0683         // only here we keep the two in sync -- all the others call this in the end!
0684         this->IBooker::setCurrentFolder(fullpath);
0685         this->IGetter::setCurrentFolder(fullpath);
0686       }
0687 
0688     public:
0689       // internal -- figure out better protection.
0690       template <typename iFunc>
0691       void bookTransaction(iFunc f, uint64_t moduleId, bool canSaveByLumi) {
0692         // taking the lock here only to protect the single, global IBooker (as
0693         // base class of DQMStore). We could avoid taking this lock by making a
0694         // new IBooker instance for each transaction, and the DQMStore itself
0695         // takes the lock before touching any data structures.
0696         // There is a race in bookME when we don't take this lock, where two
0697         // modules might prepare a global ME for the same name at the same time
0698         // and only one of them succeeds in putME: this is is safe, but we need
0699         // to remove the assertion over there and subsystem code has to be
0700         // aware that the booking callback *can* run multiple times.
0701         // Additionally, this lock is what keeps usage of getTH1() safe during
0702         // booking... all code needs to be migrated to callbacks before this can
0703         // be removed.
0704         auto lock = std::scoped_lock(this->booking_mutex_);
0705 
0706         // This is to make sure everything gets reset in case of an exception.
0707         // That is not really required (an exception here will crash the job
0708         // anyways, and it is technically not required to reset everything), but
0709         // it prevents misleading error messages in other threads.
0710         struct ModuleIdScope {
0711           IBooker& booker_;
0712           uint64_t oldid_;
0713           MonitorElementData::Scope oldscope_;
0714           edm::LuminosityBlockID oldrunlumi_;
0715           ModuleIdScope(IBooker& booker,
0716                         uint64_t newid,
0717                         MonitorElementData::Scope newscope,
0718                         edm::LuminosityBlockID newrunlumi)
0719               : booker_(booker) {
0720             oldid_ = booker_.setModuleID(newid);
0721             oldscope_ = booker_.setScope(newscope);
0722             oldrunlumi_ = booker_.setRunLumi(newrunlumi);
0723             assert(newid != kInvalidModuleID || !"moduleID must be set for normal booking transaction");
0724             assert(oldid_ == kInvalidModuleID || !"Nested booking transaction?");
0725           }
0726           ~ModuleIdScope() {
0727             booker_.setModuleID(oldid_);
0728             booker_.setScope(oldscope_);
0729             booker_.setRunLumi(oldrunlumi_);
0730           }
0731         };
0732 
0733         ModuleIdScope booker(
0734             *this,
0735             moduleId,
0736             // enable per-lumi-by-default here
0737             canSaveByLumi && this->doSaveByLumi_ ? MonitorElementData::Scope::LUMI : MonitorElementData::Scope::RUN,
0738             // always book prototypes
0739             edm::LuminosityBlockID());
0740 
0741         f(booker.booker_);
0742       };
0743 
0744       template <typename iFunc>
0745       void meBookerGetter(iFunc f) {
0746         auto lock = std::scoped_lock(this->booking_mutex_);
0747         // here, we make much less assumptions compared to bookTransaction.
0748         // This is essentially legacy semantics except we actually take the lock.
0749         f(*this, *this);
0750         // TODO: we should maybe make sure that Scope changes are reset here,
0751         // but also it makes sense to inherit the Scope from the environement
0752         // (e.g. when meBookerGetter is called *inside* a booking transaction).
0753       };
0754 
0755       // For input modules: trigger recycling without local ME/enterLumi/moduleID.
0756       MonitorElement* findOrRecycle(MonitorElementData::Key const&);
0757 
0758       // this creates local all needed global MEs for the given run/lumi (and
0759       // module), potentially cloning them if there are concurrent runs/lumis.
0760       // Symmetrical to cleanupLumi, this is called from a framwork hook, to
0761       // make sure it also runs when the module does not call anything.
0762       void initLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi);
0763       void initLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0764 
0765       // modules are expected to call these callbacks when they change run/lumi.
0766       // The DQMStore then updates the module's MEs local MEs to point to the
0767       // new run/lumi.
0768       void enterLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0769       void leaveLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0770 
0771       // this is triggered by a framework hook to remove/recycle MEs after a
0772       // run/lumi is saved. We do this via the edm::Service interface to make
0773       // sure it runs after *all* output modules, even if there are multiple.
0774       void cleanupLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi);
0775 
0776       // Add ME to DQMStore datastructures. The object will be deleted if a
0777       // similar object is already present.
0778       // For global ME
0779       MonitorElement* putME(MonitorElement* me);
0780       // For local ME
0781       MonitorElement* putME(MonitorElement* me, uint64_t moduleID);
0782       // Find a global ME of matching name, in any state.
0783       // MELIKE can be a MonitorElementData::Path or MonitorElement*.
0784       template <typename MELIKE>
0785       MonitorElement* findME(MELIKE const& path);
0786       // Log a backtrace on booking.
0787       void printTrace(std::string const& message);
0788       // print a log message if ME matches trackME_.
0789       void debugTrackME(const char* message, MonitorElement* me_local, MonitorElement* me_global) const;
0790       // accesor to keep MEsToSave_ private
0791       const auto& getMEsToSave() const { return MEsToSave_; }
0792       // accesor to keep onlineMode_ private
0793       const bool& getMode() const { return onlineMode_; }
0794 
0795     private:
0796       // MEComparison is a name-only comparison on MEs and Paths, allowing
0797       // heterogeneous lookup.
0798       // The ME objects here are lightweight, all the important stuff is in the
0799       // MEData. However we never handle MEData directly, but always keep it
0800       // wrapped in MEs (created as needed). MEs can share MEData.
0801       // ME objects must never appear more than once in these sets. ME objects
0802       // in localMEs_ cannot be deleted, since the module might hold pointers.
0803       // MEs in globalMEs_ can be deleted/recycled at the end of their scope,
0804       // if there are no local MEs left that share the data.
0805       // MEs can be _protoype MEs_ if their scope is not yet known (after
0806       // booking, after leaveLumi). A prototype is kept if and only if there is
0807       // no other global instance of the same ME. Prototype MEs have
0808       // run = lumi = 0 and scope != JOB. If scope == JOB, a prototype is never
0809       // required. Prototype MEs are reset *before* inserting, so fill calls
0810       // can go into prototype MEs and not be lost.
0811       // Key is (run, lumi), potentially one or both 0 for SCOPE::RUN or SCOPE::JOB
0812       // NEVER modify the key_ of a ME in these datastructures. Since we use
0813       // pointers, this may be possible (not everything is const), but it could
0814       // still corrupt the datastructure.
0815       std::map<edm::LuminosityBlockID, std::set<MonitorElement*, MonitorElement::MEComparison>> globalMEs_;
0816       // Key is (moduleID [, run | , stream]), run is only needed for
0817       // edm::global, stream only for edm::stream.
0818       // Legacy MEs have moduleID 0.
0819       std::map<uint64_t, std::set<MonitorElement*, MonitorElement::MEComparison>> localMEs_;
0820       // Whenever modifying these sets, take this  mutex. It's recursive, so we
0821       // can be liberal -- lock on any access, but also lock on the full booking
0822       // transaction.
0823       std::recursive_mutex booking_mutex_;
0824 
0825       // Universal verbose flag.
0826       // Only very few usages remain, the main debugging tool is trackME_.
0827       int verbose_;
0828 
0829       // If set to true, error out whenever things happen that are not safe for
0830       // legacy modules.
0831       bool assertLegacySafe_;
0832 
0833       // Book MEs by lumi by default whenever possible.
0834       bool doSaveByLumi_;
0835       // Book MEs by lumi from list in DQMServices/Core/python/DQMStore_cfi.py
0836       std::vector<std::string> MEsToSave_;  //just if perLS is ON
0837 
0838       // if non-empty, debugTrackME calls will log some information whenever a
0839       // ME path contains this string.
0840       std::string trackME_;
0841 
0842       // Online mode
0843       bool onlineMode_;
0844     };
0845   }  // namespace implementation
0846 
0847   // Since we still use a single, edm::Serivce instance of a DQMStore, these are all the same.
0848   namespace legacy {
0849     class DQMStore : public dqm::implementation::DQMStore {
0850     public:
0851       using IBooker = dqm::implementation::IBooker;
0852       using IGetter = dqm::implementation::IGetter;
0853       // import constructors.
0854       using dqm::implementation::DQMStore::DQMStore;
0855     };
0856   }  // namespace legacy
0857   namespace reco {
0858     using DQMStore = dqm::legacy::DQMStore;
0859   }  // namespace reco
0860   namespace harvesting {
0861     using DQMStore = dqm::legacy::DQMStore;
0862   }  // namespace harvesting
0863 }  // namespace dqm
0864 
0865 #endif