The Gaudi Framework  v39r1 (adb068b2)
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 <sstream>
15 #include <streambuf>
16 
17 // boost headers
18 #include <boost/algorithm/string/case_conv.hpp>
19 
20 // ROOT headers
21 #include <TClass.h>
22 #include <TDirectory.h>
23 #include <TError.h>
24 #include <TFile.h>
25 #include <TGraph.h>
26 #include <TKey.h>
27 #include <TROOT.h>
28 
29 // Gaudi headers
30 #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.find( "/" ) == 0 ) { 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  if ( m_signaledStop ) return;
1298 
1299  if ( m_maxFileSize.value() == -1 ) return;
1300 
1301  // convert to bytes.
1302  Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
1303  Long64_t mfs_warn = mfs * 95 / 100;
1304 
1305  updateFiles();
1306 
1307  for ( const auto& f : m_files ) {
1308  TFile* tf = f.second.first;
1309 
1310 #ifndef NDEBUG
1311  if ( msgLevel( MSG::DEBUG ) ) {
1312  debug() << "stream: " << f.first << " name: " << tf->GetName() << " size: " << tf->GetSize() << endmsg;
1313  }
1314 #endif
1315 
1316  // Signal job to terminate if output file is too large
1317  if ( tf->GetSize() > mfs ) {
1318 
1319  m_signaledStop = true;
1320 
1321  fatal() << "file \"" << tf->GetName() << "\" associated with stream \"" << f.first
1322  << "\" has exceeded the max file size of " << m_maxFileSize.value() << "MB. Terminating Job." << endmsg;
1323 
1324  auto evt = service<IEventProcessor>( "ApplicationMgr", true );
1325  if ( evt ) {
1326  evt->stopRun().ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
1327  } else {
1328  abort();
1329  }
1330  } else if ( tf->GetSize() > mfs_warn ) {
1331  warning() << "file \"" << tf->GetName() << "\" associated with stream \"" << f.first
1332  << "\" is at 95% of its maximum allowable file size of " << m_maxFileSize.value() << "MB" << endmsg;
1333  }
1334  }
1335 }
1336 
1341  bool all_good = true;
1342  if ( msgLevel( MSG::DEBUG ) ) { debug() << "reinitializing I/O..." << endmsg; }
1343 
1344  // retrieve the I/O component manager...
1345 
1346  auto iomgr = service<IIoComponentMgr>( "IoComponentMgr", true );
1347  if ( !iomgr ) {
1348  error() << "could not retrieve I/O component manager !" << endmsg;
1349  return StatusCode::FAILURE;
1350  }
1351 
1352  GlobalDirectoryRestore restore( m_svcMut );
1353  // to hide the expected errors upon closing the files whose
1354  // file descriptors have been swept under the rug...
1355  gErrorIgnoreLevel = kFatal;
1356 
1357  for ( auto& ifile : m_files ) {
1358  TFile* f = ifile.second.first;
1359  std::string fname = f->GetName();
1360  if ( msgLevel( MSG::DEBUG ) ) {
1361  debug() << "file [" << fname << "] mode: [" << f->GetOption() << "] r:" << f->GetFileBytesRead()
1362  << " w:" << f->GetFileBytesWritten() << " cnt:" << f->GetFileCounter() << endmsg;
1363  }
1364 
1365  if ( ifile.second.second == READ ) {
1366  if ( msgLevel( MSG::DEBUG ) ) { debug() << " TFile opened in READ mode: not reassigning names" << endmsg; }
1367  continue;
1368  }
1369 
1370  if ( !iomgr->io_retrieve( this, fname ).isSuccess() ) {
1371  error() << "could not retrieve new name for [" << fname << "] !!" << endmsg;
1372  all_good = false;
1373  continue;
1374  } else if ( fname.empty() ) {
1375  if ( msgLevel( MSG::DEBUG ) ) { debug() << "empty new name for [" << fname << "], skipping..." << endmsg; }
1376  continue;
1377  } else {
1378  if ( msgLevel( MSG::DEBUG ) ) { debug() << "got a new name [" << fname << "]..." << endmsg; }
1379  }
1380 
1381  void* vf = nullptr;
1382  Option_t* opts = f->GetOption();
1383  int r = p_fileMgr->open( Io::ROOT, name(), fname, Io::WRITE, vf, "HIST" );
1384  if ( r != 0 ) {
1385  error() << "unable to open file \"" << fname << "\" for writing" << endmsg;
1386  return StatusCode::FAILURE;
1387  }
1388  TFile* newfile = (TFile*)vf;
1389  newfile->SetOption( opts );
1390 
1391  if ( ifile.second.second != THistSvc::READ ) {
1392  copyFileLayout( newfile, f );
1393  ifile.second.first = newfile;
1394  }
1395 
1396  // loop over all uids and migrate them to the new file
1397  for ( auto& uid : m_uids ) {
1398  for ( auto& hid : *uid.second ) {
1399  if ( hid.file != f ) continue;
1400  TDirectory* olddir = this->changeDir( hid );
1401  hid.file = newfile;
1402  // side-effect: create needed directories...
1403  TDirectory* newdir = this->changeDir( hid );
1404  TClass* cl = hid.obj->IsA();
1405 
1406  // migrate the objects to the new file.
1407  // thanks to the object model of ROOT, it is super easy.
1408  if ( hid.type == ObjectType::TTREE ) {
1409  TTree& tree = dynamic_cast<TTree&>( *hid.obj );
1410  tree.SetDirectory( newdir );
1411  tree.Reset();
1412  } else if ( hid.type == ObjectType::TH1 ) {
1413  TH1& hist = dynamic_cast<TH1&>( *hid.obj );
1414  hist.SetDirectory( newdir );
1415  hist.Reset();
1416  } else if ( hid.type == ObjectType::TEFFICIENCY ) {
1417  dynamic_cast<TEfficiency&>( *hid.obj ).SetDirectory( newdir );
1418  } else if ( hid.type == ObjectType::TGRAPH ) {
1419  olddir->Remove( hid.obj );
1420  newdir->Append( hid.obj );
1421  } else {
1422  error() << "id: \"" << hid.id << "\" is not a inheriting from a class "
1423  << "we know how to handle (received [" << cl->GetName() << "], "
1424  << "expected [TTree, TH1, TGraph or TEfficiency]) !" << endmsg << "attaching to current dir ["
1425  << newdir->GetPath() << "] "
1426  << "nonetheless..." << endmsg;
1427  olddir->Remove( hid.obj );
1428  newdir->Append( hid.obj );
1429  }
1430  }
1431  }
1432  f->ReOpen( "READ" );
1433  p_fileMgr->close( f, name() );
1434  f = newfile;
1435  }
1436 
1437  return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE;
1438 }
1439 
1440 //*************************************************************************//
1441 
1443  m_gDirectory = gDirectory;
1444  m_gFile = gFile;
1445  m_gErrorIgnoreLevel = gErrorIgnoreLevel;
1446 }
1447 
1449  gDirectory = m_gDirectory;
1450  gFile = m_gFile;
1451  gErrorIgnoreLevel = m_gErrorIgnoreLevel;
1452 }
1453 
1454 //*************************************************************************//
1455 
1456 template <typename T>
1457 T* THistSvc::readHist( const std::string& id ) const {
1458  return dynamic_cast<T*>( readHist_i<T>( id ) );
1459 }
1460 
1461 TTree* THistSvc::readTree( const std::string& id ) const { return dynamic_cast<TTree*>( readHist_i<TTree>( id ) ); }
1462 
1464 
1465  if ( !m_hasTTrees ) return;
1466 
1467  // If TTrees grow beyond TTree::fgMaxTreeSize, a new file is
1468  // automatically created by root, and the old one closed. We
1469  // need to migrate all the UIDs over to show the correct file
1470  // pointer. This is ugly.
1471 
1472  for ( auto uitr = m_uids.begin(); uitr != m_uids.end(); ++uitr ) {
1473  for ( auto& hid : *( uitr->second ) ) {
1474 
1475  // Only relevant for TTrees and if not in read mode
1476  if ( hid.type != ObjectType::TTREE || hid.temp || hid.mode == READ || hid.obj == nullptr ) continue;
1477 
1478  if ( msgLevel( MSG::VERBOSE ) )
1479  verbose() << " update: " << uitr->first << " " << hid.id << " " << hid.mode << endmsg;
1480 
1481  TTree* tr = dynamic_cast<TTree*>( hid.obj );
1482  TFile* oldFile = hid.file;
1483  TFile* newFile = tr->GetCurrentFile();
1484 
1485  if ( oldFile != newFile ) {
1486  std::string newFileName = newFile->GetName();
1487  std::string oldFileName, streamName, rem;
1488  TFile* dummy = nullptr;
1489  findStream( hid.id, streamName, rem, dummy );
1490 
1491  for ( auto& itr : m_files ) {
1492  if ( itr.second.first == oldFile ) { itr.second.first = newFile; }
1493  }
1494 
1495  for ( auto uitr2 = uitr; uitr2 != m_uids.end(); ++uitr2 ) {
1496  for ( auto& hid2 : *( uitr2->second ) ) {
1497  if ( hid2.file == oldFile ) { hid2.file = newFile; }
1498  }
1499  }
1500 
1502  [&]( streamMap::const_reference s ) { return s.second == streamName; } );
1503  if ( sitr != std::end( m_fileStreams ) ) oldFileName = sitr->first;
1504 
1505 #ifndef NDEBUG
1506  if ( msgLevel( MSG::DEBUG ) ) {
1507  debug() << "migrating uid: " << hid.id << " stream: " << streamName << " oldFile: " << oldFileName
1508  << " newFile: " << newFileName << endmsg;
1509  }
1510 #endif
1511 
1512  if ( !oldFileName.empty() ) {
1513  auto i = m_fileStreams.lower_bound( oldFileName );
1514  while ( i != std::end( m_fileStreams ) && i->first == oldFileName ) {
1515 #ifndef NDEBUG
1516  if ( msgLevel( MSG::DEBUG ) ) {
1517  debug() << "changing filename \"" << i->first << "\" to \"" << newFileName << "\" for stream \""
1518  << i->second << "\"" << endmsg;
1519  }
1520 #endif
1521  std::string nm = std::move( i->second );
1522  i = m_fileStreams.erase( i );
1523  m_fileStreams.emplace( newFileName, std::move( nm ) );
1524  }
1525  } else {
1526  error() << "Problems updating fileStreams with new file name" << endmsg;
1527  }
1528  }
1529  }
1530  }
1531 }
1532 
1534  updateFiles();
1535 
1537  auto mode = i.second.second;
1538  auto file = i.second.first;
1539  if ( mode == WRITE || mode == UPDATE || mode == SHARE ) {
1540  file->Write( "", TObject::kOverwrite );
1541  } else if ( mode == APPEND ) {
1542  file->Write( "" );
1543  }
1544  } );
1545 
1546  if ( msgLevel( MSG::DEBUG ) ) {
1547  debug() << "THistSvc::writeObjectsToFile()::List of Files connected in ROOT " << endmsg;
1548  TSeqCollection* filelist = gROOT->GetListOfFiles();
1549  for ( int ii = 0; ii < filelist->GetEntries(); ii++ ) {
1550  debug() << "THistSvc::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName()
1551  << "\"" << endmsg;
1552  }
1553  }
1554 
1555  return StatusCode::SUCCESS;
1556 }
1557 
1559  auto loc = ident.find( " " );
1560  std::string stream = ident.substr( 0, loc );
1561  char typ( 0 );
1564  std::string filename, db_typ( "ROOT" );
1565  int cl( 1 );
1566 
1567  if ( loc != std::string::npos ) {
1568  using Parser = Gaudi::Utils::AttribStringParser;
1569  for ( auto attrib : Parser( ident.substr( loc + 1 ) ) ) {
1570  // Don't use to_upper_copy in order to avoid gcc 13.1 bug
1571  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109703
1572  // (Should be fixed in 13.2.)
1573  auto TAG = attrib.tag;
1574  auto VAL = attrib.value;
1575  boost::algorithm::to_upper( TAG );
1576  boost::algorithm::to_upper( VAL );
1577 
1578  if ( TAG == "FILE" || TAG == "DATAFILE" ) {
1579  filename = attrib.value;
1581  } else if ( TAG == "OPT" ) {
1582  if ( VAL == "APPEND" || VAL == "UPDATE" ) {
1583  typ = 'A';
1584  } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
1585  typ = 'N';
1586  } else if ( VAL == "RECREATE" ) {
1587  typ = 'R';
1588  } else if ( VAL == "SHARE" ) {
1589  typ = 'S';
1590  } else if ( VAL == "OLD" || VAL == "READ" ) {
1591  typ = 'O';
1592  } else {
1593  error() << "Unknown OPT: \"" << attrib.value << "\"" << endmsg;
1594  typ = 0;
1595  }
1596  } else if ( TAG == "TYP" ) {
1597  db_typ = std::move( attrib.value );
1598  } else if ( TAG == "CL" ) {
1599  cl = std::stoi( attrib.value );
1600  } else {
1601  props.emplace_back( attrib.tag, attrib.value );
1602  }
1603  }
1604  }
1605 
1606  if ( stream == "temp" ) {
1607  error() << "in JobOption \"" << ident << "\": stream name \"temp\" reserved." << endmsg;
1608  return StatusCode::FAILURE;
1609  }
1610 
1611  if ( db_typ != "ROOT" ) {
1612  error() << "in JobOption \"" << ident << "\": technology type \"" << db_typ << "\" not supported." << endmsg;
1613  return StatusCode::FAILURE;
1614  }
1615 
1616  if ( m_files.find( stream ) != m_files.end() ) {
1617  error() << "in JobOption \"" << ident << "\":\n stream \"" << stream << "\" already connected to file: \""
1618  << m_files[stream].first->GetName() << "\"" << endmsg;
1619  return StatusCode::FAILURE;
1620  }
1621 
1622  const auto newMode = charToMode( typ );
1623  if ( newMode == THistSvc::INVALID ) {
1624  error() << "No OPT= specified or unknown access mode in: " << ident << endmsg;
1625  return StatusCode::FAILURE;
1626  }
1627 
1628  // Is this file already connected to another stream?
1629  if ( m_fileStreams.find( filename ) != m_fileStreams.end() ) {
1630  auto fitr = m_fileStreams.equal_range( filename );
1631 
1632  const std::string& oldstream = fitr.first->second;
1633 
1634  const auto& f_info = m_files[oldstream];
1635 
1636  if ( newMode != f_info.second ) {
1637  error() << "in JobOption \"" << ident << "\":\n file \"" << filename << "\" already opened by stream: \""
1638  << oldstream << "\" with different access mode." << endmsg;
1639  return StatusCode::FAILURE;
1640  } else {
1641  TFile* f2 = f_info.first;
1642  m_files[stream] = std::make_pair( f2, newMode );
1643  if ( msgLevel( MSG::DEBUG ) )
1644  debug() << "Connecting stream: \"" << stream << "\" to previously opened TFile: \"" << filename << "\""
1645  << endmsg;
1646  return StatusCode::SUCCESS;
1647  }
1648  }
1649 
1650  void* vf = nullptr;
1651  TFile* f = nullptr;
1652 
1653  if ( newMode == THistSvc::READ ) {
1654  // old file
1655  int r = p_fileMgr->open( Io::ROOT, name(), filename, Io::READ, vf, "HIST" );
1656 
1657  if ( r != 0 ) {
1658  error() << "Unable to open ROOT file " << filename << " for reading" << endmsg;
1659  return StatusCode::FAILURE;
1660  }
1661 
1662  f = (TFile*)vf;
1663 
1664  // FIX ME!
1665  p_incSvc->fireIncident( FileIncident( name(), "BeginHistFile", filename ) );
1666 
1667  } else if ( newMode == THistSvc::WRITE ) {
1668  // new file. error if file exists
1669  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE | Io::EXCL ), vf, "HIST" );
1670 
1671  if ( r != 0 ) {
1672  error() << "Unable to open ROOT file " << filename << " for writing" << endmsg;
1673  return StatusCode::FAILURE;
1674  }
1675 
1676  f = (TFile*)vf;
1677 
1678  } else if ( newMode == THistSvc::APPEND ) {
1679  // update file
1680  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::APPEND ), vf, "HIST" );
1681  if ( r != 0 ) {
1682  error() << "unable to open file \"" << filename << "\" for appending" << endmsg;
1683  return StatusCode::FAILURE;
1684  }
1685 
1686  f = (TFile*)vf;
1687 
1688  } else if ( newMode == THistSvc::SHARE ) {
1689  // SHARE file type
1690  // For SHARE files, all data will be stored in a temp file and will be
1691  // merged into the target file in writeObjectsToFile() when finalize(),
1692  // this help to solve some confliction. e.g. with storegate
1693  static int ishared = 0;
1694  std::string realfilename = filename;
1695  filename = "tmp_THistSvc_" + std::to_string( ishared++ ) + ".root";
1696 
1697  if ( msgLevel( MSG::DEBUG ) ) {
1698  debug() << "Creating temp file \"" << filename << "\" and realfilename=" << realfilename << endmsg;
1699  }
1700  m_sharedFiles[stream] = realfilename;
1701 
1702  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE | Io::EXCL ), vf, "HIST" );
1703 
1704  if ( r != 0 ) {
1705  error() << "Unable to open ROOT file " << filename << " for writing" << endmsg;
1706  return StatusCode::FAILURE;
1707  }
1708 
1709  f = (TFile*)vf;
1710 
1711  } else if ( newMode == THistSvc::UPDATE ) {
1712  // update file
1713  int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE ), vf, "HIST" );
1714 
1715  if ( r != 0 ) {
1716  error() << "Unable to open ROOT file " << filename << " for appending" << endmsg;
1717  return StatusCode::FAILURE;
1718  }
1719 
1720  f = (TFile*)vf;
1721  }
1722 
1723  m_files[stream] = std::make_pair( f, newMode );
1725 
1726  if ( msgLevel( MSG::DEBUG ) ) {
1727  debug() << "Opening TFile \"" << filename << "\" stream: \"" << stream << "\" mode: \"" << typ << "\""
1728  << " comp level: " << cl << endmsg;
1729  }
1730 
1731  return StatusCode::SUCCESS;
1732 }
1733 
1734 TDirectory* THistSvc::changeDir( const THistSvc::THistID& hid ) const {
1735  std::string uid = hid.id;
1736  TFile* file = hid.file;
1737  std::string stream, fdir, bdir, dir, id;
1738 
1739  if ( file ) {
1740  file->cd( "/" );
1741  } else {
1742  gROOT->cd();
1743  }
1744 
1745  fdir = uid;
1746  bdir = stripDirectoryName( fdir );
1747 
1748  while ( ( dir = stripDirectoryName( fdir ) ) != "" ) {
1749  if ( !gDirectory->GetKey( dir.c_str() ) ) { gDirectory->mkdir( dir.c_str() ); }
1750  gDirectory->cd( dir.c_str() );
1751  }
1752 
1753  return gDirectory;
1754 }
1755 
1757  std::string::size_type i = dir.find( "/" );
1758 
1759  if ( i == std::string::npos ) return {};
1760 
1761  if ( i == 0 ) {
1762  dir.erase( 0, 1 );
1763  return stripDirectoryName( dir );
1764  }
1765 
1766  std::string root = dir.substr( 0, i );
1767  dir.erase( 0, i );
1768 
1769  return root;
1770 }
1771 
1773  while ( id.find( "//" ) != std::string::npos ) { id.replace( id.find( "//" ), 2, "/" ); }
1774 }
1775 
1776 void THistSvc::MergeRootFile( TDirectory* target, TDirectory* source ) {
1777  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Target path: " << target->GetPath() << endmsg; }
1778  TString path( (char*)strstr( target->GetPath(), ":" ) );
1779  path.Remove( 0, 2 );
1780 
1781  source->cd( path );
1782  TDirectory* current_sourcedir = gDirectory;
1783 
1784  // loop over all keys in this directory
1785  TList* lkeys = current_sourcedir->GetListOfKeys();
1786  int nkeys = lkeys->GetEntries();
1787  TKey* key = nullptr;
1788  for ( int jj = 0; jj < nkeys; jj++ ) {
1789  key = (TKey*)lkeys->At( jj );
1790  std::string pathnameinsource = current_sourcedir->GetPath() + std::string( "/" ) + key->GetName();
1791  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Reading Key:" << pathnameinsource << endmsg; }
1792  TObject* obj = source->Get( pathnameinsource.c_str() );
1793 
1794  if ( obj ) {
1795  if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
1796  // it's a subdirectory
1797  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Found subdirectory " << obj->GetName() << endmsg; }
1798 
1799  // create a new subdir of same name and title in the target file
1800  target->cd();
1801  TDirectory* newtargetdir = target->mkdir( obj->GetName(), obj->GetTitle() );
1802 
1803  MergeRootFile( newtargetdir, source );
1804 
1805  } else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
1806  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Found TTree " << obj->GetName() << endmsg; }
1807  TTree* mytree = dynamic_cast<TTree*>( obj );
1808  int nentries = (int)mytree->GetEntries();
1809  mytree->SetBranchStatus( "*", 1 );
1810 
1811  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Dumping TTree " << nentries << " entries" << endmsg; }
1812  target->cd();
1813  mytree->CloneTree();
1814 
1815  } else {
1816  target->cd();
1817  obj->Write( key->GetName() );
1818  }
1819  }
1820  }
1821 }
1822 
1823 bool THistSvc::findStream( const std::string& id, std::string& stream, std::string& rem, TFile*& file ) const {
1824  auto pos = id.find( "/" );
1825 
1826  if ( pos == std::string::npos ) {
1827  // no "/" in id
1828  stream = "temp";
1829  rem = id;
1830  } else if ( pos != 0 ) {
1831  // id does not start with "/"
1832  stream = "temp";
1833  rem = id;
1834  } else {
1835  // id starts with "/"
1836 
1837  auto pos2 = id.find( "/", pos + 1 );
1838 
1839  if ( pos2 == std::string::npos ) {
1840  // need at least 2 "/" in format "/STREAM/name" or "/STREAM/dir/name"
1841  error() << "badly formed Hist/Tree id: \"" << id << "\"" << endmsg;
1842  return false;
1843  }
1844  parseString( id, stream, rem );
1845  }
1846 
1847  if ( stream == "temp" ) {
1848  file = nullptr;
1849  return true;
1850  }
1851 
1852  auto itr = m_files.find( stream );
1853  file = ( itr != m_files.end() ? itr->second.first : nullptr );
1854  if ( !file ) { warning() << "no stream \"" << stream << "\" associated with id: \"" << id << "\"" << endmsg; }
1855 
1856  return true;
1857 }
1858 
1860  auto pos = id.find( "/" );
1861 
1862  if ( pos == std::string::npos ) {
1863  root.clear();
1864  rem = id;
1865  } else if ( pos == 0 ) {
1866  parseString( id.substr( 1 ), root, rem );
1867  } else {
1868  root = id.substr( 0, pos );
1869  rem = id.substr( pos + 1 );
1870  }
1871 }
1872 
1875  debug() << "Delaying connection of Input Files until Initialize"
1876  << ". now in " << FSMState() << endmsg;
1877 
1878  m_delayConnect = true;
1879  } else {
1880  debug() << "Now connecting of Input Files" << endmsg;
1881 
1883 
1884  for ( const auto& itr : m_inputfile.value() ) {
1885  if ( m_alreadyConnectedInFiles.end() != m_alreadyConnectedInFiles.find( itr ) ) { continue; }
1886  if ( connect( itr ).isFailure() ) {
1887  sc = StatusCode::FAILURE;
1888  } else {
1890  }
1891  }
1892 
1893  if ( !sc.isSuccess() ) { throw GaudiException( "Problem connecting inputfile !!", name(), StatusCode::FAILURE ); }
1894  }
1895 }
1896 
1899  debug() << "Delaying connection of Output Files until Initialize"
1900  << ". now in " << FSMState() << endmsg;
1901  m_delayConnect = true;
1902  } else {
1904  for ( const auto& itr : m_outputfile.value() ) {
1905  if ( m_alreadyConnectedOutFiles.end() != m_alreadyConnectedOutFiles.find( itr ) ) { continue; }
1906  if ( connect( itr ).isFailure() ) {
1907  sc = StatusCode::FAILURE;
1908  } else {
1910  }
1911  }
1912 
1913  if ( !sc.isSuccess() ) { throw GaudiException( "Problem connecting outputfile !!", name(), StatusCode::FAILURE ); }
1914  }
1915 }
1916 
1917 void THistSvc::copyFileLayout( TDirectory* destination, TDirectory* source ) {
1918  if ( msgLevel( MSG::DEBUG ) ) {
1919  debug() << "copyFileLayout() to destination path: " << destination->GetPath() << endmsg;
1920  }
1921 
1922  // strip out URLs
1923  TString path( (char*)strstr( destination->GetPath(), ":" ) );
1924  path.Remove( 0, 2 );
1925 
1926  source->cd( path );
1927  TDirectory* current_source_dir = gDirectory;
1928 
1929  // loop over all keys in this directory
1930  TList* key_list = current_source_dir->GetListOfKeys();
1931  int n = key_list->GetEntries();
1932  for ( int j = 0; j < n; ++j ) {
1933  TKey* k = (TKey*)key_list->At( j );
1934  const std::string source_pathname = current_source_dir->GetPath() + std::string( "/" ) + k->GetName();
1935  TObject* o = source->Get( source_pathname.c_str() );
1936 
1937  if ( o && o->IsA()->InheritsFrom( "TDirectory" ) ) {
1938  if ( msgLevel( MSG::VERBOSE ) ) { verbose() << " subdir [" << o->GetName() << "]..." << endmsg; }
1939  destination->cd();
1940  // Create directory if it does not exist yet
1941  TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() );
1942  if ( destination_dir == nullptr ) destination_dir = destination->GetDirectory( o->GetName() );
1943  copyFileLayout( destination_dir, source );
1944  }
1945  } // loop over keys
1946  return;
1947 }
1948 
1949 size_t THistSvc::findHistID( const std::string& id, const THistID*& hid, const size_t& index ) const {
1950  GlobalDirectoryRestore restore( m_svcMut );
1951 
1952  std::string idr( id );
1953  removeDoubleSlash( idr );
1954 
1955  hid = 0;
1956 
1957  if ( idr.find( "/" ) == 0 ) {
1958  // fully specified name, starts with "/"
1959  auto itr = m_uids.find( idr );
1960  if ( itr == m_uids.end() ) {
1961  // no matches found
1962  return 0;
1963  } else {
1964  // one or more matches found (clones).
1965  if ( index >= itr->second->size() ) {
1966  error() << "no index " << index << " found for Hist " << idr << endmsg;
1967  return 0;
1968  }
1969  hid = &( itr->second->at( index ) );
1970  return 1;
1971  }
1972  } else {
1973  // name not fully specified.
1974  auto mitr = m_ids.equal_range( idr );
1975  if ( mitr.first == mitr.second ) {
1976  // not found
1977  return 0;
1978  } else if ( distance( mitr.first, mitr.second ) == 1 ) {
1979  // one found
1980  if ( index >= mitr.first->second->size() ) {
1981  error() << "no index " << index << " found for Hist " << idr << endmsg;
1982  return 0;
1983  }
1984  hid = &( mitr.first->second->at( 0 ) );
1985  return 1;
1986  } else {
1987  // multiple matches
1988  hid = &( mitr.first->second->at( 0 ) );
1989  return distance( mitr.first, mitr.second );
1990  }
1991  }
1992 }
1993 
1994 void THistSvc::dump() const {
1995  std::ostringstream ost;
1996 
1997  // list< vector<THistID> >
1998  ost << "m_hlist: size: " << m_hlist.size() << "\n";
1999  for ( auto& vh : m_hlist ) {
2000  ost << " - " << vh->at( 0 ) << " :: [" << vh << "] " << vh->size() << " {";
2001  for ( auto& e : *vh ) {
2002  TObject* o = e.obj;
2003  ost << "[" << o << "]";
2004  }
2005  ost << "}\n";
2006  }
2007 
2008  // map uid -> vector<THistID>*
2009  ost << "\n"
2010  << "m_uids: " << m_uids.size() << "\n";
2011  for ( auto& e : m_uids ) { ost << " - " << e.first << " [" << e.second << "]" << std::endl; }
2012 
2013  // multimap id -> vector<THistID>*
2014  ost << "\n"
2015  << "m_ids: " << m_ids.size() << "\n";
2016  for ( auto& e : m_ids ) { ost << " - " << e.first << " [" << e.second << "]" << std::endl; }
2017 
2018  // map TObject* -> THistID*
2019  ost << "\n"
2020  << "m_tobjs: " << m_tobjs.size() << "\n";
2021  for ( auto& e : m_tobjs ) {
2022  TObject* o = e.first;
2023  THistID& i = e.second.first->at( e.second.second );
2024  ost << " - " << o << " -> " << i << std::endl;
2025  }
2026 
2027  debug() << "dumping THistSvc contents\n" << ost.str() << endmsg;
2028 }
2029 
2030 StatusCode THistSvc::merge( const THistID& hid ) { return merge( hid.id ); }
2031 
2033  const std::string& name = vh->at( 0 ).id;
2034  if ( vh->size() == 1 ) {
2035  debug() << "merge: id: \"" << name << "\" is size 1. nothing to do" << endmsg;
2036  return StatusCode::SUCCESS;
2037  }
2038 
2039  if ( vh->at( 0 ).type != ObjectType::TH1 ) {
2040  error() << "merge: id \"" << name << "\" is not a THn. Cannot merge" << endmsg;
2041  return StatusCode::FAILURE;
2042  }
2043 
2044  TList* l = new TList();
2045  for ( size_t i = 1; i < vh->size(); ++i ) {
2046  debug() << "merge: id: \"" << name << "\" (" << vh->at( i ).obj << ") adding index " << i << endmsg;
2047  l->Add( vh->at( i ).obj );
2048  }
2049 
2050  TH1* t0 = dynamic_cast<TH1*>( vh->at( 0 ).obj );
2051  if ( t0 == 0 ) {
2052  error() << "merge: could not dcast " << name << "(" << t0 << ") index " << 0 << " to TH1" << endmsg;
2053  return StatusCode::FAILURE;
2054  }
2055 
2056  Long64_t n = t0->Merge( l );
2057 
2058  debug() << "merge: id: \"" << name << "\" merged " << n << " entries" << endmsg;
2059 
2060  for ( size_t i = 1; i < vh->size(); ++i ) {
2061  TH1* th = dynamic_cast<TH1*>( vh->at( i ).obj );
2062  if ( th != 0 ) {
2063  debug() << "clearing index " << i << "(" << th << ")" << endmsg;
2064  th->SetDirectory( nullptr );
2065  th->Reset();
2066  } else {
2067  error() << "merge: could not dcast " << name << " index " << i << " to TH1" << endmsg;
2068  return StatusCode::FAILURE;
2069  }
2070  }
2071  return StatusCode::SUCCESS;
2072 }
2073 
2075  if ( fa->tech() != Io::ROOT ) {
2076  // This should never happen
2077  return StatusCode::SUCCESS;
2078  }
2079 
2080  if ( fa->desc() != "HIST" ) { return StatusCode::SUCCESS; }
2081 
2082  p_incSvc->fireIncident( FileIncident( caller, "OpenHistFile", fa->name() ) );
2083 
2084  if ( fa->flags().isRead() ) {
2085  p_incSvc->fireIncident( FileIncident( caller, "BeginHistFile", fa->name() ) );
2086  } else if ( fa->flags().isWrite() ) {
2087  p_incSvc->fireIncident( FileIncident( caller, IncidentType::BeginOutputFile, fa->name() ) );
2088  } else {
2089  // for Io::RW
2090  p_incSvc->fireIncident( FileIncident( caller, IncidentType::BeginOutputFile, fa->name() ) );
2091  }
2092 
2093  return StatusCode::SUCCESS;
2094 }
2095 
2097  if ( fa->tech() != Io::ROOT ) {
2098  // This should never happen
2099  return StatusCode::SUCCESS;
2100  }
2101 
2102  if ( fa->desc() != "HIST" ) { return StatusCode::SUCCESS; }
2103 
2104  if ( fa->flags().isRead() ) {
2105  p_incSvc->fireIncident( FileIncident( caller, IncidentType::FailInputFile, fa->name() ) );
2106  } else if ( fa->flags().isWrite() ) {
2107  p_incSvc->fireIncident( FileIncident( caller, IncidentType::FailOutputFile, fa->name() ) );
2108  } else {
2109  // for Io::RW
2110  p_incSvc->fireIncident( FileIncident( caller, "FailRWFile", fa->name() ) );
2111  }
2112 
2113  return StatusCode::SUCCESS;
2114 }
IOTest.evt
evt
Definition: IOTest.py:107
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_signaledStop
bool m_signaledStop
Definition: THistSvc.h:392
THistSvc::m_delayConnect
bool m_delayConnect
Definition: THistSvc.h:393
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:1917
GaudiException.h
gaudirun.s
string s
Definition: gaudirun.py:346
THistSvc::m_curstream
std::string m_curstream
Definition: THistSvc.h:397
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:1442
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:1533
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:1873
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:1457
THistSvc::rootOpenAction
StatusCode rootOpenAction(FILEMGR_CALLBACK_ARGS)
Definition: THistSvc.cpp:2074
IIoComponentMgr::IoMode::Type
Type
Definition: IIoComponentMgr.h:41
THistSvc::setupOutputFile
void setupOutputFile()
call-back method to handle output stream property
Definition: THistSvc.cpp:1897
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:1756
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:2096
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:1859
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:1823
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:239
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:1734
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:394
genconfuser.verbose
verbose
Definition: genconfuser.py:28
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:1772
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
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:1448
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:1558
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:395
THistSvc::readTree
TTree * readTree(const std::string &name) const
Definition: THistSvc.cpp:1461
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:1463
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:1340
THistSvc::m_svcMut
THistSvcMutex_t m_svcMut
Definition: THistSvc.h:399
THistSvc::findHistID
size_t findHistID(const std::string &id, const THistID *&hid, const size_t &index=0) const
Definition: THistSvc.cpp:1949
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
IEventProcessor.h
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:1994
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:1776