The Gaudi Framework  v30r3 (a5ef0a68)
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  void operator()( TBuffer& b, void* obj ) override
69  {
70  try {
71  if ( b.IsReading() )
72  get( b, obj );
73  else
74  put( b, obj );
75  } catch ( const exception& e ) {
76  string err = "Class:" + string( m_root->GetName() ) + "> Exception in object I/O";
77  err += e.what();
78  throw runtime_error( err );
79  } catch ( ... ) {
80  string err = "Class:" + string( m_root->GetName() ) + "> Exception in object I/O";
81  throw runtime_error( err );
82  }
83  }
85  virtual void get( TBuffer& b, void* obj );
87  virtual void put( TBuffer& b, void* obj );
88  };
89 
90  template <>
91  void IOHandler<SmartRefBase>::get( TBuffer& b, void* obj )
92  {
93  RefAccessor r( obj );
94  UInt_t start, count;
95  Version_t version = b.ReadVersion( &start, &count, m_root );
96  m_root->ReadBuffer( b, obj, version, start, count );
97  switch ( r.Base->objectType() ) {
100  break;
103  break;
104  default:
105  cout << "Hit uninitialized smartRef!!!!" << endl;
106  break;
107  }
108  }
109 
110  template <>
111  void IOHandler<SmartRefBase>::put( TBuffer& b, void* obj )
112  {
113  RefAccessor r( obj );
114  ContainedObject* p;
115  DataObject * curr, *pDO;
116  int hint, link;
117 
119  pDO = r.ObjectRef->data();
120  hint = r.ObjectRef->hintID();
121  link = r.ObjectRef->linkID();
122  if ( pDO ) {
123  switch ( r.Base->objectType() ) {
125  p = r.ContainedRef->data();
126  if ( p ) {
127  const ObjectContainerBase* parent = p->parent();
128  if ( parent ) {
129  link = p->index();
130  pDO = const_cast<ObjectContainerBase*>( parent );
131  break;
132  }
133  }
134  pDO = nullptr;
135  cout << "IOHandler<SmartRefBase>::onWrite> "
136  << "Found invalid smart reference with object "
137  << "having no parent." << endl;
138  throw runtime_error( "IOHandler<SmartRefBase>::onWrite> "
139  "Found invalid smart reference with object "
140  "having no parent." );
141  break;
143  link = StreamBuffer::INVALID;
144  break;
145  default:
146  break;
147  }
148  if ( pDO == last_link_object ) {
149  r.Base->set( curr, last_link_hint, link );
150  m_root->WriteBuffer( b, obj );
151  return;
152  } else if ( pDO ) {
153  LinkManager* mgr = curr->linkMgr();
154  IRegistry* reg = pDO->registry();
155  if ( reg && mgr ) {
156  hint = mgr->addLink( reg->identifier(), pDO );
157  last_link_hint = hint;
158  last_link_object = pDO;
159  }
160  } else {
161  hint = link = StreamBuffer::INVALID;
162  }
163  }
164  r.Base->set( curr, hint, link );
165  m_root->WriteBuffer( b, obj );
166  }
167 
168  template <>
169  void IOHandler<ContainedObject>::get( TBuffer& b, void* obj )
170  {
171  UInt_t start, count;
172  Version_t version = b.ReadVersion( &start, &count, m_root );
173  m_root->ReadBuffer( b, obj, version, start, count );
174  ContainedObject* p = (ContainedObject*)obj;
176  }
177 
178  template <>
179  void IOHandler<ContainedObject>::put( TBuffer& b, void* obj )
180  {
181  m_root->WriteBuffer( b, obj );
182  }
183 
184  template <>
185  void IOHandler<pool::Token>::get( TBuffer& b, void* obj )
186  {
187  UInt_t start, count;
188  pool::Token* t = (pool::Token*)obj;
189  b.ReadVersion( &start, &count, m_root );
190  b.ReadFastArray( &t->m_oid.first, 2 );
191  b.CheckByteCount( start, count, m_root );
192  }
193 
194  template <>
195  void IOHandler<pool::Token>::put( TBuffer&, void* )
196  {
197  throw runtime_error( "Writing POOL files is not implemented!" );
198  }
199 
200  template <class T>
201  static bool makeStreamer( MsgStream& log )
202  {
203  string cl_name = System::typeinfoName( typeid( T ) );
204  TClass* c = gROOT->GetClass( cl_name.c_str() );
205  if ( c ) {
206  c->AdoptStreamer( new IOHandler<T>( c ) );
207  log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
208  return true;
209  }
210  log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
211  return false;
212  }
213 
215  {
216  static bool first = true;
217  if ( first ) {
218  first = false;
219 #if ROOT_VERSION_CODE < ROOT_VERSION( 5, 99, 0 )
220  gSystem->Load( "libCintex" );
221  gROOT->ProcessLine( "Cintex::Cintex::Enable()" );
222  gROOT->ProcessLine( "#include <vector>" );
223  gInterpreter->EnableAutoLoading();
224  gInterpreter->AutoLoad( "DataObject" );
225  gInterpreter->AutoLoad( "PoolDbLinkManager" );
226  gSystem->Load( "libGaudiKernelDict" );
227  gSystem->Load( "libGaudiExamplesDict" );
228 #else
229  gInterpreter->EnableAutoLoading();
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 }
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:332
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:73
LinkManager * linkMgr() const
Retrieve Link manager.
Definition: DataObject.h:75
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:30
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)