The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
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\***********************************************************************************/
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)
25constexpr 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
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
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 {
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
173StatusCode 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
182StatusCode 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 ) {
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 {
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
271void DataSvcHelpers::RegistryEntry::assemblePath( std::string& buffer ) const {
272 if ( m_pParent ) m_pParent->assemblePath( buffer );
273 buffer += m_path;
274}
#define CAST_REGENTRY(x, y)
Definition DataSvc.cpp:46
A DataObject is the base class of any identifiable object on any data store.
Definition DataObject.h:37
virtual unsigned long addRef()
Add reference to object.
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition DataObject.h:77
Definition of an entry in the transient data store.
void setObject(DataObject *obj)
Set/Update object address.
IDataProviderSvc * m_pDataProviderSvc
Pointer to hosting transient store.
~RegistryEntry() override
Standard Destructor.
std::string m_fullpath
String containing full path of the object (volatile)
unsigned long addRef() override
IInterface implementation: Dereference the object.
Store m_store
Store of leaves.
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
unsigned long m_refCount
Reference counter.
RegistryEntry * i_create(std::string name)
Internal method to create entries.
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
IRegistry * parent() const
Pointer to parent directory entry.
void setParent(RegistryEntry *pParent)
Set new parent pointer.
IRegistry * i_find(const IRegistry *pDirectory) const
Internal method to retrieve data directory.
void assemblePath(std::string &buffer) const
The following entries serve two aspects: 1) They are faster for recursive calls, because they are non...
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
bool isSoft() const
Is the link soft or hard.
RegistryEntry * m_pParent
Pointer to parent.
DataObject * m_pObject
Pointer to object.
bool m_isSoft
Is the link soft or hard?
long deleteElements()
Delete all contained elements.
long i_add(RegistryEntry *entry)
Internal method to add entries.
void makeSoft(DataObject *pObject)
Initialize link as soft link.
unsigned long release() override
IInterface implementation: Reference the object.
std::string m_path
Path name.
void makeHard(DataObject *pObject)
Initialize link as hard link.
IOpaqueAddress * m_pAddress
Pointer to opaque address (load info)
IOpaqueAddress * address() const override
Retrieve opaque storage address.
RegistryEntry(std::string path, RegistryEntry *parent=nullptr)
Standard Constructor.
StatusCode remove(std::string_view name)
Remove an entry from the store.
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
const std::string & name() const override
Retrieve name of the entry.
Generic data agent interface.
virtual bool analyse(IRegistry *pObject, int level)=0
Analyse the data object.
Opaque address interface definition.
virtual void setRegistry(IRegistry *r)=0
Update directory pointer.
virtual unsigned long addRef()=0
Add reference to object.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition IRegistry.h:29
virtual const name_type & name() const =0
Name of the directory (or key)
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition StatusCode.h:139
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
STL namespace.