| The Gaudi Framework v27r1

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