ATLAS Offline Software
Loading...
Searching...
No Matches
TrigSerTPTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// $Id$
6
7// ROOT include(s):
8#include <TClass.h>
9
10// Gaudi/Athena include(s):
11#include "GaudiKernel/System.h"
16
17// Local include(s):
19
20
22 const std::string& name,
23 const IInterface* parent) :
24 AthAlgTool( type, name, parent ),
25 m_msgsvcTP( "", name ),
26 m_dictSvc( "AthDictLoaderSvc", name ),
27 m_useAthDictLoader( true ),
28 m_online( false ),
29 m_tpcnvsvc( "AthTPCnvSvc", name ) {
30
31 declareInterface< TrigSerTPTool >( this );
32
33 declareProperty( "TPMap", m_TPmap, "map of T->P classes" );
34 declareProperty( "ActiveClasses", m_activeClasses,
35 "allows to skip classes not relevant in the current "
36 "trigger level" );
37 declareProperty( "debuggingMsgSvc", m_msgsvcTP,
38 "an instance of the messageSvc for debugging purposes" );
39 declareProperty( "onlineMode", m_online,
40 "simpler setup for running online" );
41 declareProperty( "useAthDictLoader", m_useAthDictLoader,
42 "use AthDictLoaderSvc instead of plain ROOT" );
43}
44
46
47 // Greet the user:
48 ATH_MSG_INFO( "Initializing" );
49
50 // Retrieve a custom message service:
51 if( ! m_msgsvcTP.empty() ) {
52 if( m_msgsvcTP.retrieve().isFailure() ) {
53 ATH_MSG_INFO( "Could not retrieve a separate MsgSvc for "
54 "the T/P debugging" );
55 } else {
56 ATH_MSG_DEBUG( "Using " << m_msgsvcTP << " for debugging" );
57 IMessageSvc* msvc = m_msgsvcTP.operator->();
58 m_logTP = std::make_unique< MsgStream >( msvc,
59 "TrigSerTPTool-T/P" );
60 }
61 }
62
63 // Retrieve the used services:
64 ATH_CHECK( m_dictSvc.retrieve() );
65 ATH_CHECK( m_tpcnvsvc.retrieve() );
66
67 /* When a P<->T conversion is requested, this tool makes a call to TClass::GetClass.
68 * The way it's done here can cause performance issues in some circumstances.
69 * For example, reading data16 RAW files trigger a P->T conversion from
70 * DataVector<xAOD::TauJet_v2> to DataVector<xAOD::TauJet_v3> in RAWtoALL/22.0.62.
71 * The problem is that the converter returns the full class name through
72 * ITPCnvBase::transientTInfo(), which in this case resolves into
73 * DataVector<xAOD::TauJet_v3,DataVector<xAOD::IParticle,DataModel_detail::NoBase> >
74 * Passing this directly to TClass::GetClass causes AutoLoading/HeaderParsing
75 * which notoriously allocates memory and never releases it. Here, we work
76 * around this problem by stripping the base class information from the name
77 * that's passed to TClass::GetClass, in this case simply DataVector<xAOD::TauJet_v3>
78 */
79 m_clNameRules.add("DataVector<$T, $B>", "DataVector<$T>");
80
81 return StatusCode::SUCCESS;
82}
83
84ITPCnvBase* TrigSerTPTool::getConverter( const std::string& persistent ) const
85{
86 std::lock_guard<std::mutex> lock(m_convertersCacheMutex);
87 ITPCnvBase* cnvtr = m_convertesCache[persistent];
88 if ( ATH_LIKELY( cnvtr ) )
89 return cnvtr;
90
91 // no converter, we need to find it, first the trigger specific one
92 cnvtr = m_tpcnvsvc->p2t_cnv( persistent, Athena::TPCnvType::Trigger );
93 if( ! cnvtr ) {
94 // If there is no such thing, try a generic one:
95 cnvtr = m_tpcnvsvc->p2t_cnv( persistent );
96 }
97 m_convertesCache[persistent] = cnvtr;
98 return cnvtr;
99}
100
101void* TrigSerTPTool::convertTP( const std::string &clname, void *ptr,
102 std::string &persName ) const
103{
104 ATH_MSG_DEBUG( "TrigSerTPTool::convertTP" );
105
106 //pers and persName set only after successful conversion
107 persName = "";
108 void *pers( 0 );
109
110 // Start by trying to find the correct persistent class from the TP map
111 // Otherwise, use the internal logic of the TPCnvSvc
112 const auto tpItr = m_TPmap.find( clname );
113 if( tpItr == m_TPmap.end() ) {
114 REPORT_MESSAGE( MSG::ERROR )
115 << "Transient class " << clname
116 << " is not in the T/P Converter map";
117 return 0;
118 }
119 persName = tpItr->second;
120
121 ITPCnvBase* cnvtr = getConverter( persName );
122 if( ! cnvtr ) {
123 ATH_MSG_ERROR( "T/P Converter for transient class " << tpItr->first
124 << " persistent class " << persName << " could not be retrieved");
125 return nullptr;
126 }
127
128 // Create a persistent object:
129 const std::string persname =
130 m_clNameRules.apply( System::typeinfoName( cnvtr->persistentTInfo() ) );
131 TClass *persObjCl = getClass( persname );
132 void *persptr( 0 );
133 if( persObjCl ) {
134 persptr = persObjCl->New();
135 ATH_MSG_DEBUG( "created object of " << persptr << " at " << persptr );
136 } else {
137 REPORT_MESSAGE( MSG::ERROR )
138 << "Couldn't find dictionary for type " << persname;
139 return 0;
140 }
141
142 // Do the conversion:
143 ATH_MSG_DEBUG( "invoking TP for " << clname << " at " << ptr );
144 try {
145 cnvtr->transToPersUntyped( ptr, persptr, m_logTP ? *m_logTP : msg() );
146 persName = std::move(persname);
147 pers = persptr;
148 ATH_MSG_DEBUG( "succeeded at " << persptr );
149 }
150 catch( const std::runtime_error& e ){
151
152 //delete persObjCl->New();
153 const std::string issue = e.what();
154 if( issue.find( "is deprecated" ) != std::string::npos ) {
155 ATH_MSG_INFO( "An exception " << e.what() );
156 } else {
157 pers = 0;
158 REPORT_MESSAGE( MSG::ERROR ) << "An exception occurred: " << e.what();
159 }
160 }
161
162 // Return the converted object:
163 return pers;
164}
165
166void* TrigSerTPTool::convertPT( const std::string &persName, void *pers,
167 std::string& transName ) const
168{
169 // First look for a trigger specific converter:
170 ITPCnvBase* cnvtr =
171 m_tpcnvsvc->p2t_cnv( persName, Athena::TPCnvType::Trigger );
172 if( ! cnvtr ) {
173 // If there is no such thing, try a generic one:
174 cnvtr = m_tpcnvsvc->p2t_cnv( persName );
175 }
176 if( ! cnvtr ) {
177 REPORT_MESSAGE( MSG::ERROR )
178 << "T/P Converter for persistent class "
179 << persName << " could not be retrieved";
180 return 0;
181 }
182
183 // Get the name of the transient class:
184 transName = m_clNameRules.apply( System::typeinfoName( cnvtr->transientTInfo() ) );
185
186 // Create the transient object:
187 TClass *transCl = getClass( transName );
188 void *trans( 0 );
189 if( transCl ){
190 trans = transCl->New();
191 ATH_MSG_DEBUG( "trans " << trans );
192 }
193
194 // Do the conversion:
195 ATH_MSG_DEBUG( "invoking PT for " << transName );
196 try {
197 cnvtr->persToTransWithKeyUntyped( pers, trans, "", m_logTP ? *m_logTP : msg() );
198 ATH_MSG_DEBUG( " succeeded at " << trans );
199 }
200 catch (const std::runtime_error& e){
201 REPORT_MESSAGE( MSG::ERROR ) << "An exception occurred: " << e.what();
202 //it should destruct trans here (is it in a good state?)
203 trans = 0;
204 }
205
206 // Return the converted object:
207 return trans;
208}
209
210const std::string&
211TrigSerTPTool::persClassName( const std::string& transClassName ) const {
212
213 // Try to extract from the TP map
214 const auto tpItr = m_TPmap.find( transClassName );
215 if( tpItr == m_TPmap.end() ) {
216 REPORT_MESSAGE( MSG::ERROR )
217 << "Transient class " << transClassName
218 << " is not in the T/P Converter map";
219 static const std::string dummy( "" );
220 return dummy;
221 }
222
223 // Return the persistent class name:
224 return tpItr->second;
225}
226
227TClass *TrigSerTPTool::getClass( const std::string &cname ) const {
228
229 TClass *cl( 0 );
231 m_dictSvc->load_type( cname );
232 }
233 cl = TClass::GetClass( cname.c_str() );
234 return cl;
235}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
#define ATH_LIKELY(x)
Helpers for checking error return status codes and reporting errors.
#define REPORT_MESSAGE(LVL)
Report a message.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
MsgStream & msg() const
virtual const std::type_info & transientTInfo() const =0
return C++ type id of the transient class this converter is for
virtual void persToTransWithKeyUntyped(const void *pers, void *trans, const std::string &, MsgStream &msg)
Convert persistent object representation to transient.
Definition ITPCnvBase.h:53
virtual void transToPersUntyped(const void *trans, void *pers, MsgStream &msg)=0
Convert transient object representation to persistent.
virtual const std::type_info & persistentTInfo() const =0
return C++ type id of the persistent class this converter is for
std::vector< std::string > m_activeClasses
const std::string & persClassName(const std::string &transClassName) const
Get the name of the persistent class belonging to a transient one.
bool m_useAthDictLoader
CxxUtils::ClassName::Rules m_clNameRules
ServiceHandle< ITPCnvSvc > m_tpcnvsvc
ServiceHandle< IMessageSvc > m_msgsvcTP
ServiceHandle< IDictLoaderSvc > m_dictSvc
std::mutex m_convertersCacheMutex
std::unique_ptr< MsgStream > m_logTP
void * convertPT(const std::string &persName, void *pers, std::string &transName) const
Convert a persistent object to its transient self.
void * convertTP(const std::string &transName, void *trans, std::string &persName) const
Convert a transient object to its persistent self.
ITPCnvBase * getConverter(const std::string &persistent) const
std::map< std::string, std::string > m_TPmap
TClass * getClass(const std::string &clname) const
Get the ROOT dictionary for a type.
TrigSerTPTool(const std::string &type, const std::string &name, const IInterface *parent)
Standard AlgTool constructor.
virtual StatusCode initialize() override
Function initialising the tool.