| # Gaudi Framework, version v20r3
Generated: 24 Nov 2008

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