| The Gaudi Framework v29r0 (ff2e7097)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
9 #include "GaudiKernel/AttribStringParser.h"
10 #include "GaudiKernel/FileIncident.h"
11 #include "GaudiKernel/GaudiException.h"
12 #include "GaudiKernel/IEventProcessor.h"
13 #include "GaudiKernel/IFileMgr.h"
14 #include "GaudiKernel/IIncidentSvc.h"
15 #include "GaudiKernel/IIoComponentMgr.h"
16 #include "GaudiKernel/IJobOptionsSvc.h"
17 #include "GaudiKernel/ISvcLocator.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
34 DECLARE_COMPONENT( THistSvc )
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
61 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc ) : base_class( name, svc )
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
70 StatusCode THistSvc::initialize()
71 {
72 GlobalDirectoryRestore restore;
73
74 StatusCode status = Service::initialize();
75
76 if ( status.isFailure() ) {
77 error() << "initializing service" << endmsg;
78 return status;
79 }
80
81 StatusCode st( StatusCode::SUCCESS );
82
83 try {
84 setupOutputFile( m_outputfile );
85 } catch ( GaudiException& err ) {
86 error() << "Caught: " << err << endmsg;
87 st = StatusCode::FAILURE;
88 }
89
90 try {
91 setupInputFile( m_inputfile );
92 } catch ( GaudiException& err ) {
93 error() << "Caught: " << err << endmsg;
94 st = StatusCode::FAILURE;
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() ) {
137 setupInputFile( m_inputfile );
138 }
139 if ( !m_outputfile.value().empty() ) {
140 setupOutputFile( m_outputfile );
141 }
142
143 m_delayConnect = false;
144 }
145 m_alreadyConnectedOutFiles.clear();
146 m_alreadyConnectedInFiles.clear();
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 =
164 ( reg.second.second == THistSvc::READ ? IIoComponentMgr::IoMode::READ : IIoComponentMgr::IoMode::WRITE );
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
189 StatusCode THistSvc::reinitialize()
190 {
191
192 GlobalDirectoryRestore restore;
193 warning() << "reinitialize not implemented" << endmsg;
194 return StatusCode::SUCCESS;
195 }
196
197 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
198
199 StatusCode THistSvc::finalize()
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
332 m_sharedFiles.clear();
333 m_fileStreams.clear();
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
795 StatusCode THistSvc::deReg( TObject* obj )
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
833 StatusCode THistSvc::deReg( const std::string& id )
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
848 StatusCode THistSvc::regHist( const std::string& id )
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
869 StatusCode THistSvc::regTree( const std::string& id )
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
889 StatusCode THistSvc::regGraph( const std::string& id )
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
928 std::vector<std::string> THistSvc::getHists() const
929 {
930
931 std::vector<std::string> names;
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
943 std::vector<std::string> THistSvc::getTrees() const
944 {
945
946 std::vector<std::string> names;
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
958 std::vector<std::string> THistSvc::getGraphs() const
959 {
960
961 std::vector<std::string> names;
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
1041 void THistSvc::setupCompressionLevel( Gaudi::Details::PropertyBase& /* cl */ )
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
1050 void THistSvc::setupInputFile( Gaudi::Details::PropertyBase& /*m_inputfile*/ )
1051 {
1052
1053 if ( FSMState() < Gaudi::StateMachine::CONFIGURED || !m_okToConnect ) {
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
1063 StatusCode sc = StatusCode::SUCCESS;
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 {
1070 m_alreadyConnectedInFiles.insert( itr );
1071 }
1072 }
1073
1074 if ( !sc.isSuccess() ) {
1075 throw GaudiException( "Problem connecting inputfile !!", name(), StatusCode::FAILURE );
1076 }
1077 }
1078 }
1079
1080 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
1081
1082 void THistSvc::setupOutputFile( Gaudi::Details::PropertyBase& /*m_outputfile*/ )
1083 {
1084 if ( FSMState() < Gaudi::StateMachine::CONFIGURED || !m_okToConnect ) {
1085 debug() << "Delaying connection of Input Files until Initialize"
1086 << ". now in " << FSMState() << endmsg;
1087 m_delayConnect = true;
1088 } else {
1089
1090 StatusCode sc = StatusCode::SUCCESS;
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 {
1096 m_alreadyConnectedOutFiles.insert( itr );
1097 }
1098 }
1099
1100 if ( !sc.isSuccess() ) {
1101 throw GaudiException( "Problem connecting outputfile !!", name(), StatusCode::FAILURE );
1102 }
1103 }
1104 }
1105
1106 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
1107
1108 void THistSvc::updateFiles()
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
1154 auto sitr = std::find_if( std::begin( m_fileStreams ), std::end( m_fileStreams ),
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
1188 StatusCode THistSvc::write()
1189 {
1190
1191 updateFiles();
1192
1193 std::for_each( m_files.begin(), m_files.end(), []( std::pair<const std::string, std::pair<TFile*, Mode>>& i ) {
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
1217 StatusCode THistSvc::connect( const std::string& ident )
1218 {
1219
1220 auto loc = ident.find( " " );
1221 string stream = ident.substr( 0, loc );
1222 char typ( 0 );
1223 typedef std::pair<std::string, std::string> Prop;
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
1439 std::string THistSvc::dirname( std::string& dir ) const
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
1459 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore()
1460 {
1461 m_gd = gDirectory;
1462 m_gf = gFile;
1463 m_ge = gErrorIgnoreLevel;
1464 }
1465
1466 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore()
1467 {
1468 gDirectory = m_gd;
1469 gFile = m_gf;
1470 gErrorIgnoreLevel = m_ge;
1471 }
1472
1473 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
1474
1475 void THistSvc::removeDoubleSlash( std::string& id ) const
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 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
1643 StatusCode THistSvc::io_reinit()
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
1741 StatusCode THistSvc::rootOpenAction( const Io::FileAttr* fa, const std::string& caller )
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
1769 StatusCode THistSvc::rootOpenErrAction( const Io::FileAttr* fa, const std::string& caller )
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 }
Gaudi::Utils::AttribStringParser
Parse attribute strings allowing iteration over the various attributes.
Definition: AttribStringParser.h:32
IIoComponentMgr::io_retrieve
virtual StatusCode io_retrieve(IIoComponent *iocomponent, std::string &fname)=0
: retrieve the new filename for a given IIoComponent and
THistSvc::THistID
Definition: THistSvc.h:96
THistSvc::m_delayConnect
bool m_delayConnect
Definition: THistSvc.h:188
IIoComponentMgr
Definition: IIoComponentMgr.h:22
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:64
StatusCode::SUCCESS
Definition: StatusCode.h:31
IEventProcessor::stopRun
virtual StatusCode stopRun()=0
Schedule a stop of the current event processing.
THistSvc::getGraph
StatusCode getGraph(const std::string &name, TGraph *&) const override
Definition: THistSvc.cpp:954
FileIncident
This class is the FileIncident.
Definition: FileIncident.h:17
std::string::empty
T empty(T...args)
THistSvc::initialize
StatusCode initialize() override
Definition: THistSvc.cpp:70
Io::ROOT
Definition: IFileMgr.h:157
GaudiException
Define general base for Gaudi exception.
Definition: GaudiException.h:22
IFileMgr::open
virtual Io::open_t open(const Io::IoTech &, const std::string &caller, const std::string &fname, const Io::IoFlags &, Io::Fd &, void *&, const std::string &desc, const bool shared=false)=0
ISvcLocator
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
IEventProcessor.h
Service::name
const std::string & name() const override
Retrieve name of the service.
Definition: Service.cpp:289
Gaudi::StateMachine::CONFIGURED
Definition: StateMachine.h:16
std::placeholders
GaudiPython.HistoUtils.path
path
Definition: HistoUtils.py:895
gaudiComponentHelp.name
name
Definition: gaudiComponentHelp.py:32
StatusCode::FAILURE
Definition: StatusCode.h:31
THistSvc::m_curstream
std::string m_curstream
Definition: THistSvc.h:190
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:174
Io::OPEN
Definition: IFileMgr.h:284
CommonMessagingBase::info
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Definition: CommonMessaging.h:117
THistSvc::THistID::file
TFile * file
Definition: THistSvc.h:100
THistSvc::getGraphs
std::vector< std::string > getGraphs() const override
Definition: THistSvc.cpp:958
FileIncident.h
This file contains the class definition for the FileIncident class.
THistSvc::exists
bool exists(const std::string &name) const override
Definition: THistSvc.cpp:1552
THistSvc::p_incSvc
IIncidentSvc * p_incSvc
Definition: THistSvc.h:192
StatusCode::isSuccess
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:75
THistSvc::findStream
bool findStream(const std::string &name, std::string &root, std::string &rem, TFile *&file) const
Definition: THistSvc.cpp:985
THistSvc::getTHists
StatusCode getTHists(TDirectory *td, TList &, bool recurse=false) const override
Definition: THistSvc.cpp:393
THistSvc::browseTDir
bool browseTDir(TDirectory *dir) const
Definition: THistSvc.cpp:344
THistSvc::APPEND
Definition: THistSvc.h:94
std::string::rfind
T rfind(T...args)
std::to_string
T to_string(T...args)
CommonMessagingBase::verbose
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Definition: CommonMessaging.h:123
MSG::DEBUG
Definition: IMessageSvc.h:16
std::endl
T endl(T...args)
std
STL namespace.
THistSvc::signaledStop
bool signaledStop
Definition: THistSvc.h:187
std::vector::end
T end(T...args)
THistSvc::rootOpenAction
StatusCode rootOpenAction(FILEMGR_CALLBACK_ARGS)
Definition: THistSvc.cpp:1741
THistSvc::copyFileLayout
void copyFileLayout(TDirectory *, TDirectory *)
helper function to recursively copy the layout of a TFile into a new TFile
Definition: THistSvc.cpp:1609
graphanalysis.filename
string filename
Definition: graphanalysis.py:117
Io::EXCL
Definition: IFileMgr.h:32
THistSvc::changeDir
TDirectory * changeDir(const THistSvc::THistID &hid) const
Definition: THistSvc.cpp:1411
std::multimap::lower_bound
T lower_bound(T...args)
std::remove
T remove(T...args)
MSG::VERBOSE
Definition: IMessageSvc.h:16
THistSvc::UPDATE
Definition: THistSvc.h:94
THistSvc::setupCompressionLevel
void setupCompressionLevel(Gaudi::Details::PropertyBase &cmp)
Definition: THistSvc.cpp:1041
std::map
STL class.
StatusCode::isFailure
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
THistSvc::m_tobjs
objMap m_tobjs
Definition: THistSvc.h:180
THistSvc::m_outputfile
Gaudi::Property< std::vector< std::string > > m_outputfile
Definition: THistSvc.h:160
CommonMessagingBase::err
MsgStream & err() const
shortcut for the method msgStream(MSG::ERROR)
Definition: CommonMessaging.h:108
THistSvc::getHists
std::vector< std::string > getHists() const override
Definition: THistSvc.cpp:928
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:33
THistSvc::write
StatusCode write()
Definition: THistSvc.cpp:1188
gaudirun.opts
opts
Definition: gaudirun.py:244
THistSvc::SHARE
Definition: THistSvc.h:94
std::string
STL class.
IFileMgr::regAction
virtual StatusCode regAction(Io::bfcn_action_t, const Io::Action &, const std::string &d="")=0
IIoComponentMgr::IoMode::Type
Type
Definition: IIoComponentMgr.h:32
GaudiPluginService.cpluginsvc.n
n
Definition: cpluginsvc.py:228
Io::FileAttr::name
const std::string & name() const
Definition: IFileMgr.h:189
THistSvc::m_autoSave
Gaudi::Property< int > m_autoSave
Definition: THistSvc.h:154
std::vector::push_back
T push_back(T...args)
CommonMessagingBase::error
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
Definition: CommonMessaging.h:111
THistSvc::THistID::id
std::string id
Definition: THistSvc.h:97
IIncidentSvc::fireIncident
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
CommonMessagingBase::warning
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
Definition: CommonMessaging.h:114
Io::FileAttr::desc
const std::string & desc() const
Definition: IFileMgr.h:190
THistSvc::m_inputfile
Gaudi::Property< std::vector< std::string > > m_inputfile
Definition: THistSvc.h:161
THistSvc::dirname
std::string dirname(std::string &dir) const
Definition: THistSvc.cpp:1439
Io::WRITE
Definition: IFileMgr.h:28
THistSvc::readTree
StatusCode readTree(const std::string &name, TTree *&) const
Definition: THistSvc.cpp:981
IIncidentSvc.h
HiveAlgSequencer.h
h
Definition: HiveAlgSequencer.py:24
IIoComponentMgr.h
StatusCode
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore
GlobalDirectoryRestore()
Definition: THistSvc.cpp:1459
THistSvc::m_okToConnect
bool m_okToConnect
Definition: THistSvc.h:188
GaudiException.h
THistSvc::m_print
Gaudi::Property< bool > m_print
Definition: THistSvc.h:156
std::strcmp
T strcmp(T...args)
Io::IoFlags::isWrite
bool isWrite() const
Definition: IFileMgr.h:57
THistSvc::handle
void handle(const Incident &) override
Definition: THistSvc.cpp:1561
THistSvc::m_maxFileSize
Gaudi::Property< int > m_maxFileSize
Definition: THistSvc.h:157
std::string::erase
T erase(T...args)
Io::READ
Definition: IFileMgr.h:27
THistSvc::getTree
StatusCode getTree(const std::string &name, TTree *&) const override
Definition: THistSvc.cpp:939
std::make_pair
T make_pair(T...args)
THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore
~GlobalDirectoryRestore()
Definition: THistSvc.cpp:1466
THistSvc::rootOpenErrAction
StatusCode rootOpenErrAction(FILEMGR_CALLBACK_ARGS)
Definition: THistSvc.cpp:1769
Gaudi::Details::PropertyBase
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
THistSvc::m_compressionLevel
Gaudi::Property< int > m_compressionLevel
Definition: THistSvc.h:159
THistSvc::parseString
void parseString(const std::string &id, std::string &root, std::string &rem) const
Definition: THistSvc.cpp:1024
std::set::clear
T clear(T...args)
THistSvc::getHist_i
StatusCode getHist_i(const std::string &name, T *&hist, bool quiet=false) const
Definition: THistSvc.icc:142
THistSvc::finalize
StatusCode finalize() override
Definition: THistSvc.cpp:199
std::move
T move(T...args)
THistSvc::regHist
StatusCode regHist(const std::string &name) override
Definition: THistSvc.cpp:848
THistSvc::Mode
Mode
Definition: THistSvc.h:94
std::pair
Gaudi::Units::nm
constexpr double nm
Definition: SystemOfUnits.h:83
std::set::insert
T insert(T...args)
ReadAndWriteWhiteBoard.dst
dst
Definition: ReadAndWriteWhiteBoard.py:17
THistSvc::getTTrees
StatusCode getTTrees(TDirectory *td, TList &, bool recurse=false) const override
Definition: THistSvc.cpp:486
std::string::find
T find(T...args)
Io::APPEND
Definition: IFileMgr.h:35
std::string::length
T length(T...args)
THistSvc::THistID::obj
TObject * obj
Definition: THistSvc.h:99
std::vector
STL class.
IInterface::release
virtual unsigned long release()=0
Release Interface instance.
THistSvc::reinitialize
StatusCode reinitialize() override
Definition: THistSvc.cpp:189
THistSvc::regHist_i
StatusCode regHist_i(T *hist, const std::string &name)
Definition: THistSvc.icc:17
Gaudi::Functional::operator()
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
CommonMessagingBase::debug
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Definition: CommonMessaging.h:120
THistSvc::m_uids
uidMap m_uids
Definition: THistSvc.h:178
Io::FileAttr::tech
IoTech tech() const
Definition: IFileMgr.h:191
std::vector::begin
T begin(T...args)
THistSvc::readHist_i
StatusCode readHist_i(const std::string &name, T *&hist) const
Definition: THistSvc.icc:242
Io::CREATE
Definition: IFileMgr.h:31
std::back_inserter
T back_inserter(T...args)
Property.h
std::string::c_str
T c_str(T...args)
Incident
Base class for all Incidents (computing events).
Definition: Incident.h:17
IIncidentSvc::addListener
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
THistSvc.h
THistSvc::m_files
std::map< std::string, std::pair< TFile *, Mode > > m_files
Definition: THistSvc.h:182
std::multimap::emplace
T emplace(T...args)
gaudirun.s
string s
Definition: gaudirun.py:253
Service::FSMState
Gaudi::StateMachine::State FSMState() const override
Definition: Service.h:54
THistSvc::READ
Definition: THistSvc.h:94
AttribStringParser.h
CommonMessaging
Definition: CommonMessaging.h:62
THistSvc::connect
StatusCode connect(const std::string &)
Definition: THistSvc.cpp:1217
IEventProcessor
The IEventProcessor is the interface to process events.
Definition: IEventProcessor.h:16
THistSvc::readHist
StatusCode readHist(const std::string &name, TH1 *&) const
Definition: THistSvc.cpp:969
IIoComponentMgr::io_register
virtual StatusCode io_register(IIoComponent *iocomponent)=0
: allow a IIoComponent to register itself with this manager so appropriate actions can be taken when ...
THistSvc::m_ids
idMap m_ids
Definition: THistSvc.h:179
THistSvc::p_fileMgr
IFileMgr * p_fileMgr
Definition: THistSvc.h:193
Io::IoFlags::isRead
bool isRead() const
Definition: IFileMgr.h:56
THistSvc::m_alreadyConnectedOutFiles
std::set< std::string > m_alreadyConnectedOutFiles
list of already connected files.
Definition: THistSvc.h:171
std::strstr
T strstr(T...args)
std::string::substr
T substr(T...args)
gaudiComponentHelp.root
root
Definition: gaudiComponentHelp.py:18
IFileMgr.h
THistSvc::deReg
StatusCode deReg(TObject *obj) override
Definition: THistSvc.cpp:795
THistSvc::regTree
StatusCode regTree(const std::string &name) override
Definition: THistSvc.cpp:869
std::abort
T abort(T...args)
THistSvc::getHist
StatusCode getHist(const std::string &name, TH1 *&) const override
Definition: THistSvc.cpp:916
THistSvc::m_sharedFiles
std::map< std::string, std::string > m_sharedFiles
Definition: THistSvc.h:185
Service::service
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn&#39;t already exist.
Definition: Service.h:85
THistSvc::getTrees
std::vector< std::string > getTrees() const override
Definition: THistSvc.cpp:943
IIoComponentMgr::IoMode::WRITE
Definition: IIoComponentMgr.h:32
THistSvc::WRITE
Definition: THistSvc.h:94
StatusCode::ignore
void ignore() const
Definition: StatusCode.h:109
CommonMessagingBase::fatal
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
Definition: CommonMessaging.h:105
THistSvc::m_alreadyConnectedInFiles
std::set< std::string > m_alreadyConnectedInFiles
list of already connected files.
Definition: THistSvc.h:167
MSG::INFO
Definition: IMessageSvc.h:16
THistSvc::setupInputFile
void setupInputFile(Gaudi::Details::PropertyBase &inputfile)
call-back method to handle input stream property
Definition: THistSvc.cpp:1050
THistSvc::setupOutputFile
void setupOutputFile(Gaudi::Details::PropertyBase &outputfile)
call-back method to handle output stream property
Definition: THistSvc.cpp:1082
CommonMessagingBase::msgLevel
MSG::Level msgLevel() const
get the output level from the embedded MsgStream
Definition: CommonMessaging.h:129
std::for_each
T for_each(T...args)
THistSvc::regGraph
StatusCode regGraph(const std::string &name) override
Definition: THistSvc.cpp:889
THistSvc::m_autoFlush
Gaudi::Property< int > m_autoFlush
Definition: THistSvc.h:155
THistSvc::THistSvc
THistSvc(const std::string &name, ISvcLocator *svc)
Definition: THistSvc.cpp:61
Io::FileAttr::flags
IoFlags flags() const
Definition: IFileMgr.h:192
std::cerr
IIoComponentMgr::IoMode::READ
Definition: IIoComponentMgr.h:32
std::stoi
T stoi(T...args)
THistSvc::io_reinit
StatusCode io_reinit() override
callback method to reinitialize the internal state of the component for I/O purposes (e...
Definition: THistSvc.cpp:1643
ISvcLocator.h
Io::OPEN_ERR
Definition: IFileMgr.h:284
std::multimap::equal_range
T equal_range(T...args)
THistSvc::GlobalDirectoryRestore
Definition: THistSvc.h:82
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
Gaudi::Units::pi
constexpr double pi
Definition: PhysicalConstants.h:47
IIncidentSvc
The interface implemented by the IncidentSvc service.
Definition: IIncidentSvc.h:23
THistSvc::m_fileStreams
streamMap m_fileStreams
Definition: THistSvc.h:183
THistSvc::MergeRootFile
void MergeRootFile(TDirectory *target, TDirectory *source)
Definition: THistSvc.cpp:1485
IOTest.evt
evt
Definition: IOTest.py:96
THistSvc::removeDoubleSlash
void removeDoubleSlash(std::string &) const
Definition: THistSvc.cpp:1475
std::vector::reserve
T reserve(T...args)
THistSvc
Definition: THistSvc.h:25
Gaudi.Configuration.log
log
Definition: Configuration.py:13
THistSvc::updateFiles
void updateFiles()
Definition: THistSvc.cpp:1108
IJobOptionsSvc.h
std::vector::emplace_back
T emplace_back(T...args)
Io::FileAttr
Definition: IFileMgr.h:173
IFileMgr::close
virtual Io::close_t close(const Io::Fd, const std::string &caller)=0