Gaudi Framework, version v20r4

Generated: 8 Jan 2009

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

Generated at Thu Jan 8 17:44:22 2009 for Gaudi Framework, version v20r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004