Gaudi Framework, version v22r4

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

Generated at Fri Sep 2 2011 16:24:48 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004