The Gaudi Framework  v30r2 (9eca68f7)
RootDataConnection.cpp
Go to the documentation of this file.
1 //====================================================================
2 // RootDataConnection.cpp
3 //--------------------------------------------------------------------
4 //
5 // Author : M.Frank
6 //====================================================================
7 
8 // Framework include files
10 #include "GaudiKernel/DataObject.h"
13 #include "GaudiKernel/IRegistry.h"
14 #include "GaudiKernel/Incident.h"
16 #include "GaudiKernel/MsgStream.h"
17 #include "GaudiKernel/strcasecmp.h"
18 #include "RootUtils.h"
19 // ROOT include files
20 #include "TBranch.h"
21 #include "TClass.h"
22 #include "TFile.h"
23 #include "TLeaf.h"
24 #include "TROOT.h"
25 #include "TTree.h"
26 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
27 #include "Compression.h"
28 static int s_compressionLevel = ROOT::CompressionSettings( ROOT::kLZMA, 4 );
29 #else
30 static int s_compressionLevel = 1;
31 #endif
32 
33 // C/C++ include files
34 #include <numeric>
35 #include <stdexcept>
36 
37 using namespace Gaudi;
38 using namespace std;
39 typedef const string& CSTR;
40 
41 static const string s_empty;
42 static const string s_local = "<localDB>";
43 
44 #ifdef __POOL_COMPATIBILITY
45 #include "PoolTool.h"
46 #endif
47 #include "RootTool.h"
48 
49 namespace
50 {
51  std::array<char, 256> init_table()
52  {
54  std::iota( std::begin( table ), std::end( table ), 0 );
55  return table;
56  }
57 
58  struct RootDataConnectionCategory : StatusCode::Category {
59  const char* name() const override { return "RootDataConnection"; }
60 
61  bool isRecoverable( StatusCode::code_t ) const override { return false; }
62 
63  std::string message( StatusCode::code_t code ) const override
64  {
65  switch ( static_cast<RootDataConnection::Status>( code ) ) {
66  case RootDataConnection::Status::ROOT_READ_ERROR:
67  return "ROOT_READ_ERROR";
68  case RootDataConnection::Status::ROOT_OPEN_ERROR:
69  return "ROOT_OPEN_ERROR";
70  default:
71  return StatusCode::default_category().message( code );
72  }
73  }
74  };
75 }
76 
77 STATUSCODE_ENUM_IMPL( Gaudi::RootDataConnection::Status, RootDataConnectionCategory )
78 
79 static bool match_wild( const char* str, const char* pat )
80 {
81  //
82  // Credits: Code from Alessandro Felice Cantatore.
83  //
84  static const std::array<char, 256> table = init_table();
85  const char *s, *p;
86  bool star = false;
87 loopStart:
88  for ( s = str, p = pat; *s; ++s, ++p ) {
89  switch ( *p ) {
90  case '?':
91  if ( *s == '.' ) goto starCheck;
92  break;
93  case '*':
94  star = true;
95  str = s, pat = p;
96  do {
97  ++pat;
98  } while ( *pat == '*' );
99  if ( !*pat ) return true;
100  goto loopStart;
101  default:
102  if ( table[*s] != table[*p] ) goto starCheck;
103  break;
104  } /* endswitch */
105  } /* endfor */
106  while ( *p == '*' ) ++p;
107  return ( !*p );
108 
109 starCheck:
110  if ( !star ) return false;
111  str++;
112  goto loopStart;
113 }
114 
117 {
118 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
119  int res = 0, level = ROOT::CompressionSettings( ROOT::kLZMA, 6 );
120  auto idx = compression.find( ':' );
121  if ( idx != string::npos ) {
122  string alg = compression.substr( 0, idx );
123  ROOT::ECompressionAlgorithm alg_code = ROOT::kUseGlobalSetting;
124  if ( strcasecmp( alg.c_str(), "ZLIB" ) == 0 )
125  alg_code = ROOT::kZLIB;
126  else if ( strcasecmp( alg.c_str(), "LZMA" ) == 0 )
127  alg_code = ROOT::kLZMA;
128  else
129  throw runtime_error( "ERROR: request to set unknown ROOT compression algorithm:" + alg );
130  res = ::sscanf( compression.c_str() + idx + 1, "%d", &level );
131  if ( res == 1 ) {
132  s_compressionLevel = ROOT::CompressionSettings( alg_code, level );
133  return StatusCode::SUCCESS;
134  }
135  throw runtime_error( "ERROR: request to set unknown ROOT compression level:" + compression.substr( idx + 1 ) );
136  } else if ( 1 == ::sscanf( compression.c_str(), "%d", &level ) ) {
137  s_compressionLevel = level;
138  return StatusCode::SUCCESS;
139  }
140  throw runtime_error( "ERROR: request to set unknown ROOT compression mechanism:" + compression );
141 #else
142  if ( !compression.empty() ) {
143  }
144  return StatusCode::SUCCESS;
145 #endif
146 }
147 
149 int RootConnectionSetup::compression() { return s_compressionLevel; }
150 
152 void RootConnectionSetup::setMessageSvc( MsgStream* m ) { m_msgSvc.reset( m ); }
153 
155 void RootConnectionSetup::setIncidentSvc( IIncidentSvc* s ) { m_incidentSvc.reset( s ); }
156 
160  : IDataConnection( owner, fname ), m_setup( std::move( setup ) )
161 { // 01234567890123456789012345678901234567890
162  // Check if FID: A82A3BD8-7ECB-DC11-8DC0-000423D950B0
163  if ( fname.length() == 36 && fname[8] == '-' && fname[13] == '-' && fname[18] == '-' && fname[23] == '-' ) {
164  m_name = "FID:" + fname;
165  }
166  m_age = 0;
167  m_file.reset();
168  addClient( owner );
169 }
170 
172 void RootDataConnection::addClient( const IInterface* client ) { m_clients.insert( client ); }
173 
176 {
177  auto i = m_clients.find( client );
178  if ( i != m_clients.end() ) m_clients.erase( i );
179  return m_clients.size();
180 }
181 
183 bool RootDataConnection::lookupClient( const IInterface* client ) const
184 {
185  auto i = m_clients.find( client );
186  return i != m_clients.end();
187 }
188 
190 void RootDataConnection::badWriteError( const string& msg ) const
191 {
192  msgSvc() << MSG::ERROR << "File:" << fid() << "Failed action:" << msg << endmsg;
193 }
194 
197 {
198  if ( m_statistics ) {
199  m_statistics->Print();
200  if ( !statisticsFile.empty() ) m_statistics->SaveAs( statisticsFile.c_str() );
202  }
203 }
204 
207 {
208  if ( m_statistics ) {
209  TTree* t = getSection( section, false );
210  if ( t ) {
211  m_statistics.reset( new TTreePerfStats( ( section + "_ioperf" ).c_str(), t ) );
212  return;
213  }
214  msgSvc() << MSG::WARNING << "Failed to enable perfstats for tree:" << section << endmsg;
215  return;
216  }
217  msgSvc() << MSG::INFO << "Perfstats are ALREADY ENABLED." << endmsg;
218 }
219 
222 {
223  if ( !m_refs ) m_refs = (TTree*)m_file->Get( "Refs" );
224  if ( m_refs ) m_tool.reset( new RootTool( this ) );
225 #ifdef __POOL_COMPATIBILITY
226  else if ( m_file->Get( "##Links" ) != nullptr )
227  m_tool.reset( new PoolTool( this ) );
228 #endif
229  else
230  m_tool.reset();
231  return m_tool.get();
232 }
233 
236 {
237  m_file.reset( TFile::Open( m_pfn.c_str() ) );
238  if ( !m_file || m_file->IsZombie() ) {
239  m_file.reset();
240  return StatusCode::FAILURE;
241  }
243  msgSvc() << MSG::DEBUG << "Opened file " << m_pfn << " in mode READ. [" << m_fid << "]" << endmsg << MSG::DEBUG;
244  if ( msgSvc().isActive() ) m_file->ls();
245  msgSvc() << MSG::VERBOSE;
246  if ( msgSvc().isActive() ) m_file->Print();
247  if ( makeTool() ) {
248  sc = m_tool->readRefs();
249  sc.ignore();
250 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
251  if ( sc == Status::ROOT_READ_ERROR ) {
252  IIncidentSvc* inc = m_setup->incidentSvc();
253  if ( inc ) {
254  inc->fireIncident( Incident( pfn(), IncidentType::CorruptedInputFile ) );
255  }
256  }
257 #endif
258  }
259  if ( !sc.isSuccess() ) return sc;
260  bool need_fid = m_fid == m_pfn;
261  string fid = m_fid;
262  m_mergeFIDs.clear();
263  for ( auto& elem : m_params ) {
264  if ( elem.first == "FID" ) {
265  m_mergeFIDs.push_back( elem.second );
266  if ( elem.second != m_fid ) {
267  msgSvc() << MSG::DEBUG << "Check FID param:" << elem.second << endmsg;
268  // if ( m_fid == m_pfn ) {
269  m_fid = elem.second;
270  //}
271  }
272  }
273  }
274  if ( !need_fid && fid != m_fid ) {
275  msgSvc() << MSG::ERROR << "FID mismatch:" << fid << "(Catalog) != " << m_fid << "(file)" << endmsg
276  << "for PFN:" << m_pfn << endmsg;
277  return StatusCode::FAILURE;
278  }
279  msgSvc() << MSG::DEBUG << "Using FID " << m_fid << " from params table...." << endmsg << "for PFN:" << m_pfn
280  << endmsg;
281  return sc;
282 }
283 
286 {
287  int compress = RootConnectionSetup::compression();
288  msgSvc() << MSG::DEBUG;
289  switch ( typ ) {
290  case CREATE:
291  resetAge();
292  m_file.reset( TFile::Open( m_pfn.c_str(), "CREATE", "Root event data", compress ) );
293  m_refs = new TTree( "Refs", "Root reference data" );
294  msgSvc() << "Opened file " << m_pfn << " in mode CREATE. [" << m_fid << "]" << endmsg;
295  m_params.emplace_back( "PFN", m_pfn );
296  if ( m_fid != m_pfn ) {
297  m_params.emplace_back( "FID", m_fid );
298  }
299  makeTool();
300  break;
301  case RECREATE:
302  resetAge();
303  m_file.reset( TFile::Open( m_pfn.c_str(), "RECREATE", "Root event data", compress ) );
304  msgSvc() << "Opened file " << m_pfn << " in mode RECREATE. [" << m_fid << "]" << endmsg;
305  m_refs = new TTree( "Refs", "Root reference data" );
306  m_params.emplace_back( "PFN", m_pfn );
307  if ( m_fid != m_pfn ) {
308  m_params.emplace_back( "FID", m_fid );
309  }
310  makeTool();
311  break;
312  case UPDATE:
313  resetAge();
314  m_file.reset( TFile::Open( m_pfn.c_str(), "UPDATE", "Root event data", compress ) );
315  msgSvc() << "Opened file " << m_pfn << " in mode UPDATE. [" << m_fid << "]" << endmsg;
316  if ( m_file && !m_file->IsZombie() ) {
317  if ( makeTool() ) {
318  StatusCode sc = m_tool->readRefs();
319  sc.ignore();
320  if ( sc == Status::ROOT_READ_ERROR ) {
321 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
322  IIncidentSvc* inc = m_setup->incidentSvc();
323  if ( inc ) {
324  inc->fireIncident( Incident( pfn(), IncidentType::CorruptedInputFile ) );
325  }
326 #endif
327  }
328  return sc;
329  }
330  TDirectory::TContext ctxt( m_file.get() );
331  m_refs = new TTree( "Refs", "Root reference data" );
332  makeTool();
333  return StatusCode::SUCCESS;
334  }
335  break;
336  default:
337  m_refs = nullptr;
338  m_file.reset();
339  return StatusCode::FAILURE;
340  }
342 }
343 
346 {
347  if ( m_file ) {
348  if ( !m_file->IsZombie() ) {
349  if ( m_file->IsWritable() ) {
350  msgSvc() << MSG::DEBUG;
351  TDirectory::TContext ctxt( m_file.get() );
352  if ( m_refs ) {
353  if ( !m_tool->saveRefs().isSuccess() ) badWriteError( "Saving References" );
354  if ( m_refs->Write() < 0 ) badWriteError( "Write Reference branch" );
355  }
356  for ( auto& i : m_sections ) {
357  if ( i.second ) {
358  if ( i.second->Write() < 0 ) badWriteError( "Write section:" + i.first );
359  msgSvc() << "Disconnect section " << i.first << " " << i.second->GetName() << endmsg;
360  }
361  }
362  m_sections.clear();
363  }
364  msgSvc() << MSG::DEBUG;
365  if ( msgSvc().isActive() ) m_file->ls();
366  msgSvc() << MSG::VERBOSE;
367  if ( msgSvc().isActive() ) m_file->Print();
368  m_file->Close();
369  }
370  msgSvc() << MSG::DEBUG << "Disconnected file " << m_pfn << " " << m_file->GetName() << endmsg;
371  m_file.reset();
372  m_tool.reset();
373  }
374  return StatusCode::SUCCESS;
375 }
376 
378 TTree* RootDataConnection::getSection( CSTR section, bool create )
379 {
380  TTree* t = m_sections[section];
381  if ( !t ) {
382  t = (TTree*)m_file->Get( section.c_str() );
383  if ( !t && create ) {
384  TDirectory::TContext ctxt( m_file.get() );
385  t = new TTree( section.c_str(), "Root data for Gaudi" );
386  }
387  if ( t ) {
388  int cacheSize = m_setup->cacheSize;
389  if ( create ) {
390  // t->SetAutoFlush(100);
391  }
392  if ( section == m_setup->loadSection && cacheSize > -2 ) {
393  MsgStream& msg = msgSvc();
394  int learnEntries = m_setup->learnEntries;
395  t->SetCacheSize( cacheSize );
396  t->SetCacheLearnEntries( learnEntries );
397  msg << MSG::DEBUG;
398  if ( create ) {
399  msg << "Tree:" << section << "Setting up tree cache:" << cacheSize << endmsg;
400  } else {
401  const StringVec& vB = m_setup->vetoBranches;
402  const StringVec& cB = m_setup->cacheBranches;
403  msg << "Tree:" << section << " Setting up tree cache:" << cacheSize << " Add all branches." << endmsg;
404  msg << "Tree:" << section << " Learn for " << learnEntries << " entries." << endmsg;
405 
406  if ( cB.empty() && vB.empty() ) {
407  msg << "Adding (default) all branches to tree cache." << endmsg;
408  t->AddBranchToCache( "*", kTRUE );
409  }
410  if ( cB.size() == 1 && cB[0] == "*" ) {
411  msg << "Adding all branches to tree cache according to option \"CacheBranches\"." << endmsg;
412  t->AddBranchToCache( "*", kTRUE );
413  } else {
414  for ( TIter it( t->GetListOfBranches() ); it.Next(); ) {
415  const char* n = ( (TNamed*)( *it ) )->GetName();
416  bool add = false, veto = false;
417  for ( const auto& i : cB ) {
418  if ( !match_wild( n, ( i ).c_str() ) ) continue;
419  add = true;
420  break;
421  }
422  for ( auto i = vB.cbegin(); !add && i != vB.cend(); ++i ) {
423  if ( !match_wild( n, ( *i ).c_str() ) ) continue;
424  veto = true;
425  break;
426  }
427  if ( add && !veto ) {
428  msg << "Add " << n << " to branch cache." << endmsg;
429  t->AddBranchToCache( n, kTRUE );
430  } else {
431  msg << "Do not cache branch " << n << endmsg;
432  }
433  }
434  }
435  }
436  }
437  m_sections[section] = t;
438  }
439  }
440  return t;
441 }
442 
444 TBranch* RootDataConnection::getBranch( CSTR section, CSTR branch_name, TClass* cl, void* ptr, int buff_siz,
445  int split_lvl )
446 {
447  string n = branch_name;
448  std::replace_if( std::begin( n ), std::end( n ), []( const char c ) { return !isalnum( c ); }, '_' );
449  n += ".";
450  TTree* t = getSection( section, true );
451  TBranch* b = t->GetBranch( n.c_str() );
452  if ( !b && cl && m_file->IsWritable() ) {
453  b = t->Branch( n.c_str(), cl->GetName(), (void*)( ptr ? &ptr : nullptr ), buff_siz, split_lvl );
454  }
455  if ( !b ) b = t->GetBranch( branch_name.c_str() );
456  if ( b ) b->SetAutoDelete( kFALSE );
457  return b;
458 }
459 
462 {
463  auto ip = std::find( std::begin( m_links ), std::end( m_links ), p );
464  if ( ip != std::end( m_links ) ) return std::distance( std::begin( m_links ), ip );
465  m_links.push_back( p );
466  return m_links.size() - 1;
467 }
468 
471 {
472  if ( ( which >= 0 ) && ( size_t( which ) < m_dbs.size() ) ) {
473  if ( *( m_dbs.begin() + which ) == s_local ) return m_fid;
474  return *( m_dbs.begin() + which );
475  }
476  return s_empty;
477 }
478 
480 CSTR RootDataConnection::empty() const { return s_empty; }
481 
484  int buff_siz, int split_lvl, bool fill )
485 {
486  DataObjectPush push( pObj );
487  return save( section, cnt, cl, pObj, buff_siz, split_lvl, fill );
488 }
489 
491 pair<int, unsigned long> RootDataConnection::save( CSTR section, CSTR cnt, TClass* cl, void* pObj, int buff_siz,
492  int split_lvl, bool fill_missing )
493 {
494  split_lvl = 0;
495  TBranch* b = getBranch( section, cnt, cl, pObj ? &pObj : nullptr, buff_siz, split_lvl );
496  if ( b ) {
497  Long64_t evt = b->GetEntries();
498  // msgSvc() << MSG::DEBUG << cnt.c_str() << " Obj:" << (void*)pObj
499  // << " Split:" << split_lvl << " Buffer size:" << buff_siz << endl;
500  if ( fill_missing ) {
501  Long64_t num, nevt = b->GetTree()->GetEntries();
502  if ( nevt > evt ) {
503  b->SetAddress( nullptr );
504  num = nevt - evt;
505  while ( num > 0 ) {
506  b->Fill();
507  --num;
508  }
509  msgSvc() << MSG::DEBUG << "Added " << long( nevt - evt ) << " / Tree: " << nevt
510  << " / Branch: " << b->GetEntries() + 1 << " NULL entries to:" << cnt << endmsg;
511  evt = b->GetEntries();
512  }
513  }
514  b->SetAddress( &pObj );
515  return {b->Fill(), evt};
516  }
517  if ( pObj ) {
518  msgSvc() << MSG::ERROR << "Failed to access branch " << m_name << "/" << cnt << endmsg;
519  }
520  return {-1, ~0};
521 }
522 
524 int RootDataConnection::loadObj( CSTR section, CSTR cnt, unsigned long entry, DataObject*& pObj )
525 {
526  TBranch* b = getBranch( section, cnt );
527  if ( b ) {
528  TClass* cl = gROOT->GetClass( b->GetClassName(), kTRUE );
529  if ( cl ) {
530  int nb = -1;
531  pObj = (DataObject*)cl->New();
532  {
533  DataObjectPush push( pObj );
534  b->SetAddress( &pObj );
535  if ( section == m_setup->loadSection ) {
536  TTree* t = b->GetTree();
537  if ( Long64_t( entry ) != t->GetReadEntry() ) {
538  t->LoadTree( Long64_t( entry ) );
539  }
540  }
541  nb = b->GetEntry( entry );
542  msgSvc() << MSG::VERBOSE;
543  if ( msgSvc().isActive() ) {
544  msgSvc() << "Load [" << entry << "] --> " << section << ":" << cnt << " " << nb << " bytes." << endmsg;
545  }
546  if ( nb < 0 ) { // This is definitely an error...ROOT says if reads fail, -1 is issued.
547 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
548  IIncidentSvc* inc = m_setup->incidentSvc();
549  if ( inc ) {
550  inc->fireIncident( Incident( pfn(), IncidentType::CorruptedInputFile ) );
551  }
552 #endif
553  } else if ( nb == 0 && pObj->clID() == CLID_DataObject ) {
554  TFile* f = b->GetFile();
555  int vsn = f->GetVersion();
556  if ( vsn < 52400 ) {
557  // For Gaudi v21r5 (ROOT 5.24.00b) DataObject::m_version was not written!
558  // Still this call be well be successful.
559  nb = 1;
560  } else if ( vsn > 1000000 && ( vsn % 1000000 ) < 52400 ) {
561  // dto. Some POOL files have for unknown reasons a version
562  // not according to ROOT standards. Hack this explicitly.
563  nb = 1;
564  }
565  }
566  if ( nb < 0 ) {
567  delete pObj;
568  pObj = nullptr;
569  }
570  }
571  return nb;
572  }
573  }
574  return -1;
575 }
576 
578 int RootDataConnection::loadRefs( const std::string& section, const std::string& cnt, unsigned long entry,
579  RootObjectRefs& refs )
580 {
581  int nbytes = m_tool->loadRefs( section, cnt, entry, refs );
582 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
583  if ( nbytes < 0 ) {
584  // This is definitely an error:
585  // -- Either branch not preesent at all or
586  // -- ROOT I/O error, which issues -1
587  IIncidentSvc* inc = m_setup->incidentSvc();
588  if ( inc ) {
589  inc->fireIncident( Incident( pfn(), IncidentType::CorruptedInputFile ) );
590  }
591  }
592 #endif
593  return nbytes;
594 }
595 
598 RootDataConnection::getMergeSection( const string& container, int entry ) const
599 {
600  // size_t idx = cont.find('/',1);
601  // string container = cont[0]=='/' ? cont.substr(1,idx==string::npos?idx:idx-1) : cont;
602  auto i = m_mergeSects.find( container );
603  if ( i != m_mergeSects.end() ) {
604  size_t cnt = 0;
605  const ContainerSections& s = ( *i ).second;
606  for ( auto j = s.cbegin(); j != s.cend(); ++j, ++cnt ) {
607  const ContainerSection& c = *j;
608  if ( entry >= c.start && entry < ( c.start + c.length ) ) {
609  if ( m_linkSects.size() > cnt ) {
610  if ( msgSvc().isActive() ) {
611  msgSvc() << MSG::VERBOSE << "MergeSection for:" << container << " [" << entry << "]" << endmsg
612  << "FID:" << m_fid << " -> PFN:" << m_pfn << endmsg;
613  }
614  return {&( m_linkSects[cnt] ), &c};
615  }
616  }
617  }
618  }
619  msgSvc() << MSG::DEBUG << "Return INVALID MergeSection for:" << container << " [" << entry << "]" << endmsg
620  << "FID:" << m_fid << " -> PFN:" << m_pfn << endmsg;
621  return {nullptr, nullptr};
622 }
623 
626 {
627  IOpaqueAddress* pA = pR->address();
628  makeRef( pR->name(), pA->clID(), pA->svcType(), pA->par()[0], pA->par()[1], -1, ref );
629 }
630 
632 void RootDataConnection::makeRef( CSTR name, long clid, int tech, CSTR dbase, CSTR cnt, int entry, RootRef& ref )
633 {
634  string db( dbase );
635  if ( db == m_fid ) db = s_local;
636  ref.entry = entry;
637 
638  int cdb = -1;
639  if ( !db.empty() ) {
640  auto idb = std::find_if( m_dbs.begin(), m_dbs.end(), [&]( const std::string& i ) { return i == db; } );
641  cdb = std::distance( m_dbs.begin(), idb );
642  if ( idb == m_dbs.end() ) m_dbs.push_back( db );
643  }
644 
645  int ccnt = -1;
646  if ( !cnt.empty() ) {
647  auto icnt = std::find_if( m_conts.begin(), m_conts.end(), [&]( const std::string& i ) { return i == cnt; } );
648  ccnt = std::distance( m_conts.begin(), icnt );
649  if ( icnt == m_conts.end() ) m_conts.push_back( cnt );
650  }
651 
652  int clnk = -1;
653  if ( !name.empty() ) {
654  auto ilnk = std::find_if( m_links.begin(), m_links.end(), [&]( const std::string& i ) { return i == name; } );
655  clnk = std::distance( m_links.begin(), ilnk );
656  if ( ilnk == m_links.end() ) m_links.push_back( name );
657  }
658 
659  ref.dbase = cdb;
660  ref.container = ccnt;
661  ref.link = clnk;
662  ref.clid = clid;
663  ref.svc = tech;
664  if ( ref.svc == POOL_ROOT_StorageType || ref.svc == POOL_ROOTKEY_StorageType ||
665  ref.svc == POOL_ROOTTREE_StorageType ) {
666  ref.svc = ROOT_StorageType;
667  }
668 }
void addClient(const IInterface *client)
Add new client to this data source.
bool lookupClient(const IInterface *client) const
Lookup client for this data source.
constexpr static const auto FAILURE
Definition: StatusCode.h:88
MergeSections m_mergeSects
Database section map for merged files.
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
T empty(T...args)
T distance(T...args)
virtual const CLID & clID() const =0
Retrieve class information from link.
int m_age
Age counter.
const std::string & fid() const
Access file id.
std::unique_ptr< Tool > m_tool
std::string m_name
Connection name/identifier.
IoType
I/O Connection types.
std::pair< int, unsigned long > saveObj(const std::string &section, const std::string &cnt, TClass *cl, DataObject *pObj, int buff_siz, int split_lvl, bool fill_missing=false)
Save object of a given class to section and container.
void saveStatistics(const std::string &statisticsFile)
Save TTree access statistics if required.
T sscanf(T...args)
const std::string & getDb(int which) const
Access database/file name from saved index.
std::string m_fid
File ID of the connection.
bool isSuccess() const
Definition: StatusCode.h:287
The category assigned to a StatusCode.
Definition: StatusCode.h:65
std::unique_ptr< TTreePerfStats > m_statistics
I/O read statistics from TTree.
int loadObj(const std::string &section, const std::string &cnt, unsigned long entry, DataObject *&pObj)
Load object.
T isalnum(T...args)
static int compression()
Access to global compression level.
Clients m_clients
Client list.
TTree * getSection(const std::string &sect, bool create=false)
Access TTree section from section name. The section is created if required.
int start
The start entry of the section.
size_t removeClient(const IInterface *client)
Remove client from this data source.
bool isActive() const
Accessor: is MsgStream active.
Definition: MsgStream.h:116
GAUDI_API void fill(AIDA::IHistogram1D *histo, const double value, const double weight=1.0)
simple function to fill AIDA::IHistogram1D objects
Definition: Fill.cpp:35
STL namespace.
RootDataConnection(const IInterface *own, const std::string &nam, std::shared_ptr< RootConnectionSetup > setup)
Standard constructor.
virtual const name_type & name() const =0
Name of the directory (or key)
T end(T...args)
T iota(T...args)
void setMessageSvc(MsgStream *m)
Set message service reference.
StatusCode connectWrite(IoType typ) override
Open data stream in write mode.
virtual const std::string * par() const =0
Retrieve String parameters.
static StatusCode setCompression(const std::string &compression)
Set the global compression level.
const std::string & pfn() const
Access physical file name.
int loadRefs(const std::string &section, const std::string &cnt, unsigned long entry, RootObjectRefs &refs)
Load references object.
Persistent reference object containing all leafs and links corresponding to a Gaudi DataObject...
Definition: RootRefs.h:60
StringVec m_links
Map containing internal links names.
ParamMap m_params
Parameter map for file parameters.
STL class.
const long POOL_ROOTKEY_StorageType
Definition: ClassID.h:69
const string & CSTR
StringVec m_mergeFIDs
Map containing merge FIDs.
std::string m_pfn
Physical file name of the connection.
int dbase
Data members to define object location in the persistent world.
Definition: RootRefs.h:33
Persistent reference object.
Definition: RootRefs.h:31
T push_back(T...args)
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
Description:
Definition: RootTool.h:17
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:62
const std::string & name() const
Connection name.
T replace_if(T...args)
Helper class to facilitate an abstraction layer for reading POOL style files with this package...
#define STATUSCODE_ENUM_IMPL(...)
Assign a category to the StatusCode enum declared with STATUSCODE_ENUM_DECL( ENUM ) ...
Definition: StatusCode.h:267
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:51
constexpr double m
Definition: SystemOfUnits.h:94
void clear(STATE_TYPE _i=std::ios_base::failbit)
Definition: MsgStream.h:187
Definition of the basic interface.
Definition: IInterface.h:277
static const Category & default_category() noexcept
Default Gaudi StatusCode category.
Definition: StatusCode.h:282
TBranch * getBranch(const std::string &section, const std::string &branch_name)
Access data branch by name: Get existing branch in read only mode.
void makeRef(IRegistry *pA, RootRef &ref)
Create reference object from registry entry.
T erase(T...args)
StringVec m_conts
Map containing external container names.
const std::string & empty() const
Empty string reference.
Sections m_sections
Tree sections in TFile.
std::pair< const RootRef *, const ContainerSection * > getMergeSection(const std::string &container, int entry) const
Access link section for single container and entry.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
const long ROOT_StorageType
Definition: ClassID.h:52
virtual long svcType() const =0
Retrieve service type.
T reset(T...args)
T clear(T...args)
const long POOL_ROOT_StorageType
Definition: ClassID.h:68
Tool * makeTool()
Create file access tool to encapsulate POOL compatibiliy.
T move(T...args)
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
std::pair< int, unsigned long > save(const std::string &section, const std::string &cnt, TClass *cl, void *pObj, int buff_siz, int split_lvl, bool fill_missing=false)
Save object of a given class to section and container.
T get(T...args)
T insert(T...args)
T find(T...args)
T length(T...args)
StatusCode connectRead() override
Open data stream in read mode.
ABC describing basic data connection.
int makeLink(const std::string &p)
Convert path string to path index.
const long POOL_ROOTTREE_StorageType
Definition: ClassID.h:70
std::shared_ptr< RootConnectionSetup > m_setup
Reference to the setup structure.
T begin(T...args)
LinkSections m_linkSects
Database link sections.
def which(executable)
Definition: BaseTest.py:571
void resetAge()
Reset age.
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:165
T c_str(T...args)
Base class for all Incidents (computing events).
Definition: Incident.h:17
MsgStream & msgSvc() const
Allow access to printer service.
string s
Definition: gaudirun.py:253
STL class.
T substr(T...args)
std::unique_ptr< TFile > m_file
Reference to ROOT file.
Opaque address interface definition.
StringVec m_dbs
Map containing external database file names (fids)
StatusCode disconnect() override
Release data stream and release implementation dependent resources.
void setIncidentSvc(IIncidentSvc *m)
Set incident service reference.
void enableStatistics(const std::string &section)
Enable TTreePerStats.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
TTree * m_refs
Pointer to the reference tree.
virtual std::string message(code_t code) const
Description for code within this category.
Definition: StatusCode.h:73
Helper functions to set/get the application return code.
Definition: __init__.py:1
Internal helper class, which described a TBranch section in a ROOT file.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
The interface implemented by the IncidentSvc service.
Definition: IIncidentSvc.h:23
void badWriteError(const std::string &msg) const
Error handler when bad write statements occur.
evt
Definition: IOTest.py:96
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:54
T emplace_back(T...args)