![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Id: PoolDbCnvSvc.cpp,v 1.29 2008/02/21 18:01:54 hmd Exp $ 00002 //==================================================================== 00003 // PoolDbCnvSvc implementation 00004 //-------------------------------------------------------------------- 00005 // 00006 // Description: Implementation of the POOL data storage 00007 // 00008 // Author : M.Frank 00009 // 00010 //==================================================================== 00011 00012 // Framework include files 00013 #include "GaudiKernel/MsgStream.h" 00014 #include "GaudiKernel/strcasecmp.h" 00015 #include "GaudiKernel/SvcFactory.h" 00016 #include "GaudiKernel/CnvFactory.h" 00017 #include "GaudiKernel/IRegistry.h" 00018 #include "GaudiKernel/IDataManagerSvc.h" 00019 #include "GaudiKernel/IDataProviderSvc.h" 00020 00021 #include "GaudiPoolDb/IPoolCacheSvc.h" 00022 #include "GaudiPoolDb/PoolDbCnvSvc.h" 00023 #include "GaudiPoolDb/PoolDbAddress.h" 00024 #include "GaudiPoolDb/PoolDbDataConnection.h" 00025 00026 // POOL include files 00027 #include "POOLCore/Token.h" 00028 #include "StorageSvc/DbType.h" 00029 #include "StorageSvc/DbObject.h" 00030 #include "StorageSvc/DbSelect.h" 00031 #include "StorageSvc/DataCallBack.h" 00032 #include "StorageSvc/DbTypeInfo.h" 00033 #include "StorageSvc/DbInstanceCount.h" 00034 #include "StorageSvc/DbOptionCallback.h" 00035 #include "GaudiUtils/IFileCatalog.h" 00036 #include "GaudiUtils/IIODataManager.h" 00037 00038 //ROOT include files 00039 #include "TInterpreter.h" 00040 00041 #include <sstream> 00042 #include <set> 00043 00044 using ROOT::Reflex::PluginService; 00045 00046 static pool::DbInstanceCount::Counter* s_count = 00047 pool::DbInstanceCount::getCounter(typeid(PoolDbCnvSvc)); 00048 00049 DECLARE_SERVICE_FACTORY(PoolDbCnvSvc); 00050 00051 typedef std::vector<std::string> StringV; 00052 typedef const std::string& CSTR; 00053 00054 #define S_OK StatusCode::SUCCESS 00055 #define S_FAIL StatusCode::FAILURE 00056 using pool::DbType; 00057 using pool::DbContainer; 00058 using pool::DbDomain; 00059 using pool::DbDatabase; 00060 using pool::DbTypeInfo; 00061 using pool::DbTransaction; 00062 using pool::DbOptionCallback; 00063 using pool::DbAccessMode; 00064 using pool::Transaction; 00065 using namespace Gaudi; 00066 00067 static void checkAccessMode(DbAccessMode mode, DbDatabase& dbH) { 00068 DbAccessMode m = dbH.openMode(); 00069 if ( m&mode || m&pool::UPDATE || m&pool::RECREATE ) { 00070 return; 00071 } 00072 std::string err = 00073 "The dataset "+dbH.name()+" cannot be opened in mode "+ 00074 +pool::accessMode(mode)+ 00075 +"\nThe database was already open, but in mode " 00076 +pool::accessMode(m); 00077 throw std::runtime_error(err); 00078 } 00079 00081 PoolDbCnvSvc::PoolDbCnvSvc(CSTR nam, ISvcLocator* svc) 00082 : ConversionSvc( nam, svc, POOL_StorageType), 00083 m_dataMgr(0), m_cacheSvc(0), m_current(0), 00084 m_domH(pool::POOL_StorageType), 00085 m_catalog(0), m_ioMgr(0) 00086 { 00087 s_count->increment(); 00088 declareProperty("Server", m_serverConnect = ""); 00089 declareProperty("DbType", m_implementation = "Unknown"); 00090 declareProperty("PoolCache", m_cacheSvcName = "PoolDbCacheSvc"); 00091 declareProperty("ShareFiles", m_shareFiles = "NO"); 00092 declareProperty("SafeTransactions", m_safeTransactions = false); 00093 declareProperty("CheckFIDs", m_checkFIDs = true); 00094 } 00095 00097 PoolDbCnvSvc::~PoolDbCnvSvc() { 00098 s_count->decrement(); 00099 } 00100 00102 StatusCode 00103 PoolDbCnvSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) { 00104 if ( IID_IPoolDbMgr == riid ) { 00105 *ppvInterface = (IPoolDbMgr*)this; 00106 addRef(); 00107 return S_OK; 00108 } 00109 // Interface is not directly availible: try out a base class 00110 return ConversionSvc::queryInterface(riid, ppvInterface); 00111 } 00112 00114 StatusCode PoolDbCnvSvc::initialize() { 00115 StatusCode status = ConversionSvc::initialize(); 00116 MsgStream log(messageService(), name()); 00117 if ( !status.isSuccess() ) { 00118 log << MSG::ERROR << "Failed to initialize ConversionSvc base class." 00119 << endmsg; 00120 return status; 00121 } 00122 status = accessStorageType(m_implementation, m_type); 00123 if ( !status.isSuccess() ) { 00124 log << MSG::ERROR << "Failed to connect to POOL implementation:" 00125 << m_implementation << endmsg; 00126 return status; 00127 } 00128 status = service(m_cacheSvcName, m_cacheSvc); 00129 if ( !status.isSuccess() ) { 00130 log << MSG::ERROR << "Failed to connect to POOL cache service:" 00131 << m_cacheSvcName << endmsg; 00132 return status; 00133 } 00134 status = service("IODataManager", m_ioMgr); 00135 if( !status.isSuccess() ) { 00136 log << MSG::ERROR 00137 << "Unable to localize interface from service:IODataManager" << endreq; 00138 return status; 00139 } 00140 status = service("FileCatalog", m_catalog); 00141 if( !status.isSuccess() ) { 00142 log << MSG::ERROR 00143 << "Unable to localize interface from service:FileCatalog" << endreq; 00144 return status; 00145 } 00146 DbOptionCallback cb(m_cacheSvc->callbackHandler()); 00147 if ( m_domH.open(m_cacheSvc->session(),m_type,pool::UPDATE).isSuccess() ) { 00148 SmartIF<IProperty> prp(m_ioMgr); 00149 IntegerProperty ageLimit; 00150 ageLimit.assign(prp->getProperty("AgeLimit")); 00151 log << MSG::DEBUG << "POOL agelimit is set to " << ageLimit.value() << endmsg; 00152 m_domH.setAgeLimit(ageLimit.value()); 00153 return S_OK; 00154 } 00155 return S_OK; 00156 } 00157 00159 StatusCode PoolDbCnvSvc::finalize() { 00160 MsgStream log(messageService(),name()); 00161 DbOptionCallback cb(m_cacheSvc->callbackHandler()); 00162 if ( m_ioMgr ) { 00163 if ( ::toupper(m_shareFiles[0]) != 'Y' ) { 00164 IIODataManager::Connections cons = m_ioMgr->connections(this); 00165 for(IIODataManager::Connections::iterator i=cons.begin(); i != cons.end(); ++i) { 00166 if ( m_ioMgr->disconnect(*i).isSuccess() ) { 00167 log << MSG::INFO << "Disconnected data IO:" << (*i)->fid(); 00168 log << "[" << (*i)->pfn() << "]"; 00169 log << endmsg; 00170 delete (*i); 00171 } 00172 } 00173 } 00174 else { 00175 log << MSG::INFO << "File sharing enabled. Do not retire files." << endmsg; 00176 } 00177 m_ioMgr->release(); 00178 m_ioMgr = 0; 00179 } 00180 m_domH.close(); 00181 m_domH = 0; 00182 if ( m_dataMgr ) m_dataMgr->clearStore().ignore(); 00183 pool::releasePtr(m_dataMgr); 00184 pool::releasePtr(m_catalog); 00185 pool::releasePtr(m_cacheSvc); 00186 StatusCode status = ConversionSvc::finalize(); 00187 log << MSG::DEBUG << "POOL conversion service finalized " << name() << " "; 00188 log << (const char*)(status.isSuccess() ? "successfully" : "with errors") << endmsg; 00189 return status; 00190 } 00191 00193 StatusCode PoolDbCnvSvc::updateServiceState(IOpaqueAddress* /* pAddr */) { 00194 return S_OK; 00195 } 00196 00198 IConverter* 00199 PoolDbCnvSvc::createConverter(long typ,const CLID& wanted,const ICnvFactory*) 00200 { 00201 IConverter* pConverter; 00202 ConverterID cnvid(POOL_StorageType, wanted); 00203 pConverter = PluginService::CreateWithId<IConverter*>(cnvid, typ, wanted, serviceLocator()); 00204 if ( 0 == pConverter ) { 00205 const CLID gen_clids[] = { 00206 /* ObjectList */ CLID_Any + CLID_ObjectList, 00207 /* ObjectVector */ CLID_Any + CLID_ObjectVector, 00208 /* Keyed Map */ CLID_Any + CLID_ObjectVector+0x00030000, 00209 /* Keyed Hashmap */ CLID_Any + CLID_ObjectVector+0x00040000, 00210 /* Keyed redirection array */ CLID_Any + CLID_ObjectVector+0x00050000, 00211 /* Standard, non-container */ CLID_Any 00212 }; 00213 for ( unsigned int i = 0; i < sizeof(gen_clids)/sizeof(gen_clids[0]); i++ ) { 00214 if ( (wanted>>16) == (gen_clids[i]>>16) ) { 00215 ConverterID cnvid(POOL_StorageType, gen_clids[i]); 00216 pConverter = PluginService::CreateWithId<IConverter*>(cnvid, typ, wanted, serviceLocator()); 00217 if ( 0 != pConverter ) { 00218 return pConverter; 00219 } 00220 } 00221 } 00222 // Check if a converter using object update is needed 00223 if ( (wanted>>24) != 0 ) { 00224 ConverterID cnvid(POOL_StorageType, CLID_Any | 1<<31); 00225 pConverter = PluginService::CreateWithId<IConverter*>(cnvid, typ, wanted, serviceLocator()); 00226 if ( 0 != pConverter ) { 00227 return pConverter; 00228 } 00229 } 00230 // If we do not have found any suitable container after searching 00231 // for standard containers, we will use the "ANY" converter 00232 // ... and pray for everything will go well. 00233 ConverterID cnvid(POOL_StorageType, CLID_Any); 00234 pConverter = PluginService::CreateWithId<IConverter*>(cnvid, typ, wanted, serviceLocator()); 00235 if ( 0 != pConverter ) { 00236 MsgStream log(msgSvc(), name()); 00237 log << MSG::INFO << "Using \"Any\" converter " 00238 << "for objects of type " 00239 << std::showbase << std::hex << wanted << endmsg; 00240 } 00241 } 00242 return pConverter; 00243 } 00244 00245 void PoolDbCnvSvc::loadConverter(DataObject* pObject) { 00246 if (pObject) { 00247 MsgStream log(msgSvc(), name()); 00248 std::string cname = System::typeinfoName(typeid(*pObject)); 00249 log << MSG::DEBUG << "Trying to 'Autoload' dictionary for class " << cname << endmsg; 00250 gInterpreter->EnableAutoLoading(); 00251 gInterpreter->AutoLoad(cname.c_str()); 00252 } 00253 } 00254 00255 StatusCode PoolDbCnvSvc::setDataProvider(IDataProviderSvc* pDataSvc) { 00256 IDataManagerSvc* tmp = m_dataMgr; 00257 if (pDataSvc) { 00258 StatusCode status = 00259 pDataSvc->queryInterface(IID_IDataManagerSvc, pp_cast<void>(&m_dataMgr)); 00260 if ( !status.isSuccess() ) { 00261 return error("Cannot connect to \"IDataManagerSvc\" interface."); 00262 } 00263 } 00264 if ( tmp ) tmp->release(); 00265 return ConversionSvc::setDataProvider(pDataSvc); 00266 } 00267 00269 StatusCode PoolDbCnvSvc::accessStorageType(CSTR type_string, long& gaudi_type) { 00270 if ( ::strncasecmp(type_string.c_str(), "POOL_ROOTTREE", 10)==0 ) { 00271 gaudi_type = POOL_ROOTTREE_StorageType; 00272 return S_OK; 00273 } 00274 else if ( ::strncasecmp(type_string.c_str(), "POOL_ROOTKEY", 10)==0 ) { 00275 gaudi_type = POOL_ROOTKEY_StorageType; 00276 return S_OK; 00277 } 00278 else if ( ::strncasecmp(type_string.c_str(), "POOL_ROOT", 9)==0 ) { 00279 gaudi_type = POOL_ROOT_StorageType; 00280 return S_OK; 00281 } 00282 gaudi_type = TEST_StorageType; 00283 return S_FAIL; 00284 } 00285 00287 StatusCode PoolDbCnvSvc::connectOutput(CSTR dsn, CSTR openMode) { 00288 StatusCode sc = StatusCode::FAILURE; 00289 DbAccessMode mode = pool::NOT_OPEN; 00290 m_current = 0; 00291 if ( ::strncasecmp(openMode.c_str(),"RECREATE",3)==0 ) 00292 sc = connectDatabase(UNKNOWN, dsn, mode=pool::RECREATE, &m_current); 00293 else if ( ::strncasecmp(openMode.c_str(),"NEW",1)==0 ) 00294 sc = connectDatabase(UNKNOWN, dsn, mode=pool::CREATE, &m_current); 00295 else if ( ::strncasecmp(openMode.c_str(),"CREATE",1)==0 ) 00296 sc = connectDatabase(UNKNOWN, dsn, mode=pool::CREATE, &m_current); 00297 else if ( ::strncasecmp(openMode.c_str(),"UPDATE",1)==0 ) 00298 sc = connectDatabase(UNKNOWN, dsn, mode=pool::UPDATE, &m_current); 00299 if ( sc.isSuccess() && m_current && m_current->isConnected() ) { 00300 return S_OK; 00301 } 00302 error("The dataset "+dsn+" cannot be opened in mode "+openMode+". [Invalid mode]"); 00303 return sc; 00304 } 00305 00306 // Conect output stream (valid until overwritten) 00307 StatusCode PoolDbCnvSvc::connectOutput(CSTR db_name) { 00308 return connectOutput(db_name, "NEW"); 00309 } 00310 00311 // Commit pending output on open container 00312 StatusCode PoolDbCnvSvc::commitOutput(CSTR dsn, bool doCommit) { 00313 if ( m_current ) { 00314 try { 00315 if ( doCommit ) 00316 m_current->transaction().set(m_safeTransactions ? Transaction::TRANSACT_FLUSH : Transaction::TRANSACT_COMMIT); 00317 else 00318 m_current->transaction().set(Transaction::TRANSACT_ROLLBACK); 00319 if ( m_current->database().transAct(m_current->transaction()).isSuccess() ) { 00320 return S_OK; 00321 } 00322 std::string action(doCommit ? "commit to" : "rollback"); 00323 return error("commitOutput> Cannot "+action+" database:"+dsn); 00324 } 00325 catch (std::exception& e) { 00326 error(std::string("commitOutput> Caught exception:")+e.what(), false); 00327 } 00328 catch (...) { 00329 error("commitOutput> Unknown Fatal Exception on commit to "+dsn, false); 00330 } 00331 } 00332 return error("commitOutput> Cannot connect to database: "+dsn); 00333 } 00334 00335 // Connect to a POOL container in read mode 00336 StatusCode PoolDbCnvSvc::connect(CSTR dsn, CSTR cntName, DbContainer& cntH) { 00337 return connectContainer(UNKNOWN, dsn, cntName, pool::READ, 0, cntH); 00338 } 00339 00341 StatusCode 00342 PoolDbCnvSvc::connectDatabase(int typ, CSTR dataset, DbAccessMode mode, PoolDbDataConnection** con) { 00343 try { 00344 DbOptionCallback cb(m_cacheSvc->callbackHandler()); 00345 IDataConnection* c = m_ioMgr->connection(dataset); 00346 if ( !c ) { 00347 DbType dbType(DbType(m_type).majorType()); 00348 std::auto_ptr<IDataConnection> connection(new PoolDbDataConnection(this,dataset,typ,mode,m_domH)); 00349 StatusCode sc = (mode == pool::READ) 00350 ? m_ioMgr->connectRead(false,connection.get()) 00351 : m_ioMgr->connectWrite(connection.get(),IDataConnection::IoType(mode),dbType.storageName()); 00352 c = sc.isSuccess() ? m_ioMgr->connection(dataset) : 0; 00353 if ( c ) connection.release(); 00354 else return sc; 00355 } 00356 PoolDbDataConnection* pc = dynamic_cast<PoolDbDataConnection*>(c); 00357 if ( pc ) { 00358 if ( !pc->isConnected() ) pc->connectRead(); 00359 static int wr = pool::RECREATE|pool::CREATE|pool::UPDATE; 00360 // Got a valid connection. Now rearm the transaction 00361 checkAccessMode(mode, pc->database()); 00362 if ( (mode&wr) != 0 ) { 00363 pc->transaction().set(pool::Transaction::TRANSACT_START); 00364 if ( !pc->database().transAct(pc->transaction()).isSuccess() ) 00365 return StatusCode::FAILURE; 00366 } 00367 *con = pc; 00368 pc->resetAge(); 00369 } 00370 return *con ? StatusCode::SUCCESS : StatusCode::FAILURE; 00371 } 00372 catch (std::exception& e) { 00373 return error(std::string("connectDatabase> Caught exception:")+e.what(), false); 00374 } 00375 catch (...) { 00376 return error("connectDatabase> Unknown Fatal Exception for "+dataset, false); 00377 } 00378 } 00379 00380 StatusCode 00381 PoolDbCnvSvc::connectContainer(int type, 00382 CSTR dbName, 00383 CSTR cntName, 00384 DbAccessMode mode, 00385 const DbTypeInfo* info, 00386 DbContainer& cntH) 00387 { 00388 PoolDbDataConnection* c = 0; 00389 StatusCode sc = connectDatabase(type, dbName, mode, &c); 00390 if( sc.isSuccess() ) { 00391 return connectContainer(c->database(), cntName, mode, info, cntH); 00392 } 00393 return sc; 00394 } 00395 00396 StatusCode 00397 PoolDbCnvSvc::connectContainer(DbDatabase& dbH, 00398 CSTR cntName, 00399 DbAccessMode mode, 00400 const DbTypeInfo* shapeH, 00401 DbContainer& cntH) 00402 { 00403 std::string pfn, fid; 00404 int all = pool::READ + pool::CREATE + pool::UPDATE; 00405 int wr = pool::CREATE + pool::UPDATE; 00406 if ( dbH.isValid() ) { 00407 fid = dbH.token()->dbID(); 00408 pfn = dbH.token()->contID(); 00409 int m = dbH.openMode(); 00410 if ( (m&all) && mode == pool::READ ) { 00411 } 00412 else if ( m&wr && mode&pool::CREATE ) { 00413 } 00414 else if ( m&wr && mode&pool::UPDATE ) { 00415 } 00416 else { 00417 dbH.reopen(pool::UPDATE); 00418 } 00419 } 00420 // No Else! 00421 if ( !dbH.isValid() ) { 00422 error("Cannot connect to Database: FID="+fid+" PFN="+pfn+ 00423 " [Invalid database handle]",false); 00424 return StatusCode::FAILURE; 00425 } 00426 cntH = DbContainer(dbH.find(cntName)); 00427 if ( cntH.isValid() ) { 00428 return StatusCode::SUCCESS; 00429 } 00430 if ( mode&pool::READ ) { 00431 shapeH = dbH.contShape(cntName); 00432 } 00433 if ( shapeH ) { 00434 if ( cntH.open(dbH, cntName, shapeH, m_type, mode).isSuccess() ) { 00435 return StatusCode::SUCCESS; 00436 } 00437 return error("connectContainer> Failed to open container:"+cntName+ 00438 " in "+dbH.name(),false); 00439 } 00440 return error("connectContainer> No shape present for container:"+cntName+ 00441 " in "+dbH.name(),false); 00442 } 00443 00444 // Disconnect from an existing data stream. 00445 StatusCode PoolDbCnvSvc::disconnect(CSTR dataset) { 00446 IDataConnection* c = m_ioMgr->connection(dataset); 00447 return c ? m_ioMgr->disconnect(c) : S_FAIL; 00448 } 00449 00450 // Request an iterator over a container from the service 00451 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria,CSTR db,CSTR cnt) { 00452 PoolDbDataConnection* c = 0; 00453 StatusCode sc = connectDatabase(UNKNOWN, db, pool::READ, &c); 00454 if ( sc.isSuccess() ) { 00455 // Now select according to criteria 00456 std::auto_ptr<pool::DbSelect> sel(new pool::DbSelect(criteria)); 00457 if ( sel->start(c->database(), cnt).isSuccess() ) { 00458 return sel.release(); 00459 } 00460 return 0; 00461 } 00462 error("createSelect> Cannot open database:"+db, false); 00463 return 0; 00464 } 00465 00467 StatusCode PoolDbCnvSvc::createAddress( long typ, 00468 const CLID& clid, 00469 const std::string* par, 00470 const unsigned long* ip, 00471 IOpaqueAddress*& refpAddress) 00472 { 00473 PoolDbAddress* pA = 0; 00474 pool::Guid guid = pool::Guid::null(); 00475 std::auto_ptr<pool::Token> tok(new pool::Token()); 00476 guid.Data1 = clid; 00477 tok->setDb(par[0]); 00478 tok->setCont(par[1]); 00479 tok->setTechnology(typ); 00480 tok->setClassID(guid); 00481 tok->oid().first = ip[0]; 00482 tok->oid().second = ip[1]; 00483 if ( createAddress(tok.get(), &pA).isSuccess() ) { 00484 refpAddress = pA; 00485 tok->release(); 00486 tok.release(); 00487 return S_OK; 00488 } 00489 return error("createAddress> Failed to create opaque address."); 00490 } 00491 00492 // Create an opaque address from a POOL token structure 00493 StatusCode PoolDbCnvSvc::createAddress(pool::Token* pTok,PoolDbAddress** ppAdd) { 00494 if ( pTok ) { 00495 *ppAdd = new PoolDbAddress(pTok); 00496 return S_OK; 00497 } 00498 return error("createAddress> Failed to create opaque address from POOL token."); 00499 } 00500 00501 // Mark an object for write given an object reference 00502 StatusCode 00503 PoolDbCnvSvc::markWrite(pool::DataCallBack* call,CSTR cntName,PoolDbAddress** ppAddr) 00504 { 00505 if ( m_current ) { 00506 DbOptionCallback call_back(m_cacheSvc->callbackHandler()); 00507 const DbTypeInfo* shapeH = (const DbTypeInfo*)call->shape(); 00508 DbDatabase& dbH = m_current->database(); 00509 if ( dbH.transactionActive() ) { 00510 std::auto_ptr<pool::Token> token(new pool::Token()); 00511 token->setDb(dbH.name()).setCont(cntName); 00512 token->setClassID(shapeH->shapeID()); 00513 token->setTechnology(m_type); 00514 DbContainer cntH(POOL_StorageType); 00515 StatusCode sc = connectContainer(dbH,cntName,pool::UPDATE|pool::CREATE,shapeH,cntH); 00516 if ( sc.isSuccess() ) { 00517 call->setHandler(&m_handler); 00518 if ( cntH.allocate(call, token->oid()).isSuccess() ) { 00519 if ( dbH.makeLink(token.get(), token->oid()).isSuccess() ) { 00520 if ( ppAddr ) { 00521 if ( *ppAddr ) { 00522 (*ppAddr)->token()->setData(token.get()); 00523 } 00524 else { 00525 *ppAddr = new PoolDbAddress(token.get()); 00526 } 00527 } 00528 long cnt = token->release(); 00529 if ( cnt > 1 ) { 00530 MsgStream log(messageService(), name()); 00531 log << MSG::ERROR << "markWrite> Token count wrong: " 00532 << cnt << " expect memory leak. " << endmsg 00533 << "run again with environment POOLDB_TRACE=ON and" 00534 << " check instance counts." << endmsg; 00535 } 00536 token.release(); 00537 return S_OK; 00538 } 00539 } 00540 } 00541 } 00542 return error("markWrite> No active transaction present for "+dbH.name()); 00543 } 00544 return error("markWrite> Current Database is invalid!"); 00545 } 00546 00547 // Mark an object for update 00548 StatusCode PoolDbCnvSvc::markUpdate(pool::DataCallBack* call, PoolDbAddress* pA) { 00549 if ( pA && call ) { 00550 pool::Token* tok = pA->token(); 00551 DbContainer cntH(POOL_StorageType); 00552 const DbTypeInfo* info = (const DbTypeInfo*)call->shape(); 00553 StatusCode sc = connectContainer(FID,tok->dbID(),tok->contID(),pool::UPDATE,info,cntH); 00554 if ( sc.isSuccess() ) { 00555 call->setHandler(&m_handler); 00556 if ( cntH.update(call, tok->oid()).isSuccess() ) { 00557 return S_OK; 00558 } 00559 return error("markUpdate> Failed to update object:"+tok->toString()); 00560 } 00561 MsgStream log(messageService(), name()); 00562 log << MSG::ERROR << "markUpdate> The container " 00563 << tok->dbID() << "::" << tok->contID() 00564 << " cannot be accessed." << endmsg 00565 << "Was this object really read from the container " 00566 << "the object token claims?" 00567 << endmsg; 00568 return S_FAIL; 00569 } 00570 return error("createRep> Invalid object address for update."); 00571 } 00572 00574 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, PoolDbAddress* pA) { 00575 StatusCode sc = read(call, *pA->token()); 00576 if ( sc.isSuccess() || sc == BAD_DATA_CONNECTION ) { 00577 return sc; 00578 } 00579 std::string err="read> Cannot read object:"+pA->registry()->identifier()+" "; 00580 return error(err, false); 00581 } 00582 00584 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, pool::Token& tok) { 00585 try { 00586 DbContainer cntH(tok.technology()); 00587 const DbTypeInfo* info = (const DbTypeInfo*)call->shape(); 00588 StatusCode sc = connectContainer(FID,tok.dbID(),tok.contID(),pool::READ,info,cntH); 00589 if ( sc.isSuccess() ) { 00590 typedef pool::DbObjectHandle<pool::DbObject> ObjH; 00591 call->setHandler(&m_handler); 00592 return ObjH::openEx(cntH, tok, call, pool::READ).isSuccess() ? S_OK : S_FAIL; 00593 } 00594 else if ( sc == BAD_DATA_CONNECTION ) { 00595 return sc; 00596 } 00597 } 00598 catch (std::exception& e) { 00599 std::string err="read> Cannot read object:"+tok.toString()+" "; 00600 return error(err+e.what(), false); 00601 } 00602 catch (...) { 00603 std::string err = "read> Cannot read object:"+tok.toString(); 00604 return error(err+" [Unknown fatal exception]", false); 00605 } 00606 return error("read> Cannot read object:"+tok.toString(), false); 00607 } 00608 00609 // Small routine to issue exceptions 00610 StatusCode PoolDbCnvSvc::error(CSTR msg, bool rethrow) { 00611 if ( rethrow ) { 00612 pool::debugBreak("PoolDbCnvSvc", "Error:"+msg, rethrow); 00613 } 00614 else { 00615 MsgStream log(messageService(),name()); 00616 log << MSG::ERROR << "Error: " << msg << endmsg; 00617 } 00618 return S_FAIL; 00619 }