| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

# PoolDbIOHandler.cpp

Go to the documentation of this file.

    00001 // $Id: PoolDbIOHandler.cpp,v 1.11 2008/05/05 19:48:13 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 using namespace pool;
    00032 using namespace ROOT::Reflex;
    00033 using namespace ROOT::Cintex;
    00034
    00035 namespace ROOT { namespace Cintex  {
    00036   bool IsTypeOf(Type& typ, const std::string& base_name);
    00037 }}
    00038 namespace pool  {
    00039   const std::string typeName(const std::type_info& typ);
    00040 }
    00041
    00042 static DataObject*       s_objPtr = 0;
    00043 static DataObject**      s_currObj = &s_objPtr;
    00044 static const DataObject* last_link_object = 0;
    00045 static int last_link_hint = -1;
    00046
    00047 static std::vector<DataObject**>& currentObject() {
    00048   static std::auto_ptr<std::vector<DataObject**> > s_current;
    00049   if ( 0 == s_current.get() )  {
    00050     s_current = std::auto_ptr<std::vector<DataObject**> >(new std::vector<DataObject**>());
    00051   }
    00052   return *(s_current.get());
    00053 }
    00054
    00055 void pushCurrentDataObject(DataObject** pobjAddr) {
    00056   static std::vector<DataObject**>& c = currentObject();
    00057   c.push_back(pobjAddr);
    00058   s_currObj = pobjAddr ? pobjAddr : &s_objPtr;
    00059   last_link_object = 0;
    00060   last_link_hint   = -1;
    00061 }
    00062
    00063 void popCurrentDataObject() {
    00064   static std::vector<DataObject**>& c = currentObject();
    00065   last_link_object = 0;
    00066   last_link_hint   = -1;
    00067   switch(c.size())  {
    00068     case 0:
    00069       s_currObj = c.back();
    00070       c.pop_back();
    00071       break;
    00072     default:
    00073       s_currObj = &s_objPtr;
    00074       break;
    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)(*s_currObj);
    00110     }
    00111     break;
    00112   case SmartRefBase::CONTAINEDOBJECT:
    00113    {
    00114      SmartRef<ContainedObject>* r = (SmartRef<ContainedObject>*)obj;
    00115      (*r)(*s_currObj);
    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 = *s_currObj;
    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 if ( pDO ) {
    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     else {
    00182       hint = link = StreamBuffer::INVALID;
    00183     }
    00184   }
    00185   //if ( hint == StreamBuffer::INVALID )  {
    00186   //  std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> "
    00187   //            << "Found invalid smart reference."
    00188   //            << std::endl;
    00189   //}
    00190   ref->set(curr, hint, link);
    00191   m_root->WriteBuffer(b, obj);
    00192 }
    00193
    00194 template <>
    00195 void PoolDbIOHandler<ContainedObject>::get(TBuffer &b, void* obj) {
    00196   UInt_t start, count;
    00197   Version_t version = b.ReadVersion(&start, &count, m_root);
    00198   m_root->ReadBuffer(b, obj, version, start, count);
    00199   ContainedObject* p = (ContainedObject*)obj;
    00200   p->setParent((ObjectContainerBase*)*s_currObj);
    00201 }
    00202
    00203 template <>
    00204 void PoolDbIOHandler<ContainedObject>::put(TBuffer &b, void* obj) {
    00205   m_root->WriteBuffer(b, obj);
    00206 }
    00207
    00208 static void getOID_40000(TBuffer& b, TClass* cl, Token::OID_t& oid) {
    00209   unsigned long loid[2];
    00210   UInt_t start, count, tmp;
    00211   // read the class version from the buffer
    00212   /* Version_t vsn = */ b.ReadVersion(&start, &count, 0);
    00213   switch(count) {
    00214   case 22:              // These tokens were written as pair<long,long>
    00215     b >> tmp;           //
    00216     b.ReadFastArray(loid,2); // There was a bug in POOL....
    00217     oid.first = loid[0];
    00218     oid.second = loid[1];
    00219     break;              // see TBuffer::ReadFastArray(ulong*, int)
    00220   case 14:              // Normal case: version:checksum+8 Bytes
    00221     b >> tmp;           //
    00222   case 10:              // Normal case: version:checksum+8 Bytes
    00223   case 8:               // Without checksum and version
    00224   default:              // No better idea
    00225     b.ReadFastArray(&oid.first, 2);
    00226     break;
    00227   }
    00228   // Check that the buffer position correesponds to the byte count
    00229   b.CheckByteCount(start, count, cl);
    00230 }
    00231
    00232 template <>
    00233 void PoolDbIOHandler<Token>::get(TBuffer& b, void* obj) {
    00234   Token* t = (Token*)obj;
    00235   DataCallBack* caller = DbDataHandlerGuard::caller();
    00236   Int_t file_version = ((TFile*)b.GetParent())->GetVersion();
    00237   if ( file_version >= 40000 ) {
    00238     getOID_40000(b, m_root, t->oid());
    00239   }
    00240   else {
    00241     UInt_t start, count, tmp;
    00242     Version_t vsn = b.ReadVersion(&start, &count, m_root);
    00243     switch(vsn)  {
    00244     case 2:
    00245       b >> tmp;
    00246       b.ReadFastArray(&t->oid().first, 2);
    00247       b >> tmp;
    00248       break;
    00249     default:
    00250       b.SetBufferOffset(start+4);
    00251       b.ReadFastArray(&t->oid().first, 2);
    00252       break;
    00253     }
    00254   }
    00255   if (caller) caller->notify(DataCallBack::GET,DataCallBack::TOKEN,m_type,obj,&t->oid());
    00256 }
    00257
    00258 template <>
    00259 void PoolDbIOHandler<Token>::put(TBuffer &b, void* obj) {
    00260   Token::OID_t* poid = &(((Token*)obj)->oid());
    00261   UInt_t count = b.WriteVersion(m_root, true);
    00262   DataCallBack* caller = DbDataHandlerGuard::caller();
    00263   if (caller) caller->notify(DataCallBack::PUT,DataCallBack::TOKEN,m_type,obj,poid);
    00264   b.WriteFastArray(&poid->first, 2);
    00265   b.SetByteCount(count, true);
    00266 }
    00267
    00268 template <>
    00269 void PoolDbIOHandler<Reference>::get(TBuffer& b, void* obj) {
    00270   Token::OID_t oid(~0x0,~0x0);
    00271   DataCallBack* caller = DbDataHandlerGuard::caller();
    00272   Int_t file_version = ((TFile*)b.GetParent())->GetVersion();
    00273   (file_version >= 40000) ? getOID_40000(b, m_root,oid) : b.ReadFastArray(&oid.first, 2);
    00274   if (caller) caller->notify(DataCallBack::GET,DataCallBack::REFERENCE,m_type,obj,&oid);
    00275 }
    00276
    00277 template <>
    00278 void PoolDbIOHandler<Reference>::put(TBuffer &b, void* obj) {
    00279   UInt_t count = b.WriteVersion(m_root, true);
    00280   DataCallBack* caller = DbDataHandlerGuard::caller();
    00281   Token::OID_t oid(~0x0, ~0x0);
    00282   if (caller) caller->notify(DataCallBack::PUT,DataCallBack::REFERENCE,m_type,obj,&oid);
    00283   b.WriteFastArray(&oid.first, 2);
    00284   b.SetByteCount(count, true);
    00285 }
    00286
    00287 template <class T> static bool makeStreamer(MsgStream& log)  {
    00288   std::string cl_name = typeName(typeid(T));
    00289   ROOT::Reflex::Type t = ROOT::Reflex::Type::ByName(cl_name);
    00290   if ( t )  {
    00291     TClass* c = gROOT->GetClass(cl_name.c_str());
    00292     if ( c ) {
    00293       TClassStreamer* s = new PoolDbIOHandler<T>(t,c);
    00294       c->AdoptStreamer(s);
    00295       log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg;
    00296       return true;
    00297     }
    00298     else if ( !c )  {
    00299       log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg;
    00300     }
    00301   }
    00302   else  {
    00303     log << MSG::ERROR << "[No Reflection Type] Failed to install IOHandler for class " << cl_name << endmsg;
    00304   }
    00305   return false;
    00306 }
    00307
    00308 namespace GaudiPoolDb  {
    00309   bool patchStreamers(MsgStream& s)  {
    00310     static bool first = true;
    00311     if ( first ) {
    00312       first = false;
    00313       for ( Type_Iterator i=Type::Type_Begin(); i != Type::Type_End(); ++i)   {
    00314         Type typ = *i;
    00315         if ( !(typ.IsStruct() || typ.IsClass()) )  continue;
    00316         TClass* cl = 0;
    00317         if ( IsTypeOf(typ,"pool::Reference") )  {
    00318           cl = gROOT->GetClass(typ.Name(SCOPED).c_str());
    00319           if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Reference>(typ,cl));
    00320         }
    00321         else if ( IsTypeOf(typ,"pool::Token") )  {
    00322           cl = gROOT->GetClass(typ.Name(SCOPED).c_str());
    00323           if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Token>(typ,cl));
    00324         }
    00325       }
    00326       ROOT::Cintex::Cintex::Enable();
    00327       bool b2 = makeStreamer<SmartRefBase>(s);
    00328       bool b3 = makeStreamer<ContainedObject>(s);
    00329       return b2 && b3;
    00330     }
    00331     return true;
    00332    }
    00333 }