Gaudi Framework, version v22r0

Home   Generated: 9 Feb 2011

PoolDbIOHandler.cpp

Go to the documentation of this file.
00001 // $Id: PoolDbIOHandler.cpp,v 1.13 2008/11/12 23:39:47 marcocle Exp $
00002 //====================================================================
00003 //
00004 //      Package    : System (The POOL project)
00005 //
00006 //  Description: Generate neccessary infrastructure for the
00007 //               SEAL plugin manager modules
00008 //
00009 //      @author      M.Frank
00010 //====================================================================
00011 #ifdef __ICC
00012 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
00013 //   TODO: To be removed, coming from ROOT
00014 #pragma warning(disable:2259)
00015 #endif
00016 
00017 #include "GaudiPoolDb/PoolDbIOHandler.h"
00018 #include "GaudiKernel/ObjectContainerBase.h"
00019 #include "GaudiKernel/ContainedObject.h"
00020 #include "GaudiKernel/LinkManager.h"
00021 #include "GaudiKernel/IRegistry.h"
00022 #include "GaudiKernel/MsgStream.h"
00023 #include "GaudiKernel/SmartRef.h"
00024 #include <stdexcept>
00025 #include <iostream>
00026 #include "TROOT.h"
00027 #include "TFile.h"
00028 #include "TClass.h"
00029 #include "TStreamerInfo.h"
00030 #include "Cintex/Cintex.h"
00031 #include "POOLCore/Token.h"
00032 #include "POOLCore/Reference.h"
00033 #include "StorageSvc/DbReflex.h"
00034 #include "StorageSvc/DataCallBack.h"
00035 #include "StorageSvc/DbDataHandlerGuard.h"
00036 
00037 #include <memory>
00038 
00039 using namespace pool;
00040 using namespace ROOT::Reflex;
00041 using namespace ROOT::Cintex;
00042 
00043 namespace ROOT { namespace Cintex  {
00044   bool IsTypeOf(Type& typ, const std::string& base_name);
00045 }}
00046 namespace pool  {
00047   const std::string typeName(const std::type_info& typ);
00048 }
00049 
00050 
00051 static const DataObject* last_link_object = 0;
00052 static int               last_link_hint = -1;
00053 
00054 void resetLastLink() {
00055   last_link_object = 0;
00056   last_link_hint   = -1;
00057 }
00058 
00059 using Gaudi::getCurrentDataObject;
00060 
00061 void pushCurrentDataObject(DataObject** pobjAddr) {
00062   Gaudi::pushCurrentDataObject(pobjAddr);
00063   resetLastLink();
00064 }
00065 
00066 void popCurrentDataObject() {
00067   Gaudi::popCurrentDataObject();
00068   resetLastLink();
00069 }
00070 
00071 
00072 template <class T>
00073 void PoolDbIOHandler<T>::operator()(TBuffer &b, void *obj)  {
00074   try {
00075     if ( b.IsReading() )   {
00076       get(b,obj);
00077     }
00078     else  {
00079       put(b,obj);
00080     }
00081   }
00082   catch( const std::exception& e )    {
00083     std::string err = "Class:" + std::string(m_root->GetName()) + "> Exception in object I/O";
00084     err += e.what();
00085     throw std::runtime_error(err);
00086   }
00087   catch( ... )    {
00088     std::string err = "Class:" + std::string(m_root->GetName()) + "> Exception in object I/O";
00089     throw std::runtime_error(err);
00090   }
00091 }
00092 
00093 template <>
00094 void PoolDbIOHandler<SmartRefBase>::get(TBuffer &b, void* obj) {
00095   UInt_t start, count;
00096   SmartRefBase* ref = (SmartRefBase*)obj;
00097   Version_t version = b.ReadVersion(&start, &count, m_root);
00098   m_root->ReadBuffer(b, obj, version, start, count);
00099   switch( ref->objectType() ) {
00100    case SmartRefBase::DATAOBJECT:
00101     {
00102       SmartRef<DataObject>* r = (SmartRef<DataObject>*)obj;
00103       (*r)(getCurrentDataObject());
00104     }
00105     break;
00106   case SmartRefBase::CONTAINEDOBJECT:
00107    {
00108      SmartRef<ContainedObject>* r = (SmartRef<ContainedObject>*)obj;
00109      (*r)(getCurrentDataObject());
00110    }
00111    break;
00112   default:
00113     std::cout << "Hit uninitialized smartRef!!!!" << std::endl;
00114     break;
00115   }
00116 }
00117 
00118 template <>
00119 void PoolDbIOHandler<SmartRefBase>::put(TBuffer &b, void* obj) {
00120   SmartRefBase* ref = (SmartRefBase*)obj;
00121   SmartRef<DataObject>* r1 = (SmartRef<DataObject>*)ref;
00122   DataObject* curr = getCurrentDataObject();
00123   DataObject* pDO  = r1->data();
00124   int hint = r1->hintID();
00125   int link = r1->linkID();
00126   if ( pDO )  {
00127     switch( ref->objectType() ) {
00128     case SmartRefBase::CONTAINEDOBJECT:
00129       {
00130         SmartRef<ContainedObject>* r2 = (SmartRef<ContainedObject>*)ref;
00131         ContainedObject* p = r2->data();
00132         if ( p )  {
00133           const ObjectContainerBase* parent = p->parent();
00134           if ( parent )  {
00135             link = p->index();
00136             pDO  = const_cast<ObjectContainerBase*>(parent);
00137             break;
00138           }
00139         }
00140       }
00141       pDO = 0;
00142       std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> "
00143                 << "Found invalid smart reference with object "
00144                 << "having no parent."
00145                 << std::endl;
00146       throw std::runtime_error("PoolDbIOHandler<SmartRefBase>::onWrite> "
00147                                "Found invalid smart reference with object "
00148                                "having no parent.");
00149       break;
00150     case SmartRefBase::DATAOBJECT:
00151       link = StreamBuffer::INVALID;
00152       break;
00153     default:
00154       break;
00155     }
00156     //if ( pDO == last_link_object && last_link_hint == -1 )  {
00157     //  std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> "
00158     //            << "Found invalid smart reference."
00159     //            << std::endl;
00160     //}
00161     if ( pDO == last_link_object )  {
00162       ref->set(curr, last_link_hint, link);
00163       m_root->WriteBuffer(b, obj);
00164       return;
00165     }
00166     else {
00167       LinkManager* mgr = curr->linkMgr();
00168       IRegistry*   reg = pDO->registry();
00169       if ( reg && mgr )  {
00170         hint = mgr->addLink(reg->identifier(), pDO);
00171         last_link_hint   = hint;
00172         last_link_object = pDO;
00173       }
00174     }
00175   }
00176   //if ( hint == StreamBuffer::INVALID )  {
00177   //  std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> "
00178   //            << "Found invalid smart reference."
00179   //            << std::endl;
00180   //}
00181   ref->set(curr, hint, link);
00182   m_root->WriteBuffer(b, obj);
00183 }
00184 
00185 template <>
00186 void PoolDbIOHandler<ContainedObject>::get(TBuffer &b, void* obj) {
00187   UInt_t start, count;
00188   Version_t version = b.ReadVersion(&start, &count, m_root);
00189   m_root->ReadBuffer(b, obj, version, start, count);
00190   ContainedObject* p = (ContainedObject*)obj;
00191   p->setParent((ObjectContainerBase*)getCurrentDataObject());
00192 }
00193 
00194 template <>
00195 void PoolDbIOHandler<ContainedObject>::put(TBuffer &b, void* obj) {
00196   m_root->WriteBuffer(b, obj);
00197 }
00198 
00199 static void getOID_40000(TBuffer& b, TClass* cl, Token::OID_t& oid) {
00200   unsigned long loid[2];
00201   UInt_t start, count, tmp;
00202   // read the class version from the buffer
00203   /* Version_t vsn = */ b.ReadVersion(&start, &count, 0);
00204   switch(count) {
00205   case 22:              // These tokens were written as pair<long,long>
00206     b >> tmp;           //
00207     b.ReadFastArray(loid,2); // There was a bug in POOL....
00208     oid.first = loid[0];
00209     oid.second = loid[1];
00210     break;              // see TBuffer::ReadFastArray(ulong*, int)
00211   case 14:              // Normal case: version:checksum+8 Bytes
00212     b >> tmp;           //
00213   case 10:              // Normal case: version:checksum+8 Bytes
00214   case 8:               // Without checksum and version
00215   default:              // No better idea
00216     b.ReadFastArray(&oid.first, 2);
00217     break;
00218   }
00219   // Check that the buffer position correesponds to the byte count
00220   b.CheckByteCount(start, count, cl);
00221 }
00222 
00223 template <>
00224 void PoolDbIOHandler<Token>::get(TBuffer& b, void* obj) {
00225   Token* t = (Token*)obj;
00226   DataCallBack* caller = DbDataHandlerGuard::caller();
00227   Int_t file_version = ((TFile*)b.GetParent())->GetVersion();
00228   if ( file_version >= 40000 ) {
00229     getOID_40000(b, m_root, t->oid());
00230   }
00231   else {
00232     UInt_t start, count, tmp;
00233     Version_t vsn = b.ReadVersion(&start, &count, m_root);
00234     switch(vsn)  {
00235     case 2:
00236       b >> tmp;
00237       b.ReadFastArray(&t->oid().first, 2);
00238       b >> tmp;
00239       break;
00240     default:
00241       b.SetBufferOffset(start+4);
00242       b.ReadFastArray(&t->oid().first, 2);
00243       break;
00244     }
00245   }
00246   if (caller) caller->notify(DataCallBack::GET,DataCallBack::TOKEN,m_type,obj,&t->oid());
00247 }
00248 
00249 template <>
00250 void PoolDbIOHandler<Token>::put(TBuffer &b, void* obj) {
00251   Token::OID_t* poid = &(((Token*)obj)->oid());
00252   UInt_t count = b.WriteVersion(m_root, true);
00253   DataCallBack* caller = DbDataHandlerGuard::caller();
00254   if (caller) caller->notify(DataCallBack::PUT,DataCallBack::TOKEN,m_type,obj,poid);
00255   b.WriteFastArray(&poid->first, 2);
00256   b.SetByteCount(count, true);
00257 }
00258 
00259 template <>
00260 void PoolDbIOHandler<Reference>::get(TBuffer& b, void* obj) {
00261   Token::OID_t oid(~0x0,~0x0);
00262   DataCallBack* caller = DbDataHandlerGuard::caller();
00263   Int_t file_version = ((TFile*)b.GetParent())->GetVersion();
00264   (file_version >= 40000) ? getOID_40000(b, m_root,oid) : b.ReadFastArray(&oid.first, 2);
00265   if (caller) caller->notify(DataCallBack::GET,DataCallBack::REFERENCE,m_type,obj,&oid);
00266 }
00267 
00268 template <>
00269 void PoolDbIOHandler<Reference>::put(TBuffer &b, void* obj) {
00270   UInt_t count = b.WriteVersion(m_root, true);
00271   DataCallBack* caller = DbDataHandlerGuard::caller();
00272   Token::OID_t oid(~0x0, ~0x0);
00273   if (caller) caller->notify(DataCallBack::PUT,DataCallBack::REFERENCE,m_type,obj,&oid);
00274   b.WriteFastArray(&oid.first, 2);
00275   b.SetByteCount(count, true);
00276 }
00277 
00278 template <class T> static bool makeStreamer(MsgStream& log)  {
00279   std::string cl_name = typeName(typeid(T));
00280   ROOT::Reflex::Type t = ROOT::Reflex::Type::ByName(cl_name);
00281   if ( t )  {
00282     TClass* c = gROOT->GetClass(cl_name.c_str());
00283     if ( c ) {
00284       TClassStreamer* s = new PoolDbIOHandler<T>(t,c);
00285       c->AdoptStreamer(s);
00286       log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
00287       return true;
00288     }
00289     else if ( !c )  {
00290       log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
00291     }
00292   }
00293   else  {
00294     log << MSG::ERROR << "[No Reflection Type] Failed to install IOHandler for class " << cl_name << endmsg;
00295   }
00296   return false;
00297 }
00298 
00299 namespace GaudiPoolDb  {
00300   bool patchStreamers(MsgStream& s)  {
00301     static bool first = true;
00302     if ( first ) {
00303       first = false;
00304       for ( Type_Iterator i=Type::Type_Begin(); i != Type::Type_End(); ++i)   {
00305         Type typ = *i;
00306         if ( !(typ.IsStruct() || typ.IsClass()) )  continue;
00307         TClass* cl = 0;
00308         if ( IsTypeOf(typ,"pool::Reference") )  {
00309           cl = gROOT->GetClass(typ.Name(SCOPED).c_str());
00310           if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Reference>(typ,cl));
00311         }
00312         else if ( IsTypeOf(typ,"pool::Token") )  {
00313           cl = gROOT->GetClass(typ.Name(SCOPED).c_str());
00314           if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Token>(typ,cl));
00315         }
00316       }
00317       ROOT::Cintex::Cintex::Enable();
00318       bool b2 = makeStreamer<SmartRefBase>(s);
00319       bool b3 = makeStreamer<ContainedObject>(s);
00320       return b2 && b3;
00321     }
00322     return true;
00323    }
00324 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Wed Feb 9 16:24:58 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004