| # Gaudi Framework, version v21r8 |

Home |  | Generated: 17 Mar 2010

# THistSvc.cpp

Go to the documentation of this file.

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