ATLAS Offline Software
Loading...
Searching...
No Matches
TFileAccessTracer.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3// System include(s):
4#include <atomic>
5#include <cstdlib>
6#include <mutex>
7#include <set>
8
9// ROOT include(s):
10#include <TError.h>
11#include <TFile.h>
12#include <TRandom.h>
13#include <TSystem.h>
14#include <TTimeStamp.h>
15#include <TUrl.h>
16
17// EDM include(s):
20
21// Local include(s):
25
26namespace xAOD {
27
29
31 struct AccessedFile {
33 std::string m_filePath;
35 std::string m_fileName;
37 bool operator<(const AccessedFile& rhs) const {
38 if (m_filePath != rhs.m_filePath) {
39 return m_filePath < rhs.m_filePath;
40 }
41 if (m_fileName != rhs.m_fileName) {
42 return m_fileName < rhs.m_fileName;
43 }
44 return false;
45 }
46
47 std::string fullFilePath() const {
48 if (m_filePath == "") {
49 return m_fileName;
50 } else {
51 return (m_filePath + "/" + m_fileName);
52 }
53 }
54 };
55
57 std::set<AccessedFile> m_accessedFiles;
58
60 std::string m_serverAddress{"http://rucio-lb-prod.cern.ch:18762/traces/"};
62 std::atomic_bool m_enableDataSumbission{true};
63
66
69
71 mutable std::mutex m_mutex;
72
73}; // struct TFileAccessTracer::Impl
74
82
83 // Make sure that nobody is trying to update the object at this point.
84 std::lock_guard<std::mutex> lock(m_impl->m_mutex);
85
86 // If the user turned off the data submission, then stop already here...
87 if (m_impl->m_enableDataSumbission == false) {
88 return;
89 }
90
91 // Decide what monitoring fraction to take. To make it possible for Panda
92 // to override it with larger/smaller values if needed.
93 double monitoredFraction = m_impl->m_monitoredFraction;
94 const char* fractionString = gSystem->Getenv("XAOD_ACCESSTRACER_FRACTION");
95 if (fractionString) {
96 char* endptr = 0;
97 const double fraction = strtod(fractionString, &endptr);
98 if (endptr != fractionString) {
99 monitoredFraction = fraction;
100 }
101 }
102
103 // Decide randomly whether to send the monitoring data or not. While
104 // TRandom is not good enough for statistical purposes, it's fast, and is
105 // perfectly good to make this decision...
106 ::TRandom rng(::TTimeStamp().GetNanoSec());
107 if (rng.Rndm() > monitoredFraction) {
108 return;
109 }
110
111 // Decide what server to send the information to. To make it possible for
112 // Panda to override it if needed.
113 std::string serverAddress = m_impl->m_serverAddress;
114 const char* serverAddressString = gSystem->Getenv("XAOD_ACCESSTRACER_SERVER");
115 if (serverAddressString) {
116 serverAddress = serverAddressString;
117 }
118
119 // Construct the "technical address" of the host:
120 const ::TUrl url(serverAddress.c_str());
121 const ::TInetAddress serverInetAddress =
122 gSystem->GetHostByName(url.GetHost());
123
124 // Open a socket to the server:
125 TSocket socket;
126 if (socket.connect(serverInetAddress, url.GetPort()).isSuccess() == false) {
127 // Just exit silently. If we can't send the info, we can't send the
128 // info. It's not a problem.
129 return;
130 }
131
132 // Let the user know what's happening:
133 ::Info("xAOD::TFileAccessTracer", "Sending file access statistics to %s",
134 serverAddress.c_str());
135
136 // Start constructing the header of the message to send to the server:
137 ::TString hdr = "POST /";
138 hdr += url.GetFile();
139 hdr += " HTTP/1.1\r\n";
140 hdr += "From: ";
141 hdr += gSystem->HostName();
142 hdr += "\r\n";
143 hdr += "Host: ";
144 hdr += url.GetHost();
145 hdr += "\r\n";
146 hdr += "User-Agent: xAODRootAccess\r\n";
147 hdr += "Content-Type: application/json\r\n";
148 hdr += "Connection: close\r\n";
149 hdr += "Content-Length: ";
150
151 //
152 // Now construct the message payload:
153 //
154 ::TString pld = "{";
155
156 //
157 // Collect the names of all the accessed files:
158 //
159 pld += "\"accessedFiles\": [";
160 bool first = true;
161 for (const Impl::AccessedFile& info : m_impl->m_accessedFiles) {
162 if (!first) {
163 pld += ", ";
164 }
165 pld += "\"";
166 pld += info.fullFilePath();
167 pld += "\"";
168 first = false;
169 }
170 pld += "], ";
171 //
172 // Collect the names of all the containers that were accessed:
173 //
174 pld += "\"accessedContainers\": [";
175 first = true;
176 for (const auto& bs : m_impl->m_readStats.containers()) {
177 if (!bs.second.readEntries()) {
178 continue;
179 }
180 if (!first) {
181 pld += ", ";
182 }
183 pld += "{\"";
184 pld += bs.second.GetName();
185 pld += "\": ";
186 pld += bs.second.readEntries();
187 pld += "}";
188 first = false;
189 }
190 pld += "], ";
191 //
192 // Collect the names of all the branches that were accessed:
193 //
194 pld += "\"accessedBranches\": [";
195 first = true;
196 for (const auto& branch : m_impl->m_readStats.branches()) {
197 for (const xAOD::BranchStats* bs : branch.second) {
198 if ((!bs) || (!bs->readEntries())) {
199 continue;
200 }
201 if (!first) {
202 pld += ", ";
203 }
204 pld += "{\"";
205 pld += bs->GetName();
206 pld += "\": ";
207 pld += bs->readEntries();
208 pld += "}";
209 first = false;
210 }
211 }
212 pld += "]";
213 //
214 // Collect some possible Panda information in case the job is running
215 // on the grid:
216 //
217 const char* pandaID = gSystem->Getenv("PandaID");
218 if (pandaID) {
219 pld += ", \"PandaID\": ";
220 pld += pandaID;
221 pld += "";
222 }
223 const char* taskID = gSystem->Getenv("PanDA_TaskID");
224 if (taskID) {
225 pld += ", \"PanDA_TaskID\": ";
226 pld += taskID;
227 pld += "";
228 }
229 //
230 // Add some simple information about the host:
231 //
232 pld += ", \"ROOT_RELEASE\": \"";
233 pld += ROOT_RELEASE;
234 pld += "\"";
235 pld += ", \"ReportRate\": ";
236 pld += monitoredFraction;
237 //
238 // Add some information about the file access pattern:
239 //
240 pld += ", \"ReadCalls\": ";
241 pld += m_impl->m_readStats.fileReads();
242 pld += ", \"ReadSize\": ";
243 pld +=
244 (m_impl->m_readStats.fileReads() != 0
245 ? m_impl->m_readStats.bytesRead() / m_impl->m_readStats.fileReads()
246 : 0);
247 pld += ", \"CacheSize\": ";
248 pld += m_impl->m_readStats.cacheSize();
249 pld += "}";
250
251 // Now finish constructing the header, and merge the two into a single
252 // message:
253 hdr += TString::Format("%i", pld.Length());
254 hdr += "\r\n\r\n";
255 const ::TString msg = hdr + pld;
256
257 // Send the message, and try to receive an answer.
258 socket.send(msg).ignore();
259 TString response;
260 socket.receive(4096, response).ignore();
261}
262
268
274void TFileAccessTracer::add(std::string_view fileName) {
275
276 // Protect this call:
277 std::lock_guard<std::mutex> lock(m_impl->m_mutex);
278
279 // Remember this file:
280 m_impl->m_accessedFiles.insert(
281 {gSystem->DirName(fileName.data()), gSystem->BaseName(fileName.data())});
282}
283
284const std::string& TFileAccessTracer::serverAddress() const {
285
286 // Protect this call:
287 std::lock_guard<std::mutex> lock(m_impl->m_mutex);
288
289 return m_impl->m_serverAddress;
290}
291
292void TFileAccessTracer::setServerAddress(const std::string& addr) {
293
294 // Protect this call:
295 std::lock_guard<std::mutex> lock(m_impl->m_mutex);
296
297 // Set the address itself:
298 m_impl->m_serverAddress = addr;
299}
300
302
303 // Protect this call:
304 std::lock_guard<std::mutex> lock(m_impl->m_mutex);
305
306 return m_impl->m_monitoredFraction;
307}
308
310
311 // Protect this call:
312 std::lock_guard<std::mutex> lock(m_impl->m_mutex);
313
314 m_impl->m_monitoredFraction = value;
315}
316
323
324 m_impl->m_enableDataSumbission = value;
325}
326
328
329} // namespace xAOD
MDT_Response response
Class describing the access statistics of one (sub-)branch.
Definition ReadStats.h:43
::Long64_t readEntries() const
Get how many entries were read from this branch.
ReadStats & stats()
Access the object belonging to the current thread.
Definition IOStats.cxx:17
static IOStats & instance()
Singleton object accessor.
Definition IOStats.cxx:11
Class describing the access statistics of a collection of branches.
Definition ReadStats.h:123
double monitoredFraction() const
Fraction of jobs that should send monitoring information.
void enableDataSubmission(bool value)
Function for turning data submission on/off.
void setMonitoredFraction(double value)
Set the fraction of jobs that should send monitoring information.
const std::string & serverAddress() const
The address of the server that information is sent to.
void add(std::string_view fileName)
Add information about a new file that got accessed.
TFileAccessTracer()
Default constructor.
void setServerAddress(const std::string &addr)
Set the address of the server that information is sent to.
static TFileAccessTracer & instance()
Access the singleton instance of this class.
std::unique_ptr< Impl > m_impl
Pointer to the implementation of the class.
Very simple wrapper around POSIX sockets.
Definition TSocket.h:32
StatusCode send(const TString &payload)
Function sending a message to the connected address.
Definition TSocket.cxx:119
StatusCode connect(const TInetAddress &address, int port)
Function connecting to the specified address.
Definition TSocket.cxx:45
StatusCode receive(std::size_t maxSize, TString &response)
Function receiving a message from the connected address.
Definition TSocket.cxx:147
STL namespace.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Helper struct storing information about the accessed files.
std::string m_filePath
The full path to the file.
bool operator<(const AccessedFile &rhs) const
Operator to be able to put this into an std::set.
std::string fullFilePath() const
Function returning the full file path.
std::string m_fileName
The name of the file.
std::atomic_bool m_enableDataSumbission
Overall flag for enabling/disabling the data submission.
std::set< AccessedFile > m_accessedFiles
List of all the input files that were accessed in the job.
const ReadStats & m_readStats
Permanent reference to the job's ReadStats object.
std::string m_serverAddress
Address of the server to send monitoring information to.
double m_monitoredFraction
Fraction of jobs that should send monitoring information.
std::mutex m_mutex
Mutex for modifying the object.
MsgStream & msg
Definition testRead.cxx:32