ROOT logo
// @(#)root/io:$Id: TFileMerger.cxx 39826 2011-06-20 11:55:08Z pcanal $
// Author: Andreas Peters + Fons Rademakers + Rene Brun  26/5/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TFileMerger                                                          //
//                                                                      //
// This class provides file copy and merging services.                  //
//                                                                      //
// It can be used to copy files (not only ROOT files), using TFile or   //
// any of its remote file access plugins. It is therefore usefull in    //
// a Grid environment where the files might be accessable via Castor,   //
// rfio, dcap, etc.                                                     //
// The merging interface allows files containing histograms and trees   //
// to be merged, like the standalone hadd program.                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TFileMerger.h"
#include "TUrl.h"
#include "TFile.h"
#include "TUUID.h"
#include "TSystem.h"
#include "TKey.h"
#include "THashList.h"
#include "TObjString.h"
#include "TClass.h"
#include "TMethodCall.h"
#include "Riostream.h"
#include "TFileMergeInfo.h"
#include "TClassRef.h"
#include "TROOT.h"

ClassImp(TFileMerger)

TClassRef R__TH1_Class("TH1");
TClassRef R__TTree_Class("TTree");

//______________________________________________________________________________
TFileMerger::TFileMerger(Bool_t isLocal, Bool_t histoOneGo)
            : fOutputFile(0), fFastMethod(kTRUE), fNoTrees(kFALSE), fExplicitCompLevel(kFALSE), fCompressionChange(kFALSE),
              fPrintLevel(0),
              fLocal(isLocal), fHistoOneGo(histoOneGo)
{
   // Create file merger object.

   fFileList = new TList;
   fFileList->SetOwner(kTRUE);

   fMergeList = new TList;
   fMergeList->SetOwner(kTRUE);
   
   gROOT->GetListOfCleanups()->Add(this);
}

//______________________________________________________________________________
TFileMerger::~TFileMerger()
{
   // Cleanup.

   gROOT->GetListOfCleanups()->Remove(this);
   SafeDelete(fFileList);
   SafeDelete(fMergeList);
   SafeDelete(fOutputFile);
}

//______________________________________________________________________________
void TFileMerger::Reset()
{
   // Reset merger file list.

   fFileList->Clear();
   fMergeList->Clear();
}

//______________________________________________________________________________
Bool_t TFileMerger::AddFile(const char *url, Bool_t cpProgress)
{
   // Add file to file merger.

   if (fPrintLevel > 0) {
      Printf("Source file %d: %s",fFileList->GetEntries()+1,url);
   }

   TFile *newfile = 0;
   TString localcopy;

   if (fLocal) {
      TUUID uuid;
      localcopy.Form("file:%s/ROOTMERGE-%s.root", gSystem->TempDirectory(), uuid.AsString());
      if (!TFile::Cp(url, localcopy, cpProgress)) {
         Error("AddFile", "cannot get a local copy of file %s", url);
         return kFALSE;
      }
      newfile = TFile::Open(localcopy, "READ");
   } else {
      newfile = TFile::Open(url, "READ");
   }

   if (!newfile) {
      if (fLocal)
         Error("AddFile", "cannot open local copy %s of URL %s",
                          localcopy.Data(), url);
      else
         Error("AddFile", "cannot open file %s", url);
      return kFALSE;
   } else {
      if (fOutputFile && fOutputFile->GetCompressionLevel() != newfile->GetCompressionLevel()) fCompressionChange = kTRUE;

      fFileList->Add(newfile);

      if (!fMergeList)
         fMergeList = new TList;
      TObjString *urlObj = new TObjString(url);
      fMergeList->Add(urlObj);

      return  kTRUE;
   }
}

//______________________________________________________________________________
Bool_t TFileMerger::OutputFile(const char *outputfile, Bool_t force, Int_t compressionLevel)
{
   // Open merger output file.
   
   fExplicitCompLevel = kTRUE;

   SafeDelete(fOutputFile);
   
   fOutputFilename = outputfile;
   
   if (!(fOutputFile = TFile::Open(outputfile, (force?"RECREATE":"CREATE"), "", compressionLevel)) || fOutputFile->IsZombie()) {
      Error("OutputFile", "cannot open the MERGER output file %s", fOutputFilename.Data());
      return kFALSE;
   }
   return kTRUE;
}

