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