Gaudi Framework, version v21r6

Home   Generated: 11 Nov 2009

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   : 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   // Protect against multiple instances of TROOT
00097   if ( 0 == gROOT )   {
00098     static TROOT root("root","ROOT I/O");
00099     //    gDebug = 99;
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 //     if (uitr->second.temp == true) {
00183 //       MsgStream log ( msgSvc(), name() );
00184 //       log << MSG::INFO << "Deleting \"" << uitr->first << "\"" << endmsg;
00185 //       delete uitr->second.obj;
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       //Merge File
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   //  TIter nextkey(dir->GetListOfKeys());
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     //    if (obj->IsA()->InheritsFrom("TDirectory")) {
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& /*m_inputfile*/ )
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& /*m_outputfile*/ )
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   // If TTrees grow beyond TTree::fgMaxFileSize, a new file is
00857   // automatically created by root, and the old one closed. We
00858   // need to migrate all the UIDs over to show the correct file
00859   // pointer. This is ugly.
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     // something else?
01048     log << MSG::ERROR << "No OPT= specified or unknown access mode in: "
01049         << ident << endmsg;
01050     return StatusCode::FAILURE;
01051   }
01052 
01053   // Is this file already connected to another stream?
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     // old file
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     // new file
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     // update file
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     // SHARE file type
01139     //For SHARE files, all data will be stored in a temp file and will be merged into the target file
01140     //in write() when finalize(), this help to solve some confliction. e.g. with storegate
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     // update file
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   // loop over all keys in this directory
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     //key->Dump();
01307     //TObject *obj=key->ReadObj();
01308     TObject *obj=source->Get(pathnameinsource.c_str());
01309 
01310     if (obj->IsA()->InheritsFrom("TDirectory") ) {
01311       // it's a subdirectory
01312 
01313       log <<MSG::DEBUG << "Found subdirectory " << obj->GetName()
01314           << endmsg;
01315 
01316       // create a new subdir of same name and title in the target file
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       //mytree->Print();
01332       //for (int ij=0; ij<nentries; ij++) {
01333       //log <<MSG::DEBUG << "Dumping TTree Show( " << ij <<" )"
01334       //<< endmsg;
01335       //mytree->Show(ij);
01336       //}
01337       target->cd();
01338       mytree->CloneTree();
01339 
01340       //log <<MSG::DEBUG << "Writing TTree to target file: ( "
01341       //<< mycopiedtree->Write(key->GetName()) <<" ) bytes written"
01342       //<< endmsg;
01343 
01344     } else if (obj) {
01345       target->cd();
01346       obj->Write(key->GetName() );
01347     }
01348 
01349   } // while ( ( TKey *key = (TKey*)nextkey() ) )
01350 
01351   // save modifications to target file
01352 
01353 }
01354 
01355 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//

Generated at Wed Nov 11 16:23:15 2009 for Gaudi Framework, version v21r6 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004