ROOT logo
// @(#)root/io:$Id$
// Author: Philippe Canal, May 2011

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TMemFile                                                             //
//                                                                      //
// A TMemFile is like a normal TFile except that it reads and writes    //
// only from memory.                                                    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TMemFile.h"
#include "TError.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TArrayC.h"
#include "TKey.h"
#include "TClass.h"
#include "TVirtualMutex.h"
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>

// The following snippet is used for developer-level debugging
#define TMemFile_TRACE
#ifndef TMemFile_TRACE
#define TRACE(x) \
  Debug("TMemFile", "%s", x);
#else
#define TRACE(x);
#endif

ClassImp(TMemFile)

Long64_t TMemFile::fgDefaultBlockSize = 2*1024*1024;

//______________________________________________________________________________
TMemFile::TMemBlock::TMemBlock() : fPrevious(0), fNext(0), fBuffer(0), fSize(0)
{
   // Default constructor
}

//______________________________________________________________________________
TMemFile::TMemBlock::TMemBlock(Long64_t size, TMemBlock *previous) : 
   fPrevious(previous), fNext(0), fBuffer(0), fSize(0)
{
   // Constructor allocating the memory buffer.
   
   fBuffer = new UChar_t[size];
   fSize = size;
}

//______________________________________________________________________________
TMemFile::TMemBlock::~TMemBlock()
{
   // Usual destructors.  Delete the block memory.
   
   delete fNext;
   delete [] fBuffer;
}

//______________________________________________________________________________
void TMemFile::TMemBlock::CreateNext(Long64_t size)
{
   R__ASSERT(fNext == 0);
   fNext = new TMemBlock(size,this);
}

//______________________________________________________________________________
TMemFile::TMemFile(const char *path, Option_t *option,
                   const char *ftitle, Int_t compress) :
   TFile(path, "WEB", ftitle, compress),
   fSize(-1), fSysOffset(0), fBlockSeek(&fBlockList), fBlockOffset(0)
{
   // Usual Constructor.  See the TFile constructor for details.

   fOption = option;
   fOption.ToUpper();
   if (fOption == "NEW")  fOption = "CREATE";
   Bool_t create   = (fOption == "CREATE") ? kTRUE : kFALSE;
   Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
   Bool_t update   = (fOption == "UPDATE") ? kTRUE : kFALSE;
   Bool_t read     = (fOption == "READ") ? kTRUE : kFALSE;
   if (!create && !recreate && !update && !read) {
      read    = kTRUE;
      fOption = "READ";
   }

   if (!(create || recreate)) {
      Error("TMemFile","Reading a TMemFile requires a memory buffer\n");
      goto zombie;
   }
   if (create || update || recreate) {
      Int_t mode = O_RDWR | O_CREAT;
      if (recreate) mode |= O_TRUNC;

      fD = SysOpen(path, O_RDWR | O_CREAT, 0644);
      if (fD == -1) {
         SysError("TMemFile", "file %s can not be opened", path);
         goto zombie;
      }
      fWritable = kTRUE;
   } else {
      fD = SysOpen(path, O_RDONLY, 0644);
      if (fD == -1) {
         SysError("TMemFile", "file %s can not be opened for reading", path);
         goto zombie;
      }
      fWritable = kFALSE;
   }

   Init(create || recreate);

   return;

zombie:
   // Error in opening file; make this a zombie
   MakeZombie();
   gDirectory = gROOT;
}

//______________________________________________________________________________
TMemFile::TMemFile(const char *path, char *buffer, Long64_t size, Option_t *option,
                   const char *ftitle, Int_t compress):
   TFile(path, "WEB", ftitle, compress), fBlockList(size),  
   fSize(size), fSysOffset(0), fBlockSeek(&(fBlockList)), fBlockOffset(0)
{
   // Usual Constructor.  See the TFile constructor for details.

   fOption = option;
   fOption.ToUpper();
   Bool_t create   = (fOption == "CREATE") ? kTRUE : kFALSE;
   Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
   Bool_t update   = (fOption == "UPDATE") ? kTRUE : kFALSE;
   Bool_t read     = (fOption == "READ") ? kTRUE : kFALSE;
   if (!create && !recreate && !update && !read) {
      read    = kTRUE;
      fOption = "READ";
   }
   
   if (create || update || recreate) {
      Int_t mode = O_RDWR | O_CREAT;
      if (recreate) mode |= O_TRUNC;

      fD = SysOpen(path, O_RDWR | O_CREAT, 0644);
      if (fD == -1) {
         SysError("TMemFile", "file %s can not be opened", path);
         goto zombie;
      }
      fWritable = kTRUE;

   } else {
      fD = SysOpen(path, O_RDONLY, 0644);
      if (fD == -1) {
         SysError("TMemFile", "file %s can not be opened for reading", path);
         goto zombie;
      }
      fWritable = kFALSE;
   }

   SysWrite(fD,buffer,size);

   Init(create || recreate);
   return;

zombie:
   // Error in opening file; make this a zombie
   MakeZombie();
   gDirectory = gROOT;
}

