| # Gaudi Framework, version v21r6 |

Home |  | Generated: 11 Nov 2009

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