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