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