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 
33 // If you absolutely need optimization: switch off dynamic_cast.
34 // This improves access to the data store roughly by more than 10 %
35 // for balanced trees.
36 //
37 // M.Frank
38 //
39 #define CAST_REGENTRY(x,y) dynamic_cast<x>(y)
40 //#define CAST_REGENTRY(x,y) (x)(y)
41 constexpr char SEPARATOR { '/' };
42 
45  m_path(std::move(path)),
46  m_pParent(parent)
47 {
48  std::string::size_type sep = m_path.rfind(SEPARATOR);
49  if ( m_path.front() != SEPARATOR ) m_path.insert(0,1,SEPARATOR);
50  if ( sep != std::string::npos ) m_path.erase(0,sep);
52  addRef();
53 }
54 
58  if ( m_pObject ) {
59  if ( !m_isSoft ) m_pObject->setRegistry(nullptr);
60  m_pObject->release();
61  }
62  if ( m_pAddress ) {
63  if ( !m_isSoft ) m_pAddress->setRegistry(nullptr);
65  }
66 }
67 
70  unsigned long cnt = --m_refCount;
71  if ( !m_refCount ) delete this;
72  return cnt;
73 }
74 
77  m_pParent = pParent;
78  m_fullpath.clear();
80 }
81 
84  m_isSoft = true;
85  setObject(pObject);
86 // if ( 0 != m_pObject ) { // Useless: This justs sets my own address again...
87 // setAddress(m_pObject->address());
88 // }
89 }
90 
93  m_isSoft = true;
94  setAddress(pAddress);
95 }
96 
99  makeSoft(pObject);
100  m_isSoft = false;
101  if ( m_pObject ) m_pObject->setRegistry(this);
102  if ( m_pAddress ) m_pAddress->setRegistry(this);
103 }
104 
107  m_isSoft = false;
108  setAddress(pAddress);
109 }
110 
113  if ( pAddress ) {
114  pAddress->addRef();
115  pAddress->setRegistry(this);
116  }
117  if ( m_pAddress ) m_pAddress->release();
118  m_pAddress = pAddress;
119 }
120 
123  if ( pObject ) {
124  pObject->addRef();
125  if ( !isSoft() ) pObject->setRegistry(this);
126  }
127  if ( m_pObject ) m_pObject->release();
128  m_pObject = pObject;
129 }
130 
133  try {
134  RegistryEntry* pEntry = dynamic_cast<RegistryEntry*>(obj);
135  auto i = std::remove(std::begin(m_store), std::end(m_store), pEntry);
136  if (i != std::end(m_store)) {
137  pEntry->release();
138  m_store.erase( i, std::end(m_store) );
139  }
140  }
141  catch ( ... ) { }
142  return m_store.size();
143 }
144 
147  if ( nam.front() != SEPARATOR ) return remove( SEPARATOR+nam );
148  // if this object is already present, this is an error....
149  for (auto& i : m_store ) {
150  if ( nam == i->name() ) {
151  remove(i);
152  return StatusCode::SUCCESS;
153  }
154  }
155  return StatusCode::FAILURE;
156 }
157 
160  if ( nam.front() != SEPARATOR ) nam.insert(0,1,SEPARATOR);
161  // if this object is already present, this is an error....
162  auto not_present = std::none_of( std::begin(m_store), std::end(m_store),
163  [&](IRegistry* i) { return nam == i->name();
164  } );
165  return not_present ? new RegistryEntry( std::move(nam), this ) : nullptr;
166 }
167 
170  RegistryEntry* pEntry = CAST_REGENTRY(RegistryEntry*, obj);
171  return i_add(pEntry);
172 }
173 
176 //TODO: if this is the sole place where items are added to m_store,
177 // and we know here that they must be RegisteryEntry, can we
178 // drop the dynamic_cast every where else???
179 //TODO: if so, can we also change m_store to be std::vector<RegistryEntry*>
180 // instead
181 //TODO: if so, can we not make it std::vector<RegistryEntry> instead?
182 //TODO: if so, should make sure that a RegistryEntry can be std::move'ed
183  try {
185  m_store.push_back(pEntry);
186  pEntry->setParent(this);
187  if ( !pEntry->isSoft() && pEntry->address() ) {
188  pEntry->address()->setRegistry(pEntry);
189  }
190  }
191  catch ( ... ) {
192  }
193  return m_store.size();
194 }
195 
197 long DataSvcHelpers::RegistryEntry::add ( const std::string& name, DataObject* pObject, bool is_soft ) {
198  RegistryEntry* entry = i_create(name);
199  if ( !entry ) return StatusCode::FAILURE;
200  ( is_soft ) ? entry->makeSoft(pObject) : entry->makeHard(pObject);
201  i_add( entry );
202  return StatusCode::SUCCESS;
203 }
204 
206 long DataSvcHelpers::RegistryEntry::add ( const std::string& name, IOpaqueAddress* pAddress, bool is_soft ) {
207  RegistryEntry* entry = i_create(name);
208  if ( !entry ) return StatusCode::FAILURE;
209  ( is_soft ) ? entry->makeSoft(pAddress) : entry->makeHard(pAddress);
210  i_add( entry );
211  return StatusCode::SUCCESS;
212 }
213 
216  for (auto& i : m_store ) {
218  if ( entry ) {
219  entry->deleteElements();
220  entry->release();
221  }
222  }
223  m_store.erase(m_store.begin(), m_store.end());
224  return 0;
225 }
226 
229  auto i = std::find(m_store.begin(),m_store.end(),obj);
230  return (i!=m_store.end()) ? (*i) : nullptr;
231 }
232 
235  if ( path.front() == SEPARATOR ) path.remove_prefix(1); // strip leading '/', if present
236  while (!path.empty()) {
237  // check that the chars of path prior to / are the same as regEnt->name()
238  // (i.e. match { nam:"/Ab" path:"/Ab/C"}
239  // but not { nam:"/Abc" path:"/Ab/C"})
240  auto loc1 = path.find(SEPARATOR);
241  auto cpath = path.substr(0,loc1);
242  if (loc1 != boost::string_ref::npos) {
243  path.remove_prefix(loc1+1);
244  } else {
245  path.clear();
246  }
248  [&](decltype(m_store)::const_reference reg) {
249  return cpath == boost::string_ref{reg->name()}.substr(1);
250  });
251  if ( i!=std::end(m_store) ) {
252  RegistryEntry* regEnt = CAST_REGENTRY(RegistryEntry*, *i);
253  return path.empty() ? regEnt : regEnt->i_find(path);
254  }
255  // If this node is "/NodeA", this part allows to find "/NodeA/NodeB" as
256  // our "/NodeB" child.
257  if ( cpath != boost::string_ref{m_path}.substr(1) ) break;
258  }
259  return nullptr;
260 }
261 
264  if ( key ) {
265  if ( key == m_pObject ) {
266  return const_cast<RegistryEntry*>(this);
267  }
268  // Look in the immediate level:
270  if ( result ) return result;
271  // Go levels down
272  for (const auto& i : m_store) {
273  try {
274  const RegistryEntry *entry = CAST_REGENTRY(RegistryEntry*, i);
275  result = entry->i_find(key);
276  if( result ) return result;
277  }
278  catch ( ... ) { }
279  }
280  }
281  return nullptr;
282 }
283 
284 // Traverse registry tree
286  bool go_down = pAgent->analyse(this, level);
287  long status = StatusCode::SUCCESS;
288  if ( go_down ) {
289  for ( auto& i : m_store ) {
290  try {
292  entry->traverseTree(pAgent, level+1);
293  }
294  catch (...) {
295  status = StatusCode::FAILURE;
296  }
297  }
298  }
299  return status;
300 }
301 
302 // Recursive helper to assemble the full path name of the entry
304  if ( m_pParent ) m_pParent->assemblePath(buffer);
305  buffer += m_path;
306 }
virtual long deleteElements()
Delete all contained elements.
constexpr char SEPARATOR
const std::string & name() const override
Retrieve name of the entry.
T front(T...args)
virtual bool analyse(IRegistry *pObject, int level)=0
Analyse the data object.
unsigned long addRef() override
IInterface implementation: Dereference the object.
virtual long add(const std::string &name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
T rfind(T...args)
RegistryEntry * m_pParent
Pointer to parent.
Definition: RegistryEntry.h:56
virtual long traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
~RegistryEntry() override
Standard Destructor.
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
virtual long remove(const std::string &name)
Remove an entry from the store.
T remove(T...args)
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:74
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:52
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.
T push_back(T...args)
void setParent(RegistryEntry *pParent)
Set new parent pointer.
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:63
void setObject(DataObject *obj)
Set/Update object address.
T erase(T...args)
IDataProviderSvc * m_pDataProviderSvc
Pointer to hosting transient store.
Definition: RegistryEntry.h:62
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:87
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:58
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:50
Definition of an entry in the transient data store.
Definition: RegistryEntry.h:36
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:56
T insert(T...args)
DataObject * m_pObject
Pointer to object.
Definition: RegistryEntry.h:60
T find(T...args)
unsigned long m_refCount
Reference counter.
Definition: RegistryEntry.h:48
T size(T...args)
Generic data agent interface.
T begin(T...args)
T none_of(T...args)
Store m_store
Store of leaves.
Definition: RegistryEntry.h:64
RegistryEntry(std::string path, RegistryEntry *parent=nullptr)
Standard Constructor.
std::string m_path
Path name.
Definition: RegistryEntry.h:54
T substr(T...args)
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.
virtual unsigned long addRef()=0
Add reference to object.
void makeHard(DataObject *pObject)
Initialize link as hard link.