| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

# PoolDbCnvSvc.cpp

Go to the documentation of this file.

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