//______________________________________________________________________________
Bool_t TFileMerger::OutputFile(const char *outputfile, Bool_t force /* = kTRUE */ )
{
   // Open merger output file.
   
   Bool_t res = OutputFile(outputfile,force,1); // 1 is the same as the default from the TFile constructor.
   fExplicitCompLevel = kFALSE;
   return res;
}

//______________________________________________________________________________
void TFileMerger::PrintFiles(Option_t *options)
{
   // Print list of files being merged.

   fFileList->Print(options);
}

//______________________________________________________________________________
Bool_t TFileMerger::Merge(Bool_t)
{
   // Merge the files. If no output file was specified it will write into
   // the file "FileMerger.root" in the working directory. Returns true
   // on success, false in case of error.

   if (!fOutputFile) {
      TString outf(fOutputFilename);
      if (outf.IsNull()) {
         outf.Form("file:%s/FileMerger.root", gSystem->TempDirectory());
         Info("Merge", "will merge the results to the file %s\n"
                       "since you didn't specify a merge filename",
                       TUrl(outf).GetFile());
      }
      if (!OutputFile(outf.Data())) {
         return kFALSE;
      }
   }

   fOutputFile->SetBit(kMustCleanup);
   Bool_t result = MergeRecursive(fOutputFile, fFileList);
   if (!result) {
      Error("Merge", "error during merge of your ROOT files");
   } else {
      // But Close is required so the file is complete.
      fOutputFile->Close();
   }

   // Cleanup
   fOutputFile->ResetBit(kMustCleanup);
   SafeDelete(fOutputFile);

   // Remove local copies if there are any
   TIter next(fFileList);
   TFile *file;
   while ((file = (TFile*) next())) {
      // close the files
      file->Close();
      // remove the temporary files
      if(fLocal) {
         TString p(file->GetPath());
         p = p(0, p.Index(':',0));
         gSystem->Unlink(p);
      }
   }
   return result;
}

