00001 #ifdef __ICC
00002
00003
00004 #pragma warning(disable:2259)
00005 #endif
00006
00007 #include "THistSvc.h"
00008
00009 #include "GaudiKernel/SvcFactory.h"
00010 #include "GaudiKernel/ISvcLocator.h"
00011 #include "GaudiKernel/Tokenizer.h"
00012 #include "GaudiKernel/GaudiException.h"
00013 #include "GaudiKernel/Property.h"
00014 #include "GaudiKernel/IIncidentSvc.h"
00015 #include "GaudiKernel/FileIncident.h"
00016 #include "GaudiKernel/IEventProcessor.h"
00017 #include "GaudiKernel/IJobOptionsSvc.h"
00018 #include "GaudiKernel/IIoComponentMgr.h"
00019
00020
00021 #include "TROOT.h"
00022 #include "TFile.h"
00023 #include "TDirectory.h"
00024 #include "TKey.h"
00025 #include "TError.h"
00026 #include "TGraph.h"
00027
00028 #include <sstream>
00029 #include <streambuf>
00030 #include <cstdio>
00031
00032 using namespace std;
00033
00034
00035 DECLARE_SERVICE_FACTORY(THistSvc)
00036
00037 inline void toupper(std::string &s)
00038 {
00039 std::transform(s.begin(), s.end(), s.begin(),
00040 (int(*)(int)) toupper);
00041 }
00042
00043
00044
00045
00046 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc )
00047 : base_class(name, svc), m_log(msgSvc(), name ), signaledStop(false) {
00048
00049 declareProperty ("AutoSave", m_autoSave=0 );
00050 declareProperty ("AutoFlush", m_autoFlush=0 );
00051 declareProperty ("PrintAll", m_print=false);
00052 declareProperty ("MaxFileSize", m_maxFileSize=10240,
00053 "maximum file size in MB. if exceeded, will cause an abort");
00054 declareProperty ("CompressionLevel", m_compressionLevel=1 )->declareUpdateHandler( &THistSvc::setupCompressionLevel, this );
00055 declareProperty ("Output", m_outputfile )->declareUpdateHandler( &THistSvc::setupOutputFile, this );
00056 declareProperty ("Input", m_inputfile )->declareUpdateHandler ( &THistSvc::setupInputFile, this );
00057
00058
00059 }
00060
00061
00062
00063 THistSvc::~THistSvc() {
00064
00065 }
00066
00067
00068
00069 StatusCode
00070 THistSvc::initialize() {
00071 GlobalDirectoryRestore restore;
00072
00073 m_alreadyConnectedOutFiles.clear();
00074 m_alreadyConnectedInFiles.clear();
00075
00076
00077
00078
00079 IJobOptionsSvc* jos(0);
00080 if( serviceLocator()->service( "JobOptionsSvc", jos, true ).isSuccess() ) {
00081 const std::vector<const Property*> *props = jos->getProperties( name() );
00082
00083 if (props != NULL) {
00084 for ( std::vector<const Property*>::const_iterator cur = props->begin();
00085 cur != props->end(); cur++) {
00086 if ( (*cur)->name() == "OutputLevel" ) {
00087 setProperty( **cur ).ignore();
00088 m_log.setLevel( m_outputLevel.value() );
00089 break;
00090 }
00091 }
00092 }
00093 }
00094
00095
00096 StatusCode status = Service::initialize();
00097 m_log.setLevel( m_outputLevel.value() );
00098
00099 if (status.isFailure()) {
00100 m_log << MSG::ERROR << "initializing service" << endmsg;
00101 return status;
00102 }
00103
00104 vector<string>::const_iterator itr;
00105 StatusCode st(StatusCode::SUCCESS);
00106
00107 try {
00108 setupOutputFile( m_outputfile );
00109 } catch ( GaudiException& err ) {
00110 m_log << MSG::ERROR
00111 << "Caught: " << err << endmsg;
00112 st = StatusCode::FAILURE;
00113 }
00114
00115 try {
00116 setupInputFile( m_inputfile );
00117 } catch ( GaudiException& err ) {
00118 m_log << MSG::ERROR
00119 << "Caught: " << err << endmsg;
00120 st = StatusCode::FAILURE;
00121 }
00122
00123
00124 if ( 0 == gROOT ) {
00125 static TROOT root("root","ROOT I/O");
00126
00127 } else {
00128 if (m_log.level() <= MSG::VERBOSE)
00129 m_log << MSG::VERBOSE << "ROOT already initialized, debug = "
00130 << gDebug<< endmsg;
00131 }
00132
00133 IIncidentSvc* p_incSvc(0);
00134
00135 if (service("IncidentSvc", p_incSvc, true).isFailure()) {
00136 m_log << MSG::ERROR << "unable to get the IncidentSvc" << endmsg;
00137 st = StatusCode::FAILURE;
00138 } else {
00139 p_incSvc->addListener( this, "EndEvent", 100, true);
00140 }
00141
00142 IIoComponentMgr* iomgr(0);
00143
00144 if (service("IoComponentMgr", iomgr, true).isFailure()) {
00145 m_log << MSG::ERROR << "unable to get the IoComponentMgr" << endmsg;
00146 st = StatusCode::FAILURE;
00147 } else {
00148
00149 if ( !iomgr->io_register (this).isSuccess() ) {
00150 m_log << MSG::ERROR
00151 << "could not register with the I/O component manager !"
00152 << endmsg;
00153 st = StatusCode::FAILURE;
00154 } else {
00155 bool all_good = true;
00156 typedef std::map<std::string, std::pair<TFile*,Mode> > Registry_t;
00157
00158 for ( Registry_t::const_iterator
00159 ireg = m_files.begin(),
00160 iend = m_files.end();
00161 ireg != iend;
00162 ++ireg ) {
00163 const std::string fname = ireg->second.first->GetName();
00164 const IIoComponentMgr::IoMode::Type iomode =
00165 ( ireg->second.second==THistSvc::READ
00166 ? IIoComponentMgr::IoMode::Input
00167 : IIoComponentMgr::IoMode::Output );
00168 if ( !iomgr->io_register (this, iomode, fname).isSuccess () ) {
00169 m_log << MSG::WARNING << "could not register file ["
00170 << fname << "] with the I/O component manager..." << endmsg;
00171 all_good = false;
00172 } else {
00173 m_log << MSG::INFO << "registered file [" << fname << "]... [ok]"
00174 << endmsg;
00175 }
00176 }
00177 if (!all_good) {
00178 m_log << MSG::ERROR
00179 << "problem while registering input/output files with "
00180 << "the I/O component manager !" << endmsg;
00181 st = StatusCode::FAILURE;
00182 }
00183 }
00184
00185 }
00186
00187 if (st.isFailure()) {
00188 m_log << MSG::FATAL << "Unable to initialize THistSvc" << endmsg;
00189 }
00190
00191 return st;
00192
00193 }
00194
00195
00196
00197 StatusCode
00198 THistSvc::reinitialize() {
00199
00200 GlobalDirectoryRestore restore;
00201
00202 m_log << MSG::WARNING << "reinitialize not implemented" << endmsg;
00203
00204
00205 return StatusCode::SUCCESS;
00206
00207 }
00208
00209
00210
00211 StatusCode
00212 THistSvc::finalize() {
00213
00214 GlobalDirectoryRestore restore;
00215
00216 if (m_log.level() <= MSG::DEBUG)
00217 m_log << MSG::DEBUG << "THistSvc::finalize" << endmsg;
00218
00219 #ifndef NDEBUG
00220 if (m_log.level() <= MSG::DEBUG) {
00221 uidMap::const_iterator uitr;
00222 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
00223
00224 TObject* to = uitr->second.obj;
00225
00226 string dirname("none");
00227 if (to && to->IsA()->InheritsFrom("TTree")) {
00228 TTree* tr = dynamic_cast<TTree*>(to);
00229 if (tr->GetDirectory() != 0) {
00230 dirname = tr->GetDirectory()->GetPath();
00231 }
00232 } else if (to && to->IsA()->InheritsFrom("TGraph")) {
00233 if (!uitr->second.temp) {
00234 dirname = uitr->second.file->GetPath();
00235 string id2(uitr->second.id);
00236 id2.erase(0,id2.find("/",1));
00237 id2.erase(id2.rfind("/"), id2.length());
00238 if (id2.find("/") == 0) {
00239 id2.erase(0,1);
00240 }
00241 dirname += id2;
00242 } else {
00243 dirname = "/tmp";
00244 }
00245 } else if (to && to->IsA()->InheritsFrom("TH1")) {
00246 TH1* th = dynamic_cast<TH1*>(to);
00247 if (th == 0) {
00248 m_log << MSG::ERROR << "Couldn't dcast: " << uitr->first << endmsg;
00249 } else {
00250 if (th->GetDirectory() != 0) {
00251 dirname = th->GetDirectory()->GetPath();
00252 }
00253 }
00254 } else if (! to ) {
00255 m_log << MSG::WARNING << uitr->first << " has NULL TObject ptr"
00256 << endmsg;
00257 }
00258
00259 m_log << MSG::DEBUG << "uid: \"" << uitr->first << "\" temp: "
00260 << uitr->second.temp << " dir: " << dirname
00261 << endmsg;
00262 }
00263 }
00264 #endif
00265
00266 StatusCode sc = write();
00267 if (sc.isFailure()) {
00268 m_log << MSG::ERROR << "problems writing histograms" << endmsg;
00269 }
00270
00271 if (m_print) {
00272 m_log << MSG::INFO << "Listing contents of ROOT files: " << endmsg;
00273 }
00274 vector<TFile*> deleted_files;
00275 map<string, pair<TFile*,Mode> >::const_iterator itr;
00276 for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
00277
00278 if (find(deleted_files.begin(), deleted_files.end(), itr->second.first) ==
00279 deleted_files.end()) {
00280 deleted_files.push_back(itr->second.first);
00281
00282 #ifndef NDEBUG
00283 if (m_log.level() <= MSG::DEBUG)
00284 m_log << MSG::DEBUG << "finalizing stream/file " << itr->first << ":"
00285 << itr->second.first->GetName()
00286 << endmsg;
00287 #endif
00288 } else {
00289 #ifndef NDEBUG
00290 if (m_log.level() <= MSG::DEBUG)
00291 m_log << MSG::DEBUG << "already finalized stream " << itr->first << endmsg;
00292 #endif
00293 continue;
00294 }
00295
00296
00297 if (m_print && m_log.level() <= MSG::INFO) {
00298
00299 m_log << MSG::INFO;
00300 m_log << "==> File: " << itr->second.first->GetName()
00301 << " stream: " << itr->first << endmsg;
00302
00303 itr->second.first->Print("base");
00304 }
00305
00306 string tmpfn=itr->second.first->GetName();
00307
00308 itr->second.first->Close();
00309
00310 IIncidentSvc *pi(0);
00311 if (service("IncidentSvc",pi).isFailure()) {
00312 m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg;
00313 return StatusCode::FAILURE;
00314 }
00315
00316 if (itr->second.second==SHARE) {
00317 TFile *outputfile;
00318
00319 try {
00320 if (m_log.level() <= MSG::DEBUG)
00321 m_log << MSG::DEBUG << "Opening Final Output File: "
00322 << m_sharedFiles[itr->first].c_str() << endmsg;
00323 outputfile = new TFile(m_sharedFiles[itr->first].c_str(), "UPDATE");
00324 } catch (const std::exception& Exception) {
00325 m_log << MSG::ERROR << "exception caught while trying to open root"
00326 << " file for appending: " << Exception.what() << std::endl
00327 << " -> file probably corrupt." << endmsg;
00328 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
00329 m_sharedFiles[itr->first]));
00330 return StatusCode::FAILURE;
00331 } catch (...) {
00332 m_log << MSG::ERROR << "Problems opening output file \""
00333 << m_sharedFiles[itr->first]
00334 << "\" for append: probably corrupt" << endmsg;
00335 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
00336 m_sharedFiles[itr->first]));
00337 return StatusCode::FAILURE;
00338 }
00339
00340 pi->fireIncident(FileIncident(name(), IncidentType::WroteToOutputFile,
00341 m_sharedFiles[itr->first]));
00342
00343 if (m_log.level() <= MSG::DEBUG)
00344 m_log << MSG::DEBUG << "THistSvc::write()::Merging Rootfile "<<endmsg;
00345 TFile *inputfile;
00346 try {
00347 if (m_log.level() <= MSG::DEBUG)
00348 m_log << MSG::DEBUG << "Openning again Temporary File: "
00349 << tmpfn.c_str() << endmsg;
00350 inputfile=new TFile(tmpfn.c_str(),"READ");
00351 } catch (const std::exception& Exception) {
00352 m_log << MSG::ERROR << "exception caught while trying to open root"
00353 << " file for appending: " << Exception.what() << std::endl
00354 << " -> file probably corrupt." << endmsg;
00355 return StatusCode::FAILURE;
00356 } catch (...) {
00357 m_log << MSG::ERROR << "Problems opening output file \""
00358 << tmpfn.c_str()
00359 << "\" for append: probably corrupt" << endmsg;
00360 return StatusCode::FAILURE;
00361 }
00362
00363 outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
00364
00365 MergeRootFile(outputfile, inputfile);
00366
00367 outputfile->Write();
00368 outputfile->Close();
00369 inputfile->Close();
00370
00371 if (m_log.level() <= MSG::DEBUG)
00372 m_log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn
00373 << "\""<<endmsg;
00374
00375 std::remove(tmpfn.c_str());
00376 }
00377 delete itr->second.first;
00378 }
00379
00380 m_sharedFiles.clear();
00381 m_fileStreams.clear();
00382 m_files.clear();
00383 m_uids.clear();
00384 m_ids.clear();
00385 m_tobjs.clear();
00386
00387 return Service::finalize();
00388 }
00389
00390
00391
00392 bool
00393 THistSvc::browseTDir(TDirectory *dir) const {
00394
00395 if (dir == 0) {
00396 std::cerr << "TDirectory == 0" << std::endl;
00397 return false;
00398 }
00399
00400 GlobalDirectoryRestore restore;
00401
00402 dir->cd();
00403
00404
00405 cout << "-> " << dir->GetPath() << " "
00406 << dir->GetListOfKeys()->GetSize() << endl;
00407
00408
00409 TIter nextkey(dir->GetList());
00410 while (TKey *key = (TKey*)nextkey()) {
00411
00412 TObject *obj = key->ReadObj();
00413 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00414
00415 cout << " Key: " << key->GetName() << " "
00416 << " tit: " << obj->GetTitle() << " "
00417 << " (" << key->GetClassName() << ")" << endl;
00418
00419 }
00420
00421 nextkey = dir->GetListOfKeys();
00422 while (TKey *key = (TKey*)nextkey()) {
00423
00424 TObject *obj = key->ReadObj();
00425 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00426 if (obj->IsA()->InheritsFrom("TDirectory")) {
00427 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00428 browseTDir(tt);
00429 }
00430 }
00431
00432 return true;
00433 }
00434
00435
00436
00437
00438 StatusCode
00439 THistSvc::getTHists(TDirectory *td, TList & tl, bool rcs) const {
00440 GlobalDirectoryRestore restore;
00441
00442 gErrorIgnoreLevel = kBreak;
00443
00444 if (!td->cd()) {
00445 m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath()
00446 << "\"" << endmsg;
00447 return StatusCode::FAILURE;
00448 }
00449
00450 if (m_log.level() <= MSG::DEBUG)
00451 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00452 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00453
00454 TIter nextkey(td->GetListOfKeys());
00455 while (TKey *key = (TKey*)nextkey()) {
00456 if (m_log.level() <= MSG::DEBUG)
00457 m_log << MSG::DEBUG << " key: " << key->GetName();
00458 TObject *obj = key->ReadObj();
00459 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00460 if (m_log.level() <= MSG::DEBUG)
00461 m_log << " (" << obj->IsA()->GetName() << ")";
00462 } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) {
00463 if (m_log.level() <= MSG::DEBUG)
00464 m_log << " (" << obj->IsA()->GetName() << ")";
00465 tl.Add(obj);
00466 } else if (obj != 0) {
00467 if (m_log.level() <= MSG::DEBUG)
00468 m_log << " [" << obj->IsA()->GetName() << "]";
00469 }
00470 if (m_log.level() <= MSG::DEBUG)
00471 m_log << endmsg;
00472 }
00473
00474
00475 if (rcs) {
00476 nextkey = td->GetListOfKeys();
00477 while (TKey *key = (TKey*)nextkey()) {
00478 TObject *obj = key->ReadObj();
00479 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00480 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00481 getTHists(tt, tl, rcs);
00482 }
00483 }
00484 }
00485
00486 return StatusCode::SUCCESS;
00487
00488
00489 }
00490
00491
00492
00493 StatusCode
00494 THistSvc::getTHists(const std::string& dir, TList & tl, bool rcs) const {
00495
00496 GlobalDirectoryRestore restore;
00497
00498 gErrorIgnoreLevel = kBreak;
00499
00500 StatusCode sc;
00501
00502 std::string stream,rem,r2;
00503 parseString(dir,stream,rem);
00504
00505 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00506 if (itr != m_files.end()) {
00507 r2 = itr->second.first->GetName();
00508 r2 += ":/";
00509 r2 += rem;
00510
00511 if (m_log.level() <= MSG::DEBUG)
00512 m_log << MSG::DEBUG << "getTHists: \"" << dir
00513 << "\" looks like a stream name." << " associated TFile: \""
00514 << itr->second.first->GetName() << "\"" << endmsg;
00515
00516 if (gDirectory->cd(r2.c_str())) {
00517 m_curstream = stream;
00518 sc = getTHists(gDirectory,tl,rcs);
00519 m_curstream = "";
00520 return sc;
00521 } else {
00522 if (m_log.level() <= MSG::DEBUG)
00523 m_log << MSG::DEBUG << "getTHists: no such TDirectory \""
00524 << r2 << "\"" << endmsg;
00525 }
00526
00527 } else {
00528 if (m_log.level() <= MSG::DEBUG)
00529 m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found"
00530 << endmsg;
00531 }
00532
00533 if (!gDirectory->cd(dir.c_str())) {
00534 m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir
00535 << "\"" << endmsg;
00536 sc = StatusCode::FAILURE;
00537 } else {
00538 sc = getTHists(gDirectory,tl,rcs);
00539 }
00540
00541 return sc;
00542
00543 }
00544
00545
00546 StatusCode
00547 THistSvc::getTTrees(TDirectory *td, TList & tl, bool rcs) const {
00548 GlobalDirectoryRestore restore;
00549
00550 gErrorIgnoreLevel = kBreak;
00551
00552 if (!td->cd()) {
00553 m_log << MSG::ERROR << "getTTrees: No such TDirectory \""
00554 << td->GetPath() << "\"" << endmsg;
00555 return StatusCode::FAILURE;
00556 }
00557
00558 if (m_log.level() <= MSG::DEBUG)
00559 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00560 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00561
00562 TIter nextkey(td->GetListOfKeys());
00563 while (TKey *key = (TKey*)nextkey()) {
00564 if (m_log.level() <= MSG::DEBUG)
00565 m_log << MSG::DEBUG << " key: " << key->GetName();
00566 TObject *obj = key->ReadObj();
00567 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00568 if (m_log.level() <= MSG::DEBUG)
00569 m_log << " (" << obj->IsA()->GetName() << ")";
00570 } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) {
00571 if (m_log.level() <= MSG::DEBUG)
00572 m_log << " (" << obj->IsA()->GetName() << ")";
00573 tl.Add(obj);
00574 } else if (obj != 0) {
00575 if (m_log.level() <= MSG::DEBUG)
00576 m_log << " [" << obj->IsA()->GetName() << "]";
00577 }
00578 m_log << endmsg;
00579 }
00580
00581
00582 if (rcs) {
00583 nextkey = td->GetListOfKeys();
00584 while (TKey *key = (TKey*)nextkey()) {
00585 TObject *obj = key->ReadObj();
00586 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00587 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00588 getTTrees(tt, tl, rcs);
00589 }
00590 }
00591 }
00592
00593 return StatusCode::SUCCESS;
00594
00595 }
00596
00597
00598
00599 StatusCode
00600 THistSvc::getTTrees(const std::string& dir, TList & tl, bool rcs) const {
00601 GlobalDirectoryRestore restore;
00602
00603 gErrorIgnoreLevel = kBreak;
00604
00605 StatusCode sc;
00606
00607 std::string stream,rem,r2;
00608 parseString(dir,stream,rem);
00609
00610 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00611 if (itr != m_files.end()) {
00612 r2 = itr->second.first->GetName();
00613 r2 += ":/";
00614 r2 += rem;
00615
00616 if (m_log.level() <= MSG::DEBUG)
00617 m_log << MSG::DEBUG << "getTTrees: \"" << dir
00618 << "\" looks like a stream name." << " associated TFile: \""
00619 << itr->second.first->GetName() << "\"" << endmsg;
00620
00621 if (gDirectory->cd(r2.c_str())) {
00622 return getTTrees(gDirectory,tl,rcs);
00623 } else {
00624 if (m_log.level() <= MSG::DEBUG)
00625 m_log << MSG::DEBUG << "getTTrees: no such TDirectory \""
00626 << r2 << "\"" << endmsg;
00627 }
00628
00629 } else {
00630 if (m_log.level() <= MSG::DEBUG)
00631 m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found"
00632 << endmsg;
00633 }
00634
00635 if (!gDirectory->cd(dir.c_str())) {
00636 m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir
00637 << "\"" << endmsg;
00638 sc = StatusCode::FAILURE;
00639 } else {
00640 sc = getTTrees(gDirectory,tl,rcs);
00641 }
00642
00643 return sc;
00644
00645
00646 }
00647
00648
00649
00650
00651 StatusCode
00652 THistSvc::getTHists(TDirectory *td, TList & tl, bool rcs, bool reg) {
00653
00654 GlobalDirectoryRestore restore;
00655
00656 gErrorIgnoreLevel = kBreak;
00657
00658 if (!td->cd()) {
00659 m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath()
00660 << "\"" << endmsg;
00661 return StatusCode::FAILURE;
00662 }
00663
00664 if (m_log.level() <= MSG::DEBUG)
00665 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00666 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00667
00668 TIter nextkey(td->GetListOfKeys());
00669 while (TKey *key = (TKey*)nextkey()) {
00670 if (m_log.level() <= MSG::DEBUG)
00671 m_log << MSG::DEBUG << " key: " << key->GetName();
00672 TObject *obj = key->ReadObj();
00673 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00674 if (m_log.level() <= MSG::DEBUG)
00675 m_log << " (" << obj->IsA()->GetName() << ")";
00676 } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) {
00677 if (m_log.level() <= MSG::DEBUG)
00678 m_log << " (" << obj->IsA()->GetName() << ")";
00679 tl.Add(obj);
00680 if (reg && m_curstream != "") {
00681 string dir = td->GetPath();
00682 string fil = td->GetFile()->GetName();
00683 dir.erase(0,fil.length()+1);
00684 string id = "/" + m_curstream;
00685 if ( dir == "/" ) {
00686 id = id + "/" + key->GetName();
00687 } else {
00688 id = id + dir + "/" + key->GetName();
00689 }
00690 if (!exists(id)) {
00691 if (m_log.level() <= MSG::DEBUG)
00692 m_log << " reg as \"" << id << "\"";
00693 regHist(id).ignore();
00694 } else {
00695 if (m_log.level() <= MSG::DEBUG)
00696 m_log << " already registered";
00697 }
00698 }
00699 } else if (obj != 0) {
00700 if (m_log.level() <= MSG::DEBUG)
00701 m_log << " [" << obj->IsA()->GetName() << "]";
00702 }
00703 if (m_log.level() <= MSG::DEBUG)
00704 m_log << endmsg;
00705 }
00706
00707
00708 if (rcs) {
00709 nextkey = td->GetListOfKeys();
00710 while (TKey *key = (TKey*)nextkey()) {
00711 TObject *obj = key->ReadObj();
00712 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00713 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00714 getTHists(tt, tl, rcs, reg);
00715 }
00716 }
00717 }
00718
00719 return StatusCode::SUCCESS;
00720
00721 }
00722
00723
00724
00725 StatusCode
00726 THistSvc::getTHists(const std::string& dir, TList & tl, bool rcs, bool reg) {
00727
00728 GlobalDirectoryRestore restore;
00729
00730 gErrorIgnoreLevel = kBreak;
00731
00732 StatusCode sc;
00733
00734 std::string stream,rem,r2;
00735 parseString(dir,stream,rem);
00736
00737 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00738 if (itr != m_files.end()) {
00739 r2 = itr->second.first->GetName();
00740 r2 += ":/";
00741 r2 += rem;
00742
00743 if (m_log.level() <= MSG::DEBUG)
00744 m_log << MSG::DEBUG << "getTHists: \"" << dir
00745 << "\" looks like a stream name." << " associated TFile: \""
00746 << itr->second.first->GetName() << "\"" << endmsg;
00747
00748 if (gDirectory->cd(r2.c_str())) {
00749 m_curstream = stream;
00750 sc = getTHists(gDirectory,tl,rcs,reg);
00751 m_curstream = "";
00752 return sc;
00753 } else {
00754 if (m_log.level() <= MSG::DEBUG)
00755 m_log << MSG::DEBUG << "getTHists: no such TDirectory \""
00756 << r2 << "\"" << endmsg;
00757 }
00758
00759 } else {
00760 if (m_log.level() <= MSG::DEBUG)
00761 m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found"
00762 << endmsg;
00763 }
00764
00765 if (!gDirectory->cd(dir.c_str())) {
00766 m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir
00767 << "\"" << endmsg;
00768 sc = StatusCode::FAILURE;
00769 } else {
00770 if (reg) {
00771 m_log << MSG::WARNING << "Unable to register histograms automatically "
00772 << "without a valid stream name" << endmsg;
00773 reg = false;
00774 }
00775 sc = getTHists(gDirectory,tl,rcs,reg);
00776 }
00777
00778 return sc;
00779
00780 }
00781
00782
00783 StatusCode
00784 THistSvc::getTTrees(TDirectory *td, TList & tl, bool rcs, bool reg) {
00785
00786 GlobalDirectoryRestore restore;
00787
00788 gErrorIgnoreLevel = kBreak;
00789
00790 if (!td->cd()) {
00791 m_log << MSG::ERROR << "getTTrees: No such TDirectory \""
00792 << td->GetPath() << "\"" << endmsg;
00793 return StatusCode::FAILURE;
00794 }
00795
00796 if (m_log.level() <= MSG::DEBUG)
00797 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00798 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00799
00800 TIter nextkey(td->GetListOfKeys());
00801 while (TKey *key = (TKey*)nextkey()) {
00802 if (m_log.level() <= MSG::DEBUG)
00803 m_log << MSG::DEBUG << " key: " << key->GetName();
00804 TObject *obj = key->ReadObj();
00805 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00806 if (m_log.level() <= MSG::DEBUG)
00807 m_log << " (" << obj->IsA()->GetName() << ")";
00808 } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) {
00809 if (m_log.level() <= MSG::DEBUG)
00810 m_log << " (" << obj->IsA()->GetName() << ")";
00811 tl.Add(obj);
00812 if (reg && m_curstream != "") {
00813 string dir = td->GetPath();
00814 string fil = td->GetFile()->GetName();
00815 dir.erase(0,fil.length()+1);
00816 string id = "/" + m_curstream;
00817 if ( dir == "/" ) {
00818 id = id + "/" + key->GetName();
00819 } else {
00820 id = id + dir + "/" + key->GetName();
00821 }
00822 if (!exists(id)) {
00823 if (m_log.level() <= MSG::DEBUG)
00824 m_log << " reg as \"" << id << "\"";
00825 regHist(id).ignore();
00826 } else {
00827 if (m_log.level() <= MSG::DEBUG)
00828 m_log << " already registered";
00829 }
00830 }
00831 } else if (obj != 0) {
00832 if (m_log.level() <= MSG::DEBUG)
00833 m_log << " [" << obj->IsA()->GetName() << "]";
00834 }
00835 if (m_log.level() <= MSG::DEBUG)
00836 m_log << endmsg;
00837 }
00838
00839
00840 if (rcs) {
00841 nextkey = td->GetListOfKeys();
00842 while (TKey *key = (TKey*)nextkey()) {
00843 TObject *obj = key->ReadObj();
00844 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00845 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00846 getTTrees(tt, tl, rcs, reg);
00847 }
00848 }
00849 }
00850
00851 return StatusCode::SUCCESS;
00852
00853 }
00854
00855
00856
00857 StatusCode
00858 THistSvc::getTTrees(const std::string& dir, TList & tl, bool rcs, bool reg) {
00859
00860 GlobalDirectoryRestore restore;
00861
00862 gErrorIgnoreLevel = kBreak;
00863
00864 StatusCode sc;
00865
00866 std::string stream,rem,r2;
00867 parseString(dir,stream,rem);
00868
00869 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00870 if (itr != m_files.end()) {
00871 r2 = itr->second.first->GetName();
00872 r2 += ":/";
00873 r2 += rem;
00874
00875 if (m_log.level() <= MSG::DEBUG)
00876 m_log << MSG::DEBUG << "getTTrees: \"" << dir
00877 << "\" looks like a stream name." << " associated TFile: \""
00878 << itr->second.first->GetName() << "\"" << endmsg;
00879
00880 if (gDirectory->cd(r2.c_str())) {
00881 return getTTrees(gDirectory,tl,rcs,reg);
00882 } else {
00883 if (m_log.level() <= MSG::DEBUG)
00884 m_log << MSG::DEBUG << "getTTrees: no such TDirectory \""
00885 << r2 << "\"" << endmsg;
00886 }
00887
00888 } else {
00889 if (m_log.level() <= MSG::DEBUG)
00890 m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found"
00891 << endmsg;
00892 }
00893
00894 if (!gDirectory->cd(dir.c_str())) {
00895 m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir
00896 << "\"" << endmsg;
00897 sc = StatusCode::FAILURE;
00898 } else {
00899 sc = getTTrees(gDirectory,tl,rcs,reg);
00900 }
00901
00902 return sc;
00903
00904 }
00905
00906
00907
00908 StatusCode
00909 THistSvc::deReg(TObject* obj) {
00910
00911 objMap::iterator itr = m_tobjs.find(obj);
00912 if (itr != m_tobjs.end()) {
00913 THistID hid = itr->second;
00914
00915 uidMap::iterator itr2 = m_uids.find(hid.id);
00916 if (itr2 == m_uids.end()) {
00917 m_log << MSG::ERROR << "Problems deregistering TObject \""
00918 << obj->GetName()
00919 << "\" with id \"" << hid.id << "\"" << endmsg;
00920 return StatusCode::FAILURE;
00921 }
00922
00923 std::string id,root,rem;
00924 parseString(hid.id, root, rem);
00925
00926 idMap::iterator itr3;
00927 bool found(false);
00928
00929 std::pair<idMap::iterator, idMap::iterator> mitr = m_ids.equal_range(rem);
00930 if (mitr.first == mitr.second) {
00931 m_log << MSG::ERROR << "Problems deregistering TObject \""
00932 << obj->GetName()
00933 << "\" with id \"" << hid.id << "\"" << endmsg;
00934 return StatusCode::FAILURE;
00935 } else {
00936 for (itr3 = mitr.first; itr3 != mitr.second; ++itr3) {
00937 if (itr3->second.obj == obj) {
00938 found = true;
00939 break;
00940 }
00941 }
00942 if (!found) {
00943 m_log << MSG::ERROR << "Problems deregistering TObject \""
00944 << obj->GetName()
00945 << "\" with id \"" << hid.id << "\"" << endmsg;
00946 }
00947 }
00948
00949 m_tobjs.erase(itr);
00950 m_uids.erase(itr2);
00951 m_ids.erase(itr3);
00952
00953 return StatusCode::SUCCESS;
00954
00955 } else {
00956 m_log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName()
00957 << "\": not known to THistSvc" << endmsg;
00958 return StatusCode::FAILURE;
00959 }
00960
00961 }
00962
00963
00964
00965
00966 StatusCode
00967 THistSvc::deReg(const std::string& id) {
00968
00969 uidMap::iterator itr = m_uids.find(id);
00970 if (itr == m_uids.end()) {
00971 m_log << MSG::ERROR << "Problems deregistering id \""
00972 << id << "\"" << endmsg;
00973 return StatusCode::FAILURE;
00974 }
00975
00976 TObject* obj = itr->second.obj;
00977
00978 return deReg(obj);
00979 }
00980
00981
00982
00983 StatusCode
00984 THistSvc::regHist(const std::string& id) {
00985
00986 TH1 *hist(0);
00987
00988 return regHist_i(hist, id);
00989 }
00990
00991
00992
00993 StatusCode
00994 THistSvc::regHist(const std::string& id, TH1* hist) {
00995 return regHist_i(hist, id);
00996 }
00997
00998
00999
01000 StatusCode
01001 THistSvc::regHist(const std::string& id, TH2* hist) {
01002 return regHist_i(hist, id);
01003 }
01004
01005
01006
01007 StatusCode
01008 THistSvc::regHist(const std::string& id, TH3* hist) {
01009 return regHist_i(hist, id);
01010 }
01011
01012
01013
01014 StatusCode
01015 THistSvc::regTree(const std::string& id) {
01016 TTree *hist(0);
01017 return regHist_i(hist, id);
01018 }
01019
01020
01021
01022 StatusCode
01023 THistSvc::regTree(const std::string& id, TTree* hist) {
01024 StatusCode sc = regHist_i(hist, id);
01025 if (hist != 0 && sc.isSuccess()) {
01026 if (m_autoSave != 0)
01027 hist->SetAutoSave(m_autoSave);
01028 hist->SetAutoFlush(m_autoFlush);
01029 }
01030 return sc;
01031 }
01032
01033
01034
01035 StatusCode
01036 THistSvc::regGraph(const std::string& id) {
01037 TGraph *hist(0);
01038 return regHist_i(hist, id);
01039 }
01040
01041
01042
01043 StatusCode
01044 THistSvc::regGraph(const std::string& id, TGraph* hist) {
01045 if ( strcmp(hist->GetName(),"Graph") == 0 ) {
01046
01047 std::string id2(id);
01048 string::size_type i = id2.rfind("/");
01049 if (i != string::npos) {
01050 id2.erase(0,i+1);
01051 }
01052
01053 m_log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \""
01054 << id2 << "\" since it is unset" << endmsg;
01055 hist->SetName(id2.c_str());
01056 }
01057
01058 return regHist_i(hist, id);
01059 }
01060
01061
01062
01063 StatusCode
01064 THistSvc::getHist(const std::string& id, TH1*& hist) const {
01065 return getHist_i(id, hist);
01066 }
01067
01068
01069
01070 StatusCode
01071 THistSvc::getHist(const std::string& id, TH2*& hist) const {
01072 return getHist_i(id, hist);
01073 }
01074
01075
01076
01077 StatusCode
01078 THistSvc::getHist(const std::string& id, TH3*& hist) const {
01079 return getHist_i(id, hist);
01080 }
01081
01082
01083
01084 std::vector<std::string>
01085 THistSvc::getHists() const {
01086
01087 std::vector<std::string> names;
01088 names.reserve(m_uids.size());
01089
01090 uidMap::const_iterator itr;
01091 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01092 THistID tid = itr->second;
01093
01094 if (tid.obj->IsA()->InheritsFrom("TH1")) {
01095 names.push_back(itr->first);
01096 }
01097
01098 }
01099
01100 return names;
01101
01102 }
01103
01104
01105 StatusCode
01106 THistSvc::getTree(const std::string& id, TTree*& hist) const {
01107 return getHist_i(id, hist);
01108 }
01109
01110
01111
01112 std::vector<std::string>
01113 THistSvc::getTrees() const {
01114
01115 std::vector<std::string> names;
01116 names.reserve(m_uids.size());
01117
01118 uidMap::const_iterator itr;
01119 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01120 THistID tid = itr->second;
01121
01122 if (tid.obj->IsA()->InheritsFrom("TTree")) {
01123 names.push_back(itr->first);
01124 }
01125
01126 }
01127
01128 return names;
01129
01130 }
01131
01132
01133 StatusCode
01134 THistSvc::getGraph(const std::string& id, TGraph*& hist) const {
01135 return getHist_i(id, hist);
01136 }
01137
01138
01139
01140 std::vector<std::string>
01141 THistSvc::getGraphs() const {
01142
01143 std::vector<std::string> names;
01144 names.reserve(m_uids.size());
01145
01146 uidMap::const_iterator itr;
01147 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01148 THistID tid = itr->second;
01149
01150 if (tid.obj->IsA()->InheritsFrom("TGraph")) {
01151 names.push_back(itr->first);
01152 }
01153
01154 }
01155
01156 return names;
01157
01158 }
01159
01160
01161 StatusCode
01162 THistSvc::readHist(const std::string& id, TH1*& hist) const {
01163 return readHist_i(id, hist);
01164 }
01165
01166
01167
01168 StatusCode
01169 THistSvc::readHist(const std::string& id, TH2*& hist) const {
01170 return readHist_i(id, hist);
01171 }
01172
01173
01174
01175 StatusCode
01176 THistSvc::readHist(const std::string& id, TH3*& hist) const {
01177 return readHist_i(id, hist);
01178 }
01179
01180
01181
01182 StatusCode
01183 THistSvc::readTree(const std::string& id, TTree*& hist) const {
01184 return readHist_i(id, hist);
01185 }
01186
01187
01188
01189 bool
01190 THistSvc::findStream(const string& id, string& stream, string& rem,
01191 TFile*& file) const {
01192
01193 string::size_type pos = id.find("/");
01194
01195 if (pos == string::npos) {
01196 stream = "temp";
01197 rem = id;
01198 } else if (pos != 0) {
01199 stream = "temp";
01200 rem = id;
01201 } else {
01202
01203 string::size_type pos2 = id.find("/",pos+1);
01204
01205 if (pos2 == string::npos) {
01206 m_log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\""
01207 << endmsg;
01208 return false;
01209 }
01210
01211 parseString(id,stream,rem);
01212
01213 }
01214
01215 if (stream == "temp") {
01216 file = 0;
01217 return true;
01218 }
01219
01220 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
01221 if (itr != m_files.end()) {
01222 file = itr->second.first;
01223 } else {
01224 file = 0;
01225 m_log << MSG::WARNING << "no stream \"" << stream
01226 << "\" associated with id: \"" << id << "\""
01227 << endmsg;
01228 }
01229
01230 return true;
01231
01232 }
01233
01234
01235
01236 void
01237 THistSvc::parseString(const string& id, string& root, string& rem) const {
01238 string::size_type pos = id.find("/");
01239
01240 if (pos == string::npos) {
01241 root = "";
01242 rem = id;
01243 return;
01244 }
01245
01246 if (pos == 0) {
01247 parseString(id.substr(1,id.length()),root,rem);
01248 } else {
01249 root = id.substr(0,pos);
01250 rem = id.substr(pos+1,id.length());
01251 }
01252
01253 }
01254
01255
01256
01257 void
01258 THistSvc::setupCompressionLevel( Property& )
01259 {
01260
01261 m_log << MSG::WARNING << "\"CompressionLevel\" Property has been deprecated. "
01262 << "Set it via the \"CL=\" parameter in the \"Output\" Property"
01263 << endmsg;
01264
01265 }
01266
01267
01268
01269
01270 void
01271 THistSvc::setupInputFile( Property& )
01272 {
01273 StatusCode sc = StatusCode::SUCCESS;
01274
01275 typedef std::vector<std::string> Strings_t;
01276 for ( Strings_t::const_iterator
01277 itr = m_inputfile.value().begin(),
01278 iEnd = m_inputfile.value().end();
01279 itr != iEnd;
01280 ++itr ) {
01281 if ( m_alreadyConnectedInFiles.end() ==
01282 m_alreadyConnectedInFiles.find( *itr ) ) {
01283 if ( connect(*itr).isFailure() ) {
01284 sc = StatusCode::FAILURE;
01285 } else {
01286 m_alreadyConnectedInFiles.insert( *itr );
01287 }
01288 }
01289 }
01290
01291 if ( !sc.isSuccess() ) {
01292 throw GaudiException( "Problem connecting inputfile !!", name(),
01293 StatusCode::FAILURE );
01294 }
01295 return;
01296 }
01297
01298
01299
01300 void
01301 THistSvc::setupOutputFile( Property& )
01302 {
01303 StatusCode sc = StatusCode::SUCCESS;
01304
01305 typedef std::vector<std::string> Strings_t;
01306 for ( Strings_t::const_iterator
01307 itr = m_outputfile.value().begin(),
01308 iEnd = m_outputfile.value().end();
01309 itr != iEnd;
01310 ++itr ) {
01311 if ( m_alreadyConnectedOutFiles.end() ==
01312 m_alreadyConnectedOutFiles.find( *itr ) ) {
01313 if ( connect(*itr).isFailure() ) {
01314 sc = StatusCode::FAILURE;
01315 } else {
01316 m_alreadyConnectedOutFiles.insert( *itr );
01317 }
01318 }
01319 }
01320
01321 if ( !sc.isSuccess() ) {
01322 throw GaudiException( "Problem connecting outputfile !!", name(),
01323 StatusCode::FAILURE );
01324 }
01325 return;
01326 }
01327
01328
01329
01330 void
01331 THistSvc::updateFiles() {
01332
01333
01334
01335
01336
01337
01338 if (m_log.level() <= MSG::DEBUG)
01339 m_log << MSG::DEBUG << "updateFiles()" << endmsg;
01340
01341
01342 uidMap::iterator uitr, uitr2;
01343 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
01344 #ifndef NDEBUG
01345 if (m_log.level() <= MSG::VERBOSE)
01346 m_log << MSG::VERBOSE << " update: " << uitr->first << " "
01347 << uitr->second.id << endmsg;
01348 #endif
01349 TObject* to = uitr->second.obj;
01350 TFile* oldFile = uitr->second.file;
01351 if (!to) {
01352 m_log << MSG::WARNING << uitr->first << ": TObject == 0" << endmsg;
01353 } else if (to->IsA()->InheritsFrom("TTree")) {
01354 TTree* tr = dynamic_cast<TTree*>(to);
01355 TFile* newFile = tr->GetCurrentFile();
01356
01357 if (oldFile != newFile) {
01358 std::string newFileName = newFile->GetName();
01359 std::string oldFileName(""), streamName, rem;
01360 TFile* dummy;
01361 findStream(uitr->second.id, streamName, rem, dummy);
01362
01363 map<string, pair<TFile*,Mode> >::iterator itr;
01364 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01365 if (itr->second.first == oldFile) {
01366 itr->second.first = newFile;
01367
01368 }
01369 }
01370
01371 uitr2 = uitr;
01372 for (; uitr2 != m_uids.end(); ++uitr2) {
01373 if (uitr2->second.file == oldFile) {
01374 uitr2->second.file = newFile;
01375 }
01376 }
01377
01378 streamMap::iterator sitr;
01379 for (sitr = m_fileStreams.begin(); sitr!=m_fileStreams.end(); ++sitr) {
01380 if (sitr->second == streamName) {
01381 oldFileName = sitr->first;
01382 break;
01383 }
01384 }
01385
01386
01387 #ifndef NDEBUG
01388 if (m_log.level() <= MSG::DEBUG)
01389 m_log << MSG::DEBUG << "migrating uid: " << uitr->second.id
01390 << " stream: " << streamName
01391 << " oldFile: " << oldFileName
01392 << " newFile: " << newFileName
01393 << endmsg;
01394 #endif
01395
01396
01397 if (oldFileName != "") {
01398 while ( (sitr=m_fileStreams.find(oldFileName)) != m_fileStreams.end() ) {
01399
01400 #ifndef NDEBUG
01401 if (m_log.level() <= MSG::DEBUG)
01402 m_log << MSG::DEBUG << "changing filename \"" << oldFileName
01403 << "\" to \"" << newFileName << "\" for stream \""
01404 << sitr->second << "\"" << endmsg;
01405 #endif
01406 m_fileStreams.erase(sitr);
01407 m_fileStreams.insert( make_pair(newFileName, streamName) );
01408 }
01409
01410
01411 } else {
01412 m_log << MSG::ERROR
01413 << "Problems updating fileStreams with new file name" << endmsg;
01414 }
01415
01416 }
01417
01418 }
01419 }
01420
01421 }
01422
01423
01424
01425 StatusCode
01426 THistSvc::write() {
01427
01428 updateFiles();
01429
01430 map<string, pair<TFile*,Mode> >::const_iterator itr;
01431 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01432 if (itr->second.second == WRITE || itr->second.second == UPDATE
01433 ||itr->second.second==SHARE) {
01434 itr->second.first->Write("",TObject::kOverwrite);
01435 } else if (itr->second.second == APPEND) {
01436 itr->second.first->Write("");
01437 }
01438 }
01439
01440
01441 if (m_log.level() <= MSG::DEBUG)
01442 m_log << MSG::DEBUG << "THistSvc::write()::List of Files connected in ROOT "
01443 << endmsg;
01444
01445 TSeqCollection *filelist=gROOT->GetListOfFiles();
01446 for (int ii=0; ii<filelist->GetEntries(); ii++) {
01447 if (m_log.level() <= MSG::DEBUG)
01448 m_log << MSG::DEBUG
01449 << "THistSvc::write()::List of Files connected in ROOT: \""
01450 << filelist->At(ii)->GetName()<<"\""<<endmsg;
01451 }
01452
01453 return StatusCode::SUCCESS;
01454
01455 }
01456
01457
01458
01459 StatusCode
01460 THistSvc::connect(const std::string& ident) {
01461
01462 Tokenizer tok(true);
01463
01464 string::size_type loc = ident.find(" ");
01465 string stream = ident.substr(0,loc);
01466 char typ(0);
01467 typedef std::pair<std::string,std::string> Prop;
01468 std::vector<Prop> props;
01469 string val,VAL,TAG,filename,db_typ("ROOT");
01470 int cl(1);
01471
01472 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
01473
01474 for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++) {
01475 const std::string& tag = (*i).tag();
01476 TAG = tag;
01477 toupper(TAG);
01478
01479 val = (*i).value();
01480 VAL = val;
01481 toupper(VAL);
01482
01483 if (TAG == "FILE" || TAG == "DATAFILE") {
01484 filename = val;
01485 removeDoubleSlash( filename );
01486 } else if ( TAG == "OPT" ) {
01487 if ( VAL == "APPEND" || VAL == "UPDATE" ) {
01488 typ = 'A';
01489 } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
01490 typ = 'N';
01491 } else if ( VAL == "RECREATE" ) {
01492 typ = 'R';
01493 } else if (VAL == "SHARE") {
01494 typ = 'S';
01495 } else if ( VAL == "OLD" || VAL == "READ" ) {
01496 typ = 'O';
01497 } else {
01498 m_log << MSG::ERROR << "Unknown OPT: \"" << (*i).value() << "\""
01499 << endmsg;
01500 typ = 0;
01501 }
01502 } else if (TAG == "TYP") {
01503 db_typ = (*i).value();
01504 } else if (TAG == "CL") {
01505 cl = atoi(val.c_str());
01506 } else {
01507 props.push_back( Prop((*i).tag(), (*i).value()));
01508 }
01509
01510 }
01511
01512 if (stream == "temp") {
01513 m_log << MSG::ERROR << "in JobOption \"" << ident
01514 << "\": stream name \"temp\" reserved."
01515 << endmsg;
01516 return StatusCode::FAILURE;
01517 }
01518
01519 if (db_typ != "ROOT") {
01520 m_log << MSG::ERROR << "in JobOption \"" << ident
01521 << "\": technology type \"" << db_typ << "\" not supported."
01522 << endmsg;
01523 return StatusCode::FAILURE;
01524 }
01525
01526
01527 if (m_files.find(stream) != m_files.end()) {
01528 m_log << MSG::ERROR << "in JobOption \"" << ident
01529 << "\":\n stream \"" << stream << "\" already connected to file: \""
01530 << m_files[stream].first->GetName() << "\""
01531 << endmsg;
01532 return StatusCode::FAILURE;
01533 }
01534
01535 Mode newMode;
01536 if (typ == 'O') {
01537 newMode = THistSvc::READ;
01538 } else if (typ == 'N') {
01539 newMode = THistSvc::WRITE;
01540 } else if (typ == 'A') {
01541 newMode = THistSvc::APPEND;
01542 } else if (typ == 'R') {
01543 newMode = THistSvc::UPDATE;
01544 } else if (typ == 'S') {
01545 newMode = THistSvc::SHARE;
01546 } else {
01547
01548 m_log << MSG::ERROR << "No OPT= specified or unknown access mode in: "
01549 << ident << endmsg;
01550 return StatusCode::FAILURE;
01551 }
01552
01553
01554 if (m_fileStreams.find(filename) != m_fileStreams.end()) {
01555 std::pair<streamMap::iterator, streamMap::iterator> fitr =
01556 m_fileStreams.equal_range(filename);
01557
01558 std::string oldstream = (fitr.first)->second;
01559
01560 std::pair<TFile*,Mode> f_info = m_files[oldstream];
01561
01562 if (newMode != f_info.second) {
01563 m_log << MSG::ERROR << "in JobOption \"" << ident
01564 << "\":\n file \"" << filename << "\" already opened by stream: \""
01565 << oldstream << "\" with different access mode."
01566 << endmsg;
01567 return StatusCode::FAILURE;
01568 } else {
01569 TFile *f2 = f_info.first;
01570 m_files[stream] = make_pair(f2, newMode);
01571 if (m_log.level() <= MSG::DEBUG)
01572 m_log << MSG::DEBUG << "Connecting stream: \"" << stream
01573 << "\" to previously opened TFile: \"" << filename << "\""
01574 << endmsg;
01575 return StatusCode::SUCCESS;
01576 }
01577 }
01578
01579
01580 IIncidentSvc *pi(0);
01581 if (service("IncidentSvc",pi).isFailure()) {
01582 m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg;
01583 return StatusCode::FAILURE;
01584 }
01585
01586 TFile *f(0) ;
01587 if (newMode == THistSvc::READ) {
01588
01589
01590 try {
01591 f = TFile::Open(filename.c_str(),"READ");
01592 } catch (const std::exception& Exception) {
01593 m_log << MSG::ERROR << "exception caught while trying to open root"
01594 << " file for reading: " << Exception.what() << std::endl
01595 << " -> file probably corrupt." << endmsg;
01596 pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01597 filename));
01598 return StatusCode::FAILURE;
01599 } catch (...) {
01600 m_log << MSG::ERROR << "Problems opening input file \"" << filename
01601 << "\": probably corrupt" << endmsg;
01602 pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01603 filename));
01604 return StatusCode::FAILURE;
01605 }
01606
01607 if (!f->IsOpen()) {
01608 m_log << MSG::ERROR << "Unable to open input file \"" << filename
01609 << "\": file does not exist" << endmsg;
01610 pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01611 filename));
01612 return StatusCode::FAILURE;
01613 }
01614
01615
01616 pi->fireIncident(FileIncident(name(), "BeginHistFile",
01617 filename));
01618
01619
01620 } else if (newMode == THistSvc::WRITE) {
01621
01622
01623 f = TFile::Open(filename.c_str(),"NEW",stream.c_str(),cl);
01624 if (!f->IsOpen()) {
01625 m_log << MSG::ERROR << "Unable to create new output file \"" << filename
01626 << "\" for writing: file already exists" << endmsg;
01627 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01628 filename));
01629 return StatusCode::FAILURE;
01630 }
01631
01632
01633 pi->fireIncident(FileIncident(name(), "BeginHistFile",
01634 filename));
01635
01636 } else if (newMode == THistSvc::APPEND) {
01637
01638
01639 try {
01640 f = TFile::Open(filename.c_str(),"UPDATE",stream.c_str(),cl);
01641 } catch (const std::exception& Exception) {
01642 m_log << MSG::ERROR << "exception caught while trying to open root"
01643 << " file for appending: " << Exception.what() << std::endl
01644 << " -> file probably corrupt." << endmsg;
01645 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01646 filename));
01647 return StatusCode::FAILURE;
01648 } catch (...) {
01649 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01650 << "\" for append: probably corrupt" << endmsg;
01651 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01652 filename));
01653 return StatusCode::FAILURE;
01654 }
01655
01656 if (!f->IsOpen()) {
01657 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01658 << "\" for appending" << endmsg;
01659 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01660 filename));
01661 return StatusCode::FAILURE;
01662 }
01663 pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01664 filename));
01665
01666 } else if (newMode == THistSvc::SHARE) {
01667
01668
01669
01670
01671 static int ishared = 0;
01672 stringstream out;
01673 string realfilename=filename;
01674 out << ishared++;
01675 filename = string("tmp_THistSvc_")+out.str()+string(".root");
01676
01677 if (m_log.level() <= MSG::DEBUG)
01678 m_log << MSG::DEBUG << "Creating temp file \"" << filename
01679 << "\" and realfilename="<<realfilename << endmsg;
01680 m_sharedFiles[stream]=realfilename;
01681
01682 try {
01683 f = TFile::Open(filename.c_str(),"NEW",stream.c_str(),cl);
01684 } catch (const std::exception& Exception) {
01685 m_log << MSG::ERROR << "exception caught while trying to open root"
01686 << " file for appending: " << Exception.what() << std::endl
01687 << " -> file probably corrupt." << endmsg;
01688 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01689 filename));
01690 return StatusCode::FAILURE;
01691 } catch (...) {
01692 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01693 << "\" for append: probably corrupt" << endmsg;
01694 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01695 filename));
01696 return StatusCode::FAILURE;
01697 }
01698
01699 if (!f->IsOpen()) {
01700 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01701 << "\" for appending" << endmsg;
01702 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01703 filename));
01704 return StatusCode::FAILURE;
01705 }
01706 pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01707 filename));
01708
01709 } else if (newMode == THistSvc::UPDATE) {
01710
01711
01712 try {
01713 f = TFile::Open(filename.c_str(),"RECREATE",stream.c_str(),cl);
01714 } catch (const std::exception& Exception) {
01715 m_log << MSG::ERROR << "exception caught while trying to open root"
01716 << " file for updating: " << Exception.what() << std::endl
01717 << " -> file probably corrupt." << endmsg;
01718 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01719 filename));
01720 return StatusCode::FAILURE;
01721 } catch (...) {
01722 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01723 << "\" for update: probably corrupt" << endmsg;
01724 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01725 filename));
01726 return StatusCode::FAILURE;
01727 }
01728
01729 if (!f->IsOpen()) {
01730 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01731 << "\" for updating" << endmsg;
01732 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01733 filename));
01734 return StatusCode::FAILURE;
01735 }
01736 pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01737 filename));
01738
01739 }
01740
01741 m_files[stream] = make_pair(f, newMode);
01742 m_fileStreams.insert(make_pair(filename, stream));
01743
01744 if (m_log.level() <= MSG::DEBUG)
01745 m_log << MSG::DEBUG << "Opening TFile \"" << filename << "\" stream: \""
01746 << stream << "\" mode: \"" << typ << "\"" << " comp level: " << cl
01747 << endmsg;
01748
01749 return StatusCode::SUCCESS;
01750 }
01751
01752
01753
01754 TDirectory*
01755 THistSvc::changeDir(const THistSvc::THistID& hid) const {
01756
01757 string uid = hid.id;
01758 TFile* file = hid.file;
01759 string stream, fdir, bdir, dir, id;
01760
01761 if (file != 0) {
01762 file->cd("/");
01763 } else {
01764 gROOT->cd();
01765 }
01766
01767 fdir = uid;
01768 bdir = dirname(fdir);
01769
01770 while ( (dir = dirname(fdir)) != "") {
01771 if (! gDirectory->GetKey(dir.c_str())) {
01772 gDirectory->mkdir(dir.c_str());
01773 }
01774 gDirectory->cd(dir.c_str());
01775 }
01776
01777 return gDirectory;
01778
01779 }
01780
01781
01782
01783 std::string
01784 THistSvc::dirname(std::string& dir) const {
01785
01786
01787 string::size_type i = dir.find("/");
01788
01789 if (i == string::npos) {
01790 return "";
01791 }
01792
01793 if ( i == 0 ) {
01794 dir.erase(0,1);
01795 return dirname(dir);
01796 }
01797
01798 string root = dir.substr(0,i);
01799 dir.erase(0,i);
01800
01801 return root;
01802
01803 }
01804
01805
01806
01807 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore() {
01808 m_gd = gDirectory;
01809 m_gf = gFile;
01810 m_ge = gErrorIgnoreLevel;
01811 }
01812
01813 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore() {
01814 gDirectory = m_gd;
01815 gFile = m_gf;
01816 gErrorIgnoreLevel = m_ge;
01817 }
01818
01819
01820
01821 void
01822 THistSvc::removeDoubleSlash(std::string& id) const {
01823
01824 while (id.find("//") != std::string::npos) {
01825 id.replace(id.find("//"),2,"/");
01826 }
01827
01828 }
01829
01830
01831
01832 void THistSvc::MergeRootFile(TDirectory *target, TDirectory *source) {
01833
01834 if (m_log.level() <= MSG::DEBUG)
01835 m_log <<MSG::DEBUG << "Target path: " << target->GetPath() << endmsg;
01836 TString path( (char*)strstr(target->GetPath(), ":") );
01837 path.Remove( 0, 2);
01838
01839 source->cd(path);
01840 TDirectory *current_sourcedir = gDirectory;
01841
01842
01843 TList *lkeys=current_sourcedir->GetListOfKeys();
01844 int nkeys=lkeys->GetEntries();
01845 TKey *key;
01846 for (int jj=0; jj<nkeys; jj++) {
01847 key=(TKey*) lkeys->At(jj);
01848 string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName();
01849 if (m_log.level() <= MSG::DEBUG)
01850 m_log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endmsg;
01851
01852
01853 TObject *obj=source->Get(pathnameinsource.c_str());
01854
01855 if (obj->IsA()->InheritsFrom("TDirectory") ) {
01856
01857
01858 if (m_log.level() <= MSG::DEBUG)
01859 m_log <<MSG::DEBUG << "Found subdirectory " << obj->GetName()
01860 << endmsg;
01861
01862
01863 target->cd();
01864 TDirectory *newtargetdir =
01865 target->mkdir(obj->GetName(), obj->GetTitle() );
01866
01867 MergeRootFile(newtargetdir, source);
01868
01869 } else if (obj->IsA()->InheritsFrom("TTree")) {
01870 if (m_log.level() <= MSG::DEBUG)
01871 m_log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endmsg;
01872 TTree *mytree=dynamic_cast<TTree*>(obj);
01873 int nentries=(int) mytree->GetEntries();
01874 mytree->SetBranchStatus("*",1);
01875
01876 if (m_log.level() <= MSG::DEBUG)
01877 m_log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries"
01878 << endmsg;
01879
01880
01881
01882
01883
01884
01885 target->cd();
01886 mytree->CloneTree();
01887
01888
01889
01890
01891
01892 } else if (obj) {
01893 target->cd();
01894 obj->Write(key->GetName() );
01895 }
01896
01897 }
01898
01899
01900
01901 }
01902
01903
01904
01905 bool
01906 THistSvc::exists( const std::string& name ) const {
01907
01908 TH1* h;
01909
01910 return getHist_i(name,h,true).isSuccess();
01911
01912
01913 }
01914
01915
01916
01917 void
01918 THistSvc::handle( const Incident& ) {
01919
01920 if (signaledStop) return ;
01921
01922
01923 Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
01924 Long64_t mfs_warn = mfs * 95 / 100;
01925
01926 updateFiles();
01927
01928 map<string, pair<TFile*,Mode> >::const_iterator itr;
01929 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01930 TFile* tf = itr->second.first;
01931
01932 #ifndef NDEBUG
01933 if (m_log.level() <= MSG::DEBUG)
01934 m_log << MSG::DEBUG << "stream: " << itr->first << " name: "
01935 << tf->GetName() << " size: " << tf->GetSize()
01936 << endmsg;
01937 #endif
01938
01939
01940 if (tf->GetSize() > mfs) {
01941
01942 signaledStop = true;
01943
01944 m_log << MSG::FATAL << "file \"" << tf->GetName()
01945 << "\" associated with stream \"" << itr->first
01946 << "\" has exceeded the max file size of "
01947 << m_maxFileSize.value() << "MB. Terminating Job."
01948 << endmsg;
01949
01950 IEventProcessor* evt(0);
01951 if (service("ApplicationMgr", evt, true).isSuccess()) {
01952 evt->stopRun();
01953 evt->release();
01954 } else {
01955 abort();
01956 }
01957 } else if (tf->GetSize() > mfs_warn) {
01958 m_log << MSG::WARNING << "file \"" << tf->GetName()
01959 << "\" associated with stream \"" << itr->first
01960 << "\" is at 95% of its maximum allowable file size of "
01961 << m_maxFileSize.value() << "MB"
01962 << endmsg;
01963 }
01964 }
01965 }
01966
01967
01968
01971 void
01972 THistSvc::copyFileLayout (TDirectory *dst, TDirectory *src) {
01973
01974 if (m_log.level() <= MSG::DEBUG)
01975 m_log << MSG::DEBUG
01976 << "copyFileLayout() to dst path: " << dst->GetPath () << endmsg;
01977
01978
01979 TString path ((char*)strstr (dst->GetPath(), ":"));
01980 path.Remove (0, 2);
01981
01982 src->cd (path);
01983 TDirectory *cur_src_dir = gDirectory;
01984
01985
01986 TList *key_list = cur_src_dir->GetListOfKeys ();
01987 int n = key_list->GetEntries ();
01988 for ( int j = 0; j < n; ++j ) {
01989 TKey *k = (TKey*)key_list->At (j);
01990 const std::string src_pathname = cur_src_dir->GetPath()
01991 + std::string("/")
01992 + k->GetName();
01993 TObject *o=src->Get (src_pathname.c_str());
01994
01995 if (o != NULL && o->IsA()->InheritsFrom ("TDirectory")) {
01996 if (m_log.level() <= MSG::VERBOSE)
01997 m_log << MSG::VERBOSE << " subdir [" << o->GetName() << "]..."
01998 << endmsg;
01999 dst->cd ();
02000 TDirectory * dst_dir = dst->mkdir (o->GetName(), o->GetTitle());
02001 copyFileLayout (dst_dir, src);
02002 }
02003 }
02004 return;
02005 }
02006
02007
02011 StatusCode
02012 THistSvc::io_reinit ()
02013 {
02014 bool all_good = true;
02015 if (m_log.level() <= MSG::DEBUG)
02016 m_log << MSG::DEBUG << "reinitializing I/O..." << endmsg;
02017
02018
02019
02020 IIoComponentMgr* iomgr(0);
02021
02022 if (service("IoComponentMgr", iomgr, true).isFailure()) {
02023 m_log << MSG::ERROR << "could not retrieve I/O component manager !"
02024 << endmsg;
02025 return StatusCode::FAILURE;
02026 }
02027
02028 GlobalDirectoryRestore restore;
02029
02030
02031 gErrorIgnoreLevel = kFatal;
02032
02033 typedef std::map<std::string, std::pair<TFile*,Mode> > FileReg_t;
02034
02035 for (FileReg_t::iterator ifile = m_files.begin(), iend=m_files.end();
02036 ifile != iend; ++ifile) {
02037 TFile *f = ifile->second.first;
02038 std::string fname = f->GetName();
02039 if (m_log.level() <= MSG::DEBUG)
02040 m_log << MSG::DEBUG << "file [" << fname << "] mode: ["
02041 << f->GetOption() << "] r:"
02042 << f->GetFileBytesRead()
02043 << " w:" << f->GetFileBytesWritten()
02044 << " cnt:" << f->GetFileCounter()
02045 << endmsg;
02046
02047 if ( ifile->second.second == READ ) {
02048 if (m_log.level() <= MSG::DEBUG)
02049 m_log << MSG::DEBUG
02050 << " TFile opened in READ mode: not reassigning names" << endmsg;
02051 continue;
02052 }
02053
02054 if ( !iomgr->io_retrieve (this, fname).isSuccess () ) {
02055 m_log << MSG::ERROR << "could not retrieve new name for [" << fname
02056 << "] !!" << endmsg;
02057 all_good = false;
02058 continue;
02059 } else {
02060 if (m_log.level() <= MSG::DEBUG)
02061 m_log << MSG::DEBUG << "got a new name [" << fname << "]..." << endmsg;
02062 }
02063
02064 TFile *newfile = TFile::Open (fname.c_str(), f->GetOption());
02065 if (ifile->second.second != THistSvc::READ) {
02066 copyFileLayout (newfile, f);
02067 }
02068
02069
02070
02071 for ( uidMap::iterator uid = m_uids.begin(), uid_end = m_uids.end();
02072 uid != uid_end;
02073 ++uid ) {
02074 THistID& hid = uid->second;
02075 if ( hid.file != f ) {
02076 continue;
02077 }
02078 TDirectory *olddir = this->changeDir (hid);
02079 hid.file = newfile;
02080 ifile->second.first = newfile;
02081
02082 TDirectory *newdir = this->changeDir (hid);
02083 TClass *cl = hid.obj->IsA();
02084
02085
02086
02087 if (cl->InheritsFrom ("TTree")) {
02088 dynamic_cast<TTree*> (hid.obj)->SetDirectory (newdir);
02089 dynamic_cast<TTree*> (hid.obj)->Reset();
02090 }
02091 else if (cl->InheritsFrom ("TH1")) {
02092 dynamic_cast<TH1*> (hid.obj)->SetDirectory (newdir);
02093 dynamic_cast<TH1*> (hid.obj)->Reset();
02094 }
02095 else if (cl->InheritsFrom ("TGraph")) {
02096 olddir->Remove (hid.obj);
02097 newdir->Append (hid.obj);
02098 } else {
02099 m_log << MSG::ERROR
02100 << "id: \"" << hid.id << "\" is not a inheriting from a class "
02101 << "we know how to handle (received [" << cl->GetName()
02102 << "], " << "expected [TTree, TH1 or TGraph]) !"
02103 << endmsg
02104 << "attaching to current dir [" << newdir->GetPath() << "] "
02105 << "nonetheless..." << endmsg;
02106 olddir->Remove (hid.obj);
02107 newdir->Append (hid.obj);
02108 }
02109 }
02110 f->ReOpen ("READ");
02111 f->Close();
02112 f = newfile;
02113 }
02114
02115 return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE;
02116 }
02117
02118