//______________________________________________________________________________
TMemFile::TMemFile(const TMemFile &orig) :
   TFile(orig.GetEndpointUrl()->GetUrl(), "WEB", orig.GetTitle(), 
         orig.GetCompressionSettings() ), fBlockList(orig.GetEND()),  
   fSize(orig.GetEND()), fSysOffset(0), fBlockSeek(&(fBlockList)), fBlockOffset(0)
{
   // Copying the content of the TMemFile into another TMemFile.
   
   fOption = orig.fOption;
   
   Bool_t create   = (fOption == "CREATE") ? kTRUE : kFALSE;
   Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
   Bool_t update   = (fOption == "UPDATE") ? kTRUE : kFALSE;
   Bool_t read     = (fOption == "READ") ? kTRUE : kFALSE;
   if (!create && !recreate && !update && !read) {
      read    = kTRUE;
      fOption = "READ";
   }
   
   fD = orig.fD; // not really used, so it is okay to have the same value.
   fWritable = orig.fWritable;
   
   // We intentionally allocated just one big buffer for this object.
   orig.CopyTo(fBlockList.fBuffer,fSize);
   
   Init(create || recreate); // A copy is 
}
   
   
//______________________________________________________________________________
TMemFile::~TMemFile()
{
   // Close and clean-up HDFS file.

   // Need to call close, now as it will need both our virtual table
   // and the content of the list of blocks
   Close();
   TRACE("destroy")
}

//______________________________________________________________________________
Long64_t TMemFile::CopyTo(void *to, Long64_t maxsize) const 
{
   // Copy the binary representation of the TMemFile into
   // the memory area starting at 'to' and of length at most 'maxsize'
   // returns the number of bytes actually copied.
   
   Long64_t len = GetSize();
   if (len > maxsize) {
      len = maxsize;
   }
   Long64_t storedSysOffset   = fSysOffset;
   Long64_t storedBlockOffset = fBlockOffset;
   TMemBlock *storedBlockSeek = fBlockSeek;
   
   const_cast<TMemFile*>(this)->SysSeek(fD, 0, SEEK_SET);
   len = const_cast<TMemFile*>(this)->SysRead(fD, to, len);
   
   const_cast<TMemFile*>(this)->fBlockSeek   = storedBlockSeek;
   const_cast<TMemFile*>(this)->fBlockOffset = storedBlockOffset;
   const_cast<TMemFile*>(this)->fSysOffset   = storedSysOffset;
   return len;
}

//______________________________________________________________________________
void TMemFile::CopyTo(TBuffer &tobuf) const 
{
   // Copy the binary representation of the TMemFile into
   // the TBuffer tobuf

   const TMemBlock *current = &fBlockList;
   while(current) {
      tobuf.WriteFastArray(current->fBuffer,current->fSize);
      current = current->fNext;
   }
}

//______________________________________________________________________________
Long64_t TMemFile::GetSize() const
{
   // Return the current size of the memory file

   // We could also attempt to read it from the beginning of the buffer
   return fSize;
}

