Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
DataSvc.cpp
Go to the documentation of this file.
1 //====================================================================
2 // DataSvc.cpp
3 //--------------------------------------------------------------------
4 //
5 // Package : System ( The LHCb Offline System)
6 //
7 // Description: implementation of the Transient data service: DataSvc
8 //
9 // Author : M.Frank
10 // History :
11 // +---------+----------------------------------------------+---------
12 // | Date | Comment | Who
13 // +---------+----------------------------------------------+---------
14 // | 29/10/98| Initial version | M.Frank
15 // | 20/2/99 | Automatic data preloading introduced. | M.Frank
16 // +---------+----------------------------------------------+---------
17 //
18 //====================================================================
19 #define DATASVC_DATASVC_CPP
20 
21 // Framework include files
23 #include "GaudiKernel/IConverter.h"
25 
26 #include "GaudiKernel/DataObject.h"
28 
30 #include "GaudiKernel/DataSvc.h"
33 
34 // Include files
35 #include <algorithm>
36 #include <cassert>
37 #include <cstdlib>
38 #include <sstream>
39 #include <vector>
40 
41 #include "boost/utility/string_ref.hpp"
42 
43 namespace {
44  std::string operator+( char c, boost::string_ref sr ) {
45  std::string s{c};
46  s.append( sr.data(), sr.size() );
47  return s;
48  }
49 
50  boost::string_ref::size_type find( boost::string_ref s, char c, size_t o ) {
51  if ( !s.empty() ) s.remove_prefix( o );
52  auto r = s.find( c );
53  return r == boost::string_ref::npos ? r : ( r + o );
54  }
55 
56  std::string to_string( boost::string_ref sr ) { return {sr.data(), sr.size()}; }
57 } // namespace
58 
59 // If you absolutely need optimization: switch off dynamic_cast.
60 // This improves access to the data store roughly by 10 %
61 // for balanced trees.
62 //
63 // M.Frank
64 #define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
65 //#define CAST_REGENTRY(x,y) (x)(y)
67 
68 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
69 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
70 
71 #define DEBMSG ON_DEBUG debug()
72 #define VERMSG ON_VERBOSE verbose()
73 
77 StatusCode DataSvc::clearSubTree( boost::string_ref sub_tree_path ) {
78  DataObject* pObject = nullptr;
79  StatusCode status = findObject( sub_tree_path, pObject );
80  if ( !status.isSuccess() ) return status;
81  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
82  if ( !node_entry ) return Status::INVALID_OBJECT;
83  RegEntry* parent = node_entry->parentEntry();
84  if ( !parent ) return Status::INVALID_PARENT;
85  parent->remove( node_entry );
86  return StatusCode::SUCCESS;
87 }
88 
93  if ( !checkRoot() ) return Status::INVALID_ROOT;
94  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
95  if ( !entry ) return Status::INVALID_OBJECT;
96  RegEntry* parent = entry->parentEntry();
97  if ( !parent ) return Status::INVALID_PARENT;
98  parent->remove( entry );
99  return StatusCode::SUCCESS;
100 }
101 
104  if ( !checkRoot() ) return Status::INVALID_ROOT;
105  m_root.reset();
106  return StatusCode::SUCCESS;
107 }
108 
112 StatusCode DataSvc::traverseSubTree( boost::string_ref sub_tree_path, IDataStoreAgent* pAgent ) {
113  DataObject* pO = nullptr;
114  StatusCode status = findObject( sub_tree_path, pO );
115  return status.isSuccess() ? traverseSubTree( pO, pAgent ) : status;
116 }
117 
120  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
121  return entry ? entry->traverseTree( pAgent ) : Status::INVALID_OBJECT;
122 }
123 
126  if ( !checkRoot() ) return Status::INVALID_ROOT;
127  return m_root->traverseTree( pAgent );
128 }
129 
135  clearStore().ignore();
136  return i_setRoot( std::move( root_path ), pRootObj );
137 }
138 
145  if ( pRootObj ) {
146  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
147  m_root->makeHard( pRootObj );
148  m_root->setDataSvc( this );
149  // No done with GaudiHive. preLoad().ignore();
150  }
151  return StatusCode::SUCCESS;
152 }
153 
159  clearStore().ignore();
160  return i_setRoot( std::move( root_path ), pRootAddr );
161 }
162 
169  if ( pRootAddr ) {
170  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
171  m_root->makeHard( pRootAddr );
172  m_root->setDataSvc( this );
173  // Not done with GaudiHive. preLoad().ignore();
174  }
175  return StatusCode::SUCCESS;
176 }
177 
180  m_dataLoader = pDataLoader;
181  if ( m_dataLoader ) m_dataLoader->setDataProvider( dpsvc ? dpsvc : this ).ignore();
182  return StatusCode::SUCCESS;
183 }
184 
186 StatusCode DataSvc::objectParent( const DataObject* pObject, IRegistry*& refpParent ) {
187  if ( !pObject ) return Status::INVALID_OBJECT;
188  return objectParent( pObject->registry(), refpParent );
189 }
191 StatusCode DataSvc::objectParent( const IRegistry* pRegistry, IRegistry*& refpParent ) {
192  if ( !checkRoot() ) return Status::INVALID_ROOT;
193  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
194  if ( !node_entry ) return Status::INVALID_OBJECT;
195  refpParent = node_entry->parent();
196  return StatusCode::SUCCESS;
197 }
198 
201  if ( !pObject ) return Status::INVALID_OBJECT;
202  return objectLeaves( pObject->registry(), leaves );
203 }
204 
209  if ( !checkRoot() ) return Status::INVALID_ROOT;
210  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
211  if ( !node_entry ) return Status::INVALID_OBJECT;
212  leaves = node_entry->leaves();
213  return StatusCode::SUCCESS;
214 }
215 
217 StatusCode DataSvc::registerAddress( boost::string_ref fullPath, IOpaqueAddress* pAddress ) {
218  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
219  return registerAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath, pAddress );
220 }
221 
223 StatusCode DataSvc::registerAddress( IRegistry* parentObj, boost::string_ref objPath, IOpaqueAddress* pAddress ) {
224  if ( !checkRoot() ) return Status::INVALID_ROOT;
225  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
226 
227  if ( !parentObj ) {
228  if ( objPath.front() != SEPARATOR ) { return registerAddress( m_root.get(), objPath, pAddress ); }
229  auto sep = find( objPath, SEPARATOR, 1 );
230  if ( sep == boost::string_ref::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
231  return Status::INVALID_PARENT;
232  }
233  return registerAddress( m_root.get(), objPath.substr( sep ), pAddress );
234  }
235  if ( objPath.front() != SEPARATOR ) { return registerAddress( parentObj, char( SEPARATOR ) + objPath, pAddress ); }
236  RegEntry* par_entry = CAST_REGENTRY( RegEntry*, parentObj );
237  if ( !par_entry ) return Status::INVALID_PARENT;
238 
239  auto sep = objPath.rfind( SEPARATOR );
240  if ( sep > 0 && sep != boost::string_ref::npos ) {
241  auto p_path = objPath.substr( 0, sep );
242  auto o_path = objPath.substr( sep );
243  RegEntry* p_entry = par_entry->findLeaf( p_path );
244  // Create default object leafs if the
245  // intermediate nodes are not present
246  if ( !p_entry && m_forceLeaves ) {
247  DataObject* pLeaf = createDefaultObject();
248  StatusCode sc = registerObject( par_entry->identifier(), p_path, pLeaf );
249  if ( sc.isFailure() ) delete pLeaf;
250  p_entry = par_entry->findLeaf( p_path );
251  }
252  if ( !p_entry ) return Status::INVALID_PARENT;
253  return registerAddress( p_entry, o_path, pAddress );
254  }
255  StatusCode status = par_entry->add( to_string( objPath ), pAddress );
256  return status.isSuccess() ? status : Status::DOUBL_OBJ_PATH;
257 }
258 
260 StatusCode DataSvc::unregisterAddress( boost::string_ref fullPath ) {
261  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
262  return unregisterAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath );
263 }
264 
266 StatusCode DataSvc::unregisterAddress( IRegistry* pParent, boost::string_ref objPath ) {
267  if ( !checkRoot() ) return Status::INVALID_ROOT;
268  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
269 
270  if ( !pParent ) {
271  if ( objPath.front() != SEPARATOR ) return unregisterAddress( m_root.get(), objPath );
272  auto sep = find( objPath, SEPARATOR, 1 );
273  if ( sep != boost::string_ref::npos && objPath.substr( 0, sep ) == m_rootName.value() ) {
274  return unregisterAddress( m_root.get(), objPath.substr( sep ) );
275  }
276  return Status::INVALID_PARENT;
277  }
278  if ( objPath.front() != SEPARATOR ) { return unregisterAddress( pParent, char( SEPARATOR ) + objPath ); }
279  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pParent );
280  if ( node_entry ) {
281  RegEntry* leaf_entry = node_entry->findLeaf( objPath );
282  if ( leaf_entry ) {
283  auto sep = objPath.rfind( SEPARATOR );
284  if ( sep > 0 && sep != boost::string_ref::npos ) {
285  return unregisterAddress( leaf_entry->parent(), objPath.substr( sep ) );
286  }
287  StatusCode status = node_entry->remove( objPath );
288  if ( status.isSuccess() ) return status;
289  }
290  }
291  return Status::INVALID_PARENT;
292 }
293 
295 StatusCode DataSvc::registerObject( boost::string_ref parentPath, boost::string_ref objPath, DataObject* pObject ) {
296  DataObject* pO = nullptr;
297  StatusCode status = retrieveObject( parentPath, pO );
298  if ( !status.isSuccess() && m_forceLeaves ) {
299  pO = createDefaultObject();
300  status = registerObject( parentPath, pO );
301  if ( !status.isSuccess() ) pO->release();
302  }
303  return status.isSuccess() ? registerObject( pO, objPath, pObject ) : status;
304 }
305 
307 StatusCode DataSvc::registerObject( DataObject* parentObj, boost::string_ref objPath, DataObject* pObject ) {
308  if ( !checkRoot() ) return Status::INVALID_ROOT;
309 
310  if ( !parentObj ) {
311  if ( !objPath.empty() ) {
312  if ( objPath.front() != SEPARATOR ) { return registerObject( m_rootName.value(), objPath, pObject ); }
313  auto sep = find( objPath, SEPARATOR, 1 );
314  if ( sep != boost::string_ref::npos ) {
315  return registerObject( objPath.substr( 0, sep ), objPath.substr( sep ), pObject );
316  }
317  }
318  return Status::INVALID_OBJ_PATH;
319  }
320  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, parentObj->registry() );
321  if ( node_entry ) {
322  StatusCode status = Status::INVALID_PARENT;
323  auto sep = find( objPath, SEPARATOR, 1 );
324  if ( sep != boost::string_ref::npos ) {
325  auto p_path = objPath.substr( 0, sep );
326  auto o_path = objPath.substr( sep );
327  RegEntry* par_entry = node_entry->findLeaf( p_path );
328  // Create default object leafs if the
329  // intermediate nodes are not present
330  if ( !par_entry && m_forceLeaves ) {
331  DataObject* pLeaf = createDefaultObject();
332  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
333  if ( !sc.isSuccess() ) delete pLeaf;
334  par_entry = node_entry->findLeaf( p_path );
335  } else if ( par_entry && !par_entry->object() ) {
336  status = i_retrieveEntry( node_entry, p_path, par_entry );
337  if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
338  DataObject* pLeaf = createDefaultObject();
339  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
340  if ( !sc.isSuccess() ) delete pLeaf;
341  par_entry = node_entry->findLeaf( p_path );
342  }
343  }
344  node_entry = par_entry;
345  if ( node_entry ) {
346  DataObject* obj = node_entry->object();
347  if ( obj ) status = registerObject( obj, o_path, pObject );
348  }
349  } else {
350  RegEntry* leaf = node_entry->findLeaf( objPath );
351  if ( !leaf ) {
352  status = node_entry->add( to_string( objPath ), pObject );
353  } else {
354  DataObject* obj = leaf->object();
355  if ( !obj ) {
356  if ( !pObject ) {
357  error() << "registerObject: trying to register null DataObject" << endmsg;
358  return StatusCode::FAILURE;
359  }
360  pObject->setRegistry( leaf );
361  leaf->setAddress( nullptr );
362  leaf->setObject( pObject );
363  status = StatusCode::SUCCESS;
364  } else {
365  status = Status::DOUBL_OBJ_PATH;
366  }
367  }
368  }
369  return status;
370  }
371  return Status::INVALID_PARENT;
372 }
373 
375 StatusCode DataSvc::unregisterObject( boost::string_ref fullPath ) {
376  DataObject* pObject = nullptr;
377  StatusCode status = findObject( fullPath, pObject );
378  if ( status.isFailure() ) return status;
379  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pObject->registry() );
380  if ( !pEntry ) return Status::INVALID_ROOT;
381  if ( !pEntry->isEmpty() ) return Status::DIR_NOT_EMPTY;
382  RegEntry* pParent = pEntry->parentEntry();
383  if ( !pParent ) return Status::INVALID_PARENT;
384  if ( pObject ) pObject->addRef();
385  pParent->remove( pEntry );
386  return StatusCode::SUCCESS;
387 }
388 
391  if ( !checkRoot() ) return Status::INVALID_ROOT;
392  RegEntry* entry = m_root->findLeaf( pObject );
393  if ( !entry ) return Status::INVALID_OBJECT;
394  RegEntry* parent = entry->parentEntry();
395  if ( !parent ) return Status::INVALID_PARENT;
396  if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
397  if ( entry->object() ) entry->object()->addRef();
398  if ( parent ) parent->remove( entry );
399  return StatusCode::SUCCESS;
400 }
401 
403 StatusCode DataSvc::unregisterObject( DataObject* pParentObj, boost::string_ref objectPath ) {
404  if ( checkRoot() ) {
405  try {
406  RegEntry* parent = CAST_REGENTRY( RegEntry*, pParentObj->registry() );
407  if ( parent ) {
408  RegEntry* entry = parent->findLeaf( objectPath );
409  if ( entry ) {
410  if ( entry->isEmpty() ) {
411  if ( entry->object() ) { entry->object()->addRef(); }
412  parent->remove( entry );
413  return StatusCode::SUCCESS;
414  }
415  return Status::DIR_NOT_EMPTY;
416  }
417  return Status::INVALID_OBJECT;
418  }
419  } catch ( ... ) {}
420  return Status::INVALID_PARENT;
421  }
422  return Status::INVALID_ROOT;
423 }
424 
427 DataObject* DataSvc::handleDataFault( IRegistry* pReg, boost::string_ref path ) {
428  return i_handleDataFault( pReg, path );
429 }
430 
431 DataObject* DataSvc::i_handleDataFault( IRegistry* pReg, boost::string_ref path ) {
432  if ( m_enableFaultHdlr ) {
433  IRegistry* pLeaf = nullptr;
434  if ( pReg && path.empty() ) {
435  DataIncident incident( name(), m_faultName, pReg->identifier() );
436  m_incidentSvc->fireIncident( incident );
437  return pReg->object();
438  }
439  if ( pReg ) {
440  std::string p = pReg->identifier();
441  if ( path.front() != SEPARATOR ) p += SEPARATOR;
442  p.append( path.data(), path.size() );
443  DataIncident incident( name(), m_faultName, p );
444  m_incidentSvc->fireIncident( incident );
445  pLeaf = m_root->findLeaf( p );
446  } else {
448  if ( path.front() != SEPARATOR ) p += SEPARATOR;
449  p.append( path.data(), path.size() );
450  DataIncident incident( name(), m_faultName, p );
451  m_incidentSvc->fireIncident( incident );
452  pLeaf = m_root->findLeaf( p );
453  }
454  if ( pLeaf ) { return pLeaf->object(); }
455  }
456  return nullptr;
457 }
458 
463  IConversionSvc* pLoader = getDataLoader( pRegistry );
464  return loadObject( pLoader, pRegistry );
465 }
466 
471  StatusCode status = Status::INVALID_OBJ_ADDR;
472  DataObject* pObject = nullptr;
473  if ( !pLoader ) { // Precondition: Data loader must be present
474  return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::NO_DATA_LOADER );
475  }
476  if ( !pRegistry ) { // Precondition: Directory must be valid
477  return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::INVALID_OBJ_ADDR );
478  }
479 
480  VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
481 
482  if ( m_enableAccessHdlr ) {
483  // Fire data access incident
484  DataIncident incident( name(), m_accessName, pRegistry->identifier() );
485  m_incidentSvc->fireIncident( incident );
486  }
487  if ( !m_inhibitPathes.empty() ) {
488  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
489  if ( inhibit != m_inhibitPathes.end() ) { return Status::NO_ACCESS; }
490  }
491  IOpaqueAddress* pAddress = pRegistry->address();
492  if ( !pAddress ) { // Precondition:
493  return Status::INVALID_OBJ_ADDR; // Address must be valid
494  }
495  try {
496  status = pLoader->createObj( pAddress, pObject ); // Call data loader
497  if ( status.isSuccess() ) {
498 
499  VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
500 
501  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pRegistry );
502  pEntry->setObject( pObject );
503 
504  VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
505  status = pLoader->fillObjRefs( pAddress, pObject );
506  }
507  } catch ( const GaudiException& exc ) {
508  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
509  throw GaudiException( "GaudiException in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE,
510  exc );
511  } catch ( const std::exception& x ) {
512  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
513  throw GaudiException( "std::exception in loadObject() " + pRegistry->identifier() + ": " +
514  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
516  } catch ( ... ) {
517  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
518  throw GaudiException( "UNKN exception in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE );
519  }
520  if ( !status.isSuccess() ) {
521  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
522  }
523  ON_VERBOSE if ( status.isSuccess() ) {
524  verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
525  }
526  return status;
527 }
528 
530 StatusCode DataSvc::retrieveEntry( RegEntry* parentObj, boost::string_ref path, RegEntry*& pEntry ) {
531  return i_retrieveEntry( parentObj, path, pEntry );
532 }
533 
534 StatusCode DataSvc::i_retrieveEntry( RegEntry* parentObj, boost::string_ref path, RegEntry*& pEntry ) {
535  // A.Valassi 16.08.2001 avoid core dump if store is empty
536  if ( !checkRoot() ) return StatusCode( Status::INVALID_ROOT, true );
537 
538  static constexpr auto empty = boost::string_ref{};
539  auto sep = find( path, SEPARATOR, 1 );
540  pEntry = nullptr;
541 
542  if ( !parentObj ) {
543  if ( path.empty() || path == m_rootName.value() ) {
544  parentObj = m_root.get();
545  path = empty;
546  } else if ( path.front() != SEPARATOR ) {
547  parentObj = m_root.get();
548  } else if ( sep != boost::string_ref::npos ) {
549  if ( !m_root->object() ) {
550  RegEntry* r = nullptr;
551  auto status = i_retrieveEntry( m_root.get(), empty, r );
552  if ( !status.isSuccess() ) return status;
553  }
554  parentObj = m_root.get();
555  path = path.substr( sep );
556  } else {
557  return Status::INVALID_OBJ_PATH;
558  }
559  sep = find( path, SEPARATOR, 1 );
560  }
561 
562  StatusCode status = StatusCode( Status::INVALID_ROOT, true );
563  if ( sep != boost::string_ref::npos ) { // the string contains a separator (after pos 0)
564  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
565  status = loadObject( parentObj );
566  if ( !status.isSuccess() ) return status;
567  }
568  auto p_path = path.substr( 0, sep );
569  RegEntry* root_entry = parentObj->findLeaf( p_path );
570  if ( !root_entry && m_enableFaultHdlr ) {
571  // If not even the parent is there, an incident
572  // to load the parent must be fired...
573  i_handleDataFault( parentObj, p_path );
574  root_entry = parentObj->findLeaf( p_path );
575  }
576  if ( root_entry ) {
577  DataObject* pO = root_entry->object();
578  if ( !pO ) {
579  // Object is not loaded: load the object if at all possible
580  status = loadObject( root_entry );
581  if ( !status.isSuccess() ) return status;
582  }
583  if ( root_entry->isSoft() ) { root_entry = CAST_REGENTRY( RegEntry*, pO->registry() ); }
584  return i_retrieveEntry( root_entry, path.substr( sep ), pEntry );
585  }
586  return status;
587  } else if ( path.empty() ) {
588  pEntry = parentObj;
589  } else {
590  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
591  status = loadObject( parentObj );
592  if ( !status.isSuccess() ) return status;
593  }
594  // last leave in search: find leaf and load
595  pEntry = parentObj->findLeaf( path );
596  // If no registry entry was found, trigger incident for action-on-demand
597  if ( !pEntry && m_enableFaultHdlr ) {
598  i_handleDataFault( parentObj, path );
599  pEntry = ( path.empty() ? parentObj : parentObj->findLeaf( path ) );
600  }
601  }
602 
603  // Check results and return
604  if ( !pEntry ) return Status::INVALID_OBJ_PATH;
605  if ( !pEntry->object() ) return loadObject( pEntry );
606 
607  if ( m_enableAccessHdlr ) {
608  // Fire data access incident
609  // I do not know if this is a good idea....
610  // This fires too often!
611  //
612  // DataIncident incident(name(), m_accessName, pEntry->identifier());
613  // m_incidentSvc->fireIncident(incident);
614  return StatusCode::SUCCESS;
615  }
616  return StatusCode::SUCCESS;
617 }
618 
620 StatusCode DataSvc::retrieveObject( IRegistry* pRegistry, boost::string_ref path, DataObject*& pObject ) {
621  pObject = nullptr;
622  RegEntry * result = nullptr, *parent = CAST_REGENTRY( RegEntry*, pRegistry );
623  StatusCode status = i_retrieveEntry( parent, path, result );
624  if ( status.isSuccess() ) pObject = result->object();
625  return status;
626 }
627 
629 StatusCode DataSvc::findObject( IRegistry* pRegistry, boost::string_ref path, DataObject*& pObject ) {
630  pObject = nullptr;
631  IRegistry* pReg = ( pRegistry ? pRegistry : m_root.get() );
632  RegEntry* root_entry = CAST_REGENTRY( RegEntry*, pReg );
633  if ( root_entry ) {
634  if ( !path.empty() ) pReg = root_entry->find( path );
635  if ( !pReg ) return Status::INVALID_OBJ_PATH;
636  pObject = pReg->object();
637  }
638  return ( !pObject ) ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
639 }
640 
642 StatusCode DataSvc::findObject( boost::string_ref path, DataObject*& pObject ) {
643  pObject = nullptr;
644  if ( !checkRoot() ) return Status::INVALID_ROOT;
645  if ( path.empty() || path == m_rootName.value() ) {
646  pObject = m_root->object();
647  return !pObject ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
648  }
649  return findObject( path.front() != SEPARATOR ? m_root.get() : nullptr, path, pObject );
650 }
651 
654  if ( !pRegistry ) { // Precondition:
655  return Status::INVALID_OBJ_ADDR; // Addres must be valid
656  }
657  DataObject* toUpdate = pRegistry->object();
658  if ( !toUpdate ) { // Try first to load
659  return loadObject( pRegistry );
660  }
661  return updateObject( toUpdate );
662 }
663 
666  StatusCode status = Status::INVALID_OBJ_ADDR;
667  if ( !toUpdate ) { // Precondition:
668  return Status::INVALID_OBJECT; // Address must be valid
669  }
670  IRegistry* pRegistry = toUpdate->registry(); // Precondition:
671  if ( !pRegistry ) { // Need valid registry
672  return Status::INVALID_OBJECT;
673  }
674  IOpaqueAddress* pAddress = pRegistry->address(); // Precondition:
675  if ( !pAddress ) { // Need valid address
676  return Status::INVALID_OBJ_ADDR;
677  }
678  IConversionSvc* pLoader = getDataLoader( pRegistry );
679  if ( !pLoader ) { // Precondition:
680  return Status::NO_DATA_LOADER; // Data loader must be present
681  }
682  if ( !m_inhibitPathes.empty() ) {
683  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
684  if ( inhibit != m_inhibitPathes.end() ) { return Status::NO_ACCESS; }
685  }
686  try {
687  status = pLoader->updateObj( pAddress, toUpdate ); // Call data loader
688  if ( status.isSuccess() ) { status = pLoader->updateObjRefs( pAddress, toUpdate ); }
689  } catch ( const GaudiException& exc ) {
690  throw GaudiException( "GaudiException in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE, exc );
691  } catch ( const std::exception& x ) {
692  throw GaudiException( "std::exception in updateObject() " + pRegistry->name() + ": " +
693  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
695  } catch ( ... ) {
696  throw GaudiException( "UNKN exception in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE );
697  }
698  return status;
699 }
700 
701 // Link object
702 StatusCode DataSvc::linkObject( IRegistry* from, boost::string_ref objPath, DataObject* to ) {
703  if ( !checkRoot() ) return Status::INVALID_ROOT;
704  try {
705  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
706  if ( from_entry ) {
707  // First check if both objects are already registered to the store
708  RegEntry* to_entry = m_root->findLeaf( to );
709  if ( !to_entry ) return Status::INVALID_OBJECT;
710  auto sep = objPath.rfind( SEPARATOR );
711  if ( sep > 0 && sep != boost::string_ref::npos ) { // in case the objPath is a sub-directory itself
712  DataObject* pO = nullptr;
713  StatusCode sc = retrieveObject( from, objPath.substr( 0, sep ), pO );
714  return sc.isSuccess() ? linkObject( pO->registry(), objPath.substr( sep ), to ) : sc;
715  }
716  // Now register the soft link
717  StatusCode status = from_entry->add( to_string( objPath ), to, true );
718  return status.isSuccess() ? Status::IDataProviderSvc_NO_ERROR : Status::DOUBL_OBJ_PATH;
719  }
720  } catch ( ... ) {}
721  return Status::INVALID_PARENT;
722 }
723 
725 StatusCode DataSvc::linkObject( boost::string_ref fullPath, DataObject* to ) {
726  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
727  if ( fullPath.front() != SEPARATOR ) { return linkObject( m_rootName.value(), fullPath, to ); }
728  auto sep = fullPath.rfind( SEPARATOR );
729  return linkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ), to );
730 }
731 
733 StatusCode DataSvc::unlinkObject( IRegistry* from, boost::string_ref objPath ) {
734  if ( !checkRoot() ) return Status::INVALID_ROOT;
735  try {
736  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
737  if ( from_entry ) {
738  auto sep = objPath.rfind( SEPARATOR );
739  if ( sep > 0 && sep != boost::string_ref::npos ) { // in case the objPath is a sub-directory itself
740  DataObject* pO = nullptr;
741  StatusCode sc = findObject( from, objPath.substr( 0, sep ), pO );
742  return sc.isSuccess() ? unlinkObject( pO->registry(), objPath.substr( sep ) ) : sc;
743  }
744  StatusCode status = from_entry->remove( objPath );
745  if ( status.isSuccess() ) return status;
746  return Status::INVALID_OBJ_PATH;
747  }
748  } catch ( ... ) {}
749  return Status::INVALID_PARENT;
750 }
751 
753 StatusCode DataSvc::unlinkObject( boost::string_ref fullPath ) {
754  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
755  if ( fullPath.front() != SEPARATOR ) return unlinkObject( m_rootName.value(), fullPath );
756  auto sep = fullPath.rfind( SEPARATOR );
757  return unlinkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ) );
758 }
759 
761 StatusCode DataSvc::unlinkObject( DataObject* from, boost::string_ref objPath ) {
762  if ( !checkRoot() ) return Status::INVALID_ROOT;
763  IRegistry* from_entry = m_root->findLeaf( from );
764  return unlinkObject( from_entry, objPath );
765 }
766 
769  auto i = std::find( begin( m_preLoads ), end( m_preLoads ), item );
770  if ( i == end( m_preLoads ) ) m_preLoads.push_back( item );
771  return StatusCode::SUCCESS;
772 }
773 
777  return StatusCode::SUCCESS;
778 }
779 
783  return StatusCode::SUCCESS;
784 }
785 
787 StatusCode DataSvc::preLoad( int depth, int load_depth, DataObject* pObject ) {
788  // unused: StatusCode sc = StatusCode::FAILURE;
789  if ( pObject && depth++ < load_depth ) {
790  RegEntry* dir = CAST_REGENTRY( RegEntry*, pObject->registry() );
791  if ( dir ) {
792  for ( const auto& i : *dir ) {
793  DataObject* pObj = nullptr;
794  StatusCode status = retrieveObject( pObject, i->name(), pObj );
795  if ( status.isSuccess() && depth < load_depth ) { preLoad( depth, load_depth, pObj ).ignore(); }
796  }
797  }
798  }
799  return StatusCode::SUCCESS;
800 }
801 
804  DataObject* pObj = nullptr;
805  for ( const auto& i : m_preLoads ) {
806  StatusCode sc = retrieveObject( i.path(), pObj );
807  int load_depth = i.depth();
808  if ( sc.isSuccess() && load_depth > 1 ) { preLoad( 1, load_depth, pObj ).ignore(); }
809  }
810  return StatusCode::SUCCESS;
811 }
812 
815  // Nothing to do: just call base class initialisation
817  if ( UNLIKELY( !sc.isSuccess() ) ) return sc;
818  m_incidentSvc = service( "IncidentSvc", true );
819  if ( UNLIKELY( !m_incidentSvc ) ) { error() << "Failed to access incident service." << endmsg; }
820  return sc;
821 }
822 
825  // the finalize part is copied here
826  setDataLoader( nullptr ).ignore();
827  resetPreLoad().ignore();
828  clearStore().ignore();
830  // re-initialize the base class
832  if ( UNLIKELY( !sc.isSuccess() ) ) {
833  error() << "Unable to reinitialize base class" << endmsg;
834  return sc;
835  }
836  // the initialize part is copied here
837  m_incidentSvc = service( "IncidentSvc", true );
838  if ( UNLIKELY( !m_incidentSvc ) ) {
839  error() << "Failed to access incident service." << endmsg;
840  return StatusCode::FAILURE;
841  }
842  // return
843  return StatusCode::SUCCESS;
844 }
845 
848  // Nothing to do: just call base class initialisation
849  setDataLoader( nullptr ).ignore();
850  resetPreLoad().ignore();
851  clearStore().ignore();
853  return Service::finalize();
854 }
855 
857 CLID DataSvc::rootCLID() const { return (CLID)m_rootCLID; }
858 
860 const std::string& DataSvc::rootName() const { return m_rootName; }
861 
864 
StatusCode registerAddress(boost::string_ref fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition: DataSvc.cpp:217
StatusCode unregisterAddress(boost::string_ref fullPath) override
IDataManagerSvc: Unregister object address from the data store.
Definition: DataSvc.cpp:260
Gaudi::Property< CLID > m_rootCLID
Definition: DataSvc.h:51
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
Definition: DataSvc.cpp:768
StatusCode unregisterObject(boost::string_ref fullPath) override
Unregister object from the data store.
Definition: DataSvc.cpp:375
#define VERMSG
Definition: DataSvc.cpp:72
#define UNLIKELY(x)
Definition: Kernel.h:89
constexpr double sr
StatusCode initialize() override
Definition: Service.cpp:60
StatusCode linkObject(IRegistry *from, boost::string_ref objPath, DataObject *to) override
Add a link to another object.
Definition: DataSvc.cpp:702
std::unique_ptr< DataSvcHelpers::RegistryEntry > m_root
Pointer to root entry.
Definition: DataSvc.h:71
RegistryEntry * findLeaf(boost::string_ref path) const
Find identified leaf in this registry node.
Definition: RegistryEntry.h:93
Define general base for Gaudi exception.
DataObject * object() const override
Retrive object behind the link.
const std::string & name() const override
Retrieve name of the service.
Definition: Service.cpp:274
StatusCode preLoad() override
load all preload items of the list
Definition: DataSvc.cpp:803
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
constexpr char SEPARATOR
StatusCode finalize() override
Definition: Service.cpp:164
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Definition: DataSvc.cpp:857
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:309
Gaudi::Property< std::string > m_accessName
Definition: DataSvc.h:64
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
bool isSuccess() const
Definition: StatusCode.h:267
StatusCode setRoot(std::string root_name, DataObject *pRootObj) override
Initialize data store for new event by giving new event path and root object.
Definition: DataSvc.cpp:134
StatusCode setDataLoader(IConversionSvc *svc, IDataProviderSvc *dpsvc=nullptr) override
IDataManagerSvc: IDataManagerSvc: Pass a default data loader to the service and optionally a data pro...
Definition: DataSvc.cpp:179
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Gaudi::Property< std::string > m_rootName
Definition: DataSvc.h:52
virtual StatusCode setDataProvider(IDataProviderSvc *pService)=0
Set Data provider service.
virtual StatusCode loadObject(IRegistry *pNode)
Invoke Persistency service to create transient object from its persistent representation.
Definition: DataSvc.cpp:462
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
Gaudi::Property< bool > m_forceLeaves
Definition: DataSvc.h:55
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:70
Gaudi::Property< bool > m_enableFaultHdlr
Definition: DataSvc.h:58
virtual const name_type & name() const =0
Name of the directory (or key)
StatusCode traverseTree(IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects in the data store.
Definition: DataSvc.cpp:125
bool checkRoot()
Check if root path is valid.
Definition: DataSvc.h:257
DataObject * i_handleDataFault(IRegistry *pReg, boost::string_ref path=boost::string_ref{})
Definition: DataSvc.cpp:431
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, boost::string_ref path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
Definition: DataSvc.cpp:530
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Definition: DataSvc.cpp:775
const Store & leaves() const
Access the leaves of the object.
bool isSoft() const
Is the link soft or hard.
Data provider interface definition.
T remove(T...args)
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
Description of the DataStoreItem class.
Definition: DataStoreItem.h:17
bool isFailure() const
Definition: StatusCode.h:130
StatusCode registerObject(boost::string_ref parentPath, boost::string_ref objPath, DataObject *pObject) override
Register object with the data store.
Definition: DataSvc.cpp:295
StatusCode clearSubTree(boost::string_ref sub_tree_path) override
IDataManagerSvc: Remove all data objects below the sub tree identified by its full path name...
Definition: DataSvc.cpp:77
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:72
virtual StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *refpObject)=0
Update the transient object from the other representation.
STL class.
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:76
T push_back(T...args)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:53
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
void setObject(DataObject *obj)
Set/Update object address.
StatusCode i_retrieveEntry(DataSvcHelpers::RegistryEntry *parentObj, boost::string_ref path, DataSvcHelpers::RegistryEntry *&pEntry)
Definition: DataSvc.cpp:534
Gaudi::Property< std::string > m_faultName
Definition: DataSvc.h:60
virtual const id_type & identifier() const =0
Full identifier (or key)
T what(T...args)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
T append(T...args)
IRegistry * parent() const
Pointer to parent directory entry.
virtual StatusCode updateObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Update the references of an updated transient object.
SmartIF< IIncidentSvc > m_incidentSvc
Pointer to incident service.
Definition: DataSvc.h:49
T erase(T...args)
StatusCode unlinkObject(IRegistry *from, boost::string_ref objPath) override
Remove a link to another object.
Definition: DataSvc.cpp:733
StatusCode objectLeaves(const DataObject *pObject, std::vector< IRegistry * > &refLeaves) override
IDataManagerSvc: Explore the object store: retrieve all leaves attached to the object.
Definition: DataSvc.cpp:200
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
StatusCode finalize() override
Service initialization.
Definition: DataSvc.cpp:847
T reset(T...args)
StatusCode reinitialize() override
Definition: Service.cpp:237
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
IOpaqueAddress * address() const override
Retrieve opaque storage address.
STL class.
T move(T...args)
#define CAST_REGENTRY(x, y)
Definition: DataSvc.cpp:64
virtual DataObject * object() const =0
Retrieve object behind the link.
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
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition: DataSvc.h:56
T get(T...args)
T find(T...args)
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
virtual StatusCode i_setRoot(std::string root_name, DataObject *pRootObj)
Initialize data store for new event by giving new event path and root object.
Definition: DataSvc.cpp:144
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
StatusCode reinitialize() override
Service initialization.
Definition: DataSvc.cpp:824
SmartIF< IConversionSvc > m_dataLoader
Pointer to data loader service.
Definition: DataSvc.h:45
Generic data agent interface.
StatusCode initialize() override
Service initialization.
Definition: DataSvc.cpp:814
RegistryEntry * parentEntry()
Pointer to parent registry entry.
Definition: RegistryEntry.h:91
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:153
decltype(auto) operator+(const T &v, const Property< TP, V, H > &p)
implemantation of (value + property)
Definition: Property.h:707
StatusCode traverseSubTree(boost::string_ref sub_tree_path, IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects below the sub tree identified by its full pat...
Definition: DataSvc.cpp:112
IRegistry * find(const IRegistry *obj) const
Try to find an object identified by its pointer.
string s
Definition: gaudirun.py:312
constexpr static const auto FAILURE
Definition: StatusCode.h:86
Gaudi::Property< bool > m_enableAccessHdlr
Definition: DataSvc.h:62
const std::string & name() const
Retreive DataObject name. It is the name when registered in the store.
Definition: DataObject.cpp:62
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
Definition: DataSvc.cpp:860
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object&#39;s parent.
Definition: DataSvc.cpp:186
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn&#39;t already exist.
Definition: Service.h:83
const std::string & identifier() const override
Full identifier (or key)
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:86
StatusCode remove(boost::string_ref name)
Remove an entry from the store.
bool isEmpty() const
Simple check if the Container is empty.
Data service incident class.
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Opaque address interface definition.
StatusCode retrieveObject(IRegistry *pDirectory, boost::string_ref path, DataObject *&pObject) override
Retrieve object from data store.
Definition: DataSvc.cpp:620
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
Definition: DataSvc.cpp:868
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
Definition: DataSvc.cpp:653
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
StatusCode resetPreLoad() override
Clear the preload list.
Definition: DataSvc.cpp:781
StatusCode findObject(boost::string_ref fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition: DataSvc.cpp:642
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition: DataSvc.h:67
#define ON_VERBOSE
Definition: DataSvc.cpp:69
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
Definition: DataSvc.cpp:863
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition: DataSvc.cpp:103
DataSvcHelpers::RegistryEntry RegEntry
Definition: DataSvc.cpp:66
DataObject * handleDataFault(IRegistry *pReg, boost::string_ref path="")
Invoke data fault handling if enabled.
Definition: DataSvc.cpp:427
void makeHard(DataObject *pObject)
Initialize link as hard link.