The Gaudi Framework  v40r0 (475e45c1)
RegistryEntry.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #include <GaudiKernel/DataObject.h>
15 #include <algorithm>
16 
17 // If you absolutely need optimization: switch off dynamic_cast.
18 // This improves access to the data store roughly by more than 10 %
19 // for balanced trees.
20 //
21 // M.Frank
22 //
23 #define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
24 // #define CAST_REGENTRY(x,y) (x)(y)
25 constexpr char SEPARATOR{ '/' };
26 
29  : m_path( std::move( path ) ), m_pParent( parent ) {
30  std::string::size_type sep = m_path.rfind( SEPARATOR );
31  if ( m_path.front() != SEPARATOR ) m_path.insert( 0, 1, SEPARATOR );
32  if ( sep != std::string::npos ) m_path.erase( 0, sep );
34  addRef();
35 }
36 
39  deleteElements();
40  if ( m_pObject ) {
41  if ( !m_isSoft ) m_pObject->setRegistry( nullptr );
42  m_pObject->release();
43  }
44  if ( m_pAddress ) {
45  if ( !m_isSoft ) m_pAddress->setRegistry( nullptr );
46  m_pAddress->release();
47  }
48 }
49 
52  unsigned long cnt = --m_refCount;
53  if ( !m_refCount ) delete this;
54  return cnt;
55 }
56 
59  m_pParent = pParent;
60  m_fullpath.clear();
61  assemblePath( m_fullpath );
62 }
63 
66  m_isSoft = true;
67  setObject( pObject );
68  // if ( 0 != m_pObject ) { // Useless: This justs sets my own address again...
69  // setAddress(m_pObject->address());
70  // }
71 }
72 
75  m_isSoft = true;
76  setAddress( pAddress );
77 }
78 
81  makeSoft( pObject );
82  m_isSoft = false;
83  if ( m_pObject ) m_pObject->setRegistry( this );
84  if ( m_pAddress ) m_pAddress->setRegistry( this );
85 }
86 
89  m_isSoft = false;
90  setAddress( pAddress );
91 }
92 
95  if ( pAddress ) {
96  pAddress->addRef();
97  pAddress->setRegistry( this );
98  }
99  if ( m_pAddress ) m_pAddress->release();
100  m_pAddress = pAddress;
101 }
102 
105  if ( pObject ) {
106  pObject->addRef();
107  if ( !isSoft() ) pObject->setRegistry( this );
108  }
109  if ( m_pObject ) m_pObject->release();
110  m_pObject = pObject;
111 }
112 
115  try {
116  RegistryEntry* pEntry = dynamic_cast<RegistryEntry*>( obj );
117  auto i = std::remove( std::begin( m_store ), std::end( m_store ), pEntry );
118  if ( i != std::end( m_store ) ) {
119  pEntry->release();
120  m_store.erase( i, std::end( m_store ) );
121  }
122  } catch ( ... ) {}
123  return m_store.size();
124 }
125 
128  if ( nam.front() == SEPARATOR ) nam.remove_prefix( 1 );
129  auto i = std::find_if( m_store.begin(), m_store.end(), [&]( const auto* entry ) {
130  // skip leading SEPARATOR
131  return entry->name().compare( 1, std::string::npos, nam.data(), nam.size() ) == 0;
132  } );
133  // if the requested object is not present, this is an error....
134  if ( i == m_store.end() ) return StatusCode::FAILURE;
135  remove( *i );
136  return StatusCode::SUCCESS;
137 }
138 
141  if ( nam.front() != SEPARATOR ) nam.insert( 0, 1, SEPARATOR );
142  // if this object is already present, this is an error....
143  auto not_present =
144  std::none_of( std::begin( m_store ), std::end( m_store ), [&]( IRegistry* i ) { return nam == i->name(); } );
145  return not_present ? new RegistryEntry( std::move( nam ), this ) : nullptr;
146 }
147 
150  RegistryEntry* pEntry = CAST_REGENTRY( RegistryEntry*, obj );
151  return i_add( pEntry );
152 }
153 
156  // TODO: if this is the sole place where items are added to m_store,
157  // and we know here that they must be RegisteryEntry, can we
158  // drop the dynamic_cast every where else???
159  // TODO: if so, can we also change m_store to be std::vector<RegistryEntry*>
160  // instead
161  // TODO: if so, can we not make it std::vector<RegistryEntry> instead?
162  // TODO: if so, should make sure that a RegistryEntry can be std::move'ed
163  try {
164  pEntry->setDataSvc( m_pDataProviderSvc );
165  m_store.push_back( pEntry );
166  pEntry->setParent( this );
167  if ( !pEntry->isSoft() && pEntry->address() ) { pEntry->address()->setRegistry( pEntry ); }
168  } catch ( ... ) {}
169  return m_store.size();
170 }
171 
173 StatusCode DataSvcHelpers::RegistryEntry::add( std::string name, DataObject* pObject, bool is_soft ) {
174  RegistryEntry* entry = i_create( std::move( name ) );
175  if ( !entry ) return StatusCode::FAILURE;
176  ( is_soft ) ? entry->makeSoft( pObject ) : entry->makeHard( pObject );
177  i_add( entry );
178  return StatusCode::SUCCESS;
179 }
180 
182 StatusCode DataSvcHelpers::RegistryEntry::add( std::string name, IOpaqueAddress* pAddress, bool is_soft ) {
183  RegistryEntry* entry = i_create( std::move( name ) );
184  if ( !entry ) return StatusCode::FAILURE;
185  ( is_soft ) ? entry->makeSoft( pAddress ) : entry->makeHard( pAddress );
186  i_add( entry );
187  return StatusCode::SUCCESS;
188 }
189 
192  for ( auto& i : m_store ) {
193  RegistryEntry* entry = CAST_REGENTRY( RegistryEntry*, i );
194  if ( entry ) {
195  entry->deleteElements();
196  entry->release();
197  }
198  }
199  m_store.erase( m_store.begin(), m_store.end() );
200  return 0;
201 }
202 
205  auto i = std::find( m_store.begin(), m_store.end(), obj );
206  return ( i != m_store.end() ) ? ( *i ) : nullptr;
207 }
208 
211  if ( path.front() == SEPARATOR ) path.remove_prefix( 1 ); // strip leading '/', if present
212  while ( !path.empty() ) {
213  // check that the chars of path prior to / are the same as regEnt->name()
214  // (i.e. match { nam:"/Ab" path:"/Ab/C"}
215  // but not { nam:"/Abc" path:"/Ab/C"})
216  auto loc1 = path.find( SEPARATOR );
217  auto cpath = path.substr( 0, loc1 );
218  if ( loc1 != std::string_view::npos ) {
219  path.remove_prefix( loc1 + 1 );
220  } else {
221  path = std::string_view{};
222  }
223  auto i = std::find_if( std::begin( m_store ), std::end( m_store ),
224  [&]( const auto& reg ) { return cpath == std::string_view{ reg->name() }.substr( 1 ); } );
225  if ( i != std::end( m_store ) ) {
226  RegistryEntry* regEnt = CAST_REGENTRY( RegistryEntry*, *i );
227  return path.empty() ? regEnt : regEnt->i_find( path );
228  }
229  // If this node is "/NodeA", this part allows to find "/NodeA/NodeB" as
230  // our "/NodeB" child.
231  if ( cpath != std::string_view{ m_path }.substr( 1 ) ) break;
232  }
233  return nullptr;
234 }
235 
238  if ( key ) {
239  if ( key == m_pObject ) return const_cast<RegistryEntry*>( this );
240  // Look in the immediate level:
241  RegistryEntry* result = CAST_REGENTRY( RegistryEntry*, i_find( key->registry() ) );
242  if ( result ) return result;
243  // Go levels down
244  for ( const auto& i : m_store ) {
245  try {
246  const RegistryEntry* entry = CAST_REGENTRY( RegistryEntry*, i );
247  result = entry->i_find( key );
248  if ( result ) return result;
249  } catch ( ... ) {}
250  }
251  }
252  return nullptr;
253 }
254 
255 // Traverse registry tree
257  bool go_down = pAgent->analyse( this, level );
258  StatusCode status;
259  if ( go_down ) {
260  for ( auto& i : m_store ) {
261  try {
262  RegistryEntry* entry = CAST_REGENTRY( RegistryEntry*, i );
263  entry->traverseTree( pAgent, level + 1 ).ignore();
264  } catch ( ... ) { status = StatusCode::FAILURE; }
265  }
266  }
267  return status;
268 }
269 
270 // Recursive helper to assemble the full path name of the entry
271 void DataSvcHelpers::RegistryEntry::assemblePath( std::string& buffer ) const {
272  if ( m_pParent ) m_pParent->assemblePath( buffer );
273  buffer += m_path;
274 }
DataObject::setRegistry
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:77
DataSvcHelpers::RegistryEntry::setAddress
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
Definition: RegistryEntry.cpp:94
DataSvcHelpers::RegistryEntry::i_add
long i_add(RegistryEntry *entry)
Internal method to add entries.
Definition: RegistryEntry.cpp:155
DataSvcHelpers::RegistryEntry::m_path
std::string m_path
Path name.
Definition: RegistryEntry.h:61
AtlasMCRecoFullPrecedenceDump.path
path
Definition: AtlasMCRecoFullPrecedenceDump.py:49
GaudiPartProp.decorators.std
std
Definition: decorators.py:32
DataSvcHelpers::RegistryEntry::setParent
void setParent(RegistryEntry *pParent)
Set new parent pointer.
Definition: RegistryEntry.cpp:58
DataSvcHelpers::RegistryEntry::isSoft
bool isSoft() const
Is the link soft or hard.
Definition: RegistryEntry.h:132
IOpaqueAddress::addRef
virtual unsigned long addRef()=0
Add reference to object.
IDataStoreAgent::analyse
virtual bool analyse(IRegistry *pObject, int level)=0
Analyse the data object.
IOpaqueAddress
Definition: IOpaqueAddress.h:28
DataSvcHelpers::RegistryEntry::makeHard
void makeHard(DataObject *pObject)
Initialize link as hard link.
Definition: RegistryEntry.cpp:80
IRegistry
Definition: IRegistry.h:29
DataSvcHelpers::RegistryEntry::i_find
IRegistry * i_find(const IRegistry *pDirectory) const
Internal method to retrieve data directory.
Definition: RegistryEntry.cpp:204
DataSvcHelpers::RegistryEntry::m_fullpath
std::string m_fullpath
String containing full path of the object (volatile)
Definition: RegistryEntry.h:59
DataSvcHelpers::RegistryEntry::addRef
unsigned long addRef() override
IInterface implementation: Dereference the object.
Definition: RegistryEntry.h:118
DataSvcHelpers::RegistryEntry::release
unsigned long release() override
IInterface implementation: Reference the object.
Definition: RegistryEntry.cpp:51
RegistryEntry.h
DataSvcHelpers::RegistryEntry::address
IOpaqueAddress * address() const override
Retrieve opaque storage address.
Definition: RegistryEntry.h:128
IRegistry::name
virtual const name_type & name() const =0
Name of the directory (or key)
Gaudi::Utils::begin
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Definition: AttribStringParser.h:135
StatusCode
Definition: StatusCode.h:64
IOpaqueAddress.h
DataSvcHelpers::RegistryEntry::remove
StatusCode remove(std::string_view name)
Remove an entry from the store.
Definition: RegistryEntry.cpp:127
DataSvcHelpers::RegistryEntry::setObject
void setObject(DataObject *obj)
Set/Update object address.
Definition: RegistryEntry.cpp:104
CAST_REGENTRY
#define CAST_REGENTRY(x, y)
Definition: RegistryEntry.cpp:23
DataSvcHelpers::RegistryEntry::assemblePath
void assemblePath(std::string &buffer) const
The following entries serve two aspects: 1) They are faster for recursive calls, because they are non...
Definition: RegistryEntry.cpp:271
DataSvcHelpers::RegistryEntry::setDataSvc
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:94
gaudirun.level
level
Definition: gaudirun.py:364
StatusCode::ignore
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition: StatusCode.h:139
SEPARATOR
constexpr char SEPARATOR
Definition: RegistryEntry.cpp:25
DataSvcHelpers::RegistryEntry::makeSoft
void makeSoft(DataObject *pObject)
Initialize link as soft link.
Definition: RegistryEntry.cpp:65
DataSvcHelpers::RegistryEntry::RegistryEntry
RegistryEntry(std::string path, RegistryEntry *parent=nullptr)
Standard Constructor.
Definition: RegistryEntry.cpp:28
IOpaqueAddress::setRegistry
virtual void setRegistry(IRegistry *r)=0
Update directory pointer.
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:99
DataObject.h
DataSvcHelpers::RegistryEntry
Definition: RegistryEntry.h:41
DataSvcHelpers::RegistryEntry::deleteElements
long deleteElements()
Delete all contained elements.
Definition: RegistryEntry.cpp:191
DataSvcHelpers::RegistryEntry::add
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
Definition: RegistryEntry.cpp:173
DataObject
Definition: DataObject.h:37
IOTest.end
end
Definition: IOTest.py:125
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:100
DataSvcHelpers::RegistryEntry::i_create
RegistryEntry * i_create(std::string name)
Internal method to create entries.
Definition: RegistryEntry.cpp:140
DataSvcHelpers::RegistryEntry::traverseTree
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
Definition: RegistryEntry.cpp:256
ProduceConsume.key
key
Definition: ProduceConsume.py:84
IDataStoreAgent.h
DataObject::addRef
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:63
DataSvcHelpers::RegistryEntry::~RegistryEntry
~RegistryEntry() override
Standard Destructor.
Definition: RegistryEntry.cpp:38
IDataStoreAgent
Definition: IDataStoreAgent.h:24