| # Gaudi Framework, version v21r8 |

Home |  | Generated: 17 Mar 2010

# PoolDbCnvSvc.cpp

Go to the documentation of this file.

    00001 // $Id: PoolDbCnvSvc.cpp,v 1.30 2008/10/27 16:41:33 marcocle Exp $
    00002 //====================================================================
    00003 //      PoolDbCnvSvc implementation
    00004 //--------------------------------------------------------------------
    00005 //
    00006 //  Description: Implementation of the POOL data storage
    00007 //
    00008 //      Author     : M.Frank
    00009 //
    00010 //====================================================================
    00011 // Framework include files
    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 // POOL include files
    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 //ROOT include files
    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* /* pAddr */)  {
    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     /* ObjectList               */ CLID_Any + CLID_ObjectList,
    00206     /* ObjectVector             */ CLID_Any + CLID_ObjectVector,
    00207     /* Keyed Map                */ CLID_Any + CLID_ObjectVector+0x00030000,
    00208     /* Keyed Hashmap            */ CLID_Any + CLID_ObjectVector+0x00040000,
    00209     /* Keyed redirection array  */ CLID_Any + CLID_ObjectVector+0x00050000,
    00210     /* Standard, non-container  */ CLID_Any
    00211     };
    00212     for ( unsigned int i = 0; i < sizeof(gen_clids)/sizeof(gen_clids[0]); i++ ) {
    00213       if ( (wanted>>16) == (gen_clids[i]>>16) )  {
    00214         ConverterID cnvid1(POOL_StorageType, gen_clids[i]);
    00215         pConverter = PluginService::CreateWithId<IConverter*>(cnvid1, typ, wanted, serviceLocator().get());
    00216         if ( 0 != pConverter ) {
    00217           return pConverter;
    00218         }
    00219       }
    00220     }
    00221     // Check if a converter using object update is needed
    00222     if ( (wanted>>24) != 0 )  {
    00223       ConverterID cnvid1(POOL_StorageType, CLID_Any | 1<<31);
    00224       pConverter = PluginService::CreateWithId<IConverter*>(cnvid1, typ, wanted, serviceLocator().get());
    00225       if ( 0 != pConverter ) {
    00226         return pConverter;
    00227       }
    00228     }
    00229     // If we do not have found any suitable container after searching
    00230     // for standard containers, we will use the "ANY" converter
    00231     // ... and pray for everything will go well.
    00232     ConverterID cnvid1(POOL_StorageType, CLID_Any);
    00233     pConverter = PluginService::CreateWithId<IConverter*>(cnvid1, typ, wanted, serviceLocator().get());
    00234     if ( 0 != pConverter ) {
    00235       MsgStream log(msgSvc(), name());
    00236       log << MSG::INFO << "Using \"Any\" converter "
    00237           << "for objects of type "
    00238           << std::showbase << std::hex << wanted << endmsg;
    00239     }
    00240   }
    00241   return pConverter;
    00242 }
    00243
    00244 void PoolDbCnvSvc::loadConverter(DataObject* pObject) {
    00245   if (pObject) {
    00246     MsgStream log(msgSvc(), name());
    00247     std::string cname = System::typeinfoName(typeid(*pObject));
    00248     log << MSG::DEBUG << "Trying to 'Autoload' dictionary for class " << cname << endmsg;
    00249     gInterpreter->EnableAutoLoading();
    00250     gInterpreter->AutoLoad(cname.c_str());
    00251   }
    00252 }
    00253
    00254 StatusCode PoolDbCnvSvc::setDataProvider(IDataProviderSvc* pDataSvc)  {
    00255   IDataManagerSvc* tmp = m_dataMgr;
    00256   if (pDataSvc)  {
    00257     StatusCode status =
    00258       pDataSvc->queryInterface(IDataManagerSvc::interfaceID(), pp_cast<void>(&m_dataMgr));
    00259     if ( !status.isSuccess() )    {
    00260       return error("Cannot connect to \"IDataManagerSvc\" interface.");
    00261     }
    00262   }
    00263   if ( tmp ) tmp->release();
    00264   return ConversionSvc::setDataProvider(pDataSvc);
    00265 }
    00266
    00268 StatusCode PoolDbCnvSvc::accessStorageType(CSTR type_string, long& gaudi_type) {
    00269   if ( ::strncasecmp(type_string.c_str(), "POOL_ROOTTREE", 10)==0 ) {
    00270     gaudi_type  = POOL_ROOTTREE_StorageType;
    00271     return S_OK;
    00272   }
    00273   else if ( ::strncasecmp(type_string.c_str(), "POOL_ROOTKEY", 10)==0 ) {
    00274     gaudi_type  = POOL_ROOTKEY_StorageType;
    00275     return S_OK;
    00276   }
    00277   else if ( ::strncasecmp(type_string.c_str(), "POOL_ROOT", 9)==0 ) {
    00278     gaudi_type  = POOL_ROOT_StorageType;
    00279     return S_OK;
    00280   }
    00281   gaudi_type = TEST_StorageType;
    00282   return S_FAIL;
    00283 }
    00284
    00286 StatusCode PoolDbCnvSvc::connectOutput(CSTR dsn, CSTR openMode)   {
    00287   StatusCode sc = StatusCode::FAILURE;
    00288   m_current = 0;
    00289   if ( ::strncasecmp(openMode.c_str(),"RECREATE",3)==0 )
    00290     sc = connectDatabase(UNKNOWN, dsn, pool::RECREATE, &m_current);
    00291   else if ( ::strncasecmp(openMode.c_str(),"NEW",1)==0 )
    00292     sc = connectDatabase(UNKNOWN, dsn, pool::CREATE, &m_current);
    00293   else if ( ::strncasecmp(openMode.c_str(),"CREATE",1)==0 )
    00294     sc = connectDatabase(UNKNOWN, dsn, pool::CREATE, &m_current);
    00295   else if ( ::strncasecmp(openMode.c_str(),"UPDATE",1)==0 )
    00296     sc = connectDatabase(UNKNOWN, dsn, pool::UPDATE, &m_current);
    00297   if ( sc.isSuccess() && m_current && m_current->isConnected() )  {
    00298     return S_OK;
    00299   }
    00300   m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
    00301   error("The dataset "+dsn+" cannot be opened in mode "+openMode+". [Invalid mode]");
    00302   return sc;
    00303 }
    00304
    00305 // Conect output stream (valid until overwritten)
    00306 StatusCode PoolDbCnvSvc::connectOutput(CSTR db_name)  {
    00307   return connectOutput(db_name, "NEW");
    00308 }
    00309
    00310 // Commit pending output on open container
    00311 StatusCode  PoolDbCnvSvc::commitOutput(CSTR dsn, bool doCommit) {
    00312   if ( m_current )  {
    00313     try  {
    00314       if ( doCommit )
    00315         m_current->transaction().set(m_safeTransactions ? Transaction::TRANSACT_FLUSH : Transaction::TRANSACT_COMMIT);
    00316       else
    00317         m_current->transaction().set(Transaction::TRANSACT_ROLLBACK);
    00318       if ( m_current->database().transAct(m_current->transaction()).isSuccess() )  {
    00319         return S_OK;
    00320       }
    00321       std::string action(doCommit ? "commit to" : "rollback");
    00322       m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
    00323       return error("commitOutput> Cannot "+action+" database:"+dsn);
    00324     }
    00325     catch (std::exception& e)  {
    00326       error(std::string("commitOutput> Caught exception:")+e.what(), false);
    00327     }
    00328     catch (...)   {
    00329       error("commitOutput> Unknown Fatal Exception on commit to "+dsn, false);
    00330     }
    00331   }
    00332   m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
    00333   return error("commitOutput> Cannot connect to database: "+dsn);
    00334 }
    00335
    00336 // Connect to a POOL container in read mode
    00337 StatusCode PoolDbCnvSvc::connect(CSTR dsn, CSTR cntName, DbContainer& cntH)   {
    00338   return connectContainer(UNKNOWN, dsn, cntName, pool::READ, 0, cntH);
    00339 }
    00340
    00342 StatusCode
    00343 PoolDbCnvSvc::connectDatabase(int typ, CSTR dataset, DbAccessMode mode, PoolDbDataConnection** con)  {
    00344   try {
    00345     DbOptionCallback cb(m_cacheSvc->callbackHandler());
    00346     IDataConnection* c = m_ioMgr->connection(dataset);
    00347     bool fire_incident = false;
    00348     if ( !c )  {
    00349       DbType dbType(DbType(m_type).majorType());
    00350       std::auto_ptr<IDataConnection> connection(new PoolDbDataConnection(this,dataset,typ,mode,m_domH));
    00351       StatusCode sc = (mode == pool::READ)
    00352         ? m_ioMgr->connectRead(false,connection.get())
    00353         : m_ioMgr->connectWrite(connection.get(),IDataConnection::IoType(mode),dbType.storageName());
    00354       c = sc.isSuccess() ? m_ioMgr->connection(dataset) : 0;
    00355       if ( c )   {
    00356         fire_incident = m_incidentEnabled && (0 != (mode&(pool::UPDATE|pool::READ)));
    00357         connection.release();
    00358       }
    00359       else  {
    00360         return sc;
    00361       }
    00362     }
    00363     PoolDbDataConnection* pc = dynamic_cast<PoolDbDataConnection*>(c);
    00364     if ( pc )  {
    00365       if ( !pc->isConnected() ) pc->connectRead();
    00366       static int wr  = pool::RECREATE|pool::CREATE|pool::UPDATE;
    00367       // Got a valid connection. Now rearm the transaction
    00368       checkAccessMode(mode, pc->database());
    00369       if ( (mode&wr) != 0 )  {
    00370         pc->transaction().set(pool::Transaction::TRANSACT_START);
    00371         if ( !pc->database().transAct(pc->transaction()).isSuccess() )
    00372           return StatusCode::FAILURE;
    00373       }
    00374       *con = pc;
    00375       pc->resetAge();
    00376     }
    00377     if ( *con )  {
    00378       if ( fire_incident ) {
    00379         PoolDbAddress* pAddr = 0;
    00380         MsgStream log(msgSvc(), name());
    00381         pool::Token* token = 0, *prev = 0;
    00382         DbDatabase& dbH = pc->database();
    00383         if ( dbH.cntToken(m_recordName) )   {
    00384           std::auto_ptr<pool::DbSelect> sel(createSelect("*",dbH,m_recordName));
    00385           if ( sel.get() ) {
    00386             while(1) {
    00387               if ( prev ) prev->release();
    00388               prev = token;
    00389               if ( prev ) prev->addRef();
    00390               if ( !sel->next(token).isSuccess() ) break;
    00391             }
    00392           }
    00393           if ( prev ) {
    00394             log << MSG::INFO << "Records token:" << prev->toString() << endmsg;
    00395             if ( !createAddress(prev,&pAddr).isSuccess() ) {
    00396               prev->release();
    00397             }
    00398           }
    00399           else {
    00400             log << MSG::INFO << "No Record " << m_recordName << " entries present in:" << c->fid() << endmsg;
    00401           }
    00402         }
    00403         else {
    00404           log << MSG::INFO << "No Records " << m_recordName << " present in:" << c->fid() << endmsg;
    00405         }
    00406         m_incidentSvc->fireIncident(ContextIncident<IOpaqueAddress*>(c->fid(),"FILE_OPEN_READ",pAddr));
    00407       }
    00408       return StatusCode::SUCCESS;
    00409     }
    00410     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
    00411     return StatusCode::FAILURE;
    00412   }
    00413   catch (std::exception& e)  {
    00414     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
    00415     return error(std::string("connectDatabase> Caught exception:")+e.what(), false);
    00416   }
    00417   catch (...)   {
    00418     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
    00419     return error("connectDatabase> Unknown Fatal Exception for "+dataset, false);
    00420   }
    00421 }
    00422
    00423 StatusCode
    00424 PoolDbCnvSvc::connectContainer(int type,
    00425                                CSTR dbName,
    00426                                CSTR cntName,
    00427                                DbAccessMode mode,
    00428                                const DbTypeInfo* info,
    00429                                DbContainer& cntH)
    00430 {
    00431   PoolDbDataConnection* c = 0;
    00432   StatusCode sc = connectDatabase(type, dbName, mode, &c);
    00433   if( sc.isSuccess() )  {
    00434     return connectContainer(c->database(), cntName, mode, info, cntH);
    00435   }
    00436   return sc;
    00437 }
    00438
    00439 StatusCode
    00440 PoolDbCnvSvc::connectContainer(DbDatabase& dbH,
    00441                                CSTR cntName,
    00442                                DbAccessMode mode,
    00443                                const DbTypeInfo* shapeH,
    00444                                DbContainer& cntH)
    00445 {
    00446   std::string pfn, fid;
    00447   int all = pool::READ + pool::CREATE + pool::UPDATE;
    00448   int wr  = pool::CREATE + pool::UPDATE;
    00449   if ( dbH.isValid() )  {
    00450     fid = dbH.token()->dbID();
    00451     pfn = dbH.token()->contID();
    00452     int m   = dbH.openMode();
    00453     if ( (m&all) && mode == pool::READ )    {
    00454     }
    00455     else if ( m&wr && mode&pool::CREATE )   {
    00456     }
    00457     else if ( m&wr && mode&pool::UPDATE )   {
    00458     }
    00459     else  {
    00460       dbH.reopen(pool::UPDATE);
    00461     }
    00462   }
    00463   // No Else!
    00464   if ( !dbH.isValid() )  {
    00465     m_incidentSvc->fireIncident(Incident(pfn,IncidentType::FailOutputFile));
    00466     error("Cannot connect to Database: FID="+fid+" PFN="+pfn+
    00467           " [Invalid database handle]",false);
    00468     return StatusCode::FAILURE;
    00469   }
    00470   cntH = DbContainer(dbH.find(cntName));
    00471   if ( cntH.isValid() )  {
    00472     return StatusCode::SUCCESS;
    00473   }
    00474   if ( mode&pool::READ )  {
    00475     shapeH = dbH.contShape(cntName);
    00476   }
    00477   if ( shapeH )  {
    00478     if ( cntH.open(dbH, cntName, shapeH, m_type, mode).isSuccess() )  {
    00479       return StatusCode::SUCCESS;
    00480     }
    00481     return error("connectContainer> Failed to open container:"+cntName+
    00482       " in "+dbH.name(),false);
    00483   }
    00484   return error("connectContainer> No shape present for container:"+cntName+
    00485     " in "+dbH.name(),false);
    00486 }
    00487
    00488 // Disconnect from an existing data stream.
    00489 StatusCode PoolDbCnvSvc::disconnect(CSTR dataset)  {
    00490   IDataConnection* c = m_ioMgr->connection(dataset);
    00491   return c ? m_ioMgr->disconnect(c) : S_FAIL;
    00492 }
    00493
    00494 // Request an iterator over a container from the service
    00495 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, CSTR db, CSTR cnt) {
    00496   PoolDbDataConnection* c = 0;
    00497   StatusCode sc = connectDatabase(UNKNOWN, db, pool::READ, &c);
    00498   if ( sc.isSuccess() )  {
    00499     return createSelect(criteria,c->database(), cnt);
    00500   }
    00501   error("createSelect> Cannot open database:"+db, false);
    00502   m_incidentSvc->fireIncident(Incident(db,IncidentType::FailInputFile));
    00503   return 0;
    00504 }
    00505
    00506 // Request an iterator over a container from the service
    00507 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, DbDatabase& dbH, CSTR cnt) {
    00508   // Now select according to criteria
    00509   std::auto_ptr<pool::DbSelect> sel(new pool::DbSelect(criteria));
    00510   if ( sel->start(dbH, cnt).isSuccess() )  {
    00511     return sel.release();
    00512   }
    00513   return 0;
    00514 }
    00515
    00517 StatusCode PoolDbCnvSvc::createAddress( long  typ,
    00518                                         const CLID& clid,
    00519                                         const std::string* par,
    00520                                         const unsigned long* ip,
    00521                                         IOpaqueAddress*& refpAddress)
    00522 {
    00523   PoolDbAddress* pA = 0;
    00524   pool::Guid guid = pool::Guid::null();
    00525   std::auto_ptr<pool::Token> tok(new pool::Token());
    00526   guid.Data1 = clid;
    00527   tok->setDb(par[0]);
    00528   tok->setCont(par[1]);
    00529   tok->setTechnology(typ);
    00530   tok->setClassID(guid);
    00531   tok->oid().first = ip[0];
    00532   tok->oid().second = ip[1];
    00533   if ( createAddress(tok.get(), &pA).isSuccess() )  {
    00534     refpAddress = pA;
    00535     tok->release();
    00536     tok.release();
    00537     return S_OK;
    00538   }
    00539   return error("createAddress> Failed to create opaque address.");
    00540 }
    00541
    00542 // Create an opaque address from a POOL token structure
    00543 StatusCode PoolDbCnvSvc::createAddress(pool::Token* pTok,PoolDbAddress** ppAdd) {
    00544   if ( pTok )  {
    00545     *ppAdd = new PoolDbAddress(pTok);
    00546     return S_OK;
    00547   }
    00548   return error("createAddress> Failed to create opaque address from POOL token.");
    00549 }
    00550
    00551 // Mark an object for write given an object reference
    00552 StatusCode
    00553 PoolDbCnvSvc::markWrite(pool::DataCallBack* call,CSTR cntName,PoolDbAddress** ppAddr)
    00554 {
    00555   if ( m_current )  {
    00556     DbOptionCallback call_back(m_cacheSvc->callbackHandler());
    00557     const DbTypeInfo* shapeH = (const DbTypeInfo*)call->shape();
    00558     DbDatabase& dbH = m_current->database();
    00559     if ( dbH.transactionActive() )  {
    00560       std::auto_ptr<pool::Token> token(new pool::Token());
    00561       token->setDb(dbH.name()).setCont(cntName);
    00562       token->setClassID(shapeH->shapeID());
    00563       token->setTechnology(m_type);
    00564       DbContainer cntH(POOL_StorageType);
    00565       StatusCode sc = connectContainer(dbH,cntName,pool::UPDATE|pool::CREATE,shapeH,cntH);
    00566       if ( sc.isSuccess() )  {
    00567         call->setHandler(&m_handler);
    00568         if ( cntH.allocate(call, token->oid()).isSuccess() )  {
    00569           if ( dbH.makeLink(token.get(), token->oid()).isSuccess() )  {
    00570             if ( ppAddr )  {
    00571               if ( *ppAddr ) {
    00572                 (*ppAddr)->token()->setData(token.get());
    00573               }
    00574               else {
    00575                 *ppAddr = new PoolDbAddress(token.get());
    00576               }
    00577             }
    00578             long cnt = token->release();
    00579             if ( cnt > 1 ) {
    00580               MsgStream log(msgSvc(), name());
    00581               log << MSG::ERROR << "markWrite> Token count wrong: "
    00582                   << cnt << " expect memory leak. " << endmsg
    00583                   << "run again with environment POOLDB_TRACE=ON and"
    00584                   << " check instance counts." << endmsg;
    00585             }
    00586             token.release();
    00587             return S_OK;
    00588           }
    00589         }
    00590       }
    00591     }
    00592     return error("markWrite> No active transaction present for "+dbH.name());
    00593   }
    00594   return error("markWrite> Current Database is invalid!");
    00595 }
    00596
    00597 // Mark an object for update
    00598 StatusCode PoolDbCnvSvc::markUpdate(pool::DataCallBack* call, PoolDbAddress* pA)  {
    00599   if ( pA && call )  {
    00600     pool::Token* tok = pA->token();
    00601     DbContainer cntH(POOL_StorageType);
    00602     const DbTypeInfo* info = (const DbTypeInfo*)call->shape();
    00603     StatusCode sc = connectContainer(FID,tok->dbID(),tok->contID(),pool::UPDATE,info,cntH);
    00604     if ( sc.isSuccess() )  {
    00605       call->setHandler(&m_handler);
    00606       if ( cntH.update(call, tok->oid()).isSuccess() )  {
    00607         return S_OK;
    00608       }
    00609       return error("markUpdate> Failed to update object:"+tok->toString());
    00610     }
    00611     MsgStream log(msgSvc(), name());
    00612     log << MSG::ERROR << "markUpdate> The container "
    00613         << tok->dbID() << "::" << tok->contID()
    00614         << " cannot be accessed." << endmsg
    00615         << "Was this object really read from the container "
    00616         << "the object token claims?"
    00617         << endmsg;
    00618     return S_FAIL;
    00619   }
    00620   return error("createRep> Invalid object address for update.");
    00621 }
    00622
    00624 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, PoolDbAddress* pA)  {
    00625   StatusCode sc = read(call, *pA->token());
    00626   if ( sc.isSuccess() || sc == BAD_DATA_CONNECTION )  {
    00627     return sc;
    00628   }
    00629   std::string err="read> Cannot read object:"+pA->registry()->identifier()+" ";
    00630   return error(err, false);
    00631 }
    00632
    00634 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, pool::Token& tok)  {
    00635   try  {
    00636     DbContainer cntH(tok.technology());
    00637     const DbTypeInfo* info = (const DbTypeInfo*)call->shape();
    00638     StatusCode sc = connectContainer(FID,tok.dbID(),tok.contID(),pool::READ,info,cntH);
    00639     if ( sc.isSuccess() )  {
    00640       typedef pool::DbObjectHandle<pool::DbObject> ObjH;
    00641       call->setHandler(&m_handler);
    00642       return ObjH::openEx(cntH, tok, call, pool::READ).isSuccess() ? S_OK : S_FAIL;
    00643     }
    00644     else if ( sc == BAD_DATA_CONNECTION )  {
    00645       return sc;
    00646     }
    00647   }
    00648   catch (std::exception& e)  {
    00649     std::string err="read> Cannot read object:"+tok.toString()+" ";
    00650     return error(err+e.what(), false);
    00651   }
    00652   catch (...)   {
    00653     std::string err = "read> Cannot read object:"+tok.toString();
    00654     return error(err+" [Unknown fatal exception]", false);
    00655   }
    00656   return error("read> Cannot read object:"+tok.toString(), false);
    00657 }
    00658
    00659 // Small routine to issue exceptions
    00660 StatusCode PoolDbCnvSvc::error(CSTR msg, bool rethrow)  {
    00661   if ( rethrow )  {
    00662     pool::debugBreak("PoolDbCnvSvc", "Error:"+msg, rethrow);
    00663   }
    00664   else  {
    00665     MsgStream log(msgSvc(),name());
    00666     log << MSG::ERROR << "Error: " << msg << endmsg;
    00667   }
    00668   return S_FAIL;
    00669 }