| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 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         return error("Cannot open data file:"+dataset);
    00247       }
    00248     }
    00249     RootDataConnection* pc = dynamic_cast<RootDataConnection*>(c);
    00250     if ( pc )  {
    00251       if ( !pc->isConnected() ) pc->connectRead();
    00252       *con = pc;
    00253       pc->resetAge();
    00254       pc->addClient(this);
    00255     }
    00256     if ( *con )  {
    00257       if ( fire_incident )   {
    00258         IOpaqueAddress* pAddr = 0;
    00259         string fid = pc->fid();
    00260         string section = m_recordName[0] == '/' ? m_recordName.substr(1) : m_recordName;
    00261         TBranch* b = pc->getBranch(section,m_recordName);
    00262         log() << MSG::VERBOSE;
    00263         if ( b ) {
    00264           const string par[2] = { fid, m_recordName };
    00265           unsigned long ipar[2] = { (unsigned long)(*con), (unsigned long)b->GetEntries()-1 };
    00266           for(int i=0; i<b->GetEntries(); ++i) {
    00267             ipar[1] = i;
    00268             if ( !pc->mergeFIDs().empty() )
    00269               fid = pc->mergeFIDs()[i];
    00270             if ( !createAddress(repSvcType(),CLID_DataObject,par,ipar,pAddr).isSuccess() ) {
    00271               log() << "Failed to create address for " << m_recordName << " in:" << fid
    00272                 << " [" << pc->fid() << "][" << i << "]" << endmsg;
    00273               continue;
    00274             }
    00275             log() << "Prepare " << m_recordName << " " << fid << " [" << par[0] << "][" << i << "]" << endmsg;
    00276             m_incidentSvc->fireIncident(ContextIncident<IOpaqueAddress*>(fid,"FILE_OPEN_READ",pAddr));
    00277           }
    00278         }
    00279         else {
    00280           log() << "No valid Records " << m_recordName << " present in:" << pc->fid() << endmsg;
    00281         }
    00282       }
    00283       // We can remove retired connections, which are no longer used....
    00284       IIODataManager::Connections cons = m_ioMgr->connections(this);
    00285       for(IIODataManager::Connections::iterator i=cons.begin(); i != cons.end(); ++i)  {
    00286         if ( (*i) != *con && !(*i)->isConnected() )  {
    00287           RootDataConnection* pc = dynamic_cast<RootDataConnection*>(*i);
    00288           if ( pc && pc->lookupClient(this) )   {
    00289             size_t num_client = pc->removeClient(this);
    00290             if ( num_client == 0 ) {
    00291               if ( m_ioMgr->disconnect(pc).isSuccess() )  {
    00292                 log() << MSG::INFO << "Removed disconnected IO  stream:" << pc->fid()
    00293                       << " [" << pc->pfn() << "]" << endmsg;
    00294                 delete pc;
    00295               }
    00296             }
    00297           }
    00298         }
    00299       }
    00300       return S_OK;
    00301     }
    00302     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
    00303     return S_FAIL;
    00304   }
    00305   catch (exception& e)  {
    00306     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
    00307     return error(string("connectDatabase> Caught exception:")+e.what());
    00308   }
    00309   catch (...)   {
    00310     m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
    00311     return error("connectDatabase> Unknown Fatal Exception for "+dataset);
    00312   }
    00313 }
    00314
    00315 // Conect output stream (valid until overwritten)
    00316 StatusCode RootCnvSvc::connectOutput(CSTR db_name)  {
    00317   return connectOutput(db_name, "NEW");
    00318 }
    00319
    00320 // Commit pending output on open container
    00321 StatusCode  RootCnvSvc::commitOutput(CSTR dsn, bool /* doCommit */) {
    00322   if ( m_current ) {
    00323     size_t len = m_currSection.find('/',1);
    00324     string section = m_currSection.substr(1,len==string::npos ? string::npos : len-1);
    00325     TBranch* b = m_current->getBranch(section, m_currSection);
    00326     if ( b ) {
    00327       Long64_t evt = b->GetEntries();
    00328       TTree* t = b->GetTree();
    00329       TObjArray* a = t->GetListOfBranches();
    00330       Int_t nb = a->GetEntriesFast();
    00331       log() << MSG::DEBUG;
    00333       for(Int_t i=0; i<nb; ++i) {
    00334         TBranch* br_ptr = (TBranch*)a->UncheckedAt(i);
    00335         Long64_t br_evt = br_ptr->GetEntries();
    00336         if ( br_evt < evt ) {
    00337           Long64_t num = evt-br_evt;
    00338           br_ptr->SetAddress(0);
    00339           while(num>0) { br_ptr->Fill(); --num; }
    00340           log() << "commit: Added " << long(evt-br_evt)
    00341                 << " Section: " << evt << " Branch: " << br_ptr->GetEntries()
    00342                 << " RefNo: " << br_ptr->GetEntries()-1
    00343                 << " NULL entries to:" << br_ptr->GetName() << endmsg;
    00344         }
    00345       }
    00346
    00347       b->GetTree()->SetEntries(evt);
    00348       if ( evt == 1 )  {
    00349         b->GetTree()->OptimizeBaskets(m_setup->basketSize,1.1,"");
    00350       }
    00351       if ( evt > 0 && (evt%m_setup->autoFlush)==0 ) {
    00352         if ( evt == m_setup->autoFlush ) {
    00353           b->GetTree()->SetAutoFlush(m_setup->autoFlush);
    00354           b->GetTree()->OptimizeBaskets(m_setup->basketSize,1.,"");
    00355         }
    00356         else   {
    00357           b->GetTree()->FlushBaskets();
    00358         }
    00359       }
    00360       log() << MSG::DEBUG << "Set section entries of " << m_currSection
    00361         << " to " << long(evt) << " entries." << endmsg;
    00362     }
    00363     else {
    00364       return error("commitOutput> Failed to update entry numbers on "+dsn);
    00365     }
    00366   }
    00367   return S_OK;
    00368 }
    00369
    00370 // Disconnect from an existing data stream.
    00371 StatusCode RootCnvSvc::disconnect(CSTR dataset)  {
    00372   IDataConnection* c = m_ioMgr->connection(dataset);
    00373   return c ? m_ioMgr->disconnect(c) : S_FAIL;
    00374 }
    00375
    00376 // IAddressCreator implementation: Address creation
    00377 StatusCode RootCnvSvc::createAddress(long  typ,
    00378                                      const CLID& clid,
    00379                                      const string* par,
    00380                                      const unsigned long* ip,
    00381                                      IOpaqueAddress*& refpAddress)
    00382 {
    00383   refpAddress = new RootAddress(typ,clid,par[0],par[1],ip[0],ip[1]);
    00384   return S_OK;
    00385 }
    00386
    00387 // Insert null marker for not existent transient object
    00388 StatusCode RootCnvSvc::createNullRep(const std::string& path) {
    00389   size_t len = path.find('/',1);
    00390   string section = path.substr(1,len==string::npos ? string::npos : len-1);
    00391   m_current->saveObj(section,path,0,0);
    00392   return S_OK;
    00393 }
    00394
    00395 // Insert null marker for not existent transient object
    00396 StatusCode RootCnvSvc::createNullRef(const std::string& path) {
    00397   RootObjectRefs* refs = 0;
    00398   size_t len = path.find('/',1);
    00399   string section = path.substr(1,len==string::npos ? string::npos : len-1);
    00400   pair<int,unsigned long> ret = m_current->save(section,path+"#R",0,refs);
    00401   log() << MSG::VERBOSE << "Writing object:" << path << " "
    00402     << ret.first << " " << hex << ret.second << dec << " [NULL]" << endmsg;
    00403   return S_OK;
    00404 }
    00405
    00406 // Mark an object for write given an object reference
    00407 StatusCode RootCnvSvc::i__createRep(DataObject* pObj, IOpaqueAddress*& refpAddr)  {
    00408   refpAddr = 0;
    00409   if ( pObj ) {
    00410     CLID       clid = pObj->clID();
    00411     IRegistry* pR   = pObj->registry();
    00412     string     p[2] = {m_current->fid(), pR->identifier()};
    00413     TClass*    cl   = (clid == CLID_DataObject) ? m_classDO : getClass(pObj);
    00414     size_t     len  = p[1].find('/',1);
    00415     string     sect = p[1].substr(1,len==string::npos ? string::npos : len-1);
    00416     pair<int,unsigned long> ret = m_current->saveObj(sect,p[1],cl,pObj,true);
    00417     if ( ret.first > 1 || (clid == CLID_DataObject && ret.first==1) ) {
    00418       unsigned long ip[2] = {0,ret.second};
    00419       if ( m_currSection.empty() ) m_currSection = p[1];
    00420       return createAddress(repSvcType(),clid,p,ip,refpAddr);
    00421     }
    00422     return error("Failed to write object data for:"+p[1]);
    00423   }
    00424   return error("createRep> Current Database is invalid!");
    00425 }
    00426
    00427 // Save object references to data file
    00428 StatusCode RootCnvSvc::i__fillRepRefs(IOpaqueAddress* /* pA */, DataObject* pObj) {
    00429   if ( pObj ) {
    00430     typedef vector<IRegistry*> Leaves;
    00431     Leaves leaves;
    00432     RootObjectRefs refs;
    00433     IRegistry* pR = pObj->registry();
    00434     SmartIF<IDataManagerSvc> dataMgr(pR->dataSvc());
    00435     if ( dataMgr ) {
    00436       StatusCode status = dataMgr->objectLeaves(pObj, leaves);
    00437       if ( status.isSuccess() )  {
    00438         RootRef ref;
    00439         const string& id    = pR->identifier();
    00440         size_t        len   = id.find('/',1);
    00441         string        sect  = id.substr(1,len==string::npos ? string::npos : len-1);
    00442         LinkManager* pLinks = pObj->linkMgr();
    00443         for(Leaves::iterator i=leaves.begin(), iend=leaves.end(); i != iend; ++i)  {
    00444           if ( (*i)->address() ) {
    00445             m_current->makeRef(*i,ref);
    00446             ref.entry = (*i)->address()->ipar()[1];
    00447             refs.refs.push_back(ref);
    00448           }
    00449         }
    00450         for(int i = 0, n=pLinks->size(); i < n; ++i)  {
    00451           LinkManager::Link* lnk = pLinks->link(i);
    00452           int link_id = m_current->makeLink(lnk->path());
    00453           refs.links.push_back(link_id);
    00454         }
    00455         pair<int,unsigned long> ret = m_current->save(sect,id+"#R",m_classRefs,&refs,true);
    00456         if ( ret.first > 1 ) {
    00457           log() << MSG::DEBUG << "Writing object:" << id << " "
    00458                 << ret.first << " " << hex << ret.second << dec << endmsg;
    00459           return S_OK;
    00460         }
    00461       }
    00462     }
    00463   }
    00464   return S_FAIL;
    00465 }
    00466
    00467 // Read existing object. Open transaction in read mode if not active
    00468 StatusCode RootCnvSvc::i__createObj(IOpaqueAddress* pA, DataObject*& refpObj)  {
    00469   refpObj = 0;
    00470   if ( pA ) {
    00471     RootDataConnection* con = 0;
    00472     const string*  par  = pA->par();
    00473     unsigned long* ipar = const_cast<unsigned long*>(pA->ipar());
    00474     StatusCode sc = connectDatabase(par[0],IDataConnection::READ,&con);
    00475     if ( sc.isSuccess() ) {
    00476       ipar[0] = (unsigned long)con;
    00477       DataObject* pObj = 0;
    00478       size_t len = par[1].find('/',1);
    00479       string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
    00480
    00481       int nb = con->loadObj(section,par[1],ipar[1],pObj);
    00482       if ( nb > 1 || (nb == 1 && pObj->clID() == CLID_DataObject) ) {
    00483         refpObj = pObj;
    00484         return S_OK;
    00485       }
    00486       delete pObj;
    00487     }
    00488     string tag = par[0]+":"+par[1];
    00489     if ( m_badFiles.find(tag) == m_badFiles.end() ) {
    00490       m_badFiles.insert(tag);
    00491       return error("createObj> Cannot access the object:"+tag);
    00492     }
    00493     return S_FAIL;
    00494   }
    00495   return S_FAIL;
    00496 }
    00497
    00498 // Resolve the references of the created transient object.
    00499 StatusCode RootCnvSvc::i__fillObjRefs(IOpaqueAddress* pA, DataObject* pObj) {
    00500   if ( pA && pObj )  {
    00501     const unsigned long* ipar = pA->ipar();
    00502     RootDataConnection* con = (RootDataConnection*)ipar[0];
    00503     if ( con ) {
    00504       RootObjectRefs refs;
    00505       const string* par = pA->par();
    00506       size_t len = par[1].find('/',1);
    00507       string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
    00508       int nb = con->loadRefs(section,par[1],ipar[1],refs);
    00509       log() << MSG::VERBOSE;
    00510       if ( nb >= 1 ) {
    00511         string npar[3];
    00512         unsigned long nipar[2];
    00513         IOpaqueAddress* nPA;
    00514         IRegistry* pR = pObj->registry();
    00515         SmartIF<IService> isvc(pR->dataSvc());
    00516         SmartIF<IDataManagerSvc> dataMgr(pR->dataSvc());
    00517         LinkManager* mgr = pObj->linkMgr();
    00518         bool active = log().isActive();
    00519         for(vector<int>::const_iterator i=refs.links.begin(); i!=refs.links.end();++i) {
    00520           mgr->addLink(con->getLink(*i),0);
    00521         }
    00522         for(size_t j=0, n=refs.refs.size(); j<n; ++j)  {
    00523           const RootRef& r = refs.refs[j];
    00524           npar[0] = con->getDb(r.dbase);
    00525           npar[1] = con->getCont(r.container);
    00526           npar[2] = con->getLink(r.link);
    00527           nipar[0] = 0;
    00528           nipar[1] = r.entry;
    00529           StatusCode sc = addressCreator()->createAddress(r.svc,r.clid,npar,nipar,nPA);
    00530           if ( sc.isSuccess() ) {
    00531             if ( active )  {
    00532               log() << isvc->name() << " -> Register:" << pA->registry()->identifier()
    00533                 << "#" << npar[2] << "[" << r.entry << "]" << endmsg;
    00534             }
    00535             sc = dataMgr->registerAddress(pA->registry(),npar[2],nPA);
    00536             if ( sc.isSuccess() ) {
    00537               continue;
    00538             }
    00539           }
    00540           log() << MSG::ERROR << con->fid() << ": Failed to create address!!!!" << endmsg;
    00541           return S_FAIL;
    00542         }
    00543         return pObj->update();
    00544       }
    00545     }
    00546     return S_FAIL;
    00547   }
    00548   return error("read> Cannot read object -- no valid object address present ");
    00549 }

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines