Gaudi Framework, version v22r2

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

Generated at Tue May 10 2011 18:54:10 for Gaudi Framework, version v22r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004