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