The Gaudi Framework  master (37c0b60a)
RegistryEntry.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 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 //====================================================================
12 // RegistryEntry.cpp
13 //--------------------------------------------------------------------
14 //
15 // Package : DataSvc ( The LHCb Offline System)
16 //
17 // Description: implementation of the Transient data store
18 //
19 // Author : M.Frank
20 // History :
21 // +---------+----------------------------------------------+---------
22 // | Date | Comment | Who
23 // +---------+----------------------------------------------+---------
24 // | 29/10/98| Initial version | MF
25 // | 03/02/99| Protect dynamic_cast with try-catch clauses | MF
26 // +---------+----------------------------------------------+---------
27 //
28 //====================================================================
29 #define DATASVC_REGISTRYENTRY_CPP
30 
31 // STL include files
32 #include <algorithm>
33 
34 // Interfaces
37 
38 // Framework include files
39 #include <GaudiKernel/DataObject.h>
41 
42 // If you absolutely need optimization: switch off dynamic_cast.
43 // This improves access to the data store roughly by more than 10 %
44 // for balanced trees.
45 //
46 // M.Frank
47 //
48 #define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
49 // #define CAST_REGENTRY(x,y) (x)(y)
50 constexpr char SEPARATOR{ '/' };
51 
54  : m_path( std::move( path ) ), m_pParent( parent ) {
55  std::string::size_type sep = m_path.rfind( SEPARATOR );
56  if ( m_path.front() != SEPARATOR ) m_path.insert( 0, 1, SEPARATOR );
57  if ( sep != std::string::npos ) m_path.erase( 0, sep );
59  addRef();
60 }
61 
64  deleteElements();
65  if ( m_pObject ) {
66  if ( !m_isSoft ) m_pObject->setRegistry( nullptr );
67  m_pObject->release();
68  }
69  if ( m_pAddress ) {
70  if ( !m_isSoft ) m_pAddress->setRegistry( nullptr );
71  m_pAddress->release();
72  }
73 }
74 
77  unsigned long cnt = --m_refCount;
78  if ( !m_refCount ) delete this;
79  return cnt;
80 }
81 
84  m_pParent = pParent;
85  m_fullpath.clear();
86  assemblePath( m_fullpath );
87 }
88 
91  m_isSoft = true;
92  setObject( pObject );
93  // if ( 0 != m_pObject ) { // Useless: This justs sets my own address again...
94  // setAddress(m_pObject->address());
95  // }
96 }
97 
100  m_isSoft = true;
101  setAddress( pAddress );
102 }
103 
106  makeSoft( pObject );
107  m_isSoft = false;
108  if ( m_pObject ) m_pObject->setRegistry( this );
109  if ( m_pAddress ) m_pAddress->setRegistry( this );
110 }
111 
114  m_isSoft = false;
115  setAddress( pAddress );
116 }
117 
120  if ( pAddress ) {
121  pAddress->addRef();
122  pAddress->setRegistry( this );
123  }
124  if ( m_pAddress ) m_pAddress->release();
125  m_pAddress = pAddress;
126 }
127 
130  if ( pObject ) {
131  pObject->addRef();
132  if ( !isSoft() ) pObject->setRegistry( this );
133  }
134  if ( m_pObject ) m_pObject->release();
135  m_pObject = pObject;
136 }
137 
140  try {
141  RegistryEntry* pEntry = dynamic_cast<RegistryEntry*>( obj );
142  auto i = std::remove( std::begin( m_store ), std::end( m_store ), pEntry );
143  if ( i != std::end( m_store ) ) {
144  pEntry->release();
145  m_store.erase( i, std::end( m_store ) );
146  }
147  } catch ( ... ) {}
148  return m_store.size();
149 }
150 
153  if ( nam.front() == SEPARATOR ) nam.remove_prefix( 1 );
154  auto i = std::find_if( m_store.begin(), m_store.end(), [&]( const auto* entry ) {
155  // skip leading SEPARATOR
156  return entry->name().compare( 1, std::string::npos, nam.data(), nam.size() ) == 0;
157  } );
158  // if the requested object is not present, this is an error....
159  if ( i == m_store.end() ) return StatusCode::FAILURE;
160  remove( *i );
161  return StatusCode::SUCCESS;
162 }
163 
166  if ( nam.front() != SEPARATOR ) nam.insert( 0, 1, SEPARATOR );
167  // if this object is already present, this is an error....
168  auto not_present =
169  std::none_of( std::begin( m_store ), std::end( m_store ), [&]( IRegistry* i ) { return nam == i->name(); } );
170  return not_present ? new RegistryEntry( std::move( nam ), this ) : nullptr;
171 }
172 
175  RegistryEntry* pEntry = CAST_REGENTRY( RegistryEntry*, obj );
176  return i_add( pEntry );
177 }
178 
181  // TODO: if this is the sole place where items are added to m_store,
182  // and we know here that they must be RegisteryEntry, can we
183  // drop the dynamic_cast every where else???
184  // TODO: if so, can we also change m_store to be std::vector<RegistryEntry*>
185  // instead
186  // TODO: if so, can we not make it std::vector<RegistryEntry> instead?
187  // TODO: if so, should make sure that a RegistryEntry can be std::move'ed
188  try {
189  pEntry->setDataSvc( m_pDataProviderSvc );
190  m_store.push_back( pEntry );
191  pEntry->setParent( this );
192  if ( !pEntry->isSoft() && pEntry->address() ) { pEntry->address()->setRegistry( pEntry ); }
193  } catch ( ... ) {}
194  return m_store.size();
195 }
196 
199  RegistryEntry* entry = i_create( std::move( name ) );
200  if ( !entry ) return StatusCode::FAILURE;
201  ( is_soft ) ? entry->makeSoft( pObject ) : entry->makeHard( pObject );
202  i_add( entry );
203  return StatusCode::SUCCESS;
204 }
205 
208  RegistryEntry* entry = i_create( std::move( name ) );
209  if ( !entry ) return StatusCode::FAILURE;
210  ( is_soft ) ? entry->makeSoft( pAddress ) : entry->makeHard( pAddress );
211  i_add( entry );
212  return StatusCode::SUCCESS;
213 }
214 
217  for ( auto& i : m_store ) {
218  RegistryEntry* entry = CAST_REGENTRY( RegistryEntry*, i );
219  if ( entry ) {
220  entry->deleteElements();
221  entry->release();
222  }
223  }
224  m_store.erase( m_store.begin(), m_store.end() );
225  return 0;
226 }
227 
230  auto i = std::find( m_store.begin(), m_store.end(), obj );
231  return ( i != m_store.end() ) ? ( *i ) : nullptr;
232 }
233 
236  if ( path.front() == SEPARATOR ) path.remove_prefix( 1 ); // strip leading '/', if present
237  while ( !path.empty() ) {
238  // check that the chars of path prior to / are the same as regEnt->name()
239  // (i.e. match { nam:"/Ab" path:"/Ab/C"}
240  // but not { nam:"/Abc" path:"/Ab/C"})
241  auto loc1 = path.find( SEPARATOR );
242  auto cpath = path.substr( 0, loc1 );
243  if ( loc1 != std::string_view::npos ) {
244  path.remove_prefix( loc1 + 1 );
245  } else {
246  path = std::string_view{};
247  }
248  auto i = std::find_if( std::begin( m_store ), std::end( m_store ),
249  [&]( const auto& reg ) { return cpath == std::string_view{ reg->name() }.substr( 1 ); } );
250  if ( i != std::end( m_store ) ) {
251  RegistryEntry* regEnt = CAST_REGENTRY( RegistryEntry*, *i );
252  return path.empty() ? regEnt : regEnt->i_find( path );
253  }
254  // If this node is "/NodeA", this part allows to find "/NodeA/NodeB" as
255  // our "/NodeB" child.
256  if ( cpath != std::string_view{ m_path }.substr( 1 ) ) break;
257  }
258  return nullptr;
259 }
260 
263  if ( key ) {
264  if ( key == m_pObject ) return const_cast<RegistryEntry*>( this );
265  // Look in the immediate level:
266  RegistryEntry* result = CAST_REGENTRY( RegistryEntry*, i_find( key->registry() ) );
267  if ( result ) return result;
268  // Go levels down
269  for ( const auto& i : m_store ) {
270  try {
271  const RegistryEntry* entry = CAST_REGENTRY( RegistryEntry*, i );
272  result = entry->i_find( key );
273  if ( result ) return result;
274  } catch ( ... ) {}
275  }
276  }
277  return nullptr;
278 }
279 
280 // Traverse registry tree
282  bool go_down = pAgent->analyse( this, level );
283  StatusCode status;
284  if ( go_down ) {
285  for ( auto& i : m_store ) {
286  try {
287  RegistryEntry* entry = CAST_REGENTRY( RegistryEntry*, i );
288  entry->traverseTree( pAgent, level + 1 ).ignore();
289  } catch ( ... ) { status = StatusCode::FAILURE; }
290  }
291  }
292  return status;
293 }
294 
295 // Recursive helper to assemble the full path name of the entry
297  if ( m_pParent ) m_pParent->assemblePath( buffer );
298  buffer += m_path;
299 }
DataObject::setRegistry
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:76
DataSvcHelpers::RegistryEntry::setAddress
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
Definition: RegistryEntry.cpp:119
DataSvcHelpers::RegistryEntry::i_add
long i_add(RegistryEntry *entry)
Internal method to add entries.
Definition: RegistryEntry.cpp:180
std::string
STL class.
DataSvcHelpers::RegistryEntry::m_path
std::string m_path
Path name.
Definition: RegistryEntry.h:66
std::move
T move(T... args)
AtlasMCRecoFullPrecedenceDump.path
path
Definition: AtlasMCRecoFullPrecedenceDump.py:49
DataSvcHelpers::RegistryEntry::setParent
void setParent(RegistryEntry *pParent)
Set new parent pointer.
Definition: RegistryEntry.cpp:83
DataSvcHelpers::RegistryEntry::isSoft
bool isSoft() const
Is the link soft or hard.
Definition: RegistryEntry.h:137
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:33
std::find_if
T find_if(T... args)
DataSvcHelpers::RegistryEntry::makeHard
void makeHard(DataObject *pObject)
Initialize link as hard link.
Definition: RegistryEntry.cpp:105
IRegistry
Definition: IRegistry.h:32
std::none_of
T none_of(T... args)
DataSvcHelpers::RegistryEntry::i_find
IRegistry * i_find(const IRegistry *pDirectory) const
Internal method to retrieve data directory.
Definition: RegistryEntry.cpp:229
DataSvcHelpers::RegistryEntry::m_fullpath
std::string m_fullpath
String containing full path of the object (volatile)
Definition: RegistryEntry.h:64
DataSvcHelpers::RegistryEntry::addRef
unsigned long addRef() override
IInterface implementation: Dereference the object.
Definition: RegistryEntry.h:123
DataSvcHelpers::RegistryEntry::release
unsigned long release() override
IInterface implementation: Reference the object.
Definition: RegistryEntry.cpp:76
std::string::front
T front(T... args)
RegistryEntry.h
DataSvcHelpers::RegistryEntry::address
IOpaqueAddress * address() const override
Retrieve opaque storage address.
Definition: RegistryEntry.h:133
IRegistry::name
virtual const name_type & name() const =0
Name of the directory (or key)
StatusCode
Definition: StatusCode.h:65
IOpaqueAddress.h
DataSvcHelpers::RegistryEntry::remove
StatusCode remove(std::string_view name)
Remove an entry from the store.
Definition: RegistryEntry.cpp:152
DataSvcHelpers::RegistryEntry::setObject
void setObject(DataObject *obj)
Set/Update object address.
Definition: RegistryEntry.cpp:129
CAST_REGENTRY
#define CAST_REGENTRY(x, y)
Definition: RegistryEntry.cpp:48
std::string::erase
T erase(T... args)
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:296
std::remove
T remove(T... args)
DataSvcHelpers::RegistryEntry::setDataSvc
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:99
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:50
DataSvcHelpers::RegistryEntry::makeSoft
void makeSoft(DataObject *pObject)
Initialize link as soft link.
Definition: RegistryEntry.cpp:90
DataSvcHelpers::RegistryEntry::RegistryEntry
RegistryEntry(std::string path, RegistryEntry *parent=nullptr)
Standard Constructor.
Definition: RegistryEntry.cpp:53
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:100
DataObject.h
DataSvcHelpers::RegistryEntry
Definition: RegistryEntry.h:46
std::begin
T begin(T... args)
std
STL namespace.
std::string::insert
T insert(T... args)
DataSvcHelpers::RegistryEntry::deleteElements
long deleteElements()
Delete all contained elements.
Definition: RegistryEntry.cpp:216
DataSvcHelpers::RegistryEntry::add
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
Definition: RegistryEntry.cpp:198
DataObject
Definition: DataObject.h:36
std::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
DataSvcHelpers::RegistryEntry::i_create
RegistryEntry * i_create(std::string name)
Internal method to create entries.
Definition: RegistryEntry.cpp:165
DataSvcHelpers::RegistryEntry::traverseTree
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
Definition: RegistryEntry.cpp:281
ProduceConsume.key
key
Definition: ProduceConsume.py:84
IDataStoreAgent.h
std::string::rfind
T rfind(T... args)
DataObject::addRef
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:63
DataSvcHelpers::RegistryEntry::~RegistryEntry
~RegistryEntry() override
Standard Destructor.
Definition: RegistryEntry.cpp:63
IDataStoreAgent
Definition: IDataStoreAgent.h:27