![]() |
|
|
Generated: 8 Jan 2009 |
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 }