Gaudi Framework, version v22r0

Home   Generated: 9 Feb 2011

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 #ifdef __ICC
00004 // disable icc warning #654: overloaded virtual function "IAddressCreator::createAddress" is only partially overridden in class "PoolDbCnvSvc"
00005 //   TODO: there is only a partial overload of IAddressCreator::createAddress
00006 #pragma warning(disable:654)
00007 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
00008 //   TODO: To be removed, coming from CORAL
00009 #pragma warning(disable:2259)
00010 #endif
00011 
00012 //====================================================================
00013 //      PoolDbCnvSvc implementation
00014 //--------------------------------------------------------------------
00015 //
00016 //  Description: Implementation of the POOL data storage
00017 //
00018 //      Author     : M.Frank
00019 //
00020 //====================================================================
00021 // Framework include files
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 // POOL include files
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 //ROOT include files
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* /* pAddr */)  {
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     /* ObjectList               */ CLID_Any + CLID_ObjectList,
00216     /* ObjectVector             */ CLID_Any + CLID_ObjectVector,
00217     /* Keyed Map                */ CLID_Any + CLID_ObjectVector+0x00030000,
00218     /* Keyed Hashmap            */ CLID_Any + CLID_ObjectVector+0x00040000,
00219     /* Keyed redirection array  */ CLID_Any + CLID_ObjectVector+0x00050000,
00220     /* Standard, non-container  */ 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     // Check if a converter using object update is needed
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     // If we do not have found any suitable container after searching
00240     // for standard containers, we will use the "ANY" converter
00241     // ... and pray for everything will go well.
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 // Conect output stream (valid until overwritten)
00316 StatusCode PoolDbCnvSvc::connectOutput(CSTR db_name)  {
00317   return connectOutput(db_name, "NEW");
00318 }
00319 
00320 // Commit pending output on open container
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 // Connect to a POOL container in read mode
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       // Got a valid connection. Now rearm the transaction
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   // No Else!
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 // Disconnect from an existing data stream.
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 // Request an iterator over a container from the service
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 // Request an iterator over a container from the service
00517 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, DbDatabase& dbH, CSTR cnt) {
00518   // Now select according to criteria
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 // Create an opaque address from a POOL token structure
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 // Mark an object for write given an object reference
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 // Mark an object for update
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 // Small routine to issue exceptions
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Wed Feb 9 16:24:58 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004