ROOT logo
// @(#)root/proofplayer:$Id: TFileMerger.cxx 31840 2009-12-11 10:01:17Z ganis $
// 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 "TH1.h"
#include "TChain.h"
#include "TKey.h"
#include "THashList.h"
#include "TObjString.h"
#include "TClass.h"
#include "TMethodCall.h"
#include "Riostream.h"


ClassImp(TFileMerger)

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

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

   fMergeList = new TList;
   fMergeList->SetOwner(kTRUE);
}

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

   SafeDelete(fFileList);
   SafeDelete(fMergeList);
   SafeDelete(fOutputFile);
}

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

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

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

   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)) {
         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 {
      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)
{
   // Open merger output file.

   SafeDelete(fOutputFile);

   fOutputFilename = outputfile;

   if (!(fOutputFile = TFile::Open(outputfile, "RECREATE"))) {
      Error("OutputFile", "cannot open the MERGER output file %s", fOutputFilename.Data());
      return kFALSE;
   }
   return kTRUE;
}

//______________________________________________________________________________
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.
   // "cp_progressbar" is pass to TFile::Cp to control whether there is 
   // visual feedback on the progress of the copy.

   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;
      }
   }

   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 
   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

   // 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 = TH1::AddDirectoryStatus();
   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);

   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
      TChain *globChain = 0;
      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")) {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()));

         // read object from first source file
         current_sourcedir->cd();
         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("TH1")) {
            // descendant of TH1 -> merge it

            TH1 *h1 = (TH1*)obj;
            TList listH;

            // loop over all source files and add the content of the
            // correspondant histogram to the one pointed to by "h1"
            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();
                     hobj->ResetBit(kMustCleanup);
                     listH.Add(hobj);
                     // Run the merging now, if required
                     if (!fHistoOneGo) {
                        h1->Merge(&listH);
                        listH.Delete();
                     }
                  }
               }
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
            // Merge the list, if still to be done
            if (fHistoOneGo) {
               h1->Merge(&listH);
               listH.Delete();
            }
         } else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {

            // loop over all source files create a chain of Trees "globChain"
            if (!fNoTrees) {
               TString obj_name;
               if (path.Length()) {
                  obj_name = path + "/" + obj->GetName();
               } else {
                  obj_name = obj->GetName();
               }
               globChain = new TChain(obj_name);
               globChain->Add(first_source->GetName());
               TFile *nextsource = (TFile*)sourcelist->After( first_source );
               while ( nextsource ) {
                  //do not add to the list a file that does not contain this Tree
                  TFile *curf = TFile::Open(nextsource->GetName());
                  if (curf) {
                     Bool_t mustAdd = kFALSE;
                     if (curf->FindKey(obj_name)) {
                        mustAdd = kTRUE;
                     } else {
                        //we could be more clever here. No need to import the object
                        //we are missing a function in TDirectory
                        TObject *aobj = curf->Get(obj_name);
                        if (aobj) { mustAdd = kTRUE; delete aobj;}
                     }
                     if (mustAdd) {
                        globChain->Add(nextsource->GetName());
                     }
                  }
                  delete curf;
                  nextsource = (TFile*)sourcelist->After( nextsource );
               }
            }
         } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
            // it's a subdirectory

            //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
            MergeRecursive( newdir, sourcelist);

         } else if (obj->InheritsFrom(TObject::Class()) &&
                    obj->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
            // Object implements Merge(TCollection*)

            TList listH;
            TString listHargs;
            listHargs.Form("((TCollection*)0x%lx)",&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();
                     // 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();
                     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());
                     }
                     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" )) {
            //printf("cas d'une directory\n");
         } else if(obj->IsA()->InheritsFrom( "TTree" )) {
            if (!fNoTrees) {
               if (globChain) {
                  globChain->ls();
                  if (fFastMethod) globChain->Merge(target->GetFile(),0,"keep fast");
                  else             globChain->Merge(target->GetFile(),0,"keep");
                  delete globChain;
               }
            }
         } else if (obj->IsA()->InheritsFrom( "TCollection" )) {
            obj->Write( key->GetName(), TObject::kSingleKey );
            ((TCollection*)obj)->SetOwner();
         } else {
            obj->Write( key->GetName() );
         }
         if (obj->IsA()->InheritsFrom("TCollection")) ((TCollection*)obj)->Delete();
         oldkey = key;
         delete obj;
      } // while ( ( TKey *key = (TKey*)nextkey() ) )
      first_source = (TDirectory*)sourcelist->After(first_source);
   }
   // save modifications to target file
   target->SaveSelf(kTRUE);
   TH1::AddDirectory(addDirStat);
   return kTRUE;
}
 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