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