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