| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DataSvc.cpp
Go to the documentation of this file.
1 //====================================================================
2 // DataSvc.cpp
3 //--------------------------------------------------------------------
4 //
5 // Package : System ( The LHCb Offline System)
6 //
7 // Description: implementation of the Transient data service: DataSvc
8 //
9 // Author : M.Frank
10 // History :
11 // +---------+----------------------------------------------+---------
12 // | Date | Comment | Who
13 // +---------+----------------------------------------------+---------
14 // | 29/10/98| Initial version | M.Frank
15 // | 20/2/99 | Automatic data preloading introduced. | M.Frank
16 // +---------+----------------------------------------------+---------
17 //
18 //====================================================================
19 #define DATASVC_DATASVC_CPP
20
21 // Framework include files
22 #include "GaudiKernel/IConverter.h"
23 #include "GaudiKernel/IOpaqueAddress.h"
24 #include "GaudiKernel/IConversionSvc.h"
25
26 #include "GaudiKernel/xtoa.h"
27 #include "GaudiKernel/DataObject.h"
28 #include "GaudiKernel/GaudiException.h"
29
30 #include "GaudiKernel/RegistryEntry.h"
31 #include "GaudiKernel/DataSvc.h"
32 #include "GaudiKernel/DataIncident.h"
33 #include "GaudiKernel/IIncidentSvc.h"
34
35 // Include files
36 #include <cassert>
37 #include <cstdlib>
38 #include <vector>
39 #include <algorithm>
40 #include <sstream>
41
42 namespace {
45 inline std::string itemToPath(int item) {
46 std::ostringstream path;
47 path << '/' << item;
48 return path.str();
49 }
50 }
51
52 // If you absolutely need optimization: switch off dynamic_cast.
53 // This improves access to the data store roughly by 10 %
54 // for balanced trees.
55 //
56 // M.Frank
57 #define CAST_REGENTRY(x,y) dynamic_cast<x>(y)
58 //#define CAST_REGENTRY(x,y) (x)(y)
59 typedef DataSvcHelpers::RegistryEntry RegEntry;
60
61 #define ON_DEBUG if (UNLIKELY(outputLevel() <= MSG::DEBUG))
62 #define ON_VERBOSE if (UNLIKELY(outputLevel() <= MSG::VERBOSE))
63
64 #define DEBMSG ON_DEBUG debug()
65 #define VERMSG ON_VERBOSE verbose()
66
70 StatusCode DataSvc::clearSubTree(const std::string& sub_tree_path) {
71 DataObject* pObject = 0;
72 StatusCode status = findObject(sub_tree_path, pObject);
73 if ( status.isSuccess() ) {
74 RegEntry* node_entry = CAST_REGENTRY(RegEntry*,pObject->registry());
75 if ( 0 != node_entry ) {
76 RegEntry* parent = node_entry->parentEntry();
77 if ( 0 != parent ) {
78 parent->remove(node_entry);
79 return StatusCode::SUCCESS;
80 }
81 return INVALID_PARENT;
82 }
83 return INVALID_OBJECT;
84 }
85 return status;
86 }
87
91 StatusCode DataSvc::clearSubTree(DataObject* pObject) {
92 if ( checkRoot() ) {
93 RegEntry* entry = CAST_REGENTRY(RegEntry*,pObject->registry());
94 if ( 0 != entry ) {
95 RegEntry* parent = entry->parentEntry();
96 if ( 0 != parent ) {
97 parent->remove(entry);
98 return SUCCESS;
99 }
100 return INVALID_PARENT;
101 }
102 return INVALID_OBJECT;
103 }
104 return INVALID_ROOT;
105 }
106
108 StatusCode DataSvc::clearStore() {
109 if ( checkRoot() ) {
110 m_root->release();
111 m_root = 0;
112 return SUCCESS;
113 }
114 return INVALID_ROOT;
115 }
116
120 StatusCode DataSvc::traverseSubTree (const std::string& sub_tree_path,
121 IDataStoreAgent* pAgent) {
122 DataObject* pO = 0;
123 StatusCode status = findObject(sub_tree_path, pO);
124 if ( status.isSuccess() ) {
125 status = traverseSubTree(pO, pAgent);
126 }
127 return status;
128 }
129
131 StatusCode DataSvc::traverseSubTree ( DataObject* pObject,
132 IDataStoreAgent* pAgent ) {
133 if ( checkRoot() ) {
134 RegEntry* entry = CAST_REGENTRY(RegEntry*,pObject->registry());
135 if ( 0 != entry ) {
136 return entry->traverseTree(pAgent);
137 }
138 return INVALID_OBJECT;
139 }
140 return INVALID_ROOT;
141 }
142
144 StatusCode DataSvc::traverseTree(IDataStoreAgent* pAgent) {
145 if ( checkRoot() ) {
146 return m_root->traverseTree(pAgent);
147 }
148 return INVALID_ROOT;
149 }
150
155 StatusCode DataSvc::setRoot(const std::string& root_path,
156 DataObject* pRootObj) {
157 clearStore().ignore();
158 return i_setRoot (root_path, pRootObj);
159 }
160
166 StatusCode DataSvc::i_setRoot(const std::string& root_path,
167 DataObject* pRootObj) {
168 if ( 0 != pRootObj ) {
169 m_root = new RegEntry(root_path);
170 m_root->makeHard(pRootObj);
171 m_root->setDataSvc(this);
172 preLoad().ignore();
173 }
174 return SUCCESS;
175 }
176
181 StatusCode DataSvc::setRoot(const std::string& root_path,
182 IOpaqueAddress* pRootAddr) {
183 clearStore().ignore();
184 return i_setRoot (root_path, pRootAddr);
185 }
186
192 StatusCode DataSvc::i_setRoot(const std::string& root_path,
193 IOpaqueAddress* pRootAddr) {
194 if ( 0 != pRootAddr ) {
195 m_root = new RegEntry(root_path);
196 m_root->makeHard(pRootAddr);
197 m_root->setDataSvc(this);
198 preLoad().ignore();
199 }
200 return SUCCESS;
201 }
202
204 StatusCode DataSvc::setDataLoader(IConversionSvc* pDataLoader) {
205 if ( 0 != pDataLoader ) pDataLoader->addRef();
206 if ( 0 != m_dataLoader ) m_dataLoader->release();
207 if ( 0 != pDataLoader ) {
208 pDataLoader->setDataProvider(this).ignore();
209 }
210 m_dataLoader = pDataLoader;
211 return SUCCESS;
212 }
213
215 StatusCode DataSvc::objectParent(const DataObject* pObject,
216 IRegistry*& refpParent) {
217 if ( pObject ) {
218 return objectParent(pObject->registry(), refpParent);
219 }
220 return INVALID_OBJECT;
221 }
223 StatusCode DataSvc::objectParent(const IRegistry* pRegistry,
224 IRegistry*& refpParent) {
225 if ( checkRoot() ) {
226 const RegEntry* node_entry = CAST_REGENTRY(const RegEntry*,pRegistry);
227 if ( node_entry ) {
228 refpParent = node_entry->parent();
229 return StatusCode::SUCCESS;
230 }
231 return INVALID_OBJECT;
232 }
233 return INVALID_ROOT;
234 }
235
237 StatusCode DataSvc::objectLeaves( const DataObject* pObject,
238 std::vector<IRegistry*>& leaves) {
239 if ( pObject ) {
240 return objectLeaves(pObject->registry(), leaves);
241 }
242 return INVALID_OBJECT;
243 }
244
248 StatusCode DataSvc::objectLeaves( const IRegistry* pRegistry,
249 std::vector<IRegistry*>& leaves) {
250 if ( checkRoot() ) {
251 const RegEntry* node_entry = CAST_REGENTRY(const RegEntry*,pRegistry);
252 if ( node_entry ) {
253 leaves = node_entry->leaves();
254 return StatusCode::SUCCESS;
255 }
256 return INVALID_OBJECT;
257 }
258 return INVALID_ROOT;
259 }
260
262 StatusCode DataSvc::registerAddress(const std::string& fullPath,
263 IOpaqueAddress* pAddress) {
264 if ( fullPath.length() > 0 ) {
265 if ( fullPath[0] != SEPARATOR ) {
266 return registerAddress(m_root, fullPath, pAddress);
267 }
268 IRegistry* pRegistry = 0;
269 return registerAddress(pRegistry, fullPath, pAddress);
270 }
271 return INVALID_OBJ_PATH;
272 }
273
275 StatusCode DataSvc::registerAddress(DataObject* parentObj,
276 const std::string& objectPath,
277 IOpaqueAddress* pAddress) {
278 IRegistry* pRegistry = (0 == parentObj) ? 0 : parentObj->registry();
279 return registerAddress(pRegistry, objectPath, pAddress);
280 }
281
283 StatusCode DataSvc::registerAddress(IRegistry* parentObj,
284 const std::string& objPath,
285 IOpaqueAddress* pAddress) {
286 if ( checkRoot() ) {
287 if ( objPath.length() > 0 ) {
288 if ( 0 == parentObj ) {
289 if ( objPath[0] != SEPARATOR ) {
290 return registerAddress(m_root, objPath, pAddress);
291 }
292 std::string::size_type sep = objPath.find(SEPARATOR,1);
293 if ( sep != std::string::npos ) {
294 std::string p_path (objPath, 0, sep);
295 if ( p_path == m_rootName ) {
296 std::string o_path (objPath, sep, objPath.length());
297 return registerAddress(m_root, o_path, pAddress);
298 }
299 }
300 return INVALID_PARENT;
301 }
302 if ( objPath[0] != SEPARATOR ) {
303 std::string path;
304 path = SEPARATOR;
305 path += objPath;
306 return registerAddress(parentObj, path, pAddress);
307 }
308 RegEntry* par_entry = CAST_REGENTRY(RegEntry*,parentObj);
309 if ( 0 != par_entry ) {
310 std::string::size_type sep = objPath.rfind(SEPARATOR);
311 if ( sep > 0 && sep != std::string::npos ) {
312 std::string p_path (objPath, 0, sep);
313 std::string o_path (objPath, sep, objPath.length());
314 RegEntry* p_entry = par_entry->findLeaf(p_path);
315 // Create default object leafs if the
316 // intermediate nodes are not present
317 if ( 0 == p_entry && m_forceLeaves ) {
318 DataObject *pLeaf = createDefaultObject();
319 StatusCode sc = registerObject(par_entry->identifier(),
320 p_path,
321 pLeaf);
322 if ( ! sc.isSuccess() ) {
323 delete pLeaf;
324 }
325 p_entry = par_entry->findLeaf(p_path);
326 }
327 if ( 0 != p_entry ) {
328 return registerAddress(p_entry, o_path, pAddress);
329 }
330 return INVALID_PARENT;
331 }
332 StatusCode status = par_entry->add(objPath, pAddress);
333 if ( status.isSuccess() ) {
334 return status;
335 }
336 return DOUBL_OBJ_PATH;
337 }
338 return INVALID_PARENT;
339 }
340 return INVALID_OBJ_PATH;
341 }
342 return INVALID_ROOT;
343 }
344
346 StatusCode DataSvc::unregisterAddress(const std::string& fullPath) {
347 if ( fullPath.length() > 0 ) {
348 IRegistry* pRegistry = 0;
349 if ( fullPath[0] != SEPARATOR ) {
350 return unregisterAddress(m_root, fullPath);
351 }
352 return unregisterAddress(pRegistry, fullPath);
353 }
354 return INVALID_OBJ_PATH;
355 }
356
358 StatusCode DataSvc::unregisterAddress(DataObject* pParent,
359 const std::string& objPath) {
360 IRegistry* pRegistry = (0 == pParent) ? 0 : pParent->registry();
361 return unregisterAddress(pRegistry, objPath);
362 }
363
365 StatusCode DataSvc::unregisterAddress(IRegistry* pParent,
366 const std::string& objPath) {
367 if ( checkRoot() ) {
368 if ( objPath.length() > 0 ) {
369 if ( 0 == pParent ) {
370 if ( objPath[0] != SEPARATOR ) {
371 return unregisterAddress(m_root, objPath);
372 }
373 std::string::size_type sep = objPath.find(SEPARATOR,1);
374 if ( sep != std::string::npos ) {
375 std::string p_path (objPath, 0, sep);
376 if ( p_path == m_rootName ) {
377 std::string o_path (objPath, sep, objPath.length());
378 return unregisterAddress(m_root, o_path);
379 }
380 }
381 return INVALID_PARENT;
382 }
383 if ( objPath[0] != SEPARATOR ) {
384 std::string path;
385 path = SEPARATOR;
386 path += objPath;
387 return unregisterAddress(pParent, path);
388 }
389 RegEntry* node_entry = CAST_REGENTRY(RegEntry*,pParent);
390 if ( 0 != node_entry ) {
391 RegEntry* leaf_entry = node_entry->findLeaf(objPath);
392 if ( 0 != leaf_entry ) {
393 std::string::size_type sep = objPath.rfind(SEPARATOR);
394 if ( sep > 0 && sep != std::string::npos ) {
395 std::string path = objPath.substr(sep);
396 return unregisterAddress(leaf_entry->parent(), path);
397 }
398 StatusCode status = node_entry->remove(objPath);
399 if ( status.isSuccess() ) {
400 return status;
401 }
402 }
403 }
404 return INVALID_PARENT;
405 }
406 return INVALID_OBJ_PATH;
407 }
408 return INVALID_ROOT;
409 }
410
412 StatusCode DataSvc::registerObject (const std::string& fullPath,
413 DataObject* pObject) {
414 return registerObject(0, fullPath, pObject);
415 }
416
417
419 StatusCode DataSvc::registerObject (const std::string& parentPath,
420 const std::string& objPath,
421 DataObject* pObject) {
422 DataObject* pO = 0;
423 StatusCode status = retrieveObject(parentPath, pO);
424 if ( !status.isSuccess() && m_forceLeaves ) {
425 pO = createDefaultObject();
426 status = registerObject(parentPath, pO);
427 if ( !status.isSuccess() ) {
428 pO->release();
429 }
430 }
431 if ( status.isSuccess() ) {
432 status = registerObject(pO, objPath, pObject);
433 }
434 return status;
435 }
436
438 StatusCode DataSvc::registerObject(const std::string& parentPath,
439 int item,
440 DataObject* pObject) {
441 return registerObject(parentPath, itemToPath(item), pObject);
442 }
443
445 StatusCode DataSvc::registerObject(DataObject* parentObj,
446 int item,
447 DataObject* pObject) {
448 return registerObject(parentObj, itemToPath(item), pObject);
449 }
450
452 StatusCode DataSvc::registerObject(DataObject* parentObj,
453 const std::string& objPath,
454 DataObject* pObject) {
455 if ( checkRoot() ) {
456 if ( 0 == parentObj ) {
457 if ( objPath.length() > 0 ) {
458 if ( objPath[0] == SEPARATOR ) {
459 std::string::size_type sep = objPath.find(SEPARATOR,1);
460 if ( sep != std::string::npos ) {
461 std::string p_path (objPath, 0, sep);
462 std::string o_path (objPath, sep, objPath.length());
463 return registerObject(p_path, o_path, pObject);
464 }
465 }
466 else {
467 return registerObject(m_rootName, objPath, pObject);
468 }
469 }
470 return INVALID_OBJ_PATH;
471 }
472 RegEntry* node_entry = CAST_REGENTRY(RegEntry*,parentObj->registry());
473 if ( 0 != node_entry ) {
474 StatusCode status = INVALID_PARENT;
475 std::string::size_type sep = objPath.find(SEPARATOR,1);
476 if ( sep != std::string::npos ) {
477 std::string p_path (objPath, 0, sep);
478 std::string o_path (objPath, sep, objPath.length());
479 RegEntry* par_entry = node_entry->findLeaf(p_path);
480 // Create default object leafs if the
481 // intermediate nodes are not present
482 if ( 0 == par_entry && m_forceLeaves ) {
483 DataObject *pLeaf = createDefaultObject();
484 StatusCode sc = registerObject(parentObj, p_path, pLeaf);
485 if ( ! sc.isSuccess() ) {
486 delete pLeaf;
487 }
488 par_entry = node_entry->findLeaf(p_path);
489 }
490 else if ( 0 != par_entry && par_entry->object() == 0 ) {
491 status = retrieveEntry( node_entry, p_path, par_entry);
492 if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
493 DataObject *pLeaf = createDefaultObject();
494 StatusCode sc = registerObject(parentObj, p_path, pLeaf);
495 if ( ! sc.isSuccess() ) {
496 delete pLeaf;
497 }
498 par_entry = node_entry->findLeaf(p_path);
499 }
500 }
501 node_entry = par_entry;
502 if ( 0 != node_entry ) {
503 DataObject* obj = node_entry->object();
504 if ( 0 != obj ) {
505 status = registerObject( obj, o_path, pObject );
506 }
507 }
508 }
509 else {
510 RegEntry* leaf = node_entry->findLeaf(objPath);
511 if ( 0 == leaf ) {
512 status = node_entry->add( objPath, pObject );
513 }
514 else {
515 DataObject* obj = leaf->object();
516 if ( 0 == obj ) {
517 if (0 == pObject) {
518 error() << "registerObject: trying to register null DataObject" << endmsg;
519 return StatusCode::FAILURE;
520 }
521 else {
522 pObject->setRegistry(leaf);
523 }
524 leaf->setAddress(0);
525 leaf->setObject(pObject);
526 status = StatusCode::SUCCESS;
527 }
528 else {
529 status = DOUBL_OBJ_PATH;
530 }
531 }
532 }
533 return status;
534 }
535 return INVALID_PARENT;
536 }
537 return INVALID_ROOT;
538 }
539
541 StatusCode DataSvc::unregisterObject(const std::string& fullPath) {
542 DataObject* pObject = 0;
543 StatusCode status = findObject(fullPath, pObject);
544 if ( status.isSuccess() ) {
545 RegEntry* pEntry = CAST_REGENTRY(RegEntry*,pObject->registry());
546 if ( 0 != pEntry ) {
547 if ( pEntry->isEmpty() ) {
548 RegEntry* pParent = pEntry->parentEntry();
549 if ( 0 != pParent ) {
550 if ( 0 != pObject ) {
551 pObject->addRef();
552 }
553 pParent->remove(pEntry);
554 return StatusCode::SUCCESS;
555 }
556 return INVALID_PARENT;
557 }
558 return DIR_NOT_EMPTY;
559 }
560 return INVALID_ROOT;
561 }
562 return status;
563 }
564
566 StatusCode DataSvc::unregisterObject(const std::string& parentPath,
567 const std::string& objPath) {
568 DataObject* pO = 0;
569 StatusCode status = findObject(parentPath, pO);
570 if ( status.isSuccess() ) {
571 status = unregisterObject(pO, objPath);
572 }
573 return status;
574 }
575
577 StatusCode DataSvc::unregisterObject(const std::string& parentPath, int item) {
578 return unregisterObject(parentPath, itemToPath(item));
579 }
580
582 StatusCode DataSvc::unregisterObject(DataObject* pObject) {
583 if ( checkRoot() ) {
584 RegEntry* entry = m_root->findLeaf(pObject);
585 if ( 0 != entry ) {
586 RegEntry* parent = entry->parentEntry();
587 if ( 0 != parent ) {
588 if ( entry->isEmpty() ) {
589 if ( 0 != entry->object() ) {
590 entry->object()->addRef();
591 }
592 if ( 0 != parent ) {
593 parent->remove(entry);
594 }
595 return SUCCESS;
596 }
597 return INVALID_PARENT;
598 }
599 return DIR_NOT_EMPTY;
600 }
601 return INVALID_OBJECT;
602 }
603 return INVALID_ROOT;
604 }
605
607 StatusCode DataSvc::unregisterObject (DataObject* pParentObj,
608 const std::string& objectPath) {
609 if ( checkRoot() ) {
610 try {
611 RegEntry* parent = CAST_REGENTRY(RegEntry*,pParentObj->registry());
612 if ( 0 != parent ) {
613 RegEntry* entry = parent->findLeaf(objectPath);
614 if ( 0 != entry ) {
615 if ( entry->isEmpty() ) {
616 if ( 0 != entry->object() ) {
617 entry->object()->addRef();
618 }
619 parent->remove(entry);
620 return SUCCESS;
621 }
622 return DIR_NOT_EMPTY;
623 }
624 return INVALID_OBJECT;
625 }
626 }
627 catch(...) {
628 }
629 return INVALID_PARENT;
630 }
631 return INVALID_ROOT;
632 }
633
635 StatusCode DataSvc::unregisterObject(DataObject* pParentObj, int item) {
636 return unregisterObject(pParentObj, itemToPath(item));
637 }
638
641 DataObject* DataSvc::handleDataFault(IRegistry* pReg, const std::string& path)
642 {
643 if ( m_enableFaultHdlr ) {
644 IRegistry* pLeaf = 0;
645 if ( pReg && path.length() == 0 ) {
646 DataIncident incident(name(), m_faultName, pReg->identifier());
647 m_incidentSvc->fireIncident(incident);
648 return pReg->object();
649 }
650 else if ( pReg ) {
651 std::string p = pReg->identifier();
652 if (path[0] != SEPARATOR ) p += SEPARATOR;
653 p += path;
654 DataIncident incident(name(), m_faultName, p);
655 m_incidentSvc->fireIncident(incident);
656 pLeaf = m_root->findLeaf(p);
657 }
658 else {
659 std::string p = m_root->identifier();
660 if (path[0] != SEPARATOR ) p += SEPARATOR;
661 p += path;
662 DataIncident incident(name(), m_faultName, p);
663 m_incidentSvc->fireIncident(incident);
664 pLeaf = m_root->findLeaf(p);
665 }
666 if ( pLeaf ) {
667 return pLeaf->object();
668 }
669 }
670 return 0;
671 }
672
676 StatusCode DataSvc::loadObject(IRegistry* pRegistry) {
677 IConversionSvc* pLoader = getDataLoader(pRegistry);
678 return loadObject(pLoader, pRegistry);
679 }
680
684 StatusCode DataSvc::loadObject(IConversionSvc* pLoader, IRegistry* pRegistry) {
685 StatusCode status = INVALID_OBJ_ADDR;
686 DataObject* pObject = 0;
687 if ( 0 == pLoader ) { // Precondition: Data loader must be present
688 if (handleDataFault(pRegistry) != 0) return SUCCESS;
689 else return NO_DATA_LOADER;
690 }
691 if ( 0 == pRegistry ) { // Precondition: Directory must be valid
692 if (handleDataFault(pRegistry) != 0) return SUCCESS;
693 else return INVALID_OBJ_ADDR;
694 }
695
696 VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
697
698 if ( m_enableAccessHdlr ) {
699 // Fire data access incident
700 DataIncident incident(name(), m_accessName, pRegistry->identifier());
701 m_incidentSvc->fireIncident(incident);
702 }
703 if ( m_inhibitPathes.size() > 0 ) {
704 const std::string& ident = pRegistry->identifier();
705 std::vector<std::string>::iterator inhibit =
706 std::find(m_inhibitPathes.begin(), m_inhibitPathes.end(), ident);
707 if ( inhibit != m_inhibitPathes.end() ) {
708 return NO_ACCESS;
709 }
710 }
711 IOpaqueAddress* pAddress = pRegistry->address();
712 if ( 0 == pAddress ) { // Precondition:
713 return INVALID_OBJ_ADDR; // Address must be valid
714 }
715 try {
716 status = pLoader->createObj(pAddress, pObject); // Call data loader
717 if ( status.isSuccess() ) {
718
719 VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
720
721 RegEntry *pEntry = CAST_REGENTRY(RegEntry*,pRegistry);
722 pEntry->setObject(pObject);
723
724 VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
725 status = pLoader->fillObjRefs(pAddress, pObject);
726 }
727 }
728 catch( const GaudiException& exc ) {
729 if ( handleDataFault(pRegistry) != 0 ) {
730 return SUCCESS;
731 }
732 throw GaudiException("GaudiException in loadObject() " + pRegistry->identifier(),
733 name(), StatusCode::FAILURE, exc);
734 }
735 catch( const std::exception& x) {
736 if ( handleDataFault(pRegistry) != 0 ) {
737 return SUCCESS;
738 }
739 throw GaudiException("std::exception in loadObject() " + pRegistry->identifier() +
740 ": " + System::typeinfoName(typeid(x)) + ", " + x.what(),
741 name(), StatusCode::FAILURE);
742 }
743 catch(...) {
744 if ( handleDataFault(pRegistry) != 0 ) {
745 return SUCCESS;
746 }
747 throw GaudiException("UNKN exception in loadObject() " + pRegistry->identifier(),
748 name(), StatusCode::FAILURE);
749 }
750 if ( !status.isSuccess() ) {
751 if ( handleDataFault(pRegistry) != 0 ) {
752 return StatusCode::SUCCESS;
753 }
754 }
755 ON_VERBOSE if ( status.isSuccess() ) {
756 verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
757 }
758 return status;
759 }
760
762 StatusCode DataSvc::retrieveEntry(RegEntry* parentObj,
763 const std::string& path,
764 RegEntry*& pEntry) {
765 std::string::size_type sep = path.find(SEPARATOR,1);
766 StatusCode status = StatusCode(INVALID_ROOT,true);
767 pEntry = 0;
768 // A.Valassi 16.08.2001 avoid core dump if store is empty
769 if ( checkRoot() ) {
770 if ( 0 == parentObj ) {
771 if ( path.length() == 0 || path == m_rootName ) {
772 return retrieveEntry(m_root, "", pEntry);
773 }
774 else if ( path[0] != SEPARATOR ) {
775 return retrieveEntry(m_root, path, pEntry);
776 }
777 else if ( sep != std::string::npos ) {
778 if ( m_root->object() == 0 ) {
779 RegEntry* r = 0;
780 status = retrieveEntry(m_root, "", r);
781 if ( !status.isSuccess() ) {
782 return status;
783 }
784 }
785 std::string o_path (path, sep, path.length());
786 return retrieveEntry(m_root, o_path, pEntry);
787 }
788 return INVALID_OBJ_PATH;
789 }
790 if ( sep != std::string::npos ) { // the string contains a separator (after pos 0)
791 std::string p_path (path,0,sep);
792 std::string o_path (path,sep,path.length());
793 if (!parentObj->object()) { // if the parent object has not been loaded yet, load it now
794 status = loadObject(parentObj);
795 if ( !status.isSuccess() ) {
796 return status;
797 }
798 }
799 RegEntry* root_entry = parentObj->findLeaf(p_path);
800 if ( !root_entry && m_enableFaultHdlr ) {
801 // If not even the parent is there, an incident
802 // to load the parent must be fired...
803 handleDataFault(parentObj, p_path);
804 root_entry = parentObj->findLeaf(p_path);
805 }
806 if ( root_entry ) {
807 DataObject* pO = root_entry->object();
808 if ( 0 == pO ) {
809 // Object is not loaded: load the object if at all possible
810 status = loadObject(root_entry);
811 if ( !status.isSuccess() ) {
812 return status;
813 }
814 }
815 if ( root_entry->isSoft() ) {
816 root_entry = CAST_REGENTRY(RegEntry*,pO->registry());
817 }
818 return retrieveEntry (root_entry, o_path, pEntry);
819 }
820 return status;
821 }
822 else if ( path.length() == 0 ) {
823 pEntry = parentObj;
824 }
825 else {
826 if (!parentObj->object()) { // if the parent object has not been loaded yet, load it now
827 status = loadObject(parentObj);
828 if ( !status.isSuccess() ) {
829 return status;
830 }
831 }
832 // last leave in search: find leaf and load
833 pEntry = parentObj->findLeaf(path);
834 // If no registry entry was found, trigger incident for action-on-demand
835 if ( !pEntry && m_enableFaultHdlr ) {
836 handleDataFault(parentObj, path);
837 pEntry = (0==path.length()) ? parentObj : parentObj->findLeaf(path);
838 }
839 }
840 // Check results and return
841 if ( 0 == pEntry ) {
842 status = INVALID_OBJ_PATH;
843 }
844 else if ( 0 == pEntry->object() ) {
845 status = loadObject(pEntry);
846 }
847 else if ( m_enableAccessHdlr ) {
848 // Fire data access incident
849 // I do not know if this is a good idea....
850 // This fires too often!
851 //
852 //DataIncident incident(name(), m_accessName, pEntry->identifier());
853 //m_incidentSvc->fireIncident(incident);
854 status = SUCCESS;
855 }
856 else {
857 status = SUCCESS;
858 }
859 }
860 return status;
861 }
862
864 StatusCode DataSvc::retrieveObject(IRegistry* pRegistry,
865 const std::string& path,
866 DataObject*& pObject) {
867 pObject = 0;
868 RegEntry *result = 0, *parent = CAST_REGENTRY(RegEntry*,pRegistry);
869 StatusCode status = retrieveEntry(parent, path, result);
870 if ( status.isSuccess() ) {
871 pObject = result->object();
872 }
873 return status;
874 }
875
877 StatusCode DataSvc::retrieveObject(const std::string& fullPath,
878 DataObject*& pObject) {
879 IRegistry* nullDir = 0;
880 return retrieveObject(nullDir, fullPath, pObject);
881 }
882
884 StatusCode DataSvc::retrieveObject(const std::string& parentPath,
885 const std::string& objectPath,
886 DataObject*& pObject) {
887 DataObject* parent = 0;
888 StatusCode status = retrieveObject(parentPath, parent);
889 if ( status.isSuccess() ) {
890 status = retrieveObject (parent, objectPath, pObject);
891 }
892 return status;
893 }
894
896 StatusCode DataSvc::retrieveObject(const std::string& parentPath,
897 int item,
898 DataObject*& pObject) {
899 return retrieveObject(parentPath, itemToPath(item), pObject);
900 }
901
903 StatusCode DataSvc::retrieveObject(DataObject* parentObj,
904 const std::string& path,
905 DataObject*& pObject) {
906 IRegistry* pRegistry = (0==parentObj) ? 0 : parentObj->registry();
907 return retrieveObject(pRegistry, path, pObject);
908 }
909
911 StatusCode DataSvc::retrieveObject(DataObject* parentObj,
912 int item,
913 DataObject*& pObject) {
914 return retrieveObject(parentObj, itemToPath(item), pObject);
915 }
916
918 StatusCode DataSvc::findObject(IRegistry* pRegistry,
919 const std::string& path,
920 DataObject*& pObject) {
921 pObject = 0;
922 IRegistry* pReg = (0==pRegistry) ? m_root : pRegistry;
923 RegEntry* root_entry = CAST_REGENTRY(RegEntry*, pReg);
924 if ( 0 != root_entry ) {
925 if ( path.length() > 0 ) {
926 pReg = root_entry->find(path);
927 }
928 if ( 0 == pReg ) {
929 return INVALID_OBJ_PATH;
930 }
931 pObject = pReg->object();
932 }
933 return (0 == pObject) ? OBJ_NOT_LOADED : IDataProviderSvc_NO_ERROR;
934 }
935
937 StatusCode DataSvc::findObject(const std::string& path,
938 DataObject*& pObject) {
939 pObject = 0;
940 if ( checkRoot() ) {
941 if ( path.length() == 0 || path == m_rootName ) {
942 pObject = m_root->object();
943 return (0 == pObject) ? OBJ_NOT_LOADED : IDataProviderSvc_NO_ERROR;
944 }
945 else if ( path[0] != SEPARATOR ) {
946 return findObject(m_rootName, path, pObject);
947 }
948 return findObject((IRegistry*)0, path, pObject);
949 }
950 return INVALID_ROOT;
951 }
952
954 StatusCode DataSvc::findObject(const std::string& parentPath,
955 const std::string& objectPath,
956 DataObject*& pObject) {
957 DataObject* parent = 0;
958 StatusCode status = findObject(parentPath, parent);
959 if ( status.isSuccess() ) {
960 status = findObject (parent, objectPath, pObject);
961 }
962 return status;
963 }
964
966 StatusCode DataSvc::findObject(const std::string& parentPath,
967 int item, DataObject*& pObject) {
968 return findObject(parentPath, itemToPath(item), pObject);
969 }
970
972 StatusCode DataSvc::findObject(DataObject* parentObj,
973 int item,
974 DataObject*& pObject) {
975 return findObject(parentObj, itemToPath(item), pObject);
976 }
977
979 StatusCode DataSvc::findObject(DataObject* parentObj,
980 const std::string& path,
981 DataObject*& pObject) {
982 IRegistry* pDir = (0==parentObj) ? 0 : parentObj->registry();
983 return findObject(pDir, path, pObject);
984 }
985
987 StatusCode DataSvc::updateObject(const std::string& updatePath) {
988 DataObject* pO = 0;
989 StatusCode status = findObject(updatePath, pO);
990 if ( status.isSuccess() ) {
991 return updateObject(pO);
992 }
993 return retrieveObject(updatePath, pO);
994 }
995
997 StatusCode DataSvc::updateObject(IRegistry* pRegistry) {
998 if ( 0 == pRegistry ) { // Precondition:
999 return INVALID_OBJ_ADDR; // Addres must be valid
1000 }
1001 DataObject* toUpdate = pRegistry->object();
1002 if ( 0 == toUpdate ) { // Try first to load
1003 return loadObject(pRegistry);
1004 }
1005 return updateObject(toUpdate);
1006 }
1007
1009 StatusCode DataSvc::updateObject(DataObject* toUpdate) {
1010 StatusCode status = INVALID_OBJ_ADDR;
1011 if ( 0 == toUpdate ) { // Precondition:
1012 return INVALID_OBJECT; // Address must be valid
1013 }
1014 IRegistry* pRegistry = toUpdate->registry(); // Precondition:
1015 if ( 0 == pRegistry ) { // Need valid registry
1016 return INVALID_OBJECT;
1017 }
1018 IOpaqueAddress* pAddress = pRegistry->address(); // Precondition:
1019 if ( 0 == pAddress ) { // Need valid address
1020 return INVALID_OBJ_ADDR;
1021 }
1022 IConversionSvc* pLoader = getDataLoader(pRegistry);
1023 if ( 0 == pLoader ) { // Precondition:
1024 return NO_DATA_LOADER; // Data loader must be present
1025 }
1026 if ( m_inhibitPathes.size() > 0 ) {
1027 const std::string& ident = pRegistry->identifier();
1028 std::vector<std::string>::iterator inhibit =
1029 std::find(m_inhibitPathes.begin(), m_inhibitPathes.end(), ident);
1030 if ( inhibit != m_inhibitPathes.end() ) {
1031 return NO_ACCESS;
1032 }
1033 }
1034 try {
1035 status = pLoader->updateObj(pAddress, toUpdate); // Call data loader
1036 if ( status.isSuccess() ) {
1037 status = pLoader->updateObjRefs(pAddress, toUpdate);
1038 }
1039 }
1040 catch( const GaudiException& exc ) {
1041 throw GaudiException("GaudiException in updateObject() " +
1042 pRegistry->name(),
1043 name(),
1044 StatusCode::FAILURE, exc);
1045 }
1046 catch( const std::exception& x) {
1047 throw GaudiException("std::exception in updateObject() " +
1048 pRegistry->name() + ": " +
1049 System::typeinfoName(typeid(x)) + ", " +
1050 x.what(),
1051 name(), StatusCode::FAILURE);
1052 }
1053 catch(...) {
1054 throw GaudiException("UNKN exception in updateObject() " +
1055 pRegistry->name(),
1056 name(), StatusCode::FAILURE);
1057 }
1058 return status;
1059 }
1060
1062 StatusCode DataSvc::updateObject(const std::string& parentPath,
1063 const std::string& updatePath) {
1064 DataObject* pParent = 0;
1065 StatusCode status = findObject(parentPath, pParent);
1066 if ( status.isSuccess() ) {
1067 status = updateObject( pParent, updatePath);
1068 }
1069 return status;
1070 }
1071
1073 StatusCode DataSvc::updateObject(DataObject* parent,
1074 const std::string& updatePath) {
1075 DataObject* pObject = 0;
1076 StatusCode status = findObject(parent, updatePath, pObject);
1077 if ( status.isSuccess() ) {
1078 status = updateObject(pObject);
1079 }
1080 return status;
1081 }
1082
1083 // Link object
1084 StatusCode DataSvc::linkObject(IRegistry* from,
1085 const std::string& objPath, DataObject* to) {
1086 if ( checkRoot() ) {
1087 try {
1088 RegEntry* from_entry = CAST_REGENTRY(RegEntry*,from);
1089 if ( 0 != from_entry ) {
1090 // First check if both objects are already registered to the store
1091 RegEntry* to_entry = m_root->findLeaf(to);
1092 if ( 0 == to_entry ) {
1093 return INVALID_OBJECT;
1094 }
1095 else {
1096 std::string::size_type sep = objPath.rfind(SEPARATOR);
1097 if ( sep > 0 && sep != std::string::npos ) { // in case the objPath is a sub-directory itself
1098 DataObject* pO = 0;
1099 std::string fromPath(objPath, 0, sep);
1100 StatusCode sc = retrieveObject(from, fromPath, pO);
1101 if ( sc.isSuccess() ) {
1102 std::string toPath(objPath, sep, objPath.length());
1103 sc = linkObject(pO->registry(), toPath, to);
1104 }
1105 return sc;
1106 }
1107 // Now register the soft link
1108 StatusCode status = from_entry->add( objPath, to, true);
1109 return status.isSuccess() ?
1110 IDataProviderSvc_NO_ERROR : DOUBL_OBJ_PATH;
1111 }
1112 }
1113 }
1114 catch (...) {
1115 }
1116 return INVALID_PARENT;
1117 }
1118 return INVALID_ROOT;
1119 }
1120
1122 StatusCode DataSvc::linkObject(const std::string& fullPath,
1123 DataObject* to) {
1124 if ( fullPath.length() > 0 ) {
1125 if ( fullPath[0] != SEPARATOR ) {
1126 return linkObject(m_rootName, fullPath, to);
1127 }
1128 std::string::size_type sep = fullPath.rfind(SEPARATOR);
1129 std::string objPath(fullPath, sep, fullPath.length());
1130 std::string fromPath(fullPath, 0, sep);
1131 return linkObject( fromPath, objPath, to);
1132 }
1133 return INVALID_OBJ_PATH;
1134 }
1135
1137 StatusCode DataSvc::linkObject(const std::string& from,
1138 const std::string& objPath,
1139 DataObject* to) {
1140 DataObject* pO = 0;
1141 StatusCode status = retrieveObject(from, pO);
1142 if ( status.isSuccess() ) {
1143 return linkObject(pO->registry(), objPath, to);
1144 }
1145 return status;
1146 }
1147
1149 StatusCode DataSvc::linkObject(DataObject* from,
1150 const std::string& objPath,
1151 DataObject* to) {
1152 if ( 0 != from ) {
1153 IRegistry* from_entry = from->registry();
1154 if ( 0 != from_entry ) {
1155 return linkObject( from_entry, objPath, to);
1156 }
1157 }
1158 return INVALID_PARENT;
1159 }
1160
1162 StatusCode DataSvc::unlinkObject(IRegistry* from,
1163 const std::string& objPath) {
1164 if ( checkRoot() ) {
1165 try {
1166 RegEntry* from_entry = CAST_REGENTRY(RegEntry*,from);
1167 if ( 0 != from_entry ) {
1168 std::string::size_type sep = objPath.rfind(SEPARATOR);
1169 if ( sep > 0 && sep != std::string::npos ) { // in case the objPath is a sub-directory itself
1170 DataObject* pO = 0;
1171 std::string fromPath(objPath, 0, sep);
1172 StatusCode sc = findObject(from, fromPath, pO);
1173 if ( sc.isSuccess() ) {
1174 std::string toPath(objPath, sep, objPath.length());
1175 sc = unlinkObject(pO->registry(), toPath);
1176 }
1177 return sc;
1178 }
1179 StatusCode status = from_entry->remove( objPath );
1180 if ( status.isSuccess() ) {
1181 return status;
1182 }
1183 return INVALID_OBJ_PATH;
1184 }
1185 }
1186 catch (...) {
1187 }
1188 return INVALID_PARENT;
1189 }
1190 return INVALID_ROOT;
1191 }
1192
1194 StatusCode DataSvc::unlinkObject(const std::string& fullPath) {
1195 if ( fullPath.length() > 0 ) {
1196 if ( fullPath[0] != SEPARATOR ) {
1197 return unlinkObject(m_rootName, fullPath);
1198 }
1199 std::string::size_type sep = fullPath.rfind(SEPARATOR);
1200 std::string objPath(fullPath, sep, fullPath.length());
1201 std::string fromPath(fullPath, 0, sep);
1202 return unlinkObject(fromPath, objPath);
1203 }
1204 return INVALID_OBJ_PATH;
1205 }
1206
1208 StatusCode DataSvc::unlinkObject(const std::string& from,
1209 const std::string& objPath) {
1210 DataObject* pObject = 0;
1211 StatusCode status = findObject(from, pObject);
1212 if ( status.isSuccess() ) {
1213 status = unlinkObject(pObject->registry(), objPath);
1214 }
1215 return status;
1216 }
1217
1219 StatusCode DataSvc::unlinkObject(DataObject* from,
1220 const std::string& objPath) {
1221 if ( checkRoot() ) {
1222 IRegistry* from_entry = m_root->findLeaf(from);
1223 return unlinkObject(from_entry, objPath);
1224 }
1225 return INVALID_ROOT;
1226 }
1227
1229 StatusCode DataSvc::addPreLoadItem(const DataStoreItem& item) {
1230 LoadItems::iterator i = std::find(m_preLoads.begin(), m_preLoads.end(), item);
1231 if ( i == m_preLoads.end() ) {
1232 m_preLoads.push_back(item);
1233 }
1234 return StatusCode::SUCCESS;
1235 }
1236
1238 StatusCode DataSvc::addPreLoadItem(const std::string& itemPath) {
1239 return addPreLoadItem( DataStoreItem(itemPath,1) );
1240 }
1241
1243 StatusCode DataSvc::removePreLoadItem(const DataStoreItem& item) {
1244 LoadItems::iterator i =
1245 std::remove(m_preLoads.begin(), m_preLoads.end(), item);
1246 if ( i != m_preLoads.end() ) {
1247 m_preLoads.erase(i, m_preLoads.end());
1248 }
1249 return StatusCode::SUCCESS;
1250 }
1251
1253 StatusCode DataSvc::removePreLoadItem(const std::string& itemPath) {
1254 return removePreLoadItem( DataStoreItem(itemPath,1) );
1255 }
1256
1258 StatusCode DataSvc::resetPreLoad() {
1259 m_preLoads.erase(m_preLoads.begin(), m_preLoads.end());
1260 return StatusCode::SUCCESS;
1261 }
1262
1264 StatusCode DataSvc::preLoad(int depth, int load_depth, DataObject* pObject) {
1265 //unused: StatusCode sc = StatusCode::FAILURE;
1266 if ( 0 != pObject && depth++ < load_depth ) {
1267 RegEntry* dir = CAST_REGENTRY(RegEntry*,pObject->registry());
1268 if ( 0 != dir ) {
1269 for (RegEntry::Iterator i = dir->begin(); i != dir->end(); i++ ) {
1270 DataObject *pObj = 0;
1271 StatusCode status = retrieveObject(pObject, (*i)->name(), pObj);
1272 if ( status.isSuccess() && depth < load_depth ) {
1273 preLoad(depth, load_depth, pObj).ignore();
1274 }
1275 }
1276 }
1277 }
1278 return StatusCode::SUCCESS;
1279 }
1280
1282 StatusCode DataSvc::preLoad() {
1283 DataObject* pObj = 0;
1284 for (LoadItems::iterator i = m_preLoads.begin(); i != m_preLoads.end(); i++) {
1285 StatusCode sc = retrieveObject( (*i).path(), pObj);
1286 int load_depth = (*i).depth();
1287 if ( sc.isSuccess() && load_depth > 1 ) {
1288 preLoad(1, load_depth, pObj).ignore();
1289 }
1290 }
1291 return StatusCode::SUCCESS;
1292 }
1293
1295 StatusCode DataSvc::initialize() {
1296 // Nothing to do: just call base class initialisation
1297 StatusCode sc = Service::initialize();
1298 if ( !sc.isSuccess() ) {
1299 return sc;
1300 }
1301 sc = service("IncidentSvc", m_incidentSvc, true);
1302 if ( UNLIKELY(!sc.isSuccess()) ) {
1303 error() << "Failed to access incident service." << endmsg;
1304 }
1305 return sc;
1306 }
1307
1309 StatusCode DataSvc::reinitialize() {
1310 StatusCode sc;
1311 // the finalize part is copied here
1312 setDataLoader(0).ignore();
1313 resetPreLoad().ignore();
1314 clearStore().ignore();
1315 if ( m_incidentSvc ) {
1316 m_incidentSvc->release();
1317 m_incidentSvc = 0;
1318 }
1319 // re-initialize the base class
1320 sc = Service::reinitialize();
1321 if ( UNLIKELY(!sc.isSuccess()) ) {
1322 error() << "Unable to reinitialize base class" << endmsg;
1323 return sc;
1324 }
1325 // the initialize part is copied here
1326 sc = service("IncidentSvc", m_incidentSvc, true);
1327 if ( UNLIKELY(!sc.isSuccess()) ) {
1328 error() << "Failed to access incident service." << endmsg;
1329 return sc;
1330 }
1331 // return
1332 return StatusCode::SUCCESS;
1333 }
1334
1336 StatusCode DataSvc::finalize() {
1337 // Nothing to do: just call base class initialisation
1338 setDataLoader(0).ignore();
1339 resetPreLoad().ignore();
1340 clearStore().ignore();
1341 if ( m_incidentSvc ) {
1342 m_incidentSvc->release();
1343 m_incidentSvc = 0;
1344 }
1345 return Service::finalize();
1346 }
1347
1349 CLID DataSvc::rootCLID() const {
1350 return( (CLID)m_rootCLID );
1351 }
1352
1354 std::string DataSvc::rootName() const {
1355 return( m_rootName );
1356 }
1357
1359 DataObject* DataSvc::createDefaultObject() const {
1360 return new DataObject();
1361 }
1362
1366 IConversionSvc* DataSvc::getDataLoader(IRegistry* /* pReg */) {
1367 return m_dataLoader;
1368 }
1369
1371 DataSvc::DataSvc(const std::string& name,ISvcLocator* svc)
1372 : base_class(name,svc), m_rootCLID( /*CLID_Event*/ 110),
1373 m_rootName( "/Event"), m_root(0)
1374 {
1375 m_dataLoader = 0;
1376 m_inhibitMap = 0;
1377 m_incidentSvc = 0;
1378 m_forceLeaves = false;
1379 m_enableFaultHdlr = false;
1380 m_enableAccessHdlr = false;
1381 m_faultName = "DataFault";
1382 m_accessName = "DataAccess";
1383 declareProperty("RootCLID", m_rootCLID);
1384 declareProperty("RootName", m_rootName);
1385 declareProperty("ForceLeaves", m_forceLeaves);
1386 declareProperty("InhibitPathes", m_inhibitPathes);
1387 declareProperty("DataFaultName", m_faultName);
1388 declareProperty("DataAccessName", m_accessName);
1389 declareProperty("EnableFaultHandler", m_enableFaultHdlr);
1390 declareProperty("EnableAccessHandler", m_enableAccessHdlr);
1391 }
1392
1394 DataSvc::~DataSvc() {
1395 setDataLoader(0).ignore();
1396 resetPreLoad().ignore();
1397 clearStore().ignore();
1398 }