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