The Gaudi Framework  master (181af51f)
Loading...
Searching...
No Matches
TsDataSvc.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 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\***********************************************************************************/
19#include <cassert>
20#include <cstdlib>
21#include <string>
22#include <string_view>
23
24// Macro to lock a scope
25#define STD_LOCK_GUARD_MACRO std::scoped_lock lock{ m_accessMutex };
26
27namespace {
28 std::string operator+( char c, std::string_view sr ) {
29 std::string s{ c };
30 s.append( sr.data(), sr.size() );
31 return s;
32 }
33
34 std::string_view::size_type find( std::string_view s, char c, size_t o ) {
35 if ( !s.empty() ) s.remove_prefix( o );
36 auto r = s.find( c );
37 return r == std::string_view::npos ? r : ( r + o );
38 }
39} // namespace
40
41// If you absolutely need optimization: switch off dynamic_cast.
42// This improves access to the data store roughly by 10 %
43// for balanced trees.
44//
45// M.Frank
46#define CAST_REGENTRY( x, y ) dynamic_cast<x>( y )
47// #define CAST_REGENTRY(x,y) (x)(y)
49
50#define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
51#define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
52
53#define DEBMSG ON_DEBUG debug()
54#define VERMSG ON_VERBOSE verbose()
55
57TsDataSvc::TsDataSvc( const std::string& name, ISvcLocator* svc )
58 : base_class( name, svc ), m_incidentSvc( "IncidentSvc", name ) {}
59
63StatusCode TsDataSvc::clearSubTree( std::string_view sub_tree_path ) {
64 DataObject* pObject = nullptr;
65 StatusCode status = findObject( sub_tree_path, pObject );
66 if ( !status.isSuccess() ) return status;
67 RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
68 if ( !node_entry ) return Status::INVALID_OBJECT;
69 RegEntry* parent = node_entry->parentEntry();
70 if ( !parent ) return Status::INVALID_PARENT;
71 parent->remove( node_entry );
73}
74
79 if ( !checkRoot() ) return Status::INVALID_ROOT;
80 RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
81 if ( !entry ) return Status::INVALID_OBJECT;
82 RegEntry* parent = entry->parentEntry();
83 if ( !parent ) return Status::INVALID_PARENT;
84 parent->remove( entry );
86}
87
90 if ( !checkRoot() ) return Status::INVALID_ROOT;
91 m_root.reset();
93}
94
98StatusCode TsDataSvc::traverseSubTree( std::string_view sub_tree_path, IDataStoreAgent* pAgent ) {
99 DataObject* pO = nullptr;
100 StatusCode status = findObject( sub_tree_path, pO );
101 return status.isSuccess() ? traverseSubTree( pO, pAgent ) : status;
102}
103
107 if ( !checkRoot() ) return Status::INVALID_ROOT;
108 RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
109 if ( !entry ) return Status::INVALID_OBJECT;
110 return entry->traverseTree( pAgent );
111}
112
116 if ( !checkRoot() ) return Status::INVALID_ROOT;
117 return m_root->traverseTree( pAgent );
118}
119
124StatusCode TsDataSvc::setRoot( std::string root_path, DataObject* pRootObj ) {
125 clearStore().ignore();
126 return i_setRoot( std::move( root_path ), pRootObj );
127}
128
134StatusCode TsDataSvc::i_setRoot( std::string root_path, DataObject* pRootObj ) {
135 if ( pRootObj ) {
136 m_root = std::make_unique<RegEntry>( std::move( root_path ) );
137 m_root->makeHard( pRootObj );
138 m_root->setDataSvc( this );
139 // No done with GaudiHive. preLoad().ignore();
140 }
141 return StatusCode::SUCCESS;
142}
143
148StatusCode TsDataSvc::setRoot( std::string root_path, IOpaqueAddress* pRootAddr ) {
149 clearStore().ignore();
150 return i_setRoot( std::move( root_path ), pRootAddr );
151}
152
158StatusCode TsDataSvc::i_setRoot( std::string root_path, IOpaqueAddress* pRootAddr ) {
159 if ( pRootAddr ) {
160 m_root = std::make_unique<RegEntry>( std::move( root_path ) );
161 m_root->makeHard( pRootAddr );
162 m_root->setDataSvc( this );
163 // Not done with GaudiHive. preLoad().ignore();
164 }
165 return StatusCode::SUCCESS;
166}
167
170 if ( pDataLoader ) pDataLoader->addRef();
171 if ( m_dataLoader ) m_dataLoader->release();
172 if ( pDataLoader ) { pDataLoader->setDataProvider( dpsvc == nullptr ? this : dpsvc ).ignore(); }
173 m_dataLoader = pDataLoader;
174 return StatusCode::SUCCESS;
175}
176
179 if ( !pObject ) return Status::INVALID_OBJECT;
180 return objectParent( pObject->registry(), refpParent );
181}
182
183StatusCode TsDataSvc::objectParent( const IRegistry* pRegistry, IRegistry*& refpParent ) {
185 if ( !checkRoot() ) return Status::INVALID_ROOT;
186 const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
187 if ( !node_entry ) return Status::INVALID_OBJECT;
188 refpParent = node_entry->parent();
189 return StatusCode::SUCCESS;
190}
191
193StatusCode TsDataSvc::objectLeaves( const DataObject* pObject, std::vector<IRegistry*>& leaves ) {
194 if ( !pObject ) return Status::INVALID_OBJECT;
195 return objectLeaves( pObject->registry(), leaves );
196}
197
201StatusCode TsDataSvc::objectLeaves( const IRegistry* pRegistry, std::vector<IRegistry*>& leaves ) {
202 if ( !pRegistry ) return Status::INVALID_OBJECT;
203 const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
204 if ( !node_entry ) return Status::INVALID_OBJECT;
206 leaves.insert( leaves.end(), node_entry->leaves().begin(), node_entry->leaves().end() );
207 // leaves = node_entry->leaves();
208 return StatusCode::SUCCESS;
209}
210
212StatusCode TsDataSvc::registerAddress( std::string_view fullPath, IOpaqueAddress* pAddress ) {
213 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
214 return registerAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath, pAddress );
215}
216
218StatusCode TsDataSvc::registerAddress( IRegistry* parentObj, std::string_view objPath, IOpaqueAddress* pAddress ) {
219 if ( !checkRoot() ) return Status::INVALID_ROOT;
220 if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
221 if ( !parentObj ) {
222 if ( objPath.front() != SEPARATOR ) { return registerAddress( m_root.get(), objPath, pAddress ); }
223 auto sep = find( objPath, SEPARATOR, 1 );
224 if ( sep == std::string_view::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
225 return Status::INVALID_PARENT;
226 }
227 return registerAddress( m_root.get(), objPath.substr( sep ), pAddress );
228 }
229 if ( objPath.front() != SEPARATOR ) { return registerAddress( parentObj, SEPARATOR + objPath, pAddress ); }
230 RegEntry* par_entry = CAST_REGENTRY( RegEntry*, parentObj );
231 if ( !par_entry ) return Status::INVALID_PARENT;
232 auto sep = objPath.rfind( SEPARATOR );
233 if ( sep > 0 && sep != std::string_view::npos ) {
234 auto p_path = objPath.substr( 0, sep );
235 auto o_path = objPath.substr( sep );
236 RegEntry* p_entry = par_entry->findLeaf( p_path );
237 // Create default object leafs if the
238 // intermediate nodes are not present
239 if ( !p_entry && m_forceLeaves ) {
241 StatusCode sc = registerObject( par_entry->identifier(), p_path, pLeaf );
242 if ( !sc.isSuccess() ) delete pLeaf;
243 p_entry = par_entry->findLeaf( p_path );
244 }
245 if ( !p_entry ) return Status::INVALID_PARENT;
246 return registerAddress( p_entry, o_path, pAddress );
247 }
248 StatusCode status = par_entry->add( std::string{ objPath }, pAddress );
249 return status.isSuccess() ? status : Status::DOUBL_OBJ_PATH;
250}
251
253StatusCode TsDataSvc::unregisterAddress( std::string_view fullPath ) {
254 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
255 return unregisterAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath );
256}
257
259StatusCode TsDataSvc::unregisterAddress( IRegistry* pParent, std::string_view objPath ) {
260 if ( !checkRoot() ) return Status::INVALID_ROOT;
261
262 if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
263 if ( !pParent ) {
264 if ( objPath.front() != SEPARATOR ) { return unregisterAddress( m_root.get(), objPath ); }
265 auto sep = find( objPath, SEPARATOR, 1 );
266 if ( sep == std::string_view::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
267 return Status::INVALID_PARENT;
268 }
269 return unregisterAddress( m_root.get(), objPath.substr( sep ) );
270 }
271 if ( objPath.front() != SEPARATOR ) { return unregisterAddress( pParent, SEPARATOR + objPath ); }
272 RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pParent );
273 if ( node_entry ) {
274 RegEntry* leaf_entry = node_entry->findLeaf( objPath );
275 if ( leaf_entry ) {
276 auto sep = objPath.rfind( SEPARATOR );
277 if ( sep > 0 && sep != std::string_view::npos ) {
278 return unregisterAddress( leaf_entry->parent(), objPath.substr( sep ) );
279 }
280 StatusCode status = node_entry->remove( objPath );
281 if ( status.isSuccess() ) return status;
282 }
283 }
284 return Status::INVALID_PARENT;
285}
286
288StatusCode TsDataSvc::registerObject( std::string_view parentPath, std::string_view objPath, DataObject* pObject ) {
289 DataObject* pO = nullptr;
290 StatusCode status = retrieveObject( parentPath, pO );
291 if ( !status.isSuccess() && m_forceLeaves ) {
292 pO = createDefaultObject();
293 status = registerObject( parentPath, pO );
294 if ( !status.isSuccess() ) pO->release();
295 }
296 return status.isSuccess() ? registerObject( pO, objPath, pObject ) : status;
297}
298
300StatusCode TsDataSvc::registerObject( DataObject* parentObj, std::string_view objPath, DataObject* pObject ) {
301 if ( !checkRoot() ) return Status::INVALID_ROOT;
302 if ( !parentObj ) {
303 if ( !objPath.empty() ) {
304 if ( objPath.front() != SEPARATOR ) { return registerObject( m_rootName.value(), objPath, pObject ); }
305 auto sep = find( objPath, SEPARATOR, 1 );
306 if ( sep != std::string_view::npos ) {
307 return registerObject( objPath.substr( 0, sep ), objPath.substr( sep ), pObject );
308 }
309 }
310 return Status::INVALID_OBJ_PATH;
311 }
312 RegEntry* node_entry = CAST_REGENTRY( RegEntry*, parentObj->registry() );
313 if ( node_entry ) {
314 StatusCode status = Status::INVALID_PARENT;
315 auto sep = find( objPath, SEPARATOR, 1 );
316 if ( sep != std::string_view::npos ) {
317 auto p_path = objPath.substr( 0, sep );
318 auto o_path = objPath.substr( sep );
319 RegEntry* par_entry = node_entry->findLeaf( p_path );
320 // Create default object leafs if the
321 // intermediate nodes are not present
322 if ( !par_entry && m_forceLeaves ) {
324 StatusCode sc = registerObject( parentObj, p_path, pLeaf );
325 if ( !sc.isSuccess() ) delete pLeaf;
326 par_entry = node_entry->findLeaf( p_path );
327 } else if ( par_entry && !par_entry->object() ) {
328 status = retrieveEntry( node_entry, p_path, par_entry );
329 if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
331 StatusCode sc = registerObject( parentObj, p_path, pLeaf );
332 if ( !sc.isSuccess() ) delete pLeaf;
333 par_entry = node_entry->findLeaf( p_path );
334 }
335 }
336 node_entry = par_entry;
337 if ( node_entry ) {
338 DataObject* obj = node_entry->object();
339 if ( obj ) status = registerObject( obj, o_path, pObject );
340 }
341 } else {
342 RegEntry* leaf = node_entry->findLeaf( objPath );
343 if ( !leaf ) {
344 status = node_entry->add( std::string{ objPath }, pObject );
345 } else {
346 DataObject* obj = leaf->object();
347 if ( !obj ) {
348 if ( !pObject ) {
349 error() << "registerObject: trying to register null DataObject" << endmsg;
350 return StatusCode::FAILURE;
351 } else {
352 pObject->setRegistry( leaf );
353 }
354 leaf->setAddress( nullptr );
355 leaf->setObject( pObject );
356 status = StatusCode::SUCCESS;
357 } else {
358 status = Status::DOUBL_OBJ_PATH;
359 }
360 }
361 }
362 return status;
363 }
364 return Status::INVALID_PARENT;
365}
366
368StatusCode TsDataSvc::unregisterObject( std::string_view fullPath ) {
369 DataObject* pObject = nullptr;
370 StatusCode status = findObject( fullPath, pObject );
371 if ( status.isFailure() ) return status;
372 RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pObject->registry() );
373 if ( !pEntry ) return Status::INVALID_ROOT;
374 if ( !pEntry->isEmpty() ) return Status::DIR_NOT_EMPTY;
375 RegEntry* pParent = pEntry->parentEntry();
376 if ( !pParent ) return Status::INVALID_PARENT;
377 pObject->addRef();
378 pParent->remove( pEntry );
379 return StatusCode::SUCCESS;
380}
381
384 if ( !checkRoot() ) return Status::INVALID_ROOT;
385 RegEntry* entry = m_root->findLeaf( pObject );
386 if ( !entry ) return Status::INVALID_OBJECT;
387 RegEntry* parent = entry->parentEntry();
388 if ( !parent ) return Status::INVALID_PARENT;
389 if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
390 if ( entry->object() ) entry->object()->addRef();
391 if ( parent ) parent->remove( entry );
392 return StatusCode::SUCCESS;
393}
394
396StatusCode TsDataSvc::unregisterObject( DataObject* pParentObj, std::string_view objectPath ) {
397 if ( !checkRoot() ) return Status::INVALID_ROOT;
398 try {
399 RegEntry* parent = CAST_REGENTRY( RegEntry*, pParentObj->registry() );
400 if ( parent ) {
401 RegEntry* entry = parent->findLeaf( objectPath );
402 if ( !entry ) return Status::INVALID_OBJECT;
403 if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
404 if ( entry->object() ) entry->object()->addRef();
405 parent->remove( entry );
406 return StatusCode::SUCCESS;
407 }
408 } catch ( ... ) {}
409 return Status::INVALID_PARENT;
410}
411
414DataObject* TsDataSvc::handleDataFault( IRegistry* pReg, std::string_view path ) {
415 if ( m_enableFaultHdlr ) {
416 IRegistry* pLeaf = nullptr;
417 if ( pReg && path.empty() ) {
418 DataIncident incident( name(), m_faultName, pReg->identifier() );
419 m_incidentSvc->fireIncident( incident );
420 return pReg->object();
421 } else if ( pReg ) {
422 std::string p = pReg->identifier();
423 if ( path.front() != SEPARATOR ) p += SEPARATOR;
424 p.append( path.data(), path.size() );
425 DataIncident incident( name(), m_faultName, p );
426 m_incidentSvc->fireIncident( incident );
427 pLeaf = m_root->findLeaf( p );
428 } else {
429 std::string p = m_root->identifier();
430 if ( path.front() != SEPARATOR ) p += SEPARATOR;
431 p.append( path.data(), path.size() );
432 DataIncident incident( name(), m_faultName, p );
433 m_incidentSvc->fireIncident( incident );
434 pLeaf = m_root->findLeaf( p );
435 }
436 if ( pLeaf ) return pLeaf->object();
437 }
438 return nullptr;
439}
440
445 IConversionSvc* pLoader = getDataLoader( pRegistry );
446 return loadObject( pLoader, pRegistry );
447}
448
453 StatusCode status = Status::INVALID_OBJ_ADDR;
454 DataObject* pObject = nullptr;
456 if ( !pLoader ) { // Precondition: Data loader must be present
457 if ( handleDataFault( pRegistry ) )
458 return StatusCode::SUCCESS;
459 else
460 return Status::NO_DATA_LOADER;
461 }
462 if ( !pRegistry ) { // Precondition: Directory must be valid
463 if ( handleDataFault( pRegistry ) )
464 return StatusCode::SUCCESS;
465 else
466 return Status::INVALID_OBJ_ADDR;
467 }
468
469 VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
470
471 if ( m_enableAccessHdlr ) {
472 // Fire data access incident
473 DataIncident incident( name(), m_accessName, pRegistry->identifier() );
474 m_incidentSvc->fireIncident( incident );
475 }
476 if ( !m_inhibitPathes.empty() ) {
477 const auto& ident = pRegistry->identifier();
478 auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), ident );
479 if ( inhibit != m_inhibitPathes.end() ) return Status::NO_ACCESS;
480 }
481 IOpaqueAddress* pAddress = pRegistry->address();
482 if ( !pAddress ) { // Precondition:
483 return Status::INVALID_OBJ_ADDR; // Address must be valid
484 }
485 try {
486 status = pLoader->createObj( pAddress, pObject ); // Call data loader
487 if ( status.isSuccess() ) {
488
489 VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
490
491 RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pRegistry );
492 pEntry->setObject( pObject );
493
494 VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
495 status = pLoader->fillObjRefs( pAddress, pObject );
496 }
497 } catch ( const GaudiException& exc ) {
498 if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
499 throw GaudiException( "GaudiException in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE,
500 exc );
501 } catch ( const std::exception& x ) {
502 if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
503 throw GaudiException( "std::exception in loadObject() " + pRegistry->identifier() + ": " +
504 System::typeinfoName( typeid( x ) ) + ", " + x.what(),
506 } catch ( ... ) {
507 if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
508 throw GaudiException( "UNKN exception in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE );
509 }
510 if ( !status.isSuccess() ) {
511 if ( handleDataFault( pRegistry ) ) return StatusCode::SUCCESS;
512 }
513 ON_VERBOSE if ( status.isSuccess() ) {
514 verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
515 }
516 return status;
517}
518
520StatusCode TsDataSvc::retrieveEntry( RegEntry* parentObj, std::string_view path, RegEntry*& pEntry ) {
521 auto sep = find( path, SEPARATOR, 1 );
522 StatusCode status = Status::INVALID_ROOT;
523 pEntry = nullptr;
525 // A.Valassi 16.08.2001 avoid core dump if store is empty
526 if ( checkRoot() ) {
527 if ( !parentObj ) {
528 if ( path.empty() || path == m_rootName ) return retrieveEntry( m_root.get(), "", pEntry );
529 if ( path.front() != SEPARATOR ) return retrieveEntry( m_root.get(), path, pEntry );
530 if ( sep == std::string_view::npos ) return Status::INVALID_OBJ_PATH;
531 if ( !m_root->object() ) {
532 RegEntry* r = nullptr;
533 status = retrieveEntry( m_root.get(), "", r );
534 if ( !status.isSuccess() ) return status;
535 }
536 return retrieveEntry( m_root.get(), path.substr( sep ), pEntry );
537 }
538 if ( sep != std::string_view::npos ) { // the string contains a separator (after pos 0)
539 auto p_path = path.substr( 0, sep );
540 auto o_path = path.substr( sep );
541 if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
542 status = loadObject( parentObj );
543 if ( !status.isSuccess() ) return status;
544 }
545 RegEntry* root_entry = parentObj->findLeaf( p_path );
546 if ( !root_entry && m_enableFaultHdlr ) {
547 // If not even the parent is there, an incident
548 // to load the parent must be fired...
549 handleDataFault( parentObj, p_path );
550 root_entry = parentObj->findLeaf( p_path );
551 }
552 if ( root_entry ) {
553 DataObject* pO = root_entry->object();
554 if ( !pO ) {
555 // Object is not loaded: load the object if at all possible
556 status = loadObject( root_entry );
557 if ( !status.isSuccess() ) return status;
558 }
559 if ( root_entry->isSoft() ) { root_entry = CAST_REGENTRY( RegEntry*, pO->registry() ); }
560 return retrieveEntry( root_entry, o_path, pEntry );
561 }
562 return Status::INVALID_OBJ_PATH;
563 } else if ( path.empty() ) {
564 pEntry = parentObj;
565 } else {
566 if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
567 status = loadObject( parentObj );
568 if ( !status.isSuccess() ) return status;
569 }
570 // last leave in search: find leaf and load
571 pEntry = parentObj->findLeaf( path );
572 // If no registry entry was found, trigger incident for action-on-demand
573 if ( !pEntry && m_enableFaultHdlr ) {
574 handleDataFault( parentObj, path );
575 pEntry = ( path.empty() ? parentObj : parentObj->findLeaf( path ) );
576 }
577 }
578 // Check results and return
579 if ( !pEntry ) {
580 status = Status::INVALID_OBJ_PATH;
581 } else if ( !pEntry->object() ) {
582 status = loadObject( pEntry );
583 } else if ( m_enableAccessHdlr ) {
584 // Fire data access incident
585 // I do not know if this is a good idea....
586 // This fires too often!
587 //
588 // DataIncident incident(name(), m_accessName, pEntry->identifier());
589 // m_incidentSvc->fireIncident(incident);
590 status = StatusCode::SUCCESS;
591 } else {
592 status = StatusCode::SUCCESS;
593 }
594 }
595 return status;
596}
597
599StatusCode TsDataSvc::retrieveObject( IRegistry* pRegistry, std::string_view path, DataObject*& pObject ) {
600 pObject = nullptr;
601 RegEntry * result = nullptr, *parent = CAST_REGENTRY( RegEntry*, pRegistry );
602 StatusCode status = retrieveEntry( parent, path, result );
603 if ( status.isSuccess() ) pObject = result->object();
604 return status;
605}
606
608StatusCode TsDataSvc::findObject( IRegistry* pRegistry, std::string_view path, DataObject*& pObject ) {
610 pObject = nullptr;
611 IRegistry* pReg = ( pRegistry ? pRegistry : m_root.get() );
612 RegEntry* root_entry = CAST_REGENTRY( RegEntry*, pReg );
613 if ( root_entry ) {
614 if ( !path.empty() ) pReg = root_entry->find( path );
615 if ( !pReg ) return Status::INVALID_OBJ_PATH;
616 pObject = pReg->object();
617 }
618 return pObject ? Status::IDataProviderSvc_NO_ERROR : Status::OBJ_NOT_LOADED;
619}
620
622StatusCode TsDataSvc::findObject( std::string_view path, DataObject*& pObject ) {
623 pObject = nullptr;
625 if ( !checkRoot() ) return Status::INVALID_ROOT;
626 if ( path.empty() || path == m_rootName ) {
627 pObject = m_root->object();
628 return !pObject ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
629 }
630 return findObject( path.front() != SEPARATOR ? m_root.get() : nullptr, path, pObject );
631}
632
635 if ( !pRegistry ) return Status::INVALID_OBJ_ADDR; // Precondition: Addres must be valid
636 DataObject* toUpdate = pRegistry->object();
637 return toUpdate ? updateObject( toUpdate ) : loadObject( pRegistry );
638}
639
642 StatusCode status = Status::INVALID_OBJ_ADDR;
643 if ( !toUpdate ) return Status::INVALID_OBJECT; // Precondition: Address must be valid
644 IRegistry* pRegistry = toUpdate->registry();
645 if ( !pRegistry ) return Status::INVALID_OBJECT; // Precondition: Need valid registry
646 IOpaqueAddress* pAddress = pRegistry->address();
647 if ( !pAddress ) return Status::INVALID_OBJ_ADDR; // Precondition: Need valid address
649 IConversionSvc* pLoader = getDataLoader( pRegistry );
650 if ( !pLoader ) return Status::NO_DATA_LOADER; // Precondition: Data loader must be present
651 if ( !m_inhibitPathes.empty() ) {
652 auto& ident = pRegistry->identifier();
653 auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), ident );
654 if ( inhibit != m_inhibitPathes.end() ) return Status::NO_ACCESS;
655 }
656 try {
657 status = pLoader->updateObj( pAddress, toUpdate ); // Call data loader
658 if ( status.isSuccess() ) { status = pLoader->updateObjRefs( pAddress, toUpdate ); }
659 } catch ( const GaudiException& exc ) {
660 throw GaudiException( "GaudiException in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE, exc );
661 } catch ( const std::exception& x ) {
662 throw GaudiException( "std::exception in updateObject() " + pRegistry->name() + ": " +
663 System::typeinfoName( typeid( x ) ) + ", " + x.what(),
665 } catch ( ... ) {
666 throw GaudiException( "UNKN exception in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE );
667 }
668 return status;
669}
670
671// Link object
672StatusCode TsDataSvc::linkObject( IRegistry* from, std::string_view objPath, DataObject* to ) {
674 if ( !checkRoot() ) return Status::INVALID_ROOT;
675 try {
676 RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
677 if ( from_entry ) {
678 // First check if both objects are already registered to the store
679 RegEntry* to_entry = m_root->findLeaf( to );
680 if ( !to_entry ) return Status::INVALID_OBJECT;
681 auto sep = objPath.rfind( SEPARATOR );
682 if ( sep > 0 && sep != std::string_view::npos ) { // in case the objPath is a sub-directory itself
683 DataObject* pO = nullptr;
684 StatusCode sc = retrieveObject( from, objPath.substr( 0, sep ), pO );
685 return sc.isSuccess() ? linkObject( pO->registry(), objPath.substr( sep ), to ) : sc;
686 }
687 // Now register the soft link
688 StatusCode status = from_entry->add( std::string{ objPath }, to, true );
689 return status.isSuccess() ? Status::IDataProviderSvc_NO_ERROR : Status::DOUBL_OBJ_PATH;
690 }
691 } catch ( ... ) {}
692 return Status::INVALID_PARENT;
693}
694
696StatusCode TsDataSvc::linkObject( std::string_view fullPath, DataObject* to ) {
697 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
698 if ( fullPath.front() == SEPARATOR ) {
699 auto sep = fullPath.rfind( SEPARATOR );
700 return linkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ), to );
701 }
703 return linkObject( m_root.get(), fullPath, to );
704}
705
707StatusCode TsDataSvc::unlinkObject( IRegistry* from, std::string_view objPath ) {
709 if ( !checkRoot() ) return Status::INVALID_ROOT;
710 try {
711 RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
712 if ( from_entry ) {
713 auto sep = objPath.rfind( SEPARATOR );
714 if ( sep > 0 && sep != std::string_view::npos ) { // in case the objPath is a sub-directory itself
715 DataObject* pO = nullptr;
716 StatusCode sc = findObject( from, objPath.substr( 0, sep ), pO );
717 return sc.isSuccess() ? unlinkObject( pO->registry(), objPath.substr( sep ) ) : sc;
718 }
719 StatusCode status = from_entry->remove( objPath );
720 return status.isSuccess() ? status : Status::INVALID_OBJ_PATH;
721 }
722 } catch ( ... ) {}
723 return Status::INVALID_PARENT;
724}
725
727StatusCode TsDataSvc::unlinkObject( std::string_view fullPath ) {
728 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
729 if ( fullPath.front() != SEPARATOR ) { return unlinkObject( m_root.get(), fullPath ); }
730 auto sep = fullPath.rfind( SEPARATOR );
731 return unlinkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ) );
732}
733
735StatusCode TsDataSvc::unlinkObject( DataObject* from, std::string_view objPath ) {
736 if ( !checkRoot() ) return Status::INVALID_ROOT;
737 return unlinkObject( m_root->findLeaf( from ), objPath );
738}
739
742 auto i = std::find( m_preLoads.begin(), m_preLoads.end(), item );
743 if ( i == m_preLoads.end() ) m_preLoads.push_back( item );
744 return StatusCode::SUCCESS;
745}
746
749 auto i = std::remove( m_preLoads.begin(), m_preLoads.end(), item );
750 m_preLoads.erase( i, m_preLoads.end() );
751 return StatusCode::SUCCESS;
752}
753
759
761StatusCode TsDataSvc::preLoad( int depth, int load_depth, DataObject* pObject ) {
762 // unused: StatusCode sc = StatusCode::FAILURE;
763 if ( pObject && depth++ < load_depth ) {
764 RegEntry* dir = CAST_REGENTRY( RegEntry*, pObject->registry() );
765 if ( dir ) {
766 for ( const auto& i : *dir ) {
767 DataObject* pObj = nullptr;
768 StatusCode status = retrieveObject( pObject, i->name(), pObj );
769 if ( status.isSuccess() && depth < load_depth ) { preLoad( depth, load_depth, pObj ).ignore(); }
770 }
771 }
772 }
773 return StatusCode::SUCCESS;
774}
775
778 DataObject* pObj = nullptr;
779 for ( const auto& i : m_preLoads ) {
780 StatusCode sc = retrieveObject( i.path(), pObj );
781 int load_depth = i.depth();
782 if ( sc.isSuccess() && load_depth > 1 ) { preLoad( 1, load_depth, pObj ).ignore(); }
783 }
784 return StatusCode::SUCCESS;
785}
786
789 // Nothing to do: just call base class initialisation
791 if ( !sc.isSuccess() ) return sc;
792 sc = m_incidentSvc.retrieve();
793 if ( !sc.isSuccess() ) { error() << "Failed to access incident service." << endmsg; }
794 return sc;
795}
796
799 StatusCode sc;
800 // the finalize part is copied here
801 setDataLoader( nullptr ).ignore();
803 clearStore().ignore();
804 // re-initialize the base class
806 if ( !sc.isSuccess() ) {
807 error() << "Unable to reinitialize base class" << endmsg;
808 return sc;
809 }
810 // the initialize part is copied here
811 sc = m_incidentSvc.retrieve();
812 if ( !sc.isSuccess() ) {
813 error() << "Failed to access incident service." << endmsg;
814 return sc;
815 }
816
817 return StatusCode::SUCCESS;
818}
819
822 // Nothing to do: just call base class initialisation
823 setDataLoader( nullptr ).ignore();
825 clearStore().ignore();
826 return Service::finalize();
827}
828
830CLID TsDataSvc::rootCLID() const { return ( (CLID)m_rootCLID ); }
831
833const std::string& TsDataSvc::rootName() const { return ( m_rootName ); }
834
837
#define ON_VERBOSE
unsigned int CLID
Class ID definition.
Definition ClassID.h:16
DataSvcHelpers::RegistryEntry RegEntry
Definition DataSvc.cpp:48
#define CAST_REGENTRY(x, y)
Definition DataSvc.cpp:46
#define VERMSG
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
GAUDI_API Stat operator+(const Stat &stat, const double value)
external operator for addition of Stat and a number
Definition Stat.cpp:69
#define STD_LOCK_GUARD_MACRO
Definition TsDataSvc.cpp:25
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Data service incident class.
A DataObject is the base class of any identifiable object on any data store.
Definition DataObject.h:37
virtual unsigned long addRef()
Add reference to object.
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition DataObject.h:77
const std::string & name() const
Retreive DataObject name. It is the name when registered in the store.
IRegistry * registry() const
Get pointer to Registry.
Definition DataObject.h:79
virtual unsigned long release()
release reference to object
Description of the DataStoreItem class.
Definition of an entry in the transient data store.
void setObject(DataObject *obj)
Set/Update object address.
StatusCode traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
IRegistry * parent() const
Pointer to parent directory entry.
const Store & leaves() const
Access the leaves of the object.
bool isSoft() const
Is the link soft or hard.
const std::string & identifier() const override
Full identifier (or key)
RegistryEntry * findLeaf(std::string_view path) const
Find identified leaf in this registry node.
IRegistry * find(const IRegistry *obj) const
Try to find an object identified by its pointer.
RegistryEntry * parentEntry()
Pointer to parent registry entry.
DataObject * object() const override
Retrive object behind the link.
bool isEmpty() const
Simple check if the Container is empty.
IOpaqueAddress * address() const override
Retrieve opaque storage address.
StatusCode remove(std::string_view name)
Remove an entry from the store.
StatusCode add(std::string name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
Define general base for Gaudi exception.
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
virtual StatusCode setDataProvider(IDataProviderSvc *pService)=0
Set Data provider service.
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
Data provider interface definition.
Generic data agent interface.
virtual unsigned long addRef() const =0
Increment the reference count of Interface instance.
Opaque address interface definition.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition IRegistry.h:29
virtual const name_type & name() const =0
Name of the directory (or key)
virtual const id_type & identifier() const =0
Full identifier (or key)
virtual DataObject * object() const =0
Retrieve object behind the link.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition ISvcLocator.h:42
StatusCode finalize() override
Definition Service.cpp:223
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
StatusCode reinitialize() override
Definition Service.cpp:296
StatusCode initialize() override
Definition Service.cpp:118
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition StatusCode.h:139
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, std::string_view path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
StatusCode setRoot(std::string root_name, DataObject *pRootObj) override
Initialize data store for new event by giving new event path and root object.
ServiceHandle< IIncidentSvc > m_incidentSvc
Handle to incident service.
Definition TsDataSvc.h:58
Gaudi::Property< bool > m_forceLeaves
Definition TsDataSvc.h:62
virtual StatusCode i_setRoot(std::string root_name, DataObject *pRootObj)
Initialize data store for new event by giving new event path and root object.
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object's parent.
Gaudi::Property< CLID > m_rootCLID
Definition TsDataSvc.h:60
Gaudi::Property< bool > m_enableFaultHdlr
Definition TsDataSvc.h:66
Gaudi::Property< std::string > m_faultName
Definition TsDataSvc.h:68
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
bool checkRoot()
Check if root path is valid.
Definition TsDataSvc.h:260
StatusCode finalize() override
Service initialization.
StatusCode resetPreLoad() override
Clear the preload list.
StatusCode retrieveObject(IRegistry *pDirectory, std::string_view path, DataObject *&pObject) override
Retrieve object from data store.
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition TsDataSvc.h:75
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
StatusCode unregisterObject(std::string_view fullPath) override
Unregister object from the data store.
StatusCode registerAddress(std::string_view fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
StatusCode initialize() override
Service initialization.
Gaudi::Property< std::string > m_accessName
Definition TsDataSvc.h:72
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition TsDataSvc.h:64
StatusCode objectLeaves(const DataObject *pObject, std::vector< IRegistry * > &refLeaves) override
IDataManagerSvc: Explore the object store: retrieve all leaves attached to the object.
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Gaudi::Property< bool > m_enableAccessHdlr
Definition TsDataSvc.h:70
StatusCode traverseTree(IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects in the data store.
StatusCode reinitialize() override
Service initialization.
StatusCode unlinkObject(IRegistry *from, std::string_view objPath) override
Remove a link to another object.
virtual StatusCode loadObject(IRegistry *pNode)
Invoke Persistency service to create transient object from its persistent representation.
StatusCode preLoad() override
load all preload items of the list
StatusCode unregisterAddress(std::string_view fullPath) override
IDataManagerSvc: Unregister object address from the data store.
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 TsDataSvc.cpp:63
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition TsDataSvc.cpp:89
DataObject * handleDataFault(IRegistry *pReg, std::string_view path={})
Invoke data fault handling if enabled.
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Gaudi::Property< std::string > m_rootName
Definition TsDataSvc.h:61
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
StatusCode registerObject(std::string_view parentPath, std::string_view objPath, DataObject *pObject) override
Register object with the data store.
std::unique_ptr< DataSvcHelpers::RegistryEntry > m_root
Pointer to root entry.
Definition TsDataSvc.h:77
StatusCode setDataLoader(IConversionSvc *svc, IDataProviderSvc *dpsvc=nullptr) override
IDataManagerSvc: IDataManagerSvc: Pass a default data loader to the service and optionally a data pro...
TsDataSvc(const std::string &name, ISvcLocator *svc)
constructor
Definition TsDataSvc.cpp:57
StatusCode findObject(std::string_view fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
IConversionSvc * m_dataLoader
Pointer to data loader service.
Definition TsDataSvc.h:56
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 TsDataSvc.cpp:98
StatusCode linkObject(IRegistry *from, std::string_view objPath, DataObject *to) override
Add a link to another object.
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:260