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