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