![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Id: PoolDbBaseCnv.cpp,v 1.18 2008/02/21 18:01:54 hmd Exp $ 00002 //==================================================================== 00003 // PoolDbBaseCnv implementation 00004 //-------------------------------------------------------------------- 00005 // 00006 // Package : GaudiPoolDb ( The LHCb Offline System) 00007 // 00008 // Description: Generic Db data converter 00009 // 00010 // Author : M.Frank 00011 //==================================================================== 00012 00013 // Framework include files 00014 #include "GaudiKernel/MsgStream.h" 00015 #include "GaudiKernel/IRegistry.h" 00016 #include "GaudiKernel/DataObject.h" 00017 #include "GaudiKernel/LinkManager.h" 00018 #include "GaudiKernel/ContainedObject.h" 00019 #include "GaudiKernel/IDataManagerSvc.h" 00020 #include "GaudiKernel/IAddressCreator.h" 00021 #include "GaudiKernel/IDataProviderSvc.h" 00022 00023 #include "GaudiPoolDb/IPoolDbMgr.h" 00024 #include "GaudiPoolDb/PoolDbBaseCnv.h" 00025 #include "GaudiPoolDb/PoolDbAddress.h" 00026 //#include "GaudiPoolDb/PoolDbCnvFactory.h" 00027 #include "GaudiKernel/CnvFactory.h" 00028 #include "GaudiPoolDb/PoolDbLinkManager.h" 00029 00030 #include "PersistencySvc/IPersistencySvc.h" 00031 #include "PersistencySvc/IDataTransform.h" 00032 #include "StorageSvc/DbObjectCallBack.h" 00033 #include "StorageSvc/DbInstanceCount.h" 00034 #include "StorageSvc/DbTransform.h" 00035 #include "StorageSvc/DbTypeInfo.h" 00036 #include "StorageSvc/DbColumn.h" 00037 #include "StorageSvc/DbReflex.h" 00038 #include "Reflex/Reflex.h" 00039 #include "POOLCore/Token.h" 00040 00041 #include <stdexcept> 00042 00043 static pool::DbInstanceCount::Counter* s_count = 00044 pool::DbInstanceCount::getCounter(typeid(PoolDbBaseCnv)); 00045 00046 00047 PLUGINSVC_FACTORY_WITH_ID( PoolDbBaseCnv, 00048 ConverterID(POOL_StorageType,CLID_Any), 00049 IConverter*(long, CLID, ISvcLocator*) ); 00050 PLUGINSVC_FACTORY_WITH_ID( PoolDbBaseCnv, 00051 ConverterID(POOL_StorageType,CLID_Any+CLID_ObjectList), 00052 IConverter*(long, CLID, ISvcLocator*) ); 00053 PLUGINSVC_FACTORY_WITH_ID( PoolDbBaseCnv, 00054 ConverterID(POOL_StorageType,CLID_Any+CLID_ObjectVector), 00055 IConverter*(long, CLID, ISvcLocator*) ); 00056 00057 class PoolDbObjectContext; 00058 static PoolDbObjectContext* s_context = 0; 00059 00060 class PoolDbObjectContext { 00061 PoolDbBaseCnv* m_converter; 00062 IRegistry* m_registry; 00063 public: 00064 PoolDbObjectContext(PoolDbBaseCnv* dm, IRegistry* pReg) { 00065 m_converter = dm; 00066 m_registry = pReg; 00067 s_context = this; 00068 } 00069 ~PoolDbObjectContext() { 00070 m_converter = 0; 00071 s_context = 0; 00072 } 00073 PoolDbBaseCnv* cnv() { 00074 return m_converter; 00075 } 00076 IRegistry* registry() { 00077 return m_registry; 00078 } 00079 }; 00080 00081 00082 class PoolDbDataObjectHandler : public pool::DbObjectCallBack { 00083 protected: 00084 LinkManager* m_links; 00085 PoolDbLinkManager* m_refs; 00086 PoolDbBaseCnv* m_converter; 00087 IRegistry* m_registry; 00088 public: 00090 PoolDbDataObjectHandler(const ROOT::Reflex::Type& cl) 00091 : pool::DbObjectCallBack(cl), m_links(0), m_refs(0), 00092 m_converter(0), m_registry(0) 00093 { 00094 } 00096 PoolDbDataObjectHandler(const ROOT::Reflex::Type& cl, 00097 PoolDbBaseCnv* dm, 00098 IRegistry* pReg) 00099 : pool::DbObjectCallBack(cl), m_links(0), m_refs(0), 00100 m_converter(dm), m_registry(pReg) 00101 { 00102 } 00104 virtual ~PoolDbDataObjectHandler() { 00105 } 00107 virtual pool::DataCallBack* clone() const { 00108 if ( s_context ) { 00109 PoolDbDataObjectHandler* p = 00110 new PoolDbDataObjectHandler( transientType(), 00111 s_context->cnv(), 00112 s_context->registry()); 00113 p->setShape(shape()); 00114 return p; 00115 } 00116 PoolDbDataObjectHandler* p = 00117 new PoolDbDataObjectHandler(transientType(),0,0); 00118 p->setShape(shape()); 00119 return p; 00120 } 00122 00128 pool::DbStatus start(pool::DataCallBack::CallType action_type, 00129 void* data, 00130 void** context); 00132 pool::DbStatus bind(pool::DataCallBack::CallType action_type, 00133 const pool::DbColumn* col_ident, 00134 int col_number, 00135 void* context, 00136 void** data_pointer); 00138 pool::DbStatus end(pool::DataCallBack::CallType action_type, void* context ); 00139 }; 00140 00141 void popCurrentDataObject(); 00142 void pushCurrentDataObject(DataObject** pobjAddr); 00143 00144 namespace { 00145 static bool printLinks() { 00146 static bool prt = false; 00147 return prt; 00148 } 00149 } 00150 00152 pool::DbStatus 00153 PoolDbDataObjectHandler::bind(pool::DataCallBack::CallType action_type, 00154 const pool::DbColumn* /* col_ident */, 00155 int col_number , 00156 void* /* context */, 00157 void** data_pointer) 00158 { 00159 DataObject* pObj = (DataObject*)m_objectData; 00160 switch(action_type) { 00161 case GET: 00162 switch(col_number) { 00163 case 0: 00164 *data_pointer = &m_objectData; 00165 return pool::Success; 00166 case 1: 00167 *data_pointer = &m_links; 00168 return pool::Success; 00169 case 2: 00170 *data_pointer = &m_refs; 00171 return pool::Success; 00172 } 00173 00174 case PUT: 00175 switch(col_number) { 00176 case 0: 00177 *data_pointer = pObj; 00178 return pool::Success; 00179 case 1: 00180 *data_pointer = pObj->linkMgr(); 00181 return pool::Success; 00182 case 2: 00183 m_refs = m_converter->createReferences(pObj); 00184 *data_pointer = m_refs; 00185 return pool::Success; 00186 } 00187 } 00188 return pool::Error; 00189 } 00190 00192 pool::DbStatus 00193 PoolDbDataObjectHandler::end(pool::DataCallBack::CallType action_type, void* /* context */) 00194 { 00195 DataObject* pObj = (DataObject*)m_objectData; 00196 switch(action_type) { 00197 case GET: 00198 m_converter->setReferences(m_refs, m_links, pObj, m_registry).ignore(); 00199 pool::deletePtr(m_links); 00200 break; 00201 case PUT: 00202 m_converter->dumpReferences(m_refs, m_links, pObj, m_registry).ignore(); 00203 break; 00204 } 00205 pool::deletePtr(m_refs); 00206 popCurrentDataObject(); 00207 return pool::Success; 00208 } 00209 00210 pool::DbStatus 00211 PoolDbDataObjectHandler::start( pool::DataCallBack::CallType action_type, 00212 void* /* data */, 00213 void** context) 00214 { 00215 m_refs = 0; 00216 *context = 0; 00217 switch(action_type) { 00218 case GET: 00219 m_objectData = 0; 00220 break; 00221 case PUT: 00222 break; 00223 } 00224 void **ptr = const_cast<void**>(&m_objectData); 00225 pushCurrentDataObject((DataObject**)ptr); 00226 return pool::Success; 00227 } 00228 00230 PoolDbBaseCnv::PoolDbBaseCnv(long typ, const CLID& clid, ISvcLocator* svc) 00231 : Converter(typ, clid, svc), m_objGuid(pool::Guid::null()), m_call(0) 00232 { 00233 s_count->increment(); 00234 m_dbMgr = 0; 00235 m_objGuid.Data1 = clid; 00236 } 00237 00239 PoolDbBaseCnv::~PoolDbBaseCnv() { 00240 pool::releasePtr(m_dbMgr); 00241 s_count->decrement(); 00242 } 00243 00245 StatusCode PoolDbBaseCnv::initialize() { 00246 StatusCode status = Converter::initialize(); 00247 MsgStream log(msgSvc(),"PoolDbBaseCnv"); 00248 if ( !status.isSuccess() ) { 00249 log << MSG::ERROR << "Cannot initialize base class \"Converter\"" << endmsg; 00250 return status; 00251 } 00252 IPoolDbMgr **ptr1 = &m_dbMgr; 00253 status = conversionSvc()->queryInterface(IID_IPoolDbMgr, (void**)ptr1); 00254 if ( !status.isSuccess() ) { 00255 log << MSG::ERROR << "Cannot connect to \"IPoolDbMgr\" interface." << endmsg; 00256 return status; 00257 } 00258 IDataManagerSvc **ptr2 = &m_dataMgr; 00259 status = dataProvider()->queryInterface(IID_IDataManagerSvc, (void**)ptr2); 00260 if ( !status.isSuccess() ) { 00261 log << MSG::ERROR << "Cannot connect to \"IDataManagerSvc\" interface." << endmsg; 00262 return status; 00263 } 00264 const pool::DbTypeInfo* shapeH = 0; 00265 const ROOT::Reflex::Type refH = ROOT::Reflex::Type::ByName("PoolDbLinkManager"); 00266 if ( !refH ) { 00267 log << MSG::ERROR << "Dictionary for class \"PoolDbLinkManager\" missing." << endmsg; 00268 return StatusCode::FAILURE; 00269 } 00270 const ROOT::Reflex::Type lnkH = ROOT::Reflex::Type::ByName("LinkManager"); 00271 if ( !lnkH ) { 00272 log << MSG::ERROR << "Dictionary for class \"LinkManager\" missing." << endmsg; 00273 return StatusCode::FAILURE; 00274 } 00275 m_class = pool::DbReflex::forGuid(m_objGuid); 00276 if ( !m_class ) { 00277 // This may fail if the dictionary is not yet loaded, therefore it is not going to report an ERROR 00278 log << MSG::DEBUG << "Dictionary for class with GUID:" << m_objGuid.toString() 00279 << " missing." << endmsg; 00280 return StatusCode::FAILURE; 00281 } 00282 if ( !pool::DbTransform::getShape(m_objGuid, shapeH).isSuccess() ) { 00283 std::vector<const pool::DbColumn*> c; 00284 c.push_back(new pool::DbColumn(m_class.Name(), 00285 m_class.Name(ROOT::Reflex::SCOPED), 00286 pool::DbColumn::POINTER, 00287 0)); 00288 c.push_back(new pool::DbColumn("Links", 00289 lnkH.Name(ROOT::Reflex::SCOPED), 00290 pool::DbColumn::POINTER, 00291 0)); 00292 c.push_back(new pool::DbColumn("Refs", 00293 refH.Name(ROOT::Reflex::SCOPED), 00294 pool::DbColumn::POINTER, 00295 0)); 00296 shapeH = pool::DbTypeInfo::create(m_objGuid, c); 00297 } 00298 if ( shapeH ) { 00299 log << MSG::DEBUG << "Created object shape for class:" 00300 << m_class.Name(ROOT::Reflex::SCOPED) << endmsg 00301 << shapeH->toString() << endmsg; 00302 m_call = new PoolDbDataObjectHandler(m_class); 00303 m_call->setShape(shapeH); 00304 } 00305 else { 00306 return makeError("Failed to create POOL shape information for GUID:"+ 00307 m_objGuid.toString(),false); 00308 } 00309 return status; 00310 } 00311 00313 StatusCode PoolDbBaseCnv::finalize() { 00314 pool::releasePtr(m_call); 00315 pool::releasePtr(m_dbMgr); 00316 pool::releasePtr(m_dataMgr); 00317 return Converter::finalize(); 00318 } 00319 00321 const std::string 00322 PoolDbBaseCnv::containerName(IRegistry* pRegistry) const { 00323 if ( 0 != pRegistry ) { 00324 return pRegistry->identifier(); 00325 } 00326 return ""; 00327 } 00328 00329 StatusCode PoolDbBaseCnv::makeError(const std::string& msg, bool rethrow) 00330 { 00331 MsgStream log(messageService(),"PoolDbBaseCnv"); 00332 log << MSG::ERROR << "Trouble with class:" << m_objGuid.toString() << " "; 00333 if ( m_class ) log << "<" << m_class.Name(ROOT::Reflex::SCOPED) << "> "; 00334 log << endmsg; 00335 log << msg << endmsg; 00336 if ( rethrow ) { 00337 pool::debugBreak("Error:"+msg, "PoolDbBaseCnv", true); 00338 } 00339 return StatusCode::FAILURE; 00340 } 00341 00342 StatusCode 00343 PoolDbBaseCnv::dumpReferences(PoolDbLinkManager* /* mgr */, 00344 LinkManager* /* pLinks */, 00345 DataObject* pObj, 00346 IRegistry* /* pReg */) 00347 { 00348 if ( printLinks() ) { 00349 MsgStream log(msgSvc(), "dumpReferences"); 00350 LinkManager* mgr = pObj->linkMgr(); 00351 for ( int i = 0; i < mgr->size(); ++i) { 00352 LinkManager::Link* lnk = mgr->link(i); 00353 log << MSG::ALWAYS << "PUT> " << pObj->registry()->identifier() << "[" << i << "] = " << lnk->path() << endmsg; 00354 } 00355 } 00356 return StatusCode::SUCCESS; 00357 } 00358 00359 StatusCode 00360 PoolDbBaseCnv::setReferences(PoolDbLinkManager* mgr, 00361 LinkManager* pLinks, 00362 DataObject* pObj, 00363 IRegistry* pReg) 00364 { 00365 std::string tmp; 00366 LinkManager* pmgr = pObj->linkMgr(); 00367 for(int i = 0; i < pLinks->size(); ++i) { 00368 LinkManager::Link* lnk = pLinks->link(i); 00369 pmgr->addLink(lnk->path(), 0); 00370 } 00371 size_t ref_size = mgr->references().size(); 00372 for(size_t j = 0; j < ref_size; ++j) { 00373 IOpaqueAddress* pA = 0; 00374 const pool::Token* token = mgr->references()[j]; 00375 std::string& location = mgr->links()[j]; 00376 long typ = token->technology(); 00377 CLID clid = token->classID().Data1; 00378 std::string spar[] = {token->dbID(), 00379 token->contID()}; 00380 unsigned long ipar[] = {token->oid().first, 00381 token->oid().second}; 00382 StatusCode sc = addressCreator()->createAddress(typ,clid,spar,ipar,pA); 00383 if ( sc.isSuccess() ) { 00384 // Temporary fix for all files written with previous release(s) 00385 // The fix should be removed when these files are obsolete 00386 if ( location.substr(0,7) == "/Event/" ) { 00387 size_t idx = location.rfind("/"); 00388 tmp = location.substr(idx); 00389 location = tmp; 00390 } 00391 sc = m_dataMgr->registerAddress(pReg, location, pA); 00392 if ( sc.isSuccess() ) { 00393 // MsgStream log(msgSvc(), "Reflection"); 00394 // log << MSG::ALWAYS << "Registered:" << pReg->identifier() << " as " << location << endmsg; 00395 continue; 00396 } 00397 pA->release(); 00398 ROOT::Reflex::Type classH = pool::DbReflex::forGuid(token->classID()); 00399 MsgStream err(msgSvc(), "Reflection"); 00400 if ( 0 == classH ) { 00401 err << MSG::ERROR << "No reflection information availible for class ID:" 00402 << token->classID().toString() << endmsg; 00403 } 00404 else { 00405 err << MSG::ERROR << "Reflection information availible for class ID:" 00406 << token->classID().toString() << endmsg 00407 << classH.Name(ROOT::Reflex::SCOPED) << endmsg; 00408 } 00409 makeError("setReferences> Failed to register opaque address:"+location+ 00410 "\n"+token->toString()); 00411 } 00412 } 00413 return StatusCode::SUCCESS; 00414 } 00415 00416 PoolDbLinkManager* 00417 PoolDbBaseCnv::createReferences(DataObject* pObj) 00418 { 00419 typedef std::vector<IRegistry*> Leaves; 00420 PoolDbLinkManager* refs = new PoolDbLinkManager; 00421 Leaves leaves; 00422 StatusCode status = m_dataMgr->objectLeaves(pObj, leaves); 00423 if ( status.isSuccess() ) { 00424 for(Leaves::iterator i=leaves.begin(), iend=leaves.end(); i != iend; ++i) { 00425 IRegistry* pR = *i; 00426 IOpaqueAddress* pA = pR->address(); 00427 if ( 0 != pA ) { 00428 PoolDbAddress* pdbA = dynamic_cast<PoolDbAddress*>(pA); 00429 if ( 0 != pdbA ) { 00430 pool::Token* tok = const_cast<pool::Token*>(pdbA->token()); 00431 if ( tok ) { 00432 tok->addRef(); 00433 refs->references().push_back(tok); 00434 refs->links().push_back(pR->name()); 00435 } 00436 else { 00437 // What should we do here ? 00438 // Not so clear... 00439 } 00440 } 00441 else { 00442 const std::string* spar = pA->par(); 00443 const unsigned long* ipar = pA->ipar(); 00444 pool::Guid guid(pool::Guid::null()); 00445 guid.Data1 = pA->clID(); 00446 pool::Token* tok = new pool::Token(); 00447 tok->setClassID(guid); 00448 tok->setTechnology(pA->svcType()); 00449 tok->setDb(spar[0]).setCont(spar[1]); 00450 tok->oid().first = ipar[0]; 00451 tok->oid().second = ipar[1]; 00452 refs->references().push_back(tok); 00453 refs->links().push_back(pR->name()); 00454 } 00455 } 00456 else { 00457 // This is not really an error, it only means that the object 00458 // pointed to is not persistent. Hence, this link cannot be followed 00459 // from the data written. 00460 } 00461 } 00462 } 00463 return refs; 00464 } 00465 00466 00468 StatusCode 00469 PoolDbBaseCnv::createObj(IOpaqueAddress* pAddress, DataObject*& refpObject) 00470 { 00471 try { 00472 PoolDbAddress* pA = dynamic_cast<PoolDbAddress*>(pAddress); 00473 if ( pA ) { 00474 PoolDbObjectContext ctxt(this, pAddress->registry()); 00475 pool::DataCallBack* call = m_call->clone(); 00476 StatusCode sc = m_dbMgr->read(call, pA); 00477 if ( sc.isSuccess() ) { 00478 refpObject = (DataObject*)call->object(); 00479 call->release(); 00480 return StatusCode::SUCCESS; 00481 } 00482 call->release(); 00483 std::string tag = pA->par()[0]+":"+pA->par()[1]; 00484 if ( sc.getCode() == IPoolDbMgr::BAD_DATA_CONNECTION ) { 00485 if ( m_badFiles.find(tag) != m_badFiles.end() ) { 00486 return sc; // Let's save us the additional printout 00487 } 00488 m_badFiles.insert(tag); 00489 } 00490 MsgStream log(messageService(),"PoolDbBaseCnv"); 00491 log << MSG::ERROR << "createObj> Cannot access the object:"+tag << endreq; 00492 return StatusCode::FAILURE; 00493 } 00494 return makeError("createObj> Invalid object address.", false); 00495 } 00496 catch (std::exception& e) { 00497 return makeError(std::string("createObj> Caught exception:")+e.what(), false); 00498 } 00499 catch(...) { 00500 } 00501 return makeError("createObj> Unknown exception occurred.", false); 00502 } 00503 00505 StatusCode 00506 PoolDbBaseCnv::fillObjRefs(IOpaqueAddress* pAddress, DataObject* pObject) 00507 { 00508 return updateObjRefs(pAddress, pObject); 00509 } 00510 00512 StatusCode 00513 PoolDbBaseCnv::updateObj(IOpaqueAddress* pAddr, DataObject* /* pObj */) 00514 { 00515 try { 00516 PoolDbAddress* pA = dynamic_cast<PoolDbAddress*>(pAddr); 00517 if ( 0 != pA ) { 00518 return makeError("updateObj> Sorry folks, not yet implemented..."); 00519 } 00520 return makeError("updateObj> Invalid opaque object address."); 00521 } 00522 catch (std::exception& e) { 00523 return makeError(std::string("updateObj> Caught exception:")+e.what()); 00524 } 00525 catch (...) { 00526 } 00527 return makeError("updateObj> Unknown Error - exception was thrown."); 00528 } 00529 00531 StatusCode 00532 PoolDbBaseCnv::updateObjRefs(IOpaqueAddress* /*pAddr*/, DataObject* pObj) 00533 { 00534 if ( 0 != pObj ) { 00535 if ( printLinks() ) { 00536 MsgStream log(msgSvc(), "updateObjRefs"); 00537 LinkManager* mgr = pObj->linkMgr(); 00538 std::string id = pObj->registry()->identifier(); 00539 for ( int i = 0; i < mgr->size(); ++i) { 00540 LinkManager::Link* lnk = mgr->link(i); 00541 log << MSG::ALWAYS << "GET> " << id << "[" << i << "] = " << lnk->path() << endmsg; 00542 } 00543 } 00544 return StatusCode::SUCCESS; 00545 } 00546 return makeError("updateObjRefs> Invalid object reference."); 00547 } 00548 00550 StatusCode 00551 PoolDbBaseCnv::createRep(DataObject* pObj, IOpaqueAddress*& refpA) 00552 { 00553 try { 00554 refpA = 0; 00555 if ( pObj ) { 00556 IRegistry* pReg = pObj->registry(); 00557 if ( pReg ) { 00558 PoolDbAddress* pA = 0; 00559 std::string cnt = containerName(pReg); 00560 PoolDbObjectContext ctxt(this, pObj->registry()); 00561 pool::DataCallBack* call = m_call->clone(); 00562 call->setObject(pObj); 00563 StatusCode sc = m_dbMgr->markWrite(call, cnt, &pA); 00564 if ( sc.isSuccess() ) { 00565 refpA = pA; 00566 return sc; 00567 } 00568 } 00569 return makeError("createRep> Invalid object registry entry."); 00570 } 00571 return makeError("createRep> Invalid object reference."); 00572 } 00573 catch (std::exception& e) { 00574 makeError(std::string("createRep> Caught exception:")+e.what()); 00575 } 00576 catch (...) { 00577 return makeError("createRep> Unknown Fatal Exception."); 00578 } 00579 return makeError("createRep> Fatal Error."); 00580 } 00581 00583 StatusCode 00584 PoolDbBaseCnv::updateRep(IOpaqueAddress* pAddr, DataObject* pObj) { 00585 try { 00586 PoolDbAddress* pA = dynamic_cast<PoolDbAddress*>(pAddr); 00587 if ( 0 != pA ) { 00588 if ( pObj ) { 00589 PoolDbObjectContext ctxt(this, pAddr->registry()); 00590 pool::DataCallBack* call = m_call->clone(); 00591 call->setObject(pObj); 00592 return m_dbMgr->markUpdate(call, pA); 00593 } 00594 return makeError("updateRep> Invalid object reference."); 00595 } 00596 return makeError("updateRep> Invalid opaque object address."); 00597 } 00598 catch (std::exception& e) { 00599 makeError(std::string("updateRep> Caught exception:")+e.what()); 00600 } 00601 catch (...) { 00602 return makeError("updateRep> Unknown Fatal Exception."); 00603 } 00604 return makeError("updateRep> Fatal Error."); 00605 } 00606 00608 StatusCode 00609 PoolDbBaseCnv::fillRepRefs(IOpaqueAddress* pAddr, DataObject* pObj) 00610 { 00611 return updateRepRefs(pAddr, pObj); 00612 } 00613 00615 StatusCode 00616 PoolDbBaseCnv::updateRepRefs(IOpaqueAddress* /* pAddr */, DataObject* pObj) 00617 { 00618 if ( pObj ) { 00619 return StatusCode::SUCCESS; 00620 } 00621 return makeError("updateRepRefs> Invalid object reference."); 00622 }