Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-05-01 22:51:55

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