Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
27 
28 // Framework include files
29 #include "GaudiKernel/DataObject.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 
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 );
49  addRef();
50 }
51 
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 );
62  }
63 }
64 
67  unsigned long cnt = --m_refCount;
68  if ( !m_refCount ) delete this;
69  return cnt;
70 }
71 
74  m_pParent = pParent;
75  m_fullpath.clear();
77 }
78 
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 
90  m_isSoft = true;
91  setAddress( pAddress );
92 }
93 
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 
104  m_isSoft = false;
105  setAddress( pAddress );
106 }
107 
110  if ( pAddress ) {
111  pAddress->addRef();
112  pAddress->setRegistry( this );
113  }
114  if ( m_pAddress ) m_pAddress->release();
115  m_pAddress = pAddress;
116 }
117 
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 
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 
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 
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 
165  RegistryEntry* pEntry = CAST_REGENTRY( RegistryEntry*, obj );
166  return i_add( pEntry );
167 }
168 
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 
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 
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 
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 
220  auto i = std::find( m_store.begin(), m_store.end(), obj );
221  return ( i != m_store.end() ) ? ( *i ) : nullptr;
222 }
223 
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 != boost::string_ref::npos ) {
234  path.remove_prefix( loc1 + 1 );
235  } else {
236  path.clear();
237  }
239  [&]( const auto& reg ) { return cpath == boost::string_ref{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 != boost::string_ref{m_path}.substr( 1 ) ) break;
247  }
248  return nullptr;
249 }
250 
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
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
287  if ( m_pParent ) m_pParent->assemblePath( buffer );
288  buffer += m_path;
289 }
long deleteElements()
Delete all contained elements.
constexpr char SEPARATOR
const std::string & name() const override
Retrieve name of the entry.
T front(T...args)
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
virtual bool analyse(IRegistry *pObject, int level)=0
Analyse the data object.
unsigned long addRef() override
IInterface implementation: Dereference the object.
T rfind(T...args)
RegistryEntry * m_pParent
Pointer to parent.
Definition: RegistryEntry.h:58
~RegistryEntry() override
Standard Destructor.
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
STL namespace.
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:70
unsigned long release() override
IInterface implementation: Reference the object.
#define CAST_REGENTRY(x, y)
virtual const name_type & name() const =0
Name of the directory (or key)
T end(T...args)
virtual unsigned long release()=0
release reference to object
bool isSoft() const
Is the link soft or hard.
T remove(T...args)
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:72
long i_add(RegistryEntry *entry)
Internal method to add entries.
STL class.
std::string m_fullpath
String containing full path of the object (volatile)
Definition: RegistryEntry.h:54
void assemblePath(std::string &buffer) const
The following entries serve two aspects: 1) They are faster for recursive calls, because they are non...
T push_back(T...args)
void setParent(RegistryEntry *pParent)
Set new parent pointer.
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:53
void setObject(DataObject *obj)
Set/Update object address.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
T erase(T...args)
IDataProviderSvc * m_pDataProviderSvc
Pointer to hosting transient store.
Definition: RegistryEntry.h:64
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:89
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
T clear(T...args)
IOpaqueAddress * address() const override
Retrieve opaque storage address.
IOpaqueAddress * m_pAddress
Pointer to opaque address (load info)
Definition: RegistryEntry.h:60
void makeSoft(DataObject *pObject)
Initialize link as soft link.
RegistryEntry * i_create(std::string name)
Internal method to create entries.
T move(T...args)
bool m_isSoft
Is the link soft or hard?
Definition: RegistryEntry.h:52
Definition of an entry in the transient data store.
Definition: RegistryEntry.h:36
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:46
T insert(T...args)
DataObject * m_pObject
Pointer to object.
Definition: RegistryEntry.h:62
T find_if(T...args)
unsigned long m_refCount
Reference counter.
Definition: RegistryEntry.h:50
T size(T...args)
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
Generic data agent interface.
T begin(T...args)
T none_of(T...args)
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:153
Store m_store
Store of leaves.
Definition: RegistryEntry.h:66
RegistryEntry(std::string path, RegistryEntry *parent=nullptr)
Standard Constructor.
constexpr static const auto FAILURE
Definition: StatusCode.h:86
std::string m_path
Path name.
Definition: RegistryEntry.h:56
T substr(T...args)
StatusCode remove(boost::string_ref name)
Remove an entry from the store.
virtual void setRegistry(IRegistry *r)=0
Update directory pointer.
Opaque address interface definition.
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
IRegistry * i_find(const IRegistry *pDirectory) const
Internal method to retrieve data directory.
T compare(T...args)
virtual unsigned long addRef()=0
Add reference to object.
void makeHard(DataObject *pObject)
Initialize link as hard link.