All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules 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"
25 
26 #include "GaudiKernel/DataObject.h"
28 
30 #include "GaudiKernel/DataSvc.h"
33 
34 // Include files
35 #include <cassert>
36 #include <cstdlib>
37 #include <vector>
38 #include <algorithm>
39 #include <sstream>
40 
41 #include "boost/utility/string_ref.hpp"
42 
43 
44 namespace {
47  inline std::string itemToPath(int item) {
48  return '/' + std::to_string(item);
49  }
50 
51  inline boost::string_ref::size_type find( boost::string_ref s, char c, size_t o ) {
52  if (!s.empty()) s.remove_prefix(o);
53  auto r = s.find(c);
54  return r==boost::string_ref::npos ? r : ( r + o ) ;
55  }
56 }
57 
58 // If you absolutely need optimization: switch off dynamic_cast.
59 // This improves access to the data store roughly by 10 %
60 // for balanced trees.
61 //
62 // M.Frank
63 #define CAST_REGENTRY(x,y) dynamic_cast<x>(y)
64 //#define CAST_REGENTRY(x,y) (x)(y)
66 
67 #define ON_DEBUG if (msgLevel(MSG::DEBUG))
68 #define ON_VERBOSE if (msgLevel(MSG::VERBOSE))
69 
70 #define DEBMSG ON_DEBUG debug()
71 #define VERMSG ON_VERBOSE verbose()
72 
77  DataObject* pObject = nullptr;
78  StatusCode status = findObject(sub_tree_path, pObject);
79  if ( status.isSuccess() ) {
80  RegEntry* node_entry = CAST_REGENTRY(RegEntry*,pObject->registry());
81  if ( node_entry ) {
82  RegEntry* parent = node_entry->parentEntry();
83  if ( parent ) {
84  parent->remove(node_entry);
85  return StatusCode::SUCCESS;
86  }
87  return INVALID_PARENT;
88  }
89  return INVALID_OBJECT;
90  }
91  return status;
92 }
93 
98  if ( checkRoot() ) {
99  RegEntry* entry = CAST_REGENTRY(RegEntry*,pObject->registry());
100  if ( entry ) {
101  RegEntry* parent = entry->parentEntry();
102  if ( parent ) {
103  parent->remove(entry);
104  return SUCCESS;
105  }
106  return INVALID_PARENT;
107  }
108  return INVALID_OBJECT;
109  }
110  return INVALID_ROOT;
111 }
112 
115  if ( checkRoot() ) {
116  m_root->release();
117  m_root = nullptr;
118  return SUCCESS;
119  }
120  return INVALID_ROOT;
121 }
122 
127  IDataStoreAgent* pAgent) {
128  DataObject* pO = nullptr;
129  StatusCode status = findObject(sub_tree_path, pO);
130  if ( status.isFailure() ) return status;
131  return traverseSubTree(pO, pAgent);
132 }
133 
136  IDataStoreAgent* pAgent ) {
137  if ( !checkRoot() ) return INVALID_ROOT;
138  RegEntry* entry = CAST_REGENTRY(RegEntry*,pObject->registry());
139  if ( !entry ) return INVALID_OBJECT;
140  return entry->traverseTree(pAgent);
141 }
142 
145  if ( !checkRoot() ) return INVALID_ROOT;
146  return m_root->traverseTree(pAgent);
147 }
148 
154  DataObject* pRootObj) {
155  clearStore().ignore();
156  return i_setRoot (std::move(root_path), pRootObj);
157 }
158 
165  DataObject* pRootObj) {
166  if ( pRootObj ) {
167  m_root = new RegEntry(std::move(root_path));
168  m_root->makeHard(pRootObj);
169  m_root->setDataSvc(this);
170  // No done with GaudiHive. preLoad().ignore();
171  }
172  return SUCCESS;
173 }
174 
180  IOpaqueAddress* pRootAddr) {
181  clearStore().ignore();
182  return i_setRoot (std::move(root_path), pRootAddr);
183 }
184 
191  IOpaqueAddress* pRootAddr) {
192  if ( pRootAddr ) {
193  m_root = new RegEntry(std::move(root_path));
194  m_root->makeHard(pRootAddr);
195  m_root->setDataSvc(this);
196  // Not done with GaudiHive. preLoad().ignore();
197  }
198  return SUCCESS;
199 }
200 
203  m_dataLoader = pDataLoader;
204  if ( m_dataLoader ) m_dataLoader->setDataProvider(dpsvc ? dpsvc :this).ignore();
205  return SUCCESS;
206 }
207 
210  IRegistry*& refpParent) {
211  if ( !pObject ) return INVALID_OBJECT;
212  return objectParent(pObject->registry(), refpParent);
213 }
216  IRegistry*& refpParent) {
217  if ( !checkRoot() ) return INVALID_ROOT;
218  const RegEntry* node_entry = CAST_REGENTRY(const RegEntry*,pRegistry);
219  if ( !node_entry ) return INVALID_OBJECT;
220  refpParent = node_entry->parent();
221  return StatusCode::SUCCESS;
222 }
223 
226  std::vector<IRegistry*>& leaves) {
227  if ( !pObject ) return INVALID_OBJECT;
228  return objectLeaves(pObject->registry(), leaves);
229 }
230 
235  std::vector<IRegistry*>& leaves) {
236  if ( !checkRoot() ) return INVALID_ROOT;
237  const RegEntry* node_entry = CAST_REGENTRY(const RegEntry*,pRegistry);
238  if ( !node_entry ) return INVALID_OBJECT;
239  leaves = node_entry->leaves();
240  return StatusCode::SUCCESS;
241 }
242 
245  IOpaqueAddress* pAddress) {
246  if ( fullPath.empty() ) return INVALID_OBJ_PATH;
247  return registerAddress( fullPath.front() != SEPARATOR ? m_root : nullptr,
248  fullPath, pAddress);
249 }
250 
253  const std::string& objectPath,
254  IOpaqueAddress* pAddress) {
255  IRegistry* pRegistry = ( parentObj ? parentObj->registry() : nullptr );
256  return registerAddress(pRegistry, objectPath, pAddress);
257 }
258 
261  const std::string& objPath,
262  IOpaqueAddress* pAddress) {
263  if ( !checkRoot() ) return INVALID_ROOT;
264  if ( objPath.empty() ) return INVALID_OBJ_PATH;
265 
266  if ( !parentObj ) {
267  if ( objPath.front() != SEPARATOR ) {
268  return registerAddress(m_root, objPath, pAddress);
269  }
270  std::string::size_type sep = objPath.find(SEPARATOR,1);
271  if ( sep == std::string::npos ) {
272  return INVALID_PARENT;
273  }
274  if ( objPath.compare(0,sep,m_rootName) == 0 ) {
275  return registerAddress(m_root, objPath.substr(sep), pAddress);
276  }
277  }
278  if ( objPath.front() != SEPARATOR ) {
279  return registerAddress(parentObj, char(SEPARATOR)+objPath, pAddress);
280  }
281  RegEntry* par_entry = CAST_REGENTRY(RegEntry*,parentObj);
282  if ( !par_entry ) return INVALID_PARENT;
283 
284  std::string::size_type sep = objPath.rfind(SEPARATOR);
285  if ( sep > 0 && sep != std::string::npos ) {
286  auto p_path = objPath.substr( 0, sep);
287  auto o_path = objPath.substr( sep );
288  RegEntry* p_entry = par_entry->findLeaf(p_path);
289  // Create default object leafs if the
290  // intermediate nodes are not present
291  if ( !p_entry && m_forceLeaves ) {
292  DataObject *pLeaf = createDefaultObject();
293  StatusCode sc = registerObject(par_entry->identifier(),
294  p_path,
295  pLeaf);
296  if ( sc.isFailure() ) delete pLeaf;
297  p_entry = par_entry->findLeaf(p_path);
298  }
299  if ( !p_entry ) return INVALID_PARENT;
300  return registerAddress(p_entry, o_path, pAddress);
301  }
302  StatusCode status = par_entry->add(objPath, pAddress);
303  return status.isSuccess() ? status : DOUBL_OBJ_PATH;
304 }
305 
308  if ( fullPath.empty() ) return INVALID_OBJ_PATH;
309  return unregisterAddress( fullPath.front() != SEPARATOR ? m_root : nullptr,
310  fullPath );
311 }
312 
315  const std::string& objPath) {
316  return unregisterAddress( pParent ? pParent->registry() : nullptr,
317  objPath);
318 }
319 
322  const std::string& objPath) {
323  if ( !checkRoot() ) return INVALID_ROOT;
324  if ( objPath.empty() ) return INVALID_OBJ_PATH;
325 
326  if ( !pParent ) {
327  if ( objPath.front() != SEPARATOR ) {
328  return unregisterAddress(m_root, objPath);
329  }
330  std::string::size_type sep = objPath.find(SEPARATOR,1);
331  if ( sep != std::string::npos &&
332  objPath.compare( 0, sep, m_rootName) == 0 ) {
333  return unregisterAddress(m_root, objPath.substr(sep));
334  }
335  return INVALID_PARENT;
336  }
337  if ( objPath.front() != SEPARATOR ) {
338  return unregisterAddress(pParent, char(SEPARATOR)+objPath);
339  }
340  RegEntry* node_entry = CAST_REGENTRY(RegEntry*,pParent);
341  if ( node_entry ) {
342  RegEntry* leaf_entry = node_entry->findLeaf(objPath);
343  if ( leaf_entry ) {
344  std::string::size_type sep = objPath.rfind(SEPARATOR);
345  if ( sep > 0 && sep != std::string::npos ) {
346  return unregisterAddress(leaf_entry->parent(), objPath.substr(sep));
347  }
348  StatusCode status = node_entry->remove(objPath);
349  if ( status.isSuccess() ) return status;
350  }
351  }
352  return INVALID_PARENT;
353 }
354 
357  DataObject* pObject) {
358  return registerObject(nullptr, fullPath, pObject);
359 }
360 
361 
364  const std::string& objPath,
365  DataObject* pObject) {
366  DataObject* pO = nullptr;
367  StatusCode status = retrieveObject(parentPath, pO);
368  if ( !status.isSuccess() && m_forceLeaves ) {
369  pO = createDefaultObject();
370  status = registerObject(parentPath, pO);
371  if ( !status.isSuccess() ) pO->release();
372  }
373  if ( status.isFailure() ) return status;
374  return registerObject(pO, objPath, pObject);
375 }
376 
379  int item,
380  DataObject* pObject) {
381  return registerObject(parentPath, itemToPath(item), pObject);
382 }
383 
386  int item,
387  DataObject* pObject) {
388  return registerObject(parentObj, itemToPath(item), pObject);
389 }
390 
393  const std::string& objPath,
394  DataObject* pObject) {
395  if ( !checkRoot() ) return INVALID_ROOT;
396 
397  if ( !parentObj ) {
398  if ( !objPath.empty() ) {
399  if ( objPath.front() == SEPARATOR ) {
400  auto sep = objPath.find(SEPARATOR,1);
401  if ( sep != std::string::npos ) {
402  return registerObject(objPath.substr( 0, sep), objPath.substr( sep ), pObject);
403  }
404  } else {
405  return registerObject(m_rootName, objPath, pObject);
406  }
407  }
408  return INVALID_OBJ_PATH;
409  }
410  RegEntry* node_entry = CAST_REGENTRY(RegEntry*,parentObj->registry());
411  if ( node_entry ) {
412  StatusCode status = INVALID_PARENT;
413  auto sep = objPath.find(SEPARATOR,1);
414  if ( sep != std::string::npos ) {
415  auto p_path = objPath.substr( 0, sep );
416  auto o_path = objPath.substr( sep );
417  RegEntry* par_entry = node_entry->findLeaf(p_path);
418  // Create default object leafs if the
419  // intermediate nodes are not present
420  if ( !par_entry && m_forceLeaves ) {
421  DataObject *pLeaf = createDefaultObject();
422  StatusCode sc = registerObject(parentObj, p_path, pLeaf);
423  if ( ! sc.isSuccess() ) delete pLeaf;
424  par_entry = node_entry->findLeaf(p_path);
425  }
426  else if ( par_entry && !par_entry->object() ) {
427  status = i_retrieveEntry( node_entry, p_path, par_entry);
428  if ( !status.isSuccess() && !par_entry->address() && m_forceLeaves ) {
429  DataObject *pLeaf = createDefaultObject();
430  StatusCode sc = registerObject(parentObj, p_path, pLeaf);
431  if ( ! sc.isSuccess() ) delete pLeaf;
432  par_entry = node_entry->findLeaf(p_path);
433  }
434  }
435  node_entry = par_entry;
436  if ( node_entry ) {
437  DataObject* obj = node_entry->object();
438  if ( obj ) {
439  status = registerObject( obj, o_path, pObject );
440  }
441  }
442  }
443  else {
444  RegEntry* leaf = node_entry->findLeaf(objPath);
445  if ( !leaf ) {
446  status = node_entry->add( objPath, pObject );
447  }
448  else {
449  DataObject* obj = leaf->object();
450  if ( !obj ) {
451  if ( !pObject ) {
452  error() << "registerObject: trying to register null DataObject" << endmsg;
453  return StatusCode::FAILURE;
454  }
455  pObject->setRegistry(leaf);
456  leaf->setAddress(nullptr);
457  leaf->setObject(pObject);
458  status = StatusCode::SUCCESS;
459  }
460  else {
461  status = DOUBL_OBJ_PATH;
462  }
463  }
464  }
465  return status;
466  }
467  return INVALID_PARENT;
468 }
469 
472  DataObject* pObject = nullptr;
473  StatusCode status = findObject(fullPath, pObject);
474  if ( status.isFailure() ) return status;
475  RegEntry* pEntry = CAST_REGENTRY(RegEntry*,pObject->registry());
476  if ( !pEntry ) return INVALID_ROOT;
477  if ( !pEntry->isEmpty() ) return DIR_NOT_EMPTY;
478  RegEntry* pParent = pEntry->parentEntry();
479  if ( !pParent ) return INVALID_PARENT;
480  if ( pObject ) pObject->addRef();
481  pParent->remove(pEntry);
482  return StatusCode::SUCCESS;
483 }
484 
487  const std::string& objPath) {
488  DataObject* pO = nullptr;
489  StatusCode status = findObject(parentPath, pO);
490  return status.isSuccess() ? unregisterObject(pO, objPath) : status;
491 }
492 
494 StatusCode DataSvc::unregisterObject(const std::string& parentPath, int item) {
495  return unregisterObject(parentPath, itemToPath(item));
496 }
497 
500  if ( !checkRoot() ) return INVALID_ROOT;
501  RegEntry* entry = m_root->findLeaf(pObject);
502  if ( !entry ) return INVALID_OBJECT;
503  RegEntry* parent = entry->parentEntry();
504  if ( !parent ) return INVALID_PARENT;
505  if ( !entry->isEmpty() ) return DIR_NOT_EMPTY;
506  if ( entry->object() ) entry->object()->addRef();
507  if ( parent ) parent->remove(entry);
508  return SUCCESS;
509 }
510 
513  const std::string& objectPath) {
514  if ( checkRoot() ) {
515  try {
516  RegEntry* parent = CAST_REGENTRY(RegEntry*,pParentObj->registry());
517  if ( parent ) {
518  RegEntry* entry = parent->findLeaf(objectPath);
519  if ( entry ) {
520  if ( entry->isEmpty() ) {
521  if ( entry->object() ) {
522  entry->object()->addRef();
523  }
524  parent->remove(entry);
525  return SUCCESS;
526  }
527  return DIR_NOT_EMPTY;
528  }
529  return INVALID_OBJECT;
530  }
531  }
532  catch(...) {
533  }
534  return INVALID_PARENT;
535  }
536  return INVALID_ROOT;
537 }
538 
541  return unregisterObject(pParentObj, itemToPath(item));
542 }
543 
547  return i_handleDataFault(pReg,path);
548 }
549 
551 {
552  if ( m_enableFaultHdlr ) {
553  IRegistry* pLeaf = nullptr;
554  if ( pReg && path.empty() ) {
555  DataIncident incident(name(), m_faultName, pReg->identifier());
556  m_incidentSvc->fireIncident(incident);
557  return pReg->object();
558  }
559  if ( pReg ) {
560  std::string p = pReg->identifier();
561  if (path.front() != SEPARATOR ) p += SEPARATOR;
562  p.append(path.data(),path.size());
563  DataIncident incident(name(), m_faultName, p);
564  m_incidentSvc->fireIncident(incident);
565  pLeaf = m_root->findLeaf(p);
566  } else {
568  if (path.front() != SEPARATOR ) p += SEPARATOR;
569  p.append(path.data(),path.size());
570  DataIncident incident(name(), m_faultName, p);
571  m_incidentSvc->fireIncident(incident);
572  pLeaf = m_root->findLeaf(p);
573  }
574  if ( pLeaf ) {
575  return pLeaf->object();
576  }
577  }
578  return nullptr;
579 }
580 
585  IConversionSvc* pLoader = getDataLoader(pRegistry);
586  return loadObject(pLoader, pRegistry);
587 }
588 
593  StatusCode status = INVALID_OBJ_ADDR;
594  DataObject* pObject = nullptr;
595  if ( !pLoader ) { // Precondition: Data loader must be present
596  return handleDataFault(pRegistry) ? StatusCode{SUCCESS} : NO_DATA_LOADER;
597  }
598  if ( !pRegistry ) { // Precondition: Directory must be valid
599  return handleDataFault(pRegistry) ? StatusCode{SUCCESS} : INVALID_OBJ_ADDR;
600  }
601 
602  VERMSG << "Requested object " << pRegistry->identifier() << endmsg;
603 
604  if ( m_enableAccessHdlr ) {
605  // Fire data access incident
606  DataIncident incident(name(), m_accessName, pRegistry->identifier());
607  m_incidentSvc->fireIncident(incident);
608  }
609  if ( !m_inhibitPathes.empty() ) {
610  auto inhibit = std::find(m_inhibitPathes.begin(), m_inhibitPathes.end(),
611  pRegistry->identifier());
612  if ( inhibit != m_inhibitPathes.end() ) {
613  return NO_ACCESS;
614  }
615  }
616  IOpaqueAddress* pAddress = pRegistry->address();
617  if ( !pAddress ) { // Precondition:
618  return INVALID_OBJ_ADDR; // Address must be valid
619  }
620  try {
621  status = pLoader->createObj(pAddress, pObject); // Call data loader
622  if ( status.isSuccess() ) {
623 
624  VERMSG << "Object " << pRegistry->identifier() << " created" << endmsg;
625 
626  RegEntry *pEntry = CAST_REGENTRY(RegEntry*,pRegistry);
627  pEntry->setObject(pObject);
628 
629  VERMSG << "Filling object " << pRegistry->identifier() << endmsg;
630  status = pLoader->fillObjRefs(pAddress, pObject);
631  }
632  }
633  catch( const GaudiException& exc ) {
634  if ( handleDataFault(pRegistry) ) {
635  return SUCCESS;
636  }
637  throw GaudiException("GaudiException in loadObject() " + pRegistry->identifier(),
638  name(), StatusCode::FAILURE, exc);
639  }
640  catch( const std::exception& x) {
641  if ( handleDataFault(pRegistry) ) {
642  return SUCCESS;
643  }
644  throw GaudiException("std::exception in loadObject() " + pRegistry->identifier() +
645  ": " + System::typeinfoName(typeid(x)) + ", " + x.what(),
647  }
648  catch(...) {
649  if ( handleDataFault(pRegistry) ) {
650  return SUCCESS;
651  }
652  throw GaudiException("UNKN exception in loadObject() " + pRegistry->identifier(),
654  }
655  if ( !status.isSuccess() ) {
656  if ( handleDataFault(pRegistry) ) {
657  return StatusCode::SUCCESS;
658  }
659  }
660  ON_VERBOSE if ( status.isSuccess() ) {
661  verbose() << "Object " << pRegistry->identifier() << " successfully loaded" << endmsg;
662  }
663  return status;
664 }
665 
668  const std::string& path,
669  RegEntry*& pEntry) {
670  return i_retrieveEntry(parentObj,path,pEntry);
671 }
672 
674  boost::string_ref path,
675  RegEntry*& pEntry) {
676  // A.Valassi 16.08.2001 avoid core dump if store is empty
677  if ( !checkRoot() ) return StatusCode(INVALID_ROOT,true);
678 
679  static const auto empty = boost::string_ref{};
680  auto sep = find(path,SEPARATOR,1);
681  pEntry = nullptr;
682 
683  if ( !parentObj ) {
684  if ( path.empty() || path == m_rootName ) {
685  parentObj = m_root;
686  path = empty;
687  } else if ( path.front() != SEPARATOR ) {
688  parentObj = m_root;
689  } else if ( sep != boost::string_ref::npos ) {
690  if ( !m_root->object() ) {
691  RegEntry* r = nullptr;
692  auto status = i_retrieveEntry(m_root, empty, r);
693  if ( !status.isSuccess() ) return status;
694  }
695  parentObj = m_root;
696  path = path.substr(sep);
697  } else {
698  return INVALID_OBJ_PATH;
699  }
700  sep = find(path,SEPARATOR,1);
701  }
702 
703  StatusCode status = StatusCode(INVALID_ROOT,true);
704  if ( sep != boost::string_ref::npos ) { // the string contains a separator (after pos 0)
705  if (!parentObj->object()) { // if the parent object has not been loaded yet, load it now
706  status = loadObject(parentObj);
707  if ( !status.isSuccess() ) return status;
708  }
709  auto p_path = path.substr(0,sep);
710  RegEntry* root_entry = parentObj->findLeaf(p_path);
711  if ( !root_entry && m_enableFaultHdlr ) {
712  // If not even the parent is there, an incident
713  // to load the parent must be fired...
714  i_handleDataFault(parentObj, p_path);
715  root_entry = parentObj->findLeaf(p_path);
716  }
717  if ( root_entry ) {
718  DataObject* pO = root_entry->object();
719  if ( !pO ) {
720  // Object is not loaded: load the object if at all possible
721  status = loadObject(root_entry);
722  if ( !status.isSuccess() ) return status;
723  }
724  if ( root_entry->isSoft() ) {
725  root_entry = CAST_REGENTRY(RegEntry*,pO->registry());
726  }
727  return i_retrieveEntry(root_entry, path.substr(sep), pEntry);
728  }
729  return status;
730  } else if ( path.empty() ) {
731  pEntry = parentObj;
732  } else {
733  if (!parentObj->object()) { // if the parent object has not been loaded yet, load it now
734  status = loadObject(parentObj);
735  if ( !status.isSuccess() ) return status;
736  }
737  // last leave in search: find leaf and load
738  pEntry = parentObj->findLeaf(path);
739  // If no registry entry was found, trigger incident for action-on-demand
740  if ( !pEntry && m_enableFaultHdlr ) {
741  i_handleDataFault(parentObj, path);
742  pEntry = (path.empty() ? parentObj : parentObj->findLeaf(path) );
743  }
744  }
745 
746  // Check results and return
747  if ( !pEntry ) return INVALID_OBJ_PATH;
748  if ( !pEntry->object() ) return loadObject(pEntry);
749 
750  if ( m_enableAccessHdlr ) {
751  // Fire data access incident
752  // I do not know if this is a good idea....
753  // This fires too often!
754  //
755  //DataIncident incident(name(), m_accessName, pEntry->identifier());
756  //m_incidentSvc->fireIncident(incident);
757  return SUCCESS;
758  }
759  return SUCCESS;
760 }
761 
764  const std::string& path,
765  DataObject*& pObject) {
766  pObject = nullptr;
767  RegEntry *result = nullptr, *parent = CAST_REGENTRY(RegEntry*,pRegistry);
768  StatusCode status = i_retrieveEntry(parent, path, result);
769  if ( status.isSuccess() ) pObject = result->object();
770  return status;
771 }
772 
775  DataObject*& pObject) {
776  IRegistry* nullDir = nullptr;
777  return retrieveObject(nullDir, fullPath, pObject);
778 }
779 
782  const std::string& objectPath,
783  DataObject*& pObject) {
784  DataObject* parent = nullptr;
785  StatusCode status = retrieveObject(parentPath, parent);
786  return status.isSuccess() ? retrieveObject (parent, objectPath, pObject)
787  : status;
788 }
789 
792  int item,
793  DataObject*& pObject) {
794  return retrieveObject(parentPath, itemToPath(item), pObject);
795 }
796 
799  const std::string& path,
800  DataObject*& pObject) {
801  IRegistry* pRegistry = (parentObj ? parentObj->registry() : nullptr);
802  return retrieveObject(pRegistry, path, pObject);
803 }
804 
807  int item,
808  DataObject*& pObject) {
809  return retrieveObject(parentObj, itemToPath(item), pObject);
810 }
811 
814  const std::string& path,
815  DataObject*& pObject) {
816  pObject = nullptr;
817  IRegistry* pReg = ( pRegistry ? pRegistry : m_root );
818  RegEntry* root_entry = CAST_REGENTRY(RegEntry*, pReg);
819  if ( root_entry ) {
820  if ( !path.empty() ) pReg = root_entry->find(path);
821  if ( !pReg ) return INVALID_OBJ_PATH;
822  pObject = pReg->object();
823  }
824  return (!pObject) ? OBJ_NOT_LOADED : IDataProviderSvc_NO_ERROR;
825 }
826 
829  DataObject*& pObject) {
830  pObject = nullptr;
831  if ( checkRoot() ) {
832  if ( path.empty() || path == m_rootName ) {
833  pObject = m_root->object();
834  return !pObject ? OBJ_NOT_LOADED : IDataProviderSvc_NO_ERROR;
835  }
836  else if ( path.front() != SEPARATOR ) {
837  return findObject(m_rootName, path, pObject);
838  }
839  return findObject((IRegistry*)nullptr, path, pObject);
840  }
841  return INVALID_ROOT;
842 }
843 
846  const std::string& objectPath,
847  DataObject*& pObject) {
848  DataObject* parent = nullptr;
849  StatusCode status = findObject(parentPath, parent);
850  return status.isSuccess() ? findObject (parent, objectPath, pObject)
851  : status;
852 }
853 
856  int item, DataObject*& pObject) {
857  return findObject(parentPath, itemToPath(item), pObject);
858 }
859 
862  int item,
863  DataObject*& pObject) {
864  return findObject(parentObj, itemToPath(item), pObject);
865 }
866 
869  const std::string& path,
870  DataObject*& pObject) {
871  IRegistry* pDir = ( parentObj ? parentObj->registry() : nullptr );
872  return findObject(pDir, path, pObject);
873 }
874 
877  DataObject* pO = nullptr;
878  StatusCode status = findObject(updatePath, pO);
879  return status.isSuccess() ? updateObject(pO)
880  : retrieveObject(updatePath, pO);
881 }
882 
885  if ( !pRegistry ) { // Precondition:
886  return INVALID_OBJ_ADDR; // Addres must be valid
887  }
888  DataObject* toUpdate = pRegistry->object();
889  if ( !toUpdate ) { // Try first to load
890  return loadObject(pRegistry);
891  }
892  return updateObject(toUpdate);
893 }
894 
897  StatusCode status = INVALID_OBJ_ADDR;
898  if ( !toUpdate ) { // Precondition:
899  return INVALID_OBJECT; // Address must be valid
900  }
901  IRegistry* pRegistry = toUpdate->registry(); // Precondition:
902  if ( !pRegistry ) { // Need valid registry
903  return INVALID_OBJECT;
904  }
905  IOpaqueAddress* pAddress = pRegistry->address(); // Precondition:
906  if ( !pAddress ) { // Need valid address
907  return INVALID_OBJ_ADDR;
908  }
909  IConversionSvc* pLoader = getDataLoader(pRegistry);
910  if ( !pLoader ) { // Precondition:
911  return NO_DATA_LOADER; // Data loader must be present
912  }
913  if ( !m_inhibitPathes.empty() ) {
914  auto inhibit = std::find( m_inhibitPathes.begin(), m_inhibitPathes.end(),
915  pRegistry->identifier());
916  if ( inhibit != m_inhibitPathes.end() ) {
917  return NO_ACCESS;
918  }
919  }
920  try {
921  status = pLoader->updateObj(pAddress, toUpdate); // Call data loader
922  if ( status.isSuccess() ) {
923  status = pLoader->updateObjRefs(pAddress, toUpdate);
924  }
925  }
926  catch( const GaudiException& exc ) {
927  throw GaudiException("GaudiException in updateObject() " +
928  pRegistry->name(),
929  name(),
930  StatusCode::FAILURE, exc);
931  }
932  catch( const std::exception& x) {
933  throw GaudiException("std::exception in updateObject() " +
934  pRegistry->name() + ": " +
935  System::typeinfoName(typeid(x)) + ", " +
936  x.what(),
938  }
939  catch(...) {
940  throw GaudiException("UNKN exception in updateObject() " +
941  pRegistry->name(),
943  }
944  return status;
945 }
946 
949  const std::string& updatePath) {
950  DataObject* pParent = nullptr;
951  StatusCode status = findObject(parentPath, pParent);
952  return status.isSuccess() ? updateObject( pParent, updatePath)
953  : status;
954 }
955 
958  const std::string& updatePath) {
959  DataObject* pObject = nullptr;
960  StatusCode status = findObject(parent, updatePath, pObject);
961  return status.isSuccess() ? updateObject(pObject)
962  : status;
963 }
964 
965 // Link object
967  const std::string& objPath, DataObject* to) {
968  if ( checkRoot() ) {
969  try {
970  RegEntry* from_entry = CAST_REGENTRY(RegEntry*,from);
971  if ( from_entry ) {
972  // First check if both objects are already registered to the store
973  RegEntry* to_entry = m_root->findLeaf(to);
974  if ( !to_entry ) {
975  return INVALID_OBJECT;
976  }
977  std::string::size_type sep = objPath.rfind(SEPARATOR);
978  if ( sep > 0 && sep != std::string::npos ) { // in case the objPath is a sub-directory itself
979  DataObject* pO = nullptr;
980  StatusCode sc = retrieveObject(from, objPath.substr(0,sep), pO);
981  if ( sc.isSuccess() ) {
982  sc = linkObject(pO->registry(), objPath.substr(sep), to);
983  }
984  return sc;
985  }
986  // Now register the soft link
987  StatusCode status = from_entry->add( objPath, to, true);
988  return status.isSuccess() ? IDataProviderSvc_NO_ERROR : DOUBL_OBJ_PATH;
989  }
990  }
991  catch (...) {
992  }
993  return INVALID_PARENT;
994  }
995  return INVALID_ROOT;
996 }
997 
1000  DataObject* to) {
1001  if ( !fullPath.empty() ) {
1002  if ( fullPath.front() != SEPARATOR ) {
1003  return linkObject(m_rootName, fullPath, to);
1004  }
1005  auto sep = fullPath.rfind(SEPARATOR);
1006  return linkObject( fullPath.substr( 0, sep), fullPath.substr(sep), to);
1007  }
1008  return INVALID_OBJ_PATH;
1009 }
1010 
1013  const std::string& objPath,
1014  DataObject* to) {
1015  DataObject* pO = nullptr;
1016  StatusCode status = retrieveObject(from, pO);
1017  return status.isSuccess() ? linkObject(pO->registry(), objPath, to)
1018  : status;
1019 }
1020 
1023  const std::string& objPath,
1024  DataObject* to) {
1025  if ( from ) {
1026  IRegistry* from_entry = from->registry();
1027  if ( from_entry ) {
1028  return linkObject( from_entry, objPath, to);
1029  }
1030  }
1031  return INVALID_PARENT;
1032 }
1033 
1036  const std::string& objPath) {
1037  if ( checkRoot() ) {
1038  try {
1039  RegEntry* from_entry = CAST_REGENTRY(RegEntry*,from);
1040  if ( from_entry ) {
1041  std::string::size_type sep = objPath.rfind(SEPARATOR);
1042  if ( sep > 0 && sep != std::string::npos ) { // in case the objPath is a sub-directory itself
1043  DataObject* pO = nullptr;
1044  StatusCode sc = findObject(from, objPath.substr(0,sep), pO);
1045  if ( sc.isSuccess() ) {
1046  sc = unlinkObject(pO->registry(), objPath.substr(sep));
1047  }
1048  return sc;
1049  }
1050  StatusCode status = from_entry->remove( objPath );
1051  if ( status.isSuccess() ) return status;
1052  return INVALID_OBJ_PATH;
1053  }
1054  }
1055  catch (...) {
1056  }
1057  return INVALID_PARENT;
1058  }
1059  return INVALID_ROOT;
1060 }
1061 
1064  if ( fullPath.empty() ) return INVALID_OBJ_PATH;
1065  if ( fullPath.front() != SEPARATOR ) {
1066  return unlinkObject(m_rootName, fullPath);
1067  }
1068  auto sep = fullPath.rfind(SEPARATOR);
1069  return unlinkObject(fullPath.substr(0,sep), fullPath.substr(sep));
1070 }
1071 
1074  const std::string& objPath) {
1075  DataObject* pObject = nullptr;
1076  StatusCode status = findObject(from, pObject);
1077  return status.isSuccess() ? unlinkObject(pObject->registry(), objPath)
1078  : status;
1079 }
1080 
1083  const std::string& objPath) {
1084  if ( !checkRoot() ) return INVALID_ROOT;
1085  IRegistry* from_entry = m_root->findLeaf(from);
1086  return unlinkObject(from_entry, objPath);
1087 }
1088 
1091  auto i = std::find(std::begin(m_preLoads), std::end(m_preLoads), item);
1092  if ( i == std::end(m_preLoads) ) {
1093  m_preLoads.push_back(item);
1094  }
1095  return StatusCode::SUCCESS;
1096 }
1097 
1100  return addPreLoadItem( DataStoreItem(itemPath,1) );
1101 }
1102 
1106  std::end(m_preLoads));
1107  return StatusCode::SUCCESS;
1108 }
1109 
1112  return removePreLoadItem( DataStoreItem(itemPath,1) );
1113 }
1114 
1118  return StatusCode::SUCCESS;
1119 }
1120 
1122 StatusCode DataSvc::preLoad(int depth, int load_depth, DataObject* pObject) {
1123  //unused: StatusCode sc = StatusCode::FAILURE;
1124  if ( pObject && depth++ < load_depth ) {
1125  RegEntry* dir = CAST_REGENTRY(RegEntry*,pObject->registry());
1126  if ( dir ) {
1127  for (const auto& i : *dir) {
1128  DataObject *pObj = nullptr;
1129  StatusCode status = retrieveObject(pObject, i->name(), pObj);
1130  if ( status.isSuccess() && depth < load_depth ) {
1131  preLoad(depth, load_depth, pObj).ignore();
1132  }
1133  }
1134  }
1135  }
1136  return StatusCode::SUCCESS;
1137 }
1138 
1141  DataObject* pObj = nullptr;
1142  for (const auto& i : m_preLoads ) {
1143  StatusCode sc = retrieveObject( i.path(), pObj);
1144  int load_depth = i.depth();
1145  if ( sc.isSuccess() && load_depth > 1 ) {
1146  preLoad(1, load_depth, pObj).ignore();
1147  }
1148  }
1149  return StatusCode::SUCCESS;
1150 }
1151 
1154  // Nothing to do: just call base class initialisation
1156  if ( UNLIKELY(!sc.isSuccess()) ) return sc;
1157  m_incidentSvc = service("IncidentSvc", true);
1158  if ( UNLIKELY(!m_incidentSvc) ) {
1159  error() << "Failed to access incident service." << endmsg;
1160  }
1161  return sc;
1162 }
1163 
1166  // the finalize part is copied here
1167  setDataLoader(nullptr).ignore();
1168  resetPreLoad().ignore();
1169  clearStore().ignore();
1170  m_incidentSvc.reset();
1171  // re-initialize the base class
1173  if ( UNLIKELY(!sc.isSuccess()) ) {
1174  error() << "Unable to reinitialize base class" << endmsg;
1175  return sc;
1176  }
1177  // the initialize part is copied here
1178  m_incidentSvc = service("IncidentSvc", true);
1179  if ( UNLIKELY(!m_incidentSvc) ) {
1180  error() << "Failed to access incident service." << endmsg;
1181  return StatusCode::FAILURE;
1182  }
1183  // return
1184  return StatusCode::SUCCESS;
1185 }
1186 
1189  // Nothing to do: just call base class initialisation
1190  setDataLoader(nullptr).ignore();
1191  resetPreLoad().ignore();
1192  clearStore().ignore();
1193  m_incidentSvc.reset();
1194  return Service::finalize();
1195 }
1196 
1199  return( (CLID)m_rootCLID );
1200 }
1201 
1204  return m_rootName;
1205 }
1206 
1209  return new DataObject();
1210 }
1211 
1216  return m_dataLoader.get();
1217 }
1218 
1221  setDataLoader(nullptr).ignore();
1222  resetPreLoad().ignore();
1223  clearStore().ignore();
1224 }
StatusCode unregisterObject(const std::string &fullPath) override
Unregister object from the data store.
Definition: DataSvc.cpp:471
Gaudi::Property< CLID > m_rootCLID
Definition: DataSvc.h:56
StatusCode addPreLoadItem(const DataStoreItem &item) override
Add an item to the preload list.
Definition: DataSvc.cpp:1090
#define VERMSG
Definition: DataSvc.cpp:71
StatusCode initialize() override
Definition: Service.cpp:64
T empty(T...args)
RegistryEntry * findLeaf(boost::string_ref path) const
Find identified leaf in this registry node.
Definition: RegistryEntry.h:95
~DataSvc() override
Standard Destructor.
Definition: DataSvc.cpp:1220
Define general base for Gaudi exception.
DataObject * object() const override
Retrive object behind the link.
const std::string & name() const override
Retrieve name of the service.
Definition: Service.cpp:289
StatusCode preLoad() override
load all preload items of the list
Definition: DataSvc.cpp:1140
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
constexpr char SEPARATOR
StatusCode finalize() override
Definition: Service.cpp:174
CLID rootCLID() const override
IDataManagerSvc: Accessor for root event CLID.
Definition: DataSvc.cpp:1198
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:299
T front(T...args)
Gaudi::Property< std::string > m_accessName
Definition: DataSvc.h:67
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:74
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:153
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:202
virtual long add(const std::string &name, DataObject *pObject, bool is_soft=false)
Add entry to data store.
T rfind(T...args)
T to_string(T...args)
virtual long traverseTree(IDataStoreAgent *pAgent, int level=0)
traverse data tree
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Gaudi::Property< std::string > m_rootName
Definition: DataSvc.h:57
virtual StatusCode setDataProvider(IDataProviderSvc *pService)=0
Set Data provider service.
#define UNLIKELY(x)
Definition: Kernel.h:126
virtual StatusCode loadObject(IRegistry *pNode)
Invoke Persistency service to create transient object from its persistent representation.
Definition: DataSvc.cpp:584
LoadItems m_preLoads
Items to be pre-loaded.
Definition: DataSvc.h:70
Gaudi::Property< bool > m_forceLeaves
Definition: DataSvc.h:58
void setRegistry(IRegistry *pRegistry)
Set pointer to Registry.
Definition: DataObject.h:70
unsigned long release() override
IInterface implementation: Reference the object.
Gaudi::Property< bool > m_enableFaultHdlr
Definition: DataSvc.h:61
virtual const name_type & name() const =0
Name of the directory (or key)
StatusCode traverseTree(IDataStoreAgent *pAgent) override
IDataManagerSvc: Analyze by traversing all data objects in the data store.
Definition: DataSvc.cpp:144
T end(T...args)
bool checkRoot()
Check if root path is valid.
Definition: DataSvc.h:321
DataObject * i_handleDataFault(IRegistry *pReg, boost::string_ref path=boost::string_ref{})
Definition: DataSvc.cpp:550
StatusCode removePreLoadItem(const DataStoreItem &item) override
Remove an item from the preload list.
Definition: DataSvc.cpp:1104
virtual long remove(const std::string &name)
Remove an entry from the store.
const Store & leaves() const
Access the leaves of the object.
StatusCode registerObject(const std::string &fullPath, DataObject *pObject) override
Register object with the data store.
Definition: DataSvc.cpp:356
Data provider interface definition.
DataSvcHelpers::RegistryEntry * m_root
Pointer to root entry.
Definition: DataSvc.h:72
T remove(T...args)
void setAddress(IOpaqueAddress *pAddress) override
Set/Update Opaque address.
Description of the DataStoreItem class.
Definition: DataStoreItem.h:17
StatusCode registerAddress(const std::string &fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition: DataSvc.cpp:244
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:84
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:74
virtual StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *refpObject)=0
Update the transient object from the other representation.
virtual RegistryEntry * parentEntry()
Pointer to parent registry entry.
Definition: RegistryEntry.h:91
STL class.
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:76
virtual bool isSoft() const
Is the link soft or hard.
T push_back(T...args)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
virtual unsigned long addRef()
Add reference to object.
Definition: DataObject.cpp:63
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
void setObject(DataObject *obj)
Set/Update object address.
StatusCode i_retrieveEntry(DataSvcHelpers::RegistryEntry *parentObj, boost::string_ref path, DataSvcHelpers::RegistryEntry *&pEntry)
Definition: DataSvc.cpp:673
Gaudi::Property< std::string > m_faultName
Definition: DataSvc.h:63
virtual const id_type & identifier() const =0
Full identifier (or key)
T what(T...args)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
StatusCode retrieveEntry(DataSvcHelpers::RegistryEntry *pNode, const std::string &path, DataSvcHelpers::RegistryEntry *&pEntry)
Retrieve registry entry from store.
Definition: DataSvc.cpp:667
T append(T...args)
virtual StatusCode updateObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Update the references of an updated transient object.
SmartIF< IIncidentSvc > m_incidentSvc
Pointer to incident service.
Definition: DataSvc.h:54
StatusCode findObject(const std::string &fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition: DataSvc.cpp:828
T erase(T...args)
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:225
void setDataSvc(IDataProviderSvc *s)
Set the transient data store.
Definition: RegistryEntry.h:87
StatusCode unregisterAddress(const std::string &fullPath) override
IDataManagerSvc: Unregister object address from the data store.
Definition: DataSvc.cpp:307
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
StatusCode finalize() override
Service initialization.
Definition: DataSvc.cpp:1188
virtual bool isEmpty() const
Simple check if the Container is empty.
StatusCode reinitialize() override
Definition: Service.cpp:250
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
StatusCode clearSubTree(const std::string &sub_tree_path) override
IDataManagerSvc: Remove all data objects below the sub tree identified by its full path name...
Definition: DataSvc.cpp:76
IOpaqueAddress * address() const override
Retrieve opaque storage address.
StatusCode retrieveObject(IRegistry *pDirectory, const std::string &path, DataObject *&pObject) override
Retrieve object from data store.
Definition: DataSvc.cpp:763
STL class.
T move(T...args)
StatusCode linkObject(IRegistry *from, const std::string &objPath, DataObject *to) override
Add a link to another object.
Definition: DataSvc.cpp:966
#define CAST_REGENTRY(x, y)
Definition: DataSvc.cpp:63
virtual DataObject * object() const =0
Retrieve object behind the link.
Definition of an entry in the transient data store.
Definition: RegistryEntry.h:36
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:56
Gaudi::Property< std::vector< std::string > > m_inhibitPathes
Definition: DataSvc.h:59
T find(T...args)
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:164
DataObject * handleDataFault(IRegistry *pReg, const std::string &path="")
Invoke data fault handling if enabled.
Definition: DataSvc.cpp:546
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject)=0
Resolve the references of the created transient object.
StatusCode reinitialize() override
Service initialization.
Definition: DataSvc.cpp:1165
SmartIF< IConversionSvc > m_dataLoader
Pointer to data loader service.
Definition: DataSvc.h:52
virtual IRegistry * parent() const
Pointer to parent directory entry.
Generic data agent interface.
StatusCode initialize() override
Service initialization.
Definition: DataSvc.cpp:1153
T begin(T...args)
StatusCode unlinkObject(IRegistry *from, const std::string &objPath) override
Remove a link to another object.
Definition: DataSvc.cpp:1035
string s
Definition: gaudirun.py:245
Gaudi::Property< bool > m_enableAccessHdlr
Definition: DataSvc.h:65
const std::string & name() const
Retreive DataObject name. It is the name when registered in the store.
Definition: DataObject.cpp:78
const std::string & rootName() const override
IDataManagerSvc: Accessor for root event name.
Definition: DataSvc.cpp:1203
T substr(T...args)
StatusCode objectParent(const DataObject *pObject, IRegistry *&refpParent) override
IDataManagerSvc: Explore the object store: retrieve the object&#39;s parent.
Definition: DataSvc.cpp:209
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn&#39;t already exist.
Definition: Service.h:85
const std::string & identifier() const override
Full identifier (or key)
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:88
Data service incident class.
Opaque address interface definition.
void ignore() const
Definition: StatusCode.h:106
virtual IConversionSvc * getDataLoader(IRegistry *pReg)
Retrieve customizable data loader according to registry entry to be retrieved.
Definition: DataSvc.cpp:1215
StatusCode traverseSubTree(const std::string &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:126
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
StatusCode updateObject(IRegistry *pDirectory) override
Update object identified by its directory entry.
Definition: DataSvc.cpp:884
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
StatusCode resetPreLoad() override
Clear the preload list.
Definition: DataSvc.cpp:1116
#define ON_VERBOSE
Definition: DataSvc.cpp:68
virtual DataObject * createDefaultObject() const
Create default objects in case forced creation of leaves is requested.
Definition: DataSvc.cpp:1208
virtual IRegistry * find(const IRegistry *obj) const
Try to find an object identified by its pointer.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition: DataSvc.cpp:114
T compare(T...args)
DataSvcHelpers::RegistryEntry RegEntry
Definition: DataSvc.cpp:65
void makeHard(DataObject *pObject)
Initialize link as hard link.