Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
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 }