Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:09

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       static constexpr uint64_t kInvalidModuleID = std::numeric_limits<uint64_t>::max();
0558       uint64_t moduleID_ = kInvalidModuleID;
0559       edm::LuminosityBlockID runlumi_ = edm::LuminosityBlockID();
0560     };
0561 
0562     class IGetter : public dqm::implementation::NavigatorBase {
0563     public:
0564       // The IGetter interface is not really suitable for concurrent lumis/runs,
0565       // so we don't even try much to get it right. Harvesting needs to run
0566       // sequentially for now. Therefore, the methods just return the next-best
0567       // global MEs that they find, ignoring Scope and run/lumi.
0568       // Since these are global MEs, they may be deleted at some point; don't
0569       // store the pointers!
0570       // They are also shared with other modules. That is save when running
0571       // multi-threaded as long as getTH1() etc. are not used, but of course
0572       // all dependencies need to be properly declared to get correct results.
0573 
0574       // TODO: review and possibly rename the all methods below:
0575       // get MEs that are direct children of full path `path`
0576       virtual std::vector<dqm::harvesting::MonitorElement*> getContents(std::string const& path) const;
0577 
0578       // get all elements below full path `path`
0579       // we have to discuss semantics here -- are run/lumi ever used?
0580       virtual std::vector<dqm::harvesting::MonitorElement*> getAllContents(std::string const& path) const;
0581       DQM_DEPRECATED
0582       virtual std::vector<dqm::harvesting::MonitorElement*> getAllContents(std::string const& path,
0583                                                                            uint32_t runNumber,
0584                                                                            uint32_t lumi) const;
0585       // TODO: rename to reflect the fact that it requires full path
0586       // return ME identified by full path `path`, or nullptr
0587       virtual MonitorElement* get(std::string const& fullpath) const;
0588 
0589       // This is the most specific way to get a ME, specifying also run and
0590       // lumi in the key. Primarily for internal use.
0591       virtual MonitorElement* get(MonitorElementData::Key const& key) const;
0592 
0593       // same as get, throws an exception if histogram not found
0594       // Deprecated simply because it is barely used.
0595       DQM_DEPRECATED
0596       virtual MonitorElement* getElement(std::string const& path) const;
0597 
0598       // return sub-directories of current directory
0599       // Deprecated because the current implementation is very slow and barely
0600       // used, use getAllContents instead.
0601       DQM_DEPRECATED
0602       virtual std::vector<std::string> getSubdirs() const;
0603       // return element names of direct children of current directory
0604       virtual std::vector<std::string> getMEs() const;
0605       // returns whether there are objects at full path `path`
0606       virtual bool dirExists(std::string const& path) const;
0607 
0608       ~IGetter() override;
0609 
0610     protected:
0611       IGetter(DQMStore* store);
0612 
0613       DQMStore* store_;
0614     };
0615 
0616     class DQMStore : public IGetter, public IBooker {
0617     public:
0618       // IGetter uses the globalMEs_ directly.
0619       friend IGetter;
0620       enum OpenRunDirs { KeepRunDirs, StripRunDirs };
0621 
0622       DQMStore(edm::ParameterSet const& pset, edm::ActivityRegistry&);
0623       DQMStore(DQMStore const&) = delete;
0624       DQMStore(DQMStore&&) = delete;
0625       DQMStore& operator=(DQMStore const&) = delete;
0626       ~DQMStore() override;
0627 
0628       // ------------------------------------------------------------------------
0629       // ---------------------- public I/O --------------------------------------
0630       DQM_DEPRECATED
0631       void save(std::string const& filename, std::string const& path = "");
0632       DQM_DEPRECATED
0633       bool open(std::string const& filename,
0634                 bool overwrite = false,
0635                 std::string const& path = "",
0636                 std::string const& prepend = "",
0637                 OpenRunDirs stripdirs = KeepRunDirs,
0638                 bool fileMustExist = true);
0639 
0640       // ------------------------------------------------------------------------
0641       // ------------ IBooker/IGetter overrides to prevent ambiguity ------------
0642       void cd() override { this->IBooker::cd(); }
0643       void cd(std::string const& dir) override { this->IBooker::cd(dir); }
0644       void goUp() override { this->IBooker::goUp(); }
0645       std::string pwd() override { return this->IBooker::pwd(); }
0646 
0647       void setCurrentFolder(std::string const& fullpath) override {
0648         // only here we keep the two in sync -- all the others call this in the end!
0649         this->IBooker::setCurrentFolder(fullpath);
0650         this->IGetter::setCurrentFolder(fullpath);
0651       }
0652 
0653     public:
0654       // internal -- figure out better protection.
0655       template <typename iFunc>
0656       void bookTransaction(iFunc f, uint64_t moduleId, bool canSaveByLumi) {
0657         // taking the lock here only to protect the single, global IBooker (as
0658         // base class of DQMStore). We could avoid taking this lock by making a
0659         // new IBooker instance for each transaction, and the DQMStore itself
0660         // takes the lock before touching any data structures.
0661         // There is a race in bookME when we don't take this lock, where two
0662         // modules might prepare a global ME for the same name at the same time
0663         // and only one of them succeeds in putME: this is is safe, but we need
0664         // to remove the assertion over there and subsystem code has to be
0665         // aware that the booking callback *can* run multiple times.
0666         // Additionally, this lock is what keeps usage of getTH1() safe during
0667         // booking... all code needs to be migrated to callbacks before this can
0668         // be removed.
0669         auto lock = std::scoped_lock(this->booking_mutex_);
0670 
0671         // This is to make sure everything gets reset in case of an exception.
0672         // That is not really required (an exception here will crash the job
0673         // anyways, and it is technically not required to reset everything), but
0674         // it prevents misleading error messages in other threads.
0675         struct ModuleIdScope {
0676           IBooker& booker_;
0677           uint64_t oldid_;
0678           MonitorElementData::Scope oldscope_;
0679           edm::LuminosityBlockID oldrunlumi_;
0680           ModuleIdScope(IBooker& booker,
0681                         uint64_t newid,
0682                         MonitorElementData::Scope newscope,
0683                         edm::LuminosityBlockID newrunlumi)
0684               : booker_(booker) {
0685             oldid_ = booker_.setModuleID(newid);
0686             oldscope_ = booker_.setScope(newscope);
0687             oldrunlumi_ = booker_.setRunLumi(newrunlumi);
0688             assert(newid != kInvalidModuleID || !"moduleID must be set for normal booking transaction");
0689             assert(oldid_ == kInvalidModuleID || !"Nested booking transaction?");
0690           }
0691           ~ModuleIdScope() {
0692             booker_.setModuleID(oldid_);
0693             booker_.setScope(oldscope_);
0694             booker_.setRunLumi(oldrunlumi_);
0695           }
0696         };
0697 
0698         ModuleIdScope booker(
0699             *this,
0700             moduleId,
0701             // enable per-lumi-by-default here
0702             canSaveByLumi && this->doSaveByLumi_ ? MonitorElementData::Scope::LUMI : MonitorElementData::Scope::RUN,
0703             // always book prototypes
0704             edm::LuminosityBlockID());
0705 
0706         f(booker.booker_);
0707       };
0708 
0709       template <typename iFunc>
0710       void meBookerGetter(iFunc f) {
0711         auto lock = std::scoped_lock(this->booking_mutex_);
0712         // here, we make much less assumptions compared to bookTransaction.
0713         // This is essentially legacy semantics except we actually take the lock.
0714         f(*this, *this);
0715         // TODO: we should maybe make sure that Scope changes are reset here,
0716         // but also it makes sense to inherit the Scope from the environement
0717         // (e.g. when meBookerGetter is called *inside* a booking transaction).
0718       };
0719 
0720       // For input modules: trigger recycling without local ME/enterLumi/moduleID.
0721       MonitorElement* findOrRecycle(MonitorElementData::Key const&);
0722 
0723       // this creates local all needed global MEs for the given run/lumi (and
0724       // module), potentially cloning them if there are concurrent runs/lumis.
0725       // Symmetrical to cleanupLumi, this is called from a framwork hook, to
0726       // make sure it also runs when the module does not call anything.
0727       void initLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi);
0728       void initLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0729 
0730       // modules are expected to call these callbacks when they change run/lumi.
0731       // The DQMStore then updates the module's MEs local MEs to point to the
0732       // new run/lumi.
0733       void enterLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0734       void leaveLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, uint64_t moduleID);
0735 
0736       // this is triggered by a framework hook to remove/recycle MEs after a
0737       // run/lumi is saved. We do this via the edm::Service interface to make
0738       // sure it runs after *all* output modules, even if there are multiple.
0739       void cleanupLumi(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi);
0740 
0741       // Add ME to DQMStore datastructures. The object will be deleted if a
0742       // similar object is already present.
0743       // For global ME
0744       MonitorElement* putME(MonitorElement* me);
0745       // For local ME
0746       MonitorElement* putME(MonitorElement* me, uint64_t moduleID);
0747       // Find a global ME of matching name, in any state.
0748       // MELIKE can be a MonitorElementData::Path or MonitorElement*.
0749       template <typename MELIKE>
0750       MonitorElement* findME(MELIKE const& path);
0751       // Log a backtrace on booking.
0752       void printTrace(std::string const& message);
0753       // print a log message if ME matches trackME_.
0754       void debugTrackME(const char* message, MonitorElement* me_local, MonitorElement* me_global) const;
0755       // accesor to keep MEsToSave_ private
0756       const auto& getMEsToSave() const { return MEsToSave_; }
0757       // accesor to keep onlineMode_ private
0758       const bool& getMode() const { return onlineMode_; }
0759 
0760     private:
0761       // MEComparison is a name-only comparison on MEs and Paths, allowing
0762       // heterogeneous lookup.
0763       // The ME objects here are lightweight, all the important stuff is in the
0764       // MEData. However we never handle MEData directly, but always keep it
0765       // wrapped in MEs (created as needed). MEs can share MEData.
0766       // ME objects must never appear more than once in these sets. ME objects
0767       // in localMEs_ cannot be deleted, since the module might hold pointers.
0768       // MEs in globalMEs_ can be deleted/recycled at the end of their scope,
0769       // if there are no local MEs left that share the data.
0770       // MEs can be _protoype MEs_ if their scope is not yet known (after
0771       // booking, after leaveLumi). A prototype is kept if and only if there is
0772       // no other global instance of the same ME. Prototype MEs have
0773       // run = lumi = 0 and scope != JOB. If scope == JOB, a prototype is never
0774       // required. Prototype MEs are reset *before* inserting, so fill calls
0775       // can go into prototype MEs and not be lost.
0776       // Key is (run, lumi), potentially one or both 0 for SCOPE::RUN or SCOPE::JOB
0777       // NEVER modify the key_ of a ME in these datastructures. Since we use
0778       // pointers, this may be possible (not everything is const), but it could
0779       // still corrupt the datastructure.
0780       std::map<edm::LuminosityBlockID, std::set<MonitorElement*, MonitorElement::MEComparison>> globalMEs_;
0781       // Key is (moduleID [, run | , stream]), run is only needed for
0782       // edm::global, stream only for edm::stream.
0783       // Legacy MEs have moduleID 0.
0784       std::map<uint64_t, std::set<MonitorElement*, MonitorElement::MEComparison>> localMEs_;
0785       // Whenever modifying these sets, take this  mutex. It's recursive, so we
0786       // can be liberal -- lock on any access, but also lock on the full booking
0787       // transaction.
0788       std::recursive_mutex booking_mutex_;
0789 
0790       // Universal verbose flag.
0791       // Only very few usages remain, the main debugging tool is trackME_.
0792       int verbose_;
0793 
0794       // If set to true, error out whenever things happen that are not safe for
0795       // legacy modules.
0796       bool assertLegacySafe_;
0797 
0798       // Book MEs by lumi by default whenever possible.
0799       bool doSaveByLumi_;
0800       // Book MEs by lumi from list in DQMServices/Core/python/DQMStore_cfi.py
0801       std::vector<std::string> MEsToSave_;  //just if perLS is ON
0802 
0803       // if non-empty, debugTrackME calls will log some information whenever a
0804       // ME path contains this string.
0805       std::string trackME_;
0806 
0807       // Online mode
0808       bool onlineMode_;
0809     };
0810   }  // namespace implementation
0811 
0812   // Since we still use a single, edm::Serivce instance of a DQMStore, these are all the same.
0813   namespace legacy {
0814     class DQMStore : public dqm::implementation::DQMStore {
0815     public:
0816       using IBooker = dqm::implementation::IBooker;
0817       using IGetter = dqm::implementation::IGetter;
0818       // import constructors.
0819       using dqm::implementation::DQMStore::DQMStore;
0820     };
0821   }  // namespace legacy
0822   namespace reco {
0823     using DQMStore = dqm::legacy::DQMStore;
0824   }  // namespace reco
0825   namespace harvesting {
0826     using DQMStore = dqm::legacy::DQMStore;
0827   }  // namespace harvesting
0828 }  // namespace dqm
0829 
0830 #endif