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