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