ATLAS Offline Software
Loading...
Searching...
No Matches
TrigSerTPTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// ROOT include(s):
6#include <TClass.h>
7
8// Gaudi/Athena include(s):
9#include "GaudiKernel/System.h"
14
15// Local include(s):
17
18
20 const std::string& name,
21 const IInterface* parent) :
22 AthAlgTool( type, name, parent ),
23 m_dictSvc( "AthDictLoaderSvc", name ),
24 m_useAthDictLoader( true ),
25 m_tpcnvsvc( "AthTPCnvSvc", name ) {
26
27 declareInterface< TrigSerTPTool >( this );
28
29 declareProperty( "TPMap", m_TPmap, "map of T->P classes" );
30 declareProperty( "useAthDictLoader", m_useAthDictLoader,
31 "use AthDictLoaderSvc instead of plain ROOT" );
32}
33
35
36 // Greet the user:
37 ATH_MSG_INFO( "Initializing" );
38
39 // Retrieve the used services:
40 ATH_CHECK( m_dictSvc.retrieve() );
41 ATH_CHECK( m_tpcnvsvc.retrieve() );
42
43 /* When a P<->T conversion is requested, this tool makes a call to TClass::GetClass.
44 * The way it's done here can cause performance issues in some circumstances.
45 * For example, reading data16 RAW files trigger a P->T conversion from
46 * DataVector<xAOD::TauJet_v2> to DataVector<xAOD::TauJet_v3> in RAWtoALL/22.0.62.
47 * The problem is that the converter returns the full class name through
48 * ITPCnvBase::transientTInfo(), which in this case resolves into
49 * DataVector<xAOD::TauJet_v3,DataVector<xAOD::IParticle,DataModel_detail::NoBase> >
50 * Passing this directly to TClass::GetClass causes AutoLoading/HeaderParsing
51 * which notoriously allocates memory and never releases it. Here, we work
52 * around this problem by stripping the base class information from the name
53 * that's passed to TClass::GetClass, in this case simply DataVector<xAOD::TauJet_v3>
54 */
55 m_clNameRules.add("DataVector<$T, $B>", "DataVector<$T>");
56
57 return StatusCode::SUCCESS;
58}
59
60ITPCnvBase* TrigSerTPTool::getConverter( const std::string& persistent ) const
61{
62 std::lock_guard<std::mutex> lock(m_convertersCacheMutex);
63 ITPCnvBase* cnvtr = m_convertesCache[persistent];
64 if ( ATH_LIKELY( cnvtr ) )
65 return cnvtr;
66
67 // no converter, we need to find it, first the trigger specific one
68 cnvtr = m_tpcnvsvc->p2t_cnv( persistent, Athena::TPCnvType::Trigger );
69 if( ! cnvtr ) {
70 // If there is no such thing, try a generic one:
71 cnvtr = m_tpcnvsvc->p2t_cnv( persistent );
72 }
73 m_convertesCache[persistent] = cnvtr;
74 return cnvtr;
75}
76
77void* TrigSerTPTool::convertTP( const std::string &clname, void *ptr,
78 std::string &persName ) const
79{
80 ATH_MSG_DEBUG( "TrigSerTPTool::convertTP" );
81
82 //pers and persName set only after successful conversion
83 persName = "";
84 void *pers( 0 );
85
86 // Start by trying to find the correct persistent class from the TP map
87 // Otherwise, use the internal logic of the TPCnvSvc
88 const auto tpItr = m_TPmap.find( clname );
89 if( tpItr == m_TPmap.end() ) {
90 REPORT_MESSAGE( MSG::ERROR )
91 << "Transient class " << clname
92 << " is not in the T/P Converter map";
93 return 0;
94 }
95 persName = tpItr->second;
96
97 ITPCnvBase* cnvtr = getConverter( persName );
98 if( ! cnvtr ) {
99 ATH_MSG_ERROR( "T/P Converter for transient class " << tpItr->first
100 << " persistent class " << persName << " could not be retrieved");
101 return nullptr;
102 }
103
104 // Create a persistent object:
105 const std::string persname =
106 m_clNameRules.apply( System::typeinfoName( cnvtr->persistentTInfo() ) );
107 TClass *persObjCl = getClass( persname );
108 void *persptr( 0 );
109 if( persObjCl ) {
110 persptr = persObjCl->New();
111 ATH_MSG_DEBUG( "created object of " << persptr << " at " << persptr );
112 } else {
113 REPORT_MESSAGE( MSG::ERROR )
114 << "Couldn't find dictionary for type " << persname;
115 return 0;
116 }
117
118 // Do the conversion:
119 ATH_MSG_DEBUG( "invoking TP for " << clname << " at " << ptr );
120 try {
121 cnvtr->transToPersUntyped( ptr, persptr, msg() );
122 persName = std::move(persname);
123 pers = persptr;
124 ATH_MSG_DEBUG( "succeeded at " << persptr );
125 }
126 catch( const std::runtime_error& e ){
127
128 //delete persObjCl->New();
129 const std::string issue = e.what();
130 if( issue.find( "is deprecated" ) != std::string::npos ) {
131 ATH_MSG_INFO( "An exception " << e.what() );
132 } else {
133 pers = 0;
134 REPORT_MESSAGE( MSG::ERROR ) << "An exception occurred: " << e.what();
135 }
136 }
137
138 // Return the converted object:
139 return pers;
140}
141
142void* TrigSerTPTool::convertPT( const std::string &persName, void *pers,
143 std::string& transName ) const
144{
145 // First look for a trigger specific converter:
146 ITPCnvBase* cnvtr =
147 m_tpcnvsvc->p2t_cnv( persName, Athena::TPCnvType::Trigger );
148 if( ! cnvtr ) {
149 // If there is no such thing, try a generic one:
150 cnvtr = m_tpcnvsvc->p2t_cnv( persName );
151 }
152 if( ! cnvtr ) {
153 REPORT_MESSAGE( MSG::ERROR )
154 << "T/P Converter for persistent class "
155 << persName << " could not be retrieved";
156 return 0;
157 }
158
159 // Get the name of the transient class:
160 transName = m_clNameRules.apply( System::typeinfoName( cnvtr->transientTInfo() ) );
161
162 // Create the transient object:
163 TClass *transCl = getClass( transName );
164 void *trans( 0 );
165 if( transCl ){
166 trans = transCl->New();
167 ATH_MSG_DEBUG( "trans " << trans );
168 }
169
170 // Do the conversion:
171 ATH_MSG_DEBUG( "invoking PT for " << transName );
172 try {
173 cnvtr->persToTransWithKeyUntyped( pers, trans, "", msg() );
174 ATH_MSG_DEBUG( " succeeded at " << trans );
175 }
176 catch (const std::runtime_error& e){
177 REPORT_MESSAGE( MSG::ERROR ) << "An exception occurred: " << e.what();
178 //it should destruct trans here (is it in a good state?)
179 trans = 0;
180 }
181
182 // Return the converted object:
183 return trans;
184}
185
186const std::string&
187TrigSerTPTool::persClassName( const std::string& transClassName ) const {
188
189 // Try to extract from the TP map
190 const auto tpItr = m_TPmap.find( transClassName );
191 if( tpItr == m_TPmap.end() ) {
192 REPORT_MESSAGE( MSG::ERROR )
193 << "Transient class " << transClassName
194 << " is not in the T/P Converter map";
195 static const std::string dummy( "" );
196 return dummy;
197 }
198
199 // Return the persistent class name:
200 return tpItr->second;
201}
202
203TClass *TrigSerTPTool::getClass( const std::string &cname ) const {
204
205 TClass *cl( 0 );
207 m_dictSvc->load_type( cname );
208 }
209 cl = TClass::GetClass( cname.c_str() );
210 return cl;
211}
#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
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< IDictLoaderSvc > m_dictSvc
std::mutex m_convertersCacheMutex
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.