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