The Gaudi Framework  v30r4 (9b837755)
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 {
45  std::string operator+( char c, boost::string_ref sr )
46  {
47  std::string s{c};
48  s.append( sr.data(), sr.size() );
49  return s;
50  }
51 
52  boost::string_ref::size_type find( boost::string_ref s, char c, size_t o )
53  {
54  if ( !s.empty() ) s.remove_prefix( o );
55  auto r = s.find( c );
56  return r == boost::string_ref::npos ? r : ( r + o );
57  }
58 
59  std::string to_string( boost::string_ref sr ) { return {sr.data(), sr.size()}; }
60 }
61 
62 // If you absolutely need optimization: switch off dynamic_cast.
63 // This improves access to the data store roughly by 10 %
64 // for balanced trees.
65 //
66 // M.Frank
67 #define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
68 //#define CAST_REGENTRY(x,y) (x)(y)
70 
71 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
72 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
73 
74 #define DEBMSG ON_DEBUG debug()
75 #define VERMSG ON_VERBOSE verbose()
76 
80 StatusCode DataSvc::clearSubTree( boost::string_ref sub_tree_path )
81 {
82  DataObject* pObject = nullptr;
83  StatusCode status = findObject( sub_tree_path, pObject );
84  if ( !status.isSuccess() ) return status;
85  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
86  if ( !node_entry ) return Status::INVALID_OBJECT;
87  RegEntry* parent = node_entry->parentEntry();
88  if ( !parent ) return Status::INVALID_PARENT;
89  parent->remove( node_entry );
90  return StatusCode::SUCCESS;
91 }
92 
97 {
98  if ( !checkRoot() ) return Status::INVALID_ROOT;
99  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
100  if ( !entry ) return Status::INVALID_OBJECT;
101  RegEntry* parent = entry->parentEntry();
102  if ( !parent ) return Status::INVALID_PARENT;
103  parent->remove( entry );
104  return StatusCode::SUCCESS;
105 }
106 
109 {
110  if ( !checkRoot() ) return Status::INVALID_ROOT;
111  m_root.reset();
112  return StatusCode::SUCCESS;
113 }
114 
118 StatusCode DataSvc::traverseSubTree( boost::string_ref sub_tree_path, IDataStoreAgent* pAgent )
119 {
120  DataObject* pO = nullptr;
121  StatusCode status = findObject( sub_tree_path, pO );
122  return status.isSuccess() ? traverseSubTree( pO, pAgent ) : status;
123 }
124 
127 {
128  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
129  return entry ? entry->traverseTree( pAgent ) : Status::INVALID_OBJECT;
130 }
131 
134 {
135  if ( !checkRoot() ) return Status::INVALID_ROOT;
136  return m_root->traverseTree( pAgent );
137 }
138 
144 {
145  clearStore().ignore();
146  return i_setRoot( std::move( root_path ), pRootObj );
147 }
148 
155 {
156  if ( pRootObj ) {
157  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
158  m_root->makeHard( pRootObj );
159  m_root->setDataSvc( this );
160  // No done with GaudiHive. preLoad().ignore();
161  }
162  return StatusCode::SUCCESS;
163 }
164 
170 {
171  clearStore().ignore();
172  return i_setRoot( std::move( root_path ), pRootAddr );
173 }
174 
181 {
182  if ( pRootAddr ) {
183  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
184  m_root->makeHard( pRootAddr );
185  m_root->setDataSvc( this );
186  // Not done with GaudiHive. preLoad().ignore();
187  }
188  return StatusCode::SUCCESS;
189 }
190 
193 {
194  m_dataLoader = pDataLoader;
195  if ( m_dataLoader ) m_dataLoader->setDataProvider( dpsvc ? dpsvc : this ).ignore();
196  return StatusCode::SUCCESS;
197 }
198 
200 StatusCode DataSvc::objectParent( const DataObject* pObject, IRegistry*& refpParent )
201 {
202  if ( !pObject ) return Status::INVALID_OBJECT;
203  return objectParent( pObject->registry(), refpParent );
204 }
206 StatusCode DataSvc::objectParent( const IRegistry* pRegistry, IRegistry*& refpParent )
207 {
208  if ( !checkRoot() ) return Status::INVALID_ROOT;
209  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
210  if ( !node_entry ) return Status::INVALID_OBJECT;
211  refpParent = node_entry->parent();
212  return StatusCode::SUCCESS;
213 }
214 
217 {
218  if ( !pObject ) return Status::INVALID_OBJECT;
219  return objectLeaves( pObject->registry(), leaves );
220 }
221 
226 {
227  if ( !checkRoot() ) return Status::INVALID_ROOT;
228  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
229  if ( !node_entry ) return Status::INVALID_OBJECT;
230  leaves = node_entry->leaves();
231  return StatusCode::SUCCESS;
232 }
233 
235 StatusCode DataSvc::registerAddress( boost::string_ref fullPath, IOpaqueAddress* pAddress )
236 {
237  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
238  return registerAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath, pAddress );
239 }
240 
242 StatusCode DataSvc::registerAddress( IRegistry* parentObj, boost::string_ref objPath, IOpaqueAddress* pAddress )
243 {
244  if ( !checkRoot() ) return Status::INVALID_ROOT;
245  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
246 
247  if ( !parentObj ) {
248  if ( objPath.front() != SEPARATOR ) {
249  return registerAddress( m_root.get(), objPath, pAddress );
250  }
251  auto sep = find( objPath, SEPARATOR, 1 );
252  if ( sep == boost::string_ref::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
253  return Status::INVALID_PARENT;
254  }
255  return registerAddress( m_root.get(), objPath.substr( sep ), pAddress );
256  }
257  if ( objPath.front() != SEPARATOR ) {
258  return registerAddress( parentObj, char( SEPARATOR ) + objPath, pAddress );
259  }
260  RegEntry* par_entry = CAST_REGENTRY( RegEntry*, parentObj );
261  if ( !par_entry ) return Status::INVALID_PARENT;
262 
263  auto sep = objPath.rfind( SEPARATOR );
264  if ( sep > 0 && sep != boost::string_ref::npos ) {
265  auto p_path = objPath.substr( 0, sep );
266  auto o_path = objPath.substr( sep );
267  RegEntry* p_entry = par_entry->findLeaf( p_path );
268  // Create default object leafs if the
269  // intermediate nodes are not present
270  if ( !p_entry && m_forceLeaves ) {
271  DataObject* pLeaf = createDefaultObject();
272  StatusCode sc = registerObject( par_entry->identifier(), p_path, pLeaf );
273  if ( sc.isFailure() ) delete pLeaf;
274  p_entry = par_entry->findLeaf( p_path );
275  }
276  if ( !p_entry ) return Status::INVALID_PARENT;
277  return registerAddress( p_entry, o_path, pAddress );
278  }
279  StatusCode status = par_entry->add( to_string( objPath ), pAddress );
280  return status.isSuccess() ? status : Status::DOUBL_OBJ_PATH;
281 }
282 
284 StatusCode DataSvc::unregisterAddress( boost::string_ref fullPath )
285 {
286  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
287  return unregisterAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath );
288 }
289 
291 StatusCode DataSvc::unregisterAddress( IRegistry* pParent, boost::string_ref objPath )
292 {
293  if ( !checkRoot() ) return Status::INVALID_ROOT;
294  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
295 
296  if ( !pParent ) {
297  if ( objPath.front() != SEPARATOR ) return unregisterAddress( m_root.get(), objPath );
298  auto sep = find( objPath, SEPARATOR, 1 );
299  if ( sep != boost::string_ref::npos && objPath.substr( 0, sep ) == m_rootName.value() ) {
300  return unregisterAddress( m_root.get(), objPath.substr( sep ) );
301  }
302  return Status::INVALID_PARENT;
303  }
304  if ( objPath.front() != SEPARATOR ) {
305  return unregisterAddress( pParent, char( SEPARATOR ) + objPath );
306  }
307  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pParent );
308  if ( node_entry ) {
309  RegEntry* leaf_entry = node_entry->findLeaf( objPath );
310  if ( leaf_entry ) {
311  auto sep = objPath.rfind( SEPARATOR );
312  if ( sep > 0 && sep != boost::string_ref::npos ) {
313  return unregisterAddress( leaf_entry->parent(), objPath.substr( sep ) );
314  }
315  StatusCode status = node_entry->remove( objPath );
316  if ( status.isSuccess() ) return status;
317  }
318  }
319  return Status::INVALID_PARENT;
320 }
321 
323 StatusCode DataSvc::registerObject( boost::string_ref parentPath, boost::string_ref objPath, DataObject* pObject )
324 {
325  DataObject* pO = nullptr;
326  StatusCode status = retrieveObject( parentPath, pO );
327  if ( !status.isSuccess() && m_forceLeaves ) {
328  pO = createDefaultObject();
329  status = registerObject( parentPath, pO );
330  if ( !status.isSuccess() ) pO->release();
331  }
332  return status.isSuccess() ? registerObject( pO, objPath, pObject ) : status;
333 }
334 
336 StatusCode DataSvc::registerObject( DataObject* parentObj, boost::string_ref objPath, DataObject* pObject )
337 {
338  if ( !checkRoot() ) return Status::INVALID_ROOT;
339 
340  if ( !parentObj ) {
341  if ( !objPath.empty() ) {
342  if ( objPath.front() != SEPARATOR ) {
343  return registerObject( m_rootName.value(), objPath, pObject );
344  }
345  auto sep = find( objPath, SEPARATOR, 1 );
346  if ( sep != boost::string_ref::npos ) {
347  return registerObject( objPath.substr( 0, sep ), objPath.substr( sep ), pObject );
348  }
349  }
350  return Status::INVALID_OBJ_PATH;
351  }
352  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, parentObj->registry() );
353  if ( node_entry ) {
354  StatusCode status = Status::INVALID_PARENT;
355  auto sep = find( objPath, SEPARATOR, 1 );
356  if ( sep != boost::string_ref::npos ) {
357  auto p_path = objPath.substr( 0, sep );
358  auto o_path = objPath.substr( sep );
359  RegEntry* par_entry = node_entry->findLeaf( p_path );
360  // Create default object leafs if the
361  // intermediate nodes are not present
362  if ( !par_entry && m_forceLeaves ) {
363  DataObject* pLeaf = createDefaultObject();
364  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
365  if ( !sc.isSuccess() ) delete pLeaf;
366  par_entry = node_entry->findLeaf( p_path );
367  } else if ( par_entry && !par_entry->object() ) {
368  status = i_retrieveEntry( node_entry, p_path, par_entry );
369  if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
370  DataObject* pLeaf = createDefaultObject();
371  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
372  if ( !sc.isSuccess() ) delete pLeaf;
373  par_entry = node_entry->findLeaf( p_path );
374  }
375  }
376  node_entry = par_entry;
377  if ( node_entry ) {
378  DataObject* obj = node_entry->object();
379  if ( obj ) status = registerObject( obj, o_path, pObject );
380  }
381  } else {
382  RegEntry* leaf = node_entry->findLeaf( objPath );
383  if ( !leaf ) {
384  status = node_entry->add( to_string( objPath ), pObject );
385  } else {
386  DataObject* obj = leaf->object();
387  if ( !obj ) {
388  if ( !pObject ) {
389  error() << "registerObject: trying to register null DataObject" << endmsg;
390  return StatusCode::FAILURE;
391  }
392  pObject->setRegistry( leaf );
393  leaf->setAddress( nullptr );
394  leaf->setObject( pObject );
395  status = StatusCode::SUCCESS;
396  } else {
397  status = Status::DOUBL_OBJ_PATH;
398  }
399  }
400  }
401  return status;
402  }
403  return Status::INVALID_PARENT;
404 }
405 
407 StatusCode DataSvc::unregisterObject( boost::string_ref fullPath )
408 {
409  DataObject* pObject = nullptr;
410  StatusCode status = findObject( fullPath, pObject );
411  if ( status.isFailure() ) return status;
412  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pObject->registry() );
413  if ( !pEntry ) return Status::INVALID_ROOT;
414  if ( !pEntry->isEmpty() ) return Status::DIR_NOT_EMPTY;
415  RegEntry* pParent = pEntry->parentEntry();
416  if ( !pParent ) return Status::INVALID_PARENT;
417  if ( pObject ) pObject->addRef();
418  pParent->remove( pEntry );
419  return StatusCode::SUCCESS;
420 }
421 
424 {
425  if ( !checkRoot() ) return Status::INVALID_ROOT;
426  RegEntry* entry = m_root->findLeaf( pObject );
427  if ( !entry ) return Status::INVALID_OBJECT;
428  RegEntry* parent = entry->parentEntry();
429  if ( !parent ) return Status::INVALID_PARENT;
430  if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
431  if ( entry->object() ) entry->object()->addRef();
432  if ( parent ) parent->remove( entry );
433  return StatusCode::SUCCESS;
434 }
435 
437 StatusCode DataSvc::unregisterObject( DataObject* pParentObj, boost::string_ref objectPath )
438 {
439  if ( checkRoot() ) {
440  try {
441  RegEntry* parent = CAST_REGENTRY( RegEntry*, pParentObj->registry() );
442  if ( parent ) {
443  RegEntry* entry = parent->findLeaf( objectPath );
444  if ( entry ) {
445  if ( entry->isEmpty() ) {
446  if ( entry->object() ) {
447  entry->object()->addRef();
448  }
449  parent->remove( entry );
450  return StatusCode::SUCCESS;
451  }
452  return Status::DIR_NOT_EMPTY;
453  }
454  return Status::INVALID_OBJECT;
455  }
456  } catch ( ... ) {
457  }
458  return Status::INVALID_PARENT;
459  }
460  return Status::INVALID_ROOT;
461 }
462 
465 DataObject* DataSvc::handleDataFault( IRegistry* pReg, boost::string_ref path )
466 {
467  return i_handleDataFault( pReg, path );
468 }
469 
471 {
472  if ( m_enableFaultHdlr ) {
473  IRegistry* pLeaf = nullptr;
474  if ( pReg && path.empty() ) {
475  DataIncident incident( name(), m_faultName, pReg->identifier() );
476  m_incidentSvc->fireIncident( incident );
477  return pReg->object();
478  }
479  if ( pReg ) {
480  std::string p = pReg->identifier();
481  if ( path.front() != SEPARATOR ) p += SEPARATOR;
482  p.append( path.data(), path.size() );
483  DataIncident incident( name(), m_faultName, p );
484  m_incidentSvc->fireIncident( incident );
485  pLeaf = m_root->findLeaf( p );
486  } else {
488  if ( path.front() != SEPARATOR ) p += SEPARATOR;
489  p.append( path.data(), path.size() );
490  DataIncident incident( name(), m_faultName, p );
491  m_incidentSvc->fireIncident( incident );
492  pLeaf = m_root->findLeaf( p );
493  }
494  if ( pLeaf ) {
495  return pLeaf->object();
496  }
497  }
498  return nullptr;
499 }
500 
505 {
506  IConversionSvc* pLoader = getDataLoader( pRegistry );
507  return loadObject( pLoader, pRegistry );
508 }
509 
514 {
515  StatusCode status = Status::INVALID_OBJ_ADDR;
516  DataObject* pObject = nullptr;
517  if ( !pLoader ) { // Precondition: Data loader must be present
518  return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::NO_DATA_LOADER );
519  }
520  if ( !pRegistry ) { // Precondition: Directory must be valid
521  return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::INVALID_OBJ_ADDR );
522  }
523 
524  VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
525 
526  if ( m_enableAccessHdlr ) {
527  // Fire data access incident
528  DataIncident incident( name(), m_accessName, pRegistry->identifier() );
529  m_incidentSvc->fireIncident( incident );
530  }
531  if ( !m_inhibitPathes.empty() ) {
532  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
533  if ( inhibit != m_inhibitPathes.end() ) {
534  return Status::NO_ACCESS;
535  }
536  }
537  IOpaqueAddress* pAddress = pRegistry->address();
538  if ( !pAddress ) { // Precondition:
539  return Status::INVALID_OBJ_ADDR; // Address must be valid
540  }
541  try {
542  status = pLoader->createObj( pAddress, pObject ); // Call data loader
543  if ( status.isSuccess() ) {
544 
545  VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
546 
547  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pRegistry );
548  pEntry->setObject( pObject );
549 
550  VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
551  status = pLoader->fillObjRefs( pAddress, pObject );
552  }
553  } catch ( const GaudiException& exc ) {
554  if ( handleDataFault( pRegistry ) ) {
555  return StatusCode::SUCCESS;
556  }
557  throw GaudiException( "GaudiException in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE,
558  exc );
559  } catch ( const std::exception& x ) {
560  if ( handleDataFault( pRegistry ) ) {
561  return StatusCode::SUCCESS;
562  }
563  throw GaudiException( "std::exception in loadObject() " + pRegistry->identifier() + ": " +
564  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
566  } catch ( ... ) {
567  if ( handleDataFault( pRegistry ) ) {
568  return StatusCode::SUCCESS;
569  }
570  throw GaudiException( "UNKN exception in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE );
571  }
572  if ( !status.isSuccess() ) {
573  if ( handleDataFault( pRegistry ) ) {
574  return StatusCode::SUCCESS;
575  }
576  }
577  ON_VERBOSE if ( status.isSuccess() )
578  {
579  verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
580  }
581  return status;
582 }
583 
585 StatusCode DataSvc::retrieveEntry( RegEntry* parentObj, boost::string_ref path, RegEntry*& pEntry )
586 {
587  return i_retrieveEntry( parentObj, path, pEntry );
588 }
589 
590 StatusCode DataSvc::i_retrieveEntry( RegEntry* parentObj, boost::string_ref path, RegEntry*& pEntry )
591 {
592  // A.Valassi 16.08.2001 avoid core dump if store is empty
593  if ( !checkRoot() ) return StatusCode( Status::INVALID_ROOT, true );
594 
595  static constexpr auto empty = boost::string_ref{};
596  auto sep = find( path, SEPARATOR, 1 );
597  pEntry = nullptr;
598 
599  if ( !parentObj ) {
600  if ( path.empty() || path == m_rootName.value() ) {
601  parentObj = m_root.get();
602  path = empty;
603  } else if ( path.front() != SEPARATOR ) {
604  parentObj = m_root.get();
605  } else if ( sep != boost::string_ref::npos ) {
606  if ( !m_root->object() ) {
607  RegEntry* r = nullptr;
608  auto status = i_retrieveEntry( m_root.get(), empty, r );
609  if ( !status.isSuccess() ) return status;
610  }
611  parentObj = m_root.get();
612  path = path.substr( sep );
613  } else {
614  return Status::INVALID_OBJ_PATH;
615  }
616  sep = find( path, SEPARATOR, 1 );
617  }
618 
619  StatusCode status = StatusCode( Status::INVALID_ROOT, true );
620  if ( sep != boost::string_ref::npos ) { // the string contains a separator (after pos 0)
621  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
622  status = loadObject( parentObj );
623  if ( !status.isSuccess() ) return status;
624  }
625  auto p_path = path.substr( 0, sep );
626  RegEntry* root_entry = parentObj->findLeaf( p_path );
627  if ( !root_entry && m_enableFaultHdlr ) {
628  // If not even the parent is there, an incident
629  // to load the parent must be fired...
630  i_handleDataFault( parentObj, p_path );
631  root_entry = parentObj->findLeaf( p_path );
632  }
633  if ( root_entry ) {
634  DataObject* pO = root_entry->object();
635  if ( !pO ) {
636  // Object is not loaded: load the object if at all possible
637  status = loadObject( root_entry );
638  if ( !status.isSuccess() ) return status;
639  }
640  if ( root_entry->isSoft() ) {
641  root_entry = CAST_REGENTRY( RegEntry*, pO->registry() );
642  }
643  return i_retrieveEntry( root_entry, path.substr( sep ), pEntry );
644  }
645  return status;
646  } else if ( path.empty() ) {
647  pEntry = parentObj;
648  } else {
649  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
650  status = loadObject( parentObj );
651  if ( !status.isSuccess() ) return status;
652  }
653  // last leave in search: find leaf and load
654  pEntry = parentObj->findLeaf( path );
655  // If no registry entry was found, trigger incident for action-on-demand
656  if ( !pEntry && m_enableFaultHdlr ) {
657  i_handleDataFault( parentObj, path );
658  pEntry = ( path.empty() ? parentObj : parentObj->findLeaf( path ) );
659  }
660  }
661 
662  // Check results and return
663  if ( !pEntry ) return Status::INVALID_OBJ_PATH;
664  if ( !pEntry->object() ) return loadObject( pEntry );
665 
666  if ( m_enableAccessHdlr ) {
667  // Fire data access incident
668  // I do not know if this is a good idea....
669  // This fires too often!
670  //
671  // DataIncident incident(name(), m_accessName, pEntry->identifier());
672  // m_incidentSvc->fireIncident(incident);
673  return StatusCode::SUCCESS;
674  }
675  return StatusCode::SUCCESS;
676 }
677 
679 StatusCode DataSvc::retrieveObject( IRegistry* pRegistry, boost::string_ref path, DataObject*& pObject )
680 {
681  pObject = nullptr;
682  RegEntry * result = nullptr, *parent = CAST_REGENTRY( RegEntry *, pRegistry );
683  StatusCode status = i_retrieveEntry( parent, path, result );
684  if ( status.isSuccess() ) pObject = result->object();
685  return status;
686 }
687 
689 StatusCode DataSvc::findObject( IRegistry* pRegistry, boost::string_ref path, DataObject*& pObject )
690 {
691  pObject = nullptr;
692  IRegistry* pReg = ( pRegistry ? pRegistry : m_root.get() );
693  RegEntry* root_entry = CAST_REGENTRY( RegEntry*, pReg );
694  if ( root_entry ) {
695  if ( !path.empty() ) pReg = root_entry->find( path );
696  if ( !pReg ) return Status::INVALID_OBJ_PATH;
697  pObject = pReg->object();
698  }
699  return ( !pObject ) ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
700 }
701 
703 StatusCode DataSvc::findObject( boost::string_ref path, DataObject*& pObject )
704 {
705  pObject = nullptr;
706  if ( !checkRoot() ) return Status::INVALID_ROOT;
707  if ( path.empty() || path == m_rootName.value() ) {
708  pObject = m_root->object();
709  return !pObject ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
710  }
711  return findObject( path.front() != SEPARATOR ? m_root.get() : nullptr, path, pObject );
712 }
713 
716 {
717  if ( !pRegistry ) { // Precondition:
718  return Status::INVALID_OBJ_ADDR; // Addres must be valid
719  }
720  DataObject* toUpdate = pRegistry->object();
721  if ( !toUpdate ) { // Try first to load
722  return loadObject( pRegistry );
723  }
724  return updateObject( toUpdate );
725 }
726 
729 {
730  StatusCode status = Status::INVALID_OBJ_ADDR;
731  if ( !toUpdate ) { // Precondition:
732  return Status::INVALID_OBJECT; // Address must be valid
733  }
734  IRegistry* pRegistry = toUpdate->registry(); // Precondition:
735  if ( !pRegistry ) { // Need valid registry
736  return Status::INVALID_OBJECT;
737  }
738  IOpaqueAddress* pAddress = pRegistry->address(); // Precondition:
739  if ( !pAddress ) { // Need valid address
740  return Status::INVALID_OBJ_ADDR;
741  }
742  IConversionSvc* pLoader = getDataLoader( pRegistry );
743  if ( !pLoader ) { // Precondition:
744  return Status::NO_DATA_LOADER; // Data loader must be present
745  }
746  if ( !m_inhibitPathes.empty() ) {
747  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
748  if ( inhibit != m_inhibitPathes.end() ) {
749  return Status::NO_ACCESS;
750  }
751  }
752  try {
753  status = pLoader->updateObj( pAddress, toUpdate ); // Call data loader
754  if ( status.isSuccess() ) {
755  status = pLoader->updateObjRefs( pAddress, toUpdate );
756  }
757  } catch ( const GaudiException& exc ) {
758  throw GaudiException( "GaudiException in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE, exc );
759  } catch ( const std::exception& x ) {
760  throw GaudiException( "std::exception in updateObject() " + pRegistry->name() + ": " +
761  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
763  } catch ( ... ) {
764  throw GaudiException( "UNKN exception in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE );
765  }
766  return status;
767 }
768 
769 // Link object
770 StatusCode DataSvc::linkObject( IRegistry* from, boost::string_ref objPath, DataObject* to )
771 {
772  if ( !checkRoot() ) return Status::INVALID_ROOT;
773  try {
774  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
775  if ( from_entry ) {
776  // First check if both objects are already registered to the store
777  RegEntry* to_entry = m_root->findLeaf( to );
778  if ( !to_entry ) return Status::INVALID_OBJECT;
779  auto sep = objPath.rfind( SEPARATOR );
780  if ( sep > 0 && sep != boost::string_ref::npos ) { // in case the objPath is a sub-directory itself
781  DataObject* pO = nullptr;
782  StatusCode sc = retrieveObject( from, objPath.substr( 0, sep ), pO );
783  return sc.isSuccess() ? linkObject( pO->registry(), objPath.substr( sep ), to ) : sc;
784  }
785  // Now register the soft link
786  StatusCode status = from_entry->add( to_string( objPath ), to, true );
787  return status.isSuccess() ? Status::IDataProviderSvc_NO_ERROR : Status::DOUBL_OBJ_PATH;
788  }
789  } catch ( ... ) {
790  }
791  return Status::INVALID_PARENT;
792 }
793 
795 StatusCode DataSvc::linkObject( boost::string_ref fullPath, DataObject* to )
796 {
797  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
798  if ( fullPath.front() != SEPARATOR ) {
799  return linkObject( m_rootName.value(), fullPath, to );
800  }
801  auto sep = fullPath.rfind( SEPARATOR );
802  return linkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ), to );
803 }
804 
806 StatusCode DataSvc::unlinkObject( IRegistry* from, boost::string_ref objPath )
807 {
808  if ( !checkRoot() ) return Status::INVALID_ROOT;
809  try {
810  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
811  if ( from_entry ) {
812  auto sep = objPath.rfind( SEPARATOR );
813  if ( sep > 0 && sep != boost::string_ref::npos ) { // in case the objPath is a sub-directory itself
814  DataObject* pO = nullptr;
815  StatusCode sc = findObject( from, objPath.substr( 0, sep ), pO );
816  return sc.isSuccess() ? unlinkObject( pO->registry(), objPath.substr( sep ) ) : sc;
817  }
818  StatusCode status = from_entry->remove( objPath );
819  if ( status.isSuccess() ) return status;
820  return Status::INVALID_OBJ_PATH;
821  }
822  } catch ( ... ) {
823  }
824  return Status::INVALID_PARENT;
825 }
826 
828 StatusCode DataSvc::unlinkObject( boost::string_ref fullPath )
829 {
830  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
831  if ( fullPath.front() != SEPARATOR ) return unlinkObject( m_rootName.value(), fullPath );
832  auto sep = fullPath.rfind( SEPARATOR );
833  return unlinkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ) );
834 }
835 
837 StatusCode DataSvc::unlinkObject( DataObject* from, boost::string_ref objPath )
838 {
839  if ( !checkRoot() ) return Status::INVALID_ROOT;
840  IRegistry* from_entry = m_root->findLeaf( from );
841  return unlinkObject( from_entry, objPath );
842 }
843 
846 {
847  auto i = std::find( begin( m_preLoads ), end( m_preLoads ), item );
848  if ( i == end( m_preLoads ) ) m_preLoads.push_back( item );
849  return StatusCode::SUCCESS;
850 }
851 
854 {
856  return StatusCode::SUCCESS;
857 }
858 
861 {
863  return StatusCode::SUCCESS;
864 }
865 
867 StatusCode DataSvc::preLoad( int depth, int load_depth, DataObject* pObject )
868 {
869  // unused: StatusCode sc = StatusCode::FAILURE;
870  if ( pObject && depth++ < load_depth ) {
871  RegEntry* dir = CAST_REGENTRY( RegEntry*, pObject->registry() );
872  if ( dir ) {
873  for ( const auto& i : *dir ) {
874  DataObject* pObj = nullptr;
875  StatusCode status = retrieveObject( pObject, i->name(), pObj );
876  if ( status.isSuccess() && depth < load_depth ) {
877  preLoad( depth, load_depth, pObj ).ignore();
878  }
879  }
880  }
881  }
882  return StatusCode::SUCCESS;
883 }
884 
887 {
888  DataObject* pObj = nullptr;
889  for ( const auto& i : m_preLoads ) {
890  StatusCode sc = retrieveObject( i.path(), pObj );
891  int load_depth = i.depth();
892  if ( sc.isSuccess() && load_depth > 1 ) {
893  preLoad( 1, load_depth, pObj ).ignore();
894  }
895  }
896  return StatusCode::SUCCESS;
897 }
898 
901 {
902  // Nothing to do: just call base class initialisation
904  if ( UNLIKELY( !sc.isSuccess() ) ) return sc;
905  m_incidentSvc = service( "IncidentSvc", true );
906  if ( UNLIKELY( !m_incidentSvc ) ) {
907  error() << "Failed to access incident service." << endmsg;
908  }
909  return sc;
910 }
911 
914 {
915  // the finalize part is copied here
916  setDataLoader( nullptr ).ignore();
917  resetPreLoad().ignore();
918  clearStore().ignore();
920  // re-initialize the base class
922  if ( UNLIKELY( !sc.isSuccess() ) ) {
923  error() << "Unable to reinitialize base class" << endmsg;
924  return sc;
925  }
926  // the initialize part is copied here
927  m_incidentSvc = service( "IncidentSvc", true );
928  if ( UNLIKELY( !m_incidentSvc ) ) {
929  error() << "Failed to access incident service." << endmsg;
930  return StatusCode::FAILURE;
931  }
932  // return
933  return StatusCode::SUCCESS;
934 }
935 
938 {
939  // Nothing to do: just call base class initialisation
940  setDataLoader( nullptr ).ignore();
941  resetPreLoad().ignore();
942  clearStore().ignore();
944  return Service::finalize();
945 }
946 
948 CLID DataSvc::rootCLID() const { return (CLID)m_rootCLID; }
949 
951 const std::string& DataSvc::rootName() const { return m_rootName; }
952 
955 
StatusCode registerAddress(boost::string_ref fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition: DataSvc.cpp:235
StatusCode unregisterAddress(boost::string_ref fullPath) override
IDataManagerSvc: Unregister object address from the data store.
Definition: DataSvc.cpp:284
Gaudi::Property< CLID > m_rootCLID
Definition: DataSvc.h:53
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
Definition: DataSvc.cpp:845
StatusCode unregisterObject(boost::string_ref fullPath) override
Unregister object from the data store.
Definition: DataSvc.cpp:407
#define VERMSG
Definition: DataSvc.cpp:75
#define UNLIKELY(x)
Definition: Kernel.h:89
constexpr static const auto FAILURE
Definition: StatusCode.h:88
constexpr double sr
StatusCode initialize() override
Definition: Service.cpp:63
StatusCode linkObject(IRegistry *from, boost::string_ref objPath, DataObject *to) override
Add a link to another object.
Definition: DataSvc.cpp:770
std::unique_ptr< DataSvcHelpers::RegistryEntry > m_root
Pointer to root entry.
Definition: DataSvc.h:73
RegistryEntry * findLeaf(boost::string_ref path) const
Find identified leaf in this registry node.
Definition: RegistryEntry.h:95
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:288
StatusCode preLoad() override
load all preload items of the list
Definition: DataSvc.cpp:886
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
constexpr char SEPARATOR
StatusCode finalize() override
Definition: Service.cpp:173
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Definition: DataSvc.cpp:948
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:332
Gaudi::Property< std::string > m_accessName
Definition: DataSvc.h:66
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
bool isSuccess() const
Definition: StatusCode.h:287
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:143
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:192
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Gaudi::Property< std::string > m_rootName
Definition: DataSvc.h:54
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:504
Gaudi::Property< bool > m_forceLeaves
Definition: DataSvc.h:57
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:71
Gaudi::Property< bool > m_enableFaultHdlr
Definition: DataSvc.h:60
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:133
bool checkRoot()
Check if root path is valid.
Definition: DataSvc.h:259
DataObject * i_handleDataFault(IRegistry *pReg, boost::string_ref path=boost::string_ref{})
Definition: DataSvc.cpp:470
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, boost::string_ref path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
Definition: DataSvc.cpp:585
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Definition: DataSvc.cpp:853
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:139
StatusCode registerObject(boost::string_ref parentPath, boost::string_ref objPath, DataObject *pObject) override
Register object with the data store.
Definition: DataSvc.cpp:323
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:80
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:73
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:82
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:59
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:590
Gaudi::Property< std::string > m_faultName
Definition: DataSvc.h:62
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:51
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:51
T erase(T...args)
StatusCode unlinkObject(IRegistry *from, boost::string_ref objPath) override
Remove a link to another object.
Definition: DataSvc.cpp:806
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:216
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:91
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:937
T reset(T...args)
StatusCode reinitialize() override
Definition: Service.cpp:249
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:67
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
virtual DataObject * object() const =0
Retrieve object behind the link.
Definition of an entry in the transient data store.
Definition: RegistryEntry.h:37
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:51
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition: DataSvc.h:58
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:154
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
StatusCode reinitialize() override
Service initialization.
Definition: DataSvc.cpp:913
SmartIF< IConversionSvc > m_dataLoader
Pointer to data loader service.
Definition: DataSvc.h:47
Generic data agent interface.
StatusCode initialize() override
Service initialization.
Definition: DataSvc.cpp:900
RegistryEntry * parentEntry()
Pointer to parent registry entry.
Definition: RegistryEntry.h:93
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:165
decltype(auto) operator+(const T &v, const Property< TP, V, H > &p)
implemantation of (value + property)
Definition: Property.h:819
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:118
IRegistry * find(const IRegistry *obj) const
Try to find an object identified by its pointer.
string s
Definition: gaudirun.py:253
Gaudi::Property< bool > m_enableAccessHdlr
Definition: DataSvc.h:64
const std::string & name() const
Retreive DataObject name. It is the name when registered in the store.
Definition: DataObject.cpp:68
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
Definition: DataSvc.cpp:951
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object&#39;s parent.
Definition: DataSvc.cpp:200
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:84
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:92
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:679
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
Definition: DataSvc.cpp:959
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
Definition: DataSvc.cpp:715
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:860
StatusCode findObject(boost::string_ref fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition: DataSvc.cpp:703
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition: DataSvc.h:69
#define ON_VERBOSE
Definition: DataSvc.cpp:72
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
Definition: DataSvc.cpp:954
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition: DataSvc.cpp:108
DataSvcHelpers::RegistryEntry RegEntry
Definition: DataSvc.cpp:69
DataObject * handleDataFault(IRegistry *pReg, boost::string_ref path="")
Invoke data fault handling if enabled.
Definition: DataSvc.cpp:465
void makeHard(DataObject *pObject)
Initialize link as hard link.