Gaudi Framework, version v21r4

Home   Generated: 7 Sep 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 // 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 cnvid(POOL_StorageType, gen_clids[i]);
00215         pConverter = PluginService::CreateWithId<IConverter*>(cnvid, 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 cnvid(POOL_StorageType, CLID_Any | 1<<31);
00224       pConverter = PluginService::CreateWithId<IConverter*>(cnvid, 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 cnvid(POOL_StorageType, CLID_Any);
00233     pConverter = PluginService::CreateWithId<IConverter*>(cnvid, 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   DbAccessMode mode = pool::NOT_OPEN;
00289   m_current = 0;
00290   if ( ::strncasecmp(openMode.c_str(),"RECREATE",3)==0 )
00291     sc = connectDatabase(UNKNOWN, dsn, mode=pool::RECREATE, &m_current);
00292   else if ( ::strncasecmp(openMode.c_str(),"NEW",1)==0 )
00293     sc = connectDatabase(UNKNOWN, dsn, mode=pool::CREATE, &m_current);
00294   else if ( ::strncasecmp(openMode.c_str(),"CREATE",1)==0 )
00295     sc = connectDatabase(UNKNOWN, dsn, mode=pool::CREATE, &m_current);
00296   else if ( ::strncasecmp(openMode.c_str(),"UPDATE",1)==0 )
00297     sc = connectDatabase(UNKNOWN, dsn, mode=pool::UPDATE, &m_current);
00298   if ( sc.isSuccess() && m_current && m_current->isConnected() )  {
00299     return S_OK;
00300   }
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       return error("commitOutput> Cannot "+action+" database:"+dsn);
00323     }
00324     catch (std::exception& e)  {
00325       error(std::string("commitOutput> Caught exception:")+e.what(), false);
00326     }
00327     catch (...)   {
00328       error("commitOutput> Unknown Fatal Exception on commit to "+dsn, false);
00329     }
00330   }
00331   return error("commitOutput> Cannot connect to database: "+dsn);
00332 }
00333 
00334 // Connect to a POOL container in read mode
00335 StatusCode PoolDbCnvSvc::connect(CSTR dsn, CSTR cntName, DbContainer& cntH)   {
00336   return connectContainer(UNKNOWN, dsn, cntName, pool::READ, 0, cntH);
00337 }
00338 
00340 StatusCode
00341 PoolDbCnvSvc::connectDatabase(int typ, CSTR dataset, DbAccessMode mode, PoolDbDataConnection** con)  {
00342   try {
00343     DbOptionCallback cb(m_cacheSvc->callbackHandler());
00344     IDataConnection* c = m_ioMgr->connection(dataset);
00345     bool fire_incident = false;
00346     if ( !c )  {
00347       DbType dbType(DbType(m_type).majorType());
00348       std::auto_ptr<IDataConnection> connection(new PoolDbDataConnection(this,dataset,typ,mode,m_domH));
00349       StatusCode sc = (mode == pool::READ)
00350         ? m_ioMgr->connectRead(false,connection.get())
00351         : m_ioMgr->connectWrite(connection.get(),IDataConnection::IoType(mode),dbType.storageName());
00352       c = sc.isSuccess() ? m_ioMgr->connection(dataset) : 0;
00353       if ( c )   {
00354         fire_incident = m_incidentEnabled && (0 != (mode&(pool::UPDATE|pool::READ)));
00355         connection.release();
00356       }
00357       else  {
00358         return sc;
00359       }
00360     }
00361     PoolDbDataConnection* pc = dynamic_cast<PoolDbDataConnection*>(c);
00362     if ( pc )  {
00363       if ( !pc->isConnected() ) pc->connectRead();
00364       static int wr  = pool::RECREATE|pool::CREATE|pool::UPDATE;
00365       // Got a valid connection. Now rearm the transaction
00366       checkAccessMode(mode, pc->database());
00367       if ( (mode&wr) != 0 )  {
00368         pc->transaction().set(pool::Transaction::TRANSACT_START);
00369         if ( !pc->database().transAct(pc->transaction()).isSuccess() )
00370           return StatusCode::FAILURE;
00371       }
00372       *con = pc;
00373       pc->resetAge();
00374     }
00375     if ( *con )  {
00376       if ( fire_incident ) {
00377         PoolDbAddress* pAddr = 0;
00378         MsgStream log(msgSvc(), name());
00379         pool::Token* token = 0, *prev = 0;
00380         DbDatabase& dbH = pc->database();
00381         if ( dbH.cntToken(m_recordName) )   {
00382           std::auto_ptr<pool::DbSelect> sel(createSelect("*",dbH,m_recordName));
00383           if ( sel.get() ) {
00384             while(1) {
00385               if ( prev ) prev->release();
00386               prev = token;
00387               if ( prev ) prev->addRef();
00388               if ( !sel->next(token).isSuccess() ) break;
00389             }
00390           }
00391           if ( prev ) {
00392             log << MSG::INFO << "Records token:" << prev->toString() << endmsg;
00393             if ( !createAddress(prev,&pAddr).isSuccess() ) {
00394               prev->release();
00395             }
00396           }
00397           else {
00398             log << MSG::INFO << "No Record " << m_recordName << " entries present in:" << c->fid() << endmsg;
00399           }
00400         }
00401         else {
00402           log << MSG::INFO << "No Records " << m_recordName << " present in:" << c->fid() << endmsg;
00403         }
00404         m_incidentSvc->fireIncident(ContextIncident<IOpaqueAddress*>(c->fid(),"FILE_OPEN_READ",pAddr));
00405       }
00406       return StatusCode::SUCCESS;
00407     }
00408     return StatusCode::FAILURE;
00409   }
00410   catch (std::exception& e)  {
00411     return error(std::string("connectDatabase> Caught exception:")+e.what(), false);
00412   }
00413   catch (...)   {
00414     return error("connectDatabase> Unknown Fatal Exception for "+dataset, false);
00415   }
00416 }
00417 
00418 StatusCode
00419 PoolDbCnvSvc::connectContainer(int type,
00420                                CSTR dbName,
00421                                CSTR cntName,
00422                                DbAccessMode mode,
00423                                const DbTypeInfo* info,
00424                                DbContainer& cntH)
00425 {
00426   PoolDbDataConnection* c = 0;
00427   StatusCode sc = connectDatabase(type, dbName, mode, &c);
00428   if( sc.isSuccess() )  {
00429     return connectContainer(c->database(), cntName, mode, info, cntH);
00430   }
00431   return sc;
00432 }
00433 
00434 StatusCode
00435 PoolDbCnvSvc::connectContainer(DbDatabase& dbH,
00436                                CSTR cntName,
00437                                DbAccessMode mode,
00438                                const DbTypeInfo* shapeH,
00439                                DbContainer& cntH)
00440 {
00441   std::string pfn, fid;
00442   int all = pool::READ + pool::CREATE + pool::UPDATE;
00443   int wr  = pool::CREATE + pool::UPDATE;
00444   if ( dbH.isValid() )  {
00445     fid = dbH.token()->dbID();
00446     pfn = dbH.token()->contID();
00447     int m   = dbH.openMode();
00448     if ( (m&all) && mode == pool::READ )    {
00449     }
00450     else if ( m&wr && mode&pool::CREATE )   {
00451     }
00452     else if ( m&wr && mode&pool::UPDATE )   {
00453     }
00454     else  {
00455       dbH.reopen(pool::UPDATE);
00456     }
00457   }
00458   // No Else!
00459   if ( !dbH.isValid() )  {
00460     error("Cannot connect to Database: FID="+fid+" PFN="+pfn+
00461           " [Invalid database handle]",false);
00462     return StatusCode::FAILURE;
00463   }
00464   cntH = DbContainer(dbH.find(cntName));
00465   if ( cntH.isValid() )  {
00466     return StatusCode::SUCCESS;
00467   }
00468   if ( mode&pool::READ )  {
00469     shapeH = dbH.contShape(cntName);
00470   }
00471   if ( shapeH )  {
00472     if ( cntH.open(dbH, cntName, shapeH, m_type, mode).isSuccess() )  {
00473       return StatusCode::SUCCESS;
00474     }
00475     return error("connectContainer> Failed to open container:"+cntName+
00476       " in "+dbH.name(),false);
00477   }
00478   return error("connectContainer> No shape present for container:"+cntName+
00479     " in "+dbH.name(),false);
00480 }
00481 
00482 // Disconnect from an existing data stream.
00483 StatusCode PoolDbCnvSvc::disconnect(CSTR dataset)  {
00484   IDataConnection* c = m_ioMgr->connection(dataset);
00485   return c ? m_ioMgr->disconnect(c) : S_FAIL;
00486 }
00487 
00488 // Request an iterator over a container from the service
00489 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, CSTR db, CSTR cnt) {
00490   PoolDbDataConnection* c = 0;
00491   StatusCode sc = connectDatabase(UNKNOWN, db, pool::READ, &c);
00492   if ( sc.isSuccess() )  {
00493     return createSelect(criteria,c->database(), cnt);
00494   }
00495   error("createSelect> Cannot open database:"+db, false);
00496   return 0;
00497 }
00498 
00499 // Request an iterator over a container from the service
00500 pool::DbSelect* PoolDbCnvSvc::createSelect(CSTR criteria, DbDatabase& dbH, CSTR cnt) {
00501   // Now select according to criteria
00502   std::auto_ptr<pool::DbSelect> sel(new pool::DbSelect(criteria));
00503   if ( sel->start(dbH, cnt).isSuccess() )  {
00504     return sel.release();
00505   }
00506   return 0;
00507 }
00508 
00510 StatusCode PoolDbCnvSvc::createAddress( long  typ,
00511                                         const CLID& clid,
00512                                         const std::string* par,
00513                                         const unsigned long* ip,
00514                                         IOpaqueAddress*& refpAddress)
00515 {
00516   PoolDbAddress* pA = 0;
00517   pool::Guid guid = pool::Guid::null();
00518   std::auto_ptr<pool::Token> tok(new pool::Token());
00519   guid.Data1 = clid;
00520   tok->setDb(par[0]);
00521   tok->setCont(par[1]);
00522   tok->setTechnology(typ);
00523   tok->setClassID(guid);
00524   tok->oid().first = ip[0];
00525   tok->oid().second = ip[1];
00526   if ( createAddress(tok.get(), &pA).isSuccess() )  {
00527     refpAddress = pA;
00528     tok->release();
00529     tok.release();
00530     return S_OK;
00531   }
00532   return error("createAddress> Failed to create opaque address.");
00533 }
00534 
00535 // Create an opaque address from a POOL token structure
00536 StatusCode PoolDbCnvSvc::createAddress(pool::Token* pTok,PoolDbAddress** ppAdd) {
00537   if ( pTok )  {
00538     *ppAdd = new PoolDbAddress(pTok);
00539     return S_OK;
00540   }
00541   return error("createAddress> Failed to create opaque address from POOL token.");
00542 }
00543 
00544 // Mark an object for write given an object reference
00545 StatusCode
00546 PoolDbCnvSvc::markWrite(pool::DataCallBack* call,CSTR cntName,PoolDbAddress** ppAddr)
00547 {
00548   if ( m_current )  {
00549     DbOptionCallback call_back(m_cacheSvc->callbackHandler());
00550     const DbTypeInfo* shapeH = (const DbTypeInfo*)call->shape();
00551     DbDatabase& dbH = m_current->database();
00552     if ( dbH.transactionActive() )  {
00553       std::auto_ptr<pool::Token> token(new pool::Token());
00554       token->setDb(dbH.name()).setCont(cntName);
00555       token->setClassID(shapeH->shapeID());
00556       token->setTechnology(m_type);
00557       DbContainer cntH(POOL_StorageType);
00558       StatusCode sc = connectContainer(dbH,cntName,pool::UPDATE|pool::CREATE,shapeH,cntH);
00559       if ( sc.isSuccess() )  {
00560         call->setHandler(&m_handler);
00561         if ( cntH.allocate(call, token->oid()).isSuccess() )  {
00562           if ( dbH.makeLink(token.get(), token->oid()).isSuccess() )  {
00563             if ( ppAddr )  {
00564               if ( *ppAddr ) {
00565                 (*ppAddr)->token()->setData(token.get());
00566               }
00567               else {
00568                 *ppAddr = new PoolDbAddress(token.get());
00569               }
00570             }
00571             long cnt = token->release();
00572             if ( cnt > 1 ) {
00573               MsgStream log(msgSvc(), name());
00574               log << MSG::ERROR << "markWrite> Token count wrong: "
00575                   << cnt << " expect memory leak. " << endmsg
00576                   << "run again with environment POOLDB_TRACE=ON and"
00577                   << " check instance counts." << endmsg;
00578             }
00579             token.release();
00580             return S_OK;
00581           }
00582         }
00583       }
00584     }
00585     return error("markWrite> No active transaction present for "+dbH.name());
00586   }
00587   return error("markWrite> Current Database is invalid!");
00588 }
00589 
00590 // Mark an object for update
00591 StatusCode PoolDbCnvSvc::markUpdate(pool::DataCallBack* call, PoolDbAddress* pA)  {
00592   if ( pA && call )  {
00593     pool::Token* tok = pA->token();
00594     DbContainer cntH(POOL_StorageType);
00595     const DbTypeInfo* info = (const DbTypeInfo*)call->shape();
00596     StatusCode sc = connectContainer(FID,tok->dbID(),tok->contID(),pool::UPDATE,info,cntH);
00597     if ( sc.isSuccess() )  {
00598       call->setHandler(&m_handler);
00599       if ( cntH.update(call, tok->oid()).isSuccess() )  {
00600         return S_OK;
00601       }
00602       return error("markUpdate> Failed to update object:"+tok->toString());
00603     }
00604     MsgStream log(msgSvc(), name());
00605     log << MSG::ERROR << "markUpdate> The container "
00606         << tok->dbID() << "::" << tok->contID()
00607         << " cannot be accessed." << endmsg
00608         << "Was this object really read from the container "
00609         << "the object token claims?"
00610         << endmsg;
00611     return S_FAIL;
00612   }
00613   return error("createRep> Invalid object address for update.");
00614 }
00615 
00617 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, PoolDbAddress* pA)  {
00618   StatusCode sc = read(call, *pA->token());
00619   if ( sc.isSuccess() || sc == BAD_DATA_CONNECTION )  {
00620     return sc;
00621   }
00622   std::string err="read> Cannot read object:"+pA->registry()->identifier()+" ";
00623   return error(err, false);
00624 }
00625 
00627 StatusCode PoolDbCnvSvc::read(pool::DataCallBack* call, pool::Token& tok)  {
00628   try  {
00629     DbContainer cntH(tok.technology());
00630     const DbTypeInfo* info = (const DbTypeInfo*)call->shape();
00631     StatusCode sc = connectContainer(FID,tok.dbID(),tok.contID(),pool::READ,info,cntH);
00632     if ( sc.isSuccess() )  {
00633       typedef pool::DbObjectHandle<pool::DbObject> ObjH;
00634       call->setHandler(&m_handler);
00635       return ObjH::openEx(cntH, tok, call, pool::READ).isSuccess() ? S_OK : S_FAIL;
00636     }
00637     else if ( sc == BAD_DATA_CONNECTION )  {
00638       return sc;
00639     }
00640   }
00641   catch (std::exception& e)  {
00642     std::string err="read> Cannot read object:"+tok.toString()+" ";
00643     return error(err+e.what(), false);
00644   }
00645   catch (...)   {
00646     std::string err = "read> Cannot read object:"+tok.toString();
00647     return error(err+" [Unknown fatal exception]", false);
00648   }
00649   return error("read> Cannot read object:"+tok.toString(), false);
00650 }
00651 
00652 // Small routine to issue exceptions
00653 StatusCode PoolDbCnvSvc::error(CSTR msg, bool rethrow)  {
00654   if ( rethrow )  {
00655     pool::debugBreak("PoolDbCnvSvc", "Error:"+msg, rethrow);
00656   }
00657   else  {
00658     MsgStream log(msgSvc(),name());
00659     log << MSG::ERROR << "Error: " << msg << endmsg;
00660   }
00661   return S_FAIL;
00662 }

Generated at Mon Sep 7 18:05:45 2009 for Gaudi Framework, version v21r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004