ATLAS Offline Software
Loading...
Searching...
No Matches
OfflineHistogramProvider.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef AthenaMonitoringKernel_HistogramFiller_OfflineHistogramProvider_h
6#define AthenaMonitoringKernel_HistogramFiller_OfflineHistogramProvider_h
7
8#include <memory>
9
13
14#include "GaudiKernel/ContextSpecificPtr.h"
15
16#include "HistogramFactory.h"
17
18#include "TTree.h"
19
20// this mutex is used to protect access to the metadata trees
21namespace {
22 static std::mutex s_metadataMutex;
23}
24
25namespace Monitored {
30 public:
39 std::shared_ptr<HistogramFactory> factory,
40 const HistogramDef& histDef)
42 , m_gmTool(gmTool)
43 , m_factory(std::move(factory))
44 , m_histDef(new HistogramDef(histDef))
45 , m_objcache({0, 0, nullptr})
46 {}
47
48 // store metadata trees on object destruction
49 virtual ~OfflineHistogramProvider() override {
50 try {
52 }
53 catch (const GaudiException&) {
54 // storeMetadata can throw due to dereferencing a Gaudi handle
55 std::abort();
56 }
57 }
58
68 TNamed* histogram() override {
69 const unsigned runNumber = m_gmTool->runNumber();
70 const unsigned lumiBlock = m_gmTool->lumiBlock();
71
72 // do we have the object already?
73 std::scoped_lock lock(m_cacheMutex);
74 objcache& objcacheref = m_objcache;
75 if (objcacheref.lumiBlock == lumiBlock
76 && objcacheref.runNumber == runNumber
77 && objcacheref.object) {
78 return objcacheref.object;
79 }
80
81 std::string lbString;
82 HistogramDef::RunPeriod period = m_histDef->runperiod;
83 if ( period == HistogramDef::RunPeriod::Run ) {
84 lbString = "";
85 } else if ( period == HistogramDef::RunPeriod::LowStat ) {
86 const unsigned lbBase = lumiBlock-(((int64_t)lumiBlock-1)%20);
87 lbString = "/lowStat_LB"+std::to_string(lbBase)+"-"+std::to_string(lbBase+19);
88 } else {
89 lbString = "/lb_"+std::to_string(lumiBlock);
90 }
91 m_histDef->tld = "/run_"+std::to_string(runNumber)+lbString+"/";
92
93 objcacheref.lumiBlock = lumiBlock;
94 objcacheref.runNumber = runNumber;
95 objcacheref.object = m_factory->create(*m_histDef);
96 const auto fullName = m_factory->getFullName(*m_histDef);
97 if (std::find(m_storedPaths.begin(), m_storedPaths.end(), fullName) == m_storedPaths.end()) {
98 m_storedPaths.push_back(std::move(fullName));
99 }
100 return objcacheref.object;
101 }
102
103 private:
105 std::shared_ptr<HistogramFactory> m_factory;
106 std::shared_ptr<HistogramDef> m_histDef;
107
108 struct objcache {
109 unsigned int runNumber;
110 unsigned int lumiBlock;
111 TNamed* object;
112 };
113 mutable Gaudi::Hive::ContextSpecificData<objcache> m_objcache ATLAS_THREAD_SAFE;
114 std::mutex m_cacheMutex;
115
116 std::vector<std::string> m_storedPaths;
117
124 void storeMetadata() const {
125 std::scoped_lock<std::mutex> metadataLock(s_metadataMutex);
126 for (const auto &path : m_storedPaths) {
127 //std::cout << "Path " << path << std::endl;
128 size_t pos = path.find_last_of('/');
129 auto splitPath = std::make_pair(path.substr(0, pos), path.substr(pos + 1));
130 std::string treePath = splitPath.first + "/metadata";
131 auto &histSvc = m_gmTool->histogramService();
132 std::string interval;
133 char triggerData[] = "<none>";
134 const std::string mergeDataStr = m_histDef->merge == "" ? "<default>" : m_histDef->merge;
135 std::vector<char> mergeData{mergeDataStr.begin(), mergeDataStr.end()};
136 mergeData.push_back('\0');
137
138 HistogramDef::RunPeriod period = m_histDef->runperiod;
139 if (period == HistogramDef::RunPeriod::Run) {
140 interval = "run";
141 } else if (period == HistogramDef::RunPeriod::LowStat) {
142 interval = "lowStat";
143 } else {
144 interval = "lumiBlock";
145 }
146 if (!histSvc->existsTree(treePath)) {
147 auto tree = std::make_unique<TTree>("metadata", "Monitoring Metadata");
148
149 tree->Branch("Name", &(splitPath.second[0]), "Name/C");
150 tree->Branch("Interval", &(interval[0]), "Interval/C");
151 tree->Branch("TriggerChain", triggerData, "TriggerChain/C");
152 tree->Branch("MergeMethod", mergeData.data(), "MergeMethod/C");
153 tree->Fill();
154
155 if (!histSvc->regTree(treePath, std::move(tree))) {
156 MsgStream log(Athena::getMessageSvc(), "OfflineHistogramProvider");
157 log << MSG::ERROR
158 << "Failed to register DQ metadata TTree " << treePath << endmsg;
159 }
160 } else {
161 TTree *tree{nullptr};
162 if (histSvc->getTree(treePath, tree).isSuccess()) {
163 tree->SetBranchAddress("Name", &(splitPath.second[0]));
164 tree->SetBranchAddress("Interval", &(interval[0]));
165 tree->SetBranchAddress("TriggerChain", triggerData);
166 tree->SetBranchAddress("MergeMethod", mergeData.data());
167 tree->Fill();
168 } else {
169 MsgStream log(Athena::getMessageSvc(), "OfflineHistogramProvider");
170 log << MSG::ERROR
171 << "Failed to retrieve DQ metadata TTree " << treePath << " which is reported to exist" << endmsg;
172 }
173 }
174 }
175 }
176 };
177}
178
179#endif /* AthenaMonitoringKernel_HistogramFiller_OfflineHistogramProvider_h */
#define endmsg
Interface of the source of ROOT objects for HistogramFillers.
std::shared_ptr< HistogramDef > m_histDef
TNamed * histogram() override
Getter of ROOT object.
std::shared_ptr< HistogramFactory > m_factory
void storeMetadata() const
Store metadata trees.
OfflineHistogramProvider(GenericMonitoringTool *const gmTool, std::shared_ptr< HistogramFactory > factory, const HistogramDef &histDef)
Constructor.
Gaudi::Hive::ContextSpecificData< objcache > m_objcache ATLAS_THREAD_SAFE
IMessageSvc * getMessageSvc(bool quiet=false)
Generic monitoring tool for athena components.
STL namespace.
the internal class used to keep parsed Filler properties
@ LowStat
rebook histogram after every 20 lumiblocks
@ Run
rebook histogram after each run
TChain * tree