The Gaudi Framework  v33r1 (b1225454)
DataSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 //====================================================================
12 // DataSvc.cpp
13 //--------------------------------------------------------------------
14 //
15 // Package : System ( The LHCb Offline System)
16 //
17 // Description: implementation of the Transient data service: DataSvc
18 //
19 // Author : M.Frank
20 // History :
21 // +---------+----------------------------------------------+---------
22 // | Date | Comment | Who
23 // +---------+----------------------------------------------+---------
24 // | 29/10/98| Initial version | M.Frank
25 // | 20/2/99 | Automatic data preloading introduced. | M.Frank
26 // +---------+----------------------------------------------+---------
27 //
28 //====================================================================
29 #define DATASVC_DATASVC_CPP
30 
31 // Framework include files
33 #include "GaudiKernel/IConverter.h"
35 
36 #include "GaudiKernel/DataObject.h"
38 
40 #include "GaudiKernel/DataSvc.h"
43 
44 // Include files
45 #include <algorithm>
46 #include <cassert>
47 #include <cstdlib>
48 #include <sstream>
49 #include <vector>
50 
51 namespace {
52  std::string operator+( char c, std::string_view sr ) {
53  std::string s{c};
54  s.append( sr.data(), sr.size() );
55  return s;
56  }
57 
58  std::string_view::size_type find( std::string_view s, char c, size_t o ) {
59  if ( !s.empty() ) s.remove_prefix( o );
60  auto r = s.find( c );
61  return r == std::string_view::npos ? r : ( r + o );
62  }
63 
64  std::string to_string( std::string_view sr ) { return {sr.data(), sr.size()}; }
65 } // namespace
66 
67 // If you absolutely need optimization: switch off dynamic_cast.
68 // This improves access to the data store roughly by 10 %
69 // for balanced trees.
70 //
71 // M.Frank
72 #define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
73 //#define CAST_REGENTRY(x,y) (x)(y)
75 
76 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
77 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
78 
79 #define DEBMSG ON_DEBUG debug()
80 #define VERMSG ON_VERBOSE verbose()
81 
85 StatusCode DataSvc::clearSubTree( std::string_view sub_tree_path ) {
86  DataObject* pObject = nullptr;
87  StatusCode status = findObject( sub_tree_path, pObject );
88  if ( !status.isSuccess() ) return status;
89  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
90  if ( !node_entry ) return Status::INVALID_OBJECT;
91  RegEntry* parent = node_entry->parentEntry();
92  if ( !parent ) return Status::INVALID_PARENT;
93  parent->remove( node_entry );
94  return StatusCode::SUCCESS;
95 }
96 
101  if ( !checkRoot() ) return Status::INVALID_ROOT;
102  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
103  if ( !entry ) return Status::INVALID_OBJECT;
104  RegEntry* parent = entry->parentEntry();
105  if ( !parent ) return Status::INVALID_PARENT;
106  parent->remove( entry );
107  return StatusCode::SUCCESS;
108 }
109 
112  if ( !checkRoot() ) return Status::INVALID_ROOT;
113  m_root.reset();
114  return StatusCode::SUCCESS;
115 }
116 
120 StatusCode DataSvc::traverseSubTree( std::string_view sub_tree_path, IDataStoreAgent* pAgent ) {
121  DataObject* pO = nullptr;
122  StatusCode status = findObject( sub_tree_path, pO );
123  return status.isSuccess() ? traverseSubTree( pO, pAgent ) : status;
124 }
125 
128  RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
129  return entry ? entry->traverseTree( pAgent ) : Status::INVALID_OBJECT;
130 }
131 
134  if ( !checkRoot() ) return Status::INVALID_ROOT;
135  return m_root->traverseTree( pAgent );
136 }
137 
143  clearStore().ignore();
144  return i_setRoot( std::move( root_path ), pRootObj );
145 }
146 
153  if ( pRootObj ) {
154  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
155  m_root->makeHard( pRootObj );
156  m_root->setDataSvc( this );
157  // No done with GaudiHive. preLoad().ignore();
158  }
159  return StatusCode::SUCCESS;
160 }
161 
167  clearStore().ignore();
168  return i_setRoot( std::move( root_path ), pRootAddr );
169 }
170 
177  if ( pRootAddr ) {
178  m_root = std::make_unique<RegEntry>( std::move( root_path ) );
179  m_root->makeHard( pRootAddr );
180  m_root->setDataSvc( this );
181  // Not done with GaudiHive. preLoad().ignore();
182  }
183  return StatusCode::SUCCESS;
184 }
185 
188  m_dataLoader = pDataLoader;
189  if ( m_dataLoader ) m_dataLoader->setDataProvider( dpsvc ? dpsvc : this ).ignore();
190  return StatusCode::SUCCESS;
191 }
192 
194 StatusCode DataSvc::objectParent( const DataObject* pObject, IRegistry*& refpParent ) {
195  if ( !pObject ) return Status::INVALID_OBJECT;
196  return objectParent( pObject->registry(), refpParent );
197 }
199 StatusCode DataSvc::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 ( !checkRoot() ) return Status::INVALID_ROOT;
218  const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
219  if ( !node_entry ) return Status::INVALID_OBJECT;
220  leaves = node_entry->leaves();
221  return StatusCode::SUCCESS;
222 }
223 
225 StatusCode DataSvc::registerAddress( std::string_view fullPath, IOpaqueAddress* pAddress ) {
226  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
227  return registerAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath, pAddress );
228 }
229 
231 StatusCode DataSvc::registerAddress( IRegistry* parentObj, std::string_view objPath, IOpaqueAddress* pAddress ) {
232  if ( !checkRoot() ) return Status::INVALID_ROOT;
233  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
234 
235  if ( !parentObj ) {
236  if ( objPath.front() != SEPARATOR ) { return registerAddress( m_root.get(), objPath, pAddress ); }
237  auto sep = find( objPath, SEPARATOR, 1 );
238  if ( sep == std::string_view::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
239  return Status::INVALID_PARENT;
240  }
241  return registerAddress( m_root.get(), objPath.substr( sep ), pAddress );
242  }
243  if ( objPath.front() != SEPARATOR ) { return registerAddress( parentObj, char( SEPARATOR ) + objPath, pAddress ); }
244  RegEntry* par_entry = CAST_REGENTRY( RegEntry*, parentObj );
245  if ( !par_entry ) return Status::INVALID_PARENT;
246 
247  auto sep = objPath.rfind( SEPARATOR );
248  if ( sep > 0 && sep != std::string_view::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.isFailure() ) 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( to_string( objPath ), pAddress );
264  return status.isSuccess() ? status : Status::DOUBL_OBJ_PATH;
265 }
266 
268 StatusCode DataSvc::unregisterAddress( std::string_view 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 DataSvc::unregisterAddress( IRegistry* pParent, std::string_view objPath ) {
275  if ( !checkRoot() ) return Status::INVALID_ROOT;
276  if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
277 
278  if ( !pParent ) {
279  if ( objPath.front() != SEPARATOR ) return unregisterAddress( m_root.get(), objPath );
280  auto sep = find( objPath, SEPARATOR, 1 );
281  if ( sep != std::string_view::npos && objPath.substr( 0, sep ) == m_rootName.value() ) {
282  return unregisterAddress( m_root.get(), objPath.substr( sep ) );
283  }
284  return Status::INVALID_PARENT;
285  }
286  if ( objPath.front() != SEPARATOR ) { return unregisterAddress( pParent, char( 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 != std::string_view::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 DataSvc::registerObject( std::string_view parentPath, std::string_view 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 DataSvc::registerObject( DataObject* parentObj, std::string_view objPath, DataObject* pObject ) {
316  if ( !checkRoot() ) return Status::INVALID_ROOT;
317 
318  if ( !parentObj ) {
319  if ( !objPath.empty() ) {
320  if ( objPath.front() != SEPARATOR ) { return registerObject( m_rootName.value(), objPath, pObject ); }
321  auto sep = find( objPath, SEPARATOR, 1 );
322  if ( sep != std::string_view::npos ) {
323  return registerObject( objPath.substr( 0, sep ), objPath.substr( sep ), pObject );
324  }
325  }
326  return Status::INVALID_OBJ_PATH;
327  }
328  RegEntry* node_entry = CAST_REGENTRY( RegEntry*, parentObj->registry() );
329  if ( node_entry ) {
330  StatusCode status = Status::INVALID_PARENT;
331  auto sep = find( objPath, SEPARATOR, 1 );
332  if ( sep != std::string_view::npos ) {
333  auto p_path = objPath.substr( 0, sep );
334  auto o_path = objPath.substr( sep );
335  RegEntry* par_entry = node_entry->findLeaf( p_path );
336  // Create default object leafs if the
337  // intermediate nodes are not present
338  if ( !par_entry && m_forceLeaves ) {
339  DataObject* pLeaf = createDefaultObject();
340  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
341  if ( !sc.isSuccess() ) delete pLeaf;
342  par_entry = node_entry->findLeaf( p_path );
343  } else if ( par_entry && !par_entry->object() ) {
344  status = i_retrieveEntry( node_entry, p_path, par_entry );
345  if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
346  DataObject* pLeaf = createDefaultObject();
347  StatusCode sc = registerObject( parentObj, p_path, pLeaf );
348  if ( !sc.isSuccess() ) delete pLeaf;
349  par_entry = node_entry->findLeaf( p_path );
350  }
351  }
352  node_entry = par_entry;
353  if ( node_entry ) {
354  DataObject* obj = node_entry->object();
355  if ( obj ) status = registerObject( obj, o_path, pObject );
356  }
357  } else {
358  RegEntry* leaf = node_entry->findLeaf( objPath );
359  if ( !leaf ) {
360  status = node_entry->add( to_string( objPath ), pObject );
361  } else {
362  DataObject* obj = leaf->object();
363  if ( !obj ) {
364  if ( !pObject ) {
365  error() << "registerObject: trying to register null DataObject" << endmsg;
366  return StatusCode::FAILURE;
367  }
368  pObject->setRegistry( leaf );
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 DataSvc::unregisterObject( std::string_view 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 DataSvc::unregisterObject( DataObject* pParentObj, std::string_view objectPath ) {
412  if ( checkRoot() ) {
413  try {
414  RegEntry* parent = CAST_REGENTRY( RegEntry*, pParentObj->registry() );
415  if ( parent ) {
416  RegEntry* entry = parent->findLeaf( objectPath );
417  if ( entry ) {
418  if ( entry->isEmpty() ) {
419  if ( entry->object() ) { entry->object()->addRef(); }
420  parent->remove( entry );
421  return StatusCode::SUCCESS;
422  }
423  return Status::DIR_NOT_EMPTY;
424  }
425  return Status::INVALID_OBJECT;
426  }
427  } catch ( ... ) {}
428  return Status::INVALID_PARENT;
429  }
430  return Status::INVALID_ROOT;
431 }
432 
435 DataObject* DataSvc::handleDataFault( IRegistry* pReg, std::string_view path ) {
436  return i_handleDataFault( pReg, path );
437 }
438 
440  if ( m_enableFaultHdlr ) {
441  IRegistry* pLeaf = nullptr;
442  if ( pReg && path.empty() ) {
443  DataIncident incident( name(), m_faultName, pReg->identifier() );
444  m_incidentSvc->fireIncident( incident );
445  return pReg->object();
446  }
447  if ( pReg ) {
448  std::string p = pReg->identifier();
449  if ( path.front() != SEPARATOR ) p += SEPARATOR;
450  p.append( path.data(), path.size() );
451  DataIncident incident( name(), m_faultName, p );
452  m_incidentSvc->fireIncident( incident );
453  pLeaf = m_root->findLeaf( p );
454  } else {
456  if ( path.front() != SEPARATOR ) p += SEPARATOR;
457  p.append( path.data(), path.size() );
458  DataIncident incident( name(), m_faultName, p );
459  m_incidentSvc->fireIncident( incident );
460  pLeaf = m_root->findLeaf( p );
461  }
462  if ( pLeaf ) { return pLeaf->object(); }
463  }
464  return nullptr;
465 }
466 
471  IConversionSvc* pLoader = getDataLoader( pRegistry );
472  return loadObject( pLoader, pRegistry );
473 }
474 
479  StatusCode status = Status::INVALID_OBJ_ADDR;
480  DataObject* pObject = nullptr;
481  if ( !pLoader ) { // Precondition: Data loader must be present
482  return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::NO_DATA_LOADER );
483  }
484  if ( !pRegistry ) { // Precondition: Directory must be valid
485  return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::INVALID_OBJ_ADDR );
486  }
487 
488  VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
489 
490  if ( m_enableAccessHdlr ) {
491  // Fire data access incident
492  DataIncident incident( name(), m_accessName, pRegistry->identifier() );
493  m_incidentSvc->fireIncident( incident );
494  }
495  if ( !m_inhibitPathes.empty() ) {
496  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
497  if ( inhibit != m_inhibitPathes.end() ) { return Status::NO_ACCESS; }
498  }
499  IOpaqueAddress* pAddress = pRegistry->address();
500  if ( !pAddress ) { // Precondition:
501  return Status::INVALID_OBJ_ADDR; // Address must be valid
502  }
503  try {
504  status = pLoader->createObj( pAddress, pObject ); // Call data loader
505  if ( status.isSuccess() ) {
506 
507  VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
508 
509  RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pRegistry );
510  pEntry->setObject( pObject );
511 
512  VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
513  status = pLoader->fillObjRefs( pAddress, pObject );
514  }
515  } catch ( const GaudiException& exc ) {
516  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
517  throw GaudiException( "GaudiException in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE,
518  exc );
519  } catch ( const std::exception& x ) {
520  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
521  throw GaudiException( "std::exception in loadObject() " + pRegistry->identifier() + ": " +
522  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
524  } catch ( ... ) {
525  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
526  throw GaudiException( "UNKN exception in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE );
527  }
528  if ( !status.isSuccess() ) {
529  if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
530  }
531  ON_VERBOSE if ( status.isSuccess() ) {
532  verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
533  }
534  return status;
535 }
536 
538 StatusCode DataSvc::retrieveEntry( RegEntry* parentObj, std::string_view path, RegEntry*& pEntry ) {
539  return i_retrieveEntry( parentObj, path, pEntry );
540 }
541 
542 StatusCode DataSvc::i_retrieveEntry( RegEntry* parentObj, std::string_view path, RegEntry*& pEntry ) {
543  // A.Valassi 16.08.2001 avoid core dump if store is empty
544  if ( !checkRoot() ) return StatusCode( Status::INVALID_ROOT, true );
545 
546  static constexpr auto empty = std::string_view{};
547  auto sep = find( path, SEPARATOR, 1 );
548  pEntry = nullptr;
549 
550  if ( !parentObj ) {
551  if ( path.empty() || path == m_rootName.value() ) {
552  parentObj = m_root.get();
553  path = empty;
554  } else if ( path.front() != SEPARATOR ) {
555  parentObj = m_root.get();
556  } else if ( sep != std::string_view::npos ) {
557  if ( !m_root->object() ) {
558  RegEntry* r = nullptr;
559  auto status = i_retrieveEntry( m_root.get(), empty, r );
560  if ( !status.isSuccess() ) return status;
561  }
562  parentObj = m_root.get();
563  path = path.substr( sep );
564  } else {
565  return Status::INVALID_OBJ_PATH;
566  }
567  sep = find( path, SEPARATOR, 1 );
568  }
569 
570  StatusCode status = StatusCode( Status::INVALID_ROOT, true );
571  if ( sep != std::string_view::npos ) { // the string contains a separator (after pos 0)
572  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
573  status = loadObject( parentObj );
574  if ( !status.isSuccess() ) return status;
575  }
576  auto p_path = path.substr( 0, sep );
577  RegEntry* root_entry = parentObj->findLeaf( p_path );
578  if ( !root_entry && m_enableFaultHdlr ) {
579  // If not even the parent is there, an incident
580  // to load the parent must be fired...
581  i_handleDataFault( parentObj, p_path );
582  root_entry = parentObj->findLeaf( p_path );
583  }
584  if ( root_entry ) {
585  DataObject* pO = root_entry->object();
586  if ( !pO ) {
587  // Object is not loaded: load the object if at all possible
588  status = loadObject( root_entry );
589  if ( !status.isSuccess() ) return status;
590  }
591  if ( root_entry->isSoft() ) { root_entry = CAST_REGENTRY( RegEntry*, pO->registry() ); }
592  return i_retrieveEntry( root_entry, path.substr( sep ), pEntry );
593  }
594  return status;
595  } else if ( path.empty() ) {
596  pEntry = parentObj;
597  } else {
598  if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
599  status = loadObject( parentObj );
600  if ( !status.isSuccess() ) return status;
601  }
602  // last leave in search: find leaf and load
603  pEntry = parentObj->findLeaf( path );
604  // If no registry entry was found, trigger incident for action-on-demand
605  if ( !pEntry && m_enableFaultHdlr ) {
606  i_handleDataFault( parentObj, path );
607  pEntry = ( path.empty() ? parentObj : parentObj->findLeaf( path ) );
608  }
609  }
610 
611  // Check results and return
612  if ( !pEntry ) return Status::INVALID_OBJ_PATH;
613  if ( !pEntry->object() ) return loadObject( pEntry );
614 
615  if ( m_enableAccessHdlr ) {
616  // Fire data access incident
617  // I do not know if this is a good idea....
618  // This fires too often!
619  //
620  // DataIncident incident(name(), m_accessName, pEntry->identifier());
621  // m_incidentSvc->fireIncident(incident);
622  return StatusCode::SUCCESS;
623  }
624  return StatusCode::SUCCESS;
625 }
626 
628 StatusCode DataSvc::retrieveObject( IRegistry* pRegistry, std::string_view path, DataObject*& pObject ) {
629  pObject = nullptr;
630  RegEntry * result = nullptr, *parent = CAST_REGENTRY( RegEntry*, pRegistry );
631  StatusCode status = i_retrieveEntry( parent, path, result );
632  if ( status.isSuccess() ) pObject = result->object();
633  return status;
634 }
635 
637 StatusCode DataSvc::findObject( IRegistry* pRegistry, std::string_view path, DataObject*& pObject ) {
638  pObject = nullptr;
639  IRegistry* pReg = ( pRegistry ? pRegistry : m_root.get() );
640  RegEntry* root_entry = CAST_REGENTRY( RegEntry*, pReg );
641  if ( root_entry ) {
642  if ( !path.empty() ) pReg = root_entry->find( path );
643  if ( !pReg ) return Status::INVALID_OBJ_PATH;
644  pObject = pReg->object();
645  }
646  return ( !pObject ) ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
647 }
648 
650 StatusCode DataSvc::findObject( std::string_view path, DataObject*& pObject ) {
651  pObject = nullptr;
652  if ( !checkRoot() ) return Status::INVALID_ROOT;
653  if ( path.empty() || path == m_rootName.value() ) {
654  pObject = m_root->object();
655  return !pObject ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
656  }
657  return findObject( path.front() != SEPARATOR ? m_root.get() : nullptr, path, pObject );
658 }
659 
662  if ( !pRegistry ) { // Precondition:
663  return Status::INVALID_OBJ_ADDR; // Addres must be valid
664  }
665  DataObject* toUpdate = pRegistry->object();
666  if ( !toUpdate ) { // Try first to load
667  return loadObject( pRegistry );
668  }
669  return updateObject( toUpdate );
670 }
671 
674  StatusCode status = Status::INVALID_OBJ_ADDR;
675  if ( !toUpdate ) { // Precondition:
676  return Status::INVALID_OBJECT; // Address must be valid
677  }
678  IRegistry* pRegistry = toUpdate->registry(); // Precondition:
679  if ( !pRegistry ) { // Need valid registry
680  return Status::INVALID_OBJECT;
681  }
682  IOpaqueAddress* pAddress = pRegistry->address(); // Precondition:
683  if ( !pAddress ) { // Need valid address
684  return Status::INVALID_OBJ_ADDR;
685  }
686  IConversionSvc* pLoader = getDataLoader( pRegistry );
687  if ( !pLoader ) { // Precondition:
688  return Status::NO_DATA_LOADER; // Data loader must be present
689  }
690  if ( !m_inhibitPathes.empty() ) {
691  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
692  if ( inhibit != m_inhibitPathes.end() ) { return Status::NO_ACCESS; }
693  }
694  try {
695  status = pLoader->updateObj( pAddress, toUpdate ); // Call data loader
696  if ( status.isSuccess() ) { status = pLoader->updateObjRefs( pAddress, toUpdate ); }
697  } catch ( const GaudiException& exc ) {
698  throw GaudiException( "GaudiException in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE, exc );
699  } catch ( const std::exception& x ) {
700  throw GaudiException( "std::exception in updateObject() " + pRegistry->name() + ": " +
701  System::typeinfoName( typeid( x ) ) + ", " + x.what(),
703  } catch ( ... ) {
704  throw GaudiException( "UNKN exception in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE );
705  }
706  return status;
707 }
708 
709 // Link object
710 StatusCode DataSvc::linkObject( IRegistry* from, std::string_view objPath, DataObject* to ) {
711  if ( !checkRoot() ) return Status::INVALID_ROOT;
712  try {
713  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
714  if ( from_entry ) {
715  // First check if both objects are already registered to the store
716  RegEntry* to_entry = m_root->findLeaf( to );
717  if ( !to_entry ) return Status::INVALID_OBJECT;
718  auto sep = objPath.rfind( SEPARATOR );
719  if ( sep > 0 && sep != std::string_view::npos ) { // in case the objPath is a sub-directory itself
720  DataObject* pO = nullptr;
721  StatusCode sc = retrieveObject( from, objPath.substr( 0, sep ), pO );
722  return sc.isSuccess() ? linkObject( pO->registry(), objPath.substr( sep ), to ) : sc;
723  }
724  // Now register the soft link
725  StatusCode status = from_entry->add( to_string( objPath ), to, true );
726  return status.isSuccess() ? Status::IDataProviderSvc_NO_ERROR : Status::DOUBL_OBJ_PATH;
727  }
728  } catch ( ... ) {}
729  return Status::INVALID_PARENT;
730 }
731 
733 StatusCode DataSvc::linkObject( std::string_view fullPath, DataObject* to ) {
734  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
735  if ( fullPath.front() != SEPARATOR ) { return linkObject( m_rootName.value(), fullPath, to ); }
736  auto sep = fullPath.rfind( SEPARATOR );
737  return linkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ), to );
738 }
739 
741 StatusCode DataSvc::unlinkObject( IRegistry* from, std::string_view objPath ) {
742  if ( !checkRoot() ) return Status::INVALID_ROOT;
743  try {
744  RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
745  if ( from_entry ) {
746  auto sep = objPath.rfind( SEPARATOR );
747  if ( sep > 0 && sep != std::string_view::npos ) { // in case the objPath is a sub-directory itself
748  DataObject* pO = nullptr;
749  StatusCode sc = findObject( from, objPath.substr( 0, sep ), pO );
750  return sc.isSuccess() ? unlinkObject( pO->registry(), objPath.substr( sep ) ) : sc;
751  }
752  StatusCode status = from_entry->remove( objPath );
753  if ( status.isSuccess() ) return status;
754  return Status::INVALID_OBJ_PATH;
755  }
756  } catch ( ... ) {}
757  return Status::INVALID_PARENT;
758 }
759 
761 StatusCode DataSvc::unlinkObject( std::string_view fullPath ) {
762  if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
763  if ( fullPath.front() != SEPARATOR ) return unlinkObject( m_rootName.value(), fullPath );
764  auto sep = fullPath.rfind( SEPARATOR );
765  return unlinkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ) );
766 }
767 
769 StatusCode DataSvc::unlinkObject( DataObject* from, std::string_view objPath ) {
770  if ( !checkRoot() ) return Status::INVALID_ROOT;
771  IRegistry* from_entry = m_root->findLeaf( from );
772  return unlinkObject( from_entry, objPath );
773 }
774 
777  auto i = std::find( begin( m_preLoads ), end( m_preLoads ), item );
778  if ( i == end( m_preLoads ) ) m_preLoads.push_back( item );
779  return StatusCode::SUCCESS;
780 }
781 
785  return StatusCode::SUCCESS;
786 }
787 
791  return StatusCode::SUCCESS;
792 }
793 
795 StatusCode DataSvc::preLoad( int depth, int load_depth, DataObject* pObject ) {
796  // unused: StatusCode sc = StatusCode::FAILURE;
797  if ( pObject && depth++ < load_depth ) {
798  RegEntry* dir = CAST_REGENTRY( RegEntry*, pObject->registry() );
799  if ( dir ) {
800  for ( const auto& i : *dir ) {
801  DataObject* pObj = nullptr;
802  StatusCode status = retrieveObject( pObject, i->name(), pObj );
803  if ( status.isSuccess() && depth < load_depth ) { preLoad( depth, load_depth, pObj ).ignore(); }
804  }
805  }
806  }
807  return StatusCode::SUCCESS;
808 }
809 
812  DataObject* pObj = nullptr;
813  for ( const auto& i : m_preLoads ) {
814  StatusCode sc = retrieveObject( i.path(), pObj );
815  int load_depth = i.depth();
816  if ( sc.isSuccess() && load_depth > 1 ) { preLoad( 1, load_depth, pObj ).ignore(); }
817  }
818  return StatusCode::SUCCESS;
819 }
820 
823  // Nothing to do: just call base class initialisation
825  if ( UNLIKELY( !sc.isSuccess() ) ) return sc;
826  m_incidentSvc = service( "IncidentSvc", true );
827  if ( UNLIKELY( !m_incidentSvc ) ) { error() << "Failed to access incident service." << endmsg; }
828  return sc;
829 }
830 
833  // the finalize part is copied here
834  setDataLoader( nullptr ).ignore();
835  resetPreLoad().ignore();
836  clearStore().ignore();
838  // re-initialize the base class
840  if ( UNLIKELY( !sc.isSuccess() ) ) {
841  error() << "Unable to reinitialize base class" << endmsg;
842  return sc;
843  }
844  // the initialize part is copied here
845  m_incidentSvc = service( "IncidentSvc", true );
846  if ( UNLIKELY( !m_incidentSvc ) ) {
847  error() << "Failed to access incident service." << endmsg;
848  return StatusCode::FAILURE;
849  }
850  // return
851  return StatusCode::SUCCESS;
852 }
853 
856  // Nothing to do: just call base class initialisation
857  setDataLoader( nullptr ).ignore();
858  resetPreLoad().ignore();
859  clearStore().ignore();
861  return Service::finalize();
862 }
863 
865 CLID DataSvc::rootCLID() const { return (CLID)m_rootCLID; }
866 
868 const std::string& DataSvc::rootName() const { return m_rootName; }
869 
872 
Gaudi::Property< CLID > m_rootCLID
Definition: DataSvc.h:61
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
Definition: DataSvc.cpp:776
#define VERMSG
Definition: DataSvc.cpp:80
#define UNLIKELY(x)
Definition: Kernel.h:106
constexpr double sr
StatusCode initialize() override
Definition: Service.cpp:70
std::unique_ptr< DataSvcHelpers::RegistryEntry > m_root
Pointer to root entry.
Definition: DataSvc.h:81
Define general base for Gaudi exception.
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, std::string_view path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
Definition: DataSvc.cpp:538
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:82
StatusCode preLoad() override
load all preload items of the list
Definition: DataSvc.cpp:811
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
constexpr char SEPARATOR
StatusCode finalize() override
Definition: Service.cpp:174
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
Gaudi::Property< std::string > m_accessName
Definition: DataSvc.h:74
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
StatusCode setRoot(std::string root_name, DataObject *pRootObj) override
Initialize data store for new event by giving new event path and root object.
Definition: DataSvc.cpp:142
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:187
RegistryEntry * findLeaf(std::string_view path) const
Find identified leaf in this registry node.
Gaudi::Property< std::string > m_rootName
Definition: DataSvc.h:62
virtual StatusCode setDataProvider(IDataProviderSvc *pService)=0
Set Data provider service.
StatusCode traverseSubTree(std::string_view sub_tree_path, IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects below the sub tree identified by its full pat...
Definition: DataSvc.cpp:120
virtual StatusCode loadObject(IRegistry *pNode)
Invoke Persistency service to create transient object from its persistent representation.
Definition: DataSvc.cpp:470
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
bool isEmpty() const
Simple check if the Container is empty.
Gaudi::Property< bool > m_forceLeaves
Definition: DataSvc.h:65
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:80
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
Definition: DataSvc.cpp:871
Gaudi::Property< bool > m_enableFaultHdlr
Definition: DataSvc.h:68
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:263
IRegistry * find(const IRegistry *obj) const
Try to find an object identified by its pointer.
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Definition: DataSvc.cpp:783
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:27
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:86
IRegistry * parent() const
Pointer to parent directory entry.
virtual StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *refpObject)=0
Update the transient object from the other representation.
STL class.
DataObject * i_handleDataFault(IRegistry *pReg, std::string_view path=std::string_view{})
Definition: DataSvc.cpp:439
const std::string & name() const override
Retrieve name of the service.
Definition: Service.cpp:284
T push_back(T... args)
DataObject * handleDataFault(IRegistry *pReg, std::string_view path="")
Invoke data fault handling if enabled.
Definition: DataSvc.cpp:435
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:63
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
void setObject(DataObject *obj)
Set/Update object address.
Gaudi::Property< std::string > m_faultName
Definition: DataSvc.h:70
IOpaqueAddress * address() const override
Retrieve opaque storage address.
StatusCode unregisterObject(std::string_view fullPath) override
Unregister object from the data store.
Definition: DataSvc.cpp:383
T what(T... args)
StatusCode unregisterAddress(std::string_view fullPath) override
IDataManagerSvc: Unregister object address from the data store.
Definition: DataSvc.cpp:268
StatusCode unlinkObject(IRegistry *from, std::string_view objPath) override
Remove a link to another object.
Definition: DataSvc.cpp:741
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
StatusCode i_retrieveEntry(DataSvcHelpers::RegistryEntry *parentObj, std::string_view path, DataSvcHelpers::RegistryEntry *&pEntry)
Definition: DataSvc.cpp:542
T append(T... args)
virtual StatusCode updateObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Update the references of an updated transient object.
SmartIF< IIncidentSvc > m_incidentSvc
Pointer to incident service.
Definition: DataSvc.h:59
const Store & leaves() const
Access the leaves of the object.
T erase(T... args)
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
StatusCode objectLeaves(const DataObject *pObject, std::vector< IRegistry * > &refLeaves) override
IDataManagerSvc: Explore the object store: retrieve all leaves attached to the object.
Definition: DataSvc.cpp:208
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:99
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:32
const std::string & identifier() const override
Full identifier (or key)
StatusCode finalize() override
Service initialization.
Definition: DataSvc.cpp:855
T reset(T... args)
StatusCode reinitialize() override
Definition: Service.cpp:247
def end
Definition: IOTest.py:123
unsigned int CLID
Class ID definition.
Definition: ClassID.h:18
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Definition: DataSvc.cpp:865
StatusCode remove(std::string_view name)
Remove an entry from the store.
bool isSuccess() const
Definition: StatusCode.h:365
STL class.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
T move(T... args)
virtual DataObject * object() const =0
Retrieve object behind the link.
#define CAST_REGENTRY(x, y)
Definition: DataSvc.cpp:72
const std::string & name() const
Retreive DataObject name. It is the name when registered in the store.
Definition: DataObject.cpp:72
StatusCode registerAddress(std::string_view fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition: DataSvc.cpp:225
Definition of an entry in the transient data store.
Definition: RegistryEntry.h:46
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:56
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition: DataSvc.h:66
StatusCode linkObject(IRegistry *from, std::string_view objPath, DataObject *to) override
Add a link to another object.
Definition: DataSvc.cpp:710
T get(T... args)
T find(T... args)
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:168
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:152
DataObject * object() const override
Retrive object behind the link.
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
StatusCode reinitialize() override
Service initialization.
Definition: DataSvc.cpp:832
SmartIF< IConversionSvc > m_dataLoader
Pointer to data loader service.
Definition: DataSvc.h:55
Generic data agent interface.
StatusCode initialize() override
Service initialization.
Definition: DataSvc.cpp:822
RegistryEntry * parentEntry()
Pointer to parent registry entry.
decltype(auto) operator+(const T &v, const Property< TP, V, H > &p)
implemantation of (value + property)
Definition: Property.h:736
string s
Definition: gaudirun.py:328
constexpr static const auto FAILURE
Definition: StatusCode.h:101
StatusCode registerObject(std::string_view parentPath, std::string_view objPath, DataObject *pObject) override
Register object with the data store.
Definition: DataSvc.cpp:303
Gaudi::Property< bool > m_enableAccessHdlr
Definition: DataSvc.h:72
const Gaudi::Algorithm & parent
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object's parent.
Definition: DataSvc.cpp:194
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Service.h:93
bool isSoft() const
Is the link soft or hard.
virtual const id_type & identifier() const =0
Full identifier (or key)
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:96
bool isFailure() const
Definition: StatusCode.h:145
Data service incident class.
AttribStringParser::Iterator begin(const AttribStringParser &parser)
StatusCode findObject(std::string_view fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition: DataSvc.cpp:650
Opaque address interface definition.
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
Definition: DataSvc.cpp:876
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
Definition: DataSvc.cpp:661
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:40
StatusCode retrieveObject(IRegistry *pDirectory, std::string_view path, DataObject *&pObject) override
Retrieve object from data store.
Definition: DataSvc.cpp:628
StatusCode resetPreLoad() override
Clear the preload list.
Definition: DataSvc.cpp:789
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition: DataSvc.h:77
#define ON_VERBOSE
Definition: DataSvc.cpp:77
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition: DataSvc.cpp:111
StatusCode clearSubTree(std::string_view sub_tree_path) override
IDataManagerSvc: Remove all data objects below the sub tree identified by its full path name.
Definition: DataSvc.cpp:85
DataSvcHelpers::RegistryEntry RegEntry
Definition: DataSvc.cpp:74
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
Definition: DataSvc.cpp:868
void makeHard(DataObject *pObject)
Initialize link as hard link.