The Gaudi Framework  v29r0 (ff2e7097)
RootIOHandler.cpp
Go to the documentation of this file.
1 //====================================================================
2 //
3 // Package : RootCnv
4 //
5 // Description: Generate TClassStreamers for special Gaudi classes
6 // @author M.Frank
7 //====================================================================
10 #include "GaudiKernel/MsgStream.h"
12 #include "GaudiKernel/SmartRef.h"
13 #include "GaudiKernel/System.h"
14 #include "RootCnv/PoolClasses.h"
15 #include "RootCnv/RootRefs.h"
16 #include "TClass.h"
17 #include "TClassStreamer.h"
18 #include "TInterpreter.h"
19 #include "TROOT.h"
20 #include "TSystem.h"
21 #include <iostream>
22 #include <memory>
23 #include <stdexcept>
24 
25 using namespace std;
26 
27 namespace GaudiRoot
28 {
29  static const DataObject* last_link_object = nullptr;
30  static int last_link_hint = -1;
32  {
33  last_link_object = nullptr;
34  last_link_hint = -1;
35  }
36  void pushCurrentDataObject( DataObject** pobjAddr )
37  {
38  Gaudi::pushCurrentDataObject( pobjAddr );
39  resetLastLink();
40  }
42  {
44  resetLastLink();
45  }
46 
47  union RefAccessor {
48  void* Ptr;
52  RefAccessor( void* obj ) { Ptr = obj; }
53  };
54 
57  template <class T>
58  class IOHandler : public TClassStreamer
59  {
60  protected:
62  TClass* m_root;
63 
64  public:
66  IOHandler( TClass* c ) : m_root( c ) {}
68  ~IOHandler() override = default;
70  void operator()( TBuffer& b, void* obj ) override
71  {
72  try {
73  if ( b.IsReading() )
74  get( b, obj );
75  else
76  put( b, obj );
77  } catch ( const exception& e ) {
78  string err = "Class:" + string( m_root->GetName() ) + "> Exception in object I/O";
79  err += e.what();
80  throw runtime_error( err );
81  } catch ( ... ) {
82  string err = "Class:" + string( m_root->GetName() ) + "> Exception in object I/O";
83  throw runtime_error( err );
84  }
85  }
87  virtual void get( TBuffer& b, void* obj );
89  virtual void put( TBuffer& b, void* obj );
90  };
91 
92  template <>
93  void IOHandler<SmartRefBase>::get( TBuffer& b, void* obj )
94  {
95  RefAccessor r( obj );
96  UInt_t start, count;
97  Version_t version = b.ReadVersion( &start, &count, m_root );
98  m_root->ReadBuffer( b, obj, version, start, count );
99  switch ( r.Base->objectType() ) {
102  break;
105  break;
106  default:
107  cout << "Hit uninitialized smartRef!!!!" << endl;
108  break;
109  }
110  }
111 
112  template <>
113  void IOHandler<SmartRefBase>::put( TBuffer& b, void* obj )
114  {
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  {
173  UInt_t start, count;
174  Version_t version = b.ReadVersion( &start, &count, m_root );
175  m_root->ReadBuffer( b, obj, version, start, count );
176  ContainedObject* p = (ContainedObject*)obj;
178  }
179 
180  template <>
181  void IOHandler<ContainedObject>::put( TBuffer& b, void* obj )
182  {
183  m_root->WriteBuffer( b, obj );
184  }
185 
186  template <>
187  void IOHandler<pool::Token>::get( TBuffer& b, void* obj )
188  {
189  UInt_t start, count;
190  pool::Token* t = (pool::Token*)obj;
191  b.ReadVersion( &start, &count, m_root );
192  b.ReadFastArray( &t->m_oid.first, 2 );
193  b.CheckByteCount( start, count, m_root );
194  }
195 
196  template <>
197  void IOHandler<pool::Token>::put( TBuffer&, void* )
198  {
199  throw runtime_error( "Writing POOL files is not implemented!" );
200  }
201 
202  template <class T>
203  static bool makeStreamer( MsgStream& log )
204  {
205  string cl_name = System::typeinfoName( typeid( T ) );
206  TClass* c = gROOT->GetClass( cl_name.c_str() );
207  if ( c ) {
208  c->AdoptStreamer( new IOHandler<T>( c ) );
209  log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
210  return true;
211  }
212  log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
213  return false;
214  }
215 
217  {
218  static bool first = true;
219  if ( first ) {
220  first = false;
221 #if ROOT_VERSION_CODE < ROOT_VERSION( 5, 99, 0 )
222  gSystem->Load( "libCintex" );
223  gROOT->ProcessLine( "Cintex::Cintex::Enable()" );
224  gROOT->ProcessLine( "#include <vector>" );
225  gInterpreter->EnableAutoLoading();
226  gInterpreter->AutoLoad( "DataObject" );
227  gInterpreter->AutoLoad( "PoolDbLinkManager" );
228  gSystem->Load( "libGaudiKernelDict" );
229  gSystem->Load( "libGaudiExamplesDict" );
230 #else
231  gInterpreter->EnableAutoLoading();
232  gInterpreter->AutoLoad( "DataObject" );
233  gInterpreter->AutoLoad( "PoolDbLinkManager" );
234 #endif
235 
236  bool b1 = makeStreamer<SmartRefBase>( s );
237  bool b2 = makeStreamer<ContainedObject>( s );
238  bool b3 = makeStreamer<pool::Token>( s );
239  return b1 && b2 && b3;
240  }
241  return true;
242  }
243 }
IOHandler(TClass *c)
Initializing constructor.
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
void popCurrentDataObject()
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:329
GAUDI_API void popCurrentDataObject()
GAUDI_API DataObject * getCurrentDataObject()
T log(T...args)
void pushCurrentDataObject(DataObject **pobjAddr)
T endl(T...args)
virtual long index() const
Distance in the parent container.
STL namespace.
bool patchStreamers(MsgStream &log)
User example objects: SmartRefBase.
Definition: SmartRefBase.h:47
TClass * m_root
ROOT persistent class description.
const ObjectContainerBase * parent() const
Access to parent object.
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:72
LinkManager * linkMgr() const
Retrieve Link manager.
Definition: DataObject.h:74
STL class.
std::pair< int, int > m_oid
Object global identifier.
Definition: PoolClasses.h:34
Shadow class to mimik POOL tokens.
Definition: PoolClasses.h:26
virtual const id_type & identifier() const =0
Full identifier (or key)
T what(T...args)
void operator()(TBuffer &b, void *obj) override
ROOT I/O callback.
start
Definition: IOTest.py:99
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
GAUDI_API void pushCurrentDataObject(DataObject **pobjAddr)
STL class.
T count(T...args)
All classes that their objects may be contained in an LHCb ObjectContainer (e.g.
T c_str(T...args)
void setParent(ObjectContainerBase *value)
Update parent member.
string s
Definition: gaudirun.py:253
SmartRef< DataObject > * ObjectRef
ObjectContainerBase is the base class for Gaudi container classes.
void set(DataObject *pObj, long hint_id, long link_id)
Setup smart reference when reading. Must be allowed from external sources.
void resetLastLink()
SmartRef< ContainedObject > * ContainedRef
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:29
int objectType() const
Definition: SmartRefBase.h:110
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
Out1 * put(DataObjectHandle< Out1 > &out_handle, Out2 &&out)