ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
graphics
EventDisplaysOnline
src
OnlineEventDisplaysSvc.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3
*/
4
#include "
EventDisplaysOnline/OnlineEventDisplaysSvc.h
"
5
#include "
RootUtils/PyAthenaGILStateEnsure.h
"
6
#include "Gaudi/Property.h"
7
#include "GaudiKernel/IIncidentSvc.h"
8
#include "GaudiKernel/Incident.h"
9
#include "GaudiKernel/MsgStream.h"
10
#include "
xAODEventInfo/EventInfo.h
"
11
12
#include <iostream>
13
#include <sys/types.h>
14
#include <grp.h>
15
16
#include <cstdlib>
// For std::rand() and std::srand()
17
#include <sys/stat.h>
//mkdir
18
#include <unistd.h>
//chown
19
#include <stdexcept>
20
#include "Python.h"
21
22
namespace
{
23
template
<
typename
...Ptr>
24
bool
25
anyNullPtr(Ptr&&...p){
26
return
((p==
nullptr
) or ...);
27
}
28
}
29
30
OnlineEventDisplaysSvc::OnlineEventDisplaysSvc
(
const
std::string& name,
31
ISvcLocator* pSvcLocator ) :
32
base_class(name, pSvcLocator){}
33
34
void
OnlineEventDisplaysSvc::beginEvent
(){
35
36
SG::ReadHandle<xAOD::EventInfo>
evt (
m_evt
);
37
if
(!evt.isValid()) {
38
ATH_MSG_FATAL
(
"Could not find event info"
);
39
}
40
std::vector<std::string> streams;
41
42
m_eventNumber
= evt->eventNumber();
43
m_runNumber
= evt->runNumber();
44
45
//Check what trigger streams were fired, if in list of desired
46
//streams to be reconstructed pick one randomly
47
for
(
const
xAOD::EventInfo::StreamTag
& tag : evt->streamTags()){
48
ATH_MSG_DEBUG
(
"A trigger in stream "
<< tag.type() <<
"_"
<< tag.name() <<
" was fired in this event."
);
49
std::string stream_fullname = tag.type() +
"_"
+ tag.name();
50
51
if
(
m_streamsWanted
.empty()) {
52
ATH_MSG_WARNING
(
"You have not requested any specific streams, going to allow all streams"
);
53
streams.emplace_back(stream_fullname);
54
}
55
56
else
{
57
//If the stream is in the list of streams requested, add it
58
if
(std::find(
m_streamsWanted
.begin(),
m_streamsWanted
.end(), tag.name()) !=
m_streamsWanted
.end()){
59
streams.emplace_back(stream_fullname);
60
}
61
bool
isPublic =
false
;
62
//if the stream is not in the list of public streams wanted, continue
63
if
(std::find(
m_publicStreams
.begin(),
m_publicStreams
.end(), tag.name()) ==
m_publicStreams
.end())
continue
;
64
// Acquire the Global Interpreter Lock (GIL) to ensure thread safety when interacting with Python objects
65
RootUtils::PyGILStateEnsure
ensure;
66
// Convert the project tag string to a Python Unicode object
67
std::string tag =
m_projectTag
;
68
PyObject
* pProjectTag = PyUnicode_FromString(tag.c_str());
69
if
(!pProjectTag) {
70
// Error handling: Print Python exception if conversion fails
71
PyErr_Print();
72
ATH_MSG_WARNING
(
"Failed to create Python Unicode object from project tag"
);
73
}
else
{
74
// Import the Python module
75
PyObject
* pHelper = PyImport_ImportModule(
"EventDisplaysOnline.EventDisplaysOnlineHelpers"
);
76
if
(!pHelper) {
77
// Error handling: Print Python exception if import fails
78
PyErr_Print();
79
ATH_MSG_WARNING
(
"Failed to import EventDisplaysOnline.EventDisplaysOnlineHelpers module"
);
80
}
else
{
81
// Get the "EventCanBeSeenByPublic" function from the module
82
PyObject
* EventCanBeSeenByPublic = PyObject_GetAttrString(pHelper,
"EventCanBeSeenByPublic"
);
83
if
(!EventCanBeSeenByPublic || !PyCallable_Check(EventCanBeSeenByPublic)) {
84
// Error handling: Print warning if function not found or not callable
85
ATH_MSG_WARNING
(
"Could not find or call EventCanBeSeenByPublic function in EventDisplaysOnline.EventDisplaysOnlineHelpers module"
);
86
}
else
{
87
// Call the "EventCanBeSeenByPublic" function with the project tag as argument
88
PyObject
* result = PyObject_CallFunctionObjArgs(EventCanBeSeenByPublic, pProjectTag, NULL);
89
if
(!result) {
90
PyErr_Print();
91
ATH_MSG_WARNING
(
"Failed to call EventCanBeSeenByPublic function"
);
92
}
else
{
93
// Convert the result to a boolean value
94
isPublic = PyObject_IsTrue(result);
95
Py_DECREF(result);
// Decrement reference count of the result object
96
}
97
}
98
Py_XDECREF(EventCanBeSeenByPublic);
99
Py_DECREF(pHelper);
100
}
101
Py_DECREF(pProjectTag);
102
}
103
if
(isPublic){
104
streams.emplace_back(
"Public"
);
105
ATH_MSG_DEBUG
(
"Can send event to public stream"
);
106
}
107
}
108
}
109
for
(
const
std::string& stream : streams){
110
ATH_MSG_DEBUG
(
"streams where a trigger fired and in your desired streams list: "
<< stream);
111
}
112
std::random_shuffle(streams.begin(), streams.end());
113
//Pick the first stream as the output directory
114
if
(!streams.empty()){
115
m_outputStreamDir
= streams[0];
116
}
117
else
{
118
ATH_MSG_WARNING
(
"Cannot find a stream adding to .Unknown directory"
);
119
m_outputStreamDir
=
".Unknown"
;
120
}
121
122
m_entireOutputStr
=
m_outputDirectory
+
"/"
+
m_outputStreamDir
;
123
m_FileNamePrefix
=
m_entireOutputStr
+
"/JiveXML"
;;
124
125
gid_t zpgid =
setOwnershipToZpGrpOrDefault
();
126
createWriteableDir
(
m_outputDirectory
, zpgid);
127
createWriteableDir
(
m_entireOutputStr
, zpgid);
128
}
129
130
void
OnlineEventDisplaysSvc::endEvent
(){
131
RootUtils::PyGILStateEnsure
ensure;
132
PyObject
* pCheckPair = PyBool_FromLong(
m_CheckPair
);
133
PyObject
* pBeamSplash = PyBool_FromLong(
m_BeamSplash
);
134
PyObject
* pMaxEvents = PyLong_FromLong(
m_maxEvents
);
135
const
char
* cString =
m_entireOutputStr
.c_str();
136
PyObject
* pDirectory = PyUnicode_FromString(cString);
137
PyObject
* pArgs = PyTuple_Pack(4, pDirectory, pMaxEvents, pCheckPair,pBeamSplash);
138
PyObject
* pModule = PyImport_ImportModule(
const_cast<
char
*
>
(
"EventDisplaysOnline.EventUtils"
));
139
if
(!pCheckPair || !pBeamSplash || !pMaxEvents || !pDirectory || !pArgs){
140
PyErr_Print();
141
ATH_MSG_WARNING
(
"Failed to create Python Unicode object"
);}
142
if
(!pModule) {
143
PyErr_Print();
144
ATH_MSG_WARNING
(
"Failed to import EventDisplaysOnline.EventUtils module"
);
145
}
else
{
146
ATH_MSG_DEBUG
(
"Successfully imported EventDisplaysOnline.EventUtils module"
);
147
148
// Get the "cleanDirectory" function from the module
149
PyObject
* cleanDirectory = PyObject_GetAttrString(pModule,
"cleanDirectory"
);
150
if
(!cleanDirectory || !PyCallable_Check(cleanDirectory)) {
151
ATH_MSG_WARNING
(
"Could not find or call cleanDirectory function in EventDisplaysOnline.EventUtils module"
);
152
}
else
{
153
ATH_MSG_DEBUG
(
"Found cleanDirectory function in EventDisplaysOnline.EventUtils module"
);
154
155
// Call the "cleanDirectory" function with the provided arguments
156
PyObject_CallObject(cleanDirectory, pArgs);
157
if
(PyErr_Occurred()) {
158
PyErr_Print();
159
}
160
}
161
if
(anyNullPtr(cleanDirectory)){
162
throw
std::runtime_error(
"OnlineEventDisplaysSvc::endEvent: Py_DECREF on nullptr argument"
);
163
}
164
Py_DECREF(cleanDirectory);
165
}
166
167
if
(anyNullPtr(pModule, pArgs, pCheckPair, pMaxEvents, pDirectory)){
168
throw
std::runtime_error(
"OnlineEventDisplaysSvc::endEvent: Py_DECREF on nullptr argument"
);
169
}
170
Py_DECREF(pModule);
171
Py_DECREF(pArgs);
172
Py_DECREF(pCheckPair);
173
Py_DECREF(pMaxEvents);
174
Py_DECREF(pDirectory);
175
}
176
177
std::string
OnlineEventDisplaysSvc::getFileNamePrefix
(){
178
return
m_FileNamePrefix
;
179
}
180
181
std::string
OnlineEventDisplaysSvc::getEntireOutputStr
(){
182
return
m_entireOutputStr
;
183
}
184
185
std::string
OnlineEventDisplaysSvc::getStreamName
(){
186
return
m_outputStreamDir
;
187
}
188
void
OnlineEventDisplaysSvc::createWriteableDir
(
const
std::string& directory, gid_t zpgid){
189
190
const
char
* char_dir = directory.c_str();
191
//Time of Check, Time of Use
192
//coverity[TOCTOU]
193
if
(access(char_dir, F_OK) == 0) {
194
struct
stat directoryStat;
195
//Time of Check, Time of Use
196
//coverity[TOCTOU]
197
if
(stat(char_dir, &directoryStat) == 0 && S_ISDIR(directoryStat.st_mode) &&
198
access(char_dir, W_OK) == 0) {
199
ATH_MSG_DEBUG
(
"Going to write file to existing directory: "
<< directory);
200
if
(directoryStat.st_gid != zpgid) {
201
ATH_MSG_DEBUG
(
"Setting group to 'zp' for directory: "
<< directory);
202
chown(char_dir, -1, zpgid);
203
}
204
}
else
{
205
ATH_MSG_WARNING
(
"Directory '"
<< directory <<
"' is not usable, trying next alternative"
);
206
}
207
}
else
{
208
try
{
209
auto
rc
= mkdir(char_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
210
if
(
rc
!=0){
211
ATH_MSG_ERROR
(
"mkdir failed for directory: "
<< directory);
212
}
213
rc
= chown(char_dir, -1, zpgid);
214
if
(
rc
!=0){
215
ATH_MSG_ERROR
(
"chown failed for directory: "
<< directory);
216
}
217
ATH_MSG_DEBUG
(
"Created output directory "
<< directory);
218
}
catch
(
const
std::system_error& err) {
219
ATH_MSG_ERROR
(
"Failed to create output directory "
<< directory << err.what());
220
}
221
}
222
}
223
224
gid_t
OnlineEventDisplaysSvc::setOwnershipToZpGrpOrDefault
(){
225
gid_t zpgid;
226
struct
group grp;
227
struct
group* grp_result;
228
char
buf[1024];
// sysconf(_SC_GETGR_R_SIZE_MAX)
229
(void)getgrnam_r(
"zp"
, &grp, buf,
sizeof
(buf), &grp_result);
230
if
(grp_result !=
nullptr
) {
231
zpgid = grp.gr_gid;
232
}
else
{
233
ATH_MSG_DEBUG
(
"If running on private machine, zp group might not exist. Just set to the likely value 1307."
);
234
zpgid = 1307;
235
}
236
return
zpgid;
237
}
238
239
StatusCode
OnlineEventDisplaysSvc::initialize
(){
240
241
ATH_MSG_DEBUG
(
"Initializing "
<< name());
242
ServiceHandle<IIncidentSvc>
incSvc(
"IncidentSvc"
, name());
243
ATH_CHECK
( incSvc.retrieve() );
244
ATH_MSG_DEBUG
(
"You have requested to only output JiveXML and ESD files when a trigger in the following streams was fired: "
);
245
for
(
const
std::string& stream :
m_streamsWanted
){
246
ATH_MSG_DEBUG
(stream);
247
}
248
if
(
m_BeamSplash
){
249
m_CheckPair
=
false
;
250
}
251
incSvc->addListener(
this
,
"BeginEvent"
);
252
incSvc->addListener(
this
,
"EndEvent"
);
253
254
ATH_CHECK
(
m_evt
.initialize() );
255
256
return
StatusCode::SUCCESS;
257
}
258
259
StatusCode
OnlineEventDisplaysSvc::finalize
(){
260
261
ATH_MSG_DEBUG
(
"Finalizing "
<< name());
262
return
StatusCode::SUCCESS;
263
}
264
265
void
OnlineEventDisplaysSvc::handle
(
const
Incident& incident ){
266
ATH_MSG_DEBUG
(
"Received incident "
<< incident.type() <<
" from "
<< incident.source() );
267
if
( incident.type() == IncidentType::BeginEvent && incident.source() ==
"BeginIncFiringAlg"
){
268
beginEvent
();
269
}
270
if
(incident.type() ==
"EndEvent"
&& incident.source() ==
"EndIncFiringAlg"
){
271
endEvent
();
272
}
273
}
ATH_CHECK
#define ATH_CHECK
Evaluate an expression and check for errors.
Definition
AthCheckMacros.h:40
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition
AthMsgStreamMacros.h:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition
AthMsgStreamMacros.h:34
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition
AthMsgStreamMacros.h:32
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition
AthMsgStreamMacros.h:29
PyObject
_object PyObject
Definition
IPyComponent.h:27
rc
static Double_t rc
Definition
LArPhysWaveHECTool.cxx:37
OnlineEventDisplaysSvc.h
PyAthenaGILStateEnsure.h
OnlineEventDisplaysSvc::endEvent
void endEvent()
Definition
OnlineEventDisplaysSvc.cxx:130
OnlineEventDisplaysSvc::m_entireOutputStr
std::string m_entireOutputStr
Definition
OnlineEventDisplaysSvc.h:46
OnlineEventDisplaysSvc::m_streamsWanted
Gaudi::Property< std::vector< std::string > > m_streamsWanted
Definition
OnlineEventDisplaysSvc.h:38
OnlineEventDisplaysSvc::m_runNumber
int m_runNumber
Definition
OnlineEventDisplaysSvc.h:47
OnlineEventDisplaysSvc::createWriteableDir
void createWriteableDir(const std::string &directory, gid_t zpgid)
Definition
OnlineEventDisplaysSvc.cxx:188
OnlineEventDisplaysSvc::m_outputDirectory
Gaudi::Property< std::string > m_outputDirectory
Definition
OnlineEventDisplaysSvc.h:37
OnlineEventDisplaysSvc::finalize
StatusCode finalize() override
Definition
OnlineEventDisplaysSvc.cxx:259
OnlineEventDisplaysSvc::handle
void handle(const Incident &incident) override
Definition
OnlineEventDisplaysSvc.cxx:265
OnlineEventDisplaysSvc::beginEvent
void beginEvent()
Definition
OnlineEventDisplaysSvc.cxx:34
OnlineEventDisplaysSvc::m_evt
SG::ReadHandleKey< xAOD::EventInfo > m_evt
Definition
OnlineEventDisplaysSvc.h:36
OnlineEventDisplaysSvc::getEntireOutputStr
std::string getEntireOutputStr() override
Definition
OnlineEventDisplaysSvc.cxx:181
OnlineEventDisplaysSvc::m_FileNamePrefix
std::string m_FileNamePrefix
Definition
OnlineEventDisplaysSvc.h:44
OnlineEventDisplaysSvc::m_publicStreams
Gaudi::Property< std::vector< std::string > > m_publicStreams
Definition
OnlineEventDisplaysSvc.h:39
OnlineEventDisplaysSvc::m_projectTag
Gaudi::Property< std::string > m_projectTag
Definition
OnlineEventDisplaysSvc.h:40
OnlineEventDisplaysSvc::getStreamName
std::string getStreamName() override
Definition
OnlineEventDisplaysSvc.cxx:185
OnlineEventDisplaysSvc::OnlineEventDisplaysSvc
OnlineEventDisplaysSvc()
OnlineEventDisplaysSvc::m_CheckPair
Gaudi::Property< bool > m_CheckPair
Definition
OnlineEventDisplaysSvc.h:42
OnlineEventDisplaysSvc::m_maxEvents
Gaudi::Property< int > m_maxEvents
Definition
OnlineEventDisplaysSvc.h:43
OnlineEventDisplaysSvc::m_BeamSplash
Gaudi::Property< bool > m_BeamSplash
Definition
OnlineEventDisplaysSvc.h:41
OnlineEventDisplaysSvc::m_outputStreamDir
std::string m_outputStreamDir
Definition
OnlineEventDisplaysSvc.h:45
OnlineEventDisplaysSvc::setOwnershipToZpGrpOrDefault
gid_t setOwnershipToZpGrpOrDefault()
Definition
OnlineEventDisplaysSvc.cxx:224
OnlineEventDisplaysSvc::m_eventNumber
long m_eventNumber
Definition
OnlineEventDisplaysSvc.h:48
OnlineEventDisplaysSvc::getFileNamePrefix
std::string getFileNamePrefix() override
Definition
OnlineEventDisplaysSvc.cxx:177
OnlineEventDisplaysSvc::initialize
StatusCode initialize() override
Definition
OnlineEventDisplaysSvc.cxx:239
RootUtils::PyGILStateEnsure
Definition
PyAthenaGILStateEnsure.h:20
SG::ReadHandle
Definition
StoreGate/StoreGate/ReadHandle.h:67
ServiceHandle
Definition
ClusterMakerTool.h:36
xAOD::EventInfo_v1::StreamTag
Class describing a stream tag on the event.
Definition
EventInfo_v1.h:190
EventInfo.h
Generated on
for ATLAS Offline Software by
1.17.0