| # Gaudi Framework, version v21r9 |

Home |  | Generated: 3 May 2010

# 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/IEventProcessor.h"
    00016
    00017 #include "TROOT.h"
    00018 #include "TFile.h"
    00019 #include "TDirectory.h"
    00020 #include "TKey.h"
    00021 #include "TError.h"
    00022 #include "TGraph.h"
    00023
    00024 #include <sstream>
    00025 #include <streambuf>
    00026 #include <cstdio>
    00027 #include <algorithm>
    00028
    00029 using namespace std;
    00030
    00031
    00032 DECLARE_SERVICE_FACTORY(THistSvc)
    00033
    00034 inline void toupper(std::string &s)
    00035 {
    00036   std::transform(s.begin(), s.end(), s.begin(),
    00037                  (int(*)(int)) toupper);
    00038 }
    00039
    00040
    00041 //*************************************************************************//
    00042
    00043 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc )
    00044   : base_class(name, svc), m_log(msgSvc(), name ), signaledStop(false) {
    00045
    00046   declareProperty ("Output", m_outputfile );
    00047   declareProperty ("Input", m_inputfile );
    00048   declareProperty ("AutoSave", m_autoSave=0 );
    00049   declareProperty ("PrintAll", m_print=false);
    00050   declareProperty ("CompressionLevel", m_compressionLevel=1 );
    00051   declareProperty ("MaxFileSize", m_maxFileSize=5120,
    00052                    "maximum file size in MB. if exceeded, will cause an abort");
    00053
    00054   m_inputfile.declareUpdateHandler ( &THistSvc::setupInputFile,  this );
    00055   m_outputfile.declareUpdateHandler( &THistSvc::setupOutputFile, this );
    00056 }
    00057
    00058 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00059
    00060 THistSvc::~THistSvc() {
    00061
    00062 }
    00063
    00064 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00065
    00066 StatusCode
    00067 THistSvc::initialize() {
    00068   GlobalDirectoryRestore restore;
    00069
    00070   m_alreadyConnectedOutFiles.clear();
    00071   m_alreadyConnectedInFiles.clear();
    00072
    00073   StatusCode status = Service::initialize();
    00074   m_log.setLevel( m_outputLevel.value() );
    00075
    00076   if (status.isFailure()) {
    00077     MsgStream log ( msgSvc(), name() );
    00078     log << MSG::ERROR << "initializing service" << endmsg;
    00079     return status;
    00080   }
    00081
    00082   vector<string>::const_iterator itr;
    00083   StatusCode st(StatusCode::SUCCESS);
    00084
    00085   try {
    00086     setupOutputFile( m_outputfile );
    00087   } catch ( GaudiException& err ) {
    00088     m_log << MSG::ERROR
    00089           << "Caught: " << err << endmsg;
    00090     st = StatusCode::FAILURE;
    00091   }
    00092
    00093   try {
    00094     setupInputFile( m_inputfile );
    00095   } catch ( GaudiException& err ) {
    00096     m_log << MSG::ERROR
    00097           << "Caught: " << err << endmsg;
    00098     st = StatusCode::FAILURE;
    00099   }
    00100
    00101   // Protect against multiple instances of TROOT
    00102   if ( 0 == gROOT )   {
    00103     static TROOT root("root","ROOT I/O");
    00104     //    gDebug = 99;
    00105   } else {
    00106     m_log << MSG::VERBOSE << "ROOT already initialized, debug = "
    00107           << gDebug<< endmsg;
    00108   }
    00109
    00110   IIncidentSvc* p_incSvc(0);
    00111
    00112   if (service("IncidentSvc", p_incSvc, true).isFailure()) {
    00113     m_log << MSG::ERROR << "unable to get the IncidentSvc" << endmsg;
    00114     st = StatusCode::FAILURE;
    00115   } else {
    00116     p_incSvc->addListener( this, "EndEvent", 100, true);
    00117   }
    00118
    00119   if (st.isFailure()) {
    00120     m_log << MSG::FATAL << "Unable to initialize THistSvc" << endmsg;
    00121   }
    00122
    00123   return st;
    00124
    00125 }
    00126
    00127 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00128
    00129 StatusCode
    00130 THistSvc::reinitialize() {
    00131
    00132   GlobalDirectoryRestore restore;
    00133
    00134   m_log << MSG::WARNING << "reinitialize not implemented" << endmsg;
    00135
    00136
    00137   return StatusCode::SUCCESS;
    00138
    00139 }
    00140
    00141 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00142
    00143 StatusCode
    00144 THistSvc::finalize() {
    00145
    00146   GlobalDirectoryRestore restore;
    00147
    00148   m_log << MSG::DEBUG << "THistSvc::finalize" << endmsg;
    00149
    00150   uidMap::const_iterator uitr;
    00151   for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
    00152
    00153     TObject* to = uitr->second.obj;
    00154
    00155     string dirname("none");
    00156     if (to->IsA()->InheritsFrom("TTree")) {
    00157       TTree* tr = dynamic_cast<TTree*>(to);
    00158       if (tr->GetDirectory() != 0) {
    00159         dirname = tr->GetDirectory()->GetPath();
    00160       }
    00161     } else if (to->IsA()->InheritsFrom("TGraph")) {
    00162       if (!uitr->second.temp) {
    00163         dirname = uitr->second.file->GetPath();
    00164         string id2(uitr->second.id);
    00165         id2.erase(0,id2.find("/",1));
    00166         id2.erase(id2.rfind("/"), id2.length());
    00167         if (id2.find("/") == 0) {
    00168           id2.erase(0,1);
    00169         }
    00170         dirname += id2;
    00171       } else {
    00172         dirname = "/tmp";
    00173       }
    00174     } else if (to->IsA()->InheritsFrom("TH1")) {
    00175       TH1* th = dynamic_cast<TH1*>(to);
    00176       if (th == 0) {
    00177         m_log << MSG::ERROR << "Couldn't dcast: " << uitr->first << endmsg;
    00178       } else {
    00179         if (th->GetDirectory() != 0) {
    00180           dirname = th->GetDirectory()->GetPath();
    00181         }
    00182       }
    00183     }
    00184
    00185     m_log << MSG::DEBUG << "uid: \"" << uitr->first << "\"  temp: "
    00186         << uitr->second.temp << "  dir: " << dirname
    00187         << endmsg;
    00188
    00189
    00190 //     if (uitr->second.temp == true) {
    00191 //       log << MSG::INFO << "Deleting \"" << uitr->first << "\"" << endmsg;
    00192 //       delete uitr->second.obj;
    00193 //     }
    00194   }
    00195
    00196   StatusCode sc = write();
    00197   if (sc.isFailure()) {
    00198     m_log << MSG::ERROR << "problems writing histograms" << endmsg;
    00199   }
    00200
    00201   if (m_print) {
    00202     m_log << MSG::INFO << "Listing contents of ROOT files: " << endmsg;
    00203   }
    00204   vector<TFile*> deleted_files;
    00205   map<string, pair<TFile*,Mode> >::const_iterator itr;
    00206   for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
    00207
    00208     if (find(deleted_files.begin(), deleted_files.end(), itr->second.first) ==
    00209         deleted_files.end()) {
    00210       deleted_files.push_back(itr->second.first);
    00211
    00212       m_log << MSG::DEBUG << "finalizing stream/file " << itr->first << ":"
    00213             << itr->second.first->GetName()
    00214             << endmsg;
    00215     } else {
    00216       m_log << MSG::DEBUG << "already finalized stream " << itr->first << endmsg;
    00217       continue;
    00218     }
    00219
    00220
    00221     if (m_print && m_log.level() <= MSG::INFO) {
    00222
    00223       m_log << MSG::INFO;
    00224       m_log << "==> File: " << itr->second.first->GetName()
    00225             << "  stream: " << itr->first << endmsg;
    00226
    00227       itr->second.first->Print("base");
    00228     }
    00229
    00230     string tmpfn=itr->second.first->GetName();
    00231
    00232     itr->second.first->Close();
    00233
    00234     if (itr->second.second==SHARE) {
    00235       TFile *outputfile;
    00236       //Merge File
    00237       try {
    00238         m_log << MSG::DEBUG << "Opening Final Output File: " <<m_sharedFiles[itr->first].c_str()<<endmsg;
    00239         outputfile = new TFile(m_sharedFiles[itr->first].c_str(), "UPDATE");
    00240       } catch (const std::exception& Exception) {
    00241       m_log << MSG::ERROR << "exception caught while trying to open root"
    00242             << " file for appending: " << Exception.what() << std::endl
    00243             << "  -> file probably corrupt." << endmsg;
    00244       return StatusCode::FAILURE;
    00245       } catch (...) {
    00246         m_log << MSG::ERROR << "Problems opening output file  \"" << m_sharedFiles[itr->first]
    00247             << "\" for append: probably corrupt" << endmsg;
    00248         return StatusCode::FAILURE;
    00249       }
    00250
    00251       m_log << MSG::DEBUG << "THistSvc::write()::Merging Rootfile "<<endmsg;
    00252       TFile *inputfile;
    00253       try {
    00254         m_log << MSG::DEBUG << "Openning again Temporary File: " <<tmpfn.c_str()<<endmsg;
    00255         inputfile=new TFile(tmpfn.c_str(),"READ");
    00256       } catch (const std::exception& Exception) {
    00257         m_log << MSG::ERROR << "exception caught while trying to open root"
    00258               << " file for appending: " << Exception.what() << std::endl
    00259               << "  -> file probably corrupt." << endmsg;
    00260         return StatusCode::FAILURE;
    00261       } catch (...) {
    00262         m_log << MSG::ERROR << "Problems opening output file  \""
    00263               << tmpfn.c_str()
    00264               << "\" for append: probably corrupt" << endmsg;
    00265         return StatusCode::FAILURE;
    00266       }
    00267
    00268       MergeRootFile(outputfile, inputfile);
    00269
    00270       outputfile->SetCompressionLevel( m_compressionLevel );
    00271
    00272       outputfile->Write();
    00273       outputfile->Close();
    00274       inputfile->Close();
    00275
    00276       m_log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn
    00277             << "\""<<endmsg;
    00278
    00279       std::remove(tmpfn.c_str());
    00280     }
    00281     delete itr->second.first;
    00282   }
    00283
    00284   m_sharedFiles.clear();
    00285   m_fileStreams.clear();
    00286   m_files.clear();
    00287   m_uids.clear();
    00288   m_ids.clear();
    00289   m_tobjs.clear();
    00290
    00291   return Service::finalize();
    00292 }
    00293
    00294 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00295
    00296 bool
    00297 THistSvc::browseTDir(TDirectory *dir) const {
    00298
    00299   if (dir == 0) {
    00300     std::cerr << "TDirectory == 0" << std::endl;
    00301     return false;
    00302   }
    00303
    00304   GlobalDirectoryRestore restore;
    00305
    00306   dir->cd();
    00307
    00308
    00309   cout << "-> " << dir->GetPath() << "  "
    00310        << dir->GetListOfKeys()->GetSize() << endl;
    00311
    00312   //  TIter nextkey(dir->GetListOfKeys());
    00313   TIter nextkey(dir->GetList());
    00314   while (TKey *key = (TKey*)nextkey()) {
    00315
    00316     TObject *obj = key->ReadObj();
    00317     if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
    00318     //    if (obj->IsA()->InheritsFrom("TDirectory")) {
    00319       cout << "  Key: " << key->GetName() << "   "
    00320            << " tit: " << obj->GetTitle() << "   "
    00321            << " (" << key->GetClassName() << ")" << endl;
    00322       //    }
    00323   }
    00324
    00325   nextkey = dir->GetListOfKeys();
    00326   while (TKey *key = (TKey*)nextkey()) {
    00327
    00328     TObject *obj = key->ReadObj();
    00329     if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
    00330     if (obj->IsA()->InheritsFrom("TDirectory")) {
    00331       TDirectory *tt = dynamic_cast<TDirectory*>(obj);
    00332       browseTDir(tt);
    00333     }
    00334   }
    00335
    00336   return true;
    00337 }
    00338
    00339 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00340
    00341 StatusCode
    00342 THistSvc::getTHists(TDirectory *td, TList & tl) const {
    00343
    00344   GlobalDirectoryRestore restore;
    00345
    00346   gErrorIgnoreLevel = kBreak;
    00347
    00348   if (!td->cd()) {
    00349     m_log << MSG::ERROR << "No such TDirectory \"" << td->GetPath() << "\""
    00350           << endmsg;
    00351     return StatusCode::FAILURE;
    00352   }
    00353
    00354   TIter nextkey(td->GetList());
    00355   while (TObject *key = (TObject*)nextkey()) {
    00356     if (key != 0) {
    00357       if (key->IsA()->InheritsFrom("TH1")) { tl.Add(key); }
    00358     }
    00359   }
    00360
    00361
    00362   return StatusCode::SUCCESS;
    00363
    00364 }
    00365
    00366 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00367
    00368 StatusCode
    00369 THistSvc::getTHists(const std::string& dir, TList & tl) const {
    00370
    00371   GlobalDirectoryRestore restore;
    00372
    00373   gErrorIgnoreLevel = kBreak;
    00374
    00375   StatusCode sc;
    00376
    00377   if (!gDirectory->cd(dir.c_str())) {
    00378     m_log << MSG::ERROR << "No such TDirectory \"" << dir << "\""
    00379           << endmsg;
    00380     sc = StatusCode::FAILURE;
    00381   } else {
    00382     sc = getTHists(gDirectory,tl);
    00383   }
    00384
    00385   return sc;
    00386
    00387 }
    00388 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00389
    00390 StatusCode
    00391 THistSvc::getTTrees(TDirectory *td, TList & tl) const {
    00392
    00393   GlobalDirectoryRestore restore;
    00394
    00395   gErrorIgnoreLevel = kBreak;
    00396
    00397   if (!td->cd()) {
    00398     m_log << MSG::ERROR << "No such TDirectory \"" << td->GetPath() << "\""
    00399           << endmsg;
    00400     return StatusCode::FAILURE;
    00401   }
    00402
    00403   TIter nextkey(td->GetList());
    00404   while (TObject *key = (TObject*)nextkey()) {
    00405     if (key != 0) {
    00406       if (key->IsA()->InheritsFrom("TTree")) { tl.Add(key); }
    00407     }
    00408   }
    00409
    00410   return StatusCode::SUCCESS;
    00411
    00412 }
    00413
    00414 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00415
    00416 StatusCode
    00417 THistSvc::getTTrees(const std::string& dir, TList & tl) const {
    00418
    00419   GlobalDirectoryRestore restore;
    00420
    00421   gErrorIgnoreLevel = kBreak;
    00422
    00423   StatusCode sc;
    00424
    00425   if (!gDirectory->cd(dir.c_str())) {
    00426     m_log << MSG::ERROR << "No such TDirectory \"" << dir << "\""
    00427           << endmsg;
    00428     sc = StatusCode::FAILURE;
    00429   } else {
    00430     sc = getTTrees(gDirectory,tl);
    00431   }
    00432
    00433   return sc;
    00434
    00435 }
    00436
    00437 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00438
    00439 StatusCode
    00440 THistSvc::deReg(TObject* obj) {
    00441
    00442   objMap::iterator itr = m_tobjs.find(obj);
    00443   if (itr != m_tobjs.end()) {
    00444     THistID hid = itr->second;
    00445
    00446     uidMap::iterator itr2 = m_uids.find(hid.id);
    00447     if (itr2 == m_uids.end()) {
    00448       m_log << MSG::ERROR << "Problems deregistering TObject \""
    00449             << obj->GetName()
    00450             << "\" with id \"" << hid.id << "\"" << endmsg;
    00451       return StatusCode::FAILURE;
    00452     }
    00453
    00454     std::string id,root,rem;
    00455     parseString(hid.id, root, rem);
    00456
    00457     idMap::iterator itr3;
    00458     bool found(false);
    00459
    00460     std::pair<idMap::iterator, idMap::iterator> mitr = m_ids.equal_range(rem);
    00461     if (mitr.first == mitr.second) {
    00462       m_log << MSG::ERROR << "Problems deregistering TObject \""
    00463             << obj->GetName()
    00464             << "\" with id \"" << hid.id << "\"" << endmsg;
    00465       return StatusCode::FAILURE;
    00466     } else {
    00467       for (itr3 = mitr.first; itr3 != mitr.second; ++itr3) {
    00468         if (itr3->second.obj == obj) {
    00469           found = true;
    00470           break;
    00471         }
    00472       }
    00473       if (!found) {
    00474         m_log << MSG::ERROR << "Problems deregistering TObject \""
    00475               << obj->GetName()
    00476               << "\" with id \"" << hid.id << "\"" << endmsg;
    00477       }
    00478     }
    00479
    00480     m_tobjs.erase(itr);
    00481     m_uids.erase(itr2);
    00482     m_ids.erase(itr3);
    00483
    00484     return StatusCode::SUCCESS;
    00485
    00486   } else {
    00487     m_log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName()
    00488           << "\": not known to THistSvc" << endmsg;
    00489     return StatusCode::FAILURE;
    00490   }
    00491
    00492 }
    00493
    00494
    00495 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00496
    00497 StatusCode
    00498 THistSvc::deReg(const std::string& id) {
    00499
    00500   uidMap::iterator itr = m_uids.find(id);
    00501   if (itr == m_uids.end()) {
    00502     m_log << MSG::ERROR << "Problems deregistering id \""
    00503           << id << "\"" << endmsg;
    00504     return StatusCode::FAILURE;
    00505   }
    00506
    00507   TObject* obj = itr->second.obj;
    00508
    00509   return deReg(obj);
    00510 }
    00511
    00512 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00513
    00514 StatusCode
    00515 THistSvc::regHist(const std::string& id) {
    00516
    00517   TH1 *hist(0);
    00518
    00519   return regHist_i(hist, id);
    00520 }
    00521
    00522 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00523
    00524 StatusCode
    00525 THistSvc::regHist(const std::string& id, TH1* hist) {
    00526   return regHist_i(hist, id);
    00527 }
    00528
    00529 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00530
    00531 StatusCode
    00532 THistSvc::regHist(const std::string& id, TH2* hist) {
    00533   return regHist_i(hist, id);
    00534 }
    00535
    00536 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00537
    00538 StatusCode
    00539 THistSvc::regHist(const std::string& id, TH3* hist) {
    00540   return regHist_i(hist, id);
    00541 }
    00542
    00543 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00544
    00545 StatusCode
    00546 THistSvc::regTree(const std::string& id) {
    00547   TTree *hist(0);
    00548   return regHist_i(hist, id);
    00549 }
    00550
    00551 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00552
    00553 StatusCode
    00554 THistSvc::regTree(const std::string& id, TTree* hist) {
    00555   StatusCode sc = regHist_i(hist, id);
    00556   if (hist != 0 && m_autoSave != 0 && sc.isSuccess()) {
    00557     hist->SetAutoSave(m_autoSave);
    00558   }
    00559   return sc;
    00560 }
    00561
    00562 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00563
    00564 StatusCode
    00565 THistSvc::regGraph(const std::string& id) {
    00566   TGraph *hist(0);
    00567   return regHist_i(hist, id);
    00568 }
    00569
    00570 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00571
    00572 StatusCode
    00573 THistSvc::regGraph(const std::string& id, TGraph* hist) {
    00574   if ( strcmp(hist->GetName(),"Graph") == 0 ) {
    00575
    00576     std::string id2(id);
    00577     string::size_type i = id2.rfind("/");
    00578     if (i != string::npos) {
    00579       id2.erase(0,i+1);
    00580     }
    00581
    00582     m_log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \""
    00583           << id2 << "\" since it is unset" << endmsg;
    00584     hist->SetName(id2.c_str());
    00585   }
    00586
    00587   return regHist_i(hist, id);
    00588 }
    00589
    00590 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00591
    00592 StatusCode
    00593 THistSvc::getHist(const std::string& id, TH1*& hist) const {
    00594   return getHist_i(id, hist);
    00595 }
    00596
    00597 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00598
    00599 StatusCode
    00600 THistSvc::getHist(const std::string& id, TH2*& hist) const {
    00601   return getHist_i(id, hist);
    00602 }
    00603
    00604 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00605
    00606 StatusCode
    00607 THistSvc::getHist(const std::string& id, TH3*& hist) const {
    00608   return getHist_i(id, hist);
    00609 }
    00610
    00611 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00612
    00613 std::vector<std::string>
    00614 THistSvc::getHists() const {
    00615
    00616   std::vector<std::string> names;
    00617   names.reserve(m_uids.size());
    00618
    00619   uidMap::const_iterator itr;
    00620   for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
    00621     THistID tid = itr->second;
    00622
    00623     if (tid.obj->IsA()->InheritsFrom("TH1")) {
    00624       names.push_back(itr->first);
    00625     }
    00626
    00627   }
    00628
    00629   return names;
    00630
    00631 }
    00632 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00633
    00634 StatusCode
    00635 THistSvc::getTree(const std::string& id, TTree*& hist) const {
    00636   return getHist_i(id, hist);
    00637 }
    00638
    00639 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00640
    00641 std::vector<std::string>
    00642 THistSvc::getTrees() const {
    00643
    00644   std::vector<std::string> names;
    00645   names.reserve(m_uids.size());
    00646
    00647   uidMap::const_iterator itr;
    00648   for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
    00649     THistID tid = itr->second;
    00650
    00651     if (tid.obj->IsA()->InheritsFrom("TTree")) {
    00652       names.push_back(itr->first);
    00653     }
    00654
    00655   }
    00656
    00657   return names;
    00658
    00659 }
    00660 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00661
    00662 StatusCode
    00663 THistSvc::getGraph(const std::string& id, TGraph*& hist) const {
    00664   return getHist_i(id, hist);
    00665 }
    00666
    00667 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00668
    00669 std::vector<std::string>
    00670 THistSvc::getGraphs() const {
    00671
    00672   std::vector<std::string> names;
    00673   names.reserve(m_uids.size());
    00674
    00675   uidMap::const_iterator itr;
    00676   for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
    00677     THistID tid = itr->second;
    00678
    00679     if (tid.obj->IsA()->InheritsFrom("TGraph")) {
    00680       names.push_back(itr->first);
    00681     }
    00682
    00683   }
    00684
    00685   return names;
    00686
    00687 }
    00688 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00689
    00690 StatusCode
    00691 THistSvc::readHist(const std::string& id, TH1*& hist) const {
    00692   return readHist_i(id, hist);
    00693 }
    00694
    00695 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00696
    00697 StatusCode
    00698 THistSvc::readHist(const std::string& id, TH2*& hist) const {
    00699   return readHist_i(id, hist);
    00700 }
    00701
    00702 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00703
    00704 StatusCode
    00705 THistSvc::readHist(const std::string& id, TH3*& hist) const {
    00706   return readHist_i(id, hist);
    00707 }
    00708
    00709 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00710
    00711 StatusCode
    00712 THistSvc::readTree(const std::string& id, TTree*& hist) const {
    00713   return readHist_i(id, hist);
    00714 }
    00715
    00716 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00717
    00718 bool
    00719 THistSvc::findStream(const string& id, string& stream, string& rem,
    00720                    TFile*& file) const {
    00721
    00722   string::size_type pos = id.find("/");
    00723
    00724   if (pos == string::npos) {
    00725     stream = "temp";
    00726     rem = id;
    00727   } else if (pos != 0) {
    00728     stream = "temp";
    00729     rem = id;
    00730   } else {
    00731
    00732     string::size_type pos2 = id.find("/",pos+1);
    00733
    00734     if (pos2 == string::npos) {
    00735       m_log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\""
    00736             << endmsg;
    00737       return false;
    00738     }
    00739
    00740     parseString(id,stream,rem);
    00741
    00742   }
    00743
    00744   if (stream == "temp") {
    00745     file = 0;
    00746     return true;
    00747   }
    00748
    00749   map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
    00750   if (itr != m_files.end()) {
    00751     file = itr->second.first;
    00752   } else {
    00753     file = 0;
    00754     m_log << MSG::WARNING << "no stream \"" << stream
    00755           << "\" associated with id: \"" << id << "\""
    00756           << endmsg;
    00757   }
    00758
    00759   return true;
    00760
    00761 }
    00762
    00763 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00764
    00765 void
    00766 THistSvc::parseString(const string& id, string& root, string& rem) const {
    00767   string::size_type pos = id.find("/");
    00768
    00769   if (pos == string::npos) {
    00770     root = "";
    00771     rem = id;
    00772     return;
    00773   }
    00774
    00775   if (pos == 0) {
    00776     parseString(id.substr(1,id.length()),root,rem);
    00777   } else {
    00778     root = id.substr(0,pos);
    00779     rem = id.substr(pos+1,id.length());
    00780   }
    00781
    00782 }
    00783
    00784 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00785
    00786 void
    00787 THistSvc::setupInputFile( Property& /*m_inputfile*/ )
    00788 {
    00789   StatusCode sc = StatusCode::SUCCESS;
    00790
    00791   typedef std::vector<std::string> Strings_t;
    00792   for ( Strings_t::const_iterator
    00793           itr  = m_inputfile.value().begin(),
    00794           iEnd = m_inputfile.value().end();
    00795         itr != iEnd;
    00796         ++itr ) {
    00797     if ( m_alreadyConnectedInFiles.end() ==
    00798          m_alreadyConnectedInFiles.find( *itr ) ) {
    00799       if ( connect(*itr).isFailure() ) {
    00800         sc = StatusCode::FAILURE;
    00801       } else {
    00802         m_alreadyConnectedInFiles.insert( *itr );
    00803       }
    00804     }
    00805   }
    00806
    00807   if ( !sc.isSuccess() ) {
    00808     throw GaudiException( "Problem connecting inputfile !!", name(),
    00809                           StatusCode::FAILURE );
    00810   }
    00811   return;
    00812 }
    00813
    00814 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00815
    00816 void
    00817 THistSvc::setupOutputFile( Property& /*m_outputfile*/ )
    00818 {
    00819   StatusCode sc = StatusCode::SUCCESS;
    00820
    00821   typedef std::vector<std::string> Strings_t;
    00822   for ( Strings_t::const_iterator
    00823           itr  = m_outputfile.value().begin(),
    00824           iEnd = m_outputfile.value().end();
    00825         itr != iEnd;
    00826         ++itr ) {
    00827     if ( m_alreadyConnectedOutFiles.end() ==
    00828          m_alreadyConnectedOutFiles.find( *itr ) ) {
    00829       if ( connect(*itr).isFailure() ) {
    00830         sc = StatusCode::FAILURE;
    00831       } else {
    00832         m_alreadyConnectedOutFiles.insert( *itr );
    00833       }
    00834     }
    00835   }
    00836
    00837   if ( !sc.isSuccess() ) {
    00838     throw GaudiException( "Problem connecting outputfile !!", name(),
    00839                           StatusCode::FAILURE );
    00840   }
    00841   return;
    00842 }
    00843
    00844 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00845
    00846 void
    00847 THistSvc::updateFiles() {
    00848
    00849   // If TTrees grow beyond TTree::fgMaxFileSize, a new file is
    00850   // automatically created by root, and the old one closed. We
    00851   // need to migrate all the UIDs over to show the correct file
    00852   // pointer. This is ugly.
    00853
    00854   uidMap::iterator uitr, uitr2;
    00855   for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
    00856     TObject* to = uitr->second.obj;
    00857     TFile* oldFile = uitr->second.file;
    00858     if (to->IsA()->InheritsFrom("TTree")) {
    00859       TTree* tr = dynamic_cast<TTree*>(to);
    00860       TFile* newFile = tr->GetCurrentFile();
    00861
    00862       if (oldFile != newFile) {
    00863         std::string newFileName = newFile->GetName();
    00864         std::string oldFileName(""), streamName, rem;
    00865         TFile* dummy;
    00866         findStream(uitr->second.id, streamName, rem, dummy);
    00867
    00868         map<string, pair<TFile*,Mode> >::iterator itr;
    00869         for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
    00870           if (itr->second.first == oldFile) {
    00871             itr->second.first = newFile;
    00872
    00873           }
    00874         }
    00875
    00876         uitr2 = uitr;
    00877         for (; uitr2 != m_uids.end(); ++uitr2) {
    00878           if (uitr2->second.file == oldFile) {
    00879             uitr2->second.file = newFile;
    00880           }
    00881         }
    00882
    00883         streamMap::iterator sitr;
    00884         for (sitr = m_fileStreams.begin(); sitr!=m_fileStreams.end(); ++sitr) {
    00885           if (sitr->second == streamName) {
    00886             oldFileName = sitr->first;
    00887             break;
    00888           }
    00889         }
    00890
    00891
    00892 #ifndef NDEBUG
    00893         m_log << MSG::DEBUG << "migrating uid: " << uitr->second.id
    00894               << "   stream: " << streamName
    00895               << "   oldFile: " << oldFileName
    00896               << "   newFile: " << newFileName
    00897               << endmsg;
    00898 #endif
    00899
    00900
    00901         if (oldFileName != "") {
    00902           while ( (sitr=m_fileStreams.find(oldFileName)) != m_fileStreams.end() ) {
    00903
    00904 #ifndef NDEBUG
    00905             m_log << MSG::DEBUG << "changing filename \"" << oldFileName
    00906                   << "\" to \"" << newFileName << "\" for stream \""
    00907                   << sitr->second << "\"" << endmsg;
    00908 #endif
    00909             m_fileStreams.erase(sitr);
    00910             m_fileStreams.insert( make_pair<std::string,std::string>(newFileName,streamName) );
    00911           }
    00912
    00913
    00914         } else {
    00915           m_log << MSG::ERROR
    00916                 << "Problems updating fileStreams with new file name" << endmsg;
    00917         }
    00918
    00919       }
    00920
    00921     }
    00922   }
    00923
    00924 }
    00925
    00926 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00927
    00928 StatusCode
    00929 THistSvc::write() {
    00930
    00931   updateFiles();
    00932
    00933   map<string, pair<TFile*,Mode> >::const_iterator itr;
    00934   for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
    00935     if (itr->second.second == WRITE || itr->second.second == UPDATE
    00936         ||itr->second.second==SHARE) {
    00937       itr->second.first->Write("",TObject::kOverwrite);
    00938     } else if (itr->second.second == APPEND) {
    00939       itr->second.first->Write("");
    00940     }
    00941   }
    00942
    00943
    00944   m_log << MSG::DEBUG << "THistSvc::write()::List of Files connected in ROOT "
    00945         << endmsg;
    00946
    00947   TSeqCollection *filelist=gROOT->GetListOfFiles();
    00948   for (int ii=0; ii<filelist->GetEntries(); ii++) {
    00949     m_log << MSG::DEBUG
    00950           << "THistSvc::write()::List of Files connected in ROOT: \""
    00951           << filelist->At(ii)->GetName()<<"\""<<endmsg;
    00952   }
    00953
    00954   return StatusCode::SUCCESS;
    00955
    00956 }
    00957
    00958 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    00959
    00960 StatusCode
    00961 THistSvc::connect(const std::string& ident) {
    00962
    00963   Tokenizer tok(true);
    00964
    00965   string::size_type loc = ident.find(" ");
    00966   string stream = ident.substr(0,loc);
    00967   char typ(0);
    00968   typedef std::pair<std::string,std::string>      Prop;
    00969   std::vector<Prop> props;
    00970   string val,VAL,TAG,filename,db_typ("ROOT");
    00971
    00972   tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
    00973
    00974   for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++)    {
    00975     const std::string& tag = (*i).tag();
    00976     TAG = tag;
    00977     toupper(TAG);
    00978
    00979     val = (*i).value();
    00980     VAL = val;
    00981     toupper(VAL);
    00982
    00983     if (TAG == "FILE" || TAG == "DATAFILE") {
    00984       filename = val;
    00985       removeDoubleSlash( filename );
    00986     } else if ( TAG == "OPT" ) {
    00987       if ( VAL == "APPEND" || VAL == "UPDATE" ) {
    00988         typ = 'A';
    00989       } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
    00990         typ = 'N';
    00991       } else if ( VAL == "RECREATE" ) {
    00992         typ = 'R';
    00993       } else if (VAL == "SHARE") {
    00994         typ = 'S';
    00995       } else if ( VAL == "OLD" || VAL == "READ" ) {
    00996         typ = 'O';
    00997       } else {
    00998         m_log << MSG::ERROR << "Unknown OPT: \"" << (*i).value() << "\""
    00999             << endmsg;
    01000         typ = 0;
    01001       }
    01002     } else if (TAG == "TYP") {
    01003       db_typ = (*i).value();
    01004     } else {
    01005       props.push_back( Prop((*i).tag(), (*i).value()));
    01006     }
    01007
    01008   }
    01009
    01010   if (stream == "temp") {
    01011     m_log << MSG::ERROR << "in JobOption \"" << ident
    01012           << "\": stream name \"temp\" reserved."
    01013           << endmsg;
    01014     return StatusCode::FAILURE;
    01015   }
    01016
    01017   if (db_typ != "ROOT") {
    01018     m_log << MSG::ERROR << "in JobOption \"" << ident
    01019           << "\": technology type \"" << db_typ << "\" not supported."
    01020           << endmsg;
    01021     return StatusCode::FAILURE;
    01022   }
    01023
    01024
    01025   if (m_files.find(stream) != m_files.end()) {
    01026     m_log << MSG::ERROR << "in JobOption \"" << ident
    01027           << "\":\n stream \"" << stream << "\" already connected to file: \""
    01028           << m_files[stream].first->GetName() << "\""
    01029           << endmsg;
    01030     return StatusCode::FAILURE;
    01031   }
    01032
    01033   Mode newMode;
    01034   if (typ == 'O') {
    01035     newMode = THistSvc::READ;
    01036   } else if (typ == 'N') {
    01037     newMode = THistSvc::WRITE;
    01038   } else if (typ == 'A') {
    01039     newMode = THistSvc::APPEND;
    01040   } else if (typ == 'R') {
    01041     newMode = THistSvc::UPDATE;
    01042   } else if (typ == 'S') {
    01043     newMode = THistSvc::SHARE;
    01044   } else {
    01045     // something else?
    01046     m_log << MSG::ERROR << "No OPT= specified or unknown access mode in: "
    01047           << ident << endmsg;
    01048     return StatusCode::FAILURE;
    01049   }
    01050
    01051   // Is this file already connected to another stream?
    01052   if (m_fileStreams.find(filename) != m_fileStreams.end()) {
    01053     std::pair<streamMap::iterator, streamMap::iterator> fitr =
    01054       m_fileStreams.equal_range(filename);
    01055
    01056     std::string oldstream = (fitr.first)->second;
    01057
    01058     std::pair<TFile*,Mode> f_info = m_files[oldstream];
    01059
    01060     if (newMode != f_info.second) {
    01061       m_log << MSG::ERROR << "in JobOption \"" << ident
    01062             << "\":\n file \"" << filename << "\" already opened by stream: \""
    01063             << oldstream << "\" with different access mode."
    01064             << endmsg;
    01065       return StatusCode::FAILURE;
    01066     } else {
    01067       TFile *f2 = f_info.first;
    01068       m_files[stream] = make_pair<TFile*,Mode>(f2,newMode);
    01069       m_log << MSG::DEBUG << "Connecting stream: \"" << stream
    01070             << "\" to previously opened TFile: \"" << filename << "\""
    01071             << endmsg;
    01072       return StatusCode::SUCCESS;
    01073     }
    01074   }
    01075
    01076
    01077   TFile *f(0) ;
    01078   if (newMode == THistSvc::READ) {
    01079     // old file
    01080
    01081     try {
    01082       f = TFile::Open(filename.c_str(),"READ");
    01083     } catch (const std::exception& Exception) {
    01084       m_log << MSG::ERROR << "exception caught while trying to open root"
    01085             << " file for reading: " << Exception.what() << std::endl
    01086             << "  -> file probably corrupt." << endmsg;
    01087       return StatusCode::FAILURE;
    01088     } catch (...) {
    01089       m_log << MSG::ERROR << "Problems opening input file  \"" << filename
    01090             << "\": probably corrupt" << endmsg;
    01091       return StatusCode::FAILURE;
    01092     }
    01093
    01094     if (!f->IsOpen()) {
    01095       m_log << MSG::ERROR << "Unable to open input file \"" << filename
    01096             << "\": file does not exist" << endmsg;
    01097       return StatusCode::FAILURE;
    01098     }
    01099
    01100
    01101   } else if (newMode == THistSvc::WRITE) {
    01102     // new file
    01103
    01104     f = TFile::Open(filename.c_str(),"NEW");
    01105     if (!f->IsOpen()) {
    01106       m_log << MSG::ERROR << "Unable to create new output file \"" << filename
    01107             << "\" for writing: file already exists" << endmsg;
    01108       return StatusCode::FAILURE;
    01109     }
    01110     f->SetCompressionLevel( m_compressionLevel );
    01111
    01112   } else if (newMode == THistSvc::APPEND) {
    01113     // update file
    01114
    01115     try {
    01116       f =  TFile::Open(filename.c_str(),"UPDATE");
    01117     } catch (const std::exception& Exception) {
    01118       m_log << MSG::ERROR << "exception caught while trying to open root"
    01119             << " file for appending: " << Exception.what() << std::endl
    01120             << "  -> file probably corrupt." << endmsg;
    01121       return StatusCode::FAILURE;
    01122     } catch (...) {
    01123       m_log << MSG::ERROR << "Problems opening output file  \"" << filename
    01124             << "\" for append: probably corrupt" << endmsg;
    01125       return StatusCode::FAILURE;
    01126     }
    01127
    01128     if (!f->IsOpen()) {
    01129       m_log << MSG::ERROR << "Unable to open output file \"" << filename
    01130             << "\" for appending" << endmsg;
    01131       return StatusCode::FAILURE;
    01132     }
    01133     f->SetCompressionLevel( m_compressionLevel );
    01134
    01135   } else if (newMode == THistSvc::SHARE) {
    01136     // SHARE file type
    01137     //For SHARE files, all data will be stored in a temp file and will be merged into the target file
    01138     //in write() when finalize(), this help to solve some confliction. e.g. with storegate
    01139
    01140     static int ishared = 0;
    01141     stringstream out;
    01142     string realfilename=filename;
    01143     out << ishared++;
    01144     filename = string("tmp_THistSvc_")+out.str()+string(".root");
    01145
    01146     m_log << MSG::DEBUG << "Creating temp file \"" << filename
    01147           << "\" and realfilename="<<realfilename << endmsg;
    01148     m_sharedFiles[stream]=realfilename;
    01149
    01150     try {
    01151       f = TFile::Open(filename.c_str(),"NEW");
    01152     } catch (const std::exception& Exception) {
    01153       m_log << MSG::ERROR << "exception caught while trying to open root"
    01154             << " file for appending: " << Exception.what() << std::endl
    01155             << "  -> file probably corrupt." << endmsg;
    01156       return StatusCode::FAILURE;
    01157     } catch (...) {
    01158       m_log << MSG::ERROR << "Problems opening output file  \"" << filename
    01159             << "\" for append: probably corrupt" << endmsg;
    01160       return StatusCode::FAILURE;
    01161     }
    01162
    01163     if (!f->IsOpen()) {
    01164       m_log << MSG::ERROR << "Unable to open output file \"" << filename
    01165           << "\" for appending" << endmsg;
    01166       return StatusCode::FAILURE;
    01167     }
    01168     f->SetCompressionLevel( m_compressionLevel );
    01169
    01170   } else if (newMode == THistSvc::UPDATE) {
    01171     // update file
    01172
    01173     try {
    01174       f =  TFile::Open(filename.c_str(),"RECREATE");
    01175     } catch (const std::exception& Exception) {
    01176       m_log << MSG::ERROR << "exception caught while trying to open root"
    01177             << " file for updating: " << Exception.what() << std::endl
    01178             << "  -> file probably corrupt." << endmsg;
    01179       return StatusCode::FAILURE;
    01180     } catch (...) {
    01181       m_log << MSG::ERROR << "Problems opening output file  \"" << filename
    01182             << "\" for update: probably corrupt" << endmsg;
    01183       return StatusCode::FAILURE;
    01184     }
    01185
    01186     if (!f->IsOpen()) {
    01187       m_log << MSG::ERROR << "Unable to open output file \"" << filename
    01188             << "\" for updating" << endmsg;
    01189       return StatusCode::FAILURE;
    01190     }
    01191     f->SetCompressionLevel( m_compressionLevel );
    01192
    01193   }
    01194
    01195   m_files[stream] = make_pair<TFile*,Mode>(f,newMode);
    01196   m_fileStreams.insert(make_pair<std::string,std::string>(filename,stream));
    01197
    01198   m_log << MSG::DEBUG << "Opening TFile \"" << filename << "\"  stream: \""
    01199         << stream << "\"  mode: \"" << typ << "\""
    01200         << endmsg;
    01201
    01202   return StatusCode::SUCCESS;
    01203 }
    01204
    01205 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01206
    01207 TDirectory*
    01208 THistSvc::changeDir(const THistSvc::THistID& hid) const {
    01209
    01210   string uid = hid.id;
    01211   TFile* file = hid.file;
    01212   string stream, fdir, bdir, dir, id;
    01213
    01214   if (file != 0) {
    01215     file->cd("/");
    01216   } else {
    01217     gROOT->cd();
    01218   }
    01219
    01220   fdir = uid;
    01221   bdir = dirname(fdir);
    01222
    01223   while ( (dir = dirname(fdir)) != "") {
    01224     if (! gDirectory->GetKey(dir.c_str())) {
    01225       gDirectory->mkdir(dir.c_str());
    01226     }
    01227     gDirectory->cd(dir.c_str());
    01228   }
    01229
    01230   return gDirectory;
    01231
    01232 }
    01233
    01234 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01235
    01236 std::string
    01237 THistSvc::dirname(std::string& dir) const {
    01238
    01239
    01240   string::size_type i = dir.find("/");
    01241
    01242   if (i == string::npos) {
    01243     return "";
    01244   }
    01245
    01246   if ( i == 0 ) {
    01247     dir.erase(0,1);
    01248     return dirname(dir);
    01249   }
    01250
    01251   string root = dir.substr(0,i);
    01252   dir.erase(0,i);
    01253
    01254   return root;
    01255
    01256 }
    01257
    01258 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01259
    01260 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore() {
    01261   m_gd = gDirectory;
    01262   m_gf = gFile;
    01263   m_ge = gErrorIgnoreLevel;
    01264 }
    01265
    01266 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore() {
    01267   gDirectory = m_gd;
    01268   gFile = m_gf;
    01269   gErrorIgnoreLevel = m_ge;
    01270 }
    01271
    01272 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01273
    01274 void
    01275 THistSvc::removeDoubleSlash(std::string& id) const {
    01276
    01277   while (id.find("//") != std::string::npos) {
    01278     id.replace(id.find("//"),2,"/");
    01279   }
    01280
    01281 }
    01282
    01283 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01284
    01285 void THistSvc::MergeRootFile(TDirectory *target, TDirectory *source) {
    01286
    01287   m_log <<MSG::DEBUG << "Target path: " << target->GetPath() << endmsg;
    01288   TString path( (char*)strstr(target->GetPath(), ":") );
    01289   path.Remove( 0, 2);
    01290
    01291   source->cd(path);
    01292   TDirectory *current_sourcedir = gDirectory;
    01293
    01294   // loop over all keys in this directory
    01295   TList *lkeys=current_sourcedir->GetListOfKeys();
    01296   int nkeys=lkeys->GetEntries();
    01297   TKey *key;
    01298   for (int jj=0; jj<nkeys; jj++) {
    01299     key=(TKey*) lkeys->At(jj);
    01300     string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName();
    01301     m_log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endmsg;
    01302     //key->Dump();
    01303     //TObject *obj=key->ReadObj();
    01304     TObject *obj=source->Get(pathnameinsource.c_str());
    01305
    01306     if (obj->IsA()->InheritsFrom("TDirectory") ) {
    01307       // it's a subdirectory
    01308
    01309       m_log <<MSG::DEBUG << "Found subdirectory " << obj->GetName()
    01310             << endmsg;
    01311
    01312       // create a new subdir of same name and title in the target file
    01313       target->cd();
    01314       TDirectory *newtargetdir =
    01315         target->mkdir(obj->GetName(), obj->GetTitle() );
    01316
    01317       MergeRootFile(newtargetdir, source);
    01318
    01319     } else if (obj->IsA()->InheritsFrom("TTree")) {
    01320       m_log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endmsg;
    01321       TTree *mytree=dynamic_cast<TTree*>(obj);
    01322       int nentries=(int) mytree->GetEntries();
    01323       mytree->SetBranchStatus("*",1);
    01324
    01325       m_log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries"
    01326           << endmsg;
    01327       //mytree->Print();
    01328       //for (int ij=0; ij<nentries; ij++) {
    01329       //m_log <<MSG::DEBUG << "Dumping TTree Show( " << ij <<" )"
    01330       //<< endmsg;
    01331       //mytree->Show(ij);
    01332       //}
    01333       target->cd();
    01334       mytree->CloneTree();
    01335
    01336       //m_log <<MSG::DEBUG << "Writing TTree to target file: ( "
    01337       //<< mycopiedtree->Write(key->GetName()) <<" ) bytes written"
    01338       //<< endmsg;
    01339
    01340     } else if (obj) {
    01341       target->cd();
    01342       obj->Write(key->GetName() );
    01343     }
    01344
    01345   } // while ( ( TKey *key = (TKey*)nextkey() ) )
    01346
    01347   // save modifications to target file
    01348
    01349 }
    01350
    01351 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01352
    01353 bool
    01354 THistSvc::exists( const std::string& name ) const {
    01355
    01356   TH1* h;
    01357
    01358   return getHist_i(name,h,true).isSuccess();
    01359
    01360
    01361 }
    01362
    01363 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
    01364
    01365 void
    01366 THistSvc::handle( const Incident& /* inc */ ) {
    01367
    01368   if (signaledStop) return ;
    01369
    01370   // convert to bytes.
    01371   Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
    01372
    01373   updateFiles();
    01374
    01375   map<string, pair<TFile*,Mode> >::const_iterator itr;
    01376   for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
    01377     TFile* tf = itr->second.first;
    01378
    01379 #ifndef NDEBUG
    01380     m_log << MSG::DEBUG << "stream: " << itr->first << "  name: "
    01381           << tf->GetName() << "  size: " << tf->GetSize()
    01382           << endmsg;
    01383 #endif
    01384
    01385     // Signal job to terminate if output file is too large
    01386     if (tf->GetSize() > mfs) {
    01387
    01388       signaledStop = true;
    01389
    01390       m_log << MSG::FATAL << "file \"" << tf->GetName()
    01391             << "\" associated with stream \"" << itr->first
    01392             << "\" has exceeded the max file size of "
    01393             << m_maxFileSize.value() << "MB. Terminating Job."
    01394             << endmsg;
    01395
    01396       IEventProcessor* evt(0);
    01397       if (service("ApplicationMgr", evt, true).isSuccess()) {
    01398         evt->stopRun();
    01399         evt->release();
    01400       } else {
    01401         abort();
    01402       }
    01403     }
    01404   }
    01405 }