| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

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

- File List
- File Members

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