Gaudi Framework, version v23r9

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

Generated at Thu Jul 18 2013 12:18:05 for Gaudi Framework, version v23r9 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004