| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

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