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