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