| The Gaudi Framework v32r1 (f65d50dc)

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