//______________________________________________________________________________
Bool_t TFileMerger::MergeRecursive(TDirectory *target, TList *sourcelist)
{
   // Merge all objects in a directory
   // NB. This function is a copy of the hadd function MergeROOTFile

   Bool_t status = kTRUE;
   if (fPrintLevel > 0) {
      Printf("Target path: %s",target->GetPath());
   }

   // Get the dir name
   TString path(target->GetPath());
   path.Remove(0, path.Last(':') + 2);

   // Gain time, do not add the objects in the list in memory.
   Bool_t addDirStat = kTRUE;
   if (R__TH1_Class) {
      gROOT->ProcessLineFast("TH1::AddDirectoryStatus()");
      gROOT->ProcessLine("TH1::AddDirectory(kFALSE);");
   }
   
   TDirectory *first_source = (TDirectory*)sourcelist->First();

   Int_t nguess = sourcelist->GetSize()+1000;
   THashList allNames(nguess);
   ((THashList*)target->GetList())->Rehash(nguess);
   ((THashList*)target->GetListOfKeys())->Rehash(nguess);
   
   TFileMergeInfo info(target);

   if ((fFastMethod && !fCompressionChange)) {
      info.fOptions.Append(" fast");
   }

   while (first_source) {
      TDirectory *current_sourcedir = first_source->GetDirectory(path);
      if (!current_sourcedir) {
         first_source = (TDirectory*)sourcelist->After(first_source);
         continue;
      }

      // loop over all keys in this directory
      TIter nextkey( current_sourcedir->GetListOfKeys() );
      TKey *key, *oldkey=0;

      while ( (key = (TKey*)nextkey())) {
         if (current_sourcedir == target) break;
         //keep only the highest cycle number for each key
         if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
         if (strcmp(key->GetClassName(),"TProcessID") == 0) { key->ReadObj(); continue;}
         if (allNames.FindObject(key->GetName())) continue;

         TClass *cl = TClass::GetClass(key->GetClassName());
         if (!cl || !cl->InheritsFrom(TObject::Class())) {
            Info("MergeRecursive", "cannot merge object type, name: %s title: %s",
                                   key->GetName(), key->GetTitle());
            continue;
         }
         allNames.Add(new TObjString(key->GetName()));

         if (fNoTrees && cl->InheritsFrom(R__TTree_Class)) {
            continue;
         }
            
         // read object from first source file
         TObject *obj = key->ReadObj();
         if (!obj) {
            Info("MergeRecursive", "could not read object for key {%s, %s}",
                                   key->GetName(), key->GetTitle());
            continue;
         }

         if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
            // it's a subdirectory

            //DIFFERENCE: hadd used to issue an information message:
            //    cout << "Found subdirectory " << obj->GetName() << endl;
            // create a new subdir of same name and title in the target file
            target->cd();
            TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );

            // newdir is now the starting point of another round of merging
            // newdir still knows its depth within the target file via
            // GetPath(), so we can still figure out where we are in the recursion
            status = MergeRecursive( newdir, sourcelist);
            if (!status) return status;

         } else if (obj->IsA()->GetMerge()) {
            
            TList inputs;
            Bool_t oneGo = fHistoOneGo && obj->IsA()->InheritsFrom(R__TH1_Class);

            // Loop over all source files and merge same-name object
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            while (nextsource) {
               // make sure we are at the correct directory level by cd'ing to path
               TDirectory *ndir = nextsource->GetDirectory(path);
               if (ndir) {
                  ndir->cd();
                  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(key->GetName());
                  if (key2) {
                     TObject *hobj = key2->ReadObj();
                     if (!hobj) {
                        Info("MergeRecursive", "could not read object for key {%s, %s}; skipping file %s",
                             key->GetName(), key->GetTitle(), nextsource->GetName());
                        nextsource = (TFile*)sourcelist->After(nextsource);
                        continue;
                     }
                     // Set ownership for collections
                     if (hobj->InheritsFrom(TCollection::Class())) {
                        ((TCollection*)hobj)->SetOwner();
                     }
                     hobj->ResetBit(kMustCleanup);
                     inputs.Add(hobj);
                     if (!oneGo) {
                        ROOT::MergeFunc_t func = obj->IsA()->GetMerge();
                        Long64_t result = func(obj, &inputs, &info);
                        info.fIsFirst = kFALSE;
                        if (result < 0) {
                           Error("MergeRecursive", "calling Merge() on '%s' with the corresponding object in '%s'",
                                 obj->GetName(), nextsource->GetName());
                        }
                        inputs.Delete();
                     }
                  }
               }
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
            // Merge the list, if still to be done
            if (oneGo) {
               ROOT::MergeFunc_t func = obj->IsA()->GetMerge();
               func(obj, &inputs, &info);
               info.fIsFirst = kFALSE;
               inputs.Delete();
            }
         } else if (obj->InheritsFrom(TObject::Class()) &&
                    obj->IsA()->GetMethodWithPrototype("Merge", "TCollection*,TFileMergeInfo*") ) {
            // Object implements Merge(TCollection*,TFileMergeInfo*) and has a reflex dictionary ... 
            
            TList listH;
            TString listHargs;
            listHargs.Form("(TCollection*)0x%lx,(TFileMergeInfo*)0x%lx", (ULong_t)&listH,(ULong_t)&info);
            
            // Loop over all source files and merge same-name object
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            while (nextsource) {
               // make sure we are at the correct directory level by cd'ing to path
               TDirectory *ndir = nextsource->GetDirectory(path);
               if (ndir) {
                  ndir->cd();
                  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(key->GetName());
                  if (key2) {
                     TObject *hobj = key2->ReadObj();
                     if (!hobj) {
                        Info("MergeRecursive", "could not read object for key {%s, %s}; skipping file %s",
                             key->GetName(), key->GetTitle(), nextsource->GetName());
                        nextsource = (TFile*)sourcelist->After(nextsource);
                        continue;
                     }
                     // Set ownership for collections
                     if (hobj->InheritsFrom(TCollection::Class())) {
                        ((TCollection*)hobj)->SetOwner();
                     }
                     hobj->ResetBit(kMustCleanup);
                     listH.Add(hobj);
                     Int_t error = 0;
                     obj->Execute("Merge", listHargs.Data(), &error);
                     info.fIsFirst = kFALSE;
                     if (error) {
                        Error("MergeRecursive", "calling Merge() on '%s' with the corresponding object in '%s'",
                              obj->GetName(), nextsource->GetName());
                     }
                     listH.Delete();
                  }
               }
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
         } else if (obj->InheritsFrom(TObject::Class()) &&
                    obj->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
            // Object implements Merge(TCollection*) and has a reflex dictionary ...
            
            TList listH;
            TString listHargs;
            listHargs.Form("((TCollection*)0x%lx)", (ULong_t)&listH);
            
            // Loop over all source files and merge same-name object
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            while (nextsource) {
               // make sure we are at the correct directory level by cd'ing to path
               TDirectory *ndir = nextsource->GetDirectory(path);
               if (ndir) {
                  ndir->cd();
                  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(key->GetName());
                  if (key2) {
                     TObject *hobj = key2->ReadObj();
                     if (!hobj) {
                        Info("MergeRecursive", "could not read object for key {%s, %s}; skipping file %s",
                             key->GetName(), key->GetTitle(), nextsource->GetName());
                        nextsource = (TFile*)sourcelist->After(nextsource);
                        continue;
                     }
                     // Set ownership for collections
                     if (hobj->InheritsFrom(TCollection::Class())) {
                        ((TCollection*)hobj)->SetOwner();
                     }
                     hobj->ResetBit(kMustCleanup);
                     listH.Add(hobj);
                     Int_t error = 0;
                     obj->Execute("Merge", listHargs.Data(), &error);
                     if (error) {
                        Error("MergeRecursive", "calling Merge() on '%s' with the corresponding object in '%s'",
                              obj->GetName(), nextsource->GetName());
                     }
                     listH.Delete();
                  }
               }
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
         } else {
            // Object is of no type that we can merge
            Warning("MergeRecursive", "cannot merge object type (n:'%s', t:'%s') - "
                                      "Merge(TCollection *) not implemented",
                                      obj->GetName(), obj->GetTitle());

            // Loop over all source files and write similar objects directly to the output file
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            while (nextsource) {
               // make sure we are at the correct directory level by cd'ing to path
               TDirectory *ndir = nextsource->GetDirectory(path);
               if (ndir) {
                  ndir->cd();
                  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(key->GetName());
                  if (key2) {
                     TObject *nobj = key2->ReadObj();
                     if (!nobj) {
                        Info("MergeRecursive", "could not read object for key {%s, %s}; skipping file %s",
                                               key->GetName(), key->GetTitle(), nextsource->GetName());
                        nextsource = (TFile*)sourcelist->After(nextsource);
                        continue;
                     }
                     nobj->ResetBit(kMustCleanup);
                     if (target->WriteTObject(nobj, key2->GetName(), "SingleKey") <= 0) {
                        Warning("MergeRecursive", "problems copying object (n:'%s', t:'%s') to output file ",
                                                  obj->GetName(), obj->GetTitle());
                        status = kFALSE;
                     }
                     delete nobj;
                  }
               }
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
         }

         // now write the merged histogram (which is "in" obj) to the target file
         // note that this will just store obj in the current directory level,
         // which is not persistent until the complete directory itself is stored
         // by "target->Write()" below
         target->cd();

         //!!if the object is a tree, it is stored in globChain...
         if(obj->IsA()->InheritsFrom( TDirectory::Class() )) {
            //printf("cas d'une directory\n");
         } else if (obj->IsA()->InheritsFrom( TCollection::Class() )) {
            if ( obj->Write( key->GetName(), TObject::kSingleKey ) <= 0 ) {
               status = kFALSE;
            }
            ((TCollection*)obj)->SetOwner();
         } else {
            if ( obj->Write( key->GetName() ) <= 0) {
               status = kFALSE;
            }
         }
         if (obj->IsA()->InheritsFrom(TCollection::Class())) ((TCollection*)obj)->Delete();
         oldkey = key;
         delete obj;
         info.Reset();
      } // while ( ( TKey *key = (TKey*)nextkey() ) )
      first_source = (TDirectory*)sourcelist->After(first_source);
   }
   // save modifications to target file
   target->SaveSelf(kTRUE);
   if (R__TH1_Class) {
      gROOT->ProcessLine(TString::Format("TH1::AddDirectory(%d);",addDirStat));
   }
   return status;
}

//______________________________________________________________________________
void TFileMerger::RecursiveRemove(TObject *obj)
{
   // Intercept the case where the output TFile is deleted!
   
   if (obj == fOutputFile) {
      Fatal("RecursiveRemove","Output file of the TFile Merger (targetting %s) has been deleted (likely due to a TTree larger than 100Gb)", fOutputFilename.Data());
   }
   
}
 TFileMerger.cxx:1
 TFileMerger.cxx:2
 TFileMerger.cxx:3
 TFileMerger.cxx:4
 TFileMerger.cxx:5
 TFileMerger.cxx:6
 TFileMerger.cxx:7
 TFileMerger.cxx:8
 TFileMerger.cxx:9
 TFileMerger.cxx:10
 TFileMerger.cxx:11
 TFileMerger.cxx:12
 TFileMerger.cxx:13
 TFileMerger.cxx:14
 TFileMerger.cxx:15
 TFileMerger.cxx:16
 TFileMerger.cxx:17
 TFileMerger.cxx:18
 TFileMerger.cxx:19
 TFileMerger.cxx:20
 TFileMerger.cxx:21
 TFileMerger.cxx:22
 TFileMerger.cxx:23
 TFileMerger.cxx:24
 TFileMerger.cxx:25
 TFileMerger.cxx:26
 TFileMerger.cxx:27
 TFileMerger.cxx:28
 TFileMerger.cxx:29
 TFileMerger.cxx:30
 TFileMerger.cxx:31
 TFileMerger.cxx:32
 TFileMerger.cxx:33
 TFileMerger.cxx:34
 TFileMerger.cxx:35
 TFileMerger.cxx:36
 TFileMerger.cxx:37
 TFileMerger.cxx:38
 TFileMerger.cxx:39
 TFileMerger.cxx:40
 TFileMerger.cxx:41
 TFileMerger.cxx:42
 TFileMerger.cxx:43
 TFileMerger.cxx:44
 TFileMerger.cxx:45
 TFileMerger.cxx:46
 TFileMerger.cxx:47
 TFileMerger.cxx:48
 TFileMerger.cxx:49
 TFileMerger.cxx:50
 TFileMerger.cxx:51
 TFileMerger.cxx:52
 TFileMerger.cxx:53
 TFileMerger.cxx:54
 TFileMerger.cxx:55
 TFileMerger.cxx:56
 TFileMerger.cxx:57
 TFileMerger.cxx:58
 TFileMerger.cxx:59
 TFileMerger.cxx:60
 TFileMerger.cxx:61
 TFileMerger.cxx:62
 TFileMerger.cxx:63
 TFileMerger.cxx:64
 TFileMerger.cxx:65
 TFileMerger.cxx:66
 TFileMerger.cxx:67
 TFileMerger.cxx:68
 TFileMerger.cxx:69
 TFileMerger.cxx:70
 TFileMerger.cxx:71
 TFileMerger.cxx:72
 TFileMerger.cxx:73
 TFileMerger.cxx:74
 TFileMerger.cxx:75
 TFileMerger.cxx:76
 TFileMerger.cxx:77
 TFileMerger.cxx:78
 TFileMerger.cxx:79
 TFileMerger.cxx:80
 TFileMerger.cxx:81
 TFileMerger.cxx:82
 TFileMerger.cxx:83
 TFileMerger.cxx:84
 TFileMerger.cxx:85
 TFileMerger.cxx:86
 TFileMerger.cxx:87
 TFileMerger.cxx:88
 TFileMerger.cxx:89
 TFileMerger.cxx:90
 TFileMerger.cxx:91
 TFileMerger.cxx:92
 TFileMerger.cxx:93
 TFileMerger.cxx:94
 TFileMerger.cxx:95
 TFileMerger.cxx:96
 TFileMerger.cxx:97
 TFileMerger.cxx:98
 TFileMerger.cxx:99
 TFileMerger.cxx:100
 TFileMerger.cxx:101
 TFileMerger.cxx:102
 TFileMerger.cxx:103
 TFileMerger.cxx:104
 TFileMerger.cxx:105
 TFileMerger.cxx:106
 TFileMerger.cxx:107
 TFileMerger.cxx:108
 TFileMerger.cxx:109
 TFileMerger.cxx:110
 TFileMerger.cxx:111
 TFileMerger.cxx:112
 TFileMerger.cxx:113
 TFileMerger.cxx:114
 TFileMerger.cxx:115
 TFileMerger.cxx:116
 TFileMerger.cxx:117
 TFileMerger.cxx:118
 TFileMerger.cxx:119
 TFileMerger.cxx:120
 TFileMerger.cxx:121
 TFileMerger.cxx:122
 TFileMerger.cxx:123
 TFileMerger.cxx:124
 TFileMerger.cxx:125
 TFileMerger.cxx:126
 TFileMerger.cxx:127
 TFileMerger.cxx:128
 TFileMerger.cxx:129
 TFileMerger.cxx:130
 TFileMerger.cxx:131
 TFileMerger.cxx:132
 TFileMerger.cxx:133
 TFileMerger.cxx:134
 TFileMerger.cxx:135
 TFileMerger.cxx:136
 TFileMerger.cxx:137
 TFileMerger.cxx:138
 TFileMerger.cxx:139
 TFileMerger.cxx:140
 TFileMerger.cxx:141
 TFileMerger.cxx:142
 TFileMerger.cxx:143
 TFileMerger.cxx:144
 TFileMerger.cxx:145
 TFileMerger.cxx:146
 TFileMerger.cxx:147
 TFileMerger.cxx:148
 TFileMerger.cxx:149
 TFileMerger.cxx:150
 TFileMerger.cxx:151
 TFileMerger.cxx:152
 TFileMerger.cxx:153
 TFileMerger.cxx:154
 TFileMerger.cxx:155
 TFileMerger.cxx:156
 TFileMerger.cxx:157
 TFileMerger.cxx:158
 TFileMerger.cxx:159
 TFileMerger.cxx:160
 TFileMerger.cxx:161
 TFileMerger.cxx:162
 TFileMerger.cxx:163
 TFileMerger.cxx:164
 TFileMerger.cxx:165
 TFileMerger.cxx:166
 TFileMerger.cxx:167
 TFileMerger.cxx:168
 TFileMerger.cxx:169
 TFileMerger.cxx:170
 TFileMerger.cxx:171
 TFileMerger.cxx:172
 TFileMerger.cxx:173
 TFileMerger.cxx:174
 TFileMerger.cxx:175
 TFileMerger.cxx:176
 TFileMerger.cxx:177
 TFileMerger.cxx:178
 TFileMerger.cxx:179
 TFileMerger.cxx:180
 TFileMerger.cxx:181
 TFileMerger.cxx:182
 TFileMerger.cxx:183
 TFileMerger.cxx:184
 TFileMerger.cxx:185
 TFileMerger.cxx:186
 TFileMerger.cxx:187
 TFileMerger.cxx:188
 TFileMerger.cxx:189
 TFileMerger.cxx:190
 TFileMerger.cxx:191
 TFileMerger.cxx:192
 TFileMerger.cxx:193
 TFileMerger.cxx:194
 TFileMerger.cxx:195
 TFileMerger.cxx:196
 TFileMerger.cxx:197
 TFileMerger.cxx:198
 TFileMerger.cxx:199
 TFileMerger.cxx:200
 TFileMerger.cxx:201
 TFileMerger.cxx:202
 TFileMerger.cxx:203
 TFileMerger.cxx:204
 TFileMerger.cxx:205
 TFileMerger.cxx:206
 TFileMerger.cxx:207
 TFileMerger.cxx:208
 TFileMerger.cxx:209
 TFileMerger.cxx:210
 TFileMerger.cxx:211
 TFileMerger.cxx:212
 TFileMerger.cxx:213
 TFileMerger.cxx:214
 TFileMerger.cxx:215
 TFileMerger.cxx:216
 TFileMerger.cxx:217
 TFileMerger.cxx:218
 TFileMerger.cxx:219
 TFileMerger.cxx:220
 TFileMerger.cxx:221
 TFileMerger.cxx:222
 TFileMerger.cxx:223
 TFileMerger.cxx:224
 TFileMerger.cxx:225
 TFileMerger.cxx:226
 TFileMerger.cxx:227
 TFileMerger.cxx:228
 TFileMerger.cxx:229
 TFileMerger.cxx:230
 TFileMerger.cxx:231
 TFileMerger.cxx:232
 TFileMerger.cxx:233
 TFileMerger.cxx:234
 TFileMerger.cxx:235
 TFileMerger.cxx:236
 TFileMerger.cxx:237
 TFileMerger.cxx:238
 TFileMerger.cxx:239
 TFileMerger.cxx:240
 TFileMerger.cxx:241
 TFileMerger.cxx:242
 TFileMerger.cxx:243
 TFileMerger.cxx:244
 TFileMerger.cxx:245
 TFileMerger.cxx:246
 TFileMerger.cxx:247
 TFileMerger.cxx:248
 TFileMerger.cxx:249
 TFileMerger.cxx:250
 TFileMerger.cxx:251
 TFileMerger.cxx:252
 TFileMerger.cxx:253
 TFileMerger.cxx:254
 TFileMerger.cxx:255
 TFileMerger.cxx:256
 TFileMerger.cxx:257
 TFileMerger.cxx:258
 TFileMerger.cxx:259
 TFileMerger.cxx:260
 TFileMerger.cxx:261
 TFileMerger.cxx:262
 TFileMerger.cxx:263
 TFileMerger.cxx:264
 TFileMerger.cxx:265
 TFileMerger.cxx:266
 TFileMerger.cxx:267
 TFileMerger.cxx:268
 TFileMerger.cxx:269
 TFileMerger.cxx:270
 TFileMerger.cxx:271
 TFileMerger.cxx:272
 TFileMerger.cxx:273
 TFileMerger.cxx:274
 TFileMerger.cxx:275
 TFileMerger.cxx:276
 TFileMerger.cxx:277
 TFileMerger.cxx:278
 TFileMerger.cxx:279
 TFileMerger.cxx:280
 TFileMerger.cxx:281
 TFileMerger.cxx:282
 TFileMerger.cxx:283
 TFileMerger.cxx:284
 TFileMerger.cxx:285
 TFileMerger.cxx:286
 TFileMerger.cxx:287
 TFileMerger.cxx:288
 TFileMerger.cxx:289
 TFileMerger.cxx:290
 TFileMerger.cxx:291
 TFileMerger.cxx:292
 TFileMerger.cxx:293
 TFileMerger.cxx:294
 TFileMerger.cxx:295
 TFileMerger.cxx:296
 TFileMerger.cxx:297
 TFileMerger.cxx:298
 TFileMerger.cxx:299
 TFileMerger.cxx:300
 TFileMerger.cxx:301
 TFileMerger.cxx:302
 TFileMerger.cxx:303
 TFileMerger.cxx:304
 TFileMerger.cxx:305
 TFileMerger.cxx:306
 TFileMerger.cxx:307
 TFileMerger.cxx:308
 TFileMerger.cxx:309
 TFileMerger.cxx:310
 TFileMerger.cxx:311
 TFileMerger.cxx:312
 TFileMerger.cxx:313
 TFileMerger.cxx:314
 TFileMerger.cxx:315
 TFileMerger.cxx:316
 TFileMerger.cxx:317
 TFileMerger.cxx:318
 TFileMerger.cxx:319
 TFileMerger.cxx:320
 TFileMerger.cxx:321
 TFileMerger.cxx:322
 TFileMerger.cxx:323
 TFileMerger.cxx:324
 TFileMerger.cxx:325
 TFileMerger.cxx:326
 TFileMerger.cxx:327
 TFileMerger.cxx:328
 TFileMerger.cxx:329
 TFileMerger.cxx:330
 TFileMerger.cxx:331
 TFileMerger.cxx:332
 TFileMerger.cxx:333
 TFileMerger.cxx:334
 TFileMerger.cxx:335
 TFileMerger.cxx:336
 TFileMerger.cxx:337
 TFileMerger.cxx:338
 TFileMerger.cxx:339
 TFileMerger.cxx:340
 TFileMerger.cxx:341
 TFileMerger.cxx:342
 TFileMerger.cxx:343
 TFileMerger.cxx:344
 TFileMerger.cxx:345
 TFileMerger.cxx:346
 TFileMerger.cxx:347
 TFileMerger.cxx:348
 TFileMerger.cxx:349
 TFileMerger.cxx:350
 TFileMerger.cxx:351
 TFileMerger.cxx:352
 TFileMerger.cxx:353
 TFileMerger.cxx:354
 TFileMerger.cxx:355
 TFileMerger.cxx:356
 TFileMerger.cxx:357
 TFileMerger.cxx:358
 TFileMerger.cxx:359
 TFileMerger.cxx:360
 TFileMerger.cxx:361
 TFileMerger.cxx:362
 TFileMerger.cxx:363
 TFileMerger.cxx:364
 TFileMerger.cxx:365
 TFileMerger.cxx:366
 TFileMerger.cxx:367
 TFileMerger.cxx:368
 TFileMerger.cxx:369
 TFileMerger.cxx:370
 TFileMerger.cxx:371
 TFileMerger.cxx:372
 TFileMerger.cxx:373
 TFileMerger.cxx:374
 TFileMerger.cxx:375
 TFileMerger.cxx:376
 TFileMerger.cxx:377
 TFileMerger.cxx:378
 TFileMerger.cxx:379
 TFileMerger.cxx:380
 TFileMerger.cxx:381
 TFileMerger.cxx:382
 TFileMerger.cxx:383
 TFileMerger.cxx:384
 TFileMerger.cxx:385
 TFileMerger.cxx:386
 TFileMerger.cxx:387
 TFileMerger.cxx:388
 TFileMerger.cxx:389
 TFileMerger.cxx:390
 TFileMerger.cxx:391
 TFileMerger.cxx:392
 TFileMerger.cxx:393
 TFileMerger.cxx:394
 TFileMerger.cxx:395
 TFileMerger.cxx:396
 TFileMerger.cxx:397
 TFileMerger.cxx:398
 TFileMerger.cxx:399
 TFileMerger.cxx:400
 TFileMerger.cxx:401
 TFileMerger.cxx:402
 TFileMerger.cxx:403
 TFileMerger.cxx:404
 TFileMerger.cxx:405
 TFileMerger.cxx:406
 TFileMerger.cxx:407
 TFileMerger.cxx:408
 TFileMerger.cxx:409
 TFileMerger.cxx:410
 TFileMerger.cxx:411
 TFileMerger.cxx:412
 TFileMerger.cxx:413
 TFileMerger.cxx:414
 TFileMerger.cxx:415
 TFileMerger.cxx:416
 TFileMerger.cxx:417
 TFileMerger.cxx:418
 TFileMerger.cxx:419
 TFileMerger.cxx:420
 TFileMerger.cxx:421
 TFileMerger.cxx:422
 TFileMerger.cxx:423
 TFileMerger.cxx:424
 TFileMerger.cxx:425
 TFileMerger.cxx:426
 TFileMerger.cxx:427
 TFileMerger.cxx:428
 TFileMerger.cxx:429
 TFileMerger.cxx:430
 TFileMerger.cxx:431
 TFileMerger.cxx:432
 TFileMerger.cxx:433
 TFileMerger.cxx:434
 TFileMerger.cxx:435
 TFileMerger.cxx:436
 TFileMerger.cxx:437
 TFileMerger.cxx:438
 TFileMerger.cxx:439
 TFileMerger.cxx:440
 TFileMerger.cxx:441
 TFileMerger.cxx:442
 TFileMerger.cxx:443
 TFileMerger.cxx:444
 TFileMerger.cxx:445
 TFileMerger.cxx:446
 TFileMerger.cxx:447
 TFileMerger.cxx:448
 TFileMerger.cxx:449
 TFileMerger.cxx:450
 TFileMerger.cxx:451
 TFileMerger.cxx:452
 TFileMerger.cxx:453
 TFileMerger.cxx:454
 TFileMerger.cxx:455
 TFileMerger.cxx:456
 TFileMerger.cxx:457
 TFileMerger.cxx:458
 TFileMerger.cxx:459
 TFileMerger.cxx:460
 TFileMerger.cxx:461
 TFileMerger.cxx:462
 TFileMerger.cxx:463
 TFileMerger.cxx:464
 TFileMerger.cxx:465
 TFileMerger.cxx:466
 TFileMerger.cxx:467
 TFileMerger.cxx:468
 TFileMerger.cxx:469
 TFileMerger.cxx:470
 TFileMerger.cxx:471
 TFileMerger.cxx:472
 TFileMerger.cxx:473
 TFileMerger.cxx:474
 TFileMerger.cxx:475
 TFileMerger.cxx:476
 TFileMerger.cxx:477
 TFileMerger.cxx:478
 TFileMerger.cxx:479
 TFileMerger.cxx:480
 TFileMerger.cxx:481
 TFileMerger.cxx:482
 TFileMerger.cxx:483
 TFileMerger.cxx:484
 TFileMerger.cxx:485
 TFileMerger.cxx:486
 TFileMerger.cxx:487
 TFileMerger.cxx:488
 TFileMerger.cxx:489
 TFileMerger.cxx:490
 TFileMerger.cxx:491
 TFileMerger.cxx:492
 TFileMerger.cxx:493
 TFileMerger.cxx:494
 TFileMerger.cxx:495
 TFileMerger.cxx:496
 TFileMerger.cxx:497
 TFileMerger.cxx:498
 TFileMerger.cxx:499
 TFileMerger.cxx:500
 TFileMerger.cxx:501
 TFileMerger.cxx:502
 TFileMerger.cxx:503
 TFileMerger.cxx:504
 TFileMerger.cxx:505
 TFileMerger.cxx:506
 TFileMerger.cxx:507
 TFileMerger.cxx:508
 TFileMerger.cxx:509
 TFileMerger.cxx:510
 TFileMerger.cxx:511