Gaudi Framework, version v22r4

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

Generated at Fri Sep 2 2011 16:24:48 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004