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