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