//______________________________________________________________________________
void TMemFile::Print(Option_t *option /* = "" */) const
{
   Printf("TMemFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
   if (strcmp(option,"blocks")==0) {
      const TMemBlock *current = &fBlockList;
      Int_t counter = 0;
      while(current) {
         Printf("TMemBlock: %d size=%lld addr=%p curr=%p prev=%p next=%p",
                counter,current->fSize,current->fBuffer,
                current,current->fPrevious,current->fNext);
         current = current->fNext;
         ++counter;
      }
   } else {
      GetList()->R__FOR_EACH(TObject,Print)(option);
   }
}

//______________________________________________________________________________
void TMemFile::ResetAfterMerge(TFileMergeInfo *info)
{
   // Wipe all the data from the permanent buffer but keep, the in-memory object
   // alive.

   ResetObjects(this,info);

   fNbytesKeys = 0;
   fSeekKeys = 0;

   fMustFlush = kTRUE;
   fInitDone = kFALSE;

   if (fFree) {
      fFree->Delete();
      delete fFree;
      fFree      = 0;
   }
   fWritten      = 0;
   fSumBuffer    = 0;
   fSum2Buffer   = 0;
   fBytesRead    = 0;
   fBytesReadExtra = 0;
   fBytesWrite   = 0;
   delete fClassIndex;
   fClassIndex   = 0;
   fSeekInfo     = 0;
   fNbytesInfo   = 0;
   delete fProcessIDs;
   fProcessIDs   = 0;
   fNProcessIDs  = 0;
   fOffset       = 0;
   fCacheRead    = 0;
   fCacheWrite   = 0;
   fReadCalls    = 0;
   if (fFree) {
      fFree->Delete();
      delete fFree;
      fFree = 0;
   }

   fSysOffset   = 0;
   fBlockSeek   = &fBlockList;
   fBlockOffset = 0;
   {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfFiles()->Remove(this);
   }

   {
      TDirectory::TContext ctxt(gDirectory, this);
      Init(kTRUE);

      // And now we need re-initilize the directories ...

      TIter   next(this->GetList());
      TObject *idcur;
      while ((idcur = next())) {
         if (idcur->IsA() == TDirectoryFile::Class()) {
            ((TDirectoryFile*)idcur)->ResetAfterMerge(info);
         }
      }

   }
}

//______________________________________________________________________________
void TMemFile::ResetObjects(TDirectoryFile *directory, TFileMergeInfo *info) const
{
   // Wipe all the data from the permanent buffer but keep, the in-memory object
   // alive.

   if (directory->GetListOfKeys()) {
      TIter next(directory->GetListOfKeys());
      TKey *key;
      while( (key = (TKey*)next()) ) {
         if (0 ==  directory->GetList()->FindObject(key->GetName())) {
            Warning("ResetObjects","Key/Object %s is not attached to the directory %s and can not be ResetAfterMerge correctly",
                    key->GetName(),directory->GetName());
         }
      }
      directory->GetListOfKeys()->Delete("slow");
   }

   TString listHargs;
   listHargs.Form("(TFileMergeInfo*)0x%lx",(ULong_t)info);

   TIter   next(directory->GetList());
   TObject *idcur;
   while ((idcur = next())) {
      TClass *objcl = idcur->IsA();
      if (objcl == TDirectoryFile::Class()) {
         ResetObjects((TDirectoryFile*)idcur,info);
      } else if (objcl->GetResetAfterMerge()) {
         (objcl->GetResetAfterMerge())(idcur,info);
      } else if (idcur->IsA()->GetMethodWithPrototype("ResetAfterMerge", "TFileMergeInfo*") ) {
         Int_t error = 0;
         idcur->Execute("ResetAfterMerge", listHargs.Data(), &error);
         if (error) {
            Error("ResetObjects", "calling ResetAfterMerge() on '%s' failed.",
                  idcur->GetName());
         }
      } else {
//         Error("ResetObjects","In %s, we can not reset %s (not ResetAfterMerge function)",
//               directory->GetName(),idcur->GetName());
      }
   }
}

//______________________________________________________________________________
Int_t TMemFile::SysRead(Int_t, void *buf, Int_t len)
{
   // Read specified number of bytes from current offset into the buffer.
   // See documentation for TFile::SysRead().

   TRACE("READ")

   if (fBlockList.fBuffer == 0) {
      errno = EBADF;
      gSystem->SetErrorStr("The memory file is not open.");
      return 0;
   } else {
      // Don't read past the end.
      if (fSysOffset + len > fSize) {
         len = fSize - fSysOffset;
      }
               
      if (fBlockOffset+len <= fBlockSeek->fSize) {
         // 'len' does not go past the end of the current block,
         // so let's make a simple copy.
         memcpy(buf,fBlockSeek->fBuffer+fBlockOffset,len);
         fBlockOffset += len;
      } else {
         // We are going to have to copy data from more than one
         // block.
         
         // First copy the end of the first block.
         Int_t sublen = fBlockSeek->fSize - fBlockOffset;
         memcpy(buf,fBlockSeek->fBuffer+fBlockOffset,sublen);
         
         // Move to the next.
         buf = (char*)buf + sublen;
         Int_t len_left = len - sublen;
         fBlockSeek = fBlockSeek->fNext;
         
         // Copy all the full blocks that are covered by the request.
         while (len_left > fBlockSeek->fSize) {
            R__ASSERT(fBlockSeek);

            memcpy(buf, fBlockSeek->fBuffer, fBlockSeek->fSize);
            buf = (char*)buf + fBlockSeek->fSize;
            len_left -= fBlockSeek->fSize;
            fBlockSeek = fBlockSeek->fNext;
         }
         
         // Copy the data from the last block.
         R__ASSERT(fBlockSeek);
         memcpy(buf,fBlockSeek->fBuffer, len_left);
         fBlockOffset = len_left;

      }
      fSysOffset += len;
      return len;
   }
}

//______________________________________________________________________________
Long64_t TMemFile::SysSeek(Int_t, Long64_t offset, Int_t whence)
{
   // Seek to a specified position in the file.  See TFile::SysSeek().
   // Note that TMemFile does not support seeks when the file is open for write.

   TRACE("SEEK")
   if (whence == SEEK_SET) {
      fSysOffset = offset;
      fBlockSeek = &fBlockList;
      Long64_t counter = 0;
      while(fBlockSeek->fNext && (counter+fBlockSeek->fSize) < fSysOffset)
      {
         counter += fBlockSeek->fSize; 
         fBlockSeek = fBlockSeek->fNext;
      }
      fBlockOffset = fSysOffset - counter;  // If we seek past the 'end' of the file, we now have fBlockOffset > fBlockSeek->fSize
   } else if (whence == SEEK_CUR) {

      if (offset == 0) {
         // nothing to do, really
      } else if (offset > 0) {
         // Move forward.
         if ( (fBlockOffset+offset) < fBlockSeek->fSize) {
            fSysOffset += offset;
            fBlockOffset += offset;
         } else {
            Long64_t counter = fSysOffset;
            fSysOffset += offset;
            while(fBlockSeek->fNext && counter < fSysOffset)
            {
               counter += fBlockSeek->fSize; 
               fBlockSeek = fBlockSeek->fNext;
            }
            fBlockOffset = fSysOffset - counter; // If we seek past the 'end' of the file, we now have fBlockOffset > fBlockSeek->fSize
         }
      } else {
         // Move backward in the file (offset < 0).
         Long64_t counter = fSysOffset;
         fSysOffset += offset;
         if (fSysOffset < 0) {
            SysError("TMemFile", "Unable to seek past the beginning of file");
            fSysOffset   = 0;
            fBlockSeek   = &fBlockList;
            fBlockOffset = 0;
            return -1;
         } else {
            if (offset+fBlockOffset >= 0) {
               // We are just moving in the current block.
               fBlockOffset += offset;
            } else {
               while(fBlockSeek->fPrevious && counter > fSysOffset)
               {
                  counter -= fBlockSeek->fSize;
                  fBlockSeek = fBlockSeek->fPrevious;
               }
               fBlockOffset = fSysOffset - counter;
            }
         }
      }
   } else if (whence == SEEK_END) {
      if (offset > 0) {
         SysError("TMemFile", "Unable to seek past end of file");
         return -1;
      }
      if (fSize == -1) {
         SysError("TMemFile", "Unable to seek to end of file");
         return -1;
      }
      fSysOffset = fSize;
   } else {
      SysError("TMemFile", "Unknown whence!");
      return -1;
   }
   return fSysOffset;
}

//______________________________________________________________________________
Int_t TMemFile::SysOpen(const char * /* pathname */, Int_t /* flags */, UInt_t /* mode */)
{
   // Open a file in 'MemFile'.

   if (!fBlockList.fBuffer) {
      fBlockList.fBuffer = new UChar_t[fgDefaultBlockSize];
      fBlockList.fSize = fgDefaultBlockSize;
      fSize = fgDefaultBlockSize;
   }
   if (fBlockList.fBuffer) {
      return 0;
   } else {
      return -1;
   }
}

//______________________________________________________________________________
Int_t TMemFile::SysClose(Int_t /* fd */)
{
   // Close the mem file.

   return 0;
}

//______________________________________________________________________________
Int_t TMemFile::SysWrite(Int_t /* fd */, const void *buf, Int_t len)
{
   // Write a buffer into the file;
   
   TRACE("WRITE")
   
   if (fBlockList.fBuffer == 0) {
      errno = EBADF;
      gSystem->SetErrorStr("The memory file is not open.");
      return 0;
   } else {      
      if (fBlockOffset+len <= fBlockSeek->fSize) {
         // 'len' does not go past the end of the current block,
         // so let's make a simple copy.
         memcpy(fBlockSeek->fBuffer+fBlockOffset,buf,len);
         fBlockOffset += len;
      } else {
         // We are going to have to copy data into more than one
         // block.
         
         // First copy to the end of the first block.
         Int_t sublen = fBlockSeek->fSize - fBlockOffset;
         memcpy(fBlockSeek->fBuffer+fBlockOffset,buf,sublen);

         // Move to the next.
         buf = (char*)buf + sublen;
         Int_t len_left = len - sublen;
         if (!fBlockSeek->fNext) {
            fBlockSeek->CreateNext(fgDefaultBlockSize);
            fSize += fgDefaultBlockSize;
         }
         fBlockSeek = fBlockSeek->fNext; 
         
         // Copy all the full blocks that are covered by the request.
         while (len_left > fBlockSeek->fSize) {
            R__ASSERT(fBlockSeek);
            
            memcpy(fBlockSeek->fBuffer, buf, fBlockSeek->fSize);
            buf = (char*)buf + fBlockSeek->fSize;
            len_left -= fBlockSeek->fSize;
            if (!fBlockSeek->fNext) {
               fBlockSeek->CreateNext(fgDefaultBlockSize);
               fSize += fgDefaultBlockSize;
            }
            fBlockSeek = fBlockSeek->fNext; 
         }
         
         // Copy the data from the last block.
         R__ASSERT(fBlockSeek);
         memcpy(fBlockSeek->fBuffer, buf, len_left);
         fBlockOffset = len_left;
         
      }
      fSysOffset += len;
      return len;
   }
}

//______________________________________________________________________________
Int_t TMemFile::SysStat(Int_t, Long_t* /* id */, Long64_t* /* size */, Long_t* /* flags */, Long_t* /* modtime */)
{
   // Perform a stat on the HDFS file; see TFile::SysStat().

   MayNotUse("SysStat");
   return 0;
}

//______________________________________________________________________________
Int_t TMemFile::SysSync(Int_t)
{
   // Sync remaining data to disk;
   // Nothing to do here.

   return 0;
}

//______________________________________________________________________________
void TMemFile::ResetErrno() const
{
   // ResetErrno; simply calls TSystem::ResetErrno().

   TSystem::ResetErrno();
}
 TMemFile.cxx:1
 TMemFile.cxx:2
 TMemFile.cxx:3
 TMemFile.cxx:4
 TMemFile.cxx:5
 TMemFile.cxx:6
 TMemFile.cxx:7
 TMemFile.cxx:8
 TMemFile.cxx:9
 TMemFile.cxx:10
 TMemFile.cxx:11
 TMemFile.cxx:12
 TMemFile.cxx:13
 TMemFile.cxx:14
 TMemFile.cxx:15
 TMemFile.cxx:16
 TMemFile.cxx:17
 TMemFile.cxx:18
 TMemFile.cxx:19
 TMemFile.cxx:20
 TMemFile.cxx:21
 TMemFile.cxx:22
 TMemFile.cxx:23
 TMemFile.cxx:24
 TMemFile.cxx:25
 TMemFile.cxx:26
 TMemFile.cxx:27
 TMemFile.cxx:28
 TMemFile.cxx:29
 TMemFile.cxx:30
 TMemFile.cxx:31
 TMemFile.cxx:32
 TMemFile.cxx:33
 TMemFile.cxx:34
 TMemFile.cxx:35
 TMemFile.cxx:36
 TMemFile.cxx:37
 TMemFile.cxx:38
 TMemFile.cxx:39
 TMemFile.cxx:40
 TMemFile.cxx:41
 TMemFile.cxx:42
 TMemFile.cxx:43
 TMemFile.cxx:44
 TMemFile.cxx:45
 TMemFile.cxx:46
 TMemFile.cxx:47
 TMemFile.cxx:48
 TMemFile.cxx:49
 TMemFile.cxx:50
 TMemFile.cxx:51
 TMemFile.cxx:52
 TMemFile.cxx:53
 TMemFile.cxx:54
 TMemFile.cxx:55
 TMemFile.cxx:56
 TMemFile.cxx:57
 TMemFile.cxx:58
 TMemFile.cxx:59
 TMemFile.cxx:60
 TMemFile.cxx:61
 TMemFile.cxx:62
 TMemFile.cxx:63
 TMemFile.cxx:64
 TMemFile.cxx:65
 TMemFile.cxx:66
 TMemFile.cxx:67
 TMemFile.cxx:68
 TMemFile.cxx:69
 TMemFile.cxx:70
 TMemFile.cxx:71
 TMemFile.cxx:72
 TMemFile.cxx:73
 TMemFile.cxx:74
 TMemFile.cxx:75
 TMemFile.cxx:76
 TMemFile.cxx:77
 TMemFile.cxx:78
 TMemFile.cxx:79
 TMemFile.cxx:80
 TMemFile.cxx:81
 TMemFile.cxx:82
 TMemFile.cxx:83
 TMemFile.cxx:84
 TMemFile.cxx:85
 TMemFile.cxx:86
 TMemFile.cxx:87
 TMemFile.cxx:88
 TMemFile.cxx:89
 TMemFile.cxx:90
 TMemFile.cxx:91
 TMemFile.cxx:92
 TMemFile.cxx:93
 TMemFile.cxx:94
 TMemFile.cxx:95
 TMemFile.cxx:96
 TMemFile.cxx:97
 TMemFile.cxx:98
 TMemFile.cxx:99
 TMemFile.cxx:100
 TMemFile.cxx:101
 TMemFile.cxx:102
 TMemFile.cxx:103
 TMemFile.cxx:104
 TMemFile.cxx:105
 TMemFile.cxx:106
 TMemFile.cxx:107
 TMemFile.cxx:108
 TMemFile.cxx:109
 TMemFile.cxx:110
 TMemFile.cxx:111
 TMemFile.cxx:112
 TMemFile.cxx:113
 TMemFile.cxx:114
 TMemFile.cxx:115
 TMemFile.cxx:116
 TMemFile.cxx:117
 TMemFile.cxx:118
 TMemFile.cxx:119
 TMemFile.cxx:120
 TMemFile.cxx:121
 TMemFile.cxx:122
 TMemFile.cxx:123
 TMemFile.cxx:124
 TMemFile.cxx:125
 TMemFile.cxx:126
 TMemFile.cxx:127
 TMemFile.cxx:128
 TMemFile.cxx:129
 TMemFile.cxx:130
 TMemFile.cxx:131
 TMemFile.cxx:132
 TMemFile.cxx:133
 TMemFile.cxx:134
 TMemFile.cxx:135
 TMemFile.cxx:136
 TMemFile.cxx:137
 TMemFile.cxx:138
 TMemFile.cxx:139
 TMemFile.cxx:140
 TMemFile.cxx:141
 TMemFile.cxx:142
 TMemFile.cxx:143
 TMemFile.cxx:144
 TMemFile.cxx:145
 TMemFile.cxx:146
 TMemFile.cxx:147
 TMemFile.cxx:148
 TMemFile.cxx:149
 TMemFile.cxx:150
 TMemFile.cxx:151
 TMemFile.cxx:152
 TMemFile.cxx:153
 TMemFile.cxx:154
 TMemFile.cxx:155
 TMemFile.cxx:156
 TMemFile.cxx:157
 TMemFile.cxx:158
 TMemFile.cxx:159
 TMemFile.cxx:160
 TMemFile.cxx:161
 TMemFile.cxx:162
 TMemFile.cxx:163
 TMemFile.cxx:164
 TMemFile.cxx:165
 TMemFile.cxx:166
 TMemFile.cxx:167
 TMemFile.cxx:168
 TMemFile.cxx:169
 TMemFile.cxx:170
 TMemFile.cxx:171
 TMemFile.cxx:172
 TMemFile.cxx:173
 TMemFile.cxx:174
 TMemFile.cxx:175
 TMemFile.cxx:176
 TMemFile.cxx:177
 TMemFile.cxx:178
 TMemFile.cxx:179
 TMemFile.cxx:180
 TMemFile.cxx:181
 TMemFile.cxx:182
 TMemFile.cxx:183
 TMemFile.cxx:184
 TMemFile.cxx:185
 TMemFile.cxx:186
 TMemFile.cxx:187
 TMemFile.cxx:188
 TMemFile.cxx:189
 TMemFile.cxx:190
 TMemFile.cxx:191
 TMemFile.cxx:192
 TMemFile.cxx:193
 TMemFile.cxx:194
 TMemFile.cxx:195
 TMemFile.cxx:196
 TMemFile.cxx:197
 TMemFile.cxx:198
 TMemFile.cxx:199
 TMemFile.cxx:200
 TMemFile.cxx:201
 TMemFile.cxx:202
 TMemFile.cxx:203
 TMemFile.cxx:204
 TMemFile.cxx:205
 TMemFile.cxx:206
 TMemFile.cxx:207
 TMemFile.cxx:208
 TMemFile.cxx:209
 TMemFile.cxx:210
 TMemFile.cxx:211
 TMemFile.cxx:212
 TMemFile.cxx:213
 TMemFile.cxx:214
 TMemFile.cxx:215
 TMemFile.cxx:216
 TMemFile.cxx:217
 TMemFile.cxx:218
 TMemFile.cxx:219
 TMemFile.cxx:220
 TMemFile.cxx:221
 TMemFile.cxx:222
 TMemFile.cxx:223
 TMemFile.cxx:224
 TMemFile.cxx:225
 TMemFile.cxx:226
 TMemFile.cxx:227
 TMemFile.cxx:228
 TMemFile.cxx:229
 TMemFile.cxx:230
 TMemFile.cxx:231
 TMemFile.cxx:232
 TMemFile.cxx:233
 TMemFile.cxx:234
 TMemFile.cxx:235
 TMemFile.cxx:236
 TMemFile.cxx:237
 TMemFile.cxx:238
 TMemFile.cxx:239
 TMemFile.cxx:240
 TMemFile.cxx:241
 TMemFile.cxx:242
 TMemFile.cxx:243
 TMemFile.cxx:244
 TMemFile.cxx:245
 TMemFile.cxx:246
 TMemFile.cxx:247
 TMemFile.cxx:248
 TMemFile.cxx:249
 TMemFile.cxx:250
 TMemFile.cxx:251
 TMemFile.cxx:252
 TMemFile.cxx:253
 TMemFile.cxx:254
 TMemFile.cxx:255
 TMemFile.cxx:256
 TMemFile.cxx:257
 TMemFile.cxx:258
 TMemFile.cxx:259
 TMemFile.cxx:260
 TMemFile.cxx:261
 TMemFile.cxx:262
 TMemFile.cxx:263
 TMemFile.cxx:264
 TMemFile.cxx:265
 TMemFile.cxx:266
 TMemFile.cxx:267
 TMemFile.cxx:268
 TMemFile.cxx:269
 TMemFile.cxx:270
 TMemFile.cxx:271
 TMemFile.cxx:272
 TMemFile.cxx:273
 TMemFile.cxx:274
 TMemFile.cxx:275
 TMemFile.cxx:276
 TMemFile.cxx:277
 TMemFile.cxx:278
 TMemFile.cxx:279
 TMemFile.cxx:280
 TMemFile.cxx:281
 TMemFile.cxx:282
 TMemFile.cxx:283
 TMemFile.cxx:284
 TMemFile.cxx:285
 TMemFile.cxx:286
 TMemFile.cxx:287
 TMemFile.cxx:288
 TMemFile.cxx:289
 TMemFile.cxx:290
 TMemFile.cxx:291
 TMemFile.cxx:292
 TMemFile.cxx:293
 TMemFile.cxx:294
 TMemFile.cxx:295
 TMemFile.cxx:296
 TMemFile.cxx:297
 TMemFile.cxx:298
 TMemFile.cxx:299
 TMemFile.cxx:300
 TMemFile.cxx:301
 TMemFile.cxx:302
 TMemFile.cxx:303
 TMemFile.cxx:304
 TMemFile.cxx:305
 TMemFile.cxx:306
 TMemFile.cxx:307
 TMemFile.cxx:308
 TMemFile.cxx:309
 TMemFile.cxx:310
 TMemFile.cxx:311
 TMemFile.cxx:312
 TMemFile.cxx:313
 TMemFile.cxx:314
 TMemFile.cxx:315
 TMemFile.cxx:316
 TMemFile.cxx:317
 TMemFile.cxx:318
 TMemFile.cxx:319
 TMemFile.cxx:320
 TMemFile.cxx:321
 TMemFile.cxx:322
 TMemFile.cxx:323
 TMemFile.cxx:324
 TMemFile.cxx:325
 TMemFile.cxx:326
 TMemFile.cxx:327
 TMemFile.cxx:328
 TMemFile.cxx:329
 TMemFile.cxx:330
 TMemFile.cxx:331
 TMemFile.cxx:332
 TMemFile.cxx:333
 TMemFile.cxx:334
 TMemFile.cxx:335
 TMemFile.cxx:336
 TMemFile.cxx:337
 TMemFile.cxx:338
 TMemFile.cxx:339
 TMemFile.cxx:340
 TMemFile.cxx:341
 TMemFile.cxx:342
 TMemFile.cxx:343
 TMemFile.cxx:344
 TMemFile.cxx:345
 TMemFile.cxx:346
 TMemFile.cxx:347
 TMemFile.cxx:348
 TMemFile.cxx:349
 TMemFile.cxx:350
 TMemFile.cxx:351
 TMemFile.cxx:352
 TMemFile.cxx:353
 TMemFile.cxx:354
 TMemFile.cxx:355
 TMemFile.cxx:356
 TMemFile.cxx:357
 TMemFile.cxx:358
 TMemFile.cxx:359
 TMemFile.cxx:360
 TMemFile.cxx:361
 TMemFile.cxx:362
 TMemFile.cxx:363
 TMemFile.cxx:364
 TMemFile.cxx:365
 TMemFile.cxx:366
 TMemFile.cxx:367
 TMemFile.cxx:368
 TMemFile.cxx:369
 TMemFile.cxx:370
 TMemFile.cxx:371
 TMemFile.cxx:372
 TMemFile.cxx:373
 TMemFile.cxx:374
 TMemFile.cxx:375
 TMemFile.cxx:376
 TMemFile.cxx:377
 TMemFile.cxx:378
 TMemFile.cxx:379
 TMemFile.cxx:380
 TMemFile.cxx:381
 TMemFile.cxx:382
 TMemFile.cxx:383
 TMemFile.cxx:384
 TMemFile.cxx:385
 TMemFile.cxx:386
 TMemFile.cxx:387
 TMemFile.cxx:388
 TMemFile.cxx:389
 TMemFile.cxx:390
 TMemFile.cxx:391
 TMemFile.cxx:392
 TMemFile.cxx:393
 TMemFile.cxx:394
 TMemFile.cxx:395
 TMemFile.cxx:396
 TMemFile.cxx:397
 TMemFile.cxx:398
 TMemFile.cxx:399
 TMemFile.cxx:400
 TMemFile.cxx:401
 TMemFile.cxx:402
 TMemFile.cxx:403
 TMemFile.cxx:404
 TMemFile.cxx:405
 TMemFile.cxx:406
 TMemFile.cxx:407
 TMemFile.cxx:408
 TMemFile.cxx:409
 TMemFile.cxx:410
 TMemFile.cxx:411
 TMemFile.cxx:412
 TMemFile.cxx:413
 TMemFile.cxx:414
 TMemFile.cxx:415
 TMemFile.cxx:416
 TMemFile.cxx:417
 TMemFile.cxx:418
 TMemFile.cxx:419
 TMemFile.cxx:420
 TMemFile.cxx:421
 TMemFile.cxx:422
 TMemFile.cxx:423
 TMemFile.cxx:424
 TMemFile.cxx:425
 TMemFile.cxx:426
 TMemFile.cxx:427
 TMemFile.cxx:428
 TMemFile.cxx:429
 TMemFile.cxx:430
 TMemFile.cxx:431
 TMemFile.cxx:432
 TMemFile.cxx:433
 TMemFile.cxx:434
 TMemFile.cxx:435
 TMemFile.cxx:436
 TMemFile.cxx:437
 TMemFile.cxx:438
 TMemFile.cxx:439
 TMemFile.cxx:440
 TMemFile.cxx:441
 TMemFile.cxx:442
 TMemFile.cxx:443
 TMemFile.cxx:444
 TMemFile.cxx:445
 TMemFile.cxx:446
 TMemFile.cxx:447
 TMemFile.cxx:448
 TMemFile.cxx:449
 TMemFile.cxx:450
 TMemFile.cxx:451
 TMemFile.cxx:452
 TMemFile.cxx:453
 TMemFile.cxx:454
 TMemFile.cxx:455
 TMemFile.cxx:456
 TMemFile.cxx:457
 TMemFile.cxx:458
 TMemFile.cxx:459
 TMemFile.cxx:460
 TMemFile.cxx:461
 TMemFile.cxx:462
 TMemFile.cxx:463
 TMemFile.cxx:464
 TMemFile.cxx:465
 TMemFile.cxx:466
 TMemFile.cxx:467
 TMemFile.cxx:468
 TMemFile.cxx:469
 TMemFile.cxx:470
 TMemFile.cxx:471
 TMemFile.cxx:472
 TMemFile.cxx:473
 TMemFile.cxx:474
 TMemFile.cxx:475
 TMemFile.cxx:476
 TMemFile.cxx:477
 TMemFile.cxx:478
 TMemFile.cxx:479
 TMemFile.cxx:480
 TMemFile.cxx:481
 TMemFile.cxx:482
 TMemFile.cxx:483
 TMemFile.cxx:484
 TMemFile.cxx:485
 TMemFile.cxx:486
 TMemFile.cxx:487
 TMemFile.cxx:488
 TMemFile.cxx:489
 TMemFile.cxx:490
 TMemFile.cxx:491
 TMemFile.cxx:492
 TMemFile.cxx:493
 TMemFile.cxx:494
 TMemFile.cxx:495
 TMemFile.cxx:496
 TMemFile.cxx:497
 TMemFile.cxx:498
 TMemFile.cxx:499
 TMemFile.cxx:500
 TMemFile.cxx:501
 TMemFile.cxx:502
 TMemFile.cxx:503
 TMemFile.cxx:504
 TMemFile.cxx:505
 TMemFile.cxx:506
 TMemFile.cxx:507
 TMemFile.cxx:508
 TMemFile.cxx:509
 TMemFile.cxx:510
 TMemFile.cxx:511
 TMemFile.cxx:512
 TMemFile.cxx:513
 TMemFile.cxx:514
 TMemFile.cxx:515
 TMemFile.cxx:516
 TMemFile.cxx:517
 TMemFile.cxx:518
 TMemFile.cxx:519
 TMemFile.cxx:520
 TMemFile.cxx:521
 TMemFile.cxx:522
 TMemFile.cxx:523
 TMemFile.cxx:524
 TMemFile.cxx:525
 TMemFile.cxx:526
 TMemFile.cxx:527
 TMemFile.cxx:528
 TMemFile.cxx:529
 TMemFile.cxx:530
 TMemFile.cxx:531
 TMemFile.cxx:532
 TMemFile.cxx:533
 TMemFile.cxx:534
 TMemFile.cxx:535
 TMemFile.cxx:536
 TMemFile.cxx:537
 TMemFile.cxx:538
 TMemFile.cxx:539
 TMemFile.cxx:540
 TMemFile.cxx:541
 TMemFile.cxx:542
 TMemFile.cxx:543
 TMemFile.cxx:544
 TMemFile.cxx:545
 TMemFile.cxx:546
 TMemFile.cxx:547
 TMemFile.cxx:548
 TMemFile.cxx:549
 TMemFile.cxx:550
 TMemFile.cxx:551
 TMemFile.cxx:552
 TMemFile.cxx:553
 TMemFile.cxx:554
 TMemFile.cxx:555
 TMemFile.cxx:556
 TMemFile.cxx:557
 TMemFile.cxx:558
 TMemFile.cxx:559
 TMemFile.cxx:560
 TMemFile.cxx:561
 TMemFile.cxx:562
 TMemFile.cxx:563
 TMemFile.cxx:564
 TMemFile.cxx:565
 TMemFile.cxx:566
 TMemFile.cxx:567
 TMemFile.cxx:568
 TMemFile.cxx:569
 TMemFile.cxx:570
 TMemFile.cxx:571
 TMemFile.cxx:572
 TMemFile.cxx:573
 TMemFile.cxx:574
 TMemFile.cxx:575
 TMemFile.cxx:576
 TMemFile.cxx:577
 TMemFile.cxx:578
 TMemFile.cxx:579
 TMemFile.cxx:580
 TMemFile.cxx:581
 TMemFile.cxx:582
 TMemFile.cxx:583
 TMemFile.cxx:584
 TMemFile.cxx:585
 TMemFile.cxx:586
 TMemFile.cxx:587
 TMemFile.cxx:588
 TMemFile.cxx:589
 TMemFile.cxx:590
 TMemFile.cxx:591
 TMemFile.cxx:592
 TMemFile.cxx:593
 TMemFile.cxx:594
 TMemFile.cxx:595
 TMemFile.cxx:596
 TMemFile.cxx:597
 TMemFile.cxx:598
 TMemFile.cxx:599
 TMemFile.cxx:600
 TMemFile.cxx:601
 TMemFile.cxx:602
 TMemFile.cxx:603
 TMemFile.cxx:604
 TMemFile.cxx:605
 TMemFile.cxx:606
 TMemFile.cxx:607
 TMemFile.cxx:608
 TMemFile.cxx:609
 TMemFile.cxx:610
 TMemFile.cxx:611
 TMemFile.cxx:612
 TMemFile.cxx:613
 TMemFile.cxx:614
 TMemFile.cxx:615
 TMemFile.cxx:616
 TMemFile.cxx:617
 TMemFile.cxx:618
 TMemFile.cxx:619
 TMemFile.cxx:620
 TMemFile.cxx:621
 TMemFile.cxx:622
 TMemFile.cxx:623
 TMemFile.cxx:624
 TMemFile.cxx:625
 TMemFile.cxx:626
 TMemFile.cxx:627
 TMemFile.cxx:628
 TMemFile.cxx:629
 TMemFile.cxx:630
 TMemFile.cxx:631
 TMemFile.cxx:632
 TMemFile.cxx:633
 TMemFile.cxx:634
 TMemFile.cxx:635
 TMemFile.cxx:636
 TMemFile.cxx:637
 TMemFile.cxx:638