The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
DataSvc.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\***********************************************************************************/
11#define DATASVC_DATASVC_CPP
12
15#include <GaudiKernel/DataSvc.h>
22#include <cassert>
23#include <cstdlib>
24
25namespace {
26 std::string operator+( char c, std::string_view sr ) {
27 std::string s{ c };
28 s.append( sr.data(), sr.size() );
29 return s;
30 }
31
32 std::string_view::size_type find( std::string_view s, char c, size_t o ) {
33 if ( !s.empty() ) s.remove_prefix( o );
34 auto r = s.find( c );
35 return r == std::string_view::npos ? r : ( r + o );
36 }
37
38 std::string to_string( std::string_view sr ) { return { sr.data(), sr.size() }; }
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
59StatusCode DataSvc::clearSubTree( std::string_view sub_tree_path ) {
60 DataObject* pObject = nullptr;
61 StatusCode status = findObject( sub_tree_path, pObject );
62 if ( !status.isSuccess() ) return status;
63 RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
64 if ( !node_entry ) return Status::INVALID_OBJECT;
65 RegEntry* parent = node_entry->parentEntry();
66 if ( !parent ) return Status::INVALID_PARENT;
67 parent->remove( node_entry );
69}
70
75 if ( !checkRoot() ) return Status::INVALID_ROOT;
76 RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
77 if ( !entry ) return Status::INVALID_OBJECT;
78 RegEntry* parent = entry->parentEntry();
79 if ( !parent ) return Status::INVALID_PARENT;
80 parent->remove( entry );
82}
83
86 if ( checkRoot() ) m_root.reset();
88}
89
93StatusCode DataSvc::traverseSubTree( std::string_view sub_tree_path, IDataStoreAgent* pAgent ) {
94 DataObject* pO = nullptr;
95 StatusCode status = findObject( sub_tree_path, pO );
96 return status.isSuccess() ? traverseSubTree( pO, pAgent ) : status;
97}
98
101 RegEntry* entry = CAST_REGENTRY( RegEntry*, pObject->registry() );
102 return entry ? entry->traverseTree( pAgent ) : Status::INVALID_OBJECT;
103}
104
107 if ( !checkRoot() ) return Status::INVALID_ROOT;
108 return m_root->traverseTree( pAgent );
109}
110
115StatusCode DataSvc::setRoot( std::string root_path, DataObject* pRootObj ) {
116 clearStore().ignore();
117 return i_setRoot( std::move( root_path ), pRootObj );
118}
119
125StatusCode DataSvc::i_setRoot( std::string root_path, DataObject* pRootObj ) {
126 if ( pRootObj ) {
127 m_root = std::make_unique<RegEntry>( std::move( root_path ) );
128 m_root->makeHard( pRootObj );
129 m_root->setDataSvc( this );
130 // No done with GaudiHive. preLoad().ignore();
131 }
132 return StatusCode::SUCCESS;
133}
134
139StatusCode DataSvc::setRoot( std::string root_path, IOpaqueAddress* pRootAddr ) {
140 clearStore().ignore();
141 return i_setRoot( std::move( root_path ), pRootAddr );
142}
143
149StatusCode DataSvc::i_setRoot( std::string root_path, IOpaqueAddress* pRootAddr ) {
150 if ( pRootAddr ) {
151 m_root = std::make_unique<RegEntry>( std::move( root_path ) );
152 m_root->makeHard( pRootAddr );
153 m_root->setDataSvc( this );
154 // Not done with GaudiHive. preLoad().ignore();
155 }
156 return StatusCode::SUCCESS;
157}
158
161 m_dataLoader = pDataLoader;
162 if ( m_dataLoader ) m_dataLoader->setDataProvider( dpsvc ? dpsvc : this ).ignore();
163 return StatusCode::SUCCESS;
164}
165
167StatusCode DataSvc::objectParent( const DataObject* pObject, IRegistry*& refpParent ) {
168 if ( !pObject ) return Status::INVALID_OBJECT;
169 return objectParent( pObject->registry(), refpParent );
170}
171
172StatusCode DataSvc::objectParent( const IRegistry* pRegistry, IRegistry*& refpParent ) {
173 if ( !checkRoot() ) return Status::INVALID_ROOT;
174 const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
175 if ( !node_entry ) return Status::INVALID_OBJECT;
176 refpParent = node_entry->parent();
177 return StatusCode::SUCCESS;
178}
179
181StatusCode DataSvc::objectLeaves( const DataObject* pObject, std::vector<IRegistry*>& leaves ) {
182 if ( !pObject ) return Status::INVALID_OBJECT;
183 return objectLeaves( pObject->registry(), leaves );
185
187 * registry entry.
188 */
189StatusCode DataSvc::objectLeaves( const IRegistry* pRegistry, std::vector<IRegistry*>& leaves ) {
190 if ( !checkRoot() ) return Status::INVALID_ROOT;
191 const RegEntry* node_entry = CAST_REGENTRY( const RegEntry*, pRegistry );
192 if ( !node_entry ) return Status::INVALID_OBJECT;
193 leaves = node_entry->leaves();
194 return StatusCode::SUCCESS;
195}
196
198StatusCode DataSvc::registerAddress( std::string_view fullPath, IOpaqueAddress* pAddress ) {
199 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
200 return registerAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath, pAddress );
201}
202
204StatusCode DataSvc::registerAddress( IRegistry* parentObj, std::string_view objPath, IOpaqueAddress* pAddress ) {
205 if ( !checkRoot() ) return Status::INVALID_ROOT;
206 if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
207
208 if ( !parentObj ) {
209 if ( objPath.front() != SEPARATOR ) { return registerAddress( m_root.get(), objPath, pAddress ); }
210 auto sep = find( objPath, SEPARATOR, 1 );
211 if ( sep == std::string_view::npos || objPath.substr( 0, sep ) != m_rootName.value() ) {
212 return Status::INVALID_PARENT;
213 }
214 return registerAddress( m_root.get(), objPath.substr( sep ), pAddress );
215 }
216 if ( objPath.front() != SEPARATOR ) { return registerAddress( parentObj, char( SEPARATOR ) + objPath, pAddress ); }
217 RegEntry* par_entry = CAST_REGENTRY( RegEntry*, parentObj );
218 if ( !par_entry ) return Status::INVALID_PARENT;
219
220 auto sep = objPath.rfind( SEPARATOR );
221 if ( sep > 0 && sep != std::string_view::npos ) {
222 auto p_path = objPath.substr( 0, sep );
223 auto o_path = objPath.substr( sep );
224 RegEntry* p_entry = par_entry->findLeaf( p_path );
225 // Create default object leafs if the
226 // intermediate nodes are not present
227 if ( !p_entry && m_forceLeaves ) {
229 StatusCode sc = registerObject( par_entry->identifier(), p_path, pLeaf );
230 if ( sc.isFailure() ) delete pLeaf;
231 p_entry = par_entry->findLeaf( p_path );
232 }
233 if ( !p_entry ) return Status::INVALID_PARENT;
234 return registerAddress( p_entry, o_path, pAddress );
235 }
236 StatusCode status = par_entry->add( to_string( objPath ), pAddress );
237 return status.isSuccess() ? status : Status::DOUBL_OBJ_PATH;
238}
239
241StatusCode DataSvc::unregisterAddress( std::string_view fullPath ) {
242 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
243 return unregisterAddress( fullPath.front() != SEPARATOR ? m_root.get() : nullptr, fullPath );
244}
245
247StatusCode DataSvc::unregisterAddress( IRegistry* pParent, std::string_view objPath ) {
248 if ( !checkRoot() ) return Status::INVALID_ROOT;
249 if ( objPath.empty() ) return Status::INVALID_OBJ_PATH;
250
251 if ( !pParent ) {
252 if ( objPath.front() != SEPARATOR ) return unregisterAddress( m_root.get(), objPath );
253 auto sep = find( objPath, SEPARATOR, 1 );
254 if ( sep != std::string_view::npos && objPath.substr( 0, sep ) == m_rootName.value() ) {
255 return unregisterAddress( m_root.get(), objPath.substr( sep ) );
256 }
257 return Status::INVALID_PARENT;
258 }
259 if ( objPath.front() != SEPARATOR ) { return unregisterAddress( pParent, char( SEPARATOR ) + objPath ); }
260 RegEntry* node_entry = CAST_REGENTRY( RegEntry*, pParent );
261 if ( node_entry ) {
262 RegEntry* leaf_entry = node_entry->findLeaf( objPath );
263 if ( leaf_entry ) {
264 auto sep = objPath.rfind( SEPARATOR );
265 if ( sep > 0 && sep != std::string_view::npos ) {
266 return unregisterAddress( leaf_entry->parent(), objPath.substr( sep ) );
267 }
268 StatusCode status = node_entry->remove( objPath );
269 if ( status.isSuccess() ) return status;
270 }
271 }
272 return Status::INVALID_PARENT;
273}
274
276StatusCode DataSvc::registerObject( std::string_view parentPath, std::string_view objPath, DataObject* pObject ) {
277 DataObject* pO = nullptr;
278 StatusCode status = retrieveObject( parentPath, pO );
279 if ( !status.isSuccess() && m_forceLeaves ) {
280 pO = createDefaultObject();
281 status = registerObject( parentPath, pO );
282 if ( !status.isSuccess() ) pO->release();
283 }
284 return status.isSuccess() ? registerObject( pO, objPath, pObject ) : status;
285}
286
288StatusCode DataSvc::registerObject( DataObject* parentObj, std::string_view objPath, DataObject* pObject ) {
289 if ( !checkRoot() ) return Status::INVALID_ROOT;
290
291 if ( !parentObj ) {
292 if ( !objPath.empty() ) {
293 if ( objPath.front() != SEPARATOR ) { return registerObject( m_rootName.value(), objPath, pObject ); }
294 auto sep = find( objPath, SEPARATOR, 1 );
295 if ( sep != std::string_view::npos ) {
296 return registerObject( objPath.substr( 0, sep ), objPath.substr( sep ), pObject );
297 }
298 }
299 return Status::INVALID_OBJ_PATH;
300 }
301 RegEntry* node_entry = CAST_REGENTRY( RegEntry*, parentObj->registry() );
302 if ( node_entry ) {
303 StatusCode status = Status::INVALID_PARENT;
304 auto sep = find( objPath, SEPARATOR, 1 );
305 if ( sep != std::string_view::npos ) {
306 auto p_path = objPath.substr( 0, sep );
307 auto o_path = objPath.substr( sep );
308 RegEntry* par_entry = node_entry->findLeaf( p_path );
309 // Create default object leafs if the
310 // intermediate nodes are not present
311 if ( !par_entry && m_forceLeaves ) {
313 StatusCode sc = registerObject( parentObj, p_path, pLeaf );
314 if ( !sc.isSuccess() ) delete pLeaf;
315 par_entry = node_entry->findLeaf( p_path );
316 } else if ( par_entry && !par_entry->object() ) {
317 status = i_retrieveEntry( node_entry, p_path, par_entry );
318 if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
320 StatusCode sc = registerObject( parentObj, p_path, pLeaf );
321 if ( !sc.isSuccess() ) delete pLeaf;
322 par_entry = node_entry->findLeaf( p_path );
323 }
324 }
325 node_entry = par_entry;
326 if ( node_entry ) {
327 DataObject* obj = node_entry->object();
328 if ( obj ) status = registerObject( obj, o_path, pObject );
329 }
330 } else {
331 RegEntry* leaf = node_entry->findLeaf( objPath );
332 if ( !leaf ) {
333 status = node_entry->add( to_string( objPath ), pObject );
334 } else {
335 DataObject* obj = leaf->object();
336 if ( !obj ) {
337 if ( !pObject ) {
338 error() << "registerObject: trying to register null DataObject" << endmsg;
339 return StatusCode::FAILURE;
340 }
341 pObject->setRegistry( leaf );
342 leaf->setAddress( nullptr );
343 leaf->setObject( pObject );
344 status = StatusCode::SUCCESS;
345 } else {
346 status = Status::DOUBL_OBJ_PATH;
347 }
348 }
349 }
350 return status;
351 }
352 return Status::INVALID_PARENT;
353}
354
356StatusCode DataSvc::unregisterObject( std::string_view fullPath ) {
357 DataObject* pObject = nullptr;
358 StatusCode status = findObject( fullPath, pObject );
359 if ( status.isFailure() ) return status;
360 RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pObject->registry() );
361 if ( !pEntry ) return Status::INVALID_ROOT;
362 if ( !pEntry->isEmpty() ) return Status::DIR_NOT_EMPTY;
363 RegEntry* pParent = pEntry->parentEntry();
364 if ( !pParent ) return Status::INVALID_PARENT;
365 pObject->addRef();
366 pParent->remove( pEntry );
367 return StatusCode::SUCCESS;
368}
369
372 if ( !checkRoot() ) return Status::INVALID_ROOT;
373 RegEntry* entry = m_root->findLeaf( pObject );
374 if ( !entry ) return Status::INVALID_OBJECT;
375 RegEntry* parent = entry->parentEntry();
376 if ( !parent ) return Status::INVALID_PARENT;
377 if ( !entry->isEmpty() ) return Status::DIR_NOT_EMPTY;
378 if ( entry->object() ) entry->object()->addRef();
379 if ( parent ) parent->remove( entry );
380 return StatusCode::SUCCESS;
381}
382
384StatusCode DataSvc::unregisterObject( DataObject* pParentObj, std::string_view objectPath ) {
385 if ( checkRoot() ) {
386 try {
387 RegEntry* parent = CAST_REGENTRY( RegEntry*, pParentObj->registry() );
388 if ( parent ) {
389 RegEntry* entry = parent->findLeaf( objectPath );
390 if ( entry ) {
391 if ( entry->isEmpty() ) {
392 if ( entry->object() ) { entry->object()->addRef(); }
393 parent->remove( entry );
394 return StatusCode::SUCCESS;
395 }
396 return Status::DIR_NOT_EMPTY;
397 }
398 return Status::INVALID_OBJECT;
399 }
400 } catch ( ... ) {}
401 return Status::INVALID_PARENT;
402 }
403 return Status::INVALID_ROOT;
404}
405
408DataObject* DataSvc::handleDataFault( IRegistry* pReg, std::string_view path ) {
409 return i_handleDataFault( pReg, path );
410}
411
412DataObject* DataSvc::i_handleDataFault( IRegistry* pReg, std::string_view path ) {
413 if ( m_enableFaultHdlr ) {
414 IRegistry* pLeaf = nullptr;
415 if ( pReg && path.empty() ) {
416 DataIncident incident( name(), m_faultName, pReg->identifier() );
417 m_incidentSvc->fireIncident( incident );
418 return pReg->object();
419 }
420 if ( pReg ) {
421 std::string p = pReg->identifier();
422 if ( path.front() != SEPARATOR ) p += SEPARATOR;
423 p.append( path.data(), path.size() );
424 DataIncident incident( name(), m_faultName, p );
425 m_incidentSvc->fireIncident( incident );
426 pLeaf = m_root->findLeaf( p );
427 } else {
428 std::string p = m_root->identifier();
429 if ( path.front() != SEPARATOR ) p += SEPARATOR;
430 p.append( path.data(), path.size() );
431 DataIncident incident( name(), m_faultName, p );
432 m_incidentSvc->fireIncident( incident );
433 pLeaf = m_root->findLeaf( p );
434 }
435 if ( pLeaf ) { return pLeaf->object(); }
436 }
437 return nullptr;
438}
439
444 IConversionSvc* pLoader = getDataLoader( pRegistry );
445 return loadObject( pLoader, pRegistry );
446}
447
452 StatusCode status = Status::INVALID_OBJ_ADDR;
453 DataObject* pObject = nullptr;
454 if ( !pLoader ) { // Precondition: Data loader must be present
455 return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::NO_DATA_LOADER );
456 }
457 if ( !pRegistry ) { // Precondition: Directory must be valid
458 return handleDataFault( pRegistry ) ? StatusCode::SUCCESS : StatusCode( Status::INVALID_OBJ_ADDR );
459 }
460
461 VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
462
463 if ( m_enableAccessHdlr ) {
464 // Fire data access incident
465 DataIncident incident( name(), m_accessName, pRegistry->identifier() );
466 m_incidentSvc->fireIncident( incident );
467 }
468 if ( !m_inhibitPathes.empty() ) {
469 auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
470 if ( inhibit != m_inhibitPathes.end() ) { return Status::NO_ACCESS; }
471 }
472 IOpaqueAddress* pAddress = pRegistry->address();
473 if ( !pAddress ) { // Precondition:
474 return Status::INVALID_OBJ_ADDR; // Address must be valid
475 }
476 try {
477 status = pLoader->createObj( pAddress, pObject ); // Call data loader
478 if ( status.isSuccess() ) {
479
480 VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
481
482 RegEntry* pEntry = CAST_REGENTRY( RegEntry*, pRegistry );
483 pEntry->setObject( pObject );
484
485 VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
486 status = pLoader->fillObjRefs( pAddress, pObject );
487 }
488 } catch ( const GaudiException& exc ) {
489 if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
490 throw GaudiException( "GaudiException in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE,
491 exc );
492 } catch ( const std::exception& x ) {
493 if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
494 throw GaudiException( "std::exception in loadObject() " + pRegistry->identifier() + ": " +
495 System::typeinfoName( typeid( x ) ) + ", " + x.what(),
497 } catch ( ... ) {
498 if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
499 throw GaudiException( "UNKN exception in loadObject() " + pRegistry->identifier(), name(), StatusCode::FAILURE );
500 }
501 if ( !status.isSuccess() ) {
502 if ( handleDataFault( pRegistry ) ) { return StatusCode::SUCCESS; }
503 }
504 ON_VERBOSE if ( status.isSuccess() ) {
505 verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
506 }
507 return status;
508}
509
511StatusCode DataSvc::retrieveEntry( RegEntry* parentObj, std::string_view path, RegEntry*& pEntry ) {
512 return i_retrieveEntry( parentObj, path, pEntry );
513}
514
515StatusCode DataSvc::i_retrieveEntry( RegEntry* parentObj, std::string_view path, RegEntry*& pEntry ) {
516 // A.Valassi 16.08.2001 avoid core dump if store is empty
517 if ( !checkRoot() ) return Status::INVALID_ROOT;
518
519 static constexpr auto empty = std::string_view{};
520 auto sep = find( path, SEPARATOR, 1 );
521 pEntry = nullptr;
522
523 if ( !parentObj ) {
524 if ( path.empty() || path == m_rootName.value() ) {
525 parentObj = m_root.get();
526 path = empty;
527 } else if ( path.front() != SEPARATOR ) {
528 parentObj = m_root.get();
529 } else if ( sep != std::string_view::npos ) {
530 if ( !m_root->object() ) {
531 RegEntry* r = nullptr;
532 auto status = i_retrieveEntry( m_root.get(), empty, r );
533 if ( !status.isSuccess() ) return status;
534 }
535 parentObj = m_root.get();
536 path = path.substr( sep );
537 } else {
538 return Status::INVALID_OBJ_PATH;
539 }
540 sep = find( path, SEPARATOR, 1 );
541 }
542
543 StatusCode status{ Status::INVALID_ROOT };
544 if ( sep != std::string_view::npos ) { // the string contains a separator (after pos 0)
545 if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
546 status = loadObject( parentObj );
547 if ( !status.isSuccess() ) return status;
548 }
549 auto p_path = path.substr( 0, sep );
550 RegEntry* root_entry = parentObj->findLeaf( p_path );
551 if ( !root_entry && m_enableFaultHdlr ) {
552 // If not even the parent is there, an incident
553 // to load the parent must be fired...
554 i_handleDataFault( parentObj, p_path );
555 root_entry = parentObj->findLeaf( p_path );
556 }
557 if ( root_entry ) {
558 DataObject* pO = root_entry->object();
559 if ( !pO ) {
560 // Object is not loaded: load the object if at all possible
561 status = loadObject( root_entry );
562 if ( !status.isSuccess() ) return status;
563 }
564 if ( root_entry->isSoft() ) { root_entry = CAST_REGENTRY( RegEntry*, pO->registry() ); }
565 return i_retrieveEntry( root_entry, path.substr( sep ), pEntry );
566 }
567 return Status::INVALID_OBJ_PATH;
568 } else if ( path.empty() ) {
569 pEntry = parentObj;
570 } else {
571 if ( !parentObj->object() ) { // if the parent object has not been loaded yet, load it now
572 status = loadObject( parentObj );
573 if ( !status.isSuccess() ) return status;
574 }
575 // last leave in search: find leaf and load
576 pEntry = parentObj->findLeaf( path );
577 // If no registry entry was found, trigger incident for action-on-demand
578 if ( !pEntry && m_enableFaultHdlr ) {
579 i_handleDataFault( parentObj, path );
580 pEntry = ( path.empty() ? parentObj : parentObj->findLeaf( path ) );
581 }
582 }
583
584 // Check results and return
585 if ( !pEntry ) return Status::INVALID_OBJ_PATH;
586 if ( !pEntry->object() ) return loadObject( pEntry );
587
588 if ( m_enableAccessHdlr ) {
589 // Fire data access incident
590 // I do not know if this is a good idea....
591 // This fires too often!
592 //
593 // DataIncident incident(name(), m_accessName, pEntry->identifier());
594 // m_incidentSvc->fireIncident(incident);
595 return StatusCode::SUCCESS;
596 }
597 return StatusCode::SUCCESS;
598}
599
601StatusCode DataSvc::retrieveObject( IRegistry* pRegistry, std::string_view path, DataObject*& pObject ) {
602 pObject = nullptr;
603 RegEntry * result = nullptr, *parent = CAST_REGENTRY( RegEntry*, pRegistry );
604 StatusCode status = i_retrieveEntry( parent, path, result );
605 if ( status.isSuccess() ) pObject = result->object();
606 return status;
607}
608
610StatusCode DataSvc::findObject( IRegistry* pRegistry, std::string_view path, DataObject*& pObject ) {
611 pObject = nullptr;
612 IRegistry* pReg = ( pRegistry ? pRegistry : m_root.get() );
613 RegEntry* root_entry = CAST_REGENTRY( RegEntry*, pReg );
614 if ( root_entry ) {
615 if ( !path.empty() ) pReg = root_entry->find( path );
616 if ( !pReg ) return Status::INVALID_OBJ_PATH;
617 pObject = pReg->object();
618 }
619 return ( !pObject ) ? Status::OBJ_NOT_LOADED : Status::IDataProviderSvc_NO_ERROR;
620}
621
623StatusCode DataSvc::findObject( std::string_view path, DataObject*& pObject ) {
624 pObject = nullptr;
625 if ( !checkRoot() ) return Status::INVALID_ROOT;
626 if ( path.empty() || path == m_rootName.value() ) {
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 ) { // Precondition:
636 return Status::INVALID_OBJ_ADDR; // Addres must be valid
637 }
638 DataObject* toUpdate = pRegistry->object();
639 if ( !toUpdate ) { // Try first to load
640 return loadObject( pRegistry );
641 }
642 return updateObject( toUpdate );
643}
644
647 StatusCode status = Status::INVALID_OBJ_ADDR;
648 if ( !toUpdate ) { // Precondition:
649 return Status::INVALID_OBJECT; // Address must be valid
650 }
651 IRegistry* pRegistry = toUpdate->registry(); // Precondition:
652 if ( !pRegistry ) { // Need valid registry
653 return Status::INVALID_OBJECT;
654 }
655 IOpaqueAddress* pAddress = pRegistry->address(); // Precondition:
656 if ( !pAddress ) { // Need valid address
657 return Status::INVALID_OBJ_ADDR;
658 }
659 IConversionSvc* pLoader = getDataLoader( pRegistry );
660 if ( !pLoader ) { // Precondition:
661 return Status::NO_DATA_LOADER; // Data loader must be present
662 }
663 if ( !m_inhibitPathes.empty() ) {
664 auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(), pRegistry->identifier() );
665 if ( inhibit != m_inhibitPathes.end() ) { return Status::NO_ACCESS; }
666 }
667 try {
668 status = pLoader->updateObj( pAddress, toUpdate ); // Call data loader
669 if ( status.isSuccess() ) { status = pLoader->updateObjRefs( pAddress, toUpdate ); }
670 } catch ( const GaudiException& exc ) {
671 throw GaudiException( "GaudiException in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE, exc );
672 } catch ( const std::exception& x ) {
673 throw GaudiException( "std::exception in updateObject() " + pRegistry->name() + ": " +
674 System::typeinfoName( typeid( x ) ) + ", " + x.what(),
676 } catch ( ... ) {
677 throw GaudiException( "UNKN exception in updateObject() " + pRegistry->name(), name(), StatusCode::FAILURE );
678 }
679 return status;
680}
681
682// Link object
683StatusCode DataSvc::linkObject( IRegistry* from, std::string_view objPath, DataObject* to ) {
684 if ( !checkRoot() ) return Status::INVALID_ROOT;
685 try {
686 RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
687 if ( from_entry ) {
688 // First check if both objects are already registered to the store
689 RegEntry* to_entry = m_root->findLeaf( to );
690 if ( !to_entry ) return Status::INVALID_OBJECT;
691 auto sep = objPath.rfind( SEPARATOR );
692 if ( sep > 0 && sep != std::string_view::npos ) { // in case the objPath is a sub-directory itself
693 DataObject* pO = nullptr;
694 StatusCode sc = retrieveObject( from, objPath.substr( 0, sep ), pO );
695 return sc.isSuccess() ? linkObject( pO->registry(), objPath.substr( sep ), to ) : sc;
696 }
697 // Now register the soft link
698 StatusCode status = from_entry->add( to_string( objPath ), to, true );
699 return status.isSuccess() ? Status::IDataProviderSvc_NO_ERROR : Status::DOUBL_OBJ_PATH;
700 }
701 } catch ( ... ) {}
702 return Status::INVALID_PARENT;
703}
704
706StatusCode DataSvc::linkObject( std::string_view fullPath, DataObject* to ) {
707 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
708 if ( fullPath.front() != SEPARATOR ) { return linkObject( m_rootName.value(), fullPath, to ); }
709 auto sep = fullPath.rfind( SEPARATOR );
710 return linkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ), to );
711}
712
714StatusCode DataSvc::unlinkObject( IRegistry* from, std::string_view objPath ) {
715 if ( !checkRoot() ) return Status::INVALID_ROOT;
716 try {
717 RegEntry* from_entry = CAST_REGENTRY( RegEntry*, from );
718 if ( from_entry ) {
719 auto sep = objPath.rfind( SEPARATOR );
720 if ( sep > 0 && sep != std::string_view::npos ) { // in case the objPath is a sub-directory itself
721 DataObject* pO = nullptr;
722 StatusCode sc = findObject( from, objPath.substr( 0, sep ), pO );
723 return sc.isSuccess() ? unlinkObject( pO->registry(), objPath.substr( sep ) ) : sc;
724 }
725 StatusCode status = from_entry->remove( objPath );
726 if ( status.isSuccess() ) return status;
727 return Status::INVALID_OBJ_PATH;
728 }
729 } catch ( ... ) {}
730 return Status::INVALID_PARENT;
731}
732
734StatusCode DataSvc::unlinkObject( std::string_view fullPath ) {
735 if ( fullPath.empty() ) return Status::INVALID_OBJ_PATH;
736 if ( fullPath.front() != SEPARATOR ) return unlinkObject( m_rootName.value(), fullPath );
737 auto sep = fullPath.rfind( SEPARATOR );
738 return unlinkObject( fullPath.substr( 0, sep ), fullPath.substr( sep ) );
739}
740
742StatusCode DataSvc::unlinkObject( DataObject* from, std::string_view objPath ) {
743 if ( !checkRoot() ) return Status::INVALID_ROOT;
744 IRegistry* from_entry = m_root->findLeaf( from );
745 return unlinkObject( from_entry, objPath );
746}
747
750 auto i = std::find( begin( m_preLoads ), end( m_preLoads ), item );
751 if ( i == end( m_preLoads ) ) m_preLoads.push_back( item );
752 return StatusCode::SUCCESS;
753}
754
757 m_preLoads.erase( std::remove( begin( m_preLoads ), end( m_preLoads ), item ), end( m_preLoads ) );
758 return StatusCode::SUCCESS;
759}
760
763 m_preLoads.erase( begin( m_preLoads ), end( m_preLoads ) );
764 return StatusCode::SUCCESS;
765}
766
768StatusCode DataSvc::preLoad( int depth, int load_depth, DataObject* pObject ) {
769 // unused: StatusCode sc = StatusCode::FAILURE;
770 if ( pObject && depth++ < load_depth ) {
771 RegEntry* dir = CAST_REGENTRY( RegEntry*, pObject->registry() );
772 if ( dir ) {
773 for ( const auto& i : *dir ) {
774 DataObject* pObj = nullptr;
775 StatusCode status = retrieveObject( pObject, i->name(), pObj );
776 if ( status.isSuccess() && depth < load_depth ) { preLoad( depth, load_depth, pObj ).ignore(); }
777 }
778 }
779 }
780 return StatusCode::SUCCESS;
781}
782
785 DataObject* pObj = nullptr;
786 for ( const auto& i : m_preLoads ) {
787 StatusCode sc = retrieveObject( i.path(), pObj );
788 int load_depth = i.depth();
789 if ( sc.isSuccess() && load_depth > 1 ) { preLoad( 1, load_depth, pObj ).ignore(); }
790 }
791 return StatusCode::SUCCESS;
792}
793
796 // Nothing to do: just call base class initialisation
798 if ( !sc.isSuccess() ) return sc;
799 m_incidentSvc = service( "IncidentSvc", true );
800 if ( !m_incidentSvc ) { error() << "Failed to access incident service." << endmsg; }
801 return sc;
802}
803
806 // the finalize part is copied here
807 setDataLoader( nullptr ).ignore();
809 clearStore().ignore();
810 m_incidentSvc.reset();
811 // re-initialize the base class
813 if ( !sc.isSuccess() ) {
814 error() << "Unable to reinitialize base class" << endmsg;
815 return sc;
816 }
817 // the initialize part is copied here
818 m_incidentSvc = service( "IncidentSvc", true );
819 if ( !m_incidentSvc ) {
820 error() << "Failed to access incident service." << endmsg;
821 return StatusCode::FAILURE;
822 }
823
824 return StatusCode::SUCCESS;
825}
826
829 // Nothing to do: just call base class initialisation
830 setDataLoader( nullptr ).ignore();
832 clearStore().ignore();
833 m_incidentSvc.reset();
834 return Service::finalize();
835}
836
839
841const std::string& DataSvc::rootName() const { return m_rootName; }
842
845
#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
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.
StatusCode reinitialize() override
Service initialization.
Definition DataSvc.cpp:805
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, std::string_view path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
Definition DataSvc.cpp:511
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:93
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:115
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
Definition DataSvc.cpp:844
StatusCode finalize() override
Service initialization.
Definition DataSvc.cpp:828
Gaudi::Property< std::string > m_rootName
Definition DataSvc.h:53
StatusCode findObject(std::string_view fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition DataSvc.cpp:623
StatusCode resetPreLoad() override
Clear the preload list.
Definition DataSvc.cpp:762
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:59
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:125
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
Definition DataSvc.cpp:849
SmartIF< IConversionSvc > m_dataLoader
Pointer to data loader service.
Definition DataSvc.h:46
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:160
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:181
StatusCode initialize() override
Service initialization.
Definition DataSvc.cpp:795
StatusCode unregisterAddress(std::string_view fullPath) override
IDataManagerSvc: Unregister object address from the data store.
Definition DataSvc.cpp:241
SmartIF< IIncidentSvc > m_incidentSvc
Pointer to incident service.
Definition DataSvc.h:50
StatusCode unregisterObject(std::string_view fullPath) override
Unregister object from the data store.
Definition DataSvc.cpp:356
StatusCode registerObject(std::string_view parentPath, std::string_view objPath, DataObject *pObject) override
Register object with the data store.
Definition DataSvc.cpp:276
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
Definition DataSvc.cpp:749
DataObject * handleDataFault(IRegistry *pReg, std::string_view path="")
Invoke data fault handling if enabled.
Definition DataSvc.cpp:408
DataObject * i_handleDataFault(IRegistry *pReg, std::string_view path=std::string_view{})
Definition DataSvc.cpp:412
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition DataSvc.h:58
Gaudi::Property< bool > m_enableAccessHdlr
Definition DataSvc.h:64
Gaudi::Property< CLID > m_rootCLID
Definition DataSvc.h:52
Gaudi::Property< std::string > m_accessName
Definition DataSvc.h:66
StatusCode preLoad() override
load all preload items of the list
Definition DataSvc.cpp:784
StatusCode retrieveObject(IRegistry *pDirectory, std::string_view path, DataObject *&pObject) override
Retrieve object from data store.
Definition DataSvc.cpp:601
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
Definition DataSvc.cpp:841
StatusCode registerAddress(std::string_view fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition DataSvc.cpp:198
StatusCode traverseTree(IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects in the data store.
Definition DataSvc.cpp:106
bool checkRoot()
Check if root path is valid.
Definition DataSvc.h:255
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Definition DataSvc.cpp:838
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object's parent.
Definition DataSvc.cpp:167
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
Definition DataSvc.cpp:634
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Definition DataSvc.cpp:756
Gaudi::Property< bool > m_forceLeaves
Definition DataSvc.h:56
Gaudi::Property< bool > m_enableFaultHdlr
Definition DataSvc.h:60
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition DataSvc.cpp:85
StatusCode i_retrieveEntry(DataSvcHelpers::RegistryEntry *parentObj, std::string_view path, DataSvcHelpers::RegistryEntry *&pEntry)
Definition DataSvc.cpp:515
Gaudi::Property< std::string > m_faultName
Definition DataSvc.h:62
virtual StatusCode loadObject(IRegistry *pNode)
Invoke Persistency service to create transient object from its persistent representation.
Definition DataSvc.cpp:443
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition DataSvc.h:69
StatusCode unlinkObject(IRegistry *from, std::string_view objPath) override
Remove a link to another object.
Definition DataSvc.cpp:714
StatusCode linkObject(IRegistry *from, std::string_view objPath, DataObject *to) override
Add a link to another object.
Definition DataSvc.cpp:683
std::unique_ptr< DataSvcHelpers::RegistryEntry > m_root
Pointer to root entry.
Definition DataSvc.h:73
Define general base for Gaudi exception.
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
virtual StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *refpObject)=0
Update the transient object from the other representation.
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
virtual StatusCode updateObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Update the references of an updated transient object.
Data provider interface definition.
Generic data agent interface.
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.
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
SmartIF< IFace > service(const std::string &name, bool createIf=true) const
Definition Service.h:79
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
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:260