The Gaudi Framework  v30r4 (9b837755)
TsDataSvc.cpp
Go to the documentation of this file.
1 //====================================================================
2 // TsDataSvc.cpp
3 //--------------------------------------------------------------------
4 //
5 // Package : System ( The LHCb Offline System)
6 //
7 // Description: implementation of the Transient data service: TsDataSvc
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 // | 25/4/13 | Locking for concurrent access introduced. | D.Piparo
17 // +---------+----------------------------------------------+---------
18 //
19 //====================================================================
20 #define TSDATASVC_DATASVC_CPP
21 
22 // Framework include files
24 #include "GaudiKernel/IConverter.h"
26 
27 #include "GaudiKernel/DataObject.h"
29 
33 #include "GaudiKernel/TsDataSvc.h"
34 
35 // Include files
36 #include <algorithm>
37 #include <cassert>
38 #include <cstdlib>
39 #include <mutex>
40 #include <sstream>
41 #include <vector>
42 
43 // Macro to lock a scope
44 #define STD_LOCK_GUARD_MACRO std::lock_guard<tsDataSvcMutex> lock( m_accessMutex );
45 
46 namespace
47 {
48  std::string operator+( char c, boost::string_ref sr )
49  {
50  std::string s{c};
51  s.append( sr.data(), sr.size() );
52  return s;
53  }
54 
55  boost::string_ref::size_type find( boost::string_ref s, char c, size_t o )
56  {
57  if ( !s.empty() ) s.remove_prefix( o );
58  auto r = s.find( c );
59  return r == boost::string_ref::npos ? r : ( r + o );
60  }
61 }
62 
63 // If you absolutely need optimization: switch off dynamic_cast.
64 // This improves access to the data store roughly by 10 %
65 // for balanced trees.
66 //
67 // M.Frank
68 #define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
69 //#define CAST_REGENTRY(x,y) (x)(y)
71 
72 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
73 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
74 
75 #define DEBMSG ON_DEBUG debug()
76 #define VERMSG ON_VERBOSE verbose()
77 
81 StatusCode TsDataSvc::clearSubTree( boost::string_ref sub_tree_path )
82 {
83  DataObject* pObject = nullptr;
84  StatusCode status = findObject( sub_tree_path, pObject );
85  if ( !status.isSuccess() ) return status;
86  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
87  if ( !node_entry ) return Status::INVALID_OBJECT;
88  RegEntry* parent = node_entry->parentEntry();
89  if ( !parent ) return Status::INVALID_PARENT;
90  parent->remove( node_entry );
91  return StatusCode::SUCCESS;
92 }
93 
98 {
99  if ( !checkRoot() ) return Status::INVALID_ROOT;
100  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
101  if ( !entry ) return Status::INVALID_OBJECT;
102  RegEntry* parent = entry->parentEntry();
103  if ( !parent ) return Status::INVALID_PARENT;
104  parent->remove( entry );
105  return StatusCode::SUCCESS;
106 }
107 
110 {
111  if ( !checkRoot() ) return Status::INVALID_ROOT;
112  m_root.reset();
113  return StatusCode::SUCCESS;
114 }
115 
119 StatusCode TsDataSvc::traverseSubTree( boost::string_ref sub_tree_path, IDataStoreAgent* pAgent )
120 {
121  DataObject* pO = nullptr;
122  StatusCode status = findObject( sub_tree_path, pO );
123  return status.isSuccess() ? traverseSubTree( pO, pAgent ) : status;
124 }
125 
128 {
130  if ( !checkRoot() ) return Status::INVALID_ROOT;
131  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
132  if ( !entry ) return Status::INVALID_OBJECT;
133  return entry->traverseTree( pAgent );
134 }
135 
138 {
140  if ( !checkRoot() ) return Status::INVALID_ROOT;
141  return m_root->traverseTree( pAgent );
142 }
143 
149 {
150  clearStore().ignore();
151  return i_setRoot( std::move( root_path ), pRootObj );
152 }
153 
160 {
161  if ( pRootObj ) {
162  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
163  m_root->makeHard( pRootObj );
164  m_root->setDataSvc( this );
165  // No done with GaudiHive. preLoad().ignore();
166  }
167  return StatusCode::SUCCESS;
168 }
169 
175 {
176  clearStore().ignore();
177  return i_setRoot( std::move( root_path ), pRootAddr );
178 }
179 
186 {
187  if ( pRootAddr ) {
188  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
189  m_root->makeHard( pRootAddr );
190  m_root->setDataSvc( this );
191  // Not done with GaudiHive. preLoad().ignore();
192  }
193  return StatusCode::SUCCESS;
194 }
195 
198 {
199  if ( pDataLoader ) pDataLoader->addRef();
201  if ( pDataLoader ) {
202  pDataLoader->setDataProvider( dpsvc == nullptr ? this : dpsvc ).ignore();
203  }
204  m_dataLoader = pDataLoader;
205  return StatusCode::SUCCESS;
206 }
207 
210 {
211  if ( !pObject ) return Status::INVALID_OBJECT;
212  return objectParent( pObject->registry(), refpParent );
213 }
215 StatusCode TsDataSvc::objectParent( const IRegistry* pRegistry, IRegistry*& refpParent )
216 {
218  if ( !checkRoot() ) return Status::INVALID_ROOT;
219  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
220  if ( !node_entry ) return Status::INVALID_OBJECT;
221  refpParent = node_entry->parent();
222  return StatusCode::SUCCESS;
223 }
224 
227 {
228  if ( !pObject ) return Status::INVALID_OBJECT;
229  return objectLeaves( pObject->registry(), leaves );
230 }
231 
236 {
237  if ( !pRegistry ) return Status::INVALID_OBJECT;
238  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
239  if ( !node_entry ) return Status::INVALID_OBJECT;
241  leaves.insert( leaves.end(), node_entry->leaves().begin(), node_entry->leaves().end() );
242  // leaves = node_entry->leaves();
243  return StatusCode::SUCCESS;
244 }
245 
247 StatusCode TsDataSvc::registerAddress( boost::string_ref fullPath, IOpaqueAddress* pAddress )
248 {
249  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
250  return registerAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath, pAddress );
251 }
252 
254 StatusCode TsDataSvc::registerAddress( IRegistry* parentObj, boost::string_ref objPath, IOpaqueAddress* pAddress )
255 {
256  if ( !checkRoot() ) return Status::INVALID_ROOT;
257  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
258  if ( !parentObj ) {
259  if ( objPath.front() != SEPARATOR ) {
260  return registerAddress( m_root.get(), objPath, pAddress );
261  }
262  auto sep = find( objPath, SEPARATOR, 1 );
263  if ( sep == boost::string_ref::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
264  return Status::INVALID_PARENT;
265  }
266  return registerAddress( m_root.get(), objPath.substr( sep ), pAddress );
267  }
268  if ( objPath.front() != SEPARATOR ) {
269  return registerAddress( parentObj, SEPARATOR + objPath, pAddress );
270  }
271  RegEntry* par_entry = CAST_REGENTRY( RegEntry*, parentObj );
272  if ( !par_entry ) return Status::INVALID_PARENT;
273  auto sep = objPath.rfind( SEPARATOR );
274  if ( sep > 0 && sep != boost::string_ref::npos ) {
275  auto p_path = objPath.substr( 0, sep );
276  auto o_path = objPath.substr( sep );
277  RegEntry* p_entry = par_entry->findLeaf( p_path );
278  // Create default object leafs if the
279  // intermediate nodes are not present
280  if ( !p_entry && m_forceLeaves ) {
281  DataObject* pLeaf = createDefaultObject();
282  StatusCode sc = registerObject( par_entry->identifier(), p_path, pLeaf );
283  if ( !sc.isSuccess() ) delete pLeaf;
284  p_entry = par_entry->findLeaf( p_path );
285  }
286  if ( !p_entry ) return Status::INVALID_PARENT;
287  return registerAddress( p_entry, o_path, pAddress );
288  }
289  StatusCode status = par_entry->add( objPath.to_string(), pAddress );
290  return status.isSuccess() ? status : Status::DOUBL_OBJ_PATH;
291 }
292 
294 StatusCode TsDataSvc::unregisterAddress( boost::string_ref fullPath )
295 {
296  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
297  return unregisterAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath );
298 }
299 
301 StatusCode TsDataSvc::unregisterAddress( IRegistry* pParent, boost::string_ref objPath )
302 {
303  if ( !checkRoot() ) return Status::INVALID_ROOT;
304 
305  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
306  if ( !pParent ) {
307  if ( objPath.front() != SEPARATOR ) {
308  return unregisterAddress( m_root.get(), objPath );
309  }
310  auto sep = find( objPath, SEPARATOR, 1 );
311  if ( sep == boost::string_ref::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
312  return Status::INVALID_PARENT;
313  }
314  return unregisterAddress( m_root.get(), objPath.substr( sep ) );
315  }
316  if ( objPath.front() != SEPARATOR ) {
317  return unregisterAddress( pParent, SEPARATOR + objPath );
318  }
319  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pParent );
320  if ( node_entry ) {
321  RegEntry* leaf_entry = node_entry->findLeaf( objPath );
322  if ( leaf_entry ) {
323  auto sep = objPath.rfind( SEPARATOR );
324  if ( sep > 0 && sep != boost::string_ref::npos ) {
325  return unregisterAddress( leaf_entry->parent(), objPath.substr( sep ) );
326  }
327  StatusCode status = node_entry->remove( objPath );
328  if ( status.isSuccess() ) return status;
329  }
330  }
331  return Status::INVALID_PARENT;
332 }
333 
335 StatusCode TsDataSvc::registerObject( boost::string_ref parentPath, boost::string_ref objPath, DataObject* pObject )
336 {
337  DataObject* pO = nullptr;
338  StatusCode status = retrieveObject( parentPath, pO );
339  if ( !status.isSuccess() && m_forceLeaves ) {
340  pO = createDefaultObject();
341  status = registerObject( parentPath, pO );
342  if ( !status.isSuccess() ) pO->release();
343  }
344  return status.isSuccess() ? registerObject( pO, objPath, pObject ) : status;
345 }
346 
348 StatusCode TsDataSvc::registerObject( DataObject* parentObj, boost::string_ref objPath, DataObject* pObject )
349 {
350  if ( !checkRoot() ) return Status::INVALID_ROOT;
351  if ( !parentObj ) {
352  if ( !objPath.empty() ) {
353  if ( objPath.front() != SEPARATOR ) {
354  return registerObject( m_rootName.value(), objPath, pObject );
355  }
356  auto sep = find( objPath, SEPARATOR, 1 );
357  if ( sep != boost::string_ref::npos ) {
358  return registerObject( objPath.substr( 0, sep ), objPath.substr( sep ), pObject );
359  }
360  }
361  return Status::INVALID_OBJ_PATH;
362  }
363  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, parentObj->registry() );
364  if ( node_entry ) {
365  StatusCode status = Status::INVALID_PARENT;
366  auto sep = find( objPath, SEPARATOR, 1 );
367  if ( sep != boost::string_ref::npos ) {
368  auto p_path = objPath.substr( 0, sep );
369  auto o_path = objPath.substr( sep );
370  RegEntry* par_entry = node_entry->findLeaf( p_path );
371  // Create default object leafs if the
372  // intermediate nodes are not present
373  if ( !par_entry && m_forceLeaves ) {
374  DataObject* pLeaf = createDefaultObject();
375  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
376  if ( !sc.isSuccess() ) delete pLeaf;
377  par_entry = node_entry->findLeaf( p_path );
378  } else if ( par_entry && !par_entry->object() ) {
379  status = retrieveEntry( node_entry, p_path, par_entry );
380  if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
381  DataObject* pLeaf = createDefaultObject();
382  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
383  if ( !sc.isSuccess() ) delete pLeaf;
384  par_entry = node_entry->findLeaf( p_path );
385  }
386  }
387  node_entry = par_entry;
388  if ( node_entry ) {
389  DataObject* obj = node_entry->object();
390  if ( obj ) status = registerObject( obj, o_path, pObject );
391  }
392  } else {
393  RegEntry* leaf = node_entry->findLeaf( objPath );
394  if ( !leaf ) {
395  status = node_entry->add( objPath.to_string(), pObject );
396  } else {
397  DataObject* obj = leaf->object();
398  if ( !obj ) {
399  if ( !pObject ) {
400  error() << "registerObject: trying to register null DataObject" << endmsg;
401  return StatusCode::FAILURE;
402  } else {
403  pObject->setRegistry( leaf );
404  }
405  leaf->setAddress( nullptr );
406  leaf->setObject( pObject );
407  status = StatusCode::SUCCESS;
408  } else {
409  status = Status::DOUBL_OBJ_PATH;
410  }
411  }
412  }
413  return status;
414  }
415  return Status::INVALID_PARENT;
416 }
417 
419 StatusCode TsDataSvc::unregisterObject( boost::string_ref fullPath )
420 {
421  DataObject* pObject = nullptr;
422  StatusCode status = findObject( fullPath, pObject );
423  if ( status.isFailure() ) return status;
424  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pObject->registry() );
425  if ( !pEntry ) return Status::INVALID_ROOT;
426  if ( !pEntry->isEmpty() ) return Status::DIR_NOT_EMPTY;
427  RegEntry* pParent = pEntry->parentEntry();
428  if ( !pParent ) return Status::INVALID_PARENT;
429  if ( pObject ) pObject->addRef();
430  pParent->remove( pEntry );
431  return StatusCode::SUCCESS;
432 }
433 
436 {
437  if ( !checkRoot() ) return Status::INVALID_ROOT;
438  RegEntry* entry = m_root->findLeaf( pObject );
439  if ( !entry ) return Status::INVALID_OBJECT;
440  RegEntry* parent = entry->parentEntry();
441  if ( !parent ) return Status::INVALID_PARENT;
442  if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
443  if ( entry->object() ) entry->object()->addRef();
444  if ( parent ) parent->remove( entry );
445  return StatusCode::SUCCESS;
446 }
447 
449 StatusCode TsDataSvc::unregisterObject( DataObject* pParentObj, boost::string_ref objectPath )
450 {
451  if ( !checkRoot() ) return Status::INVALID_ROOT;
452  try {
453  RegEntry* parent = CAST_REGENTRY( RegEntry*, pParentObj->registry() );
454  if ( parent ) {
455  RegEntry* entry = parent->findLeaf( objectPath );
456  if ( !entry ) return Status::INVALID_OBJECT;
457  if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
458  if ( entry->object() ) entry->object()->addRef();
459  parent->remove( entry );
460  return StatusCode::SUCCESS;
461  }
462  } catch ( ... ) {
463  }
464  return Status::INVALID_PARENT;
465 }
466 
470 {
471  if ( m_enableFaultHdlr ) {
472  IRegistry* pLeaf = nullptr;
473  if ( pReg && path.empty() ) {
474  DataIncident incident( name(), m_faultName, pReg->identifier() );
475  m_incidentSvc->fireIncident( incident );
476  return pReg->object();
477  } else if ( pReg ) {
478  std::string p = pReg->identifier();
479  if ( path.front() != SEPARATOR ) p += SEPARATOR;
480  p.append( path.data(), path.size() );
481  DataIncident incident( name(), m_faultName, p );
482  m_incidentSvc->fireIncident( incident );
483  pLeaf = m_root->findLeaf( p );
484  } else {
486  if ( path.front() != SEPARATOR ) p += SEPARATOR;
487  p.append( path.data(), path.size() );
488  DataIncident incident( name(), m_faultName, p );
489  m_incidentSvc->fireIncident( incident );
490  pLeaf = m_root->findLeaf( p );
491  }
492  if ( pLeaf ) return pLeaf->object();
493  }
494  return nullptr;
495 }
496 
501 {
502  IConversionSvc* pLoader = getDataLoader( pRegistry );
503  return loadObject( pLoader, pRegistry );
504 }
505 
510 {
511  StatusCode status = Status::INVALID_OBJ_ADDR;
512  DataObject* pObject = nullptr;
514  if ( !pLoader ) { // Precondition: Data loader must be present
515  if ( handleDataFault( pRegistry ) )
516  return StatusCode::SUCCESS;
517  else
518  return Status::NO_DATA_LOADER;
519  }
520  if ( !pRegistry ) { // Precondition: Directory must be valid
521  if ( handleDataFault( pRegistry ) )
522  return StatusCode::SUCCESS;
523  else
524  return Status::INVALID_OBJ_ADDR;
525  }
526 
527  VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
528 
529  if ( m_enableAccessHdlr ) {
530  // Fire data access incident
531  DataIncident incident( name(), m_accessName, pRegistry->identifier() );
532  m_incidentSvc->fireIncident( incident );
533  }
534  if ( !m_inhibitPathes.empty() ) {
535  const auto& ident = pRegistry->identifier();
536  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), ident );
537  if ( inhibit != m_inhibitPathes.end() ) return Status::NO_ACCESS;
538  }
539  IOpaqueAddress* pAddress = pRegistry->address();
540  if ( !pAddress ) { // Precondition:
541  return Status::INVALID_OBJ_ADDR; // Address must be valid
542  }
543  try {
544  status = pLoader->createObj( pAddress, pObject ); // Call data loader
545  if ( status.isSuccess() ) {
546 
547  VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
548 
549  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pRegistry );
550  pEntry->setObject( pObject );
551 
552  VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
553  status = pLoader->fillObjRefs( pAddress, pObject );
554  }
555  } catch ( const GaudiException& exc ) {
556  if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
557  throw GaudiException( "GaudiException in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE,
558  exc );
559  } catch ( const std::exception& x ) {
560  if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
561  throw GaudiException( "std::exception in loadObject() " + pRegistry->identifier() + ": " +
562  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
564  } catch ( ... ) {
565  if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
566  throw GaudiException( "UNKN exception in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE );
567  }
568  if ( !status.isSuccess() ) {
569  if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
570  }
571  ON_VERBOSE if ( status.isSuccess() )
572  {
573  verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
574  }
575  return status;
576 }
577 
579 StatusCode TsDataSvc::retrieveEntry( RegEntry* parentObj, boost::string_ref path, RegEntry*& pEntry )
580 {
581  auto sep = find( path, SEPARATOR, 1 );
582  StatusCode status = StatusCode( Status::INVALID_ROOT, true );
583  pEntry = nullptr;
585  // A.Valassi 16.08.2001 avoid core dump if store is empty
586  if ( checkRoot() ) {
587  if ( !parentObj ) {
588  if ( path.empty() || path == m_rootName ) return retrieveEntry( m_root.get(), "", pEntry );
589  if ( path.front() != SEPARATOR ) return retrieveEntry( m_root.get(), path, pEntry );
590  if ( sep == boost::string_ref::npos ) return Status::INVALID_OBJ_PATH;
591  if ( !m_root->object() ) {
592  RegEntry* r = nullptr;
593  status = retrieveEntry( m_root.get(), "", r );
594  if ( !status.isSuccess() ) return status;
595  }
596  return retrieveEntry( m_root.get(), path.substr( sep ), pEntry );
597  }
598  if ( sep != boost::string_ref::npos ) { // the string contains a separator (after pos 0)
599  auto p_path = path.substr( 0, sep );
600  auto o_path = path.substr( sep );
601  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
602  status = loadObject( parentObj );
603  if ( !status.isSuccess() ) return status;
604  }
605  RegEntry* root_entry = parentObj->findLeaf( p_path );
606  if ( !root_entry && m_enableFaultHdlr ) {
607  // If not even the parent is there, an incident
608  // to load the parent must be fired...
609  handleDataFault( parentObj, p_path );
610  root_entry = parentObj->findLeaf( p_path );
611  }
612  if ( root_entry ) {
613  DataObject* pO = root_entry->object();
614  if ( !pO ) {
615  // Object is not loaded: load the object if at all possible
616  status = loadObject( root_entry );
617  if ( !status.isSuccess() ) return status;
618  }
619  if ( root_entry->isSoft() ) {
620  root_entry = CAST_REGENTRY( RegEntry*, pO->registry() );
621  }
622  return retrieveEntry( root_entry, o_path, pEntry );
623  }
624  return status;
625  } else if ( path.empty() ) {
626  pEntry = parentObj;
627  } else {
628  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
629  status = loadObject( parentObj );
630  if ( !status.isSuccess() ) return status;
631  }
632  // last leave in search: find leaf and load
633  pEntry = parentObj->findLeaf( path );
634  // If no registry entry was found, trigger incident for action-on-demand
635  if ( !pEntry && m_enableFaultHdlr ) {
636  handleDataFault( parentObj, path );
637  pEntry = ( path.empty() ? parentObj : parentObj->findLeaf( path ) );
638  }
639  }
640  // Check results and return
641  if ( !pEntry ) {
642  status = Status::INVALID_OBJ_PATH;
643  } else if ( !pEntry->object() ) {
644  status = loadObject( pEntry );
645  } else if ( m_enableAccessHdlr ) {
646  // Fire data access incident
647  // I do not know if this is a good idea....
648  // This fires too often!
649  //
650  // DataIncident incident(name(), m_accessName, pEntry->identifier());
651  // m_incidentSvc->fireIncident(incident);
652  status = StatusCode::SUCCESS;
653  } else {
654  status = StatusCode::SUCCESS;
655  }
656  }
657  return status;
658 }
659 
661 StatusCode TsDataSvc::retrieveObject( IRegistry* pRegistry, boost::string_ref path, DataObject*& pObject )
662 {
663  pObject = nullptr;
664  RegEntry * result = nullptr, *parent = CAST_REGENTRY( RegEntry *, pRegistry );
665  StatusCode status = retrieveEntry( parent, path, result );
666  if ( status.isSuccess() ) pObject = result->object();
667  return status;
668 }
669 
671 StatusCode TsDataSvc::findObject( IRegistry* pRegistry, boost::string_ref path, DataObject*& pObject )
672 {
674  pObject = nullptr;
675  IRegistry* pReg = ( pRegistry ? pRegistry : m_root.get() );
676  RegEntry* root_entry = CAST_REGENTRY( RegEntry*, pReg );
677  if ( root_entry ) {
678  if ( !path.empty() ) pReg = root_entry->find( path );
679  if ( !pReg ) return Status::INVALID_OBJ_PATH;
680  pObject = pReg->object();
681  }
682  return pObject ? Status::IDataProviderSvc_NO_ERROR : Status::OBJ_NOT_LOADED;
683 }
684 
686 StatusCode TsDataSvc::findObject( boost::string_ref path, DataObject*& pObject )
687 {
688  pObject = nullptr;
690  if ( !checkRoot() ) return Status::INVALID_ROOT;
691  if ( path.empty() || path == m_rootName ) {
692  pObject = m_root->object();
693  return !pObject ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
694  }
695  return findObject( path.front() != SEPARATOR ? m_root.get() : nullptr, path, pObject );
696 }
697 
700 {
701  if ( !pRegistry ) return Status::INVALID_OBJ_ADDR; // Precondition: Addres must be valid
702  DataObject* toUpdate = pRegistry->object();
703  return toUpdate ? updateObject( toUpdate ) : loadObject( pRegistry );
704 }
705 
708 {
709  StatusCode status = Status::INVALID_OBJ_ADDR;
710  if ( !toUpdate ) return Status::INVALID_OBJECT; // Precondition: Address must be valid
711  IRegistry* pRegistry = toUpdate->registry();
712  if ( !pRegistry ) return Status::INVALID_OBJECT; // Precondition: Need valid registry
713  IOpaqueAddress* pAddress = pRegistry->address();
714  if ( !pAddress ) return Status::INVALID_OBJ_ADDR; // Precondition: Need valid address
716  IConversionSvc* pLoader = getDataLoader( pRegistry );
717  if ( !pLoader ) return Status::NO_DATA_LOADER; // Precondition: Data loader must be present
718  if ( !m_inhibitPathes.empty() ) {
719  auto& ident = pRegistry->identifier();
720  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), ident );
721  if ( inhibit != m_inhibitPathes.end() ) return Status::NO_ACCESS;
722  }
723  try {
724  status = pLoader->updateObj( pAddress, toUpdate ); // Call data loader
725  if ( status.isSuccess() ) {
726  status = pLoader->updateObjRefs( pAddress, toUpdate );
727  }
728  } catch ( const GaudiException& exc ) {
729  throw GaudiException( "GaudiException in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE, exc );
730  } catch ( const std::exception& x ) {
731  throw GaudiException( "std::exception in updateObject() " + pRegistry->name() + ": " +
732  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
734  } catch ( ... ) {
735  throw GaudiException( "UNKN exception in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE );
736  }
737  return status;
738 }
739 
740 // Link object
741 StatusCode TsDataSvc::linkObject( IRegistry* from, boost::string_ref objPath, DataObject* to )
742 {
744  if ( !checkRoot() ) return Status::INVALID_ROOT;
745  try {
746  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
747  if ( from_entry ) {
748  // First check if both objects are already registered to the store
749  RegEntry* to_entry = m_root->findLeaf( to );
750  if ( !to_entry ) return Status::INVALID_OBJECT;
751  auto sep = objPath.rfind( SEPARATOR );
752  if ( sep > 0 && sep != boost::string_ref::npos ) { // in case the objPath is a sub-directory itself
753  DataObject* pO = nullptr;
754  StatusCode sc = retrieveObject( from, objPath.substr( 0, sep ), pO );
755  return sc.isSuccess() ? linkObject( pO->registry(), objPath.substr( sep ), to ) : sc;
756  }
757  // Now register the soft link
758  StatusCode status = from_entry->add( objPath.to_string(), to, true );
759  return status.isSuccess() ? Status::IDataProviderSvc_NO_ERROR : Status::DOUBL_OBJ_PATH;
760  }
761  } catch ( ... ) {
762  }
763  return Status::INVALID_PARENT;
764 }
765 
767 StatusCode TsDataSvc::linkObject( boost::string_ref fullPath, DataObject* to )
768 {
769  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
770  if ( fullPath.front() == SEPARATOR ) {
771  auto sep = fullPath.rfind( SEPARATOR );
772  return linkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ), to );
773  }
775  return linkObject( m_root.get(), fullPath, to );
776 }
777 
779 StatusCode TsDataSvc::unlinkObject( IRegistry* from, boost::string_ref objPath )
780 {
782  if ( !checkRoot() ) return Status::INVALID_ROOT;
783  try {
784  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
785  if ( from_entry ) {
786  auto sep = objPath.rfind( SEPARATOR );
787  if ( sep > 0 && sep != boost::string_ref::npos ) { // in case the objPath is a sub-directory itself
788  DataObject* pO = nullptr;
789  StatusCode sc = findObject( from, objPath.substr( 0, sep ), pO );
790  return sc.isSuccess() ? unlinkObject( pO->registry(), objPath.substr( sep ) ) : sc;
791  }
792  StatusCode status = from_entry->remove( objPath );
793  return status.isSuccess() ? status : Status::INVALID_OBJ_PATH;
794  }
795  } catch ( ... ) {
796  }
797  return Status::INVALID_PARENT;
798 }
799 
801 StatusCode TsDataSvc::unlinkObject( boost::string_ref fullPath )
802 {
803  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
804  if ( fullPath.front() != SEPARATOR ) {
805  return unlinkObject( m_root.get(), fullPath );
806  }
807  auto sep = fullPath.rfind( SEPARATOR );
808  return unlinkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ) );
809 }
810 
812 StatusCode TsDataSvc::unlinkObject( DataObject* from, boost::string_ref objPath )
813 {
814  if ( !checkRoot() ) return Status::INVALID_ROOT;
815  return unlinkObject( m_root->findLeaf( from ), objPath );
816 }
817 
820 {
821  auto i = std::find( m_preLoads.begin(), m_preLoads.end(), item );
822  if ( i == m_preLoads.end() ) m_preLoads.push_back( item );
823  return StatusCode::SUCCESS;
824 }
825 
828 {
829  auto i = std::remove( m_preLoads.begin(), m_preLoads.end(), item );
830  m_preLoads.erase( i, m_preLoads.end() );
831  return StatusCode::SUCCESS;
832 }
833 
836 {
837  m_preLoads.clear();
838  return StatusCode::SUCCESS;
839 }
840 
842 StatusCode TsDataSvc::preLoad( int depth, int load_depth, DataObject* pObject )
843 {
844  // unused: StatusCode sc = StatusCode::FAILURE;
845  if ( pObject && depth++ < load_depth ) {
846  RegEntry* dir = CAST_REGENTRY( RegEntry*, pObject->registry() );
847  if ( dir ) {
848  for ( const auto& i : *dir ) {
849  DataObject* pObj = nullptr;
850  StatusCode status = retrieveObject( pObject, i->name(), pObj );
851  if ( status.isSuccess() && depth < load_depth ) {
852  preLoad( depth, load_depth, pObj ).ignore();
853  }
854  }
855  }
856  }
857  return StatusCode::SUCCESS;
858 }
859 
862 {
863  DataObject* pObj = nullptr;
864  for ( const auto& i : m_preLoads ) {
865  StatusCode sc = retrieveObject( i.path(), pObj );
866  int load_depth = i.depth();
867  if ( sc.isSuccess() && load_depth > 1 ) {
868  preLoad( 1, load_depth, pObj ).ignore();
869  }
870  }
871  return StatusCode::SUCCESS;
872 }
873 
876 {
877  // Nothing to do: just call base class initialisation
879  if ( !sc.isSuccess() ) return sc;
880  sc = service( "IncidentSvc", m_incidentSvc, true );
881  if ( UNLIKELY( !sc.isSuccess() ) ) {
882  error() << "Failed to access incident service." << endmsg;
883  }
884  return sc;
885 }
886 
889 {
890  StatusCode sc;
891  // the finalize part is copied here
892  setDataLoader( nullptr ).ignore();
893  resetPreLoad().ignore();
894  clearStore().ignore();
895  if ( m_incidentSvc ) {
897  m_incidentSvc = nullptr;
898  }
899  // re-initialize the base class
900  sc = Service::reinitialize();
901  if ( UNLIKELY( !sc.isSuccess() ) ) {
902  error() << "Unable to reinitialize base class" << endmsg;
903  return sc;
904  }
905  // the initialize part is copied here
906  sc = service( "IncidentSvc", m_incidentSvc, true );
907  if ( UNLIKELY( !sc.isSuccess() ) ) {
908  error() << "Failed to access incident service." << endmsg;
909  return sc;
910  }
911  // return
912  return StatusCode::SUCCESS;
913 }
914 
917 {
918  // Nothing to do: just call base class initialisation
919  setDataLoader( nullptr ).ignore();
920  resetPreLoad().ignore();
921  clearStore().ignore();
922  if ( m_incidentSvc ) {
924  m_incidentSvc = nullptr;
925  }
926  return Service::finalize();
927 }
928 
930 CLID TsDataSvc::rootCLID() const { return ( (CLID)m_rootCLID ); }
931 
933 const std::string& TsDataSvc::rootName() const { return ( m_rootName ); }
934 
937 
#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
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
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
constexpr char SEPARATOR
StatusCode setRoot(std::string root_name, DataObject *pRootObj) override
Initialize data store for new event by giving new event path and root object.
Definition: TsDataSvc.cpp:148
StatusCode finalize() override
Definition: Service.cpp:173
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
Definition: TsDataSvc.cpp:819
StatusCode linkObject(IRegistry *from, boost::string_ref objPath, DataObject *to) override
Add a link to another object.
Definition: TsDataSvc.cpp:741
StatusCode unregisterObject(boost::string_ref fullPath) override
Unregister object from the data store.
Definition: TsDataSvc.cpp:419
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:332
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
StatusCode traverseTree(IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects in the data store.
Definition: TsDataSvc.cpp:137
bool isSuccess() const
Definition: StatusCode.h:287
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
Definition: TsDataSvc.cpp:699
StatusCode unregisterAddress(boost::string_ref fullPath) override
IDataManagerSvc: Unregister object address from the data store.
Definition: TsDataSvc.cpp:294
Gaudi::Property< std::string > m_accessName
Definition: TsDataSvc.h:78
Gaudi::Property< CLID > m_rootCLID
Definition: TsDataSvc.h:67
StatusCode retrieveObject(IRegistry *pDirectory, boost::string_ref path, DataObject *&pObject) override
Retrieve object from data store.
Definition: TsDataSvc.cpp:661
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
virtual StatusCode setDataProvider(IDataProviderSvc *pService)=0
Set Data provider service.
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:71
virtual const name_type & name() const =0
Name of the directory (or key)
StatusCode initialize() override
Service initialization.
Definition: TsDataSvc.cpp:875
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Definition: TsDataSvc.cpp:827
T end(T...args)
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
Definition: TsDataSvc.cpp:941
const Store & leaves() const
Access the leaves of the object.
bool isSoft() const
Is the link soft or hard.
IConversionSvc * m_dataLoader
Pointer to data loader service.
Definition: TsDataSvc.h:63
StatusCode setDataLoader(IConversionSvc *svc, IDataProviderSvc *dpsvc=nullptr) override
IDataManagerSvc: IDataManagerSvc: Pass a default data loader to the service and optionally a data pro...
Definition: TsDataSvc.cpp:197
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
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:73
StatusCode resetPreLoad() override
Clear the preload list.
Definition: TsDataSvc.cpp:835
STL class.
#define VERMSG
Definition: TsDataSvc.cpp:76
T push_back(T...args)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
StatusCode registerAddress(boost::string_ref fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition: TsDataSvc.cpp:247
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 preLoad() override
load all preload items of the list
Definition: TsDataSvc.cpp:861
StatusCode findObject(boost::string_ref fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition: TsDataSvc.cpp:686
IIncidentSvc * m_incidentSvc
Pointer to incident service.
Definition: TsDataSvc.h:65
virtual const id_type & identifier() const =0
Full identifier (or key)
#define ON_VERBOSE
Definition: TsDataSvc.cpp:73
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.
DataSvcHelpers::RegistryEntry RegEntry
Definition: TsDataSvc.cpp:70
T erase(T...args)
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:91
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
Definition: TsDataSvc.cpp:933
Gaudi::Property< bool > m_enableAccessHdlr
Definition: TsDataSvc.h:76
StatusCode reinitialize() override
Service initialization.
Definition: TsDataSvc.cpp:888
StatusCode objectLeaves(const DataObject *pObject, std::vector< IRegistry * > &refLeaves) override
IDataManagerSvc: Explore the object store: retrieve all leaves attached to the object.
Definition: TsDataSvc.cpp:226
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
StatusCode unlinkObject(IRegistry *from, boost::string_ref objPath) override
Remove a link to another object.
Definition: TsDataSvc.cpp:779
T reset(T...args)
StatusCode reinitialize() override
Definition: Service.cpp:249
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
T clear(T...args)
IOpaqueAddress * address() const override
Retrieve opaque storage address.
STL class.
T move(T...args)
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, boost::string_ref path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
Definition: TsDataSvc.cpp:579
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
std::unique_ptr< DataSvcHelpers::RegistryEntry > m_root
Pointer to root entry.
Definition: TsDataSvc.h:83
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:51
T get(T...args)
T insert(T...args)
T find(T...args)
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
Definition: TsDataSvc.cpp:936
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
virtual unsigned long release()=0
Release Interface instance.
StatusCode finalize() override
Service initialization.
Definition: TsDataSvc.cpp:916
Generic data agent interface.
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: TsDataSvc.cpp:81
T begin(T...args)
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition: TsDataSvc.h:81
RegistryEntry * parentEntry()
Pointer to parent registry entry.
Definition: RegistryEntry.h:93
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: TsDataSvc.cpp:159
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
IRegistry * find(const IRegistry *obj) const
Try to find an object identified by its pointer.
string s
Definition: gaudirun.py:253
const std::string & name() const
Retreive DataObject name. It is the name when registered in the store.
Definition: DataObject.cpp:68
bool checkRoot()
Check if root path is valid.
Definition: TsDataSvc.h:268
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
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: TsDataSvc.cpp:119
Gaudi::Property< bool > m_forceLeaves
Definition: TsDataSvc.h:69
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)
StatusCode remove(boost::string_ref name)
Remove an entry from the store.
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition: TsDataSvc.cpp:109
bool isEmpty() const
Simple check if the Container is empty.
StatusCode registerObject(boost::string_ref parentPath, boost::string_ref objPath, DataObject *pObject) override
Register object with the data store.
Definition: TsDataSvc.cpp:335
Data service incident class.
Opaque address interface definition.
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Definition: TsDataSvc.cpp:930
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition: TsDataSvc.h:70
DataObject * handleDataFault(IRegistry *pReg, boost::string_ref path={})
Invoke data fault handling if enabled.
Definition: TsDataSvc.cpp:469
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
#define STD_LOCK_GUARD_MACRO
Definition: TsDataSvc.cpp:44
#define CAST_REGENTRY(x, y)
Definition: TsDataSvc.cpp:68
virtual StatusCode loadObject(IRegistry *pNode)
Invoke Persistency service to create transient object from its persistent representation.
Definition: TsDataSvc.cpp:500
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object&#39;s parent.
Definition: TsDataSvc.cpp:209
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
Gaudi::Property< bool > m_enableFaultHdlr
Definition: TsDataSvc.h:72
Gaudi::Property< std::string > m_faultName
Definition: TsDataSvc.h:74
Gaudi::Property< std::string > m_rootName
Definition: TsDataSvc.h:68
void makeHard(DataObject *pObject)
Initialize link as hard link.