Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

RootIOHandler.cpp

Go to the documentation of this file.
00001 // $Id: RootIOHandler.cpp,v 1.3 2010-09-27 15:43:53 frankb Exp $
00002 //====================================================================
00003 //
00004 //  Package    : RootCnv
00005 //
00006 //  Description: Generate TClassStreamers for special Gaudi classes
00007 //  @author      M.Frank
00008 //====================================================================
00009 #include "GaudiKernel/ObjectContainerBase.h"
00010 #include "GaudiKernel/LinkManager.h"
00011 #include "GaudiKernel/IRegistry.h"
00012 #include "GaudiKernel/MsgStream.h"
00013 #include "GaudiKernel/SmartRef.h"
00014 #include "GaudiKernel/System.h"
00015 #include "RootCnv/RootRefs.h"
00016 #include "PoolClasses.h"
00017 #include <stdexcept>
00018 #include <iostream>
00019 #include "TROOT.h"
00020 #include "TClass.h"
00021 #include "TSystem.h"
00022 #include "TInterpreter.h"
00023 #include "TClassStreamer.h"
00024 #include <memory>
00025 
00026 using namespace std;
00027 
00028 namespace GaudiRoot {
00029   static const DataObject* last_link_object = 0;
00030   static int               last_link_hint = -1;
00031   void resetLastLink() {
00032     last_link_object = 0;
00033     last_link_hint   = -1;
00034   }
00035   void pushCurrentDataObject(DataObject** pobjAddr) {
00036     Gaudi::pushCurrentDataObject(pobjAddr);
00037     resetLastLink();
00038   }
00039   void popCurrentDataObject() {
00040     Gaudi::popCurrentDataObject();
00041     resetLastLink();
00042   }
00043 
00044   union RefAccessor {
00045     void*                       Ptr;
00046     SmartRefBase*               Base;
00047     SmartRef<DataObject>*       ObjectRef;
00048     SmartRef<ContainedObject>*  ContainedRef;
00049     RefAccessor(void* obj) { Ptr = obj; }
00050   };
00051 
00054   template <class T> class IOHandler : public TClassStreamer {
00055   protected:
00057     TClass*   m_root;
00058   public:
00060     IOHandler(TClass* c) : m_root(c) {  }
00062     virtual ~IOHandler() {  }
00064     virtual void operator()(TBuffer &b, void *obj)  {
00065       try {
00066         if ( b.IsReading() ) 
00067           get(b,obj);
00068         else
00069           put(b,obj);
00070       }
00071       catch( const exception& e )    {
00072         string err = "Class:" + string(m_root->GetName()) + "> Exception in object I/O";
00073         err += e.what();
00074         throw runtime_error(err);
00075       }
00076       catch( ... )    {
00077         string err = "Class:" + string(m_root->GetName()) + "> Exception in object I/O";
00078         throw runtime_error(err);
00079       }
00080     }
00082     virtual void get(TBuffer &b, void* obj);
00084     virtual void put(TBuffer &b, void* obj);
00085   };
00086 
00087   template <> void IOHandler<SmartRefBase>::get(TBuffer &b, void* obj) {
00088     RefAccessor r(obj);
00089     UInt_t start, count;
00090     Version_t version = b.ReadVersion(&start, &count, m_root);
00091     m_root->ReadBuffer(b, obj, version, start, count);
00092     switch( r.Base->objectType() ) {
00093     case SmartRefBase::DATAOBJECT:
00094       (*r.ObjectRef)(Gaudi::getCurrentDataObject());
00095       break;
00096     case SmartRefBase::CONTAINEDOBJECT:
00097       (*r.ContainedRef)(Gaudi::getCurrentDataObject());
00098       break;
00099     default:
00100       cout << "Hit uninitialized smartRef!!!!" << endl;
00101       break;
00102     }
00103   }
00104 
00105   template <> void IOHandler<SmartRefBase>::put(TBuffer &b, void* obj) {
00106     RefAccessor r(obj);
00107     ContainedObject* p;
00108     DataObject* curr, *pDO;
00109     int hint, link;
00110 
00111     curr = Gaudi::getCurrentDataObject();
00112     pDO  = r.ObjectRef->data();
00113     hint = r.ObjectRef->hintID();
00114     link = r.ObjectRef->linkID();
00115     if ( pDO )  {
00116       switch( r.Base->objectType() ) {
00117       case SmartRefBase::CONTAINEDOBJECT:
00118         p = r.ContainedRef->data();
00119         if ( p )  {
00120           const ObjectContainerBase* parent = p->parent();
00121           if ( parent )  {
00122             link = p->index();
00123             pDO  = const_cast<ObjectContainerBase*>(parent);
00124             break;
00125           }
00126         }
00127         pDO = 0;
00128         cout << "IOHandler<SmartRefBase>::onWrite> "
00129           << "Found invalid smart reference with object "
00130           << "having no parent."
00131           << endl;
00132         throw runtime_error("IOHandler<SmartRefBase>::onWrite> "
00133           "Found invalid smart reference with object "
00134           "having no parent.");
00135         break;
00136       case SmartRefBase::DATAOBJECT:
00137         link = StreamBuffer::INVALID;
00138         break;
00139       default:
00140         break;
00141       }
00142       if ( pDO == last_link_object )  {
00143         r.Base->set(curr, last_link_hint, link);
00144         m_root->WriteBuffer(b, obj);
00145         return;
00146       }
00147       else if ( pDO ) {
00148         LinkManager* mgr = curr->linkMgr();
00149         IRegistry*   reg = pDO->registry();
00150         if ( reg && mgr )  {
00151           hint = mgr->addLink(reg->identifier(), pDO);
00152           last_link_hint   = hint;
00153           last_link_object = pDO;
00154         }
00155       }
00156       else {
00157         hint = link = StreamBuffer::INVALID;
00158       }
00159     }
00160     r.Base->set(curr, hint, link);
00161     m_root->WriteBuffer(b, obj);
00162   }
00163 
00164   template <> void IOHandler<ContainedObject>::get(TBuffer &b, void* obj) {
00165     UInt_t start, count;
00166     Version_t version = b.ReadVersion(&start, &count, m_root);
00167     m_root->ReadBuffer(b, obj, version, start, count);
00168     ContainedObject* p = (ContainedObject*)obj;
00169     p->setParent((ObjectContainerBase*)Gaudi::getCurrentDataObject());
00170   }
00171 
00172   template <> void IOHandler<ContainedObject>::put(TBuffer &b, void* obj) {
00173     m_root->WriteBuffer(b, obj);
00174   }
00175 
00176   template <> void IOHandler<pool::Token>::get(TBuffer &b, void* obj) {
00177     UInt_t start, count;
00178     pool::Token* t = (pool::Token*)obj;
00179     b.ReadVersion(&start, &count, m_root);
00180     b.ReadFastArray(&t->m_oid.first, 2);
00181     b.CheckByteCount(start, count, m_root);
00182   }
00183 
00184   template <> void IOHandler<pool::Token>::put(TBuffer &, void* ) {
00185     throw runtime_error("Writing POOL files is not implemented!");
00186   }
00187 
00188   template <class T> static bool makeStreamer(MsgStream& log)  {
00189     string cl_name = System::typeinfoName(typeid(T));
00190     TClass* c = gROOT->GetClass(cl_name.c_str());
00191     if ( c ) {
00192       TClassStreamer* s = new IOHandler<T>(c);
00193       c->AdoptStreamer(s);
00194       log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
00195       return true;
00196     }
00197     log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
00198     return false;
00199   }
00200 
00201   bool patchStreamers(MsgStream& s)  {
00202     static bool first = true;
00203     if ( first ) {
00204       first = false;
00205       gSystem->Load("libCintex");
00206       gROOT->ProcessLine("Cintex::Cintex::Enable()");
00207       gROOT->ProcessLine("#include <vector>");
00208       gInterpreter->EnableAutoLoading();
00209       gInterpreter->AutoLoad("DataObject");
00210       gInterpreter->AutoLoad("PoolDbLinkManager");
00211       gSystem->Load("libGaudiKernelDict");
00212       gSystem->Load("libGaudiExamplesDict");
00213 
00214 
00215       bool b1 = makeStreamer<SmartRefBase>(s);
00216       bool b2 = makeStreamer<ContainedObject>(s);
00217       bool b3 = makeStreamer<pool::Token>(s);
00218       return b1 && b2 && b3;
00219     }
00220     return true;
00221   }
00222 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Thu Jun 28 2012 23:27:30 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004