The Gaudi Framework  master (37c0b60a)
RootIOHandler.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 //====================================================================
12 //
13 // Package : RootCnv
14 //
15 // Description: Generate TClassStreamers for special Gaudi classes
16 // @author M.Frank
17 //====================================================================
18 #include <GaudiKernel/IRegistry.h>
20 #include <GaudiKernel/MsgStream.h>
22 #include <GaudiKernel/SmartRef.h>
23 #include <GaudiKernel/System.h>
24 #include <RootCnv/PoolClasses.h>
25 #include <RootCnv/RootRefs.h>
26 #include <TClass.h>
27 #include <TClassStreamer.h>
28 #include <TInterpreter.h>
29 #include <TROOT.h>
30 #include <TSystem.h>
31 #include <iostream>
32 #include <memory>
33 #include <stdexcept>
34 
35 using namespace std;
36 
37 namespace GaudiRoot {
38  static const DataObject* last_link_object = nullptr;
39  static int last_link_hint = -1;
40  void resetLastLink() {
41  last_link_object = nullptr;
42  last_link_hint = -1;
43  }
44  void pushCurrentDataObject( DataObject** pobjAddr ) {
45  Gaudi::pushCurrentDataObject( pobjAddr );
46  resetLastLink();
47  }
50  resetLastLink();
51  }
52 
53  union RefAccessor {
54  void* Ptr;
58  RefAccessor( void* obj ) { Ptr = obj; }
59  };
60 
63  template <class T>
64  class IOHandler : public TClassStreamer {
65  protected:
67  TClass* m_root;
68 
69  public:
71  IOHandler( TClass* c ) : m_root( c ) {}
73  void operator()( TBuffer& b, void* obj ) override {
74  try {
75  if ( b.IsReading() )
76  get( b, obj );
77  else
78  put( b, obj );
79  } catch ( const exception& e ) {
80  string err = "Class:" + string( m_root->GetName() ) + "> Exception in object I/O";
81  err += e.what();
82  throw runtime_error( err );
83  } catch ( ... ) {
84  string err = "Class:" + string( m_root->GetName() ) + "> Exception in object I/O";
85  throw runtime_error( err );
86  }
87  }
89  virtual void get( TBuffer& b, void* obj );
91  virtual void put( TBuffer& b, void* obj );
92  };
93 
94  template <>
95  void IOHandler<SmartRefBase>::get( TBuffer& b, void* obj ) {
96  RefAccessor r( obj );
97  UInt_t start, count;
98  Version_t version = b.ReadVersion( &start, &count, m_root );
99  m_root->ReadBuffer( b, obj, version, start, count );
100  switch ( r.Base->objectType() ) {
103  break;
106  break;
107  default:
108  cout << "Hit uninitialized smartRef!!!!" << endl;
109  break;
110  }
111  }
112 
113  template <>
114  void IOHandler<SmartRefBase>::put( TBuffer& b, void* obj ) {
115  RefAccessor r( obj );
116  ContainedObject* p;
117  DataObject * curr, *pDO;
118  int hint, link;
119 
121  pDO = r.ObjectRef->data();
122  hint = r.ObjectRef->hintID();
123  link = r.ObjectRef->linkID();
124  if ( pDO ) {
125  switch ( r.Base->objectType() ) {
127  p = r.ContainedRef->data();
128  if ( p ) {
129  const ObjectContainerBase* parent = p->parent();
130  if ( parent ) {
131  link = p->index();
132  pDO = const_cast<ObjectContainerBase*>( parent );
133  break;
134  }
135  }
136  pDO = nullptr;
137  cout << "IOHandler<SmartRefBase>::onWrite> "
138  << "Found invalid smart reference with object "
139  << "having no parent." << endl;
140  throw runtime_error( "IOHandler<SmartRefBase>::onWrite> "
141  "Found invalid smart reference with object "
142  "having no parent." );
143  break;
145  link = StreamBuffer::INVALID;
146  break;
147  default:
148  break;
149  }
150  if ( pDO == last_link_object ) {
151  r.Base->set( curr, last_link_hint, link );
152  m_root->WriteBuffer( b, obj );
153  return;
154  } else if ( pDO ) {
155  LinkManager* mgr = curr->linkMgr();
156  IRegistry* reg = pDO->registry();
157  if ( reg && mgr ) {
158  hint = mgr->addLink( reg->identifier(), pDO );
159  last_link_hint = hint;
160  last_link_object = pDO;
161  }
162  } else {
163  hint = link = StreamBuffer::INVALID;
164  }
165  }
166  r.Base->set( curr, hint, link );
167  m_root->WriteBuffer( b, obj );
168  }
169 
170  template <>
171  void IOHandler<ContainedObject>::get( TBuffer& b, void* obj ) {
172  UInt_t start, count;
173  Version_t version = b.ReadVersion( &start, &count, m_root );
174  m_root->ReadBuffer( b, obj, version, start, count );
175  ContainedObject* p = (ContainedObject*)obj;
177  }
178 
179  template <>
180  void IOHandler<ContainedObject>::put( TBuffer& b, void* obj ) {
181  m_root->WriteBuffer( b, obj );
182  }
183 
184  template <>
185  void IOHandler<pool::Token>::get( TBuffer& b, void* obj ) {
186  UInt_t start, count;
187  pool::Token* t = (pool::Token*)obj;
188  b.ReadVersion( &start, &count, m_root );
189  b.ReadFastArray( &t->m_oid.first, 2 );
190  b.CheckByteCount( start, count, m_root );
191  }
192 
193  template <>
194  void IOHandler<pool::Token>::put( TBuffer&, void* ) {
195  throw runtime_error( "Writing POOL files is not implemented!" );
196  }
197 
198  template <class T>
199  static bool makeStreamer( MsgStream& log ) {
200  string cl_name = System::typeinfoName( typeid( T ) );
201  TClass* c = gROOT->GetClass( cl_name.c_str() );
202  if ( c ) {
203  c->AdoptStreamer( new IOHandler<T>( c ) );
204  log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
205  return true;
206  }
207  log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
208  return false;
209  }
210 
212  static bool first = true;
213  if ( first ) {
214  first = false;
215 #if ROOT_VERSION_CODE < ROOT_VERSION( 5, 99, 0 )
216  gSystem->Load( "libCintex" );
217  gROOT->ProcessLine( "Cintex::Cintex::Enable()" );
218  gROOT->ProcessLine( "#include <vector>" );
219  gInterpreter->EnableAutoLoading();
220  gInterpreter->AutoLoad( "DataObject" );
221  gInterpreter->AutoLoad( "PoolDbLinkManager" );
222  gSystem->Load( "libGaudiKernelDict" );
223  gSystem->Load( "libGaudiTestSuiteDict" );
224 #else
225 # if ROOT_VERSION_CODE < ROOT_VERSION( 6, 19, 0 )
226  gInterpreter->EnableAutoLoading();
227 # else
228  gInterpreter->LoadLibraryMap();
229 # endif
230  gInterpreter->AutoLoad( "DataObject" );
231  gInterpreter->AutoLoad( "PoolDbLinkManager" );
232 #endif
233 
234  bool b1 = makeStreamer<SmartRefBase>( s );
235  bool b2 = makeStreamer<ContainedObject>( s );
236  bool b3 = makeStreamer<pool::Token>( s );
237  return b1 && b2 && b3;
238  }
239  return true;
240  }
241 } // namespace GaudiRoot
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
GaudiRoot::RefAccessor::Base
SmartRefBase * Base
Definition: RootIOHandler.cpp:55
GaudiRoot
Definition: RootCnvSvc.cpp:49
std::string
STL class.
std::exception
STL class.
System.h
gaudirun.s
string s
Definition: gaudirun.py:346
SmartRefBase::CONTAINEDOBJECT
@ CONTAINEDOBJECT
Definition: SmartRefBase.h:70
GaudiPartProp.decorators.get
get
decorate the vector of properties
Definition: decorators.py:283
Gaudi::popCurrentDataObject
GAUDI_API void popCurrentDataObject()
GaudiRoot::IOHandler::put
virtual void put(TBuffer &b, void *obj)
Callback for writing the object.
gaudirun.c
c
Definition: gaudirun.py:525
IRegistry
Definition: IRegistry.h:32
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:315
IOTest.start
start
Definition: IOTest.py:110
Gaudi::getCurrentDataObject
GAUDI_API DataObject * getCurrentDataObject()
GaudiRoot::RefAccessor::RefAccessor
RefAccessor(void *obj)
Definition: RootIOHandler.cpp:58
GaudiRoot::IOHandler
Definition: RootIOHandler.cpp:64
SmartRefBase
User example objects: SmartRefBase.
Definition: SmartRefBase.h:57
bug_34121.t
t
Definition: bug_34121.py:31
GaudiRoot::popCurrentDataObject
void popCurrentDataObject()
Definition: RootIOHandler.cpp:48
CFinViewTest.b2
b2
Definition: CFinViewTest.py:99
std::log
T log(T... args)
GaudiRoot::RefAccessor::ObjectRef
SmartRef< DataObject > * ObjectRef
Definition: RootIOHandler.cpp:56
std::cout
conf.version
string version
Definition: conf.py:25
SmartRefBase::DATAOBJECT
@ DATAOBJECT
Definition: SmartRefBase.h:70
std::string::c_str
T c_str(T... args)
GaudiRoot::patchStreamers
bool patchStreamers(MsgStream &log)
Definition: RootIOHandler.cpp:211
GaudiRoot::IOHandler::IOHandler
IOHandler(TClass *c)
Initializing constructor.
Definition: RootIOHandler.cpp:71
std::runtime_error
STL class.
SmartRefBase::set
void set(DataObject *pObj, long hint_id, long link_id)
Setup smart reference when reading. Must be allowed from external sources.
Definition: SmartRefBase.cpp:36
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
ContainedObject::index
virtual long index() const
Distance in the parent container.
Definition: ContainedObject.h:68
GaudiRoot::pushCurrentDataObject
void pushCurrentDataObject(DataObject **pobjAddr)
Definition: RootIOHandler.cpp:44
IRegistry.h
MsgStream
Definition: MsgStream.h:33
GaudiRoot::RefAccessor::Ptr
void * Ptr
Definition: RootIOHandler.cpp:54
SmartRefBase::objectType
long objectType() const
Definition: SmartRefBase.h:114
SmartRef.h
GaudiRoot::resetLastLink
void resetLastLink()
Definition: RootIOHandler.cpp:40
ContainedObject::parent
const ObjectContainerBase * parent() const
Access to parent object.
Definition: ContainedObject.h:63
GaudiRoot::IOHandler::m_root
TClass * m_root
ROOT persistent class description.
Definition: RootIOHandler.cpp:67
Gaudi::pushCurrentDataObject
GAUDI_API void pushCurrentDataObject(DataObject **pobjAddr)
std::endl
T endl(T... args)
RootRefs.h
ContainedObject::setParent
void setParent(ObjectContainerBase *value)
Update parent member.
Definition: ContainedObject.h:65
ObjectContainerBase
Definition: ObjectContainerBase.h:29
std
STL namespace.
MSG::ERROR
@ ERROR
Definition: IMessageSvc.h:25
GaudiRoot::IOHandler::operator()
void operator()(TBuffer &b, void *obj) override
ROOT I/O callback.
Definition: RootIOHandler.cpp:73
GaudiRoot::RefAccessor
Definition: RootIOHandler.cpp:53
IRegistry::identifier
virtual const id_type & identifier() const =0
Full identifier (or key)
DataObject
Definition: DataObject.h:36
std::count
T count(T... args)
ObjectContainerBase.h
CFinViewTest.b1
b1
Definition: CFinViewTest.py:96
SmartRef< DataObject >
GaudiRoot::IOHandler::get
virtual void get(TBuffer &b, void *obj)
Callback for reading the object.
pool::Token
Definition: PoolClasses.h:34
PoolClasses.h
DataObject::linkMgr
LinkManager * linkMgr()
Retrieve Link manager.
Definition: DataObject.h:80
GaudiRoot::RefAccessor::ContainedRef
SmartRef< ContainedObject > * ContainedRef
Definition: RootIOHandler.cpp:57
DataObject::registry
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:78
ContainedObject
Definition: ContainedObject.h:41
std::exception::what
T what(T... args)
Gaudi::Functional::details::put
auto put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Definition: details.h:168
MsgStream.h
StreamBuffer::INVALID
@ INVALID
Definition: StreamBuffer.h:121