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 cnvid1(POOL_StorageType, gen_clids[i]);
00215 pConverter = PluginService::CreateWithId<IConverter*>(cnvid1, typ, wanted, serviceLocator().get());
00216 if ( 0 != pConverter ) {
00217 return pConverter;
00218 }
00219 }
00220 }
00221
00222 if ( (wanted>>24) != 0 ) {
00223 ConverterID cnvid1(POOL_StorageType, CLID_Any | 1<<31);
00224 pConverter = PluginService::CreateWithId<IConverter*>(cnvid1, typ, wanted, serviceLocator().get());
00225 if ( 0 != pConverter ) {
00226 return pConverter;
00227 }
00228 }
00229
00230
00231
00232 ConverterID cnvid1(POOL_StorageType, CLID_Any);
00233 pConverter = PluginService::CreateWithId<IConverter*>(cnvid1, 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 m_current = 0;
00289 if ( ::strncasecmp(openMode.c_str(),"RECREATE",3)==0 )
00290 sc = connectDatabase(UNKNOWN, dsn, pool::RECREATE, &m_current);
00291 else if ( ::strncasecmp(openMode.c_str(),"NEW",1)==0 )
00292 sc = connectDatabase(UNKNOWN, dsn, pool::CREATE, &m_current);
00293 else if ( ::strncasecmp(openMode.c_str(),"CREATE",1)==0 )
00294 sc = connectDatabase(UNKNOWN, dsn, pool::CREATE, &m_current);
00295 else if ( ::strncasecmp(openMode.c_str(),"UPDATE",1)==0 )
00296 sc = connectDatabase(UNKNOWN, dsn, pool::UPDATE, &m_current);
00297 if ( sc.isSuccess() && m_current && m_current->isConnected() ) {
00298 return S_OK;
00299 }
00300 m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
00301 error("The dataset "+dsn+" cannot be opened in mode "+openMode+". [Invalid mode]");
00302 return sc;
00303 }
00304
00305
00306 StatusCode PoolDbCnvSvc::connectOutput(CSTR db_name) {
00307 return connectOutput(db_name, "NEW");
00308 }
00309
00310
00311 StatusCode PoolDbCnvSvc::commitOutput(CSTR dsn, bool doCommit) {
00312 if ( m_current ) {
00313 try {
00314 if ( doCommit )
00315 m_current->transaction().set(m_safeTransactions ? Transaction::TRANSACT_FLUSH : Transaction::TRANSACT_COMMIT);
00316 else
00317 m_current->transaction().set(Transaction::TRANSACT_ROLLBACK);
00318 if ( m_current->database().transAct(m_current->transaction()).isSuccess() ) {
00319 return S_OK;
00320 }
00321 std::string action(doCommit ? "commit to" : "rollback");
00322 m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
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 m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
00333 return error("commitOutput> Cannot connect to database: "+dsn);
00334 }
00335
00336
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 bool fire_incident = false;
00348 if ( !c ) {
00349 DbType dbType(DbType(m_type).majorType());
00350 std::auto_ptr<IDataConnection> connection(new PoolDbDataConnection(this,dataset,typ,mode,m_domH));
00351 StatusCode sc = (mode == pool::READ)
00352 ? m_ioMgr->connectRead(false,connection.get())
00353 : m_ioMgr->connectWrite(connection.get(),IDataConnection::IoType(mode),dbType.storageName());
00354 c = sc.isSuccess() ? m_ioMgr->connection(dataset) : 0;
00355 if ( c ) {
00356 fire_incident = m_incidentEnabled && (0 != (mode&(pool::UPDATE|pool::READ)));
00357 connection.release();
00358 }
00359 else {
00360 return sc;
00361 }
00362 }
00363 PoolDbDataConnection* pc = dynamic_cast<PoolDbDataConnection*>(c);
00364 if ( pc ) {
00365 if ( !pc->isConnected() ) pc->connectRead();
00366 static int wr = pool::RECREATE|pool::CREATE|pool::UPDATE;
00367
00368 checkAccessMode(mode, pc->database());
00369 if ( (mode&wr) != 0 ) {
00370 pc->transaction().set(pool::Transaction::TRANSACT_START);
00371 if ( !pc->database().transAct(pc->transaction()).isSuccess() )
00372 return StatusCode::FAILURE;
00373 }
00374 *con = pc;
00375 pc->resetAge();
00376 }
00377 if ( *con ) {
00378 if ( fire_incident ) {
00379 PoolDbAddress* pAddr = 0;
00380 MsgStream log(msgSvc(), name());
00381 pool::Token* token = 0, *prev = 0;
00382 DbDatabase& dbH = pc->database();
00383 if ( dbH.cntToken(m_recordName) ) {
00384 std::auto_ptr<pool::DbSelect> sel(createSelect("*",dbH,m_recordName));
00385 if ( sel.get() ) {
00386 while(1) {
00387 if ( prev ) prev->release();
00388 prev = token;
00389 if ( prev ) prev->addRef();
00390 if ( !sel->next(token).isSuccess() ) break;
00391 }
00392 }
00393 if ( prev ) {
00394 log << MSG::INFO << "Records token:" << prev->toString() << endmsg;
00395 if ( !createAddress(prev,&pAddr).isSuccess() ) {
00396 prev->release();
00397 }
00398 }
00399 else {
00400 log << MSG::INFO << "No Record " << m_recordName << " entries present in:" << c->fid() << endmsg;
00401 }
00402 }
00403 else {
00404 log << MSG::INFO << "No Records " << m_recordName << " present in:" << c->fid() << endmsg;
00405 }
00406 m_incidentSvc->fireIncident(ContextIncident<IOpaqueAddress*>(c->fid(),"FILE_OPEN_READ",pAddr));
00407 }
00408 return StatusCode::SUCCESS;
00409 }
00410 m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
00411 return StatusCode::FAILURE;
00412 }
00413 catch (std::exception& e) {
00414 m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
00415 return error(std::string("connectDatabase> Caught exception:")+e.what(), false);
00416 }
00417 catch (...) {
00418 m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
00419 return error("connectDatabase> Unknown Fatal Exception for "+dataset, false);
00420 }
00421 }
00422
00423 StatusCode
00424 PoolDbCnvSvc::connectContainer(int type,
00425 CSTR dbName,
00426 CSTR cntName,
00427 DbAccessMode mode,
00428 const DbTypeInfo* info,
00429 DbContainer& cntH)
00430 {
00431 PoolDbDataConnection* c = 0;
00432 StatusCode sc = connectDatabase(type, dbName, mode, &c);
00433 if( sc.isSuccess() ) {
00434 return connectContainer(c->database(), cntName, mode, info, cntH);
00435 }
00436 return sc;
00437 }
00438
00439 StatusCode
00440 PoolDbCnvSvc::connectContainer(DbDatabase& dbH,
00441 CSTR cntName,
00442 DbAccessMode mode,
00443 const DbTypeInfo* shapeH,
00444 DbContainer& cntH)
00445 {
00446 std::string pfn, fid;
00447 int all = pool::READ + pool::CREATE + pool::UPDATE;
00448 int wr = pool::CREATE + pool::UPDATE;
00449 if ( dbH.isValid() ) {
00450 fid = dbH.token()->dbID();
00451 pfn = dbH.token()->contID();
00452 int m = dbH.openMode();
00453 if ( (m&all) && mode == pool::READ ) {
00454 }
00455 else if ( m&wr && mode&pool::CREATE ) {
00456 }
00457 else if ( m&wr && mode&pool::UPDATE ) {
00458 }
00459 else {
00460 dbH.reopen(pool::UPDATE);
00461 }
00462 }
00463
00464 if ( !dbH.isValid() ) {
00465 m_incidentSvc->fireIncident(Incident(pfn,IncidentType::FailOutputFile));
00466 error("Cannot connect to Database: FID="+fid+" PFN="+pfn+
00467 " [Invalid database handle]",false);
00468 return StatusCode::FAILURE;
00469 }
00470 cntH = DbContainer(dbH.find(cntName));
00471 if ( cntH.isValid() ) {
00472 return StatusCode::SUCCESS;
00473 }
00474 if ( mode&pool::READ ) {
00475 shapeH = dbH.contShape(cntName);
00476 }
00477 if ( shapeH ) {
00478 if ( cntH.open(dbH, cntName, shapeH, m_type, mode).isSuccess() ) {
00479 return StatusCode::SUCCESS;
00480 }
00481 return error("connectContainer> Failed to open container:"+cntName+
00482 " in "+dbH.name(),false);
00483 }
00484 return error("connectContainer> No shape present for container:"+cntName+
00485 " in "+dbH.name(),false);
00486 }
00487
00488
00489 StatusCode PoolDbCnvSvc::disconnect(CSTR dataset) {
00490 IDataConnection* c = m_ioMgr->connection(dataset);
00491 return c ? m_ioMgr->disconnect(c) : S_FAIL;
00492 }
00493
00494
00495 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, CSTR db, CSTR cnt) {
00496 PoolDbDataConnection* c = 0;
00497 StatusCode sc = connectDatabase(UNKNOWN, db, pool::READ, &c);
00498 if ( sc.isSuccess() ) {
00499 return createSelect(criteria,c->database(), cnt);
00500 }
00501 error("createSelect> Cannot open database:"+db, false);
00502 m_incidentSvc->fireIncident(Incident(db,IncidentType::FailInputFile));
00503 return 0;
00504 }
00505
00506
00507 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, DbDatabase& dbH, CSTR cnt) {
00508
00509 std::auto_ptr<pool::DbSelect> sel(new pool::DbSelect(criteria));
00510 if ( sel->start(dbH, cnt).isSuccess() ) {
00511 return sel.release();
00512 }
00513 return 0;
00514 }
00515
00517 StatusCode PoolDbCnvSvc::createAddress( long typ,
00518 const CLID& clid,
00519 const std::string* par,
00520 const unsigned long* ip,
00521 IOpaqueAddress*& refpAddress)
00522 {
00523 PoolDbAddress* pA = 0;
00524 pool::Guid guid = pool::Guid::null();
00525 std::auto_ptr<pool::Token> tok(new pool::Token());
00526 guid.Data1 = clid;
00527 tok->setDb(par[0]);
00528 tok->setCont(par[1]);
00529 tok->setTechnology(typ);
00530 tok->setClassID(guid);
00531 tok->oid().first = ip[0];
00532 tok->oid().second = ip[1];
00533 if ( createAddress(tok.get(), &pA).isSuccess() ) {
00534 refpAddress = pA;
00535 tok->release();
00536 tok.release();
00537 return S_OK;
00538 }
00539 return error("createAddress> Failed to create opaque address.");
00540 }
00541
00542
00543 StatusCode PoolDbCnvSvc::createAddress(pool::Token* pTok,PoolDbAddress** ppAdd) {
00544 if ( pTok ) {
00545 *ppAdd = new PoolDbAddress(pTok);
00546 return S_OK;
00547 }
00548 return error("createAddress> Failed to create opaque address from POOL token.");
00549 }
00550
00551
00552 StatusCode
00553 PoolDbCnvSvc::markWrite(pool::DataCallBack* call,CSTR cntName,PoolDbAddress** ppAddr)
00554 {
00555 if ( m_current ) {
00556 DbOptionCallback call_back(m_cacheSvc->callbackHandler());
00557 const DbTypeInfo* shapeH = (const DbTypeInfo*)call->shape();
00558 DbDatabase& dbH = m_current->database();
00559 if ( dbH.transactionActive() ) {
00560 std::auto_ptr<pool::Token> token(new pool::Token());
00561 token->setDb(dbH.name()).setCont(cntName);
00562 token->setClassID(shapeH->shapeID());
00563 token->setTechnology(m_type);
00564 DbContainer cntH(POOL_StorageType);
00565 StatusCode sc = connectContainer(dbH,cntName,pool::UPDATE|pool::CREATE,shapeH,cntH);
00566 if ( sc.isSuccess() ) {
00567 call->setHandler(&m_handler);
00568 if ( cntH.allocate(call, token->oid()).isSuccess() ) {
00569 if ( dbH.makeLink(token.get(), token->oid()).isSuccess() ) {
00570 if ( ppAddr ) {
00571 if ( *ppAddr ) {
00572 (*ppAddr)->token()->setData(token.get());
00573 }
00574 else {
00575 *ppAddr = new PoolDbAddress(token.get());
00576 }
00577 }
00578 long cnt = token->release();
00579 if ( cnt > 1 ) {
00580 MsgStream log(msgSvc(), name());
00581 log << MSG::ERROR << "markWrite> Token count wrong: "
00582 << cnt << " expect memory leak. " << endmsg
00583 << "run again with environment POOLDB_TRACE=ON and"
00584 << " check instance counts." << endmsg;
00585 }
00586 token.release();
00587 return S_OK;
00588 }
00589 }
00590 }
00591 }
00592 return error("markWrite> No active transaction present for "+dbH.name());
00593 }
00594 return error("markWrite> Current Database is invalid!");
00595 }
00596
00597
00598 StatusCode PoolDbCnvSvc::markUpdate(pool::DataCallBack* call, PoolDbAddress* pA) {
00599 if ( pA && call ) {
00600 pool::Token* tok = pA->token();
00601 DbContainer cntH(POOL_StorageType);
00602 const DbTypeInfo* info = (const DbTypeInfo*)call->shape();
00603 StatusCode sc = connectContainer(FID,tok->dbID(),tok->contID(),pool::UPDATE,info,cntH);
00604 if ( sc.isSuccess() ) {
00605 call->setHandler(&m_handler);
00606 if ( cntH.update(call, tok->oid()).isSuccess() ) {
00607 return S_OK;
00608 }
00609 return error("markUpdate> Failed to update object:"+tok->toString());
00610 }
00611 MsgStream log(msgSvc(), name());
00612 log << MSG::ERROR << "markUpdate> The container "
00613 << tok->dbID() << "::" << tok->contID()
00614 << " cannot be accessed." << endmsg
00615 << "Was this object really read from the container "
00616 << "the object token claims?"
00617 << endmsg;
00618 return S_FAIL;
00619 }
00620 return error("createRep> Invalid object address for update.");
00621 }
00622
00624 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, PoolDbAddress* pA) {
00625 StatusCode sc = read(call, *pA->token());
00626 if ( sc.isSuccess() || sc == BAD_DATA_CONNECTION ) {
00627 return sc;
00628 }
00629 std::string err="read> Cannot read object:"+pA->registry()->identifier()+" ";
00630 return error(err, false);
00631 }
00632
00634 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, pool::Token& tok) {
00635 try {
00636 DbContainer cntH(tok.technology());
00637 const DbTypeInfo* info = (const DbTypeInfo*)call->shape();
00638 StatusCode sc = connectContainer(FID,tok.dbID(),tok.contID(),pool::READ,info,cntH);
00639 if ( sc.isSuccess() ) {
00640 typedef pool::DbObjectHandle<pool::DbObject> ObjH;
00641 call->setHandler(&m_handler);
00642 return ObjH::openEx(cntH, tok, call, pool::READ).isSuccess() ? S_OK : S_FAIL;
00643 }
00644 else if ( sc == BAD_DATA_CONNECTION ) {
00645 return sc;
00646 }
00647 }
00648 catch (std::exception& e) {
00649 std::string err="read> Cannot read object:"+tok.toString()+" ";
00650 return error(err+e.what(), false);
00651 }
00652 catch (...) {
00653 std::string err = "read> Cannot read object:"+tok.toString();
00654 return error(err+" [Unknown fatal exception]", false);
00655 }
00656 return error("read> Cannot read object:"+tok.toString(), false);
00657 }
00658
00659
00660 StatusCode PoolDbCnvSvc::error(CSTR msg, bool rethrow) {
00661 if ( rethrow ) {
00662 pool::debugBreak("PoolDbCnvSvc", "Error:"+msg, rethrow);
00663 }
00664 else {
00665 MsgStream log(msgSvc(),name());
00666 log << MSG::ERROR << "Error: " << msg << endmsg;
00667 }
00668 return S_FAIL;
00669 }