Gaudi Framework, version v20r2

Generated: 18 Jul 2008

THistSvc.cpp

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

Generated at Fri Jul 18 11:59:25 2008 for Gaudi Framework, version v20r2 by Doxygen version 1.5.1 written by Dimitri van Heesch, © 1997-2004