| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 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