| # Gaudi Framework, version v21r10p1 |

Home |  | Generated: 29 Jul 2010

# 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 if ( pDO ) {
    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     else {
    00176       hint = link = StreamBuffer::INVALID;
    00177     }
    00178   }
    00179   //if ( hint == StreamBuffer::INVALID )  {
    00180   //  std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> "
    00181   //            << "Found invalid smart reference."
    00182   //            << std::endl;
    00183   //}
    00184   ref->set(curr, hint, link);
    00185   m_root->WriteBuffer(b, obj);
    00186 }
    00187
    00188 template <>
    00189 void PoolDbIOHandler<ContainedObject>::get(TBuffer &b, void* obj) {
    00190   UInt_t start, count;
    00191   Version_t version = b.ReadVersion(&start, &count, m_root);
    00192   m_root->ReadBuffer(b, obj, version, start, count);
    00193   ContainedObject* p = (ContainedObject*)obj;
    00194   p->setParent((ObjectContainerBase*)getCurrentDataObject());
    00195 }
    00196
    00197 template <>
    00198 void PoolDbIOHandler<ContainedObject>::put(TBuffer &b, void* obj) {
    00199   m_root->WriteBuffer(b, obj);
    00200 }
    00201
    00202 static void getOID_40000(TBuffer& b, TClass* cl, Token::OID_t& oid) {
    00203   unsigned long loid[2];
    00204   UInt_t start, count, tmp;
    00205   // read the class version from the buffer
    00206   /* Version_t vsn = */ b.ReadVersion(&start, &count, 0);
    00207   switch(count) {
    00208   case 22:              // These tokens were written as pair<long,long>
    00209     b >> tmp;           //
    00210     b.ReadFastArray(loid,2); // There was a bug in POOL....
    00211     oid.first = loid[0];
    00212     oid.second = loid[1];
    00213     break;              // see TBuffer::ReadFastArray(ulong*, int)
    00214   case 14:              // Normal case: version:checksum+8 Bytes
    00215     b >> tmp;           //
    00216   case 10:              // Normal case: version:checksum+8 Bytes
    00217   case 8:               // Without checksum and version
    00218   default:              // No better idea
    00219     b.ReadFastArray(&oid.first, 2);
    00220     break;
    00221   }
    00222   // Check that the buffer position correesponds to the byte count
    00223   b.CheckByteCount(start, count, cl);
    00224 }
    00225
    00226 template <>
    00227 void PoolDbIOHandler<Token>::get(TBuffer& b, void* obj) {
    00228   Token* t = (Token*)obj;
    00229   DataCallBack* caller = DbDataHandlerGuard::caller();
    00230   Int_t file_version = ((TFile*)b.GetParent())->GetVersion();
    00231   if ( file_version >= 40000 ) {
    00232     getOID_40000(b, m_root, t->oid());
    00233   }
    00234   else {
    00235     UInt_t start, count, tmp;
    00236     Version_t vsn = b.ReadVersion(&start, &count, m_root);
    00237     switch(vsn)  {
    00238     case 2:
    00239       b >> tmp;
    00240       b.ReadFastArray(&t->oid().first, 2);
    00241       b >> tmp;
    00242       break;
    00243     default:
    00244       b.SetBufferOffset(start+4);
    00245       b.ReadFastArray(&t->oid().first, 2);
    00246       break;
    00247     }
    00248   }
    00249   if (caller) caller->notify(DataCallBack::GET,DataCallBack::TOKEN,m_type,obj,&t->oid());
    00250 }
    00251
    00252 template <>
    00253 void PoolDbIOHandler<Token>::put(TBuffer &b, void* obj) {
    00254   Token::OID_t* poid = &(((Token*)obj)->oid());
    00255   UInt_t count = b.WriteVersion(m_root, true);
    00256   DataCallBack* caller = DbDataHandlerGuard::caller();
    00257   if (caller) caller->notify(DataCallBack::PUT,DataCallBack::TOKEN,m_type,obj,poid);
    00258   b.WriteFastArray(&poid->first, 2);
    00259   b.SetByteCount(count, true);
    00260 }
    00261
    00262 template <>
    00263 void PoolDbIOHandler<Reference>::get(TBuffer& b, void* obj) {
    00264   Token::OID_t oid(~0x0,~0x0);
    00265   DataCallBack* caller = DbDataHandlerGuard::caller();
    00266   Int_t file_version = ((TFile*)b.GetParent())->GetVersion();
    00267   (file_version >= 40000) ? getOID_40000(b, m_root,oid) : b.ReadFastArray(&oid.first, 2);
    00268   if (caller) caller->notify(DataCallBack::GET,DataCallBack::REFERENCE,m_type,obj,&oid);
    00269 }
    00270
    00271 template <>
    00272 void PoolDbIOHandler<Reference>::put(TBuffer &b, void* obj) {
    00273   UInt_t count = b.WriteVersion(m_root, true);
    00274   DataCallBack* caller = DbDataHandlerGuard::caller();
    00275   Token::OID_t oid(~0x0, ~0x0);
    00276   if (caller) caller->notify(DataCallBack::PUT,DataCallBack::REFERENCE,m_type,obj,&oid);
    00277   b.WriteFastArray(&oid.first, 2);
    00278   b.SetByteCount(count, true);
    00279 }
    00280
    00281 template <class T> static bool makeStreamer(MsgStream& log)  {
    00282   std::string cl_name = typeName(typeid(T));
    00283   ROOT::Reflex::Type t = ROOT::Reflex::Type::ByName(cl_name);
    00284   if ( t )  {
    00285     TClass* c = gROOT->GetClass(cl_name.c_str());
    00286     if ( c ) {
    00287       TClassStreamer* s = new PoolDbIOHandler<T>(t,c);
    00288       c->AdoptStreamer(s);
    00289       log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
    00290       return true;
    00291     }
    00292     else if ( !c )  {
    00293       log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
    00294     }
    00295   }
    00296   else  {
    00297     log << MSG::ERROR << "[No Reflection Type] Failed to install IOHandler for class " << cl_name << endmsg;
    00298   }
    00299   return false;
    00300 }
    00301
    00302 namespace GaudiPoolDb  {
    00303   bool patchStreamers(MsgStream& s)  {
    00304     static bool first = true;
    00305     if ( first ) {
    00306       first = false;
    00307       for ( Type_Iterator i=Type::Type_Begin(); i != Type::Type_End(); ++i)   {
    00308         Type typ = *i;
    00309         if ( !(typ.IsStruct() || typ.IsClass()) )  continue;
    00310         TClass* cl = 0;
    00311         if ( IsTypeOf(typ,"pool::Reference") )  {
    00312           cl = gROOT->GetClass(typ.Name(SCOPED).c_str());
    00313           if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Reference>(typ,cl));
    00314         }
    00315         else if ( IsTypeOf(typ,"pool::Token") )  {
    00316           cl = gROOT->GetClass(typ.Name(SCOPED).c_str());
    00317           if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Token>(typ,cl));
    00318         }
    00319       }
    00320       ROOT::Cintex::Cintex::Enable();
    00321       bool b2 = makeStreamer<SmartRefBase>(s);
    00322       bool b3 = makeStreamer<ContainedObject>(s);
    00323       return b2 && b3;
    00324     }
    00325     return true;
    00326    }
    00327 }