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