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