![]() |
|
|
Generated: 18 Jul 2008 |
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 }