The Gaudi Framework  v33r0 (d5ea422b)
RootIOHandler.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 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( "libGaudiExamplesDict" );
224 #else
225  gInterpreter->EnableAutoLoading();
226  gInterpreter->AutoLoad( "DataObject" );
227  gInterpreter->AutoLoad( "PoolDbLinkManager" );
228 #endif
229 
230  bool b1 = makeStreamer<SmartRefBase>( s );
231  bool b2 = makeStreamer<ContainedObject>( s );
232  bool b3 = makeStreamer<pool::Token>( s );
233  return b1 && b2 && b3;
234  }
235  return true;
236  }
237 } // namespace GaudiRoot
IOHandler(TClass *c)
Initializing constructor.
Out1 * put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:34
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:82
void popCurrentDataObject()
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
GAUDI_API void popCurrentDataObject()
GAUDI_API DataObject * getCurrentDataObject()
LinkManager * linkMgr() const
Retrieve Link manager.
Definition: DataObject.h:84
T log(T... args)
void pushCurrentDataObject(DataObject **pobjAddr)
T endl(T... args)
STL namespace.
bool patchStreamers(MsgStream &log)
User example objects: SmartRefBase.
Definition: SmartRefBase.h:57
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
TClass * m_root
ROOT persistent class description.
def start
Definition: IOTest.py:108
STL class.
std::pair< int, int > m_oid
Object global identifier.
Definition: PoolClasses.h:41
Shadow class to mimik POOL tokens.
Definition: PoolClasses.h:34
T what(T... args)
void operator()(TBuffer &b, void *obj) override
ROOT I/O callback.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:32
GAUDI_API void pushCurrentDataObject(DataObject **pobjAddr)
STL class.
T count(T... args)
virtual long index() const
Distance in the parent container.
int objectType() const
Definition: SmartRefBase.h:114
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:328
SmartRef< DataObject > * ObjectRef
const ObjectContainerBase * parent() const
Access to parent object.
virtual const id_type & identifier() const =0
Full identifier (or key)
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:40
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202