Gaudi Framework, version v22r0

Home   Generated: 9 Feb 2011

THistSvc.cpp

Go to the documentation of this file.
00001 #ifdef __ICC
00002 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
00003 //   TODO: To be removed, since it comes from ROOT TMathBase.h
00004 #pragma warning(disable:2259)
00005 #endif
00006 
00007 #include "THistSvc.h"
00008 
00009 #include "GaudiKernel/SvcFactory.h"
00010 #include "GaudiKernel/ISvcLocator.h"
00011 #include "GaudiKernel/Tokenizer.h"
00012 #include "GaudiKernel/GaudiException.h"
00013 #include "GaudiKernel/Property.h"
00014 #include "GaudiKernel/IIncidentSvc.h"
00015 #include "GaudiKernel/FileIncident.h"
00016 #include "GaudiKernel/IEventProcessor.h"
00017 #include "GaudiKernel/IJobOptionsSvc.h"
00018 
00019 
00020 #include "TROOT.h"
00021 #include "TFile.h"
00022 #include "TDirectory.h"
00023 #include "TKey.h"
00024 #include "TError.h"
00025 #include "TGraph.h"
00026 
00027 #include <sstream>
00028 #include <streambuf>
00029 #include <cstdio>
00030 
00031 using namespace std;
00032 
00033 
00034 DECLARE_SERVICE_FACTORY(THistSvc)
00035 
00036 inline void toupper(std::string &s)
00037 {
00038   std::transform(s.begin(), s.end(), s.begin(),
00039                  (int(*)(int)) toupper);
00040 }
00041 
00042 
00043 //*************************************************************************//
00044 
00045 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc )
00046   : base_class(name, svc), m_log(msgSvc(), name ), signaledStop(false) {
00047 
00048   declareProperty ("AutoSave", m_autoSave=0 );
00049   declareProperty ("PrintAll", m_print=false);
00050   declareProperty ("MaxFileSize", m_maxFileSize=10240,
00051                    "maximum file size in MB. if exceeded, will cause an abort");
00052   declareProperty ("CompressionLevel", m_compressionLevel=1 )->declareUpdateHandler( &THistSvc::setupCompressionLevel, this );
00053   declareProperty ("Output", m_outputfile )->declareUpdateHandler( &THistSvc::setupOutputFile, this );
00054   declareProperty ("Input", m_inputfile )->declareUpdateHandler ( &THistSvc::setupInputFile,  this );
00055 
00056 
00057 }
00058 
00059 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00060 
00061 THistSvc::~THistSvc() {
00062 
00063 }
00064 
00065 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00066 
00067 StatusCode
00068 THistSvc::initialize() {
00069   GlobalDirectoryRestore restore;
00070 
00071   m_alreadyConnectedOutFiles.clear();
00072   m_alreadyConnectedInFiles.clear();
00073 
00074 
00075   // Super ugly hack to make sure we have the OutputLevel set first, so we
00076   // can see DEBUG printouts in update handlers.
00077   IJobOptionsSvc* jos(0);
00078   if( serviceLocator()->service( "JobOptionsSvc", jos, true ).isSuccess() ) {
00079     const std::vector<const Property*> *props = jos->getProperties( name() );
00080 
00081     if (props != NULL) {
00082       for ( std::vector<const Property*>::const_iterator cur = props->begin();
00083             cur != props->end(); cur++) {
00084         if ( (*cur)->name() == "OutputLevel" ) {
00085           setProperty( **cur ).ignore();
00086           m_log.setLevel( m_outputLevel.value() );
00087           break;
00088         }
00089       }
00090     }
00091   }
00092 
00093 
00094   StatusCode status = Service::initialize();
00095   m_log.setLevel( m_outputLevel.value() );
00096 
00097   if (status.isFailure()) {
00098     m_log << MSG::ERROR << "initializing service" << endmsg;
00099     return status;
00100   }
00101 
00102   vector<string>::const_iterator itr;
00103   StatusCode st(StatusCode::SUCCESS);
00104 
00105   try {
00106     setupOutputFile( m_outputfile );
00107   } catch ( GaudiException& err ) {
00108     m_log << MSG::ERROR
00109           << "Caught: " << err << endmsg;
00110     st = StatusCode::FAILURE;
00111   }
00112 
00113   try {
00114     setupInputFile( m_inputfile );
00115   } catch ( GaudiException& err ) {
00116     m_log << MSG::ERROR
00117           << "Caught: " << err << endmsg;
00118     st = StatusCode::FAILURE;
00119   }
00120 
00121   // Protect against multiple instances of TROOT
00122   if ( 0 == gROOT )   {
00123     static TROOT root("root","ROOT I/O");
00124     //    gDebug = 99;
00125   } else {
00126     m_log << MSG::VERBOSE << "ROOT already initialized, debug = "
00127           << gDebug<< endmsg;
00128   }
00129 
00130   IIncidentSvc* p_incSvc(0);
00131 
00132   if (service("IncidentSvc", p_incSvc, true).isFailure()) {
00133     m_log << MSG::ERROR << "unable to get the IncidentSvc" << endmsg;
00134     st = StatusCode::FAILURE;
00135   } else {
00136     p_incSvc->addListener( this, "EndEvent", 100, true);
00137   }
00138 
00139   if (st.isFailure()) {
00140     m_log << MSG::FATAL << "Unable to initialize THistSvc" << endmsg;
00141   }
00142 
00143   return st;
00144 
00145 }
00146 
00147 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00148 
00149 StatusCode
00150 THistSvc::reinitialize() {
00151 
00152   GlobalDirectoryRestore restore;
00153 
00154   m_log << MSG::WARNING << "reinitialize not implemented" << endmsg;
00155 
00156 
00157   return StatusCode::SUCCESS;
00158 
00159 }
00160 
00161 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00162 
00163 StatusCode
00164 THistSvc::finalize() {
00165 
00166   GlobalDirectoryRestore restore;
00167 
00168   m_log << MSG::DEBUG << "THistSvc::finalize" << endmsg;
00169 
00170   uidMap::const_iterator uitr;
00171   for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
00172 
00173     TObject* to = uitr->second.obj;
00174 
00175     string dirname("none");
00176     if (to->IsA()->InheritsFrom("TTree")) {
00177       TTree* tr = dynamic_cast<TTree*>(to);
00178       if (tr->GetDirectory() != 0) {
00179         dirname = tr->GetDirectory()->GetPath();
00180       }
00181     } else if (to->IsA()->InheritsFrom("TGraph")) {
00182       if (!uitr->second.temp) {
00183         dirname = uitr->second.file->GetPath();
00184         string id2(uitr->second.id);
00185         id2.erase(0,id2.find("/",1));
00186         id2.erase(id2.rfind("/"), id2.length());
00187         if (id2.find("/") == 0) {
00188           id2.erase(0,1);
00189         }
00190         dirname += id2;
00191       } else {
00192         dirname = "/tmp";
00193       }
00194     } else if (to->IsA()->InheritsFrom("TH1")) {
00195       TH1* th = dynamic_cast<TH1*>(to);
00196       if (th == 0) {
00197         m_log << MSG::ERROR << "Couldn't dcast: " << uitr->first << endmsg;
00198       } else {
00199         if (th->GetDirectory() != 0) {
00200           dirname = th->GetDirectory()->GetPath();
00201         }
00202       }
00203     }
00204 
00205 #ifndef NDEBUG
00206     m_log << MSG::DEBUG << "uid: \"" << uitr->first << "\"  temp: "
00207         << uitr->second.temp << "  dir: " << dirname
00208         << endmsg;
00209 #endif
00210 
00211 
00212 //     if (uitr->second.temp == true) {
00213 //       log << MSG::INFO << "Deleting \"" << uitr->first << "\"" << endmsg;
00214 //       delete uitr->second.obj;
00215 //     }
00216   }
00217 
00218   StatusCode sc = write();
00219   if (sc.isFailure()) {
00220     m_log << MSG::ERROR << "problems writing histograms" << endmsg;
00221   }
00222 
00223   if (m_print) {
00224     m_log << MSG::INFO << "Listing contents of ROOT files: " << endmsg;
00225   }
00226   vector<TFile*> deleted_files;
00227   map<string, pair<TFile*,Mode> >::const_iterator itr;
00228   for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
00229 
00230     if (find(deleted_files.begin(), deleted_files.end(), itr->second.first) ==
00231         deleted_files.end()) {
00232       deleted_files.push_back(itr->second.first);
00233 
00234 #ifndef NDEBUG
00235       m_log << MSG::DEBUG << "finalizing stream/file " << itr->first << ":"
00236             << itr->second.first->GetName()
00237             << endmsg;
00238 #endif
00239     } else {
00240 #ifndef NDEBUG
00241       m_log << MSG::DEBUG << "already finalized stream " << itr->first << endmsg;
00242 #endif
00243       continue;
00244     }
00245 
00246 
00247     if (m_print && m_log.level() <= MSG::INFO) {
00248 
00249       m_log << MSG::INFO;
00250       m_log << "==> File: " << itr->second.first->GetName()
00251             << "  stream: " << itr->first << endmsg;
00252 
00253       itr->second.first->Print("base");
00254     }
00255 
00256     string tmpfn=itr->second.first->GetName();
00257 
00258     itr->second.first->Close();
00259 
00260     IIncidentSvc *pi(0);
00261     if (service("IncidentSvc",pi).isFailure()) {
00262       m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg;
00263       return StatusCode::FAILURE;
00264     }
00265 
00266     if (itr->second.second==SHARE) {
00267       TFile *outputfile;
00268       //Merge File
00269       try {
00270         m_log << MSG::DEBUG << "Opening Final Output File: " <<m_sharedFiles[itr->first].c_str()<<endmsg;
00271         outputfile = new TFile(m_sharedFiles[itr->first].c_str(), "UPDATE");
00272       } catch (const std::exception& Exception) {
00273         m_log << MSG::ERROR << "exception caught while trying to open root"
00274               << " file for appending: " << Exception.what() << std::endl
00275               << "  -> file probably corrupt." << endmsg;
00276         pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
00277                                       m_sharedFiles[itr->first]));
00278         return StatusCode::FAILURE;
00279       } catch (...) {
00280         m_log << MSG::ERROR << "Problems opening output file  \""
00281               << m_sharedFiles[itr->first]
00282               << "\" for append: probably corrupt" << endmsg;
00283         pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
00284                                       m_sharedFiles[itr->first]));
00285         return StatusCode::FAILURE;
00286       }
00287 
00288       pi->fireIncident(FileIncident(name(), IncidentType::WroteToOutputFile,
00289                                     m_sharedFiles[itr->first]));
00290 
00291       m_log << MSG::DEBUG << "THistSvc::write()::Merging Rootfile "<<endmsg;
00292       TFile *inputfile;
00293       try {
00294         m_log << MSG::DEBUG << "Openning again Temporary File: " <<tmpfn.c_str()<<endmsg;
00295         inputfile=new TFile(tmpfn.c_str(),"READ");
00296       } catch (const std::exception& Exception) {
00297         m_log << MSG::ERROR << "exception caught while trying to open root"
00298               << " file for appending: " << Exception.what() << std::endl
00299               << "  -> file probably corrupt." << endmsg;
00300         return StatusCode::FAILURE;
00301       } catch (...) {
00302         m_log << MSG::ERROR << "Problems opening output file  \""
00303               << tmpfn.c_str()
00304               << "\" for append: probably corrupt" << endmsg;
00305         return StatusCode::FAILURE;
00306       }
00307 
00308       outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
00309 
00310       MergeRootFile(outputfile, inputfile);
00311 
00312       outputfile->Write();
00313       outputfile->Close();
00314       inputfile->Close();
00315 
00316       m_log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn
00317             << "\""<<endmsg;
00318 
00319       std::remove(tmpfn.c_str());
00320     }
00321     delete itr->second.first;
00322   }
00323 
00324   m_sharedFiles.clear();
00325   m_fileStreams.clear();
00326   m_files.clear();
00327   m_uids.clear();
00328   m_ids.clear();
00329   m_tobjs.clear();
00330 
00331   return Service::finalize();
00332 }
00333 
00334 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00335 
00336 bool
00337 THistSvc::browseTDir(TDirectory *dir) const {
00338 
00339   if (dir == 0) {
00340     std::cerr << "TDirectory == 0" << std::endl;
00341     return false;
00342   }
00343 
00344   GlobalDirectoryRestore restore;
00345 
00346   dir->cd();
00347 
00348 
00349   cout << "-> " << dir->GetPath() << "  "
00350        << dir->GetListOfKeys()->GetSize() << endl;
00351 
00352   //  TIter nextkey(dir->GetListOfKeys());
00353   TIter nextkey(dir->GetList());
00354   while (TKey *key = (TKey*)nextkey()) {
00355 
00356     TObject *obj = key->ReadObj();
00357     if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00358     //    if (obj->IsA()->InheritsFrom("TDirectory")) {
00359       cout << "  Key: " << key->GetName() << "   "
00360            << " tit: " << obj->GetTitle() << "   "
00361            << " (" << key->GetClassName() << ")" << endl;
00362       //    }
00363   }
00364 
00365   nextkey = dir->GetListOfKeys();
00366   while (TKey *key = (TKey*)nextkey()) {
00367 
00368     TObject *obj = key->ReadObj();
00369     if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00370     if (obj->IsA()->InheritsFrom("TDirectory")) {
00371       TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00372       browseTDir(tt);
00373     }
00374   }
00375 
00376   return true;
00377 }
00378 
00379 
00380 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00381 
00382 StatusCode
00383 THistSvc::getTHists(TDirectory *td, TList & tl, bool rcs) const {
00384   GlobalDirectoryRestore restore;
00385 
00386   gErrorIgnoreLevel = kBreak;
00387 
00388   if (!td->cd()) {
00389     m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath()
00390           << "\"" << endmsg;
00391     return StatusCode::FAILURE;
00392   }
00393 
00394   m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00395         << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00396 
00397   TIter nextkey(td->GetListOfKeys());
00398   while (TKey *key = (TKey*)nextkey()) {
00399     m_log << MSG::DEBUG << "  key: " << key->GetName();
00400     TObject *obj = key->ReadObj();
00401     if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00402       m_log << " (" << obj->IsA()->GetName() << ")";
00403     } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) {
00404       m_log << " (" << obj->IsA()->GetName() << ")";
00405       tl.Add(obj);
00406     } else if (obj != 0) {
00407       m_log << " [" << obj->IsA()->GetName() << "]";
00408     }
00409     m_log << endmsg;
00410   }
00411 
00412   // operate recursively
00413   if (rcs) {
00414     nextkey = td->GetListOfKeys();
00415     while (TKey *key = (TKey*)nextkey()) {
00416       TObject *obj = key->ReadObj();
00417       if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00418           TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00419           getTHists(tt, tl, rcs);
00420       }
00421     }
00422   }
00423 
00424   return StatusCode::SUCCESS;
00425 
00426 
00427 }
00428 
00429 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00430 
00431 StatusCode
00432 THistSvc::getTHists(const std::string& dir, TList & tl, bool rcs) const {
00433 
00434   GlobalDirectoryRestore restore;
00435 
00436   gErrorIgnoreLevel = kBreak;
00437 
00438   StatusCode sc;
00439 
00440   std::string stream,rem,r2;
00441   parseString(dir,stream,rem);
00442 
00443   map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00444   if (itr != m_files.end()) {
00445     r2 = itr->second.first->GetName();
00446     r2 += ":/";
00447     r2 += rem;
00448 
00449     m_log << MSG::DEBUG << "getTHists: \"" << dir
00450           << "\" looks like a stream name."  << " associated TFile: \""
00451           << itr->second.first->GetName() << "\"" << endmsg;
00452 
00453     if (gDirectory->cd(r2.c_str())) {
00454       m_curstream = stream;
00455       sc = getTHists(gDirectory,tl,rcs);
00456       m_curstream = "";
00457       return sc;
00458     } else {
00459       m_log << MSG::DEBUG << "getTHists: no such TDirectory \""
00460             << r2 << "\"" << endmsg;
00461     }
00462 
00463   } else {
00464     m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found"
00465           << endmsg;
00466   }
00467 
00468   if (!gDirectory->cd(dir.c_str())) {
00469     m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir
00470           << "\"" << endmsg;
00471     sc = StatusCode::FAILURE;
00472   } else {
00473     sc = getTHists(gDirectory,tl,rcs);
00474   }
00475 
00476   return sc;
00477 
00478 }
00479 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00480 
00481 StatusCode
00482 THistSvc::getTTrees(TDirectory *td, TList & tl, bool rcs) const {
00483   GlobalDirectoryRestore restore;
00484 
00485   gErrorIgnoreLevel = kBreak;
00486 
00487   if (!td->cd()) {
00488     m_log << MSG::ERROR << "getTTrees: No such TDirectory \""
00489           << td->GetPath() << "\"" << endmsg;
00490     return StatusCode::FAILURE;
00491   }
00492 
00493   m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00494         << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00495 
00496   TIter nextkey(td->GetListOfKeys());
00497   while (TKey *key = (TKey*)nextkey()) {
00498     m_log << MSG::DEBUG << "  key: " << key->GetName();
00499     TObject *obj = key->ReadObj();
00500     if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00501       m_log << " (" << obj->IsA()->GetName() << ")";
00502     } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) {
00503       m_log << " (" << obj->IsA()->GetName() << ")";
00504       tl.Add(obj);
00505     } else if (obj != 0) {
00506       m_log << " [" << obj->IsA()->GetName() << "]";
00507     }
00508     m_log << endmsg;
00509   }
00510 
00511   // operate recursively
00512   if (rcs) {
00513     nextkey = td->GetListOfKeys();
00514     while (TKey *key = (TKey*)nextkey()) {
00515       TObject *obj = key->ReadObj();
00516       if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00517           TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00518           getTTrees(tt, tl, rcs);
00519       }
00520     }
00521   }
00522 
00523   return StatusCode::SUCCESS;
00524 
00525 }
00526 
00527 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00528 
00529 StatusCode
00530 THistSvc::getTTrees(const std::string& dir, TList & tl, bool rcs) const {
00531   GlobalDirectoryRestore restore;
00532 
00533   gErrorIgnoreLevel = kBreak;
00534 
00535   StatusCode sc;
00536 
00537   std::string stream,rem,r2;
00538   parseString(dir,stream,rem);
00539 
00540   map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00541   if (itr != m_files.end()) {
00542     r2 = itr->second.first->GetName();
00543     r2 += ":/";
00544     r2 += rem;
00545 
00546     m_log << MSG::DEBUG << "getTTrees: \"" << dir
00547           << "\" looks like a stream name."  << " associated TFile: \""
00548           << itr->second.first->GetName() << "\"" << endmsg;
00549 
00550     if (gDirectory->cd(r2.c_str())) {
00551       return getTTrees(gDirectory,tl,rcs);
00552     } else {
00553       m_log << MSG::DEBUG << "getTTrees: no such TDirectory \""
00554             << r2 << "\"" << endmsg;
00555     }
00556 
00557   } else {
00558     m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found"
00559           << endmsg;
00560   }
00561 
00562   if (!gDirectory->cd(dir.c_str())) {
00563     m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir
00564           << "\"" << endmsg;
00565     sc = StatusCode::FAILURE;
00566   } else {
00567     sc = getTTrees(gDirectory,tl,rcs);
00568   }
00569 
00570   return sc;
00571 
00572 
00573 }
00574 
00575 
00576 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00577 
00578 StatusCode
00579 THistSvc::getTHists(TDirectory *td, TList & tl, bool rcs, bool reg) {
00580 
00581   GlobalDirectoryRestore restore;
00582 
00583   gErrorIgnoreLevel = kBreak;
00584 
00585   if (!td->cd()) {
00586     m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath()
00587           << "\"" << endmsg;
00588     return StatusCode::FAILURE;
00589   }
00590 
00591   m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00592         << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00593 
00594   TIter nextkey(td->GetListOfKeys());
00595   while (TKey *key = (TKey*)nextkey()) {
00596     m_log << MSG::DEBUG << "  key: " << key->GetName();
00597     TObject *obj = key->ReadObj();
00598     if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00599       m_log << " (" << obj->IsA()->GetName() << ")";
00600     } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) {
00601       m_log << " (" << obj->IsA()->GetName() << ")";
00602       tl.Add(obj);
00603       if (reg && m_curstream != "") {
00604         string dir = td->GetPath();
00605         string fil = td->GetFile()->GetName();
00606         dir.erase(0,fil.length()+1);
00607         string id = "/" + m_curstream;
00608         if ( dir == "/" ) {
00609           id = id + "/" + key->GetName();
00610         } else {
00611           id = id + dir + "/" + key->GetName();
00612         }
00613         if (!exists(id)) {
00614           m_log << "  reg as \"" << id << "\"";
00615           regHist(id).ignore();
00616         } else {
00617           m_log << "  already registered";
00618         }
00619       }
00620     } else if (obj != 0) {
00621       m_log << " [" << obj->IsA()->GetName() << "]";
00622     }
00623     m_log << endmsg;
00624   }
00625 
00626   // operate recursively
00627   if (rcs) {
00628     nextkey = td->GetListOfKeys();
00629     while (TKey *key = (TKey*)nextkey()) {
00630       TObject *obj = key->ReadObj();
00631       if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00632           TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00633           getTHists(tt, tl, rcs, reg);
00634       }
00635     }
00636   }
00637 
00638   return StatusCode::SUCCESS;
00639 
00640 }
00641 
00642 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00643 
00644 StatusCode
00645 THistSvc::getTHists(const std::string& dir, TList & tl, bool rcs, bool reg) {
00646 
00647   GlobalDirectoryRestore restore;
00648 
00649   gErrorIgnoreLevel = kBreak;
00650 
00651   StatusCode sc;
00652 
00653   std::string stream,rem,r2;
00654   parseString(dir,stream,rem);
00655 
00656   map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00657   if (itr != m_files.end()) {
00658     r2 = itr->second.first->GetName();
00659     r2 += ":/";
00660     r2 += rem;
00661 
00662     m_log << MSG::DEBUG << "getTHists: \"" << dir
00663           << "\" looks like a stream name."  << " associated TFile: \""
00664           << itr->second.first->GetName() << "\"" << endmsg;
00665 
00666     if (gDirectory->cd(r2.c_str())) {
00667       m_curstream = stream;
00668       sc = getTHists(gDirectory,tl,rcs,reg);
00669       m_curstream = "";
00670       return sc;
00671     } else {
00672       m_log << MSG::DEBUG << "getTHists: no such TDirectory \""
00673             << r2 << "\"" << endmsg;
00674     }
00675 
00676   } else {
00677     m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found"
00678           << endmsg;
00679   }
00680 
00681   if (!gDirectory->cd(dir.c_str())) {
00682     m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir
00683           << "\"" << endmsg;
00684     sc = StatusCode::FAILURE;
00685   } else {
00686     if (reg) {
00687       m_log << MSG::WARNING << "Unable to register histograms automatically "
00688             << "without a valid stream name" << endmsg;
00689       reg = false;
00690     }
00691     sc = getTHists(gDirectory,tl,rcs,reg);
00692   }
00693 
00694   return sc;
00695 
00696 }
00697 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00698 
00699 StatusCode
00700 THistSvc::getTTrees(TDirectory *td, TList & tl, bool rcs, bool reg) {
00701 
00702   GlobalDirectoryRestore restore;
00703 
00704   gErrorIgnoreLevel = kBreak;
00705 
00706   if (!td->cd()) {
00707     m_log << MSG::ERROR << "getTTrees: No such TDirectory \""
00708           << td->GetPath() << "\"" << endmsg;
00709     return StatusCode::FAILURE;
00710   }
00711 
00712   m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00713         << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00714 
00715   TIter nextkey(td->GetListOfKeys());
00716   while (TKey *key = (TKey*)nextkey()) {
00717     m_log << MSG::DEBUG << "  key: " << key->GetName();
00718     TObject *obj = key->ReadObj();
00719     if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00720       m_log << " (" << obj->IsA()->GetName() << ")";
00721     } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) {
00722       m_log << " (" << obj->IsA()->GetName() << ")";
00723       tl.Add(obj);
00724       if (reg && m_curstream != "") {
00725         string dir = td->GetPath();
00726         string fil = td->GetFile()->GetName();
00727         dir.erase(0,fil.length()+1);
00728         string id = "/" + m_curstream;
00729         if ( dir == "/" ) {
00730           id = id + "/" + key->GetName();
00731         } else {
00732           id = id + dir + "/" + key->GetName();
00733         }
00734         if (!exists(id)) {
00735           m_log << "  reg as \"" << id << "\"";
00736           regHist(id).ignore();
00737         } else {
00738           m_log << "  already registered";
00739         }
00740       }
00741     } else if (obj != 0) {
00742       m_log << " [" << obj->IsA()->GetName() << "]";
00743     }
00744     m_log << endmsg;
00745   }
00746 
00747   // operate recursively
00748   if (rcs) {
00749     nextkey = td->GetListOfKeys();
00750     while (TKey *key = (TKey*)nextkey()) {
00751       TObject *obj = key->ReadObj();
00752       if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00753           TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00754           getTTrees(tt, tl, rcs, reg);
00755       }
00756     }
00757   }
00758 
00759   return StatusCode::SUCCESS;
00760 
00761 }
00762 
00763 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00764 
00765 StatusCode
00766 THistSvc::getTTrees(const std::string& dir, TList & tl, bool rcs, bool reg) {
00767 
00768   GlobalDirectoryRestore restore;
00769 
00770   gErrorIgnoreLevel = kBreak;
00771 
00772   StatusCode sc;
00773 
00774   std::string stream,rem,r2;
00775   parseString(dir,stream,rem);
00776 
00777   map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00778   if (itr != m_files.end()) {
00779     r2 = itr->second.first->GetName();
00780     r2 += ":/";
00781     r2 += rem;
00782 
00783     m_log << MSG::DEBUG << "getTTrees: \"" << dir
00784           << "\" looks like a stream name."  << " associated TFile: \""
00785           << itr->second.first->GetName() << "\"" << endmsg;
00786 
00787     if (gDirectory->cd(r2.c_str())) {
00788       return getTTrees(gDirectory,tl,rcs,reg);
00789     } else {
00790       m_log << MSG::DEBUG << "getTTrees: no such TDirectory \""
00791             << r2 << "\"" << endmsg;
00792     }
00793 
00794   } else {
00795     m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found"
00796           << endmsg;
00797   }
00798 
00799   if (!gDirectory->cd(dir.c_str())) {
00800     m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir
00801           << "\"" << endmsg;
00802     sc = StatusCode::FAILURE;
00803   } else {
00804     sc = getTTrees(gDirectory,tl,rcs,reg);
00805   }
00806 
00807   return sc;
00808 
00809 }
00810 
00811 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00812 
00813 StatusCode
00814 THistSvc::deReg(TObject* obj) {
00815 
00816   objMap::iterator itr = m_tobjs.find(obj);
00817   if (itr != m_tobjs.end()) {
00818     THistID hid = itr->second;
00819 
00820     uidMap::iterator itr2 = m_uids.find(hid.id);
00821     if (itr2 == m_uids.end()) {
00822       m_log << MSG::ERROR << "Problems deregistering TObject \""
00823             << obj->GetName()
00824             << "\" with id \"" << hid.id << "\"" << endmsg;
00825       return StatusCode::FAILURE;
00826     }
00827 
00828     std::string id,root,rem;
00829     parseString(hid.id, root, rem);
00830 
00831     idMap::iterator itr3;
00832     bool found(false);
00833 
00834     std::pair<idMap::iterator, idMap::iterator> mitr = m_ids.equal_range(rem);
00835     if (mitr.first == mitr.second) {
00836       m_log << MSG::ERROR << "Problems deregistering TObject \""
00837             << obj->GetName()
00838             << "\" with id \"" << hid.id << "\"" << endmsg;
00839       return StatusCode::FAILURE;
00840     } else {
00841       for (itr3 = mitr.first; itr3 != mitr.second; ++itr3) {
00842         if (itr3->second.obj == obj) {
00843           found = true;
00844           break;
00845         }
00846       }
00847       if (!found) {
00848         m_log << MSG::ERROR << "Problems deregistering TObject \""
00849               << obj->GetName()
00850               << "\" with id \"" << hid.id << "\"" << endmsg;
00851       }
00852     }
00853 
00854     m_tobjs.erase(itr);
00855     m_uids.erase(itr2);
00856     m_ids.erase(itr3);
00857 
00858     return StatusCode::SUCCESS;
00859 
00860   } else {
00861     m_log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName()
00862           << "\": not known to THistSvc" << endmsg;
00863     return StatusCode::FAILURE;
00864   }
00865 
00866 }
00867 
00868 
00869 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00870 
00871 StatusCode
00872 THistSvc::deReg(const std::string& id) {
00873 
00874   uidMap::iterator itr = m_uids.find(id);
00875   if (itr == m_uids.end()) {
00876     m_log << MSG::ERROR << "Problems deregistering id \""
00877           << id << "\"" << endmsg;
00878     return StatusCode::FAILURE;
00879   }
00880 
00881   TObject* obj = itr->second.obj;
00882 
00883   return deReg(obj);
00884 }
00885 
00886 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00887 
00888 StatusCode
00889 THistSvc::regHist(const std::string& id) {
00890 
00891   TH1 *hist(0);
00892 
00893   return regHist_i(hist, id);
00894 }
00895 
00896 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00897 
00898 StatusCode
00899 THistSvc::regHist(const std::string& id, TH1* hist) {
00900   return regHist_i(hist, id);
00901 }
00902 
00903 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00904 
00905 StatusCode
00906 THistSvc::regHist(const std::string& id, TH2* hist) {
00907   return regHist_i(hist, id);
00908 }
00909 
00910 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00911 
00912 StatusCode
00913 THistSvc::regHist(const std::string& id, TH3* hist) {
00914   return regHist_i(hist, id);
00915 }
00916 
00917 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00918 
00919 StatusCode
00920 THistSvc::regTree(const std::string& id) {
00921   TTree *hist(0);
00922   return regHist_i(hist, id);
00923 }
00924 
00925 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00926 
00927 StatusCode
00928 THistSvc::regTree(const std::string& id, TTree* hist) {
00929   StatusCode sc = regHist_i(hist, id);
00930   if (hist != 0 && m_autoSave != 0 && sc.isSuccess()) {
00931     hist->SetAutoSave(m_autoSave);
00932   }
00933   return sc;
00934 }
00935 
00936 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00937 
00938 StatusCode
00939 THistSvc::regGraph(const std::string& id) {
00940   TGraph *hist(0);
00941   return regHist_i(hist, id);
00942 }
00943 
00944 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00945 
00946 StatusCode
00947 THistSvc::regGraph(const std::string& id, TGraph* hist) {
00948   if ( strcmp(hist->GetName(),"Graph") == 0 ) {
00949 
00950     std::string id2(id);
00951     string::size_type i = id2.rfind("/");
00952     if (i != string::npos) {
00953       id2.erase(0,i+1);
00954     }
00955 
00956     m_log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \""
00957           << id2 << "\" since it is unset" << endmsg;
00958     hist->SetName(id2.c_str());
00959   }
00960 
00961   return regHist_i(hist, id);
00962 }
00963 
00964 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00965 
00966 StatusCode
00967 THistSvc::getHist(const std::string& id, TH1*& hist) const {
00968   return getHist_i(id, hist);
00969 }
00970 
00971 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00972 
00973 StatusCode
00974 THistSvc::getHist(const std::string& id, TH2*& hist) const {
00975   return getHist_i(id, hist);
00976 }
00977 
00978 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00979 
00980 StatusCode
00981 THistSvc::getHist(const std::string& id, TH3*& hist) const {
00982   return getHist_i(id, hist);
00983 }
00984 
00985 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
00986 
00987 std::vector<std::string>
00988 THistSvc::getHists() const {
00989 
00990   std::vector<std::string> names;
00991   names.reserve(m_uids.size());
00992 
00993   uidMap::const_iterator itr;
00994   for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
00995     THistID tid = itr->second;
00996 
00997     if (tid.obj->IsA()->InheritsFrom("TH1")) {
00998       names.push_back(itr->first);
00999     }
01000 
01001   }
01002 
01003   return names;
01004 
01005 }
01006 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01007 
01008 StatusCode
01009 THistSvc::getTree(const std::string& id, TTree*& hist) const {
01010   return getHist_i(id, hist);
01011 }
01012 
01013 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01014 
01015 std::vector<std::string>
01016 THistSvc::getTrees() const {
01017 
01018   std::vector<std::string> names;
01019   names.reserve(m_uids.size());
01020 
01021   uidMap::const_iterator itr;
01022   for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01023     THistID tid = itr->second;
01024 
01025     if (tid.obj->IsA()->InheritsFrom("TTree")) {
01026       names.push_back(itr->first);
01027     }
01028 
01029   }
01030 
01031   return names;
01032 
01033 }
01034 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01035 
01036 StatusCode
01037 THistSvc::getGraph(const std::string& id, TGraph*& hist) const {
01038   return getHist_i(id, hist);
01039 }
01040 
01041 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01042 
01043 std::vector<std::string>
01044 THistSvc::getGraphs() const {
01045 
01046   std::vector<std::string> names;
01047   names.reserve(m_uids.size());
01048 
01049   uidMap::const_iterator itr;
01050   for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01051     THistID tid = itr->second;
01052 
01053     if (tid.obj->IsA()->InheritsFrom("TGraph")) {
01054       names.push_back(itr->first);
01055     }
01056 
01057   }
01058 
01059   return names;
01060 
01061 }
01062 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01063 
01064 StatusCode
01065 THistSvc::readHist(const std::string& id, TH1*& hist) const {
01066   return readHist_i(id, hist);
01067 }
01068 
01069 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01070 
01071 StatusCode
01072 THistSvc::readHist(const std::string& id, TH2*& hist) const {
01073   return readHist_i(id, hist);
01074 }
01075 
01076 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01077 
01078 StatusCode
01079 THistSvc::readHist(const std::string& id, TH3*& hist) const {
01080   return readHist_i(id, hist);
01081 }
01082 
01083 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01084 
01085 StatusCode
01086 THistSvc::readTree(const std::string& id, TTree*& hist) const {
01087   return readHist_i(id, hist);
01088 }
01089 
01090 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01091 
01092 bool
01093 THistSvc::findStream(const string& id, string& stream, string& rem,
01094                    TFile*& file) const {
01095 
01096   string::size_type pos = id.find("/");
01097 
01098   if (pos == string::npos) {
01099     stream = "temp";
01100     rem = id;
01101   } else if (pos != 0) {
01102     stream = "temp";
01103     rem = id;
01104   } else {
01105 
01106     string::size_type pos2 = id.find("/",pos+1);
01107 
01108     if (pos2 == string::npos) {
01109       m_log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\""
01110             << endmsg;
01111       return false;
01112     }
01113 
01114     parseString(id,stream,rem);
01115 
01116   }
01117 
01118   if (stream == "temp") {
01119     file = 0;
01120     return true;
01121   }
01122 
01123   map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
01124   if (itr != m_files.end()) {
01125     file = itr->second.first;
01126   } else {
01127     file = 0;
01128     m_log << MSG::WARNING << "no stream \"" << stream
01129           << "\" associated with id: \"" << id << "\""
01130           << endmsg;
01131   }
01132 
01133   return true;
01134 
01135 }
01136 
01137 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01138 
01139 void
01140 THistSvc::parseString(const string& id, string& root, string& rem) const {
01141   string::size_type pos = id.find("/");
01142 
01143   if (pos == string::npos) {
01144     root = "";
01145     rem = id;
01146     return;
01147   }
01148 
01149   if (pos == 0) {
01150     parseString(id.substr(1,id.length()),root,rem);
01151   } else {
01152     root = id.substr(0,pos);
01153     rem = id.substr(pos+1,id.length());
01154   }
01155 
01156 }
01157 
01158 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01159 
01160 void
01161 THistSvc::setupCompressionLevel( Property& /* cl */ )
01162 {
01163 
01164   m_log << MSG::WARNING << "\"CompressionLevel\" Property has been deprecated. "
01165         << "Set it via the \"CL=\" parameter in the \"Output\" Property"
01166         << endmsg;
01167 
01168 }
01169 
01170 
01171 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01172 
01173 void
01174 THistSvc::setupInputFile( Property& /*m_inputfile*/ )
01175 {
01176   StatusCode sc = StatusCode::SUCCESS;
01177 
01178   typedef std::vector<std::string> Strings_t;
01179   for ( Strings_t::const_iterator
01180           itr  = m_inputfile.value().begin(),
01181           iEnd = m_inputfile.value().end();
01182         itr != iEnd;
01183         ++itr ) {
01184     if ( m_alreadyConnectedInFiles.end() ==
01185          m_alreadyConnectedInFiles.find( *itr ) ) {
01186       if ( connect(*itr).isFailure() ) {
01187         sc = StatusCode::FAILURE;
01188       } else {
01189         m_alreadyConnectedInFiles.insert( *itr );
01190       }
01191     }
01192   }
01193 
01194   if ( !sc.isSuccess() ) {
01195     throw GaudiException( "Problem connecting inputfile !!", name(),
01196                           StatusCode::FAILURE );
01197   }
01198   return;
01199 }
01200 
01201 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01202 
01203 void
01204 THistSvc::setupOutputFile( Property& /*m_outputfile*/ )
01205 {
01206   StatusCode sc = StatusCode::SUCCESS;
01207 
01208   typedef std::vector<std::string> Strings_t;
01209   for ( Strings_t::const_iterator
01210           itr  = m_outputfile.value().begin(),
01211           iEnd = m_outputfile.value().end();
01212         itr != iEnd;
01213         ++itr ) {
01214     if ( m_alreadyConnectedOutFiles.end() ==
01215          m_alreadyConnectedOutFiles.find( *itr ) ) {
01216       if ( connect(*itr).isFailure() ) {
01217         sc = StatusCode::FAILURE;
01218       } else {
01219         m_alreadyConnectedOutFiles.insert( *itr );
01220       }
01221     }
01222   }
01223 
01224   if ( !sc.isSuccess() ) {
01225     throw GaudiException( "Problem connecting outputfile !!", name(),
01226                           StatusCode::FAILURE );
01227   }
01228   return;
01229 }
01230 
01231 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01232 
01233 void
01234 THistSvc::updateFiles() {
01235 
01236   // If TTrees grow beyond TTree::fgMaxFileSize, a new file is
01237   // automatically created by root, and the old one closed. We
01238   // need to migrate all the UIDs over to show the correct file
01239   // pointer. This is ugly.
01240 
01241   uidMap::iterator uitr, uitr2;
01242   for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
01243     TObject* to = uitr->second.obj;
01244     TFile* oldFile = uitr->second.file;
01245     if (to->IsA()->InheritsFrom("TTree")) {
01246       TTree* tr = dynamic_cast<TTree*>(to);
01247       TFile* newFile = tr->GetCurrentFile();
01248 
01249       if (oldFile != newFile) {
01250         std::string newFileName = newFile->GetName();
01251         std::string oldFileName(""), streamName, rem;
01252         TFile* dummy;
01253         findStream(uitr->second.id, streamName, rem, dummy);
01254 
01255         map<string, pair<TFile*,Mode> >::iterator itr;
01256         for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01257           if (itr->second.first == oldFile) {
01258             itr->second.first = newFile;
01259 
01260           }
01261         }
01262 
01263         uitr2 = uitr;
01264         for (; uitr2 != m_uids.end(); ++uitr2) {
01265           if (uitr2->second.file == oldFile) {
01266             uitr2->second.file = newFile;
01267           }
01268         }
01269 
01270         streamMap::iterator sitr;
01271         for (sitr = m_fileStreams.begin(); sitr!=m_fileStreams.end(); ++sitr) {
01272           if (sitr->second == streamName) {
01273             oldFileName = sitr->first;
01274             break;
01275           }
01276         }
01277 
01278 
01279 #ifndef NDEBUG
01280         m_log << MSG::DEBUG << "migrating uid: " << uitr->second.id
01281               << "   stream: " << streamName
01282               << "   oldFile: " << oldFileName
01283               << "   newFile: " << newFileName
01284               << endmsg;
01285 #endif
01286 
01287 
01288         if (oldFileName != "") {
01289           while ( (sitr=m_fileStreams.find(oldFileName)) != m_fileStreams.end() ) {
01290 
01291 #ifndef NDEBUG
01292             m_log << MSG::DEBUG << "changing filename \"" << oldFileName
01293                   << "\" to \"" << newFileName << "\" for stream \""
01294                   << sitr->second << "\"" << endmsg;
01295 #endif
01296             m_fileStreams.erase(sitr);
01297             m_fileStreams.insert( make_pair<std::string,std::string>(newFileName,streamName) );
01298           }
01299 
01300 
01301         } else {
01302           m_log << MSG::ERROR
01303                 << "Problems updating fileStreams with new file name" << endmsg;
01304         }
01305 
01306       }
01307 
01308     }
01309   }
01310 
01311 }
01312 
01313 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01314 
01315 StatusCode
01316 THistSvc::write() {
01317 
01318   updateFiles();
01319 
01320   map<string, pair<TFile*,Mode> >::const_iterator itr;
01321   for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01322     if (itr->second.second == WRITE || itr->second.second == UPDATE
01323         ||itr->second.second==SHARE) {
01324       itr->second.first->Write("",TObject::kOverwrite);
01325     } else if (itr->second.second == APPEND) {
01326       itr->second.first->Write("");
01327     }
01328   }
01329 
01330 
01331   m_log << MSG::DEBUG << "THistSvc::write()::List of Files connected in ROOT "
01332         << endmsg;
01333 
01334   TSeqCollection *filelist=gROOT->GetListOfFiles();
01335   for (int ii=0; ii<filelist->GetEntries(); ii++) {
01336     m_log << MSG::DEBUG
01337           << "THistSvc::write()::List of Files connected in ROOT: \""
01338           << filelist->At(ii)->GetName()<<"\""<<endmsg;
01339   }
01340 
01341   return StatusCode::SUCCESS;
01342 
01343 }
01344 
01345 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01346 
01347 StatusCode
01348 THistSvc::connect(const std::string& ident) {
01349 
01350   Tokenizer tok(true);
01351 
01352   string::size_type loc = ident.find(" ");
01353   string stream = ident.substr(0,loc);
01354   char typ(0);
01355   typedef std::pair<std::string,std::string>      Prop;
01356   std::vector<Prop> props;
01357   string val,VAL,TAG,filename,db_typ("ROOT");
01358   int cl(1);
01359 
01360   tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
01361 
01362   for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++)    {
01363     const std::string& tag = (*i).tag();
01364     TAG = tag;
01365     toupper(TAG);
01366 
01367     val = (*i).value();
01368     VAL = val;
01369     toupper(VAL);
01370 
01371     if (TAG == "FILE" || TAG == "DATAFILE") {
01372       filename = val;
01373       removeDoubleSlash( filename );
01374     } else if ( TAG == "OPT" ) {
01375       if ( VAL == "APPEND" || VAL == "UPDATE" ) {
01376         typ = 'A';
01377       } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
01378         typ = 'N';
01379       } else if ( VAL == "RECREATE" ) {
01380         typ = 'R';
01381       } else if (VAL == "SHARE") {
01382         typ = 'S';
01383       } else if ( VAL == "OLD" || VAL == "READ" ) {
01384         typ = 'O';
01385       } else {
01386         m_log << MSG::ERROR << "Unknown OPT: \"" << (*i).value() << "\""
01387             << endmsg;
01388         typ = 0;
01389       }
01390     } else if (TAG == "TYP") {
01391       db_typ = (*i).value();
01392     } else if (TAG == "CL") {
01393       cl = atoi(val.c_str());
01394     } else {
01395       props.push_back( Prop((*i).tag(), (*i).value()));
01396     }
01397 
01398   }
01399 
01400   if (stream == "temp") {
01401     m_log << MSG::ERROR << "in JobOption \"" << ident
01402           << "\": stream name \"temp\" reserved."
01403           << endmsg;
01404     return StatusCode::FAILURE;
01405   }
01406 
01407   if (db_typ != "ROOT") {
01408     m_log << MSG::ERROR << "in JobOption \"" << ident
01409           << "\": technology type \"" << db_typ << "\" not supported."
01410           << endmsg;
01411     return StatusCode::FAILURE;
01412   }
01413 
01414 
01415   if (m_files.find(stream) != m_files.end()) {
01416     m_log << MSG::ERROR << "in JobOption \"" << ident
01417           << "\":\n stream \"" << stream << "\" already connected to file: \""
01418           << m_files[stream].first->GetName() << "\""
01419           << endmsg;
01420     return StatusCode::FAILURE;
01421   }
01422 
01423   Mode newMode;
01424   if (typ == 'O') {
01425     newMode = THistSvc::READ;
01426   } else if (typ == 'N') {
01427     newMode = THistSvc::WRITE;
01428   } else if (typ == 'A') {
01429     newMode = THistSvc::APPEND;
01430   } else if (typ == 'R') {
01431     newMode = THistSvc::UPDATE;
01432   } else if (typ == 'S') {
01433     newMode = THistSvc::SHARE;
01434   } else {
01435     // something else?
01436     m_log << MSG::ERROR << "No OPT= specified or unknown access mode in: "
01437           << ident << endmsg;
01438     return StatusCode::FAILURE;
01439   }
01440 
01441   // Is this file already connected to another stream?
01442   if (m_fileStreams.find(filename) != m_fileStreams.end()) {
01443     std::pair<streamMap::iterator, streamMap::iterator> fitr =
01444       m_fileStreams.equal_range(filename);
01445 
01446     std::string oldstream = (fitr.first)->second;
01447 
01448     std::pair<TFile*,Mode> f_info = m_files[oldstream];
01449 
01450     if (newMode != f_info.second) {
01451       m_log << MSG::ERROR << "in JobOption \"" << ident
01452             << "\":\n file \"" << filename << "\" already opened by stream: \""
01453             << oldstream << "\" with different access mode."
01454             << endmsg;
01455       return StatusCode::FAILURE;
01456     } else {
01457       TFile *f2 = f_info.first;
01458       m_files[stream] = make_pair<TFile*,Mode>(f2,newMode);
01459       m_log << MSG::DEBUG << "Connecting stream: \"" << stream
01460             << "\" to previously opened TFile: \"" << filename << "\""
01461             << endmsg;
01462       return StatusCode::SUCCESS;
01463     }
01464   }
01465 
01466 
01467   IIncidentSvc *pi(0);
01468   if (service("IncidentSvc",pi).isFailure()) {
01469     m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg;
01470     return StatusCode::FAILURE;
01471   }
01472 
01473   TFile *f(0) ;
01474   if (newMode == THistSvc::READ) {
01475     // old file
01476 
01477     try {
01478       f = TFile::Open(filename.c_str(),"READ");
01479     } catch (const std::exception& Exception) {
01480       m_log << MSG::ERROR << "exception caught while trying to open root"
01481             << " file for reading: " << Exception.what() << std::endl
01482             << "  -> file probably corrupt." << endmsg;
01483       pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01484                                     filename));
01485       return StatusCode::FAILURE;
01486     } catch (...) {
01487       m_log << MSG::ERROR << "Problems opening input file  \"" << filename
01488             << "\": probably corrupt" << endmsg;
01489       pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01490                                     filename));
01491       return StatusCode::FAILURE;
01492     }
01493 
01494     if (!f->IsOpen()) {
01495       m_log << MSG::ERROR << "Unable to open input file \"" << filename
01496             << "\": file does not exist" << endmsg;
01497       pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01498                                     filename));
01499       return StatusCode::FAILURE;
01500     }
01501 
01502     // FIX ME!
01503     pi->fireIncident(FileIncident(name(), "BeginHistFile",
01504                                   filename));
01505 
01506 
01507   } else if (newMode == THistSvc::WRITE) {
01508     // new file
01509 
01510     f = TFile::Open(filename.c_str(),"NEW",stream.c_str(),cl);
01511     if (!f->IsOpen()) {
01512       m_log << MSG::ERROR << "Unable to create new output file \"" << filename
01513             << "\" for writing: file already exists" << endmsg;
01514       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01515                                     filename));
01516       return StatusCode::FAILURE;
01517     }
01518 
01519     // FIX ME!
01520     pi->fireIncident(FileIncident(name(), "BeginHistFile",
01521                                   filename));
01522 
01523   } else if (newMode == THistSvc::APPEND) {
01524     // update file
01525 
01526     try {
01527       f =  TFile::Open(filename.c_str(),"UPDATE",stream.c_str(),cl);
01528     } catch (const std::exception& Exception) {
01529       m_log << MSG::ERROR << "exception caught while trying to open root"
01530             << " file for appending: " << Exception.what() << std::endl
01531             << "  -> file probably corrupt." << endmsg;
01532       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01533                                     filename));
01534       return StatusCode::FAILURE;
01535     } catch (...) {
01536       m_log << MSG::ERROR << "Problems opening output file  \"" << filename
01537             << "\" for append: probably corrupt" << endmsg;
01538       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01539                                     filename));
01540       return StatusCode::FAILURE;
01541     }
01542 
01543     if (!f->IsOpen()) {
01544       m_log << MSG::ERROR << "Unable to open output file \"" << filename
01545             << "\" for appending" << endmsg;
01546       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01547                                     filename));
01548       return StatusCode::FAILURE;
01549     }
01550     pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01551                                   filename));
01552 
01553   } else if (newMode == THistSvc::SHARE) {
01554     // SHARE file type
01555     //For SHARE files, all data will be stored in a temp file and will be merged into the target file
01556     //in write() when finalize(), this help to solve some confliction. e.g. with storegate
01557 
01558     static int ishared = 0;
01559     stringstream out;
01560     string realfilename=filename;
01561     out << ishared++;
01562     filename = string("tmp_THistSvc_")+out.str()+string(".root");
01563 
01564     m_log << MSG::DEBUG << "Creating temp file \"" << filename
01565           << "\" and realfilename="<<realfilename << endmsg;
01566     m_sharedFiles[stream]=realfilename;
01567 
01568     try {
01569       f = TFile::Open(filename.c_str(),"NEW",stream.c_str(),cl);
01570     } catch (const std::exception& Exception) {
01571       m_log << MSG::ERROR << "exception caught while trying to open root"
01572             << " file for appending: " << Exception.what() << std::endl
01573             << "  -> file probably corrupt." << endmsg;
01574       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01575                                     filename));
01576       return StatusCode::FAILURE;
01577     } catch (...) {
01578       m_log << MSG::ERROR << "Problems opening output file  \"" << filename
01579             << "\" for append: probably corrupt" << endmsg;
01580       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01581                                     filename));
01582       return StatusCode::FAILURE;
01583     }
01584 
01585     if (!f->IsOpen()) {
01586       m_log << MSG::ERROR << "Unable to open output file \"" << filename
01587             << "\" for appending" << endmsg;
01588       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01589                                     filename));
01590       return StatusCode::FAILURE;
01591     }
01592     pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01593                                   filename));
01594 
01595   } else if (newMode == THistSvc::UPDATE) {
01596     // update file
01597 
01598     try {
01599       f =  TFile::Open(filename.c_str(),"RECREATE",stream.c_str(),cl);
01600     } catch (const std::exception& Exception) {
01601       m_log << MSG::ERROR << "exception caught while trying to open root"
01602             << " file for updating: " << Exception.what() << std::endl
01603             << "  -> file probably corrupt." << endmsg;
01604       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01605                                     filename));
01606       return StatusCode::FAILURE;
01607     } catch (...) {
01608       m_log << MSG::ERROR << "Problems opening output file  \"" << filename
01609             << "\" for update: probably corrupt" << endmsg;
01610       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01611                                     filename));
01612       return StatusCode::FAILURE;
01613     }
01614 
01615     if (!f->IsOpen()) {
01616       m_log << MSG::ERROR << "Unable to open output file \"" << filename
01617             << "\" for updating" << endmsg;
01618       pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01619                                     filename));
01620       return StatusCode::FAILURE;
01621     }
01622     pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01623                                   filename));
01624 
01625   }
01626 
01627   m_files[stream] = make_pair<TFile*,Mode>(f,newMode);
01628   m_fileStreams.insert(make_pair<std::string,std::string>(filename,stream));
01629 
01630   m_log << MSG::DEBUG << "Opening TFile \"" << filename << "\"  stream: \""
01631         << stream << "\"  mode: \"" << typ << "\"" << " comp level: " << cl
01632         << endmsg;
01633 
01634   return StatusCode::SUCCESS;
01635 }
01636 
01637 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01638 
01639 TDirectory*
01640 THistSvc::changeDir(const THistSvc::THistID& hid) const {
01641 
01642   string uid = hid.id;
01643   TFile* file = hid.file;
01644   string stream, fdir, bdir, dir, id;
01645 
01646   if (file != 0) {
01647     file->cd("/");
01648   } else {
01649     gROOT->cd();
01650   }
01651 
01652   fdir = uid;
01653   bdir = dirname(fdir);
01654 
01655   while ( (dir = dirname(fdir)) != "") {
01656     if (! gDirectory->GetKey(dir.c_str())) {
01657       gDirectory->mkdir(dir.c_str());
01658     }
01659     gDirectory->cd(dir.c_str());
01660   }
01661 
01662   return gDirectory;
01663 
01664 }
01665 
01666 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01667 
01668 std::string
01669 THistSvc::dirname(std::string& dir) const {
01670 
01671 
01672   string::size_type i = dir.find("/");
01673 
01674   if (i == string::npos) {
01675     return "";
01676   }
01677 
01678   if ( i == 0 ) {
01679     dir.erase(0,1);
01680     return dirname(dir);
01681   }
01682 
01683   string root = dir.substr(0,i);
01684   dir.erase(0,i);
01685 
01686   return root;
01687 
01688 }
01689 
01690 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01691 
01692 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore() {
01693   m_gd = gDirectory;
01694   m_gf = gFile;
01695   m_ge = gErrorIgnoreLevel;
01696 }
01697 
01698 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore() {
01699   gDirectory = m_gd;
01700   gFile = m_gf;
01701   gErrorIgnoreLevel = m_ge;
01702 }
01703 
01704 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01705 
01706 void
01707 THistSvc::removeDoubleSlash(std::string& id) const {
01708 
01709   while (id.find("//") != std::string::npos) {
01710     id.replace(id.find("//"),2,"/");
01711   }
01712 
01713 }
01714 
01715 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01716 
01717 void THistSvc::MergeRootFile(TDirectory *target, TDirectory *source) {
01718 
01719   m_log <<MSG::DEBUG << "Target path: " << target->GetPath() << endmsg;
01720   TString path( (char*)strstr(target->GetPath(), ":") );
01721   path.Remove( 0, 2);
01722 
01723   source->cd(path);
01724   TDirectory *current_sourcedir = gDirectory;
01725 
01726   // loop over all keys in this directory
01727   TList *lkeys=current_sourcedir->GetListOfKeys();
01728   int nkeys=lkeys->GetEntries();
01729   TKey *key;
01730   for (int jj=0; jj<nkeys; jj++) {
01731     key=(TKey*) lkeys->At(jj);
01732     string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName();
01733     m_log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endmsg;
01734     //key->Dump();
01735     //TObject *obj=key->ReadObj();
01736     TObject *obj=source->Get(pathnameinsource.c_str());
01737 
01738     if (obj->IsA()->InheritsFrom("TDirectory") ) {
01739       // it's a subdirectory
01740 
01741       m_log <<MSG::DEBUG << "Found subdirectory " << obj->GetName()
01742             << endmsg;
01743 
01744       // create a new subdir of same name and title in the target file
01745       target->cd();
01746       TDirectory *newtargetdir =
01747         target->mkdir(obj->GetName(), obj->GetTitle() );
01748 
01749       MergeRootFile(newtargetdir, source);
01750 
01751     } else if (obj->IsA()->InheritsFrom("TTree")) {
01752       m_log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endmsg;
01753       TTree *mytree=dynamic_cast<TTree*>(obj);
01754       int nentries=(int) mytree->GetEntries();
01755       mytree->SetBranchStatus("*",1);
01756 
01757       m_log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries"
01758           << endmsg;
01759       //mytree->Print();
01760       //for (int ij=0; ij<nentries; ij++) {
01761       //m_log <<MSG::DEBUG << "Dumping TTree Show( " << ij <<" )"
01762       //<< endmsg;
01763       //mytree->Show(ij);
01764       //}
01765       target->cd();
01766       mytree->CloneTree();
01767 
01768       //m_log <<MSG::DEBUG << "Writing TTree to target file: ( "
01769       //<< mycopiedtree->Write(key->GetName()) <<" ) bytes written"
01770       //<< endmsg;
01771 
01772     } else if (obj) {
01773       target->cd();
01774       obj->Write(key->GetName() );
01775     }
01776 
01777   } // while ( ( TKey *key = (TKey*)nextkey() ) )
01778 
01779   // save modifications to target file
01780 
01781 }
01782 
01783 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01784 
01785 bool
01786 THistSvc::exists( const std::string& name ) const {
01787 
01788   TH1* h;
01789 
01790   return getHist_i(name,h,true).isSuccess();
01791 
01792 
01793 }
01794 
01795 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
01796 
01797 void
01798 THistSvc::handle( const Incident& /* inc */ ) {
01799 
01800   if (signaledStop) return ;
01801 
01802   // convert to bytes.
01803   Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
01804   Long64_t mfs_warn = mfs * 95 / 100;
01805 
01806   updateFiles();
01807 
01808   map<string, pair<TFile*,Mode> >::const_iterator itr;
01809   for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01810     TFile* tf = itr->second.first;
01811 
01812 #ifndef NDEBUG
01813     m_log << MSG::DEBUG << "stream: " << itr->first << "  name: "
01814           << tf->GetName() << "  size: " << tf->GetSize()
01815           << endmsg;
01816 #endif
01817 
01818     // Signal job to terminate if output file is too large
01819     if (tf->GetSize() > mfs) {
01820 
01821       signaledStop = true;
01822 
01823       m_log << MSG::FATAL << "file \"" << tf->GetName()
01824             << "\" associated with stream \"" << itr->first
01825             << "\" has exceeded the max file size of "
01826             << m_maxFileSize.value() << "MB. Terminating Job."
01827             << endmsg;
01828 
01829       IEventProcessor* evt(0);
01830       if (service("ApplicationMgr", evt, true).isSuccess()) {
01831         evt->stopRun();
01832         evt->release();
01833       } else {
01834         abort();
01835       }
01836     } else if (tf->GetSize() > mfs_warn) {
01837       m_log << MSG::WARNING << "file \"" << tf->GetName()
01838             << "\" associated with stream \"" << itr->first
01839             << "\" is at 95% of its maximum allowable file size of "
01840             << m_maxFileSize.value() << "MB"
01841             << endmsg;
01842     }
01843   }
01844 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Wed Feb 9 16:25:04 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004