ATLAS Offline Software
Loading...
Searching...
No Matches
TFileAccessTracer.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3// System include(s):
4#include <atomic>
5#include <memory>
6#include <cstdlib>
7
8// ROOT include(s):
9#include <TSystem.h>
10#include <TFile.h>
11#include <TError.h>
12#include <TUrl.h>
13#include <TTimeStamp.h>
14#include <TRandom.h>
15
16// EDM include(s):
19
20// Local include(s):
24
25namespace xAOD {
26
27 // Initialise the static variable(s):
28 static std::atomic_bool s_enableDataSumbission( true );
29
32 m_serverAddress( "http://rucio-lb-prod.cern.ch:18762/traces/" ),
35 m_readStats( &( IOStats::instance().stats() ) ) {
36
37 // Construct the "technical address" of the host:
38 const ::TUrl url( m_serverAddress.c_str() );
39 m_serverInetAddress = gSystem->GetHostByName( url.GetHost() );
40 }
41
49
50 // If the user turned off the data submission, then stop already here...
52 return;
53 }
54
55 // Decide what monitoring fraction to take. To make it possible for Panda
56 // to override it with larger/smaller values if needed.
58 const char* fractionString =
59 gSystem->Getenv( "XAOD_ACCESSTRACER_FRACTION" );
60 if( fractionString ) {
61 char* endptr = 0;
62 const Double_t fraction = strtod( fractionString, &endptr );
63 if( endptr != fractionString ) {
64 monitoredFraction = fraction;
65 }
66 }
67
68 // Decide randomly whether to send the monitoring data or not. While
69 // TRandom is not good enough for statistical purposes, it's fast, and is
70 // perfectly good to make this decision...
71 ::TRandom rng( ::TTimeStamp().GetNanoSec() );
72 if( rng.Rndm() > monitoredFraction ) {
73 return;
74 }
75
76 // Open a socket to the server:
77 const ::TUrl url( m_serverAddress.c_str() );
78 TSocket socket;
79 if( ! socket.connect( m_serverInetAddress, url.GetPort() ).isSuccess() ) {
80 // Just exit silently. If we can't send the info, we can't send the
81 // info. It's not a problem.
82 return;
83 }
84
85 // Let the user know what's happening:
86 ::Info( "xAOD::TFileAccessTracer",
87 "Sending file access statistics to %s", m_serverAddress.c_str() );
88
89 // Start constructing the header of the message to send to the server:
90 ::TString hdr = "POST /";
91 hdr += url.GetFile();
92 hdr += " HTTP/1.0";
93 hdr += "\r\n";
94 hdr += "From: ";
95 hdr += gSystem->HostName();
96 hdr += "\r\n";
97 hdr += "User-Agent: xAODRootAccess\r\n";
98 hdr += "Content-Type: application/json\r\n";
99 hdr += "Content-Length: ";
100
101 //
102 // Now construct the message payload:
103 //
104 ::TString pld = "{";
105
106 //
107 // Collect the names of all the accessed files:
108 //
109 pld += "\"accessedFiles\": [";
110 bool first = true;
111 for( auto& info : m_accessedFiles ) {
112 if( ! first ) {
113 pld += ", ";
114 }
115 pld += "\"";
116 pld += info.fullFilePath();
117 pld += "\"";
118 first = false;
119 }
120 pld += "], ";
121 //
122 // Collect the names of all the containers that were accessed:
123 //
124 pld += "\"accessedContainers\": [";
125 first = true;
126 for( const auto& bs : m_readStats->containers() ) {
127 if( ! bs.second.readEntries() ) {
128 continue;
129 }
130 if( ! first ) {
131 pld += ", ";
132 }
133 pld += "{\"";
134 pld += bs.second.GetName();
135 pld += "\": ";
136 pld += bs.second.readEntries();
137 pld += "}";
138 first = false;
139 }
140 pld += "], ";
141 //
142 // Collect the names of all the branches that were accessed:
143 //
144 pld += "\"accessedBranches\": [";
145 first = true;
146 for( const auto& branch : m_readStats->branches() ) {
147 for( const xAOD::BranchStats* bs : branch.second ) {
148 if( ( ! bs ) || ( ! bs->readEntries() ) ) {
149 continue;
150 }
151 if( ! first ) {
152 pld += ", ";
153 }
154 pld += "{\"";
155 pld += bs->GetName();
156 pld += "\": ";
157 pld += bs->readEntries();
158 pld += "}";
159 first = false;
160 }
161 }
162 pld += "]";
163 //
164 // Collect some possible Panda information in case the job is running
165 // on the grid:
166 //
167 const char* pandaID = gSystem->Getenv( "PandaID" );
168 if( pandaID ) {
169 pld += ", \"PandaID\": ";
170 pld += pandaID;
171 pld += "";
172 }
173 const char* taskID = gSystem->Getenv( "PanDA_TaskID" );
174 if( taskID ) {
175 pld += ", \"PanDA_TaskID\": ";
176 pld += taskID;
177 pld += "";
178 }
179 //
180 // Add some simple information about the host:
181 //
182 pld += ", \"ROOT_RELEASE\": \"";
183 pld += ROOT_RELEASE;
184 pld += "\"";
185 pld += ", \"ReportRate\": ";
186 pld += monitoredFraction;
187 //
188 // Add some information about the file access pattern:
189 //
190 pld += ", \"ReadCalls\": ";
191 pld += m_readStats->fileReads();
192 pld += ", \"ReadSize\": ";
193 pld += ( m_readStats->fileReads() != 0 ?
194 m_readStats->bytesRead() / m_readStats->fileReads() : 0 );
195 pld += ", \"CacheSize\": ";
196 pld += m_readStats->cacheSize();
197 pld += "}";
198
199 // Now finish constructing the header, and merge the two into a single
200 // message:
201 hdr += TString::Format( "%i", pld.Length() );
202 hdr += "\r\n\r\n";
203 const ::TString msg = hdr + pld;
204
205 // A debug message for the time being:
206 /*
207 Info( "xAOD::TFileAccessTracer::~TFileAccessTracer",
208 "Sending message:\n\n%s", msg.Data() );
209 */
210
211 // Finally, send the message:
212 if( ! socket.send( msg ).isSuccess() ) {
213 // Don't be vocal about the issue...
214 return;
215 }
216 }
217
223 void TFileAccessTracer::add( const ::TFile& file ) {
224
225 // Protect this call:
226 std::lock_guard< std::mutex > lock( m_mutex );
227
228 // Remember this file:
229 m_accessedFiles.insert(
230 AccessedFile{ gSystem->DirName( file.GetName() ),
231 gSystem->BaseName( file.GetName() ) } );
232
233 // Return gracefully:
234 return;
235 }
236
237 const std::string& TFileAccessTracer::serverAddress() const {
238
239 // Protect this call:
240 std::lock_guard< std::mutex > lock( m_mutex );
241
242 return m_serverAddress;
243 }
244
245 void TFileAccessTracer::setServerAddress( const std::string& addr ) {
246
247 // Protect this call:
248 std::lock_guard< std::mutex > lock( m_mutex );
249
250 // Set the address itself:
251 m_serverAddress = addr;
252
253 // Construct the "technical address" of the host:
254 ::TUrl url( m_serverAddress.c_str() );
255 m_serverInetAddress = gSystem->GetHostByName( url.GetHost() );
256 return;
257 }
258
260
261 // Protect this call:
262 std::lock_guard< std::mutex > lock( m_mutex );
263
264 return m_monitoredFraction;
265 }
266
268
269 // Protect this call:
270 std::lock_guard< std::mutex > lock( m_mutex );
271
272 m_monitoredFraction = value;
273 return;
274 }
275
282
284 return;
285 }
286
296 operator< ( const AccessedFile& rhs ) const {
297
298 if( filePath != rhs.filePath ) {
299 return filePath < rhs.filePath;
300 }
301 if( fileName != rhs.fileName ) {
302 return fileName < rhs.fileName;
303 }
304
305 return false;
306 }
307
316
317 if( filePath == "" ) {
318 return fileName;
319 } else {
320 return ( filePath + "/" + fileName );
321 }
322 }
323
324} // namespace xAOD
std::map< std::string, double > instance
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.
Singleton object holding on to the process's I/O statistics.
Definition IOStats.h:35
Helper class storing information about the accessed files.
::TString filePath
The full path to the file.
::TString fileName
The name of the file.
::TString fullFilePath() const
Function returning the full file path.
bool operator<(const AccessedFile &rhs) const
Operator to be able to put this into an std::set.
void add(const ::TFile &file)
Add information about a new file that got accessed.
void setMonitoredFraction(::Double_t value)
Set the fraction of jobs that should send monitoring information.
::Double_t monitoredFraction() const
Fraction of jobs that should send monitoring information.
const std::string & serverAddress() const
The address of the server that information is sent to.
::Double_t m_monitoredFraction
Fraction of jobs that should send monitoring information.
ReadStats * m_readStats
Object describing the job's xAOD access statistics.
std::mutex m_mutex
Mutex for modifying the object.
::TInetAddress m_serverInetAddress
Technical address of the server.
static void enableDataSubmission(::Bool_t value)
Function for turning data submission on/off.
TFileAccessTracer()
Default constructor.
void setServerAddress(const std::string &addr)
Set the address of the server that information is sent to.
std::set< AccessedFile > m_accessedFiles
List of all the input files that were accessed in the job.
std::string m_serverAddress
Address of the server to send monitoring information to.
Very simple wrapper around POSIX sockets.
Definition TSocket.h:29
StatusCode send(const TString &payload)
Function sending a message to the connected address.
Definition TSocket.cxx:122
StatusCode connect(const TInetAddress &address, int port)
Function connecting to the specified address.
Definition TSocket.cxx:48
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
static std::atomic_bool s_enableDataSumbission(true)
MsgStream & msg
Definition testRead.cxx:32
TFile * file