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