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