Gaudi Framework, version v20r3

Generated: 24 Nov 2008

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

Generated at Mon Nov 24 14:38:48 2008 for Gaudi Framework, version v20r3 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004