Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

RootDataConnection.cpp

Go to the documentation of this file.
00001 // $Id: RootDataConnection.cpp,v 1.16 2010-09-27 15:43:53 frankb Exp $
00002 //====================================================================
00003 //      RootDataConnection.cpp
00004 //--------------------------------------------------------------------
00005 //
00006 //      Author     : M.Frank
00007 //====================================================================
00008 // $Header: /afs/cern.ch/project/cvs/reps/lhcb/Online/RootCnv/src/RootDataConnection.cpp,v 1.16 2010-09-27 15:43:53 frankb Exp $
00009 
00010 // Framework include files
00011 #include "RootCnv/RootDataConnection.h"
00012 #include "RootUtils.h"
00013 #include "GaudiKernel/IOpaqueAddress.h"
00014 #include "GaudiKernel/LinkManager.h"
00015 #include "GaudiKernel/strcasecmp.h"
00016 #include "GaudiKernel/DataObject.h"
00017 #include "GaudiKernel/IRegistry.h"
00018 #include "GaudiKernel/MsgStream.h"
00019 // ROOT include files
00020 #include "TROOT.h"
00021 #include "TFile.h"
00022 #include "TTree.h"
00023 #include "TLeaf.h"
00024 #include "TClass.h"
00025 #include "TBranch.h"
00026 #include "Compression.h"
00027 #include "TTreePerfStats.h"
00028 
00029 // C/C++ include files
00030 #include <stdexcept>
00031 
00032 using namespace Gaudi;
00033 using namespace std;
00034 typedef const string& CSTR;
00035 
00036 static string s_empty;
00037 static string s_local = "<localDB>";
00038 
00039 #ifdef __POOL_COMPATIBILITY
00040 #include "PoolTool.h"
00041 #endif
00042 #include "RootTool.h"
00043 
00044 static int s_compressionLevel = ROOT::CompressionSettings(ROOT::kLZMA,6);
00045 
00046 static bool match_wild(const char *str, const char *pat)    {
00047   //
00048   // Credits: Code from Alessandro Felice Cantatore.
00049   // 
00050   static char table[256];
00051   static bool first = true;
00052   const char *s, *p;
00053   bool star = false;
00054   if ( first ) {
00055     for (int i = 0; i < 256; ++i) table[i] = char(i);
00056     first = false;
00057   }
00058 loopStart:
00059   for (s = str, p = pat; *s; ++s, ++p) {
00060     switch (*p) {
00061     case '?':
00062       if (*s == '.') goto starCheck;
00063       break;
00064     case '*':
00065       star = true;
00066       str = s, pat = p;
00067       do { ++pat; } while (*pat == '*');
00068       if (!*pat) return true;
00069       goto loopStart;
00070     default:
00071       if ( *(table+*s) != *(table+*p) )
00072         goto starCheck;
00073       break;
00074     } /* endswitch */
00075   } /* endfor */
00076   while (*p == '*') ++p;
00077   return (!*p);
00078 
00079 starCheck:
00080   if (!star) return false;
00081   str++;
00082   goto loopStart;
00083 }
00084 
00086 RootConnectionSetup::RootConnectionSetup() : refCount(1), m_msgSvc(0)
00087 {
00088 }
00089 
00091 RootConnectionSetup::~RootConnectionSetup() {
00092   deletePtr(m_msgSvc);
00093 }
00094 
00096 long RootConnectionSetup::setCompression(const std::string& compression) {
00097   int res = 0, level = ROOT::CompressionSettings(ROOT::kLZMA,6);
00098   size_t idx = compression.find(':');
00099   if ( idx != string::npos ) {
00100     string alg = compression.substr(0,idx);
00101     ROOT::ECompressionAlgorithm alg_code = ROOT::kUseGlobalSetting;
00102     if ( strcasecmp(alg.c_str(),"ZLIB") == 0 ) 
00103       alg_code = ROOT::kZLIB;
00104     else if ( strcasecmp(alg.c_str(),"LZMA") == 0 ) 
00105       alg_code = ROOT::kLZMA;
00106     else
00107       throw runtime_error("ERROR: request to set unknown ROOT compression algorithm:"+alg);
00108     res = ::sscanf(compression.c_str()+idx+1,"%d",&level);
00109     if ( res == 1 ) {
00110       s_compressionLevel = ROOT::CompressionSettings(alg_code,level);
00111       return StatusCode::SUCCESS;
00112     }
00113     throw runtime_error("ERROR: request to set unknown ROOT compression level:"+compression.substr(idx+1));
00114   }
00115   else if ( 1==::sscanf(compression.c_str(),"%d",&level) ) {
00116     s_compressionLevel = level;
00117     return StatusCode::SUCCESS;
00118   }
00119   throw runtime_error("ERROR: request to set unknown ROOT compression mechanism:"+compression);
00120 }
00121 
00123 int RootConnectionSetup::compression() {
00124   return s_compressionLevel;
00125 }
00126 
00128 void RootConnectionSetup::addRef() {
00129   ++refCount;
00130 }
00131 
00132 // Decrease reference count
00133 void RootConnectionSetup::release() {
00134   int tmp = --refCount;
00135   if ( tmp <= 0 ) {
00136     delete this;
00137   }
00138 }
00139 
00140 // Set message service reference
00141 void RootConnectionSetup::setMessageSvc(MsgStream* m) {
00142   MsgStream* tmp = m_msgSvc;
00143   m_msgSvc = m;
00144   deletePtr(tmp);
00145 }
00146 
00147 // Standard constructor
00148 RootDataConnection::RootDataConnection(const IInterface* owner, CSTR fname, RootConnectionSetup* setup)
00149   : IDataConnection(owner,fname), m_setup(setup), m_statistics(0), m_tool(0)
00150 { //               01234567890123456789012345678901234567890
00151   // Check if FID: A82A3BD8-7ECB-DC11-8DC0-000423D950B0
00152   if ( fname.length() == 36 && fname[8]=='-'&&fname[13]=='-'&&fname[18]=='-'&&fname[23]=='-' ) {
00153     m_name = "FID:"+fname;
00154   }
00155   m_setup->addRef();
00156   m_age  = 0;
00157   m_file = 0;
00158   m_refs = 0;
00159   addClient(owner);
00160 }
00161 
00162 // Standard destructor      
00163 RootDataConnection::~RootDataConnection()   {
00164   m_setup->release();
00165   releasePtr(m_tool);
00166 }
00167 
00168 // Add new client to this data source
00169 void RootDataConnection::addClient(const IInterface* client) {
00170   m_clients.insert(client);
00171 }
00172 
00173 // Remove client from this data source
00174 size_t RootDataConnection::removeClient(const IInterface* client) {
00175   Clients::iterator i=m_clients.find(client);
00176   if ( i != m_clients.end() ) m_clients.erase(i);
00177   return m_clients.size();
00178 }
00179 
00180 // Lookup client for this data source
00181 bool RootDataConnection::lookupClient(const IInterface* client)   const {
00182   Clients::const_iterator i=m_clients.find(client);
00183   return i != m_clients.end();
00184 }
00185 
00186 // Save TTree access statistics if required
00187 void RootDataConnection::saveStatistics(CSTR statisticsFile) {
00188   if ( m_statistics ) {
00189     m_statistics->Print();
00190     if ( !statisticsFile.empty() )
00191       m_statistics->SaveAs(statisticsFile.c_str());
00192     deletePtr(m_statistics);
00193   }
00194 }
00195 
00196 // Enable TTreePerStats
00197 void RootDataConnection::enableStatistics(CSTR section) {
00198   if ( 0 == m_statistics ) {
00199     TTree* t=getSection(section,false);
00200     if ( t ) {
00201       m_statistics = new TTreePerfStats((section+"_ioperf").c_str(),t);
00202       return;
00203     }
00204     msgSvc() << MSG::WARNING << "Failed to enable perfstats for tree:" << section << endmsg;
00205     return;
00206   }
00207   msgSvc() << MSG::INFO << "Perfstats are ALREADY ENABLED." << endmsg;
00208 }
00209 
00210 // Create file access tool to encapsulate POOL compatibiliy
00211 RootDataConnection::Tool* RootDataConnection::makeTool()   {
00212   releasePtr(m_tool);
00213   if ( !m_refs ) m_refs = (TTree*)m_file->Get("Refs");
00214   if ( m_refs )
00215     m_tool = new RootTool(this);
00216 #ifdef __POOL_COMPATIBILITY
00217   else if ( m_file->Get("##Links") != 0 )
00218     m_tool = new PoolTool(this);
00219 #endif
00220   return m_tool;
00221 }
00222 
00223 // Connect the file in READ mode
00224 StatusCode RootDataConnection::connectRead()  {
00225   m_file = TFile::Open(m_pfn.c_str());
00226   if ( m_file && !m_file->IsZombie() )   {
00227     StatusCode sc = StatusCode::FAILURE;
00228     msgSvc() << MSG::DEBUG << "Opened file " << m_pfn << " in mode READ. [" << m_fid << "]" << endmsg << MSG::DEBUG;    
00229     if ( msgSvc().isActive() ) m_file->ls();
00230     msgSvc() << MSG::VERBOSE;
00231     if ( msgSvc().isActive() ) m_file->Print();
00232     if ( makeTool() ) sc = m_tool->readRefs();
00233     if ( sc.isSuccess() ) {
00234       bool need_fid = m_fid == m_pfn;
00235       string fid = m_fid;
00236       m_mergeFIDs.clear();
00237       for(size_t i=0, n=m_params.size(); i<n; ++i) {
00238         if ( m_params[i].first == "FID" )  {
00239           m_mergeFIDs.push_back(m_params[i].second);
00240           if ( m_params[i].second != m_fid )    {
00241             msgSvc() << MSG::DEBUG << "Check FID param:" << m_params[i].second << endmsg;
00242             //if ( m_fid == m_pfn ) {
00243             m_fid = m_params[i].second;
00244             //}
00245           }
00246         }
00247       }
00248       if ( !need_fid && fid != m_fid ) {
00249         msgSvc() << MSG::ERROR << "FID mismatch:" << fid << "(Catalog) != " << m_fid << "(file)" << endmsg
00250           << "for PFN:" << m_pfn << endmsg;
00251         return StatusCode::FAILURE;
00252       }
00253       msgSvc() << MSG::DEBUG << "Using FID " << m_fid << " from params table...." << endmsg
00254         << "for PFN:" << m_pfn << endmsg;
00255       return sc;
00256     }
00257   }
00258   else if ( m_file ) {
00259     deletePtr(m_file);
00260   }
00261   return StatusCode::FAILURE;
00262 }
00263 
00264 // Open data stream in write mode
00265 StatusCode RootDataConnection::connectWrite(IoType typ)  {
00266   int compress = RootConnectionSetup::compression();
00267   msgSvc() << MSG::DEBUG;
00268   switch(typ)  {
00269   case CREATE:
00270     resetAge();
00271     m_file = TFile::Open(m_pfn.c_str(),"CREATE","Root event data",compress);
00272     m_refs = new TTree("Refs","Root reference data");
00273     msgSvc() << "Opened file " << m_pfn << " in mode CREATE. [" << m_fid << "]" << endmsg;
00274     m_params.push_back(make_pair("PFN",m_pfn));
00275     if ( m_fid != m_pfn ) {
00276       m_params.push_back(make_pair("FID",m_fid));
00277     }
00278     makeTool();
00279     break;
00280   case RECREATE:
00281     resetAge();
00282     m_file = TFile::Open(m_pfn.c_str(),"RECREATE","Root event data",compress);
00283     msgSvc() << "Opened file " << m_pfn << " in mode RECREATE. [" << m_fid << "]" << endmsg;
00284     m_refs = new TTree("Refs","Root reference data");
00285     m_params.push_back(make_pair("PFN",m_pfn));
00286     if ( m_fid != m_pfn ) {
00287       m_params.push_back(make_pair("FID",m_fid));
00288     }
00289     makeTool();
00290     break;
00291   case UPDATE:
00292     resetAge();
00293     m_file = TFile::Open(m_pfn.c_str(),"UPDATE","Root event data",compress);
00294     msgSvc() << "Opened file " << m_pfn << " in mode UPDATE. [" << m_fid << "]" << endmsg;
00295     if ( m_file && !m_file->IsZombie() )  {
00296       if ( makeTool() ) return m_tool->readRefs();
00297       TDirectory::TContext ctxt(m_file);
00298       m_refs = new TTree("Refs","Root reference data");
00299       makeTool();
00300       return StatusCode::SUCCESS;
00301     }
00302     break;
00303   default:
00304     m_refs = 0;
00305     m_file = 0;
00306     return StatusCode::FAILURE;
00307   }
00308   return 0==m_file ? StatusCode::FAILURE : StatusCode::SUCCESS;
00309 }
00310 
00311 // Release data stream and release implementation dependent resources
00312 StatusCode RootDataConnection::disconnect()    {
00313   if ( m_file ) {
00314     if ( !m_file->IsZombie() )   {
00315       if ( m_file->IsWritable() ) {
00316         msgSvc() << MSG::DEBUG;
00317         TDirectory::TContext ctxt(m_file);
00318         if ( m_refs ) {
00319           m_tool->saveRefs().ignore();
00320           m_refs->Write();
00321         }
00322         for(Sections::iterator i=m_sections.begin(); i!= m_sections.end();++i) {
00323           if ( (*i).second ) {
00324             (*i).second->Write();
00325             msgSvc() << "Disconnect section " << (*i).first << " " << (*i).second->GetName() << endmsg;
00326           }
00327         }
00328         m_sections.clear();
00329       }
00330       msgSvc() << MSG::DEBUG;
00331       if ( msgSvc().isActive() ) m_file->ls();
00332       msgSvc() << MSG::VERBOSE;
00333       if ( msgSvc().isActive() ) m_file->Print();
00334       m_file->Close();
00335     }
00336     msgSvc() << MSG::DEBUG << "Disconnected file " << m_pfn << " " << m_file->GetName() << endmsg;
00337     deletePtr(m_file);
00338     releasePtr(m_tool);
00339   }
00340   return StatusCode::SUCCESS;
00341 }
00342 
00343 // Access TTree section from section name. The section is created if required.
00344 TTree* RootDataConnection::getSection(CSTR section, bool create) {
00345   TTree* t = m_sections[section];
00346   if ( !t ) {
00347     t = (TTree*)m_file->Get(section.c_str());
00348     if ( !t && create ) {
00349       TDirectory::TContext ctxt(m_file);
00350       t = new TTree(section.c_str(),"Root data for Gaudi");
00351     }
00352     if ( t ) {
00353       int cacheSize = m_setup->cacheSize;
00354       if ( create ) {
00355         //t->SetAutoFlush(100);
00356       }
00357       if ( section == m_setup->loadSection && cacheSize>-2 )  {
00358         MsgStream& msg = msgSvc();
00359         int learnEntries = m_setup->learnEntries;
00360         t->SetCacheSize(cacheSize);
00361         t->SetCacheLearnEntries(learnEntries);
00362         msg << MSG::DEBUG;
00363         if ( create ) {
00364           msg << "Tree:" << section << "Setting up tree cache:" << cacheSize << endmsg;
00365         }
00366         else {
00367           const StringVec& vB = m_setup->vetoBranches;
00368           const StringVec& cB = m_setup->cacheBranches;
00369           msg << "Tree:" << section << " Setting up tree cache:" << cacheSize << " Add all branches." << endmsg;
00370           msg << "Tree:" << section << " Learn for " << learnEntries << " entries." << endmsg;
00371 
00372           if ( cB.size()==0 && vB.size()== 0 ) {
00373             msg << "Adding (default) all branches to tree cache." << endmsg;
00374             t->AddBranchToCache("*",kTRUE);
00375           }
00376           if ( cB.size()==1 && cB[0]=="*" ) {
00377             msg << "Adding all branches to tree cache according to option \"CacheBranches\"." << endmsg;
00378             t->AddBranchToCache("*",kTRUE);
00379           }
00380           else {
00381             StringVec::const_iterator i;
00382             for(TIter it(t->GetListOfBranches()); it.Next(); )  {
00383               const char* n = ((TNamed*)(*it))->GetName();
00384               bool add = false, veto = false;
00385               for(i=cB.begin(); i != cB.end();++i) {
00386                 if ( !match_wild(n,(*i).c_str()) ) continue;
00387                 add = true;
00388                 break;
00389               }
00390               for(i=vB.begin(); !add && i!=vB.end();++i) {
00391                 if ( !match_wild(n,(*i).c_str()) ) continue;
00392                 veto = true;
00393                 break;
00394               }
00395               if ( add && !veto ) {
00396                 msg << "Add " << n << " to branch cache." << endmsg;
00397                 t->AddBranchToCache(n,kTRUE);
00398               }
00399               else {
00400                 msg << "Do not cache branch " << n << endmsg;
00401               }
00402             }
00403           }
00404         }
00405       }
00406       m_sections[section] = t;
00407     }
00408   }
00409   return t;
00410 }
00411 
00412 // Access data branch by name: Get existing branch in write mode
00413 TBranch* RootDataConnection::getBranch(CSTR section, CSTR branch_name, TClass* cl, void* ptr) {
00414   string n = branch_name+".";
00415   for(int i=0, m=n.length()-1; i<m; ++i) if ( !isalnum(n[i]) ) n[i]='_';
00416   TTree* t = getSection(section,true);
00417   TBranch* b = t->GetBranch(n.c_str());
00418   if ( !b && cl && m_file->IsWritable() ) {
00419     b = t->Branch(n.c_str(),cl->GetName(),(void*)(ptr ? &ptr : 0));
00420   }
00421   if ( !b ) {
00422     b = t->GetBranch(branch_name.c_str());
00423   }
00424   if ( b )   {
00425     b->SetAutoDelete(kFALSE);
00426   }
00427   return b;
00428 }
00429 
00430 // Convert path string to path index
00431 int RootDataConnection::makeLink(CSTR p) {
00432   int cnt = 0;
00433   StringVec::iterator ip;
00434   for(ip=m_links.begin();ip!=m_links.end();++ip,++cnt) {
00435     if( (*ip) == p ) return cnt;
00436   }
00437   m_links.push_back(p);
00438   return m_links.size()-1;
00439 }
00440 
00441 // Access database/file name from saved index
00442 CSTR RootDataConnection::getDb(int which) const {
00443   if ( (which>=0) && (size_t(which)<m_dbs.size()) )  {
00444     if ( *(m_dbs.begin()+which) == s_local ) return m_fid;
00445     return *(m_dbs.begin()+which);
00446   }
00447   return s_empty;
00448 }
00449 
00450 // Empty string reference
00451 CSTR RootDataConnection::empty() const { 
00452   return s_empty;
00453 }
00454 
00455 // Save object of a given class to section and container
00456 pair<int,unsigned long> 
00457 RootDataConnection::saveObj(CSTR section, CSTR cnt, TClass* cl, DataObject* pObj,bool fill) {
00458   DataObjectPush push(pObj);
00459   return save(section,cnt,cl,pObj,fill);
00460 }
00461 
00462 // Save object of a given class to section and container
00463 pair<int,unsigned long> 
00464 RootDataConnection::save(CSTR section, CSTR cnt, TClass* cl, void* pObj, bool fill_missing) {
00465   TBranch* b = getBranch(section, cnt, cl, (void*)(pObj ? &pObj : 0));
00466   if ( b ) {
00467     Long64_t evt = b->GetEntries();
00468     if ( fill_missing ) {
00469       Long64_t num, nevt = b->GetTree()->GetEntries();
00470       if ( nevt > evt )   {
00471         b->SetAddress(0);
00472         num = nevt - evt;
00473         while( num > 0 ) { b->Fill(); --num; }
00474         msgSvc() << MSG::DEBUG << "Added " << long(nevt-evt) 
00475                  << " / Tree: " << nevt << " / Branch: " << b->GetEntries()+1
00476                  << " NULL entries to:" << cnt << endmsg;
00477         evt = b->GetEntries();
00478       }
00479     }
00480     b->SetAddress(&pObj);
00481     return make_pair(b->Fill(),(unsigned long)evt);
00482   }
00483   else if ( 0 != pObj ) {
00484     msgSvc() << MSG::ERROR << "Failed to access branch " << m_name << "/" << cnt << endmsg;
00485   }
00486   return make_pair(-1,~0);
00487 }
00488 
00489 // Load object
00490 int RootDataConnection::loadObj(CSTR section, CSTR cnt, unsigned long entry, DataObject*& pObj) {
00491   TBranch* b = getBranch(section,cnt);
00492   if ( b ) {
00493     TClass* cl = gROOT->GetClass(b->GetClassName(),kTRUE);
00494     if ( cl ) {
00495       int nb = -1;
00496       pObj = (DataObject*)cl->New();
00497       {
00498         DataObjectPush push(pObj);
00499         b->SetAddress(&pObj);
00500         if ( section == m_setup->loadSection ) {
00501           TTree* t = b->GetTree();
00502           if ( Long64_t(entry) != t->GetReadEntry() ) {
00503             t->LoadTree(Long64_t(entry));
00504           }
00505         }
00506         nb = b->GetEntry(entry);
00507         msgSvc() << MSG::VERBOSE;
00508         if ( msgSvc().isActive() ) {
00509           msgSvc() << "Load [" << entry << "] --> " << section 
00510                    << ":" << cnt << "  " << nb << " bytes." 
00511                    << endmsg;
00512         }
00513         if ( nb == 0 && pObj->clID() == CLID_DataObject) {
00514           TFile* f = b->GetFile();
00515           int vsn = f->GetVersion();
00516           if ( vsn < 52400 ) {
00517             // For Gaudi v21r5 (ROOT 5.24.00b) DataObject::m_version was not written!
00518             // Still this call be well be successful.
00519             nb = 1;
00520           }
00521           else if ( vsn>1000000 && (vsn%1000000)<52400 ) {
00522             // dto. Some POOL files have for unknown reasons a version
00523             // not according to ROOT standards. Hack this explicitly.
00524             nb = 1;
00525           }
00526         }
00527         if ( nb < 0 ) {
00528           delete pObj;
00529           pObj = 0;
00530         }
00531       }
00532       return nb;
00533     }
00534   }
00535   return -1;
00536 }
00537 
00538 // Access link section for single container and entry
00539 pair<const RootRef*,const RootDataConnection::ContainerSection*> 
00540 RootDataConnection::getMergeSection(const string& container, int entry) const {
00541   //size_t idx = cont.find('/',1);
00542   //string container = cont[0]=='/' ? cont.substr(1,idx==string::npos?idx:idx-1) : cont;
00543   MergeSections::const_iterator i=m_mergeSects.find(container);
00544   if ( i != m_mergeSects.end() ) {
00545     size_t cnt = 0;
00546     const ContainerSections& s = (*i).second;
00547     for(ContainerSections::const_iterator j=s.begin(); j != s.end(); ++j,++cnt) {
00548       const ContainerSection& c = *j;
00549       if ( entry >= c.start && entry < (c.start+c.length) ) {
00550         if ( m_linkSects.size() > cnt ) {
00551           if ( msgSvc().isActive() ) {
00552             msgSvc() << MSG::VERBOSE << "MergeSection for:" << container 
00553               << "  [" << entry << "]" << endmsg
00554               << "FID:" << m_fid << " -> PFN:" << m_pfn << endmsg;
00555           }
00556           return make_pair(&(m_linkSects[cnt]), &c);
00557         }
00558       }
00559     }
00560   }
00561   msgSvc() << MSG::DEBUG << "Return INVALID MergeSection for:" << container 
00562     << "  [" << entry << "]" << endmsg
00563     << "FID:" << m_fid << " -> PFN:" << m_pfn << endmsg;
00564   return make_pair((const RootRef*)0,(const ContainerSection*)0);
00565 }
00566 
00567 // Create reference object from registry entry
00568 void RootDataConnection::makeRef(IRegistry* pR, RootRef& ref) {
00569   IOpaqueAddress* pA = pR->address();
00570   makeRef(pR->name(),pA->clID(),pA->svcType(),pA->par()[0],pA->par()[1],-1,ref);
00571 }
00572 
00573 // Create reference object from values
00574 void RootDataConnection::makeRef(CSTR name, long clid, int tech, CSTR dbase, CSTR cnt, int entry, RootRef& ref) {
00575   string db(dbase);
00576   int cdb=-1, ccnt=-1, clnk=-1;
00577   StringVec::iterator idb, icnt, ilnk;
00578   if ( db == m_fid ) {
00579     db = s_local;
00580   }
00581   ref.entry = entry;
00582   if ( !db.empty() ) {
00583     for(cdb=0,idb=m_dbs.begin(); idb!=m_dbs.end();++idb,++cdb)
00584       if( (*idb) == db ) break;
00585     if ( idb == m_dbs.end() ) {
00586       cdb = m_dbs.size();
00587       m_dbs.push_back(db);
00588     }
00589   }
00590   if ( !cnt.empty() ) {
00591     for(ccnt=0,icnt=m_conts.begin(); icnt!=m_conts.end();++icnt,++ccnt)
00592       if( (*icnt) == cnt ) break;
00593     if ( icnt == m_conts.end() ) {
00594       ccnt = m_conts.size();
00595       m_conts.push_back(cnt);
00596     }
00597   }
00598   if ( !name.empty() ) {
00599     for(clnk=0,ilnk=m_links.begin(); ilnk!=m_links.end();++ilnk,++clnk)
00600       if( (*ilnk) == name ) break;
00601     if ( ilnk == m_links.end() ) {
00602       clnk = m_links.size();
00603       m_links.push_back(name);
00604     }
00605   }
00606   ref.dbase     = cdb;
00607   ref.container = ccnt;
00608   ref.link      = clnk;
00609   ref.clid      = clid;
00610   ref.svc       = tech;
00611   if ( ref.svc == POOL_ROOT_StorageType || 
00612     ref.svc == POOL_ROOTKEY_StorageType || 
00613     ref.svc == POOL_ROOTTREE_StorageType ) {
00614       ref.svc = ROOT_StorageType;
00615     }
00616 }
00617 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Thu Jun 28 2012 23:27:29 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004