![]() |
|
|
Generated: 8 Jan 2009 |
00001 // $Id: PoolDbIOHandler.cpp,v 1.13 2008/11/12 23:39:47 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 #include <memory> 00032 00033 using namespace pool; 00034 using namespace ROOT::Reflex; 00035 using namespace ROOT::Cintex; 00036 00037 namespace ROOT { namespace Cintex { 00038 bool IsTypeOf(Type& typ, const std::string& base_name); 00039 }} 00040 namespace pool { 00041 const std::string typeName(const std::type_info& typ); 00042 } 00043 00044 00045 static const DataObject* last_link_object = 0; 00046 static int last_link_hint = -1; 00047 00048 void resetLastLink() { 00049 last_link_object = 0; 00050 last_link_hint = -1; 00051 } 00052 00053 using Gaudi::getCurrentDataObject; 00054 00055 void pushCurrentDataObject(DataObject** pobjAddr) { 00056 Gaudi::pushCurrentDataObject(pobjAddr); 00057 resetLastLink(); 00058 } 00059 00060 void popCurrentDataObject() { 00061 Gaudi::popCurrentDataObject(); 00062 resetLastLink(); 00063 } 00064 00065 00066 template <class T> 00067 void PoolDbIOHandler<T>::operator()(TBuffer &b, void *obj) { 00068 try { 00069 if ( b.IsReading() ) { 00070 get(b,obj); 00071 } 00072 else { 00073 put(b,obj); 00074 } 00075 } 00076 catch( const std::exception& e ) { 00077 std::string err = "Class:" + std::string(m_root->GetName()) + "> Exception in object I/O"; 00078 err += e.what(); 00079 throw std::runtime_error(err); 00080 } 00081 catch( ... ) { 00082 std::string err = "Class:" + std::string(m_root->GetName()) + "> Exception in object I/O"; 00083 throw std::runtime_error(err); 00084 } 00085 } 00086 00087 template <> 00088 void PoolDbIOHandler<SmartRefBase>::get(TBuffer &b, void* obj) { 00089 UInt_t start, count; 00090 SmartRefBase* ref = (SmartRefBase*)obj; 00091 Version_t version = b.ReadVersion(&start, &count, m_root); 00092 m_root->ReadBuffer(b, obj, version, start, count); 00093 switch( ref->objectType() ) { 00094 case SmartRefBase::DATAOBJECT: 00095 { 00096 SmartRef<DataObject>* r = (SmartRef<DataObject>*)obj; 00097 (*r)(getCurrentDataObject()); 00098 } 00099 break; 00100 case SmartRefBase::CONTAINEDOBJECT: 00101 { 00102 SmartRef<ContainedObject>* r = (SmartRef<ContainedObject>*)obj; 00103 (*r)(getCurrentDataObject()); 00104 } 00105 break; 00106 default: 00107 std::cout << "Hit uninitialized smartRef!!!!" << std::endl; 00108 break; 00109 } 00110 } 00111 00112 template <> 00113 void PoolDbIOHandler<SmartRefBase>::put(TBuffer &b, void* obj) { 00114 SmartRefBase* ref = (SmartRefBase*)obj; 00115 SmartRef<DataObject>* r1 = (SmartRef<DataObject>*)ref; 00116 DataObject* curr = getCurrentDataObject(); 00117 DataObject* pDO = r1->data(); 00118 int hint = r1->hintID(); 00119 int link = r1->linkID(); 00120 if ( pDO ) { 00121 switch( ref->objectType() ) { 00122 case SmartRefBase::CONTAINEDOBJECT: 00123 { 00124 SmartRef<ContainedObject>* r2 = (SmartRef<ContainedObject>*)ref; 00125 ContainedObject* p = r2->data(); 00126 if ( p ) { 00127 const ObjectContainerBase* parent = p->parent(); 00128 if ( parent ) { 00129 link = p->index(); 00130 pDO = const_cast<ObjectContainerBase*>(parent); 00131 break; 00132 } 00133 } 00134 } 00135 pDO = 0; 00136 std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> " 00137 << "Found invalid smart reference with object " 00138 << "having no parent." 00139 << std::endl; 00140 throw std::runtime_error("PoolDbIOHandler<SmartRefBase>::onWrite> " 00141 "Found invalid smart reference with object " 00142 "having no parent."); 00143 break; 00144 case SmartRefBase::DATAOBJECT: 00145 link = StreamBuffer::INVALID; 00146 break; 00147 default: 00148 break; 00149 } 00150 //if ( pDO == last_link_object && last_link_hint == -1 ) { 00151 // std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> " 00152 // << "Found invalid smart reference." 00153 // << std::endl; 00154 //} 00155 if ( pDO == last_link_object ) { 00156 ref->set(curr, last_link_hint, link); 00157 m_root->WriteBuffer(b, obj); 00158 return; 00159 } 00160 else if ( pDO ) { 00161 LinkManager* mgr = curr->linkMgr(); 00162 IRegistry* reg = pDO->registry(); 00163 if ( reg && mgr ) { 00164 hint = mgr->addLink(reg->identifier(), pDO); 00165 last_link_hint = hint; 00166 last_link_object = pDO; 00167 } 00168 } 00169 else { 00170 hint = link = StreamBuffer::INVALID; 00171 } 00172 } 00173 //if ( hint == StreamBuffer::INVALID ) { 00174 // std::cout << "PoolDbIOHandler<SmartRefBase>::onWrite> " 00175 // << "Found invalid smart reference." 00176 // << std::endl; 00177 //} 00178 ref->set(curr, hint, link); 00179 m_root->WriteBuffer(b, obj); 00180 } 00181 00182 template <> 00183 void PoolDbIOHandler<ContainedObject>::get(TBuffer &b, void* obj) { 00184 UInt_t start, count; 00185 Version_t version = b.ReadVersion(&start, &count, m_root); 00186 m_root->ReadBuffer(b, obj, version, start, count); 00187 ContainedObject* p = (ContainedObject*)obj; 00188 p->setParent((ObjectContainerBase*)getCurrentDataObject()); 00189 } 00190 00191 template <> 00192 void PoolDbIOHandler<ContainedObject>::put(TBuffer &b, void* obj) { 00193 m_root->WriteBuffer(b, obj); 00194 } 00195 00196 static void getOID_40000(TBuffer& b, TClass* cl, Token::OID_t& oid) { 00197 unsigned long loid[2]; 00198 UInt_t start, count, tmp; 00199 // read the class version from the buffer 00200 /* Version_t vsn = */ b.ReadVersion(&start, &count, 0); 00201 switch(count) { 00202 case 22: // These tokens were written as pair<long,long> 00203 b >> tmp; // 00204 b.ReadFastArray(loid,2); // There was a bug in POOL.... 00205 oid.first = loid[0]; 00206 oid.second = loid[1]; 00207 break; // see TBuffer::ReadFastArray(ulong*, int) 00208 case 14: // Normal case: version:checksum+8 Bytes 00209 b >> tmp; // 00210 case 10: // Normal case: version:checksum+8 Bytes 00211 case 8: // Without checksum and version 00212 default: // No better idea 00213 b.ReadFastArray(&oid.first, 2); 00214 break; 00215 } 00216 // Check that the buffer position correesponds to the byte count 00217 b.CheckByteCount(start, count, cl); 00218 } 00219 00220 template <> 00221 void PoolDbIOHandler<Token>::get(TBuffer& b, void* obj) { 00222 Token* t = (Token*)obj; 00223 DataCallBack* caller = DbDataHandlerGuard::caller(); 00224 Int_t file_version = ((TFile*)b.GetParent())->GetVersion(); 00225 if ( file_version >= 40000 ) { 00226 getOID_40000(b, m_root, t->oid()); 00227 } 00228 else { 00229 UInt_t start, count, tmp; 00230 Version_t vsn = b.ReadVersion(&start, &count, m_root); 00231 switch(vsn) { 00232 case 2: 00233 b >> tmp; 00234 b.ReadFastArray(&t->oid().first, 2); 00235 b >> tmp; 00236 break; 00237 default: 00238 b.SetBufferOffset(start+4); 00239 b.ReadFastArray(&t->oid().first, 2); 00240 break; 00241 } 00242 } 00243 if (caller) caller->notify(DataCallBack::GET,DataCallBack::TOKEN,m_type,obj,&t->oid()); 00244 } 00245 00246 template <> 00247 void PoolDbIOHandler<Token>::put(TBuffer &b, void* obj) { 00248 Token::OID_t* poid = &(((Token*)obj)->oid()); 00249 UInt_t count = b.WriteVersion(m_root, true); 00250 DataCallBack* caller = DbDataHandlerGuard::caller(); 00251 if (caller) caller->notify(DataCallBack::PUT,DataCallBack::TOKEN,m_type,obj,poid); 00252 b.WriteFastArray(&poid->first, 2); 00253 b.SetByteCount(count, true); 00254 } 00255 00256 template <> 00257 void PoolDbIOHandler<Reference>::get(TBuffer& b, void* obj) { 00258 Token::OID_t oid(~0x0,~0x0); 00259 DataCallBack* caller = DbDataHandlerGuard::caller(); 00260 Int_t file_version = ((TFile*)b.GetParent())->GetVersion(); 00261 (file_version >= 40000) ? getOID_40000(b, m_root,oid) : b.ReadFastArray(&oid.first, 2); 00262 if (caller) caller->notify(DataCallBack::GET,DataCallBack::REFERENCE,m_type,obj,&oid); 00263 } 00264 00265 template <> 00266 void PoolDbIOHandler<Reference>::put(TBuffer &b, void* obj) { 00267 UInt_t count = b.WriteVersion(m_root, true); 00268 DataCallBack* caller = DbDataHandlerGuard::caller(); 00269 Token::OID_t oid(~0x0, ~0x0); 00270 if (caller) caller->notify(DataCallBack::PUT,DataCallBack::REFERENCE,m_type,obj,&oid); 00271 b.WriteFastArray(&oid.first, 2); 00272 b.SetByteCount(count, true); 00273 } 00274 00275 template <class T> static bool makeStreamer(MsgStream& log) { 00276 std::string cl_name = typeName(typeid(T)); 00277 ROOT::Reflex::Type t = ROOT::Reflex::Type::ByName(cl_name); 00278 if ( t ) { 00279 TClass* c = gROOT->GetClass(cl_name.c_str()); 00280 if ( c ) { 00281 TClassStreamer* s = new PoolDbIOHandler<T>(t,c); 00282 c->AdoptStreamer(s); 00283 log << MSG::DEBUG << "Installed IOHandler for class " << cl_name << endmsg; 00284 return true; 00285 } 00286 else if ( !c ) { 00287 log << MSG::ERROR << "[No ROOT TClass] Failed to install IOHandler for class " << cl_name << endmsg; 00288 } 00289 } 00290 else { 00291 log << MSG::ERROR << "[No Reflection Type] Failed to install IOHandler for class " << cl_name << endmsg; 00292 } 00293 return false; 00294 } 00295 00296 namespace GaudiPoolDb { 00297 bool patchStreamers(MsgStream& s) { 00298 static bool first = true; 00299 if ( first ) { 00300 first = false; 00301 for ( Type_Iterator i=Type::Type_Begin(); i != Type::Type_End(); ++i) { 00302 Type typ = *i; 00303 if ( !(typ.IsStruct() || typ.IsClass()) ) continue; 00304 TClass* cl = 0; 00305 if ( IsTypeOf(typ,"pool::Reference") ) { 00306 cl = gROOT->GetClass(typ.Name(SCOPED).c_str()); 00307 if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Reference>(typ,cl)); 00308 } 00309 else if ( IsTypeOf(typ,"pool::Token") ) { 00310 cl = gROOT->GetClass(typ.Name(SCOPED).c_str()); 00311 if ( cl ) cl->AdoptStreamer(new PoolDbIOHandler<Token>(typ,cl)); 00312 } 00313 } 00314 ROOT::Cintex::Cintex::Enable(); 00315 bool b2 = makeStreamer<SmartRefBase>(s); 00316 bool b3 = makeStreamer<ContainedObject>(s); 00317 return b2 && b3; 00318 } 00319 return true; 00320 } 00321 }