The Gaudi Framework  master (37c0b60a)
THistSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // system headers
12 #include <cassert>
13 #include <cstdio>
14 #include <format>
15 #include <sstream>
16 #include <streambuf>
17 
18 // boost headers
19 #include <boost/algorithm/string/case_conv.hpp>
20 
21 // ROOT headers
22 #include <TClass.h>
23 #include <TDirectory.h>
24 #include <TError.h>
25 #include <TFile.h>
26 #include <TGraph.h>
27 #include <TKey.h>
28 #include <TROOT.h>
29 
30 // Gaudi headers
31 #include <Gaudi/Property.h>
35 #include <GaudiKernel/IFileMgr.h>
39 
40 // local headers
41 #include "THistSvc.h"
42 
43 // FIXME - leak sanitizers generate a number of warnings here
44 //
45 // Appears to be an issue with the mutex ownsership with LockedHandle ?
46 // clang-format off
47 // Direct leak of 40 byte(s) in 1 object(s) allocated from:
48 // #0 0x7f09944fcda8 in operator new(unsigned long) /afs/cern.ch/cms/CAF/CMSCOMM/COMM_ECAL/dkonst/GCC/build/contrib/gcc-8.2.0/src/gcc/8.2.0/libsanitizer/lsan/lsan_interceptors.cc:229
49 // #1 0x7f0987aa2e6d in StatusCode THistSvc::regHist_i<TH1>(std::unique_ptr<TH1, std::default_delete<TH1> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, THistSvc::THistID*&) ../GaudiSvc/src/THistSvc/THistSvc.icc:139
50 // #2 0x7f0987aa3375 in LockedHandle<TH1, std::mutex> THistSvc::regShared_i<TH1>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::unique_ptr<TH1, std::default_delete<TH1> >) ../GaudiSvc/src/THistSvc/THistSvc.icc:264
51 // #3 0x7f0987a8f8ef in THistSvc::regShared(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::unique_ptr<TH1, std::default_delete<TH1> >, LockedHandle<TH1, std::mutex>&) ../GaudiSvc/src/THistSvc/THistSvc.cpp:430
52 // clang-format on
53 //
54 // These leaks are currently suppressed in Gaudi/job/Gaudi-LSan.supp - remove entry there to reactivate
55 
57 
58 namespace {
59  template <typename InputIterator, typename OutputIterator, typename UnaryOperation, typename UnaryPredicate>
60  OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
61  UnaryPredicate pred ) {
62  while ( first != last ) {
63  if ( pred( *first ) ) *result++ = op( *first );
64  ++first;
65  }
66  return result;
67  }
68 
69  constexpr struct select1st_t {
70  template <typename T, typename S>
71  const T& operator()( const std::pair<T, S>& p ) const {
72  return p.first;
73  }
74  } select1st{};
75 } // namespace
76 
77 //*************************************************************************//
78 
80  : base_class( name, svcloc ), p_incSvc( "IncidentSvc", name ), p_fileMgr( "FileMgr", name ) {}
81 
84 
86 
87  if ( status.isFailure() ) {
88  error() << "initializing service" << endmsg;
89  return status;
90  }
91 
93 
94  try {
96  } catch ( GaudiException& err ) {
97  error() << "Caught: " << err << endmsg;
99  }
100 
101  try {
102  setupInputFile();
103  } catch ( GaudiException& err ) {
104  error() << "Caught: " << err << endmsg;
105  st = StatusCode::FAILURE;
106  }
107 
108  // Protect against multiple instances of TROOT
109  if ( !gROOT ) {
110  static TROOT root( "root", "ROOT I/O" );
111  // gDebug = 99;
112  } else {
113  if ( msgLevel( MSG::VERBOSE ) ) { verbose() << "ROOT already initialized, debug = " << gDebug << endmsg; }
114  }
115 
116  if ( p_incSvc.retrieve().isFailure() ) {
117  error() << "unable to get the IncidentSvc" << endmsg;
118  st = StatusCode::FAILURE;
119  } else {
120  p_incSvc->addListener( this, "EndEvent", 100, true );
121  }
122 
123  if ( p_fileMgr.retrieve().isFailure() ) {
124  error() << "unable to get the FileMgr" << endmsg;
125  st = StatusCode::FAILURE;
126  } else {
127  if ( msgLevel( MSG::DEBUG ) ) { debug() << "got the FileMgr" << endmsg; }
128  }
129 
130  // Register open/close callback actions
131  using namespace std::placeholders;
132  auto boa = [this]( const Io::FileAttr* fa, const std::string& caller ) { return this->rootOpenAction( fa, caller ); };
133  if ( p_fileMgr->regAction( boa, Io::OPEN, Io::ROOT ).isFailure() ) {
134  error() << "unable to register ROOT file open action with FileMgr" << endmsg;
135  }
136  auto bea = [this]( const Io::FileAttr* fa, const std::string& caller ) {
137  return this->rootOpenErrAction( fa, caller );
138  };
139  if ( p_fileMgr->regAction( bea, Io::OPEN_ERR, Io::ROOT ).isFailure() ) {
140  error() << "unable to register ROOT file open Error action with FileMgr" << endmsg;
141  }
142 
143  m_okToConnect = true;
144  if ( m_delayConnect ) {
145  if ( !m_inputfile.value().empty() ) setupInputFile();
146  if ( !m_outputfile.value().empty() ) setupOutputFile();
147  m_delayConnect = false;
148  }
151 
152  auto iomgr = service<IIoComponentMgr>( "IoComponentMgr" );
153  if ( !iomgr ) {
154  error() << "unable to get the IoComponentMgr" << endmsg;
155  st = StatusCode::FAILURE;
156  } else {
157  if ( !iomgr->io_register( this ).isSuccess() ) {
158  error() << "could not register with the I/O component manager !" << endmsg;
159  st = StatusCode::FAILURE;
160  } else {
161  bool all_good = true;
162  // register input/output files...
163  for ( const auto& reg : m_files ) {
164  const std::string& fname = reg.second.first->GetName();
165  const IIoComponentMgr::IoMode::Type iomode =
167  if ( !iomgr->io_register( this, iomode, fname ).isSuccess() ) {
168  warning() << "could not register file [" << fname << "] with the I/O component manager..." << endmsg;
169  all_good = false;
170  } else {
171  info() << "registered file [" << fname << "]... [ok]" << endmsg;
172  }
173  }
174  if ( !all_good ) {
175  error() << "problem while registering input/output files with "
176  << "the I/O component manager !" << endmsg;
177  st = StatusCode::FAILURE;
178  }
179  }
180  }
181 
182  if ( st.isFailure() ) { fatal() << "Unable to initialize THistSvc" << endmsg; }
183 
184  return st;
185 }
186 
188  GlobalDirectoryRestore restore( m_svcMut );
189  warning() << "reinitialize not implemented" << endmsg;
190  return StatusCode::SUCCESS;
191 }
192 
194  GlobalDirectoryRestore restore( m_svcMut );
195 
196  if ( msgLevel( MSG::DEBUG ) ) {
197  dump();
198  debug() << "THistSvc::finalize" << endmsg;
199  }
200 
201 #ifndef NDEBUG
202  if ( msgLevel( MSG::DEBUG ) ) {
204  for ( const auto& itr : sorted_uids ) {
205  THistID& thid = itr.second->at( 0 );
206  TObject* tobj = thid.obj;
207 
208  std::string dirname( "none" );
209  if ( tobj && thid.type == ObjectType::TTREE ) {
210  TTree* tree = dynamic_cast<TTree*>( tobj );
211  if ( tree->GetDirectory() != 0 ) { dirname = tree->GetDirectory()->GetPath(); }
212  } else if ( tobj && thid.type == ObjectType::TGRAPH ) {
213  if ( !thid.temp ) {
214  dirname = thid.file->GetPath();
215  std::string id2( thid.id );
216  id2.erase( 0, id2.find( "/", 1 ) );
217  id2.erase( id2.rfind( "/" ), id2.length() );
218  if ( id2.starts_with( "/" ) ) { id2.erase( 0, 1 ); }
219  dirname += id2;
220  } else {
221  dirname = "/tmp";
222  }
223  } else if ( tobj && thid.type == ObjectType::TH1 ) {
224  TH1* th = dynamic_cast<TH1*>( tobj );
225  if ( th == nullptr ) {
226  error() << "Couldn't dcast: " << itr.first << endmsg;
227  } else {
228  if ( th->GetDirectory() != 0 ) { dirname = th->GetDirectory()->GetPath(); }
229  }
230  } else if ( !tobj ) {
231  warning() << itr.first << " has NULL TObject ptr" << endmsg;
232  }
233  debug() << "finalize: " << thid << endmsg;
234  }
235  }
236 #endif
237 
238  if ( writeObjectsToFile().isFailure() ) { error() << "problems writing histograms" << endmsg; }
239 
240  if ( m_print ) { info() << "Listing contents of ROOT files: " << endmsg; }
241  std::vector<TFile*> deleted_files;
242  for ( auto& itr : m_files ) {
243  if ( std::find( deleted_files.begin(), deleted_files.end(), itr.second.first ) == deleted_files.end() ) {
244  deleted_files.push_back( itr.second.first );
245 
246 #ifndef NDEBUG
247  if ( msgLevel( MSG::DEBUG ) ) {
248  debug() << "finalizing stream/file " << itr.first << ":" << itr.second.first->GetName() << endmsg;
249  }
250 #endif
251  } else {
252 #ifndef NDEBUG
253  if ( msgLevel( MSG::DEBUG ) ) { debug() << "already finalized stream " << itr.first << endmsg; }
254 #endif
255  continue;
256  }
257 
258  if ( m_print && msgLevel( MSG::INFO ) ) {
259  info() << "==> File: " << itr.second.first->GetName() << " stream: " << itr.first << endmsg;
260 
261  itr.second.first->Print( "base" );
262  }
263 
264  std::string tmpfn = itr.second.first->GetName();
265 
266  p_fileMgr->close( itr.second.first, name() );
267 
268  if ( itr.second.second == SHARE ) {
269  // Merge File
270  void* vfile = nullptr;
271  int returncode =
272  p_fileMgr->open( Io::ROOT, name(), m_sharedFiles[itr.first], Io::WRITE | Io::APPEND, vfile, "HIST" );
273 
274  if ( returncode ) {
275  error() << "unable to open Final Output File: \"" << m_sharedFiles[itr.first] << "\" for merging" << endmsg;
276  return StatusCode::FAILURE;
277  }
278 
279  TFile* outputfile = (TFile*)vfile;
280  p_incSvc->fireIncident( FileIncident( name(), IncidentType::WroteToOutputFile, m_sharedFiles[itr.first] ) );
281 
282  if ( msgLevel( MSG::DEBUG ) ) { debug() << "THistSvc::writeObjectsToFile()::Merging Rootfile " << endmsg; }
283 
284  vfile = nullptr;
285  returncode = p_fileMgr->open( Io::ROOT, name(), tmpfn, Io::READ, vfile, "HIST" );
286 
287  if ( returncode ) {
288  error() << "unable to open temporary file: \"" << tmpfn << endmsg;
289  return StatusCode::FAILURE;
290  }
291 
292  TFile* inputfile = (TFile*)vfile;
293 
294  outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
295 
296  MergeRootFile( outputfile, inputfile );
297 
298  outputfile->Write();
299  p_fileMgr->close( outputfile, name() );
300  p_fileMgr->close( inputfile, name() );
301 
302  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Trying to remove temporary file \"" << tmpfn << "\"" << endmsg; }
303 
304  std::remove( tmpfn.c_str() );
305  }
306  delete itr.second.first;
307  }
308 
309  m_files.clear();
312  m_hlist.clear(); // vhid* is deleted in m_tobjs
313  m_uids.clear(); // vhid* is deleted in m_tobjs
314  m_ids.clear(); // vhid* is deleted in m_tobjs
315 
316  for ( auto& obj : m_tobjs ) {
317  // TObject*'s are already dealt with through root file i/o
318  // only delete vector if this object is index 0
319  if ( obj.second.second == 0 ) {
320  delete obj.second.first; // delete vhid*
321  }
322  }
323  m_tobjs.clear();
324 
325  return Service::finalize();
326 }
327 
328 //*************************************************************************//
329 
331  std::unique_ptr<TH1> hist = nullptr;
332  return regHist_i( std::move( hist ), id, false );
333 }
334 
336  return regHist_i( std::move( hist ), id, false );
337 }
338 
339 StatusCode THistSvc::regHist( const std::string& id, TH1* hist_ptr ) {
340  std::unique_ptr<TH1> hist( hist_ptr );
341  return regHist_i( std::move( hist ), id, false );
342 }
343 
344 StatusCode THistSvc::getHist( const std::string& id, TH1*& hist, size_t ind ) const {
345  hist = getHist_i<TH1>( id, ind );
346  if ( hist != nullptr ) {
347  return StatusCode::SUCCESS;
348  } else {
349  return StatusCode::FAILURE;
350  }
351 }
352 
353 StatusCode THistSvc::getHist( const std::string& id, TH2*& hist, size_t ind ) const {
354  hist = getHist_i<TH2>( id, ind );
355  if ( hist != nullptr ) {
356  return StatusCode::SUCCESS;
357  } else {
358  return StatusCode::FAILURE;
359  }
360 }
361 
362 StatusCode THistSvc::getHist( const std::string& id, TH3*& hist, size_t ind ) const {
363  hist = getHist_i<TH3>( id, ind );
364  if ( hist != nullptr ) {
365  return StatusCode::SUCCESS;
366  } else {
367  return StatusCode::FAILURE;
368  }
369 }
370 
372  std::unique_ptr<TTree> tree = nullptr;
373  return regHist_i( std::move( tree ), id, false );
374 }
375 
377  StatusCode sc = regHist_i( std::move( tree ), id, false );
378  TTree* tr = nullptr;
379  if ( getTree( id, tr ).isSuccess() && sc.isSuccess() ) {
380  if ( m_autoSave != 0 ) { tr->SetAutoSave( m_autoSave ); }
381  tr->SetAutoFlush( m_autoFlush );
382  }
383  return sc;
384 }
385 
386 StatusCode THistSvc::regTree( const std::string& id, TTree* tree_ptr ) {
387  std::unique_ptr<TTree> tree( tree_ptr );
388  StatusCode sc = regHist_i( std::move( tree ), id, false );
389  TTree* tr = nullptr;
390  if ( getTree( id, tr ).isSuccess() && sc.isSuccess() ) {
391  if ( m_autoSave != 0 ) { tr->SetAutoSave( m_autoSave ); }
392  tr->SetAutoFlush( m_autoFlush );
393  }
394  return sc;
395 }
396 
397 StatusCode THistSvc::getTree( const std::string& id, TTree*& tree ) const {
398  tree = getHist_i<TTree>( id );
399  if ( tree != nullptr ) {
400  return StatusCode::SUCCESS;
401  } else {
402  return StatusCode::FAILURE;
403  }
404 }
405 
407  std::unique_ptr<TGraph> graph = std::make_unique<TGraph>();
408  return regHist_i( std::move( graph ), id, false );
409 }
410 
412  if ( strcmp( graph->GetName(), "Graph" ) == 0 ) {
413  std::string id2( id );
414  std::string::size_type i = id2.rfind( "/" );
415  if ( i != std::string::npos ) { id2.erase( 0, i + 1 ); }
416 
417  info() << "setting name of TGraph id: \"" << id << "\" to \"" << id2 << "\" since it is unset" << endmsg;
418  graph->SetName( id2.c_str() );
419  }
420 
421  return regHist_i( std::move( graph ), id, false );
422 }
423 
424 StatusCode THistSvc::regGraph( const std::string& id, TGraph* graph_ptr ) {
425  std::unique_ptr<TGraph> graph( graph_ptr );
426  if ( strcmp( graph->GetName(), "Graph" ) == 0 ) {
427  std::string id2( id );
428  std::string::size_type i = id2.rfind( "/" );
429  if ( i != std::string::npos ) { id2.erase( 0, i + 1 ); }
430 
431  info() << "setting name of TGraph id: \"" << id << "\" to \"" << id2 << "\" since it is unset" << endmsg;
432  graph->SetName( id2.c_str() );
433  }
434 
435  return regHist_i( std::move( graph ), id, false );
436 }
437 
438 StatusCode THistSvc::getGraph( const std::string& id, TGraph*& graph ) const {
439  graph = getHist_i<TGraph>( id );
440  if ( graph != nullptr ) {
441  return StatusCode::SUCCESS;
442  } else {
443  return StatusCode::FAILURE;
444  }
445 }
446 
448  std::unique_ptr<TEfficiency> eff = nullptr;
449  return regHist_i( std::move( eff ), id, false );
450 }
451 
453  return regHist_i( std::move( eff ), id, false );
454 }
455 
456 StatusCode THistSvc::regEfficiency( const std::string& id, TEfficiency* eff_ptr ) {
457  std::unique_ptr<TEfficiency> eff( eff_ptr );
458  return regHist_i( std::move( eff ), id, false );
459 }
460 
461 StatusCode THistSvc::getEfficiency( const std::string& id, TEfficiency*& eff ) const {
462  eff = getHist_i<TEfficiency>( id );
463  if ( eff != nullptr ) {
464  return StatusCode::SUCCESS;
465  } else {
466  return StatusCode::FAILURE;
467  }
468 }
469 
471  lh = regShared_i<TH1>( id, std::move( hist ) );
472  if ( lh ) {
473  return StatusCode::SUCCESS;
474  } else {
475  return StatusCode::FAILURE;
476  }
477 }
478 
480  lh = regShared_i<TH2>( id, std::move( hist ) );
481  if ( lh ) {
482  return StatusCode::SUCCESS;
483  } else {
484  return StatusCode::FAILURE;
485  }
486 }
487 
489  lh = regShared_i<TH3>( id, std::move( hist ) );
490  if ( lh ) {
491  return StatusCode::SUCCESS;
492  } else {
493  return StatusCode::FAILURE;
494  }
495 }
496 
498  lh = regShared_i<TGraph>( id, std::move( graph ) );
499  if ( lh ) {
500  return StatusCode::SUCCESS;
501  } else {
502  return StatusCode::FAILURE;
503  }
504 }
505 
508  lh = regShared_i<TEfficiency>( id, std::move( eff ) );
509  if ( lh ) {
510  return StatusCode::SUCCESS;
511  } else {
512  return StatusCode::FAILURE;
513  }
514 }
515 
517  lh = getShared_i<TH1>( name );
518  if ( lh ) {
519  return StatusCode::SUCCESS;
520  } else {
521  return StatusCode::FAILURE;
522  }
523 }
524 
526  lh = getShared_i<TH2>( name );
527  if ( lh ) {
528  return StatusCode::SUCCESS;
529  } else {
530  return StatusCode::FAILURE;
531  }
532 }
533 
535  lh = getShared_i<TH3>( name );
536  if ( lh ) {
537  return StatusCode::SUCCESS;
538  } else {
539  return StatusCode::FAILURE;
540  }
541 }
542 
544  lh = getShared_i<TGraph>( name );
545  if ( lh ) {
546  return StatusCode::SUCCESS;
547  } else {
548  return StatusCode::FAILURE;
549  }
550 }
551 
553  lh = getShared_i<TEfficiency>( name );
554  if ( lh ) {
555  return StatusCode::SUCCESS;
556  } else {
557  return StatusCode::FAILURE;
558  }
559 }
560 
562  auto itr = m_uids.find( id );
563  if ( itr == m_uids.end() ) {
564  error() << "Problem deregistering id \"" << id << "\": not found in registry" << endmsg;
565  return StatusCode::FAILURE;
566  }
567 
568  vhid_t* vh = itr->second;
569 
570  if ( msgLevel( MSG::DEBUG ) ) {
571  debug() << "will deregister " << vh->size() << " elements of id \"" << id << "\"" << endmsg;
572  }
574  // vh will get deleted in deReg once empty, so we cannot query the list size in the loop
575  size_t vh_size = vh->size();
576  while ( vh_size-- ) {
577  if ( deReg( vh->back().obj ).isFailure() ) {
578  sc = StatusCode::FAILURE;
579  error() << "Problems deRegistering " << vh->size() << " element of id \"" << id << "\"" << endmsg;
580  break;
581  }
582  }
583 
584  return sc;
585 }
586 
587 StatusCode THistSvc::deReg( TObject* obj ) {
588  objMap_t::iterator obj_itr = m_tobjs.find( obj );
589  if ( obj_itr != m_tobjs.end() ) {
590  vhid_t* vhid = obj_itr->second.first;
591  THistID hid = obj_itr->second.first->at( obj_itr->second.second );
592 
593  auto uid_itr = m_uids.find( hid.id );
594  if ( uid_itr == m_uids.end() ) {
595  error() << "Problems deregistering TObject \"" << obj->GetName() << "\" with id \"" << hid.id
596  << "\": not in uidMap" << endmsg;
597  return StatusCode::FAILURE;
598  }
599 
600  if ( vhid->size() == 1 ) {
601  // We are the last object, so we have to delete vhid properly
602  if ( msgLevel( MSG::DEBUG ) ) { debug() << "vhid for " << hid.id << " is empty. deleting" << endmsg; }
603 
604  std::string root, rem;
605  parseString( hid.id, root, rem );
606 
607  auto mitr = m_ids.equal_range( rem );
608  auto id_itr = std::find_if( mitr.first, mitr.second,
609  [&]( idMap_t::const_reference i ) { return i.second->at( 0 ).obj == obj; } );
610  if ( id_itr == mitr.second ) {
611  error() << "Problems deregistering TObject \"" << obj->GetName() << "\" with id \"" << hid.id
612  << "\": not in idMap" << endmsg;
613  return StatusCode::FAILURE;
614  }
615 
616  auto hlist_itr = std::find( m_hlist.begin(), m_hlist.end(), vhid );
617  if ( hlist_itr == m_hlist.end() ) {
618  error() << "Problems deregistering TObject \"" << obj->GetName() << "\" with id \"" << hid.id
619  << "\": not in hlist" << endmsg;
620  return StatusCode::FAILURE;
621  }
622 
623  vhid->erase( vhid->begin() + obj_itr->second.second );
624  m_tobjs.erase( obj_itr );
625 
626  m_uids.erase( uid_itr );
627  m_ids.erase( id_itr );
628  m_hlist.erase( hlist_itr );
629 
630  delete vhid;
631 
632  } else if ( vhid->size() > 1 ) {
633  vhid->erase( vhid->begin() + obj_itr->second.second );
634  m_tobjs.erase( obj_itr );
635 
636  // vector of THistID is still not empty (i.e. other instances with same name registered)
637  } else {
638  error() << "Deregistration failed unexpectedly. (bug in THistSvc?)" << endmsg;
639  }
640  return StatusCode::SUCCESS;
641  } else {
642  error() << "Cannot unregister TObject \"" << obj->GetName() << "\": not known to THistSvc" << endmsg;
643  return StatusCode::FAILURE;
644  }
645 }
646 
648  uidMap_t::iterator itr = m_uids.find( name );
649  if ( itr == m_uids.end() ) {
650  error() << "merge: id \"" << name << "\" not found" << endmsg;
651  return StatusCode::FAILURE;
652  }
653 
654  return merge( itr->second );
655 }
656 
657 StatusCode THistSvc::merge( TObject* obj ) {
658  objMap_t::iterator itr = m_tobjs.find( obj );
659  if ( itr != m_tobjs.end() ) {
660  return merge( itr->second.first );
661  } else {
662  error() << "merge: unknown object " << obj << endmsg;
663  return StatusCode::FAILURE;
664  }
665 }
666 
667 bool THistSvc::exists( const std::string& name ) const { return existsHist( name ); }
668 
669 bool THistSvc::existsHist( const std::string& name ) const { return ( getHist_i<TH1>( name, 0, true ) != nullptr ); }
670 
672  return ( getHist_i<TEfficiency>( name, 0, true ) != nullptr );
673 }
674 
675 bool THistSvc::existsGraph( const std::string& name ) const {
676  return ( getHist_i<TGraph>( name, 0, true ) != nullptr );
677 }
678 
679 bool THistSvc::existsTree( const std::string& name ) const { return ( getHist_i<TTree>( name, 0, true ) != nullptr ); }
680 
683  names.reserve( m_uids.size() );
684  transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st,
685  []( uidMap_t::const_reference i ) { return i.second->at( 0 ).type == ObjectType::TH1; } );
686  return names;
687 }
688 
691  names.reserve( m_uids.size() );
692  transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st,
693  []( uidMap_t::const_reference i ) { return i.second->at( 0 ).type == ObjectType::TTREE; } );
694  return names;
695 }
696 
699  names.reserve( m_uids.size() );
700  transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st,
701  []( uidMap_t::const_reference i ) { return i.second->at( 0 ).type == ObjectType::TGRAPH; } );
702  return names;
703 }
704 
707  names.reserve( m_uids.size() );
708  transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st,
709  []( uidMap_t::const_reference i ) { return i.second->at( 0 ).type == ObjectType::TEFFICIENCY; } );
710  return names;
711 }
712 
713 StatusCode THistSvc::getTHists( TDirectory* td, TList& tl, bool rcs ) const {
714  GlobalDirectoryRestore restore( m_svcMut );
715 
716  gErrorIgnoreLevel = kBreak;
717 
718  if ( !td->cd() ) {
719  error() << "getTHists: No such TDirectory \"" << td->GetPath() << "\"" << endmsg;
720  return StatusCode::FAILURE;
721  }
722 
723  if ( msgLevel( MSG::DEBUG ) ) {
724  debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
725  }
726 
727  TIter nextkey( td->GetListOfKeys() );
728  while ( TKey* key = (TKey*)nextkey() ) {
729  auto& log = debug();
730  if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName();
731  TObject* obj = key->ReadObj();
732  if ( obj != 0 && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
733  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
734  } else if ( obj != 0 && obj->IsA()->InheritsFrom( "TH1" ) ) {
735  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
736  tl.Add( obj );
737  } else if ( obj != 0 ) {
738  if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]";
739  }
740  if ( msgLevel( MSG::DEBUG ) ) log << endmsg;
741  }
742 
743  // operate recursively
744  if ( rcs ) {
745  nextkey = td->GetListOfKeys();
746  while ( TKey* key = (TKey*)nextkey() ) {
747  TObject* obj = key->ReadObj();
748  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
749  TDirectory* tt = dynamic_cast<TDirectory*>( obj );
750  getTHists( tt, tl, rcs ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
751  }
752  }
753  }
754 
755  return StatusCode::SUCCESS;
756 }
757 
758 StatusCode THistSvc::getTHists( const std::string& dir, TList& tl, bool rcs ) const {
759 
760  GlobalDirectoryRestore restore( m_svcMut );
761 
762  gErrorIgnoreLevel = kBreak;
763 
764  StatusCode sc;
765 
766  std::string stream, rem, r2;
767  parseString( dir, stream, rem );
768 
769  auto itr = m_files.find( stream );
770  if ( itr != m_files.end() ) {
771  r2 = itr->second.first->GetName();
772  r2 += ":/";
773  r2 += rem;
774 
775  if ( msgLevel( MSG::DEBUG ) ) {
776  debug() << "getTHists: \"" << dir << "\" looks like a stream name."
777  << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg;
778  }
779 
780  if ( gDirectory->cd( r2.c_str() ) ) {
782  sc = getTHists( gDirectory, tl, rcs );
783  m_curstream = "";
784  return sc;
785  } else {
786  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTHists: no such TDirectory \"" << r2 << "\"" << endmsg; }
787  }
788 
789  } else {
790  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTHists: stream \"" << stream << "\" not found" << endmsg; }
791  }
792 
793  if ( !gDirectory->cd( dir.c_str() ) ) {
794  error() << "getTHists: No such TDirectory/stream \"" << dir << "\"" << endmsg;
795  sc = StatusCode::FAILURE;
796  } else {
797  sc = getTHists( gDirectory, tl, rcs );
798  }
799 
800  return sc;
801 }
802 
803 StatusCode THistSvc::getTHists( TDirectory* td, TList& tl, bool rcs, bool reg ) {
804  GlobalDirectoryRestore restore( m_svcMut );
805 
806  gErrorIgnoreLevel = kBreak;
807 
808  if ( !td->cd() ) {
809  error() << "getTHists: No such TDirectory \"" << td->GetPath() << "\"" << endmsg;
810  return StatusCode::FAILURE;
811  }
812 
813  if ( msgLevel( MSG::DEBUG ) ) {
814  debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
815  }
816 
817  TIter nextkey( td->GetListOfKeys() );
818  while ( TKey* key = (TKey*)nextkey() ) {
819  auto& log = debug();
820  if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName();
821  TObject* obj = key->ReadObj();
822  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
823  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
824  } else if ( obj && obj->IsA()->InheritsFrom( "TH1" ) ) {
825  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
826  tl.Add( obj );
827  if ( reg && m_curstream != "" ) {
828  std::string dir = td->GetPath();
829  std::string fil = td->GetFile()->GetName();
830  dir.erase( 0, fil.length() + 1 );
831  std::string id = "/" + m_curstream;
832  if ( dir == "/" ) {
833  id = id + "/" + key->GetName();
834  } else {
835  id = id + dir + "/" + key->GetName();
836  }
837  if ( !exists( id ) ) {
838  if ( msgLevel( MSG::DEBUG ) ) log << " reg as \"" << id << "\"";
839  regHist( id ).ignore();
840  } else {
841  if ( msgLevel( MSG::DEBUG ) ) log << " already registered";
842  }
843  }
844  } else if ( obj ) {
845  if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]";
846  }
847  if ( msgLevel( MSG::DEBUG ) ) log << endmsg;
848  }
849 
850  // operate recursively
851  if ( rcs ) {
852  nextkey = td->GetListOfKeys();
853  while ( TKey* key = (TKey*)nextkey() ) {
854  TObject* obj = key->ReadObj();
855  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
856  TDirectory* tt = dynamic_cast<TDirectory*>( obj );
857  getTHists( tt, tl, rcs, reg ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
858  }
859  }
860  }
861 
862  return StatusCode::SUCCESS;
863 }
864 
865 StatusCode THistSvc::getTHists( const std::string& dir, TList& tl, bool rcs, bool reg ) {
866  GlobalDirectoryRestore restore( m_svcMut );
867 
868  gErrorIgnoreLevel = kBreak;
869 
870  StatusCode sc;
871 
872  std::string stream, rem, r2;
873  parseString( dir, stream, rem );
874 
875  auto itr = m_files.find( stream );
876  if ( itr != m_files.end() ) {
877  r2 = itr->second.first->GetName();
878  r2 += ":/";
879  r2 += rem;
880 
881  if ( msgLevel( MSG::DEBUG ) ) {
882  debug() << "getTHists: \"" << dir << "\" looks like a stream name."
883  << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg;
884  }
885 
886  if ( gDirectory->cd( r2.c_str() ) ) {
888  sc = getTHists( gDirectory, tl, rcs, reg );
889  m_curstream.clear();
890  return sc;
891  }
892  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTHists: no such TDirectory \"" << r2 << "\"" << endmsg; }
893  } else {
894  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTHists: stream \"" << stream << "\" not found" << endmsg; }
895  }
896 
897  if ( !gDirectory->cd( dir.c_str() ) ) {
898  error() << "getTHists: No such TDirectory/stream \"" << dir << "\"" << endmsg;
899  sc = StatusCode::FAILURE;
900  } else {
901  if ( reg ) {
902  warning() << "Unable to register histograms automatically "
903  << "without a valid stream name" << endmsg;
904  reg = false;
905  }
906  sc = getTHists( gDirectory, tl, rcs, reg );
907  }
908 
909  return sc;
910 }
911 
912 StatusCode THistSvc::getTTrees( TDirectory* td, TList& tl, bool rcs ) const {
913  GlobalDirectoryRestore restore( m_svcMut );
914 
915  gErrorIgnoreLevel = kBreak;
916 
917  if ( !td->cd() ) {
918  error() << "getTTrees: No such TDirectory \"" << td->GetPath() << "\"" << endmsg;
919  return StatusCode::FAILURE;
920  }
921 
922  if ( msgLevel( MSG::DEBUG ) ) {
923  debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
924  }
925 
926  TIter nextkey( td->GetListOfKeys() );
927  while ( TKey* key = (TKey*)nextkey() ) {
928  auto& log = debug();
929  if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName();
930  TObject* obj = key->ReadObj();
931  if ( obj != 0 && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
932  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
933  } else if ( obj != 0 && obj->IsA()->InheritsFrom( "TTree" ) ) {
934  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
935  tl.Add( obj );
936  } else if ( obj != 0 ) {
937  if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]";
938  }
939  log << endmsg;
940  }
941 
942  // operate recursively
943  if ( rcs ) {
944  nextkey = td->GetListOfKeys();
945  while ( TKey* key = (TKey*)nextkey() ) {
946  TObject* obj = key->ReadObj();
947  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
948  TDirectory* tt = dynamic_cast<TDirectory*>( obj );
949  getTTrees( tt, tl, rcs ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
950  }
951  }
952  }
953 
954  return StatusCode::SUCCESS;
955 }
956 
957 StatusCode THistSvc::getTTrees( const std::string& dir, TList& tl, bool rcs ) const {
958  GlobalDirectoryRestore restore( m_svcMut );
959 
960  gErrorIgnoreLevel = kBreak;
961 
962  StatusCode sc;
963 
964  std::string stream, rem, r2;
965  parseString( dir, stream, rem );
966 
967  auto itr = m_files.find( stream );
968  if ( itr != m_files.end() ) {
969  r2 = itr->second.first->GetName();
970  r2 += ":/";
971  r2 += rem;
972 
973  if ( msgLevel( MSG::DEBUG ) ) {
974  debug() << "getTTrees: \"" << dir << "\" looks like a stream name."
975  << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg;
976  }
977 
978  if ( gDirectory->cd( r2.c_str() ) ) { return getTTrees( gDirectory, tl, rcs ); }
979  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTTrees: no such TDirectory \"" << r2 << "\"" << endmsg; }
980  } else {
981  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTTrees: stream \"" << stream << "\" not found" << endmsg; }
982  }
983 
984  if ( !gDirectory->cd( dir.c_str() ) ) {
985  error() << "getTTrees: No such TDirectory/stream \"" << dir << "\"" << endmsg;
986  sc = StatusCode::FAILURE;
987  } else {
988  sc = getTTrees( gDirectory, tl, rcs );
989  }
990  return sc;
991 }
992 
993 StatusCode THistSvc::getTTrees( TDirectory* td, TList& tl, bool rcs, bool reg ) {
994  GlobalDirectoryRestore restore( m_svcMut );
995 
996  gErrorIgnoreLevel = kBreak;
997 
998  if ( !td->cd() ) {
999  error() << "getTTrees: No such TDirectory \"" << td->GetPath() << "\"" << endmsg;
1000  return StatusCode::FAILURE;
1001  }
1002 
1003  if ( msgLevel( MSG::DEBUG ) ) {
1004  debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
1005  }
1006 
1007  TIter nextkey( td->GetListOfKeys() );
1008  while ( TKey* key = (TKey*)nextkey() ) {
1009  auto& log = debug();
1010  if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName();
1011  TObject* obj = key->ReadObj();
1012  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1013  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
1014  } else if ( obj && obj->IsA()->InheritsFrom( "TTree" ) ) {
1015  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
1016  tl.Add( obj );
1017  if ( reg && m_curstream != "" ) {
1018  std::string dir = td->GetPath();
1019  std::string fil = td->GetFile()->GetName();
1020  dir.erase( 0, fil.length() + 1 );
1021  std::string id = "/" + m_curstream;
1022  if ( dir == "/" ) {
1023  id = id + "/" + key->GetName();
1024  } else {
1025  id = id + dir + "/" + key->GetName();
1026  }
1027  if ( !exists( id ) ) {
1028  if ( msgLevel( MSG::DEBUG ) ) log << " reg as \"" << id << "\"";
1029  regHist( id ).ignore();
1030  } else {
1031  if ( msgLevel( MSG::DEBUG ) ) log << " already registered";
1032  }
1033  }
1034  } else if ( obj != 0 ) {
1035  if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]";
1036  }
1037  if ( msgLevel( MSG::DEBUG ) ) log << endmsg;
1038  }
1039 
1040  // operate recursively
1041  if ( rcs ) {
1042  nextkey = td->GetListOfKeys();
1043  while ( TKey* key = (TKey*)nextkey() ) {
1044  TObject* obj = key->ReadObj();
1045  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1046  TDirectory* tt = dynamic_cast<TDirectory*>( obj );
1047  getTTrees( tt, tl, rcs, reg ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
1048  }
1049  }
1050  }
1051 
1052  return StatusCode::SUCCESS;
1053 }
1054 
1055 StatusCode THistSvc::getTTrees( const std::string& dir, TList& tl, bool rcs, bool reg ) {
1056  GlobalDirectoryRestore restore( m_svcMut );
1057 
1058  gErrorIgnoreLevel = kBreak;
1059 
1060  StatusCode sc;
1061 
1062  std::string stream, rem, r2;
1063  parseString( dir, stream, rem );
1064 
1065  auto itr = m_files.find( stream );
1066  if ( itr != m_files.end() ) {
1067  r2 = itr->second.first->GetName();
1068  r2 += ":/";
1069  r2 += rem;
1070 
1071  if ( msgLevel( MSG::DEBUG ) ) {
1072  debug() << "getTTrees: \"" << dir << "\" looks like a stream name."
1073  << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg;
1074  }
1075 
1076  if ( gDirectory->cd( r2.c_str() ) ) {
1077  return getTTrees( gDirectory, tl, rcs, reg );
1078  } else {
1079  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTTrees: no such TDirectory \"" << r2 << "\"" << endmsg; }
1080  }
1081  } else {
1082  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTTrees: stream \"" << stream << "\" not found" << endmsg; }
1083  }
1084 
1085  if ( !gDirectory->cd( dir.c_str() ) ) {
1086  error() << "getTTrees: No such TDirectory/stream \"" << dir << "\"" << endmsg;
1087  return StatusCode::FAILURE;
1088  }
1089 
1090  return getTTrees( gDirectory, tl, rcs, reg );
1091 }
1092 
1093 StatusCode THistSvc::getTEfficiencies( TDirectory* td, TList& tl, bool rcs ) const {
1094  GlobalDirectoryRestore restore( m_svcMut );
1095 
1096  gErrorIgnoreLevel = kBreak;
1097 
1098  if ( !td->cd() ) {
1099  error() << "getTEfficiencies: No such TDirectory \"" << td->GetPath() << "\"" << endmsg;
1100  return StatusCode::FAILURE;
1101  }
1102 
1103  if ( msgLevel( MSG::DEBUG ) ) {
1104  debug() << "getTEfficiencies: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys"
1105  << endmsg;
1106  }
1107 
1108  TIter nextkey( td->GetListOfKeys() );
1109  while ( TKey* key = (TKey*)nextkey() ) {
1110  auto& log = debug();
1111  if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName();
1112  TObject* obj = key->ReadObj();
1113  if ( obj != 0 && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1114  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
1115  } else if ( obj != 0 && obj->IsA()->InheritsFrom( "TEfficiency" ) ) {
1116  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
1117  tl.Add( obj );
1118  } else if ( obj != 0 ) {
1119  if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]";
1120  }
1121  if ( msgLevel( MSG::DEBUG ) ) log << endmsg;
1122  }
1123 
1124  // operate recursively
1125  if ( rcs ) {
1126  nextkey = td->GetListOfKeys();
1127  while ( TKey* key = (TKey*)nextkey() ) {
1128  TObject* obj = key->ReadObj();
1129  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1130  TDirectory* tt = dynamic_cast<TDirectory*>( obj );
1131  getTHists( tt, tl, rcs ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
1132  }
1133  }
1134  }
1135 
1136  return StatusCode::SUCCESS;
1137 }
1138 
1139 StatusCode THistSvc::getTEfficiencies( const std::string& dir, TList& tl, bool rcs ) const {
1140 
1141  GlobalDirectoryRestore restore( m_svcMut );
1142 
1143  gErrorIgnoreLevel = kBreak;
1144 
1145  StatusCode sc;
1146 
1147  std::string stream, rem, r2;
1148  parseString( dir, stream, rem );
1149 
1150  auto itr = m_files.find( stream );
1151  if ( itr != m_files.end() ) {
1152  r2 = itr->second.first->GetName();
1153  r2 += ":/";
1154  r2 += rem;
1155 
1156  if ( msgLevel( MSG::DEBUG ) ) {
1157  debug() << "getTEfficiencies: \"" << dir << "\" looks like a stream name."
1158  << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg;
1159  }
1160 
1161  if ( gDirectory->cd( r2.c_str() ) ) {
1162  m_curstream = stream;
1163  sc = getTEfficiencies( gDirectory, tl, rcs );
1164  m_curstream = "";
1165  return sc;
1166  } else {
1167  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTEfficiencies: no such TDirectory \"" << r2 << "\"" << endmsg; }
1168  }
1169 
1170  } else {
1171  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTEfficiencies: stream \"" << stream << "\" not found" << endmsg; }
1172  }
1173 
1174  if ( !gDirectory->cd( dir.c_str() ) ) {
1175  error() << "getTEfficiencies: No such TDirectory/stream \"" << dir << "\"" << endmsg;
1176  sc = StatusCode::FAILURE;
1177  } else {
1178  sc = getTHists( gDirectory, tl, rcs );
1179  }
1180 
1181  return sc;
1182 }
1183 
1184 StatusCode THistSvc::getTEfficiencies( TDirectory* td, TList& tl, bool rcs, bool reg ) {
1185  GlobalDirectoryRestore restore( m_svcMut );
1186 
1187  gErrorIgnoreLevel = kBreak;
1188 
1189  if ( !td->cd() ) {
1190  error() << "getTEfficiencies: No such TDirectory \"" << td->GetPath() << "\"" << endmsg;
1191  return StatusCode::FAILURE;
1192  }
1193 
1194  if ( msgLevel( MSG::DEBUG ) ) {
1195  debug() << "getTEfficiencies: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys"
1196  << endmsg;
1197  }
1198 
1199  TIter nextkey( td->GetListOfKeys() );
1200  while ( TKey* key = (TKey*)nextkey() ) {
1201  auto& log = debug();
1202  if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName();
1203  TObject* obj = key->ReadObj();
1204  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1205  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
1206  } else if ( obj && obj->IsA()->InheritsFrom( "TEfficiency" ) ) {
1207  if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")";
1208  tl.Add( obj );
1209  if ( reg && m_curstream != "" ) {
1210  std::string dir = td->GetPath();
1211  std::string fil = td->GetFile()->GetName();
1212  dir.erase( 0, fil.length() + 1 );
1213  std::string id = "/" + m_curstream;
1214  if ( dir == "/" ) {
1215  id = id + "/" + key->GetName();
1216  } else {
1217  id = id + dir + "/" + key->GetName();
1218  }
1219  if ( !exists( id ) ) {
1220  if ( msgLevel( MSG::DEBUG ) ) log << " reg as \"" << id << "\"";
1221  regHist( id ).ignore();
1222  } else {
1223  if ( msgLevel( MSG::DEBUG ) ) log << " already registered";
1224  }
1225  }
1226  } else if ( obj ) {
1227  if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]";
1228  }
1229  if ( msgLevel( MSG::DEBUG ) ) log << endmsg;
1230  }
1231 
1232  // operate recursively
1233  if ( rcs ) {
1234  nextkey = td->GetListOfKeys();
1235  while ( TKey* key = (TKey*)nextkey() ) {
1236  TObject* obj = key->ReadObj();
1237  if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1238  TDirectory* tt = dynamic_cast<TDirectory*>( obj );
1239  getTEfficiencies( tt, tl, rcs, reg ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
1240  }
1241  }
1242  }
1243 
1244  return StatusCode::SUCCESS;
1245 }
1246 
1247 StatusCode THistSvc::getTEfficiencies( const std::string& dir, TList& tl, bool rcs, bool reg ) {
1248  GlobalDirectoryRestore restore( m_svcMut );
1249 
1250  gErrorIgnoreLevel = kBreak;
1251 
1252  StatusCode sc;
1253 
1254  std::string stream, rem, r2;
1255  parseString( dir, stream, rem );
1256 
1257  auto itr = m_files.find( stream );
1258  if ( itr != m_files.end() ) {
1259  r2 = itr->second.first->GetName();
1260  r2 += ":/";
1261  r2 += rem;
1262 
1263  if ( msgLevel( MSG::DEBUG ) ) {
1264  debug() << "getTEfficiencies: \"" << dir << "\" looks like a stream name."
1265  << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg;
1266  }
1267 
1268  if ( gDirectory->cd( r2.c_str() ) ) {
1269  m_curstream = stream;
1270  sc = getTEfficiencies( gDirectory, tl, rcs, reg );
1271  m_curstream.clear();
1272  return sc;
1273  }
1274  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTEfficiencies: no such TDirectory \"" << r2 << "\"" << endmsg; }
1275  } else {
1276  if ( msgLevel( MSG::DEBUG ) ) { debug() << "getTEfficiencies: stream \"" << stream << "\" not found" << endmsg; }
1277  }
1278 
1279  if ( !gDirectory->cd( dir.c_str() ) ) {
1280  error() << "getTEfficiencies: No such TDirectory/stream \"" << dir << "\"" << endmsg;
1281  sc = StatusCode::FAILURE;
1282  } else {
1283  if ( reg ) {
1284  warning() << "Unable to register histograms automatically "
1285  << "without a valid stream name" << endmsg;
1286  reg = false;
1287  }
1288  sc = getTEfficiencies( gDirectory, tl, rcs, reg );
1289  }
1290 
1291  return sc;
1292 }
1293 
1294 //*************************************************************************//
1295 
1296 void THistSvc::handle( const Incident& /* inc */ ) {
1297 
1298  if ( m_maxFileSize.value() == -1 ) return;
1299 
1300  // convert to bytes.
1301  Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
1302  Long64_t mfs_warn = mfs * 95 / 100;
1303 
1304  updateFiles();
1305 
1306  for ( const auto& f : m_files ) {
1307  TFile* tf = f.second.first;
1308 
1309 #ifndef NDEBUG
1310  if ( msgLevel( MSG::DEBUG ) ) {
1311  debug() << "stream: " << f.first << " name: " << tf->GetName() << " size: " << tf->GetSize() << endmsg;
1312  }
1313 #endif
1314 
1315  // Terminate job if output file is too large
1316  if ( tf->GetSize() > mfs ) {
1317 
1318  if ( writeObjectsToFile().isFailure() ) { error() << "problems writing histograms" << endmsg; }
1319  throw GaudiException( fmt::format( "file \"{}\" associated with stream \"{}\" has exceeded the max "
1320  "file size of {} MB. Terminating Job.",
1321  tf->GetName(), f.first, m_maxFileSize.value() ),
1323 
1324  } else if ( tf->GetSize() > mfs_warn ) {
1325  warning() << "file \"" << tf->GetName() << "\" associated with stream \"" << f.first
1326  << "\" is at 95% of its maximum allowable file size of " << m_maxFileSize.value() << "MB" << endmsg;
1327  }
1328  }
1329 }
1330 
1335  bool all_good = true;
1336  if ( msgLevel( MSG::DEBUG ) ) { debug() << "reinitializing I/O..." << endmsg; }
1337 
1338  // retrieve the I/O component manager...
1339 
1340  auto iomgr = service<IIoComponentMgr>( "IoComponentMgr", true );
1341  if ( !iomgr ) {
1342  error() << "could not retrieve I/O component manager !" << endmsg;
1343  return StatusCode::FAILURE;
1344  }
1345 
1346  GlobalDirectoryRestore restore( m_svcMut );
1347  // to hide the expected errors upon closing the files whose
1348  // file descriptors have been swept under the rug...
1349  gErrorIgnoreLevel = kFatal;
1350 
1351  for ( auto& ifile : m_files ) {
1352  TFile* f = ifile.second.first;
1353  std::string fname = f->GetName();
1354  if ( msgLevel( MSG::DEBUG ) ) {
1355  debug() << "file [" << fname << "] mode: [" << f->GetOption() << "] r:" << f->GetFileBytesRead()
1356  << " w:" << f->GetFileBytesWritten() << " cnt:" << f->GetFileCounter() << endmsg;
1357  }
1358 
1359  if ( ifile.second.second == READ ) {
1360  if ( msgLevel( MSG::DEBUG ) ) { debug() << " TFile opened in READ mode: not reassigning names" << endmsg; }
1361  continue;
1362  }
1363 
1364  if ( !iomgr->io_retrieve( this, fname ).isSuccess() ) {
1365  error() << "could not retrieve new name for [" << fname << "] !!" << endmsg;
1366  all_good = false;
1367  continue;
1368  } else if ( fname.empty() ) {
1369  if ( msgLevel( MSG::DEBUG ) ) { debug() << "empty new name for [" << fname << "], skipping..." << endmsg; }
1370  continue;
1371  } else {
1372  if ( msgLevel( MSG::DEBUG ) ) { debug() << "got a new name [" << fname << "]..." << endmsg; }
1373  }
1374 
1375  void* vf = nullptr;
1376  Option_t* opts = f->GetOption();
1377  int r = p_fileMgr->open( Io::ROOT, name(), fname, Io::WRITE, vf, "HIST" );
1378  if ( r != 0 ) {
1379  error() << "unable to open file \"" << fname << "\" for writing" << endmsg;
1380  return StatusCode::FAILURE;
1381  }
1382  TFile* newfile = (TFile*)vf;
1383  newfile->SetOption( opts );
1384 
1385  if ( ifile.second.second != THistSvc::READ ) {
1386  copyFileLayout( newfile, f );
1387  ifile.second.first = newfile;
1388  }
1389 
1390  // loop over all uids and migrate them to the new file
1391  for ( auto& uid : m_uids ) {
1392  for ( auto& hid : *uid.second ) {
1393  if ( hid.file != f ) continue;
1394  TDirectory* olddir = this->changeDir( hid );
1395  hid.file = newfile;
1396  // side-effect: create needed directories...
1397  TDirectory* newdir = this->changeDir( hid );
1398  TClass* cl = hid.obj->IsA();
1399 
1400  // migrate the objects to the new file.
1401  // thanks to the object model of ROOT, it is super easy.
1402  if ( hid.type == ObjectType::TTREE ) {
1403  TTree& tree = dynamic_cast<TTree&>( *hid.obj );
1404  tree.SetDirectory( newdir );
1405  tree.Reset();
1406  } else if ( hid.type == ObjectType::TH1 ) {
1407  TH1& hist = dynamic_cast<TH1&>( *hid.obj );
1408  hist.SetDirectory( newdir );
1409  hist.Reset();
1410  } else if ( hid.type == ObjectType::TEFFICIENCY ) {
1411  dynamic_cast<TEfficiency&>( *hid.obj ).SetDirectory( newdir );
1412  } else if ( hid.type == ObjectType::TGRAPH ) {
1413  olddir->Remove( hid.obj );
1414  newdir->Append( hid.obj );
1415  } else {
1416  error() << "id: \"" << hid.id << "\" is not a inheriting from a class "
1417  << "we know how to handle (received [" << cl->GetName() << "], "
1418  << "expected [TTree, TH1, TGraph or TEfficiency]) !" << endmsg << "attaching to current dir ["
1419  << newdir->GetPath() << "] "
1420  << "nonetheless..." << endmsg;
1421  olddir->Remove( hid.obj );
1422  newdir->Append( hid.obj );
1423  }
1424  }
1425  }
1426  f->ReOpen( "READ" );
1427  p_fileMgr->close( f, name() );
1428  f = newfile;
1429  }
1430 
1431  return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE;
1432 }
1433 
1434 //*************************************************************************//
1435 
1437  m_gDirectory = gDirectory;
1438  m_gFile = gFile;
1439  m_gErrorIgnoreLevel = gErrorIgnoreLevel;
1440 }
1441 
1443  gDirectory = m_gDirectory;
1444  gFile = m_gFile;
1445  gErrorIgnoreLevel = m_gErrorIgnoreLevel;
1446 }
1447 
1448 //*************************************************************************//
1449 
1450 template <typename T>
1451 T* THistSvc::readHist( const std::string& id ) const {
1452  return dynamic_cast<T*>( readHist_i<T>( id ) );
1453 }
1454 
1455 TTree* THistSvc::readTree( const std::string& id ) const { return dynamic_cast<TTree*>( readHist_i<TTree>( id ) ); }
1456 
1458 
1459  if ( !m_hasTTrees ) return;
1460 
1461  // If TTrees grow beyond TTree::fgMaxTreeSize, a new file is
1462  // automatically created by root, and the old one closed. We
1463  // need to migrate all the UIDs over to show the correct file
1464  // pointer. This is ugly.
1465 
1466  for ( auto uitr = m_uids.begin(); uitr != m_uids.end(); ++uitr ) {
1467  for ( auto& hid : *( uitr->second ) ) {
1468 
1469  // Only relevant for TTrees and if not in read mode
1470  if ( hid.type != ObjectType::TTREE || hid.temp || hid.mode == READ || hid.obj == nullptr ) continue;
1471 
1472  if ( msgLevel( MSG::VERBOSE ) )
1473  verbose() << " update: " << uitr->first << " " << hid.id << " " << hid.mode << endmsg;
1474 
1475  TTree* tr = dynamic_cast<TTree*>( hid.obj );
1476  TFile* oldFile = hid.file;
1477  TFile* newFile = tr->GetCurrentFile();
1478 
1479  if ( oldFile != newFile ) {
1480  std::string newFileName = newFile->GetName();
1481  std::string oldFileName, streamName, rem;
1482  TFile* dummy = nullptr;
1483  findStream( hid.id, streamName, rem, dummy );
1484 
1485  for ( auto& itr : m_files ) {
1486  if ( itr.second.first == oldFile ) { itr.second.first = newFile; }
1487  }
1488 
1489  for ( auto uitr2 = uitr; uitr2 != m_uids.end(); ++uitr2 ) {
1490  for ( auto& hid2 : *( uitr2->second ) ) {
1491  if ( hid2.file == oldFile ) { hid2.file = newFile; }
1492  }
1493  }
1494 
1496  [&]( streamMap::const_reference s ) { return s.second == streamName; } );
1497  if ( sitr != std::end( m_fileStreams ) ) oldFileName = sitr->first;
1498 
1499 #ifndef NDEBUG
1500  if ( msgLevel( MSG::DEBUG ) ) {
1501  debug() << "migrating uid: " << hid.id << " stream: " << streamName << " oldFile: " << oldFileName
1502  << " newFile: " << newFileName << endmsg;
1503  }
1504 #endif
1505 
1506  if ( !oldFileName.empty() ) {
1507  auto i = m_fileStreams.lower_bound( oldFileName );
1508  while ( i != std::end( m_fileStreams ) && i->first == oldFileName ) {
1509 #ifndef NDEBUG
1510  if ( msgLevel( MSG::DEBUG ) ) {
1511  debug() << "changing filename \"" << i->first << "\" to \"" << newFileName << "\" for stream \""
1512  << i->second << "\"" << endmsg;
1513  }
1514 #endif
1515  std::string nm = std::move( i->second );
1516  i = m_fileStreams.erase( i );
1517  m_fileStreams.emplace( newFileName, std::move( nm ) );
1518  }
1519  } else {
1520  error() << "Problems updating fileStreams with new file name" << endmsg;
1521  }
1522  }
1523  }
1524  }
1525 }
1526 
1528  updateFiles();
1529 
1531  auto mode = i.second.second;
1532  auto file = i.second.first;
1533  if ( mode == WRITE || mode == UPDATE || mode == SHARE ) {
1534  file->Write( "", TObject::kOverwrite );
1535  } else if ( mode == APPEND ) {
1536  file->Write( "" );
1537  }
1538  } );
1539 
1540  if ( msgLevel( MSG::DEBUG ) ) {
1541  debug() << "THistSvc::writeObjectsToFile()::List of Files connected in ROOT " << endmsg;
1542  TSeqCollection* filelist = gROOT->GetListOfFiles();
1543  for ( int ii = 0; ii < filelist->GetEntries(); ii++ ) {
1544  debug() << "THistSvc::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName()
1545  << "\"" << endmsg;
1546  }
1547  }
1548 
1549  return StatusCode::SUCCESS;
1550 }
1551 
1553  auto loc = ident.find( " " );
1554  std::string stream = ident.substr( 0, loc );
1555  char typ( 0 );
1558  std::string filename, db_typ( "ROOT" );
1559  int cl( 1 );
1560 
1561  if ( loc != std::string::npos ) {
1562  using Parser = Gaudi::Utils::AttribStringParser;
1563  for ( auto attrib : Parser( ident.substr( loc + 1 ) ) ) {
1564  // Don't use to_upper_copy in order to avoid gcc 13.1 bug
1565  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109703
1566  // (Should be fixed in 13.2.)
1567  auto TAG = attrib.tag;
1568  auto VAL = attrib.value;
1569  boost::algorithm::to_upper( TAG );
1570  boost::algorithm::to_upper( VAL );
1571 
1572  if ( TAG == "FILE" || TAG == "DATAFILE" ) {
1573  filename = attrib.value;
1575  } else if ( TAG == "OPT" ) {
1576  if ( VAL == "APPEND" || VAL == "UPDATE" ) {
1577  typ = 'A';
1578  } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
1579  typ = 'N';
1580  } else if ( VAL == "RECREATE" ) {
1581  typ = 'R';
1582  } else if ( VAL == "SHARE" ) {
1583  typ = 'S';
1584  } else if ( VAL == "OLD" || VAL == "READ" ) {
1585  typ = 'O';
1586  } else {
1587  error() << "Unknown OPT: \"" << attrib.value << "\"" << endmsg;
1588  typ = 0;
1589  }
1590  } else if ( TAG == "TYP" ) {
1591  db_typ = std::move( attrib.value );
1592  } else if ( TAG == "CL" ) {
1593  cl = std::stoi( attrib.value );
1594  } else {
1595  props.emplace_back( attrib.tag, attrib.value );
1596  }
1597  }
1598  }
1599 
1600  if ( stream == "temp" ) {
1601  error() << "in JobOption \"" << ident << "\": stream name \"temp\" reserved." << endmsg;
1602  return StatusCode::FAILURE;
1603  }
1604 
1605  if ( db_typ != "ROOT" ) {
1606  error() << "in JobOption \"" << ident << "\": technology type \"" << db_typ << "\" not supported." << endmsg;
1607  return StatusCode::FAILURE;
1608  }
1609 
1610  if ( m_files.find( stream ) != m_files.end() ) {
1611  error() << "in JobOption \"" << ident << "\":\n stream \"" << stream << "\" already connected to file: \""
1612  << m_files[stream].first->GetName() << "\"" << endmsg;
1613  return StatusCode::FAILURE;
1614  }
1615 
1616  const auto newMode = charToMode( typ );
1617  if ( newMode == THistSvc::INVALID ) {
1618  error() << "No OPT= specified or unknown access mode in: " << ident << endmsg;
1619  return StatusCode::FAILURE;
1620  }
1621 
1622  // Is this file already connected to another stream?
1623  if ( m_fileStreams.find( filename ) != m_fileStreams.end() ) {
1624  auto fitr = m_fileStreams.equal_range( filename );
1625 
1626  const std::string& oldstream = fitr.first->second;
1627 
1628  const auto& f_info = m_files[oldstream];
1629 
1630  if ( newMode != f_info.second ) {
1631  error() << "in JobOption \"" << ident << "\":\n file \"" << filename << "\" already opened by stream: \""
1632  << oldstream << "\" with different access mode." << endmsg;
1633  return StatusCode::FAILURE;
1634  } else {
1635  TFile* f2 = f_info.first;
1636  m_files[stream] = std::make_pair( f2, newMode );
1637  if ( msgLevel( MSG::DEBUG ) )
1638  debug() << "Connecting stream: \"" << stream << "\" to previously opened TFile: \"" << filename << "\""
1639  << endmsg;
1640  return StatusCode::SUCCESS;
1641  }
1642  }
1643 
1644  void* vf = nullptr;
1645  TFile* f = nullptr;
1646 
1647  if ( newMode == THistSvc::READ ) {
1648  // old file
1649  int r = p_fileMgr->open( Io::ROOT, name(), filename, Io::READ, vf, "HIST" );
1650 
1651  if ( r != 0 ) {
1652  error() << "Unable to open ROOT file " << filename << " for reading" << endmsg;
1653  return StatusCode::FAILURE;
1654  }
1655 
1656  f = (TFile*)vf;
1657 
1658  // FIX ME!
1659  p_incSvc->fireIncident( FileIncident( name(), "BeginHistFile", filename ) );
1660 
1661  } else if ( newMode == THistSvc::WRITE ) {
1662  // new file. error if file exists
1663  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE | Io::EXCL ), vf, "HIST" );
1664 
1665  if ( r != 0 ) {
1666  error() << "Unable to open ROOT file " << filename << " for writing" << endmsg;
1667  return StatusCode::FAILURE;
1668  }
1669 
1670  f = (TFile*)vf;
1671 
1672  } else if ( newMode == THistSvc::APPEND ) {
1673  // update file
1674  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::APPEND ), vf, "HIST" );
1675  if ( r != 0 ) {
1676  error() << "unable to open file \"" << filename << "\" for appending" << endmsg;
1677  return StatusCode::FAILURE;
1678  }
1679 
1680  f = (TFile*)vf;
1681 
1682  } else if ( newMode == THistSvc::SHARE ) {
1683  // SHARE file type
1684  // For SHARE files, all data will be stored in a temp file and will be
1685  // merged into the target file in writeObjectsToFile() when finalize(),
1686  // this help to solve some confliction. e.g. with storegate
1687  static int ishared = 0;
1688  std::string realfilename = filename;
1689  filename = "tmp_THistSvc_" + std::to_string( ishared++ ) + ".root";
1690 
1691  if ( msgLevel( MSG::DEBUG ) ) {
1692  debug() << "Creating temp file \"" << filename << "\" and realfilename=" << realfilename << endmsg;
1693  }
1694  m_sharedFiles[stream] = realfilename;
1695 
1696  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE | Io::EXCL ), vf, "HIST" );
1697 
1698  if ( r != 0 ) {
1699  error() << "Unable to open ROOT file " << filename << " for writing" << endmsg;
1700  return StatusCode::FAILURE;
1701  }
1702 
1703  f = (TFile*)vf;
1704 
1705  } else if ( newMode == THistSvc::UPDATE ) {
1706  // update file
1707  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE ), vf, "HIST" );
1708 
1709  if ( r != 0 ) {
1710  error() << "Unable to open ROOT file " << filename << " for appending" << endmsg;
1711  return StatusCode::FAILURE;
1712  }
1713 
1714  f = (TFile*)vf;
1715  }
1716 
1717  m_files[stream] = std::make_pair( f, newMode );
1719 
1720  if ( msgLevel( MSG::DEBUG ) ) {
1721  debug() << "Opening TFile \"" << filename << "\" stream: \"" << stream << "\" mode: \"" << typ << "\""
1722  << " comp level: " << cl << endmsg;
1723  }
1724 
1725  return StatusCode::SUCCESS;
1726 }
1727 
1728 TDirectory* THistSvc::changeDir( const THistSvc::THistID& hid ) const {
1729  std::string uid = hid.id;
1730  TFile* file = hid.file;
1731  std::string stream, fdir, bdir, dir, id;
1732 
1733  if ( file ) {
1734  file->cd( "/" );
1735  } else {
1736  gROOT->cd();
1737  }
1738 
1739  fdir = uid;
1740  bdir = stripDirectoryName( fdir );
1741 
1742  while ( ( dir = stripDirectoryName( fdir ) ) != "" ) {
1743  if ( !gDirectory->GetKey( dir.c_str() ) ) { gDirectory->mkdir( dir.c_str() ); }
1744  gDirectory->cd( dir.c_str() );
1745  }
1746 
1747  return gDirectory;
1748 }
1749 
1751  std::string::size_type i = dir.find( "/" );
1752 
1753  if ( i == std::string::npos ) return {};
1754 
1755  if ( i == 0 ) {
1756  dir.erase( 0, 1 );
1757  return stripDirectoryName( dir );
1758  }
1759 
1760  std::string root = dir.substr( 0, i );
1761  dir.erase( 0, i );
1762 
1763  return root;
1764 }
1765 
1767  while ( id.find( "//" ) != std::string::npos ) { id.replace( id.find( "//" ), 2, "/" ); }
1768 }
1769 
1770 void THistSvc::MergeRootFile( TDirectory* target, TDirectory* source ) {
1771  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Target path: " << target->GetPath() << endmsg; }
1772  TString path( (char*)strstr( target->GetPath(), ":" ) );
1773  path.Remove( 0, 2 );
1774 
1775  source->cd( path );
1776  TDirectory* current_sourcedir = gDirectory;
1777 
1778  // loop over all keys in this directory
1779  TList* lkeys = current_sourcedir->GetListOfKeys();
1780  int nkeys = lkeys->GetEntries();
1781  TKey* key = nullptr;
1782  for ( int jj = 0; jj < nkeys; jj++ ) {
1783  key = (TKey*)lkeys->At( jj );
1784  std::string pathnameinsource = current_sourcedir->GetPath() + std::string( "/" ) + key->GetName();
1785  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Reading Key:" << pathnameinsource << endmsg; }
1786  TObject* obj = source->Get( pathnameinsource.c_str() );
1787 
1788  if ( obj ) {
1789  if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1790  // it's a subdirectory
1791  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Found subdirectory " << obj->GetName() << endmsg; }
1792 
1793  // create a new subdir of same name and title in the target file
1794  target->cd();
1795  TDirectory* newtargetdir = target->mkdir( obj->GetName(), obj->GetTitle() );
1796 
1797  MergeRootFile( newtargetdir, source );
1798 
1799  } else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
1800  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Found TTree " << obj->GetName() << endmsg; }
1801  TTree* mytree = dynamic_cast<TTree*>( obj );
1802  int nentries = (int)mytree->GetEntries();
1803  mytree->SetBranchStatus( "*", 1 );
1804 
1805  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Dumping TTree " << nentries << " entries" << endmsg; }
1806  target->cd();
1807  mytree->CloneTree();
1808 
1809  } else {
1810  target->cd();
1811  obj->Write( key->GetName() );
1812  }
1813  }
1814  }
1815 }
1816 
1817 bool THistSvc::findStream( const std::string& id, std::string& stream, std::string& rem, TFile*& file ) const {
1818  auto pos = id.find( "/" );
1819 
1820  if ( pos == std::string::npos ) {
1821  // no "/" in id
1822  stream = "temp";
1823  rem = id;
1824  } else if ( pos != 0 ) {
1825  // id does not start with "/"
1826  stream = "temp";
1827  rem = id;
1828  } else {
1829  // id starts with "/"
1830 
1831  auto pos2 = id.find( "/", pos + 1 );
1832 
1833  if ( pos2 == std::string::npos ) {
1834  // need at least 2 "/" in format "/STREAM/name" or "/STREAM/dir/name"
1835  error() << "badly formed Hist/Tree id: \"" << id << "\"" << endmsg;
1836  return false;
1837  }
1838  parseString( id, stream, rem );
1839  }
1840 
1841  if ( stream == "temp" ) {
1842  file = nullptr;
1843  return true;
1844  }
1845 
1846  auto itr = m_files.find( stream );
1847  file = ( itr != m_files.end() ? itr->second.first : nullptr );
1848  if ( !file ) { warning() << "no stream \"" << stream << "\" associated with id: \"" << id << "\"" << endmsg; }
1849 
1850  return true;
1851 }
1852 
1854  auto pos = id.find( "/" );
1855 
1856  if ( pos == std::string::npos ) {
1857  root.clear();
1858  rem = id;
1859  } else if ( pos == 0 ) {
1860  parseString( id.substr( 1 ), root, rem );
1861  } else {
1862  root = id.substr( 0, pos );
1863  rem = id.substr( pos + 1 );
1864  }
1865 }
1866 
1869  debug() << "Delaying connection of Input Files until Initialize"
1870  << ". now in " << FSMState() << endmsg;
1871 
1872  m_delayConnect = true;
1873  } else {
1874  debug() << "Now connecting of Input Files" << endmsg;
1875 
1877 
1878  for ( const auto& itr : m_inputfile.value() ) {
1879  if ( m_alreadyConnectedInFiles.end() != m_alreadyConnectedInFiles.find( itr ) ) { continue; }
1880  if ( connect( itr ).isFailure() ) {
1881  sc = StatusCode::FAILURE;
1882  } else {
1884  }
1885  }
1886 
1887  if ( !sc.isSuccess() ) { throw GaudiException( "Problem connecting inputfile !!", name(), StatusCode::FAILURE ); }
1888  }
1889 }
1890 
1893  debug() << "Delaying connection of Output Files until Initialize"
1894  << ". now in " << FSMState() << endmsg;
1895  m_delayConnect = true;
1896  } else {
1898  for ( const auto& itr : m_outputfile.value() ) {
1899  if ( m_alreadyConnectedOutFiles.end() != m_alreadyConnectedOutFiles.find( itr ) ) { continue; }
1900  if ( connect( itr ).isFailure() ) {
1901  sc = StatusCode::FAILURE;
1902  } else {
1904  }
1905  }
1906 
1907  if ( !sc.isSuccess() ) { throw GaudiException( "Problem connecting outputfile !!", name(), StatusCode::FAILURE ); }
1908  }
1909 }
1910 
1911 void THistSvc::copyFileLayout( TDirectory* destination, TDirectory* source ) {
1912  if ( msgLevel( MSG::DEBUG ) ) {
1913  debug() << "copyFileLayout() to destination path: " << destination->GetPath() << endmsg;
1914  }
1915 
1916  // strip out URLs
1917  TString path( (char*)strstr( destination->GetPath(), ":" ) );
1918  path.Remove( 0, 2 );
1919 
1920  source->cd( path );
1921  TDirectory* current_source_dir = gDirectory;
1922 
1923  // loop over all keys in this directory
1924  TList* key_list = current_source_dir->GetListOfKeys();
1925  int n = key_list->GetEntries();
1926  for ( int j = 0; j < n; ++j ) {
1927  TKey* k = (TKey*)key_list->At( j );
1928  const std::string source_pathname = current_source_dir->GetPath() + std::string( "/" ) + k->GetName();
1929  TObject* o = source->Get( source_pathname.c_str() );
1930 
1931  if ( o && o->IsA()->InheritsFrom( "TDirectory" ) ) {
1932  if ( msgLevel( MSG::VERBOSE ) ) { verbose() << " subdir [" << o->GetName() << "]..." << endmsg; }
1933  destination->cd();
1934  // Create directory if it does not exist yet
1935  TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() );
1936  if ( destination_dir == nullptr ) destination_dir = destination->GetDirectory( o->GetName() );
1937  copyFileLayout( destination_dir, source );
1938  }
1939  } // loop over keys
1940  return;
1941 }
1942 
1943 size_t THistSvc::findHistID( const std::string& id, const THistID*& hid, const size_t& index ) const {
1944  GlobalDirectoryRestore restore( m_svcMut );
1945 
1946  std::string idr( id );
1947  removeDoubleSlash( idr );
1948 
1949  hid = 0;
1950 
1951  if ( idr.starts_with( "/" ) ) {
1952  // fully specified name, starts with "/"
1953  auto itr = m_uids.find( idr );
1954  if ( itr == m_uids.end() ) {
1955  // no matches found
1956  return 0;
1957  } else {
1958  // one or more matches found (clones).
1959  if ( index >= itr->second->size() ) {
1960  error() << "no index " << index << " found for Hist " << idr << endmsg;
1961  return 0;
1962  }
1963  hid = &( itr->second->at( index ) );
1964  return 1;
1965  }
1966  } else {
1967  // name not fully specified.
1968  auto mitr = m_ids.equal_range( idr );
1969  if ( mitr.first == mitr.second ) {
1970  // not found
1971  return 0;
1972  } else if ( distance( mitr.first, mitr.second ) == 1 ) {
1973  // one found
1974  if ( index >= mitr.first->second->size() ) {
1975  error() << "no index " << index << " found for Hist " << idr << endmsg;
1976  return 0;
1977  }
1978  hid = &( mitr.first->second->at( 0 ) );
1979  return 1;
1980  } else {
1981  // multiple matches
1982  hid = &( mitr.first->second->at( 0 ) );
1983  return distance( mitr.first, mitr.second );
1984  }
1985  }
1986 }
1987 
1988 void THistSvc::dump() const {
1989  std::ostringstream ost;
1990 
1991  // list< vector<THistID> >
1992  ost << "m_hlist: size: " << m_hlist.size() << "\n";
1993  for ( auto& vh : m_hlist ) {
1994  ost << " - " << vh->at( 0 ) << " :: [" << vh << "] " << vh->size() << " {";
1995  for ( auto& e : *vh ) {
1996  TObject* o = e.obj;
1997  ost << "[" << o << "]";
1998  }
1999  ost << "}\n";
2000  }
2001 
2002  // map uid -> vector<THistID>*
2003  ost << "\n"
2004  << "m_uids: " << m_uids.size() << "\n";
2005  for ( auto& e : m_uids ) { ost << " - " << e.first << " [" << e.second << "]" << std::endl; }
2006 
2007  // multimap id -> vector<THistID>*
2008  ost << "\n"
2009  << "m_ids: " << m_ids.size() << "\n";
2010  for ( auto& e : m_ids ) { ost << " - " << e.first << " [" << e.second << "]" << std::endl; }
2011 
2012  // map TObject* -> THistID*
2013  ost << "\n"
2014  << "m_tobjs: " << m_tobjs.size() << "\n";
2015  for ( auto& e : m_tobjs ) {
2016  TObject* o = e.first;
2017  THistID& i = e.second.first->at( e.second.second );
2018  ost << " - " << o << " -> " << i << std::endl;
2019  }
2020 
2021  debug() << "dumping THistSvc contents\n" << ost.str() << endmsg;
2022 }
2023 
2024 StatusCode THistSvc::merge( const THistID& hid ) { return merge( hid.id ); }
2025 
2027  const std::string& name = vh->at( 0 ).id;
2028  if ( vh->size() == 1 ) {
2029  debug() << "merge: id: \"" << name << "\" is size 1. nothing to do" << endmsg;
2030  return StatusCode::SUCCESS;
2031  }
2032 
2033  if ( vh->at( 0 ).type != ObjectType::TH1 ) {
2034  error() << "merge: id \"" << name << "\" is not a THn. Cannot merge" << endmsg;
2035  return StatusCode::FAILURE;
2036  }
2037 
2038  TList* l = new TList();
2039  for ( size_t i = 1; i < vh->size(); ++i ) {
2040  debug() << "merge: id: \"" << name << "\" (" << vh->at( i ).obj << ") adding index " << i << endmsg;
2041  l->Add( vh->at( i ).obj );
2042  }
2043 
2044  TH1* t0 = dynamic_cast<TH1*>( vh->at( 0 ).obj );
2045  if ( t0 == 0 ) {
2046  error() << "merge: could not dcast " << name << "(" << t0 << ") index " << 0 << " to TH1" << endmsg;
2047  return StatusCode::FAILURE;
2048  }
2049 
2050  Long64_t n = t0->Merge( l );
2051 
2052  debug() << "merge: id: \"" << name << "\" merged " << n << " entries" << endmsg;
2053 
2054  for ( size_t i = 1; i < vh->size(); ++i ) {
2055  TH1* th = dynamic_cast<TH1*>( vh->at( i ).obj );
2056  if ( th != 0 ) {
2057  debug() << "clearing index " << i << "(" << th << ")" << endmsg;
2058  th->SetDirectory( nullptr );
2059  th->Reset();
2060  } else {
2061  error() << "merge: could not dcast " << name << " index " << i << " to TH1" << endmsg;
2062  return StatusCode::FAILURE;
2063  }
2064  }
2065  return StatusCode::SUCCESS;
2066 }
2067 
2069  if ( fa->tech() != Io::ROOT ) {
2070  // This should never happen
2071  return StatusCode::SUCCESS;
2072  }
2073 
2074  if ( fa->desc() != "HIST" ) { return StatusCode::SUCCESS; }
2075 
2076  p_incSvc->fireIncident( FileIncident( caller, "OpenHistFile", fa->name() ) );
2077 
2078  if ( fa->flags().isRead() ) {
2079  p_incSvc->fireIncident( FileIncident( caller, "BeginHistFile", fa->name() ) );
2080  } else if ( fa->flags().isWrite() ) {
2081  p_incSvc->fireIncident( FileIncident( caller, IncidentType::BeginOutputFile, fa->name() ) );
2082  } else {
2083  // for Io::RW
2084  p_incSvc->fireIncident( FileIncident( caller, IncidentType::BeginOutputFile, fa->name() ) );
2085  }
2086 
2087  return StatusCode::SUCCESS;
2088 }
2089 
2091  if ( fa->tech() != Io::ROOT ) {
2092  // This should never happen
2093  return StatusCode::SUCCESS;
2094  }
2095 
2096  if ( fa->desc() != "HIST" ) { return StatusCode::SUCCESS; }
2097 
2098  if ( fa->flags().isRead() ) {
2099  p_incSvc->fireIncident( FileIncident( caller, IncidentType::FailInputFile, fa->name() ) );
2100  } else if ( fa->flags().isWrite() ) {
2101  p_incSvc->fireIncident( FileIncident( caller, IncidentType::FailOutputFile, fa->name() ) );
2102  } else {
2103  // for Io::RW
2104  p_incSvc->fireIncident( FileIncident( caller, "FailRWFile", fa->name() ) );
2105  }
2106 
2107  return StatusCode::SUCCESS;
2108 }
THistSvc::THistID::id
std::string id
Definition: THistSvc.h:240
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
Io::OPEN
@ OPEN
Definition: IFileMgr.h:278
IIoComponentMgr::IoMode::READ
@ READ
Definition: IIoComponentMgr.h:41
THistSvc::getEfficiency
StatusCode getEfficiency(const std::string &name, TEfficiency *&) const override
Return TEfficiency with given name.
Definition: THistSvc.cpp:461
THistSvc::m_autoFlush
Gaudi::Property< int > m_autoFlush
Definition: THistSvc.h:371
std::for_each
T for_each(T... args)
Write.stream
stream
Definition: Write.py:32
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
THistSvc::INVALID
@ INVALID
Definition: THistSvc.h:217
THistSvc::UPDATE
@ UPDATE
Definition: THistSvc.h:217
std::string
STL class.
THistSvc::merge
StatusCode merge(const std::string &id) override
Merge all clones for object with a given id.
Definition: THistSvc.cpp:647
THistSvc::m_delayConnect
bool m_delayConnect
Definition: THistSvc.h:392
THistSvc::getEfficiencies
std::vector< std::string > getEfficiencies() const override
Definition: THistSvc.cpp:705
THistSvc::regShared
StatusCode regShared(const std::string &name, std::unique_ptr< TH1 >, LockedHandle< TH1 > &) override
Register shared object of type TH1 and return LockedHandle for that object.
Definition: THistSvc.cpp:470
THistSvc
Definition: THistSvc.h:41
Gaudi.Configuration.log
log
Definition: Configuration.py:28
Io::FileAttr::tech
IoTech tech() const
Definition: IFileMgr.h:188
THistSvc::getTrees
std::vector< std::string > getTrees() const override
Definition: THistSvc.cpp:689
std::move
T move(T... args)
AtlasMCRecoFullPrecedenceDump.path
path
Definition: AtlasMCRecoFullPrecedenceDump.py:49
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:314
MSG::INFO
@ INFO
Definition: IMessageSvc.h:25
IIncidentSvc::addListener
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
Io::FileAttr::flags
IoFlags flags() const
Definition: IFileMgr.h:189
std::pair
std::vector::reserve
T reserve(T... args)
THistSvc::copyFileLayout
void copyFileLayout(TDirectory *, TDirectory *)
helper function to recursively copy the layout of a TFile into a new TFile
Definition: THistSvc.cpp:1911
GaudiException.h
gaudirun.s
string s
Definition: gaudirun.py:346
THistSvc::m_curstream
std::string m_curstream
Definition: THistSvc.h:396
THistSvc::getTEfficiencies
StatusCode getTEfficiencies(TDirectory *td, TList &, bool recurse=false) const override
Definition: THistSvc.cpp:1093
THistSvc::getTTrees
StatusCode getTTrees(TDirectory *td, TList &, bool recurse=false) const override
Definition: THistSvc.cpp:912
THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore
GlobalDirectoryRestore(THistSvcMutex_t &mut)
Definition: THistSvc.cpp:1436
std::vector
STL class.
std::string::find
T find(T... args)
std::string::length
T length(T... args)
THistSvc::writeObjectsToFile
StatusCode writeObjectsToFile()
Definition: THistSvc.cpp:1527
check_ParticleID.props
props
Definition: check_ParticleID.py:21
THistSvc::existsEfficiency
bool existsEfficiency(const std::string &name) const override
Check if TEfficiency with given name is managed by THistSvcMT.
Definition: THistSvc.cpp:671
ISvcLocator
Definition: ISvcLocator.h:46
std::back_inserter
T back_inserter(T... args)
Io::IoFlags::isRead
bool isRead() const
Definition: IFileMgr.h:65
GaudiException
Definition: GaudiException.h:31
THistSvc::getGraph
StatusCode getGraph(const std::string &name, TGraph *&) const override
Return TGraph with given name.
Definition: THistSvc.cpp:438
THistSvc::existsGraph
bool existsGraph(const std::string &name) const override
Check if graph with given name is managed by THistSvcMT.
Definition: THistSvc.cpp:675
THistSvc::initialize
StatusCode initialize() override
Definition: THistSvc.cpp:82
THistSvc::deReg
StatusCode deReg(const std::string &name) override
Deregister object with given name and give up ownership (without deletion!)
Definition: THistSvc.cpp:561
std::multimap::emplace
T emplace(T... args)
std::recursive_mutex
STL class.
Gaudi::Units::nm
constexpr double nm
Definition: SystemOfUnits.h:97
fixtures.returncode
Generator[int, None, None] returncode(subprocess.CompletedProcess completed_process)
Definition: fixtures.py:154
gaudiComponentHelp.root
root
Definition: gaudiComponentHelp.py:42
FileIncident.h
This file contains the class definition for the FileIncident class.
THistSvc::setupInputFile
void setupInputFile()
call-back method to handle input stream property
Definition: THistSvc.cpp:1867
THistSvc::m_hlist
hlist_t m_hlist
Definition: THistSvc.h:289
THistSvc::m_autoSave
Gaudi::Property< int > m_autoSave
Definition: THistSvc.h:370
std::vector::back
T back(T... args)
IFileMgr.h
THistSvc::getTHists
StatusCode getTHists(TDirectory *td, TList &, bool recurse=false) const override
Definition: THistSvc.cpp:713
Io::WRITE
@ WRITE
Definition: IFileMgr.h:38
GaudiPartProp.tests.id
id
Definition: tests.py:111
THistSvc::getShared
StatusCode getShared(const std::string &name, LockedHandle< TH1 > &) const override
Retrieve shared object with given name as TH1 through LockedHandle.
Definition: THistSvc.cpp:516
THistSvc::m_inputfile
Gaudi::Property< std::vector< std::string > > m_inputfile
Definition: THistSvc.h:384
IIncidentSvc::fireIncident
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
CommonMessaging< implements< IService, IProperty, IStateful > >::msgLevel
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Definition: CommonMessaging.h:148
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:222
Service::FSMState
Gaudi::StateMachine::State FSMState() const override
Definition: Service.h:62
THistSvc::readHist
T * readHist(const std::string &name) const
Definition: THistSvc.cpp:1451
THistSvc::rootOpenAction
StatusCode rootOpenAction(FILEMGR_CALLBACK_ARGS)
Definition: THistSvc.cpp:2068
IIoComponentMgr::IoMode::Type
Type
Definition: IIoComponentMgr.h:41
THistSvc::setupOutputFile
void setupOutputFile()
call-back method to handle output stream property
Definition: THistSvc.cpp:1891
std::set::clear
T clear(T... args)
THistSvc::m_print
Gaudi::Property< bool > m_print
Definition: THistSvc.h:372
THistSvc::stripDirectoryName
std::string stripDirectoryName(std::string &dir) const
Definition: THistSvc.cpp:1750
IIncidentSvc.h
std::vector::push_back
T push_back(T... args)
Io::FileAttr::name
const std::string & name() const
Definition: IFileMgr.h:186
THistSvc::getHists
std::vector< std::string > getHists() const override
Definition: THistSvc.cpp:681
THistSvc::GlobalDirectoryRestore::m_gFile
TFile * m_gFile
Definition: THistSvc.h:211
std::placeholders
compareOutputFiles.target
target
Definition: compareOutputFiles.py:489
std::stoi
T stoi(T... args)
THistSvc::ObjectType::TEFFICIENCY
@ TEFFICIENCY
THistSvc::THistSvc
THistSvc(const std::string &name, ISvcLocator *svcloc)
Definition: THistSvc.cpp:79
Gaudi::Utils::begin
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Definition: AttribStringParser.h:136
THistSvc::rootOpenErrAction
StatusCode rootOpenErrAction(FILEMGR_CALLBACK_ARGS)
Definition: THistSvc.cpp:2090
plotSpeedupsPyRoot.graph
graph
Definition: plotSpeedupsPyRoot.py:168
Gaudi::StateMachine::CONFIGURED
@ CONFIGURED
Definition: StateMachine.h:24
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:332
StatusCode
Definition: StatusCode.h:65
IFileMgr::regAction
virtual StatusCode regAction(Io::bfcn_action_t, const Io::Action &, const std::string &d="")=0
Io::ROOT
@ ROOT
Definition: IFileMgr.h:156
gaudirun.opts
opts
Definition: gaudirun.py:336
THistSvc::parseString
void parseString(const std::string &id, std::string &root, std::string &rem) const
Definition: THistSvc.cpp:1853
std::vector::at
T at(T... args)
THistSvc::existsTree
bool existsTree(const std::string &name) const override
Check if tree with given name is managed by THistSvcMT.
Definition: THistSvc.cpp:679
THistSvc::SHARE
@ SHARE
Definition: THistSvc.h:217
THistSvc::handle
void handle(const Incident &) override
Definition: THistSvc.cpp:1296
THistSvc::finalize
StatusCode finalize() override
Definition: THistSvc.cpp:193
ProduceConsume.j
j
Definition: ProduceConsume.py:104
THistSvc::m_maxFileSize
Gaudi::Property< int > m_maxFileSize
Definition: THistSvc.h:373
THistSvc::findStream
bool findStream(const std::string &name, std::string &root, std::string &rem, TFile *&file) const
Definition: THistSvc.cpp:1817
THistSvc::THistID::temp
bool temp
Definition: THistSvc.h:246
CommonMessaging
Definition: CommonMessaging.h:66
THistSvc::m_tobjs
objMap_t m_tobjs
Definition: THistSvc.h:294
std::string::c_str
T c_str(T... args)
THistSvc::getHist
StatusCode getHist(const std::string &name, TH1 *&, size_t index=0) const override
Return histogram with given name as TH1*, THistSvcMT still owns object.
Definition: THistSvc.cpp:344
THistSvc::charToMode
static Mode charToMode(const char typ)
Convert a char to a Mode enum.
Definition: THistSvc.h:223
THistSvc::m_outputfile
Gaudi::Property< std::vector< std::string > > m_outputfile
Definition: THistSvc.h:382
Io::FileAttr
Definition: IFileMgr.h:171
THistSvc::THistID::file
TFile * file
Definition: THistSvc.h:242
Gaudi::Property::value
const ValueType & value() const
Definition: Property.h:237
std::to_string
T to_string(T... args)
THistSvc::regEfficiency
StatusCode regEfficiency(const std::string &name) override
Register a new TEfficiency with a given name.
Definition: THistSvc.cpp:447
THistSvc::changeDir
TDirectory * changeDir(const THistSvc::THistID &hid) const
Definition: THistSvc.cpp:1728
THistSvc::ObjectType::TTREE
@ TTREE
GaudiPython.Bindings.nullptr
nullptr
Definition: Bindings.py:87
std::string::erase
T erase(T... args)
AttribStringParser.h
THistSvc::APPEND
@ APPEND
Definition: THistSvc.h:217
THistSvc::m_ids
idMap_t m_ids
Definition: THistSvc.h:291
THistSvc::m_okToConnect
bool m_okToConnect
Definition: THistSvc.h:393
genconfuser.verbose
verbose
Definition: genconfuser.py:28
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
THistSvc::regHist
StatusCode regHist(const std::string &name) override
Register a new ROOT histogram TH*X with a name.
Definition: THistSvc.cpp:330
THistSvc::removeDoubleSlash
void removeDoubleSlash(std::string &) const
Definition: THistSvc.cpp:1766
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
THistSvc::THistID::obj
TObject * obj
Definition: THistSvc.h:241
std::remove
T remove(T... args)
std::map
STL class.
ServiceHandle::retrieve
StatusCode retrieve(T *&service) const override
Do the real retrieval of the Service.
Definition: ServiceHandle.h:97
IIoComponentMgr.h
THistSvc::GlobalDirectoryRestore
Helper class that manages ROOts global directory and file.
Definition: THistSvc.h:204
THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore
~GlobalDirectoryRestore()
Definition: THistSvc.cpp:1442
THistSvc::READ
@ READ
Definition: THistSvc.h:217
cpluginsvc.n
n
Definition: cpluginsvc.py:234
THistSvc::reinitialize
StatusCode reinitialize() override
Definition: THistSvc.cpp:187
THistSvc::getTree
StatusCode getTree(const std::string &name, TTree *&) const override
Return TTree with given name.
Definition: THistSvc.cpp:397
StatusCode::ignore
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition: StatusCode.h:139
THistSvc::m_alreadyConnectedOutFiles
std::set< std::string > m_alreadyConnectedOutFiles
list of already connected files.
Definition: THistSvc.h:276
THistSvc::p_incSvc
ServiceHandle< IIncidentSvc > p_incSvc
Definition: THistSvc.h:389
THistSvc::regTree
StatusCode regTree(const std::string &name) override
Register a new TTree with a given name.
Definition: THistSvc.cpp:371
std::string::substr
T substr(T... args)
std::ostringstream
STL class.
THistSvc::regHist_i
StatusCode regHist_i(std::unique_ptr< T > hist, const std::string &name, bool shared)
Definition: THistSvc.icc:27
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
std::unordered_multimap::equal_range
T equal_range(T... args)
FileIncident
This class is the FileIncident.
Definition: FileIncident.h:27
gaudirun.type
type
Definition: gaudirun.py:160
THistSvc::WRITE
@ WRITE
Definition: THistSvc.h:217
std::multimap::lower_bound
T lower_bound(T... args)
Io::EXCL
@ EXCL
Definition: IFileMgr.h:42
MSG::VERBOSE
@ VERBOSE
Definition: IMessageSvc.h:25
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
std::endl
T endl(T... args)
THistSvc::m_files
std::map< std::string, std::pair< TFile *, Mode > > m_files
Definition: THistSvc.h:296
gaudirun.l
dictionary l
Definition: gaudirun.py:583
THistSvc::p_fileMgr
ServiceHandle< IFileMgr > p_fileMgr
Definition: THistSvc.h:390
THistSvc::connect
StatusCode connect(const std::string &)
Definition: THistSvc.cpp:1552
std::vector::begin
T begin(T... args)
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
THistSvc::existsHist
bool existsHist(const std::string &name) const override
Check if histogram with given name is managed by THistSvcMT.
Definition: THistSvc.cpp:669
Io::CREATE
@ CREATE
Definition: IFileMgr.h:41
std::multimap::insert
T insert(T... args)
THistSvc::exists
bool exists(const std::string &name) const override
Check if object with given name is managed by THistSvcMT exists calls existsHist and only works for T...
Definition: THistSvc.cpp:667
THistSvc::m_hasTTrees
bool m_hasTTrees
Definition: THistSvc.h:394
THistSvc::readTree
TTree * readTree(const std::string &name) const
Definition: THistSvc.cpp:1455
Io::FileAttr::desc
const std::string & desc() const
Definition: IFileMgr.h:187
Io::IoFlags::isWrite
bool isWrite() const
Definition: IFileMgr.h:66
THistSvc::ObjectType::TGRAPH
@ TGRAPH
THistSvc::GlobalDirectoryRestore::m_gErrorIgnoreLevel
int m_gErrorIgnoreLevel
Definition: THistSvc.h:212
std::string::empty
T empty(T... args)
THistSvc::GlobalDirectoryRestore::m_gDirectory
TDirectory * m_gDirectory
Definition: THistSvc.h:210
Io::APPEND
@ APPEND
Definition: IFileMgr.h:45
Io::OPEN_ERR
@ OPEN_ERR
Definition: IFileMgr.h:278
GaudiConfig2.semantics.ident
ident
Definition: semantics.py:198
THistSvc.h
THistSvc::m_uids
uidMap_t m_uids
Definition: THistSvc.h:290
std::ostringstream::str
T str(T... args)
THistSvc::m_alreadyConnectedInFiles
std::set< std::string > m_alreadyConnectedInFiles
list of already connected files.
Definition: THistSvc.h:272
THistSvc::updateFiles
void updateFiles()
Handle case where TTree grows beyond TTree::fgMaxTreeSize.
Definition: THistSvc.cpp:1457
std::make_pair
T make_pair(T... args)
IFileMgr::close
virtual Io::close_t close(const Io::Fd, const std::string &caller)=0
std::vector::end
T end(T... args)
IOTest.end
end
Definition: IOTest.py:125
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
LockedHandle
Definition: LockedHandle.h:38
THistSvc::io_reinit
StatusCode io_reinit() override
callback method to reinitialize the internal state of the component for I/O purposes (e....
Definition: THistSvc.cpp:1334
THistSvc::m_svcMut
THistSvcMutex_t m_svcMut
Definition: THistSvc.h:398
THistSvc::findHistID
size_t findHistID(const std::string &id, const THistID *&hid, const size_t &index=0) const
Definition: THistSvc.cpp:1943
ISvcLocator.h
THistSvc::ObjectType::TH1
@ TH1
THistSvc::m_fileStreams
streamMap m_fileStreams
Definition: THistSvc.h:298
Incident
Definition: Incident.h:27
std::unique_ptr
STL class.
graphanalysis.filename
filename
Definition: graphanalysis.py:130
THistSvc::THistID::type
ObjectType type
Definition: THistSvc.h:245
Gaudi::Utils::AttribStringParser
Parse attribute strings allowing iteration over the various attributes.
Definition: AttribStringParser.h:40
IFileMgr::open
virtual Io::open_t open(const Io::IoTech &, const std::string &caller, const std::string &fname, const Io::IoFlags &, Io::Fd &, void *&, const std::string &desc, const bool shared=false)=0
ProduceConsume.key
key
Definition: ProduceConsume.py:84
THistSvc::regGraph
StatusCode regGraph(const std::string &name) override
Register a new TGraph with a given name.
Definition: THistSvc.cpp:406
THistSvc::getGraphs
std::vector< std::string > getGraphs() const override
Definition: THistSvc.cpp:697
THistSvc::THistID
Helper struct that bundles the histogram ID with a mutex, TFile and TObject*.
Definition: THistSvc.h:239
std::string::rfind
T rfind(T... args)
Io::READ
@ READ
Definition: IFileMgr.h:37
Property.h
THistSvc::m_sharedFiles
std::map< std::string, std::string > m_sharedFiles
Definition: THistSvc.h:301
THistSvc::dump
void dump() const
Definition: THistSvc.cpp:1988
Gaudi::ParticleProperties::index
size_t index(const Gaudi::ParticleProperty *property, const Gaudi::Interfaces::IParticlePropertySvc *service)
helper utility for mapping of Gaudi::ParticleProperty object into non-negative integral sequential id...
Definition: IParticlePropertySvc.cpp:39
IIoComponentMgr::IoMode::WRITE
@ WRITE
Definition: IIoComponentMgr.h:41
THistSvc::MergeRootFile
void MergeRootFile(TDirectory *, TDirectory *)
Definition: THistSvc.cpp:1770