00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <algorithm>
00015
00016
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
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* ,
00158 int col_number ,
00159 void* ,
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* )
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* ,
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(IPoolDbMgr::interfaceID(), (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(IDataManagerSvc::interfaceID(), (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
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(msgSvc(),"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* ,
00347 LinkManager* ,
00348 DataObject* pObj,
00349 IRegistry* )
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
00388
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
00397
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
00441
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
00461
00462
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;
00490 }
00491 m_badFiles.insert(tag);
00492 }
00493 MsgStream log(msgSvc(),"PoolDbBaseCnv");
00494 log << MSG::ERROR << "createObj> Cannot access the object:"+tag << endmsg;
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* )
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* , 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* , DataObject* pObj)
00620 {
00621 if ( pObj ) {
00622 return StatusCode::SUCCESS;
00623 }
00624 return makeError("updateRepRefs> Invalid object reference.");
00625 }