00001 #include "THistSvc.h"
00002
00003 #include "GaudiKernel/SvcFactory.h"
00004 #include "GaudiKernel/ISvcLocator.h"
00005 #include "GaudiKernel/Tokenizer.h"
00006 #include "GaudiKernel/GaudiException.h"
00007 #include "GaudiKernel/Property.h"
00008 #include "GaudiKernel/IIncidentSvc.h"
00009 #include "GaudiKernel/IEventProcessor.h"
00010
00011 #include "TROOT.h"
00012 #include "TFile.h"
00013 #include "TDirectory.h"
00014 #include "TKey.h"
00015 #include "TError.h"
00016 #include "TGraph.h"
00017
00018 #include <sstream>
00019 #include <streambuf>
00020 #include <cstdio>
00021
00022 using namespace std;
00023
00024
00025 DECLARE_SERVICE_FACTORY(THistSvc)
00026
00027 inline void toupper(std::string &s)
00028 {
00029 std::string::iterator it=s.begin();
00030 while(it != s.end())
00031 {
00032 *it = toupper(*it);
00033 it++;
00034 }
00035 }
00036
00037
00038
00039
00040 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc )
00041 : base_class(name, svc), m_log(msgSvc(), name ), signaledStop(false) {
00042
00043 declareProperty ("Output", m_outputfile );
00044 declareProperty ("Input", m_inputfile );
00045 declareProperty ("AutoSave", m_autoSave=0 );
00046 declareProperty ("PrintAll", m_print=false);
00047 declareProperty ("CompressionLevel", m_compressionLevel=1 );
00048 declareProperty ("MaxFileSize", m_maxFileSize=5120,
00049 "maximum file size in MB. if exceeded, will cause an abort");
00050
00051 m_inputfile.declareUpdateHandler ( &THistSvc::setupInputFile, this );
00052 m_outputfile.declareUpdateHandler( &THistSvc::setupOutputFile, this );
00053 }
00054
00055
00056
00057 THistSvc::~THistSvc() {
00058
00059 }
00060
00061
00062
00063 StatusCode
00064 THistSvc::initialize() {
00065 GlobalDirectoryRestore restore;
00066
00067 m_alreadyConnectedOutFiles.clear();
00068 m_alreadyConnectedInFiles.clear();
00069
00070 StatusCode status = Service::initialize();
00071 m_log.setLevel( m_outputLevel.value() );
00072
00073 if (status.isFailure()) {
00074 MsgStream log ( msgSvc(), name() );
00075 log << MSG::ERROR << "initializing service" << endmsg;
00076 return status;
00077 }
00078
00079 vector<string>::const_iterator itr;
00080 StatusCode st(StatusCode::SUCCESS);
00081
00082 try {
00083 setupOutputFile( m_outputfile );
00084 } catch ( GaudiException& err ) {
00085 m_log << MSG::ERROR
00086 << "Caught: " << err << endmsg;
00087 st = StatusCode::FAILURE;
00088 }
00089
00090 try {
00091 setupInputFile( m_inputfile );
00092 } catch ( GaudiException& err ) {
00093 m_log << MSG::ERROR
00094 << "Caught: " << err << endmsg;
00095 st = StatusCode::FAILURE;
00096 }
00097
00098
00099 if ( 0 == gROOT ) {
00100 static TROOT root("root","ROOT I/O");
00101
00102 } else {
00103 m_log << MSG::VERBOSE << "ROOT already initialized, debug = "
00104 << gDebug<< endmsg;
00105 }
00106
00107 IIncidentSvc* p_incSvc(0);
00108
00109 if (service("IncidentSvc", p_incSvc, true).isFailure()) {
00110 m_log << MSG::ERROR << "unable to get the IncidentSvc" << endmsg;
00111 st = StatusCode::FAILURE;
00112 } else {
00113 p_incSvc->addListener( this, "EndEvent", 100, true);
00114 }
00115
00116 if (st.isFailure()) {
00117 m_log << MSG::FATAL << "Unable to initialize THistSvc" << endmsg;
00118 }
00119
00120 return st;
00121
00122 }
00123
00124
00125
00126 StatusCode
00127 THistSvc::reinitialize() {
00128
00129 GlobalDirectoryRestore restore;
00130
00131 m_log << MSG::WARNING << "reinitialize not implemented" << endmsg;
00132
00133
00134 return StatusCode::SUCCESS;
00135
00136 }
00137
00138
00139
00140 StatusCode
00141 THistSvc::finalize() {
00142
00143 GlobalDirectoryRestore restore;
00144
00145 m_log << MSG::DEBUG << "THistSvc::finalize" << endmsg;
00146
00147 uidMap::const_iterator uitr;
00148 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
00149
00150 TObject* to = uitr->second.obj;
00151
00152 string dirname("none");
00153 if (to->IsA()->InheritsFrom("TTree")) {
00154 TTree* tr = dynamic_cast<TTree*>(to);
00155 if (tr->GetDirectory() != 0) {
00156 dirname = tr->GetDirectory()->GetPath();
00157 }
00158 } else if (to->IsA()->InheritsFrom("TGraph")) {
00159 if (!uitr->second.temp) {
00160 dirname = uitr->second.file->GetPath();
00161 string id2(uitr->second.id);
00162 id2.erase(0,id2.find("/",1));
00163 id2.erase(id2.rfind("/"), id2.length());
00164 if (id2.find("/") == 0) {
00165 id2.erase(0,1);
00166 }
00167 dirname += id2;
00168 } else {
00169 dirname = "/tmp";
00170 }
00171 } else if (to->IsA()->InheritsFrom("TH1")) {
00172 TH1* th = dynamic_cast<TH1*>(to);
00173 if (th == 0) {
00174 m_log << MSG::ERROR << "Couldn't dcast: " << uitr->first << endmsg;
00175 } else {
00176 if (th->GetDirectory() != 0) {
00177 dirname = th->GetDirectory()->GetPath();
00178 }
00179 }
00180 }
00181
00182 m_log << MSG::DEBUG << "uid: \"" << uitr->first << "\" temp: "
00183 << uitr->second.temp << " dir: " << dirname
00184 << endmsg;
00185
00186
00187
00188
00189
00190
00191 }
00192
00193 StatusCode sc = write();
00194 if (sc.isFailure()) {
00195 m_log << MSG::ERROR << "problems writing histograms" << endmsg;
00196 }
00197
00198 if (m_print) {
00199 m_log << MSG::INFO << "Listing contents of ROOT files: " << endmsg;
00200 }
00201 vector<TFile*> deleted_files;
00202 map<string, pair<TFile*,Mode> >::const_iterator itr;
00203 for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
00204
00205 if (find(deleted_files.begin(), deleted_files.end(), itr->second.first) ==
00206 deleted_files.end()) {
00207 deleted_files.push_back(itr->second.first);
00208
00209 m_log << MSG::DEBUG << "finalizing stream/file " << itr->first << ":"
00210 << itr->second.first->GetName()
00211 << endmsg;
00212 } else {
00213 m_log << MSG::DEBUG << "already finalized stream " << itr->first << endmsg;
00214 continue;
00215 }
00216
00217
00218 if (m_print && m_log.level() <= MSG::INFO) {
00219
00220 m_log << MSG::INFO;
00221 m_log << "==> File: " << itr->second.first->GetName()
00222 << " stream: " << itr->first << endmsg;
00223
00224 itr->second.first->Print("base");
00225 }
00226
00227 string tmpfn=itr->second.first->GetName();
00228
00229 itr->second.first->Close();
00230
00231 if (itr->second.second==SHARE) {
00232 TFile *outputfile;
00233
00234 try {
00235 m_log << MSG::DEBUG << "Opening Final Output File: " <<m_sharedFiles[itr->first].c_str()<<endmsg;
00236 outputfile = new TFile(m_sharedFiles[itr->first].c_str(), "UPDATE");
00237 } catch (const std::exception& Exception) {
00238 m_log << MSG::ERROR << "exception caught while trying to open root"
00239 << " file for appending: " << Exception.what() << std::endl
00240 << " -> file probably corrupt." << endmsg;
00241 return StatusCode::FAILURE;
00242 } catch (...) {
00243 m_log << MSG::ERROR << "Problems opening output file \"" << m_sharedFiles[itr->first]
00244 << "\" for append: probably corrupt" << endmsg;
00245 return StatusCode::FAILURE;
00246 }
00247
00248 m_log << MSG::DEBUG << "THistSvc::write()::Merging Rootfile "<<endmsg;
00249 TFile *inputfile;
00250 try {
00251 m_log << MSG::DEBUG << "Openning again Temporary File: " <<tmpfn.c_str()<<endmsg;
00252 inputfile=new TFile(tmpfn.c_str(),"READ");
00253 } catch (const std::exception& Exception) {
00254 m_log << MSG::ERROR << "exception caught while trying to open root"
00255 << " file for appending: " << Exception.what() << std::endl
00256 << " -> file probably corrupt." << endmsg;
00257 return StatusCode::FAILURE;
00258 } catch (...) {
00259 m_log << MSG::ERROR << "Problems opening output file \""
00260 << tmpfn.c_str()
00261 << "\" for append: probably corrupt" << endmsg;
00262 return StatusCode::FAILURE;
00263 }
00264
00265 MergeRootFile(outputfile, inputfile);
00266
00267 outputfile->SetCompressionLevel( m_compressionLevel );
00268
00269 outputfile->Write();
00270 outputfile->Close();
00271 inputfile->Close();
00272
00273 m_log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn
00274 << "\""<<endmsg;
00275
00276 std::remove(tmpfn.c_str());
00277 }
00278 delete itr->second.first;
00279 }
00280
00281 m_sharedFiles.clear();
00282 m_fileStreams.clear();
00283 m_files.clear();
00284 m_uids.clear();
00285 m_ids.clear();
00286 m_tobjs.clear();
00287
00288 return Service::finalize();
00289 }
00290
00291
00292
00293 bool
00294 THistSvc::browseTDir(TDirectory *dir) const {
00295
00296 if (dir == 0) {
00297 std::cerr << "TDirectory == 0" << std::endl;
00298 return false;
00299 }
00300
00301 GlobalDirectoryRestore restore;
00302
00303 dir->cd();
00304
00305
00306 cout << "-> " << dir->GetPath() << " "
00307 << dir->GetListOfKeys()->GetSize() << endl;
00308
00309
00310 TIter nextkey(dir->GetList());
00311 while (TKey *key = (TKey*)nextkey()) {
00312
00313 TObject *obj = key->ReadObj();
00314 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00315
00316 cout << " Key: " << key->GetName() << " "
00317 << " tit: " << obj->GetTitle() << " "
00318 << " (" << key->GetClassName() << ")" << endl;
00319
00320 }
00321
00322 nextkey = dir->GetListOfKeys();
00323 while (TKey *key = (TKey*)nextkey()) {
00324
00325 TObject *obj = key->ReadObj();
00326 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00327 if (obj->IsA()->InheritsFrom("TDirectory")) {
00328 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00329 browseTDir(tt);
00330 }
00331 }
00332
00333 return true;
00334 }
00335
00336
00337
00338 StatusCode
00339 THistSvc::getTHists(TDirectory *td, TList & tl) const {
00340
00341 GlobalDirectoryRestore restore;
00342
00343 gErrorIgnoreLevel = kBreak;
00344
00345 if (!td->cd()) {
00346 m_log << MSG::ERROR << "No such TDirectory \"" << td->GetPath() << "\""
00347 << endmsg;
00348 return StatusCode::FAILURE;
00349 }
00350
00351 TIter nextkey(td->GetList());
00352 while (TObject *key = (TObject*)nextkey()) {
00353 if (key != 0) {
00354 if (key->IsA()->InheritsFrom("TH1")) { tl.Add(key); }
00355 }
00356 }
00357
00358
00359 return StatusCode::SUCCESS;
00360
00361 }
00362
00363
00364
00365 StatusCode
00366 THistSvc::getTHists(const std::string& dir, TList & tl) const {
00367
00368 GlobalDirectoryRestore restore;
00369
00370 gErrorIgnoreLevel = kBreak;
00371
00372 StatusCode sc;
00373
00374 if (!gDirectory->cd(dir.c_str())) {
00375 m_log << MSG::ERROR << "No such TDirectory \"" << dir << "\""
00376 << endmsg;
00377 sc = StatusCode::FAILURE;
00378 } else {
00379 sc = getTHists(gDirectory,tl);
00380 }
00381
00382 return sc;
00383
00384 }
00385
00386
00387 StatusCode
00388 THistSvc::getTTrees(TDirectory *td, TList & tl) const {
00389
00390 GlobalDirectoryRestore restore;
00391
00392 gErrorIgnoreLevel = kBreak;
00393
00394 if (!td->cd()) {
00395 m_log << MSG::ERROR << "No such TDirectory \"" << td->GetPath() << "\""
00396 << endmsg;
00397 return StatusCode::FAILURE;
00398 }
00399
00400 TIter nextkey(td->GetList());
00401 while (TObject *key = (TObject*)nextkey()) {
00402 if (key != 0) {
00403 if (key->IsA()->InheritsFrom("TTree")) { tl.Add(key); }
00404 }
00405 }
00406
00407 return StatusCode::SUCCESS;
00408
00409 }
00410
00411
00412
00413 StatusCode
00414 THistSvc::getTTrees(const std::string& dir, TList & tl) const {
00415
00416 GlobalDirectoryRestore restore;
00417
00418 gErrorIgnoreLevel = kBreak;
00419
00420 StatusCode sc;
00421
00422 if (!gDirectory->cd(dir.c_str())) {
00423 m_log << MSG::ERROR << "No such TDirectory \"" << dir << "\""
00424 << endmsg;
00425 sc = StatusCode::FAILURE;
00426 } else {
00427 sc = getTTrees(gDirectory,tl);
00428 }
00429
00430 return sc;
00431
00432 }
00433
00434
00435
00436 StatusCode
00437 THistSvc::deReg(TObject* obj) {
00438
00439 objMap::iterator itr = m_tobjs.find(obj);
00440 if (itr != m_tobjs.end()) {
00441 THistID hid = itr->second;
00442
00443 uidMap::iterator itr2 = m_uids.find(hid.id);
00444 if (itr2 == m_uids.end()) {
00445 m_log << MSG::ERROR << "Problems deregistering TObject \""
00446 << obj->GetName()
00447 << "\" with id \"" << hid.id << "\"" << endmsg;
00448 return StatusCode::FAILURE;
00449 }
00450
00451 std::string id,root,rem;
00452 parseString(hid.id, root, rem);
00453
00454 idMap::iterator itr3;
00455 bool found(false);
00456
00457 std::pair<idMap::iterator, idMap::iterator> mitr = m_ids.equal_range(rem);
00458 if (mitr.first == mitr.second) {
00459 m_log << MSG::ERROR << "Problems deregistering TObject \""
00460 << obj->GetName()
00461 << "\" with id \"" << hid.id << "\"" << endmsg;
00462 return StatusCode::FAILURE;
00463 } else {
00464 for (itr3 = mitr.first; itr3 != mitr.second; ++itr3) {
00465 if (itr3->second.obj == obj) {
00466 found = true;
00467 break;
00468 }
00469 }
00470 if (!found) {
00471 m_log << MSG::ERROR << "Problems deregistering TObject \""
00472 << obj->GetName()
00473 << "\" with id \"" << hid.id << "\"" << endmsg;
00474 }
00475 }
00476
00477 m_tobjs.erase(itr);
00478 m_uids.erase(itr2);
00479 m_ids.erase(itr3);
00480
00481 return StatusCode::SUCCESS;
00482
00483 } else {
00484 m_log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName()
00485 << "\": not known to THistSvc" << endmsg;
00486 return StatusCode::FAILURE;
00487 }
00488
00489 }
00490
00491
00492
00493
00494 StatusCode
00495 THistSvc::deReg(const std::string& id) {
00496
00497 uidMap::iterator itr = m_uids.find(id);
00498 if (itr == m_uids.end()) {
00499 m_log << MSG::ERROR << "Problems deregistering id \""
00500 << id << "\"" << endmsg;
00501 return StatusCode::FAILURE;
00502 }
00503
00504 TObject* obj = itr->second.obj;
00505
00506 return deReg(obj);
00507 }
00508
00509
00510
00511 StatusCode
00512 THistSvc::regHist(const std::string& id) {
00513
00514 TH1 *hist(0);
00515
00516 return regHist_i(hist, id);
00517 }
00518
00519
00520
00521 StatusCode
00522 THistSvc::regHist(const std::string& id, TH1* hist) {
00523 return regHist_i(hist, id);
00524 }
00525
00526
00527
00528 StatusCode
00529 THistSvc::regHist(const std::string& id, TH2* hist) {
00530 return regHist_i(hist, id);
00531 }
00532
00533
00534
00535 StatusCode
00536 THistSvc::regHist(const std::string& id, TH3* hist) {
00537 return regHist_i(hist, id);
00538 }
00539
00540
00541
00542 StatusCode
00543 THistSvc::regTree(const std::string& id) {
00544 TTree *hist(0);
00545 return regHist_i(hist, id);
00546 }
00547
00548
00549
00550 StatusCode
00551 THistSvc::regTree(const std::string& id, TTree* hist) {
00552 StatusCode sc = regHist_i(hist, id);
00553 if (hist != 0 && m_autoSave != 0 && sc.isSuccess()) {
00554 hist->SetAutoSave(m_autoSave);
00555 }
00556 return sc;
00557 }
00558
00559
00560
00561 StatusCode
00562 THistSvc::regGraph(const std::string& id) {
00563 TGraph *hist(0);
00564 return regHist_i(hist, id);
00565 }
00566
00567
00568
00569 StatusCode
00570 THistSvc::regGraph(const std::string& id, TGraph* hist) {
00571 if ( strcmp(hist->GetName(),"Graph") == 0 ) {
00572
00573 std::string id2(id);
00574 string::size_type i = id2.rfind("/");
00575 if (i != string::npos) {
00576 id2.erase(0,i+1);
00577 }
00578
00579 m_log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \""
00580 << id2 << "\" since it is unset" << endmsg;
00581 hist->SetName(id2.c_str());
00582 }
00583
00584 return regHist_i(hist, id);
00585 }
00586
00587
00588
00589 StatusCode
00590 THistSvc::getHist(const std::string& id, TH1*& hist) const {
00591 return getHist_i(id, hist);
00592 }
00593
00594
00595
00596 StatusCode
00597 THistSvc::getHist(const std::string& id, TH2*& hist) const {
00598 return getHist_i(id, hist);
00599 }
00600
00601
00602
00603 StatusCode
00604 THistSvc::getHist(const std::string& id, TH3*& hist) const {
00605 return getHist_i(id, hist);
00606 }
00607
00608
00609
00610 std::vector<std::string>
00611 THistSvc::getHists() const {
00612
00613 std::vector<std::string> names;
00614 names.reserve(m_uids.size());
00615
00616 uidMap::const_iterator itr;
00617 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
00618 THistID tid = itr->second;
00619
00620 if (tid.obj->IsA()->InheritsFrom("TH1")) {
00621 names.push_back(itr->first);
00622 }
00623
00624 }
00625
00626 return names;
00627
00628 }
00629
00630
00631 StatusCode
00632 THistSvc::getTree(const std::string& id, TTree*& hist) const {
00633 return getHist_i(id, hist);
00634 }
00635
00636
00637
00638 std::vector<std::string>
00639 THistSvc::getTrees() const {
00640
00641 std::vector<std::string> names;
00642 names.reserve(m_uids.size());
00643
00644 uidMap::const_iterator itr;
00645 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
00646 THistID tid = itr->second;
00647
00648 if (tid.obj->IsA()->InheritsFrom("TTree")) {
00649 names.push_back(itr->first);
00650 }
00651
00652 }
00653
00654 return names;
00655
00656 }
00657
00658
00659 StatusCode
00660 THistSvc::getGraph(const std::string& id, TGraph*& hist) const {
00661 return getHist_i(id, hist);
00662 }
00663
00664
00665
00666 std::vector<std::string>
00667 THistSvc::getGraphs() const {
00668
00669 std::vector<std::string> names;
00670 names.reserve(m_uids.size());
00671
00672 uidMap::const_iterator itr;
00673 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
00674 THistID tid = itr->second;
00675
00676 if (tid.obj->IsA()->InheritsFrom("TGraph")) {
00677 names.push_back(itr->first);
00678 }
00679
00680 }
00681
00682 return names;
00683
00684 }
00685
00686
00687 StatusCode
00688 THistSvc::readHist(const std::string& id, TH1*& hist) const {
00689 return readHist_i(id, hist);
00690 }
00691
00692
00693
00694 StatusCode
00695 THistSvc::readHist(const std::string& id, TH2*& hist) const {
00696 return readHist_i(id, hist);
00697 }
00698
00699
00700
00701 StatusCode
00702 THistSvc::readHist(const std::string& id, TH3*& hist) const {
00703 return readHist_i(id, hist);
00704 }
00705
00706
00707
00708 StatusCode
00709 THistSvc::readTree(const std::string& id, TTree*& hist) const {
00710 return readHist_i(id, hist);
00711 }
00712
00713
00714
00715 bool
00716 THistSvc::findStream(const string& id, string& stream, string& rem,
00717 TFile*& file) const {
00718
00719 string::size_type pos = id.find("/");
00720
00721 if (pos == string::npos) {
00722 stream = "temp";
00723 rem = id;
00724 } else if (pos != 0) {
00725 stream = "temp";
00726 rem = id;
00727 } else {
00728
00729 string::size_type pos2 = id.find("/",pos+1);
00730
00731 if (pos2 == string::npos) {
00732 m_log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\""
00733 << endmsg;
00734 return false;
00735 }
00736
00737 parseString(id,stream,rem);
00738
00739 }
00740
00741 if (stream == "temp") {
00742 file = 0;
00743 return true;
00744 }
00745
00746 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00747 if (itr != m_files.end()) {
00748 file = itr->second.first;
00749 } else {
00750 file = 0;
00751 m_log << MSG::WARNING << "no stream \"" << stream
00752 << "\" associated with id: \"" << id << "\""
00753 << endmsg;
00754 }
00755
00756 return true;
00757
00758 }
00759
00760
00761
00762 void
00763 THistSvc::parseString(const string& id, string& root, string& rem) const {
00764 string::size_type pos = id.find("/");
00765
00766 if (pos == string::npos) {
00767 root = "";
00768 rem = id;
00769 return;
00770 }
00771
00772 if (pos == 0) {
00773 parseString(id.substr(1,id.length()),root,rem);
00774 } else {
00775 root = id.substr(0,pos);
00776 rem = id.substr(pos+1,id.length());
00777 }
00778
00779 }
00780
00781
00782
00783 void
00784 THistSvc::setupInputFile( Property& )
00785 {
00786 StatusCode sc = StatusCode::SUCCESS;
00787
00788 typedef std::vector<std::string> Strings_t;
00789 for ( Strings_t::const_iterator
00790 itr = m_inputfile.value().begin(),
00791 iEnd = m_inputfile.value().end();
00792 itr != iEnd;
00793 ++itr ) {
00794 if ( m_alreadyConnectedInFiles.end() ==
00795 m_alreadyConnectedInFiles.find( *itr ) ) {
00796 if ( connect(*itr).isFailure() ) {
00797 sc = StatusCode::FAILURE;
00798 } else {
00799 m_alreadyConnectedInFiles.insert( *itr );
00800 }
00801 }
00802 }
00803
00804 if ( !sc.isSuccess() ) {
00805 throw GaudiException( "Problem connecting inputfile !!", name(),
00806 StatusCode::FAILURE );
00807 }
00808 return;
00809 }
00810
00811
00812
00813 void
00814 THistSvc::setupOutputFile( Property& )
00815 {
00816 StatusCode sc = StatusCode::SUCCESS;
00817
00818 typedef std::vector<std::string> Strings_t;
00819 for ( Strings_t::const_iterator
00820 itr = m_outputfile.value().begin(),
00821 iEnd = m_outputfile.value().end();
00822 itr != iEnd;
00823 ++itr ) {
00824 if ( m_alreadyConnectedOutFiles.end() ==
00825 m_alreadyConnectedOutFiles.find( *itr ) ) {
00826 if ( connect(*itr).isFailure() ) {
00827 sc = StatusCode::FAILURE;
00828 } else {
00829 m_alreadyConnectedOutFiles.insert( *itr );
00830 }
00831 }
00832 }
00833
00834 if ( !sc.isSuccess() ) {
00835 throw GaudiException( "Problem connecting outputfile !!", name(),
00836 StatusCode::FAILURE );
00837 }
00838 return;
00839 }
00840
00841
00842
00843 void
00844 THistSvc::updateFiles() {
00845
00846
00847
00848
00849
00850
00851 uidMap::iterator uitr, uitr2;
00852 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
00853 TObject* to = uitr->second.obj;
00854 TFile* oldFile = uitr->second.file;
00855 if (to->IsA()->InheritsFrom("TTree")) {
00856 TTree* tr = dynamic_cast<TTree*>(to);
00857 TFile* newFile = tr->GetCurrentFile();
00858
00859 if (oldFile != newFile) {
00860 std::string newFileName = newFile->GetName();
00861 std::string oldFileName(""), streamName, rem;
00862 TFile* dummy;
00863 findStream(uitr->second.id, streamName, rem, dummy);
00864
00865 map<string, pair<TFile*,Mode> >::iterator itr;
00866 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
00867 if (itr->second.first == oldFile) {
00868 itr->second.first = newFile;
00869
00870 }
00871 }
00872
00873 uitr2 = uitr;
00874 for (; uitr2 != m_uids.end(); ++uitr2) {
00875 if (uitr2->second.file == oldFile) {
00876 uitr2->second.file = newFile;
00877 }
00878 }
00879
00880 streamMap::iterator sitr;
00881 for (sitr = m_fileStreams.begin(); sitr!=m_fileStreams.end(); ++sitr) {
00882 if (sitr->second == streamName) {
00883 oldFileName = sitr->first;
00884 break;
00885 }
00886 }
00887
00888
00889 #ifndef NDEBUG
00890 m_log << MSG::DEBUG << "migrating uid: " << uitr->second.id
00891 << " stream: " << streamName
00892 << " oldFile: " << oldFileName
00893 << " newFile: " << newFileName
00894 << endmsg;
00895 #endif
00896
00897
00898 if (oldFileName != "") {
00899 while ( (sitr=m_fileStreams.find(oldFileName)) != m_fileStreams.end() ) {
00900
00901 #ifndef NDEBUG
00902 m_log << MSG::DEBUG << "changing filename \"" << oldFileName
00903 << "\" to \"" << newFileName << "\" for stream \""
00904 << sitr->second << "\"" << endmsg;
00905 #endif
00906 m_fileStreams.erase(sitr);
00907 m_fileStreams.insert( make_pair<std::string,std::string>(newFileName,streamName) );
00908 }
00909
00910
00911 } else {
00912 m_log << MSG::ERROR
00913 << "Problems updating fileStreams with new file name" << endmsg;
00914 }
00915
00916 }
00917
00918 }
00919 }
00920
00921 }
00922
00923
00924
00925 StatusCode
00926 THistSvc::write() {
00927
00928 updateFiles();
00929
00930 map<string, pair<TFile*,Mode> >::const_iterator itr;
00931 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
00932 if (itr->second.second == WRITE || itr->second.second == UPDATE
00933 ||itr->second.second==SHARE) {
00934 itr->second.first->Write("",TObject::kOverwrite);
00935 } else if (itr->second.second == APPEND) {
00936 itr->second.first->Write("");
00937 }
00938 }
00939
00940
00941 m_log << MSG::DEBUG << "THistSvc::write()::List of Files connected in ROOT "
00942 << endmsg;
00943
00944 TSeqCollection *filelist=gROOT->GetListOfFiles();
00945 for (int ii=0; ii<filelist->GetEntries(); ii++) {
00946 m_log << MSG::DEBUG
00947 << "THistSvc::write()::List of Files connected in ROOT: \""
00948 << filelist->At(ii)->GetName()<<"\""<<endmsg;
00949 }
00950
00951 return StatusCode::SUCCESS;
00952
00953 }
00954
00955
00956
00957 StatusCode
00958 THistSvc::connect(const std::string& ident) {
00959
00960 Tokenizer tok(true);
00961
00962 string::size_type loc = ident.find(" ");
00963 string stream = ident.substr(0,loc);
00964 char typ(0);
00965 typedef std::pair<std::string,std::string> Prop;
00966 std::vector<Prop> props;
00967 string val,VAL,TAG,filename,db_typ("ROOT");
00968
00969 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
00970
00971 for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++) {
00972 const std::string& tag = (*i).tag();
00973 TAG = tag;
00974 toupper(TAG);
00975
00976 val = (*i).value();
00977 VAL = val;
00978 toupper(VAL);
00979
00980 if (TAG == "FILE" || TAG == "DATAFILE") {
00981 filename = val;
00982 removeDoubleSlash( filename );
00983 } else if ( TAG == "OPT" ) {
00984 if ( VAL == "APPEND" || VAL == "UPDATE" ) {
00985 typ = 'A';
00986 } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
00987 typ = 'N';
00988 } else if ( VAL == "RECREATE" ) {
00989 typ = 'R';
00990 } else if (VAL == "SHARE") {
00991 typ = 'S';
00992 } else if ( VAL == "OLD" || VAL == "READ" ) {
00993 typ = 'O';
00994 } else {
00995 m_log << MSG::ERROR << "Unknown OPT: \"" << (*i).value() << "\""
00996 << endmsg;
00997 typ = 0;
00998 }
00999 } else if (TAG == "TYP") {
01000 db_typ = (*i).value();
01001 } else {
01002 props.push_back( Prop((*i).tag(), (*i).value()));
01003 }
01004
01005 }
01006
01007 if (stream == "temp") {
01008 m_log << MSG::ERROR << "in JobOption \"" << ident
01009 << "\": stream name \"temp\" reserved."
01010 << endmsg;
01011 return StatusCode::FAILURE;
01012 }
01013
01014 if (db_typ != "ROOT") {
01015 m_log << MSG::ERROR << "in JobOption \"" << ident
01016 << "\": technology type \"" << db_typ << "\" not supported."
01017 << endmsg;
01018 return StatusCode::FAILURE;
01019 }
01020
01021
01022 if (m_files.find(stream) != m_files.end()) {
01023 m_log << MSG::ERROR << "in JobOption \"" << ident
01024 << "\":\n stream \"" << stream << "\" already connected to file: \""
01025 << m_files[stream].first->GetName() << "\""
01026 << endmsg;
01027 return StatusCode::FAILURE;
01028 }
01029
01030 Mode newMode;
01031 if (typ == 'O') {
01032 newMode = THistSvc::READ;
01033 } else if (typ == 'N') {
01034 newMode = THistSvc::WRITE;
01035 } else if (typ == 'A') {
01036 newMode = THistSvc::APPEND;
01037 } else if (typ == 'R') {
01038 newMode = THistSvc::UPDATE;
01039 } else if (typ == 'S') {
01040 newMode = THistSvc::SHARE;
01041 } else {
01042
01043 m_log << MSG::ERROR << "No OPT= specified or unknown access mode in: "
01044 << ident << endmsg;
01045 return StatusCode::FAILURE;
01046 }
01047
01048
01049 if (m_fileStreams.find(filename) != m_fileStreams.end()) {
01050 std::pair<streamMap::iterator, streamMap::iterator> fitr =
01051 m_fileStreams.equal_range(filename);
01052
01053 std::string oldstream = (fitr.first)->second;
01054
01055 std::pair<TFile*,Mode> f_info = m_files[oldstream];
01056
01057 if (newMode != f_info.second) {
01058 m_log << MSG::ERROR << "in JobOption \"" << ident
01059 << "\":\n file \"" << filename << "\" already opened by stream: \""
01060 << oldstream << "\" with different access mode."
01061 << endmsg;
01062 return StatusCode::FAILURE;
01063 } else {
01064 TFile *f2 = f_info.first;
01065 m_files[stream] = make_pair<TFile*,Mode>(f2,newMode);
01066 m_log << MSG::DEBUG << "Connecting stream: \"" << stream
01067 << "\" to previously opened TFile: \"" << filename << "\""
01068 << endmsg;
01069 return StatusCode::SUCCESS;
01070 }
01071 }
01072
01073
01074 TFile *f(0) ;
01075 if (newMode == THistSvc::READ) {
01076
01077
01078 try {
01079 f = TFile::Open(filename.c_str(),"READ");
01080 } catch (const std::exception& Exception) {
01081 m_log << MSG::ERROR << "exception caught while trying to open root"
01082 << " file for reading: " << Exception.what() << std::endl
01083 << " -> file probably corrupt." << endmsg;
01084 return StatusCode::FAILURE;
01085 } catch (...) {
01086 m_log << MSG::ERROR << "Problems opening input file \"" << filename
01087 << "\": probably corrupt" << endmsg;
01088 return StatusCode::FAILURE;
01089 }
01090
01091 if (!f->IsOpen()) {
01092 m_log << MSG::ERROR << "Unable to open input file \"" << filename
01093 << "\": file does not exist" << endmsg;
01094 return StatusCode::FAILURE;
01095 }
01096
01097
01098 } else if (newMode == THistSvc::WRITE) {
01099
01100
01101 f = TFile::Open(filename.c_str(),"NEW");
01102 if (!f->IsOpen()) {
01103 m_log << MSG::ERROR << "Unable to create new output file \"" << filename
01104 << "\" for writing: file already exists" << endmsg;
01105 return StatusCode::FAILURE;
01106 }
01107 f->SetCompressionLevel( m_compressionLevel );
01108
01109 } else if (newMode == THistSvc::APPEND) {
01110
01111
01112 try {
01113 f = TFile::Open(filename.c_str(),"UPDATE");
01114 } catch (const std::exception& Exception) {
01115 m_log << MSG::ERROR << "exception caught while trying to open root"
01116 << " file for appending: " << Exception.what() << std::endl
01117 << " -> file probably corrupt." << endmsg;
01118 return StatusCode::FAILURE;
01119 } catch (...) {
01120 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01121 << "\" for append: probably corrupt" << endmsg;
01122 return StatusCode::FAILURE;
01123 }
01124
01125 if (!f->IsOpen()) {
01126 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01127 << "\" for appending" << endmsg;
01128 return StatusCode::FAILURE;
01129 }
01130 f->SetCompressionLevel( m_compressionLevel );
01131
01132 } else if (newMode == THistSvc::SHARE) {
01133
01134
01135
01136
01137 static int ishared = 0;
01138 stringstream out;
01139 string realfilename=filename;
01140 out << ishared++;
01141 filename = string("tmp_THistSvc_")+out.str()+string(".root");
01142
01143 m_log << MSG::DEBUG << "Creating temp file \"" << filename
01144 << "\" and realfilename="<<realfilename << endmsg;
01145 m_sharedFiles[stream]=realfilename;
01146
01147 try {
01148 f = TFile::Open(filename.c_str(),"NEW");
01149 } catch (const std::exception& Exception) {
01150 m_log << MSG::ERROR << "exception caught while trying to open root"
01151 << " file for appending: " << Exception.what() << std::endl
01152 << " -> file probably corrupt." << endmsg;
01153 return StatusCode::FAILURE;
01154 } catch (...) {
01155 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01156 << "\" for append: probably corrupt" << endmsg;
01157 return StatusCode::FAILURE;
01158 }
01159
01160 if (!f->IsOpen()) {
01161 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01162 << "\" for appending" << endmsg;
01163 return StatusCode::FAILURE;
01164 }
01165 f->SetCompressionLevel( m_compressionLevel );
01166
01167 } else if (newMode == THistSvc::UPDATE) {
01168
01169
01170 try {
01171 f = TFile::Open(filename.c_str(),"RECREATE");
01172 } catch (const std::exception& Exception) {
01173 m_log << MSG::ERROR << "exception caught while trying to open root"
01174 << " file for updating: " << Exception.what() << std::endl
01175 << " -> file probably corrupt." << endmsg;
01176 return StatusCode::FAILURE;
01177 } catch (...) {
01178 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01179 << "\" for update: probably corrupt" << endmsg;
01180 return StatusCode::FAILURE;
01181 }
01182
01183 if (!f->IsOpen()) {
01184 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01185 << "\" for updating" << endmsg;
01186 return StatusCode::FAILURE;
01187 }
01188 f->SetCompressionLevel( m_compressionLevel );
01189
01190 }
01191
01192 m_files[stream] = make_pair<TFile*,Mode>(f,newMode);
01193 m_fileStreams.insert(make_pair<std::string,std::string>(filename,stream));
01194
01195 m_log << MSG::DEBUG << "Opening TFile \"" << filename << "\" stream: \""
01196 << stream << "\" mode: \"" << typ << "\""
01197 << endmsg;
01198
01199 return StatusCode::SUCCESS;
01200 }
01201
01202
01203
01204 TDirectory*
01205 THistSvc::changeDir(const THistSvc::THistID& hid) const {
01206
01207 string uid = hid.id;
01208 TFile* file = hid.file;
01209 string stream, fdir, bdir, dir, id;
01210
01211 if (file != 0) {
01212 file->cd("/");
01213 } else {
01214 gROOT->cd();
01215 }
01216
01217 fdir = uid;
01218 bdir = dirname(fdir);
01219
01220 while ( (dir = dirname(fdir)) != "") {
01221 if (! gDirectory->GetKey(dir.c_str())) {
01222 gDirectory->mkdir(dir.c_str());
01223 }
01224 gDirectory->cd(dir.c_str());
01225 }
01226
01227 return gDirectory;
01228
01229 }
01230
01231
01232
01233 std::string
01234 THistSvc::dirname(std::string& dir) const {
01235
01236
01237 string::size_type i = dir.find("/");
01238
01239 if (i == string::npos) {
01240 return "";
01241 }
01242
01243 if ( i == 0 ) {
01244 dir.erase(0,1);
01245 return dirname(dir);
01246 }
01247
01248 string root = dir.substr(0,i);
01249 dir.erase(0,i);
01250
01251 return root;
01252
01253 }
01254
01255
01256
01257 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore() {
01258 m_gd = gDirectory;
01259 m_gf = gFile;
01260 m_ge = gErrorIgnoreLevel;
01261 }
01262
01263 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore() {
01264 gDirectory = m_gd;
01265 gFile = m_gf;
01266 gErrorIgnoreLevel = m_ge;
01267 }
01268
01269
01270
01271 void
01272 THistSvc::removeDoubleSlash(std::string& id) const {
01273
01274 while (id.find("//") != std::string::npos) {
01275 id.replace(id.find("//"),2,"/");
01276 }
01277
01278 }
01279
01280
01281
01282 void THistSvc::MergeRootFile(TDirectory *target, TDirectory *source) {
01283
01284 m_log <<MSG::DEBUG << "Target path: " << target->GetPath() << endmsg;
01285 TString path( (char*)strstr(target->GetPath(), ":") );
01286 path.Remove( 0, 2);
01287
01288 source->cd(path);
01289 TDirectory *current_sourcedir = gDirectory;
01290
01291
01292 TList *lkeys=current_sourcedir->GetListOfKeys();
01293 int nkeys=lkeys->GetEntries();
01294 TKey *key;
01295 for (int jj=0; jj<nkeys; jj++) {
01296 key=(TKey*) lkeys->At(jj);
01297 string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName();
01298 m_log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endmsg;
01299
01300
01301 TObject *obj=source->Get(pathnameinsource.c_str());
01302
01303 if (obj->IsA()->InheritsFrom("TDirectory") ) {
01304
01305
01306 m_log <<MSG::DEBUG << "Found subdirectory " << obj->GetName()
01307 << endmsg;
01308
01309
01310 target->cd();
01311 TDirectory *newtargetdir =
01312 target->mkdir(obj->GetName(), obj->GetTitle() );
01313
01314 MergeRootFile(newtargetdir, source);
01315
01316 } else if (obj->IsA()->InheritsFrom("TTree")) {
01317 m_log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endmsg;
01318 TTree *mytree=dynamic_cast<TTree*>(obj);
01319 int nentries=(int) mytree->GetEntries();
01320 mytree->SetBranchStatus("*",1);
01321
01322 m_log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries"
01323 << endmsg;
01324
01325
01326
01327
01328
01329
01330 target->cd();
01331 mytree->CloneTree();
01332
01333
01334
01335
01336
01337 } else if (obj) {
01338 target->cd();
01339 obj->Write(key->GetName() );
01340 }
01341
01342 }
01343
01344
01345
01346 }
01347
01348
01349
01350 bool
01351 THistSvc::exists( const std::string& name ) const {
01352
01353 TH1* h;
01354
01355 return getHist_i(name,h,true).isSuccess();
01356
01357
01358 }
01359
01360
01361
01362 void
01363 THistSvc::handle( const Incident& ) {
01364
01365 if (signaledStop) return ;
01366
01367
01368 Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
01369
01370 updateFiles();
01371
01372 map<string, pair<TFile*,Mode> >::const_iterator itr;
01373 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01374 TFile* tf = itr->second.first;
01375
01376 #ifndef NDEBUG
01377 m_log << MSG::DEBUG << "stream: " << itr->first << " name: "
01378 << tf->GetName() << " size: " << tf->GetSize()
01379 << endmsg;
01380 #endif
01381
01382
01383 if (tf->GetSize() > mfs) {
01384
01385 signaledStop = true;
01386
01387 m_log << MSG::FATAL << "file \"" << tf->GetName()
01388 << "\" associated with stream \"" << itr->first
01389 << "\" has exceeded the max file size of "
01390 << m_maxFileSize.value() << "MB. Terminating Job."
01391 << endmsg;
01392
01393 IEventProcessor* evt(0);
01394 if (service("ApplicationMgr", evt, true).isSuccess()) {
01395 evt->stopRun();
01396 evt->release();
01397 } else {
01398 abort();
01399 }
01400 }
01401 }
01402 }