Gaudi Framework, version v23r4

Home   Generated: Mon Sep 17 2012

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

Generated at Mon Sep 17 2012 13:49:36 for Gaudi Framework, version v23r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004