RegistryEntry.cpp
Go to the documentation of this file.
1 // $Header: /tmp/svngaudi/tmp.jEpFh25751/Gaudi/GaudiKernel/src/Lib/RegistryEntry.cpp,v 1.12 2006/07/07 13:15:30 hmd Exp $
2 //====================================================================
3 // RegistryEntry.cpp
4 //--------------------------------------------------------------------
5 //
6 // Package : DataSvc ( The LHCb Offline System)
7 //
8 // Description: implementation of the Transient data store
9 //
10 // Author : M.Frank
11 // History :
12 // +---------+----------------------------------------------+---------
13 // | Date | Comment | Who
14 // +---------+----------------------------------------------+---------
15 // | 29/10/98| Initial version | MF
16 // | 03/02/99| Protect dynamic_cast with try-catch clauses | MF
17 // +---------+----------------------------------------------+---------
18 //
19 //====================================================================
20 #define DATASVC_REGISTRYENTRY_CPP
21 
22 // STL include files
23 #include <algorithm>
24 
25 // Interfaces
26 #include "GaudiKernel/IDataStoreAgent.h"
27 #include "GaudiKernel/IOpaqueAddress.h"
28 
29 // Framework include files
30 #include "GaudiKernel/DataObject.h"
31 #include "GaudiKernel/RegistryEntry.h"
32 
33 
34 // If you absolutely need optimization: switch off dynamic_cast.
35 // This improves access to the data store roughly by more than 10 %
36 // for balanced trees.
37 //
38 // M.Frank
39 //
40 #define CAST_REGENTRY(x,y) dynamic_cast<x>(y)
41 //#define CAST_REGENTRY(x,y) (x)(y)
42 constexpr char SEPARATOR { '/' };
43 
44 namespace {
45  inline std::string operator+(std::string s, boost::string_ref p) {
46  return s.append(p.data(),p.size());
47  }
48 }
51 : m_refCount(0),
52  m_isSoft(false),
53  m_path(std::move(path)),
54  m_pParent(parent),
55  m_pAddress(nullptr),
56  m_pObject(nullptr),
57  m_pDataProviderSvc(nullptr)
58 {
59  std::string::size_type sep = m_path.rfind(SEPARATOR);
60  if ( m_path.front() != SEPARATOR ) m_path.insert(0,1,SEPARATOR);
61  if ( sep != std::string::npos ) m_path.erase(0,sep);
63  addRef();
64 }
65 
68  deleteElements();
69  if ( m_pObject ) {
70  if ( !m_isSoft ) m_pObject->setRegistry(nullptr);
71  m_pObject->release();
72  }
73  if ( m_pAddress ) {
74  if ( !m_isSoft ) m_pAddress->setRegistry(nullptr);
75  m_pAddress->release();
76  }
77 }
78 
81  unsigned long cnt = --m_refCount;
82  if ( !m_refCount ) delete this;
83  return cnt;
84 }
85 
88  m_pParent = pParent;
89  m_fullpath = "";
90  assemblePath(m_fullpath);
91 }
92 
95  m_isSoft = true;
96  setObject(pObject);
97 // if ( 0 != m_pObject ) { // Useless: This justs sets my own address again...
98 // setAddress(m_pObject->address());
99 // }
100 }
101 
104  m_isSoft = true;
105  setAddress(pAddress);
106 }
107 
110  makeSoft(pObject);
111  m_isSoft = false;
112  if ( m_pObject ) m_pObject->setRegistry(this);
113  if ( m_pAddress ) m_pAddress->setRegistry(this);
114 }
115 
118  m_isSoft = false;
119  setAddress(pAddress);
120 }
121 
124  if ( pAddress ) {
125  pAddress->addRef();
126  pAddress->setRegistry(this);
127  }
128  if ( m_pAddress ) m_pAddress->release();
129  m_pAddress = pAddress;
130 }
131 
134  if ( pObject ) {
135  pObject->addRef();
136  if ( !isSoft() ) pObject->setRegistry(this);
137  }
138  if ( m_pObject ) m_pObject->release();
139  m_pObject = pObject;
140 }
141 
144  try {
145  RegistryEntry* pEntry = dynamic_cast<RegistryEntry*>(obj);
146  auto i = std::remove(std::begin(m_store), std::end(m_store), pEntry);
147  if (i != std::end(m_store)) {
148  pEntry->release();
149  m_store.erase( i, std::end(m_store) );
150  }
151  }
152  catch ( ... ) { }
153  return m_store.size();
154 }
155 
157 long DataSvcHelpers::RegistryEntry::remove ( const std::string& nam ) {
158  if ( nam.front() != SEPARATOR ) return remove( SEPARATOR+nam );
159  // if this object is already present, this is an error....
160  for (auto& i : m_store ) {
161  if ( nam == i->name() ) {
162  remove(i);
163  return StatusCode::SUCCESS;
164  }
165  }
166  return StatusCode::FAILURE;
167 }
168 
171  if ( nam.front() != SEPARATOR ) nam.insert(0,1,SEPARATOR);
172  // if this object is already present, this is an error....
173  auto not_present = std::none_of( std::begin(m_store), std::end(m_store),
174  [&](IRegistry* i) { return nam == i->name();
175  } );
176  return not_present ? new RegistryEntry( std::move(nam), this ) : nullptr;
177 }
178 
181  RegistryEntry* pEntry = CAST_REGENTRY(RegistryEntry*, obj);
182  return i_add(pEntry);
183 }
184 
187 //TODO: if this is the sole place where items are added to m_store,
188 // and we know here that they must be RegisteryEntry, can we
189 // drop the dynamic_cast every where else???
190 //TODO: if so, can we also change m_store to be std::vector<RegistryEntry*>
191 // instead
192 //TODO: if so, can we not make it std::vector<RegistryEntry> instead?
193 //TODO: if so, should make sure that a RegistryEntry can be std::move'ed
194  try {
195  pEntry->setDataSvc(m_pDataProviderSvc);
196  m_store.push_back(pEntry);
197  pEntry->setParent(this);
198  if ( !pEntry->isSoft() && pEntry->address() ) {
199  pEntry->address()->setRegistry(pEntry);
200  }
201  }
202  catch ( ... ) {
203  }
204  return m_store.size();
205 }
206 
208 long DataSvcHelpers::RegistryEntry::add ( const std::string& name, DataObject* pObject, bool is_soft ) {
209  RegistryEntry* entry = i_create(name);
210  if ( !entry ) return StatusCode::FAILURE;
211  ( is_soft ) ? entry->makeSoft(pObject) : entry->makeHard(pObject);
212  i_add( entry );
213  return StatusCode::SUCCESS;
214 }
215 
217 long DataSvcHelpers::RegistryEntry::add ( const std::string& name, IOpaqueAddress* pAddress, bool is_soft ) {
218  RegistryEntry* entry = i_create(name);
219  if ( !entry ) return StatusCode::FAILURE;
220  ( is_soft ) ? entry->makeSoft(pAddress) : entry->makeHard(pAddress);
221  i_add( entry );
222  return StatusCode::SUCCESS;
223 }
224 
227  for (auto& i : m_store ) {
229  if ( entry ) {
230  entry->deleteElements();
231  entry->release();
232  }
233  }
234  m_store.erase(m_store.begin(), m_store.end());
235  return 0;
236 }
237 
240  auto i = std::find(m_store.begin(),m_store.end(),obj);
241  return (i!=m_store.end()) ? (*i) : nullptr;
242 }
243 
246  if ( path.front() == SEPARATOR ) path.remove_prefix(1); // strip leading '/', if present
247  while (!path.empty()) {
248  // check that the chars of path prior to / are the same as regEnt->name()
249  // (i.e. match { nam:"/Ab" path:"/Ab/C"}
250  // but not { nam:"/Abc" path:"/Ab/C"})
251  auto loc1 = path.find(SEPARATOR);
252  auto cpath = path.substr(0,loc1);
253  if (loc1 != boost::string_ref::npos) {
254  path.remove_prefix(loc1+1);
255  } else {
256  path.clear();
257  }
258  auto i = std::find_if( std::begin(m_store), std::end(m_store),
259  [&](decltype(m_store)::const_reference reg) {
260  return cpath == boost::string_ref{reg->name()}.substr(1);
261  });
262  if ( i!=std::end(m_store) ) {
264  return path.empty() ? regEnt : regEnt->i_find(path);
265  }
266  // If this node is "/NodeA", this part allows to find "/NodeA/NodeB" as
267  // our "/NodeB" child.
268  if ( cpath != boost::string_ref{m_path}.substr(1) ) break;
269  }
270  return nullptr;
271 }
272 
275  if ( key ) {
276  if ( key == m_pObject ) {
277  return const_cast<RegistryEntry*>(this);
278  }
279  // Look in the immediate level:
280  RegistryEntry *result = CAST_REGENTRY(RegistryEntry*, i_find(key->registry()));
281  if ( result ) return result;
282  // Go levels down
283  for (const auto& i : m_store) {
284  try {
285  const RegistryEntry *entry = CAST_REGENTRY(RegistryEntry*, i);
286  result = entry->i_find(key);
287  if( result ) return result;
288  }
289  catch ( ... ) { }
290  }
291  }
292  return nullptr;
293 }
294 
295 // Traverse registry tree
297  bool go_down = pAgent->analyse(this, level);
298  long status = StatusCode::SUCCESS;
299  if ( go_down ) {
300  for ( auto& i : m_store ) {
301  try {
303  entry->traverseTree(pAgent, level+1);
304  }
305  catch (...) {
306  status = StatusCode::FAILURE;
307  }
308  }
309  }
310  return status;
311 }
312 
313 // Recursive helper to assemble the full path name of the entry
314 void DataSvcHelpers::RegistryEntry::assemblePath(std::string& buffer) const {
315  if ( m_pParent ) m_pParent->assemblePath(buffer);
316  buffer += m_path;
317 }
virtual unsigned long addRef()
IInterface implementation: Dereference the object.
virtual long deleteElements()
Delete all contained elements.
constexpr char SEPARATOR
def remove(file, logdir)
Definition: install.py:153
virtual bool analyse(IRegistry *pObject, int level)=0
Analyse the data object.
virtual long add(const std::string &name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
list path
Definition: __init__.py:15
virtual long traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
STL namespace.
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:65
#define CAST_REGENTRY(x, y)
virtual const name_type & name() const =0
Name of the directory (or key)
RegistryEntry(std::string path, RegistryEntry *parent=0)
Standard Constructor.
return false
Definition: Bootstrap.cpp:338
virtual long remove(const std::string &name)
Remove an entry from the store.
virtual unsigned long release()
IInterface implementation: Reference the object.
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:69
long i_add(RegistryEntry *entry)
Internal method to add entries.
std::string m_fullpath
String containing full path of the object (volatile)
Definition: RegistryEntry.h:49
void assemblePath(std::string &buffer) const
The following entries serve two aspects: 1) They are faster for recursive calls, because they are non...
virtual bool isSoft() const
Is the link soft or hard.
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.
virtual IOpaqueAddress * address() const
Retrieve opaque storage address.
GAUDI_API Stat operator+(const Stat &stat, const double value)
external operator for addition of Stat and a number
Definition: Stat.cpp:217
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:84
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
void makeSoft(DataObject *pObject)
Initialize link as soft link.
RegistryEntry * i_create(std::string name)
Internal method to create entries.
void setAddress(IOpaqueAddress *pAddress)
Set/Update Opaque address.
tuple end
Definition: IOTest.py:101
Definition of an entry in the transient data store.
Definition: RegistryEntry.h:35
Generic data agent interface.
string s
Definition: gaudirun.py:244
std::string m_path
Path name.
Definition: RegistryEntry.h:51
virtual ~RegistryEntry()
Standard Destructor.
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:31
list i
Definition: ana.py:128
IRegistry * i_find(const IRegistry *pDirectory) const
Internal method to retrieve data directory.
virtual unsigned long addRef()=0
Add reference to object.
void makeHard(DataObject *pObject)
Initialize link as hard link.