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