| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

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