ATLAS Offline Software
Loading...
Searching...
No Matches
AuxStoreWrapper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5// $Id: AuxStoreWrapper.cxx 695881 2015-09-21 08:47:05Z will $
6
7// Gaudi/Athena include(s):
8#include "SGTools/DataProxy.h"
11
12// EDM include(s):
19
20// xAOD include(s):
23
24// Local include(s):
25#include "AuxStoreWrapper.h"
26
27namespace {
28
30 template< typename T >
31 MsgStream& operator<< ( MsgStream& out,
32 const std::vector< T >& vec ) {
33
34 out << "[";
35 for( size_t i = 0; i < vec.size(); ++i ) {
36 out << vec[ i ];
37 if( i < ( vec.size() - 1 ) ) {
38 out << ", ";
39 }
40 }
41 out << "]";
42 return out;
43 }
44
45} // private namespace
46
47namespace xAODMaker {
48
49 AuxStoreWrapper::AuxStoreWrapper( const std::string& name,
50 ISvcLocator* svcLoc )
51 : AthAlgorithm( name, svcLoc ), m_cachesSet( false ),
52 m_clidSvc( "ClassIDSvc", name ) {
53
54 declareProperty( "SGKeys", m_keys,
55 "StoreGate keys of the store objects to be wrapped" );
56 declareProperty( "ClassIDSvc", m_clidSvc, "Service providing CLID info" );
57 }
58
60
61 ATH_MSG_INFO( "Initialising" );
62 ATH_MSG_DEBUG( " StoreGate keys: " << m_keys );
63
64 // Retrieve the needed component(s):
65 ATH_CHECK( m_clidSvc.retrieve() );
66
67 // Pack the SG keys into a structure that's more efficient during
68 // event processing:
69 m_keysSet.insert( m_keys.begin(), m_keys.end() );
70
71 // Reset the caches:
72 m_cachesSet = false;
73 m_toConvert.clear();
74 m_clids.clear();
75
76 // Return gracefully:
77 return StatusCode::SUCCESS;
78 }
79
81
82 // The StoreGate content before the object wrapping:
83 ATH_MSG_VERBOSE( "Event store before wrapping:\n" << evtStore()->dump() );
84
85 // If we don't have a list of keys to be converted yet, get one now:
86 if( ! m_cachesSet ) {
87
88 // Ask StoreGate for all the objects that it's holding on to:
89 const std::vector< const SG::DataProxy* > proxies =
90 evtStore()->proxies();
91
92 // Loop over them:
93 for( const SG::DataProxy* proxy : proxies ) {
94
95 ATH_MSG_VERBOSE( "Evaluating object with name \"" << proxy->name()
96 << "\" and CLID " << proxy->clID() );
97
98 // Check if we need to worry about this object:
99 if( !m_keysSet.empty() ) {
100 if( m_keysSet.find( proxy->name() ) == m_keysSet.end() ) {
101 // This SG key was not mentioned in the jobOptions...
102 ATH_MSG_VERBOSE( "Conversion for this key was not "
103 "requested" );
104 // But if this is a proxy for an interface container for which
105 // we wrap the auxiliary container, then let's remember it.
106 if( m_keysSet.find( proxy->name() + "Aux." ) !=
107 m_keysSet.end() ) {
108 std::string typeName;
109 ATH_CHECK( m_clidSvc->getTypeNameOfID( proxy->clID(),
110 typeName ) );
111 if( typeName.compare( 0, 6, "xAOD::" ) == 0) {
112 m_clids[ proxy->name() ] = proxy->clID();
113 }
114 }
115 continue;
116 }
117 }
118 ATH_MSG_VERBOSE( "The wrapping of this object was requested" );
119
120 // Remember the CLID of this type, if it's an xAOD type:
121 std::string typeName;
122 ATH_CHECK( m_clidSvc->getTypeNameOfID( proxy->clID(),
123 typeName ) );
124 if( ( typeName.compare( 0, 6 , "xAOD::") == 0) &&
125 ( typeName != "xAOD::ByteStreamAuxContainer_v1" ) ) {
126 m_clids[ proxy->name() ] = proxy->clID();
127 }
128
129 // Check if the key of the object looks like it is an auxiliary
130 // store. (To try to avoid unnecessary warnings.)
131 if( proxy->name().find( "Aux." ) !=
132 ( proxy->name().size() - 4 ) ) {
133 ATH_MSG_VERBOSE( "Key doesn't look like that of an auxiliary "
134 << "store" );
135 continue;
136 }
137 ATH_MSG_VERBOSE( "StoreGate key looks like that of an auxiliary "
138 << "store..." );
139
140 // This object/container will be converted:
141 m_toConvert.insert( proxy->name() );
142 }
143
144 // The caches are now set:
145 m_cachesSet = true;
146 }
147
148 // Now do the wrapping on the selected objects/containers:
149 for( const std::string& name : m_toConvert ) {
150
151 // Tell the user what's happening:
152 ATH_MSG_VERBOSE( "Now wrapping object: " << name );
153
154 // Access the object with an SG::IAuxStore pointer:
155 const SG::IAuxStore* original = nullptr;
156 if( ! evtStore()->retrieve( original, name ).isSuccess() ) {
157 ATH_MSG_WARNING( "Couldn't retrieve object \"" << name << "\" "
158 << "with interface SG::IAuxStore" );
159 continue;
160 }
161
162 // Check if the object implements the IAuxStoreHolder interface
163 // as well.
164 const SG::IAuxStoreHolder* holder =
165 dynamic_cast< const SG::IAuxStoreHolder* >( original );
166 if( ! holder ) {
167 // If not, let's just assume that it describes a container.
168 CHECK( changeContainer( original, name ) );
169 continue;
170 }
171
172 // Decide how to replace it exactly:
174 CHECK( changeElement( original, name ) );
175 } else {
176 CHECK( changeContainer( original, name ) );
177 }
178 }
179
180 // The StoreGate content before the object wrapping:
181 ATH_MSG_VERBOSE( "Event store after wrapping:\n" << evtStore()->dump() );
182
183 // Return gracefully:
184 return StatusCode::SUCCESS;
185 }
186
188 const std::string& name ) {
189
190 // Make StoreGate forget about this object:
191 auto aux_clid_itr = m_clids.find( name );
192 if( aux_clid_itr == m_clids.end() ) {
193 ATH_MSG_FATAL( "Didn't find a CLID for key: " << name );
194 ATH_MSG_FATAL( "This is an internal logic error" );
195 return StatusCode::FAILURE;
196 }
197 evtStore()->releaseObject( aux_clid_itr->second, name );
198 ATH_MSG_VERBOSE( "Released object with CLID " << aux_clid_itr->second
199 << " and name \"" << name << "\"" );
200
201 // Get the pointer for the proxy of the auxiliary store:
202 SG::DataProxy* storeProxy =
204 if( ! storeProxy ) {
205 ATH_MSG_FATAL( "Couldn't get proxy for the "
206 "SG::IAuxStore base class of: " << name );
207 return StatusCode::FAILURE;
208 }
209 // Now make StoreGate forget about this proxy completely:
210 CHECK( evtStore()->removeProxy( storeProxy, nullptr, true ) );
211
212 // Create the new object as a wrapper around the original:
214 holder->setStore( const_cast< SG::IAuxStore* >( store ) );
215
216 // Record the new container with the same key:
217 CHECK( evtStore()->overwrite( holder, name, false, true ) );
218
219 ATH_MSG_DEBUG( "Overwrote store object with key \""
220 << name << "\" with an xAOD::AuxContainerBase "
221 << "object" );
222
223 // The key of the interface container:
224 const std::string intName = name.substr( 0, name.size() - 4 );
225
226 // The CLID for the interface container:
227 CLID intId = 0;
228 auto clid_itr = m_clids.find( intName );
229 if( clid_itr == m_clids.end() ) {
230 ATH_MSG_WARNING( "Didn't cache a CLID for key: " << intName );
231 ATH_MSG_WARNING( "Interface container can't be updated, the job will "
232 "likely crash" );
233 return StatusCode::SUCCESS;
234 }
235 intId = clid_itr->second;
236
237 // Try to access the proxy for the interface container:
238 SG::DataProxy* proxy = evtStore()->proxy( intId, intName );
239 if( ! proxy ) {
240 // If there is none, return at this point:
241 ATH_MSG_VERBOSE( "Interface container with key \"" << intName
242 << "\" not available" );
243 return StatusCode::SUCCESS;
244 }
245
246 // Get the raw pointer to the object:
247 void* ptr = SG::DataProxy_cast( proxy, intId );
248 if( ! ptr ) {
249 REPORT_ERROR( StatusCode::FAILURE )
250 << "Couldn't retrieve raw pointer to interface container";
251 return StatusCode::FAILURE;
252 }
253
254 // Since all the "wrapped" objects should be xAOD objects, for which
255 // the interface containers all implement a straight inheritance tree
256 // back to SG::AuxVectorBase, the following ugly operation should be
257 // safe:
258 SG::AuxVectorBase* interface =
259 reinterpret_cast< SG::AuxVectorBase* >( ptr );
260
261 // And now connect the interface to the store depending on the const-ness
262 // of the interface:
263 if( proxy->isConst() ) {
264 interface->setConstStore( holder );
265 } else {
266 interface->setStore( holder );
267 }
268
269 ATH_MSG_DEBUG( "Interface container with key \"" << intName
270 << "\" updated" );
271
272 // Return gracefully:
273 return StatusCode::SUCCESS;
274 }
275
277 const std::string& name ) {
278
279 // Make StoreGate forget about this object:
280 auto aux_clid_itr = m_clids.find( name );
281 if( aux_clid_itr == m_clids.end() ) {
282 ATH_MSG_FATAL( "Didn't find a CLID for key: " << name );
283 ATH_MSG_FATAL( "This is an internal logic error" );
284 return StatusCode::FAILURE;
285 }
286 evtStore()->releaseObject( aux_clid_itr->second, name );
287 ATH_MSG_VERBOSE( "Released object with CLID " << aux_clid_itr->second
288 << " and name \"" << name << "\"" );
289
290 // Create the new as a wrapper around the original:
291 xAOD::AuxInfoBase* holder = new xAOD::AuxInfoBase();
292 holder->setStore( const_cast< SG::IAuxStore* >( store ) );
293
294 // Record the new container with a different key:
295 CHECK( evtStore()->overwrite( holder, name, false, true ) );
296
297 ATH_MSG_DEBUG( "Wrapped store object with key \""
298 << name << "\" into xAOD::AuxInfoBase "
299 << "object" );
300
301 // The key of the interface object:
302 const std::string intName = name.substr( 0, name.size() - 4 );
303
304 // The CLID for the interface object:
305 CLID intId = 0;
306 auto clid_itr = m_clids.find( intName );
307 if( clid_itr == m_clids.end() ) {
308 ATH_MSG_WARNING( "Didn't cache a CLID for key: " << intName );
309 ATH_MSG_WARNING( "Interface object can't be updated, the job will "
310 "likely crash" );
311 return StatusCode::SUCCESS;
312 }
313 intId = clid_itr->second;
314
315 // Try to access the proxy for the interface object:
316 SG::DataProxy* proxy = evtStore()->proxy( intId, intName );
317 if( ! proxy ) {
318 // If there is none, return at this point:
319 ATH_MSG_VERBOSE( "Interface object with key \"" << intName
320 << "\" not available" );
321 return StatusCode::SUCCESS;
322 }
323
324 // Get the raw pointer to the object:
325 void* ptr = SG::DataProxy_cast( proxy, intId );
326 if( ! ptr ) {
327 REPORT_ERROR( StatusCode::FAILURE )
328 << "Couldn't retrieve raw pointer to interface object";
329 return StatusCode::FAILURE;
330 }
331
332 // Since all the "wrapped" objects should be xAOD objects, for which
333 // the interface objects all implement a straight inheritance tree
334 // back to SG::AuxElement, the following ugly operation should be
335 // safe:
336 SG::AuxElement* interface =
337 reinterpret_cast< SG::AuxElement* >( ptr );
338
339 // And now connect the interface to the store depending on the const-ness
340 // of the interface:
341 if( proxy->isConst() ) {
342 interface->setConstStore( holder );
343 } else {
344 interface->setStore( holder );
345 }
346
347 ATH_MSG_DEBUG( "Interface object with key \"" << intName
348 << "\" updated" );
349
350 // Return gracefully:
351 return StatusCode::SUCCESS;
352 }
353
354} // namespace xAODMaker
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Base class for elements of a container that can have aux data.
Handle mappings between names and auxid_t.
Manage index tracking and synchronization of auxiliary data.
std::vector< size_t > vec
a traits class that associates a CLID to a type T It also detects whether T inherits from Gaudi DataO...
Helpers for checking error return status codes and reporting errors.
#define REPORT_ERROR(SC)
Report an error.
#define CHECK(...)
Evaluate an expression and check for errors.
uint32_t CLID
The Class ID type.
Interface for non-const operations on an auxiliary store.
Interface for const operations on an auxiliary store.
if(febId1==febId2)
std::ostream & operator<<(std::ostream &lhs, const TestGaudiProperty &rhs)
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Base class for elements of a container that can have aux data.
Definition AuxElement.h:483
Manage index tracking and synchronization of auxiliary data.
Interface for objects taking part in direct ROOT I/O.
@ AST_ObjectStore
The store describes a single object.
virtual AuxStoreType getStoreType() const =0
Return the type of the store object.
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:48
bool m_cachesSet
Flag specifying whether the internal caches were set already.
StatusCode changeContainer(const SG::IAuxStore *store, const std::string &name)
Create a new container store.
AuxStoreWrapper(const std::string &name, ISvcLocator *svcLoc)
Regular Algorithm constructor.
virtual StatusCode initialize()
Function initialising the algorithm.
std::map< std::string, CLID > m_clids
Keys and CLIDs of the interface containers touched.
std::vector< std::string > m_keys
StoreGate keys of the store objects to be wrapped.
virtual StatusCode execute()
Function executing the algorithm.
std::set< std::string > m_keysSet
Keys of the objects to be wrapped, in a set container.
std::set< std::string > m_toConvert
Keys of the auxiliary stores that need to be converted in the end.
StatusCode changeElement(const SG::IAuxStore *store, const std::string &name)
Create a new element store.
ServiceHandle< ::IClassIDSvc > m_clidSvc
Handle to the Class ID service.
Common base class for the auxiliary containers.
virtual void setStore(SG::IAuxStore *store) override
Set a different internal store object.
Common base class for auxiliary info objects.
Definition AuxInfoBase.h:45
virtual void setStore(SG::IAuxStore *store) override
Set a different internal store object.
Forward declaration.
DATA * DataProxy_cast(DataProxy *proxy)
cast the proxy into the concrete data object it proxies
-event-from-file