Gaudi Framework, version v23r4

Home   Generated: Mon Sep 17 2012

RootCnvSvc.cpp

Go to the documentation of this file.
00001 // $Id: RootCnvSvc.cpp,v 1.12 2010-09-27 15:43:53 frankb Exp $
00002 //====================================================================
00003 //  RootCnvSvc implementation
00004 //--------------------------------------------------------------------
00005 //
00006 //  Description: Implementation of the ROOT data storage
00007 //
00008 //  Author     : M.Frank
00009 //
00010 //====================================================================
00011 
00012 // Framework include files
00013 #include "GaudiKernel/MsgStream.h"
00014 #include "GaudiKernel/IRegistry.h"
00015 #include "GaudiKernel/IUpdateable.h"
00016 #include "GaudiKernel/IIncidentSvc.h"
00017 #include "GaudiKernel/IDataManagerSvc.h"
00018 #include "GaudiKernel/IDataProviderSvc.h"
00019 #include "GaudiKernel/KeyedContainer.h"
00020 #include "GaudiKernel/DataIncident.h"
00021 #include "GaudiKernel/LinkManager.h"
00022 #include "GaudiKernel/Incident.h"
00023 #include "GaudiKernel/System.h"
00024 #include "GaudiUtils/IIODataManager.h"
00025 #include "RootCnv/RootRefs.h"
00026 #include "RootCnv/RootCnvSvc.h"
00027 #include "RootCnv/RootAddress.h"
00028 #include "RootCnv/RootConverter.h"
00029 #include "RootCnv/RootDatabaseCnv.h"
00030 #include "RootCnv/RootDirectoryCnv.h"
00031 #include "RootCnv/RootNTupleCnv.h"
00032 #include "RootCnv/RootDataConnection.h"
00033 #include "RootUtils.h"
00034 
00035 // ROOT include files
00036 #include "TROOT.h"
00037 #include "TClass.h"
00038 #include "TTree.h"
00039 #include "TBranch.h"
00040 
00041 using namespace std;
00042 using namespace Gaudi;
00043 typedef const string& CSTR;
00044 
00045 #define S_OK   StatusCode::SUCCESS
00046 #define S_FAIL StatusCode::FAILURE
00047 namespace GaudiRoot {  bool patchStreamers(MsgStream& log);    }
00048 
00049 namespace { 
00050   static map<string, TClass*> s_classesNames;
00051   static map<CLID, TClass*>   s_classesClids;
00052 }
00053 #define MBYTE 1024*1024
00054 
00055 // Standard constructor
00056 RootCnvSvc::RootCnvSvc(CSTR nam, ISvcLocator* svc)
00057 : ConversionSvc( nam, svc, ROOT_StorageType), 
00058   m_ioMgr(0), m_incidentSvc(0), m_current(0), m_setup(0)
00059 {
00060   m_classRefs = m_classDO = 0;
00061   m_setup = new RootConnectionSetup();
00062   m_setup->cacheBranches.push_back("*");
00063   declareProperty("IOPerfStats",      m_ioPerfStats);
00064   declareProperty("ShareFiles",       m_shareFiles          = "NO");
00065   declareProperty("EnableIncident",   m_incidentEnabled     = true);
00066   declareProperty("RecordsName",      m_recordName          = "/FileRecords");
00067 
00068   declareProperty("BasketSize",       m_setup->basketSize   = 40*MBYTE);
00069   declareProperty("CacheSize",        m_setup->cacheSize    = 10*MBYTE);
00070   declareProperty("AutoFlush",        m_setup->autoFlush    = 100);
00071   declareProperty("LearnEntries",     m_setup->learnEntries = 10);
00072   declareProperty("LoadSection",      m_setup->loadSection  = "Event");
00073   declareProperty("CacheBranches",    m_setup->cacheBranches);
00074   declareProperty("VetoBranches",     m_setup->vetoBranches);
00075   declareProperty("GlobalCompression",m_compression); // empty: do nothing
00076 }
00077 
00078 // Standard destructor
00079 RootCnvSvc::~RootCnvSvc() {
00080   if (m_setup) m_setup->release();
00081 }
00082 
00083 // Small routine to issue exceptions
00084 StatusCode RootCnvSvc::error(CSTR msg)  {
00085   if ( m_log ) {
00086     log() << MSG::ERROR << "Error: " << msg << endmsg;
00087     return S_FAIL;
00088   }
00089   MsgStream m(msgSvc(),name());
00090   m << MSG::ERROR << "Error: " << msg << endmsg;
00091   return S_FAIL;
00092 }
00093 
00094 // Initialize the Db data persistency service
00095 StatusCode RootCnvSvc::initialize()  {
00096   string cname;
00097   StatusCode status = ConversionSvc::initialize();
00098   if ( !status.isSuccess() )
00099     return error("Failed to initialize ConversionSvc base class.");
00100   m_log = new MsgStream(msgSvc(),name());
00101   if ( !m_compression.empty() ) {
00102     log() << MSG::INFO << "Setting global ROOT compression to:" << m_compression << endmsg;
00103     if ( !(status=RootConnectionSetup::setCompression(m_compression)).isSuccess() ) {
00104       return error("Unable to interprete ROOT compression encoding:"+m_compression);
00105     }
00106   }
00107   if( !(status=service("IODataManager", m_ioMgr)).isSuccess() )
00108     return error("Unable to localize interface from service:IODataManager");
00109   if( !(status=service("IncidentSvc", m_incidentSvc)).isSuccess() )
00110     return error("Unable to localize interface from service:IncidentSvc");
00111   m_setup->setMessageSvc(new MsgStream(msgSvc(),name()));
00112   GaudiRoot::patchStreamers(log());
00113   cname = System::typeinfoName(typeid(DataObject));
00114   m_classDO = gROOT->GetClass(cname.c_str());
00115   if ( 0 == m_classDO )
00116     return error("Unable to load class description for DataObject");    
00117   cname = System::typeinfoName(typeid(RootObjectRefs));
00118   m_classRefs = gROOT->GetClass(cname.c_str());
00119   if ( 0 == m_classRefs )
00120     return error("Unable to load class description for ObjectRefs");
00121   return S_OK;
00122 }
00123 
00124 // Finalize the Db data persistency service
00125 StatusCode RootCnvSvc::finalize()    {
00126   log() << MSG::INFO;
00127   if ( m_ioMgr )  {
00128     IIODataManager::Connections cons = m_ioMgr->connections(0);
00129     for(IIODataManager::Connections::iterator i=cons.begin(); i != cons.end(); ++i)  {
00130       RootDataConnection* pc = dynamic_cast<RootDataConnection*>(*i);
00131       if ( pc ) {
00132         if ( pc->owner() == this && !m_ioPerfStats.empty() )   {
00133           pc->saveStatistics(m_ioPerfStats);
00134         }
00135         if ( pc->lookupClient(this) )   {
00136           size_t num_clients = pc->removeClient(this);
00137           if ( num_clients == 0 ) {
00138             if ( m_ioMgr->disconnect(pc).isSuccess() )  {
00139               log() << "Disconnected data IO:" << pc->fid() 
00140                     << " [" << pc->pfn() << "]" << endmsg;
00141               delete pc;
00142             }
00143           }
00144         }
00145       }
00146     }
00147     releasePtr(m_ioMgr);
00148   }
00149   deletePtr(m_log);
00150   releasePtr(m_incidentSvc);
00151   return ConversionSvc::finalize();
00152 }
00153 
00154 // ConversionSvc overload: Create new Converter using factory
00155 IConverter* RootCnvSvc::createConverter(long typ,const CLID& wanted,const ICnvFactory*)   {
00156   if ( wanted == CLID_StatisticsFile )
00157     return new RootDatabaseCnv(typ,wanted,serviceLocator().get(),this);
00158   else if ( wanted == CLID_StatisticsDirectory )
00159     return new RootDirectoryCnv(typ,wanted,serviceLocator().get(),this);
00160   else if ( wanted == CLID_RowWiseTuple )
00161     return new RootNTupleCnv(typ,wanted,serviceLocator().get(),this);
00162   else if ( wanted == CLID_ColumnWiseTuple )
00163     return new RootNTupleCnv(typ,wanted,serviceLocator().get(),this);
00164   else
00165     return new RootConverter(typ,wanted,serviceLocator().get(),this);
00166 }
00167 
00168 // ConversionSvc overload: Load the class (dictionary) for the converter 
00169 void RootCnvSvc::loadConverter(DataObject* pObject) {
00170   if (pObject) {
00171     string cname = System::typeinfoName(typeid(*pObject));
00172     log() << MSG::DEBUG << "Trying to 'Autoload' dictionary for class " << cname << endmsg;
00173     TClass* cl = s_classesNames[cname];
00174     if ( 0 == cl ) {
00175       cl = gROOT->GetClass(cname.c_str());
00176       if ( cl ) {
00177         s_classesNames[cname] = cl;
00178         s_classesClids[pObject->clID()] = cl;
00179       }
00180     }
00181   }
00182 }  
00183 
00184 // Helper: Get TClass for a given DataObject pointer
00185 TClass* RootCnvSvc::getClass(DataObject* pObject) {
00186   map<CLID, TClass*>::iterator i=s_classesClids.find(pObject->clID());
00187   if ( i != s_classesClids.end() ) return (*i).second;
00188   loadConverter(pObject);
00189   i=s_classesClids.find(pObject->clID());
00190   if ( i != s_classesClids.end() ) return (*i).second;
00191 
00192   string cname = System::typeinfoName(typeid(*pObject));
00193   throw runtime_error("Unknown ROOT class for object:"+cname);
00194   return 0;
00195 }
00196 
00197 // Connect the output file to the service with open mode.
00198 StatusCode RootCnvSvc::connectOutput(CSTR dsn, CSTR openMode)   {
00199   StatusCode sc = S_FAIL;
00200   m_current = 0;
00201   m_currSection = "";
00202   if ( ::strncasecmp(openMode.c_str(),"RECREATE",3)==0 )
00203     sc = connectDatabase(dsn, IDataConnection::RECREATE, &m_current);
00204   else if ( ::strncasecmp(openMode.c_str(),"NEW",1)==0 )
00205     sc = connectDatabase(dsn, IDataConnection::CREATE, &m_current);
00206   else if ( ::strncasecmp(openMode.c_str(),"CREATE",1)==0 )
00207     sc = connectDatabase(dsn, IDataConnection::CREATE, &m_current);
00208   else if ( ::strncasecmp(openMode.c_str(),"UPDATE",1)==0 )
00209     sc = connectDatabase(dsn, IDataConnection::UPDATE, &m_current);
00210   if ( sc.isSuccess() && m_current && m_current->isConnected() )  {
00211     return S_OK;
00212   }
00213   m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
00214   log() << MSG::ERROR << "The dataset " << dsn << " cannot be opened in mode " 
00215     << openMode << ". [Invalid mode]" << endmsg;
00216   return sc;
00217 }
00218 
00219 // Connect the output file to the service with open mode.
00220 StatusCode
00221 RootCnvSvc::connectDatabase(CSTR dataset, int mode, RootDataConnection** con)  {
00222   try {
00223     IDataConnection* c = m_ioMgr->connection(dataset);
00224     bool fire_incident = false;
00225     *con = 0;
00226     if ( !c )  {
00227       auto_ptr<IDataConnection> connection(new RootDataConnection(this,dataset,m_setup));
00228       StatusCode sc = (mode != IDataConnection::READ)
00229         ? m_ioMgr->connectWrite(connection.get(),IDataConnection::IoType(mode),"ROOT")
00230         : m_ioMgr->connectRead(false,connection.get());
00231       c = sc.isSuccess() ? m_ioMgr->connection(dataset) : 0;
00232       if ( c )   {
00233         fire_incident = m_incidentEnabled && (0 != (mode&(IDataConnection::UPDATE|IDataConnection::READ)));
00234         if ( 0 != (mode&IDataConnection::READ) ) {
00235           if ( !m_ioPerfStats.empty() ) {
00236             RootDataConnection* pc = dynamic_cast<RootDataConnection*>(c);
00237             pc->enableStatistics(m_setup->loadSection);
00238           }
00239         }
00240         connection.release();
00241       }
00242       else  {
00243         m_incidentSvc->fireIncident(Incident(dataset,mode == IDataConnection::READ
00244                                              ? IncidentType::FailInputFile
00245                                              : IncidentType::FailOutputFile));
00246         // An error message was already printed by the IODataManager. no need to do it here!
00247         return StatusCode::FAILURE;
00248       }
00249     }
00250     RootDataConnection* pc = dynamic_cast<RootDataConnection*>(c);
00251     if ( pc )  {
00252       if ( !pc->isConnected() ) pc->connectRead();
00253       *con = pc;
00254       pc->resetAge();
00255       pc->addClient(this);
00256     }
00257     if ( *con )  {
00258       if ( fire_incident )   {
00259         IOpaqueAddress* pAddr = 0;
00260         string fid = pc->fid();
00261         string section = m_recordName[0] == '/' ? m_recordName.substr(1) : m_recordName;
00262         TBranch* b = pc->getBranch(section,m_recordName);
00263         log() << MSG::VERBOSE;
00264         if ( b ) {
00265           const string par[2] = { fid, m_recordName };
00266           unsigned long ipar[2] = { (unsigned long)(*con), (unsigned long)b->GetEntries()-1 };
00267           for(int i=0; i<b->GetEntries(); ++i) {
00268             ipar[1] = i;
00269             if ( !pc->mergeFIDs().empty() )
00270               fid = pc->mergeFIDs()[i];
00271             if ( !createAddress(repSvcType(),CLID_DataObject,par,ipar,pAddr).isSuccess() ) {
00272               log() << "Failed to create address for " << m_recordName << " in:" << fid
00273                 << " [" << pc->fid() << "][" << i << "]" << endmsg;
00274               continue;
00275             }
00276             log() << "Prepare " << m_recordName << " " << fid << " [" << par[0] << "][" << i << "]" << endmsg;
00277             m_incidentSvc->fireIncident(ContextIncident<IOpaqueAddress*>(fid,"FILE_OPEN_READ",pAddr));
00278           }
00279         }
00280         else {
00281           log() << "No valid Records " << m_recordName << " present in:" << pc->fid() << endmsg;
00282         }
00283       }
00284       // We can remove retired connections, which are no longer used....
00285       IIODataManager::Connections cons = m_ioMgr->connections(this);
00286       for(IIODataManager::Connections::iterator i=cons.begin(); i != cons.end(); ++i)  {
00287         if ( (*i) != *con && !(*i)->isConnected() )  {
00288           RootDataConnection* pc = dynamic_cast<RootDataConnection*>(*i);
00289           if ( pc && pc->lookupClient(this) )   {
00290             size_t num_client = pc->removeClient(this);
00291             if ( num_client == 0 ) {
00292               if ( m_ioMgr->disconnect(pc).isSuccess() )  {
00293                 log() << MSG::INFO << "Removed disconnected IO  stream:" << pc->fid() 
00294                       << " [" << pc->pfn() << "]" << endmsg;
00295                 delete pc;
00296               }
00297             }
00298           }
00299         }
00300       }
00301       return S_OK;
00302     }
00303     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
00304     return S_FAIL;
00305   }
00306   catch (exception& e)  {
00307     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
00308     return error(string("connectDatabase> Caught exception:")+e.what());
00309   }
00310   catch (...)   {
00311     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
00312     return error("connectDatabase> Unknown Fatal Exception for "+dataset);
00313   }
00314 }
00315 
00316 // Conect output stream (valid until overwritten)
00317 StatusCode RootCnvSvc::connectOutput(CSTR db_name)  {
00318   return connectOutput(db_name, "NEW");
00319 }
00320 
00321 // Commit pending output on open container
00322 StatusCode  RootCnvSvc::commitOutput(CSTR dsn, bool /* doCommit */) {
00323   if ( m_current ) {
00324     size_t len = m_currSection.find('/',1);   
00325     string section = m_currSection.substr(1,len==string::npos ? string::npos : len-1);
00326     TBranch* b = m_current->getBranch(section, m_currSection);
00327     if ( b ) {
00328       Long64_t evt = b->GetEntries();
00329       TTree* t = b->GetTree();
00330       TObjArray* a = t->GetListOfBranches();
00331       Int_t nb = a->GetEntriesFast();
00332       log() << MSG::DEBUG;
00334       for(Int_t i=0; i<nb; ++i) {
00335         TBranch* br_ptr = (TBranch*)a->UncheckedAt(i);
00336         Long64_t br_evt = br_ptr->GetEntries();
00337         if ( br_evt < evt ) {
00338           Long64_t num = evt-br_evt;
00339           br_ptr->SetAddress(0);
00340           while(num>0) { br_ptr->Fill(); --num; }
00341           log() << "commit: Added " << long(evt-br_evt) 
00342                 << " Section: " << evt << " Branch: " << br_ptr->GetEntries()
00343                 << " RefNo: " << br_ptr->GetEntries()-1 
00344                 << " NULL entries to:" << br_ptr->GetName() << endmsg;
00345         }
00346       }
00347 
00348       b->GetTree()->SetEntries(evt);
00349       if ( evt == 1 )  {
00350         b->GetTree()->OptimizeBaskets(m_setup->basketSize,1.1,"");
00351       }
00352       if ( evt > 0 && (evt%m_setup->autoFlush)==0 ) {
00353         if ( evt == m_setup->autoFlush ) {
00354           b->GetTree()->SetAutoFlush(m_setup->autoFlush);
00355           b->GetTree()->OptimizeBaskets(m_setup->basketSize,1.,"");
00356         }
00357         else   {
00358           b->GetTree()->FlushBaskets();
00359         }
00360       }
00361       log() << MSG::DEBUG << "Set section entries of " << m_currSection
00362         << " to " << long(evt) << " entries." << endmsg;
00363     }
00364     else {
00365       return error("commitOutput> Failed to update entry numbers on "+dsn);
00366     }
00367   }
00368   return S_OK;
00369 }
00370 
00371 // Disconnect from an existing data stream.
00372 StatusCode RootCnvSvc::disconnect(CSTR dataset)  {
00373   IDataConnection* c = m_ioMgr->connection(dataset);
00374   return c ? m_ioMgr->disconnect(c) : S_FAIL;
00375 }
00376 
00377 // IAddressCreator implementation: Address creation
00378 StatusCode RootCnvSvc::createAddress(long  typ,
00379                                      const CLID& clid,
00380                                      const string* par, 
00381                                      const unsigned long* ip,
00382                                      IOpaqueAddress*& refpAddress) 
00383 {
00384   refpAddress = new RootAddress(typ,clid,par[0],par[1],ip[0],ip[1]);
00385   return S_OK;
00386 }
00387 
00388 // Insert null marker for not existent transient object
00389 StatusCode RootCnvSvc::createNullRep(const std::string& path) {
00390   size_t len = path.find('/',1);
00391   string section = path.substr(1,len==string::npos ? string::npos : len-1);
00392   m_current->saveObj(section,path,0,0);
00393   return S_OK;
00394 }
00395 
00396 // Insert null marker for not existent transient object
00397 StatusCode RootCnvSvc::createNullRef(const std::string& path) {
00398   RootObjectRefs* refs = 0;
00399   size_t len = path.find('/',1);
00400   string section = path.substr(1,len==string::npos ? string::npos : len-1);
00401   pair<int,unsigned long> ret = m_current->save(section,path+"#R",0,refs);
00402   log() << MSG::VERBOSE << "Writing object:" << path << " " 
00403     << ret.first << " " << hex << ret.second << dec << " [NULL]" << endmsg;
00404   return S_OK;
00405 }
00406 
00407 // Mark an object for write given an object reference
00408 StatusCode RootCnvSvc::i__createRep(DataObject* pObj, IOpaqueAddress*& refpAddr)  {
00409   refpAddr = 0;
00410   if ( pObj ) {
00411     CLID       clid = pObj->clID();
00412     IRegistry* pR   = pObj->registry();
00413     string     p[2] = {m_current->fid(), pR->identifier()};
00414     TClass*    cl   = (clid == CLID_DataObject) ? m_classDO : getClass(pObj);
00415     size_t     len  = p[1].find('/',1);
00416     string     sect = p[1].substr(1,len==string::npos ? string::npos : len-1);
00417     pair<int,unsigned long> ret = m_current->saveObj(sect,p[1],cl,pObj,true);
00418     if ( ret.first > 1 || (clid == CLID_DataObject && ret.first==1) ) {
00419       unsigned long ip[2] = {0,ret.second};
00420       if ( m_currSection.empty() ) m_currSection = p[1];
00421       return createAddress(repSvcType(),clid,p,ip,refpAddr);
00422     }
00423     return error("Failed to write object data for:"+p[1]);
00424   }
00425   return error("createRep> Current Database is invalid!");
00426 }
00427 
00428 // Save object references to data file
00429 StatusCode RootCnvSvc::i__fillRepRefs(IOpaqueAddress* /* pA */, DataObject* pObj) {
00430   if ( pObj ) {
00431     typedef vector<IRegistry*> Leaves;
00432     Leaves leaves;
00433     RootObjectRefs refs;
00434     IRegistry* pR = pObj->registry();
00435     SmartIF<IDataManagerSvc> dataMgr(pR->dataSvc());
00436     if ( dataMgr ) {
00437       StatusCode status = dataMgr->objectLeaves(pObj, leaves);
00438       if ( status.isSuccess() )  {
00439         RootRef ref;
00440         const string& id    = pR->identifier();
00441         size_t        len   = id.find('/',1);
00442         string        sect  = id.substr(1,len==string::npos ? string::npos : len-1);
00443         LinkManager* pLinks = pObj->linkMgr();
00444         for(Leaves::iterator i=leaves.begin(), iend=leaves.end(); i != iend; ++i)  {
00445           if ( (*i)->address() ) {
00446             m_current->makeRef(*i,ref);
00447             ref.entry = (*i)->address()->ipar()[1];
00448             refs.refs.push_back(ref);
00449           }
00450         }
00451         for(int i = 0, n=pLinks->size(); i < n; ++i)  {
00452           LinkManager::Link* lnk = pLinks->link(i);
00453           int link_id = m_current->makeLink(lnk->path());
00454           refs.links.push_back(link_id);
00455         }
00456         pair<int,unsigned long> ret = m_current->save(sect,id+"#R",m_classRefs,&refs,true);
00457         if ( ret.first > 1 ) {
00458           log() << MSG::DEBUG << "Writing object:" << id << " " 
00459                 << ret.first << " " << hex << ret.second << dec << endmsg;
00460           return S_OK;
00461         }
00462       }
00463     }
00464   }
00465   return S_FAIL;
00466 }
00467 
00468 // Read existing object. Open transaction in read mode if not active
00469 StatusCode RootCnvSvc::i__createObj(IOpaqueAddress* pA, DataObject*& refpObj)  {
00470   refpObj = 0;
00471   if ( pA ) {
00472     RootDataConnection* con = 0;
00473     const string*  par  = pA->par();
00474     unsigned long* ipar = const_cast<unsigned long*>(pA->ipar());
00475     StatusCode sc = connectDatabase(par[0],IDataConnection::READ,&con);
00476     if ( sc.isSuccess() ) {
00477       ipar[0] = (unsigned long)con;
00478       DataObject* pObj = 0;
00479       size_t len = par[1].find('/',1);
00480       string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
00481 
00482       int nb = con->loadObj(section,par[1],ipar[1],pObj);
00483       if ( nb > 1 || (nb == 1 && pObj->clID() == CLID_DataObject) ) {
00484         refpObj = pObj;
00485         return S_OK;
00486       }
00487       delete pObj;
00488     }
00489     string tag = par[0]+":"+par[1];
00490     if ( m_badFiles.find(tag) == m_badFiles.end() ) {
00491       m_badFiles.insert(tag);
00492       return error("createObj> Cannot access the object:"+tag);
00493     }
00494     return S_FAIL;
00495   }
00496   return S_FAIL;
00497 }
00498 
00499 // Resolve the references of the created transient object.
00500 StatusCode RootCnvSvc::i__fillObjRefs(IOpaqueAddress* pA, DataObject* pObj) {
00501   if ( pA && pObj )  {
00502     const unsigned long* ipar = pA->ipar();
00503     RootDataConnection* con = (RootDataConnection*)ipar[0];
00504     if ( con ) {
00505       RootObjectRefs refs;
00506       const string* par = pA->par();
00507       size_t len = par[1].find('/',1);
00508       string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
00509       int nb = con->loadRefs(section,par[1],ipar[1],refs);
00510       log() << MSG::VERBOSE;
00511       if ( nb >= 1 ) {
00512         string npar[3];
00513         unsigned long nipar[2];
00514         IOpaqueAddress* nPA;
00515         IRegistry* pR = pObj->registry();
00516         SmartIF<IService> isvc(pR->dataSvc());
00517         SmartIF<IDataManagerSvc> dataMgr(pR->dataSvc());
00518         LinkManager* mgr = pObj->linkMgr();
00519         bool active = log().isActive();
00520         for(vector<int>::const_iterator i=refs.links.begin(); i!=refs.links.end();++i) {
00521           mgr->addLink(con->getLink(*i),0);
00522         }
00523         for(size_t j=0, n=refs.refs.size(); j<n; ++j)  {
00524           const RootRef& r = refs.refs[j];
00525           npar[0] = con->getDb(r.dbase);
00526           npar[1] = con->getCont(r.container);
00527           npar[2] = con->getLink(r.link);
00528           nipar[0] = 0;
00529           nipar[1] = r.entry;
00530           StatusCode sc = addressCreator()->createAddress(r.svc,r.clid,npar,nipar,nPA);
00531           if ( sc.isSuccess() ) {
00532             if ( active )  {
00533               log() << isvc->name() << " -> Register:" << pA->registry()->identifier() 
00534                 << "#" << npar[2] << "[" << r.entry << "]" << endmsg;
00535             }
00536             sc = dataMgr->registerAddress(pA->registry(),npar[2],nPA);
00537             if ( sc.isSuccess() ) {
00538               continue;
00539             }
00540           }
00541           log() << MSG::ERROR << con->fid() << ": Failed to create address!!!!" << endmsg;
00542           return S_FAIL;
00543         }
00544         return pObj->update();
00545       }
00546     }
00547     return S_FAIL;
00548   }
00549   return error("read> Cannot read object -- no valid object address present ");
00550 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Mon Sep 17 2012 13:49:38 for Gaudi Framework, version v23r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004