Gaudi Framework, version v21r9

Home   Generated: 3 May 2010

TESSerializer.cpp

Go to the documentation of this file.
00001 // $Id: TESSerializer.cpp,v 1.2 2008/11/12 23:39:47 marcocle Exp $ 
00002 
00003 // 23 May 2009 : changes to dumpBuffer, loadBuffer.
00004 //
00005 // TESSerializer.loadBuffer : Instead of accepting a const buffer, then copying to a new local buffer
00006 // and then rebuilding the TES, the argument is now non-const, and the TES is reconstructed directly
00007 // from the incoming buffer.
00008 // 
00009 // TESSerializer.dumpBuffer : dumpBuffer now accepts an argument; a TBufferFile created externally
00010 // in python.  Sometimes, creating the buffer internally was causing errors when using TMessages and 
00011 // TSockets.  Creating the empty buffer in python and passing as an argument fixes this.
00012 
00013 #include "GaudiPython/TESSerializer.h"
00014 
00015 // Framework include files
00016 #include "GaudiKernel/IRegistry.h"
00017 #include "GaudiKernel/IDataManagerSvc.h"
00018 #include "GaudiKernel/IDataProviderSvc.h"
00019 #include "GaudiKernel/LinkManager.h"
00020 #include "GaudiKernel/DataObject.h"
00021 #include "GaudiKernel/DataStoreItem.h"
00022 #include "GaudiKernel/System.h"
00023 #include "GaudiKernel/GaudiException.h"
00024 
00025 // ROOT include files
00026 #include "TROOT.h"
00027 #include "TClass.h"
00028 #include "TInterpreter.h"
00029 #include "TBufferFile.h"
00030 
00031 #include <map>
00032 #include <iostream>
00033 
00034 namespace {
00035   struct DataObjectPush {
00036     DataObjectPush(DataObject*& p) {
00037       Gaudi::pushCurrentDataObject(&p);
00038     }
00039     ~DataObjectPush() {
00040       Gaudi::popCurrentDataObject();
00041     }
00042   };
00043 }
00044 
00045 using namespace std;
00046 
00047 
00048 bool GaudiPython::TESSerializer::analyse(IRegistry* dir, int level)   {
00049   if ( level < m_currentItem->depth() )   {
00050     if ( dir->object() != 0 )   {
00051       m_objects.push_back(dir->object());
00052       return true;
00053     }
00054   }
00055   return false;
00056 }
00057 
00058 GaudiPython::TESSerializer::TESSerializer( IDataProviderSvc* svc )
00059   : m_TES(svc) 
00060 {
00061   m_TESMgr = dynamic_cast<IDataManagerSvc*>(svc);
00062 }
00063 
00064 void GaudiPython::TESSerializer::dumpBuffer(TBufferFile& buffer) {
00065   StatusCode status;
00066   DataObject* obj;
00067 
00068   // static TBufferFile buffer(TBuffer::kWrite);        /* create a buffer */
00069   static map<string, TClass*> classes;  /* create an STL map to relate string and TClass */
00070 
00071   // Clear current selection 
00072   m_objects.erase(m_objects.begin(), m_objects.end());
00073 
00074   // Traverse the tree and collect the requested objects
00075   for ( Items::iterator i = m_itemList.begin(); i != m_itemList.end(); i++ )    {
00076     m_currentItem = (*i);
00077     status = m_TES->retrieveObject(m_currentItem->path(), obj);
00078     if ( status.isSuccess() )  {
00079       m_TESMgr->traverseSubTree(obj, this);
00080     }
00081     else  {
00082       string text("Cannot serialize mandatory object(s) ");
00083       throw GaudiException(text + m_currentItem->path(), "", status);
00084     }
00085   }
00086   // Traverse the tree and collect the requested objects (tolerate missing items here)
00087   for ( Items::iterator i = m_optItemList.begin(); i != m_optItemList.end(); i++ )    {
00088     m_currentItem = (*i);
00089     status= m_TES->retrieveObject(m_currentItem->path(), obj);
00090     if ( status.isSuccess() )  {
00091       m_TESMgr->traverseSubTree(obj, this);
00092     }
00093   }
00094 
00095   // buffer.Reset();
00096   buffer.WriteInt(m_objects.size());
00097 
00098   for(Objects::iterator i = m_objects.begin(); i != m_objects.end(); ++i) {    
00099     DataObject* pObj = (*i);    /* define pointer !pObj! to a data object */
00100     DataObjectPush p(pObj);             /* add the data object to the list... */
00101 
00102     // We build a map so gROOT has to access the whole class database as little as possible
00103     TClass* cl;                                         /* announce a TClass */
00104     const type_info& objClass = typeid(*pObj);                  /* get the type of the data object */
00105     string objClassName = System::typeinfoName(objClass);       /* and then get the descriptive string from System */
00106 
00107     /* Since we're dealing with a list of objects, we map each one, but if objects are the same, we note
00108        that they've already been mapped (ie the first 'if case below') */
00109     if (classes[objClassName])   {
00110       cl=classes[objClassName];
00111     } else {
00112       /* if a class has not been mapped: pull the class name from the objects c_str() method */
00113       const char* clName = objClassName.c_str();
00114       /* and find the relevant Tclass (cl) in gROOT */
00115       cl = gROOT->GetClass(clName);
00116       /* ... and fill in the map entry */
00117       classes[objClassName]=cl;
00118     }
00119 
00120     /* but what if the object is not mapped because gROOT->GetClass cannot find clName? */
00121     if (cl==0){
00122       throw GaudiException("gROOT->GetClass cannot find clName", objClassName, StatusCode::FAILURE);      
00123     }
00124     // write object to buffer in order location-name-object
00125     std::string loc=pObj->registry()->identifier();
00126     buffer.WriteString(loc.c_str());
00127     buffer.WriteString(cl->GetName());
00128     cl->Streamer(pObj,buffer);
00129     /* take care of links */
00130     LinkManager* linkMgr = pObj->linkMgr();
00131     int numLinks = linkMgr->size();
00132     buffer.WriteInt(numLinks);
00133     // now write each link 
00134     for (int it = 0; it != numLinks; it++)        {
00135       const string& link = linkMgr->link(it)->path();
00136       buffer.WriteString(link.c_str());
00137     }
00138   }
00139   // return &buffer;
00140 }
00141 
00142 /* ----------- define loads --------------------- */
00143 void GaudiPython::TESSerializer::loadBuffer(TBufferFile& buffer) {
00144   
00145   // reverse mechanism of dumps
00146   // buffer is: length of DataObjects vector, location string, type name string, the object itself, num of links, list of links
00147 
00148   // not used any more...
00149   // TBufferFile buffer(TBuffer::kRead, in_buffer.BufferSize()-TMsgReserved, in_buffer.Buffer()+TMsgReserved, false);
00150 
00151   int nObjects;
00152   buffer.ReadInt(nObjects);
00153 
00154   for (int i=0; i<nObjects; ++i) {
00155     char text[4096];
00156     buffer.ReadString(text,sizeof(text));
00157     string location(text);
00158     buffer.ReadString(text,sizeof(text));
00159     TClass* cl = gROOT->GetClass(text);
00160     
00162     DataObject* obj = (DataObject*)cl->New();
00163     DataObjectPush push(obj); // This is magic!
00164     
00165     cl->Streamer(obj, buffer);
00166     
00167     if ( obj ) { // Restore links
00168       int nlink = 0;
00169       LinkManager* lnkMgr = obj->linkMgr();
00170       buffer.ReadInt(nlink);
00171       
00172       for (int j=0; j<nlink; ++j) {
00173         buffer.ReadString(text,sizeof(text));
00174         lnkMgr->addLink(text,0);
00175       }
00176     }
00177     StatusCode sc;
00178     sc = m_TES->registerObject(location, obj);
00179     if (sc.isFailure()) {
00180       if ( location == "/Event" ) {
00181         sc = m_TESMgr->setRoot(location, obj);
00182         if(sc.isFailure()) {
00183           string msg("Cannot set root at location ");
00184           throw GaudiException(msg+location,"", sc);
00185         } 
00186       }
00187       else {
00188         string msg("Cannot register object at location ");
00189         throw GaudiException(msg+location,"", sc);
00190       }      
00191     }
00192   }
00193 }
00194 
00195 // Add item to output to list for serialization (protected)
00196 void GaudiPython::TESSerializer::addItem(Items& itms, const std::string& path, int level)   {
00197   DataStoreItem* item = new DataStoreItem(path, level);
00198   itms.push_back( item );
00199 }
00200 
00201 // Add item to serialization list; ie append to std::vector of DataStoreItems
00202 void GaudiPython::TESSerializer::addItem(const std::string& path, int level)   {
00203   addItem( m_itemList, path, level);
00204 }
00205 
00206 // Add item to output streamer list
00207 void GaudiPython::TESSerializer::addOptItem(const std::string& path, int level)   {
00208   addItem( m_optItemList, path, level);
00209 }

Generated at Mon May 3 12:14:40 2010 for Gaudi Framework, version v21r9 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004