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