ATLAS Offline Software
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):
22 #include "xAODCore/AuxInfoBase.h"
23 
24 // Local include(s):
25 #include "AuxStoreWrapper.h"
26 
27 namespace {
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 
47 namespace xAODMaker {
48 
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
xAOD::AuxInfoBase
Common base class for auxiliary info objects.
Definition: AuxInfoBase.h:49
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::AuxContainerBase::setStore
virtual void setStore(SG::IAuxStore *store) override
Set a different internal store object.
Definition: AuxContainerBase.cxx:194
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:69
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
REPORT_ERROR
#define REPORT_ERROR(SC)
Report an error.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:355
IAuxStoreHolder.h
StateLessPT_NewConfig.proxy
proxy
Definition: StateLessPT_NewConfig.py:392
SG::IAuxStoreHolder::getStoreType
virtual AuxStoreType getStoreType() const =0
Return the type of the store object.
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
SG::AuxElement
Base class for elements of a container that can have aux data.
Definition: AuxElement.h:446
AuxInfoBase.h
AuxContainerBase.h
xAOD::AuxContainerBase
Common base class for the auxiliary containers.
Definition: AuxContainerBase.h:59
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
xAODMaker::AuxStoreWrapper::AuxStoreWrapper
AuxStoreWrapper(const std::string &name, ISvcLocator *svcLoc)
Regular Algorithm constructor.
Definition: AuxStoreWrapper.cxx:49
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
xAODMaker
Definition: StoreGateSvc.h:72
AuxVectorBase.h
Manage index tracking and synchronization of auxiliary data.
xAODMaker::AuxStoreWrapper::m_keysSet
std::set< std::string > m_keysSet
Keys of the objects to be wrapped, in a set container.
Definition: AuxStoreWrapper.h:63
SG::AuxVectorBase
Manage index tracking and synchronization of auxiliary data.
Definition: AuxVectorBase.h:98
xAODMaker::AuxStoreWrapper::changeContainer
StatusCode changeContainer(const SG::IAuxStore *store, const std::string &name)
Create a new container store.
Definition: AuxStoreWrapper.cxx:187
AthCommonDataStore< AthCommonMsg< Algorithm > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
xAODMaker::AuxStoreWrapper::m_clids
std::map< std::string, CLID > m_clids
Keys and CLIDs of the interface containers touched.
Definition: AuxStoreWrapper.h:70
lumiFormat.i
int i
Definition: lumiFormat.py:92
ClassID_traits.h
a traits class that associates a CLID to a type T It also detects whether T inherits from Gaudi DataO...
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
ClassID_traits
Default, invalid implementation of ClassID_traits.
Definition: Control/AthenaKernel/AthenaKernel/ClassID_traits.h:40
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
xAODMaker::AuxStoreWrapper::m_toConvert
std::set< std::string > m_toConvert
Keys of the auxiliary stores that need to be converted in the end.
Definition: AuxStoreWrapper.h:68
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
AthAlgorithm
Definition: AthAlgorithm.h:47
xAODMaker::AuxStoreWrapper::changeElement
StatusCode changeElement(const SG::IAuxStore *store, const std::string &name)
Create a new element store.
Definition: AuxStoreWrapper.cxx:276
xAOD::AuxInfoBase::setStore
virtual void setStore(SG::IAuxStore *store) override
Set a different internal store object.
Definition: AuxInfoBase.cxx:160
SG::DataProxy_cast
DATA * DataProxy_cast(DataProxy *proxy)
cast the proxy into the concrete data object it proxies
xAODMaker::AuxStoreWrapper::m_clidSvc
ServiceHandle< ::IClassIDSvc > m_clidSvc
Handle to the Class ID service.
Definition: AuxStoreWrapper.h:73
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
errorcheck.h
Helpers for checking error return status codes and reporting errors.
xAODMaker::AuxStoreWrapper::m_cachesSet
bool m_cachesSet
Flag specifying whether the internal caches were set already.
Definition: AuxStoreWrapper.h:66
operator<<
std::ostream & operator<<(std::ostream &lhs, const TestGaudiProperty &rhs)
Definition: TestGaudiProperty.cxx:69
SG::IAuxStore
Interface for non-const operations on an auxiliary store.
Definition: IAuxStore.h:48
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
IAuxStore.h
Interface for non-const operations on an auxiliary store.
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
xAODMaker::AuxStoreWrapper::m_keys
std::vector< std::string > m_keys
StoreGate keys of the store objects to be wrapped.
Definition: AuxStoreWrapper.h:61
xAODMaker::AuxStoreWrapper::initialize
virtual StatusCode initialize()
Function initialising the algorithm.
Definition: AuxStoreWrapper.cxx:59
IConstAuxStore.h
Interface for const operations on an auxiliary store.
SG::DataProxy
Definition: DataProxy.h:44
SG::IAuxStoreHolder::AST_ObjectStore
@ AST_ObjectStore
The store describes a single object.
Definition: IAuxStoreHolder.h:67
SG::IAuxStoreHolder
Interface for objects taking part in direct ROOT I/O.
Definition: IAuxStoreHolder.h:36
FourMomUtils::dump
std::ostream & dump(std::ostream &out, const I4MomIter iBeg, const I4MomIter iEnd)
Helper to stream out a range of I4Momentum objects.
Definition: P4Dumper.h:24
AuxElement.h
Base class for elements of a container that can have aux data.
AuxStoreWrapper.h
DataProxy.h
xAODMaker::AuxStoreWrapper::execute
virtual StatusCode execute()
Function executing the algorithm.
Definition: AuxStoreWrapper.cxx:80