ROOT logo
// @(#)root/dcache:$Id: TDCacheFile.cxx 26184 2008-11-14 07:59:14Z rdm $
// Author: Grzegorz Mazur   20/01/2002
// Modified: William Tanenbaum 01/12/2003
// Modified: Tigran Mkrtchyan 29/06/2004
// Modified: Tigran Mkrtchyan 06/07/2007

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TDCacheFile                                                          //
//                                                                      //
// A TDCacheFile is like a normal TFile except that it may read and     //
// write its data via a dCache server (for more on the dCache daemon    //
// see http://www-dcache.desy.de/. Given a path which doesn't belong    //
// to the dCache managed filesystem, it falls back to the ordinary      //
// TFile behaviour.                                                     //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TDCacheFile.h"
#include "TError.h"
#include "TSystem.h"
#include "TROOT.h"

#include <cstdlib>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <dcap.h>
#ifndef R__WIN32
#include <unistd.h>
#if defined(R__SUN) || defined(R__SGI) || defined(R__HPUX) || \
    defined(R__AIX) || defined(R__LINUX) || defined(R__SOLARIS) || \
    defined(R__ALPHA) || defined(R__HIUX) || defined(R__FBSD) || \
    defined(R__MACOSX) || defined(R__HURD) || defined(R__OBSD)
#define HAS_DIRENT
#endif
#endif

#ifdef HAS_DIRENT
#include <dirent.h>
#endif

static const char* const DCACHE_PREFIX = "dcache:";
static const size_t DCACHE_PREFIX_LEN = strlen(DCACHE_PREFIX);
static const char* const DCAP_PREFIX = "dcap:";
static const size_t DCAP_PREFIX_LEN = strlen(DCAP_PREFIX);


ClassImp(TDCacheFile)

//______________________________________________________________________________
TDCacheFile::TDCacheFile(const char *path, Option_t *option,
                         const char *ftitle, Int_t compress):
   TFile(path, "NET", ftitle, compress)
{
   // Create a dCache file object. A dCache file is the same as a TFile
   // except that it is being accessed via a dCache server. The url
   // argument must be of the form: dcache:/pnfs/<path>/<file>.root or
   // dcap://<nodename.org>/<path>/<file>.root. If the file specified in the
   // URL does not exist, is not accessable or can not be created the kZombie
   // bit will be set in the TDCacheFile object. Use IsZombie() to see if the
   // file is accessable. For a description of the option and other arguments
   // see the TFile ctor. The preferred interface to this constructor is
   // via TFile::Open().

   TString pathString = GetDcapPath(path);
   path = pathString.Data();

   fOffset = 0;
   fOption = option;
   fOption.ToUpper();
   fStatCached = kFALSE;

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

   TString stmp;
   TString stmp2;
   const char *fname;
   const char *fnameWithPrefix;

   if (!strncmp(path, DCAP_PREFIX, DCAP_PREFIX_LEN)) {
      fnameWithPrefix = fname = path;
   } else {
      // Metadata provided by PNFS
      char *tname;
      if ((tname = gSystem->ExpandPathName(path))) {
         stmp = tname;
         stmp2 = DCACHE_PREFIX;
         stmp2 += tname;
         delete [] tname;
         fname = stmp;
         fnameWithPrefix = stmp2;
      } else {
         Error("TDCacheFile", "error expanding path %s", path);
         goto zombie;
      }
   }

   if (recreate) {
      if (!gSystem->AccessPathName(fnameWithPrefix, kFileExists))
         dc_unlink(fname);
      recreate = kFALSE;
      create   = kTRUE;
      fOption  = "CREATE";
   }
   if (create && !gSystem->AccessPathName(fnameWithPrefix, kFileExists)) {
      Error("TDCacheFile", "file %s already exists", fname);
      goto zombie;
   }
   if (update) {
      if (gSystem->AccessPathName(fnameWithPrefix, kFileExists)) {
         update = kFALSE;
         create = kTRUE;
      }
      if (update && gSystem->AccessPathName(fnameWithPrefix, kWritePermission)) {
         Error("TDCacheFile", "no write permission, could not open file %s", fname);
         goto zombie;
      }
   }

   // Connect to file system stream
   fRealName = fname;

   if (create || update) {
#ifndef WIN32
      fD = SysOpen(fname, O_RDWR | O_CREAT, 0644);
#else
      fD = SysOpen(fname, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
#endif
      if (fD == -1) {
         SysError("TDCacheFile", "file %s can not be opened", fname);
         goto zombie;
      }
      fWritable = kTRUE;
   } else {
#ifndef WIN32
      fD = SysOpen(fname, O_RDONLY, 0644);
#else
      fD = SysOpen(fname, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
#endif
      if (fD == -1) {
         if (gSystem->AccessPathName(fnameWithPrefix, kFileExists)) {
            Error("TDCacheFile", "file %s does not exist", fname);
            goto zombie;
         }
         if (gSystem->AccessPathName(fnameWithPrefix, kReadPermission)) {
            Error("TDCacheFile", "no read permission, could not open file %s", fname);
            goto zombie;
         }
         SysError("TDCacheFile", "file %s can not be opened for reading", fname);
         goto zombie;
      }
      fWritable = kFALSE;
   }

   // use 8K ( default ) read-ahead buffer to get file header.
   // vector read are not affected by read-ahead buffer
   if(read) {
     dc_setBufferSize(fD, RAHEAD_BUFFER_SIZE); 
   }else{
     dc_noBuffering(fD);
   }

   Init(create);

   return;

zombie:
   // error in file opening occured, make this object a zombie
   MakeZombie();
   gDirectory = gROOT;
}

//______________________________________________________________________________
TDCacheFile::~TDCacheFile()
{
   // Close and cleanup dCache file.

   Close();
}

//______________________________________________________________________________
Bool_t TDCacheFile::ReadBuffer(char *buf, Int_t len)
{
   // Read specified byte range from remote file via dCache daemon.
   // Returns kTRUE in case of error.

   Int_t st;
   if ((st = ReadBufferViaCache(buf, len))) {
      if (st == 2)
         return kTRUE;
      return kFALSE;
   }

   return TFile::ReadBuffer(buf, len);
}

//______________________________________________________________________________
Bool_t TDCacheFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
{
   // Read the nbuf blocks described in arrays pos and len,
   // where pos[i] is the seek position of block i of length len[i].
   // Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer.
   // This function is overloaded by TNetFile, TWebFile, etc.
   // Returns kTRUE in case of failure.

#ifdef _IOVEC2_

   iovec2 *vector;

   vector = (iovec2 *)malloc(sizeof(iovec2)*nbuf);

   Int_t total_len = 0;
   for (Int_t i = 0; i < nbuf; i++) {
	   vector[i].buf    = &buf[total_len];
	   vector[i].offset = pos[i];
	   vector[i].len    = len[i];
	   total_len       += len[i];
   }

   Int_t rc = dc_readv2(fD, vector, nbuf);
   free(vector);

   if (rc == 0) {
      fBytesRead += total_len;
      SetFileBytesRead(GetFileBytesRead() + total_len);
	   return kFALSE;
   }

#endif

   // if we failed to get with dc_readv2 (old server), try to loop over

   Int_t k = 0;
   Bool_t result = kTRUE;
   TFileCacheRead *old = fCacheRead;
   fCacheRead = 0;

   Long64_t low  = pos[0];
   Long64_t high = pos[nbuf-1] + len[nbuf-1] - pos[0];

   Long64_t total = 0;
   for(Int_t j=0; j < nbuf; j++) {
      total += len[j];
   }

   if ( high / total < 10 ) {

      char *temp = new char[high];
      Seek(low);
      result = ReadBuffer(temp,high);

      if (result==0) {
         for (Int_t i = 0; i < nbuf; i++) {
            memcpy(&buf[k], &(temp[pos[i]-pos[0]]), len[i]);
            k += len[i];
         }
      }

      delete [] temp;

   } else {

      for (Int_t i = 0; i < nbuf; i++) {
         Seek(pos[i]);
         result = ReadBuffer(&buf[k], len[i]);
         if (result) break;
         k += len[i];
      }

   }

   fCacheRead = old;
   return result;
}

//______________________________________________________________________________
Bool_t TDCacheFile::WriteBuffer(const char *buf, Int_t len)
{
   // Write specified byte range to remote file via dCache daemon.
   // Returns kTRUE in case of error.

   if (!IsOpen() || !fWritable) return kTRUE;

   Int_t st;
   if ((st = WriteBufferViaCache(buf, len))) {
      if (st == 2)
         return kTRUE;
      return kFALSE;
   }

   return TFile::WriteBuffer(buf, len);
}

//______________________________________________________________________________
Bool_t TDCacheFile::Stage(const char *path, UInt_t after, const char *location)
{
   // Stage() returns kTRUE on success and kFALSE on failure.

   TString pathString = GetDcapPath(path);
   path = pathString.Data();

   dc_errno = 0;

   if (dc_stage(path, after, location) == 0)
      return kTRUE;

   if (dc_errno != 0)
      gSystem->SetErrorStr(dc_strerror(dc_errno));

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TDCacheFile::CheckFile(const char *path, const char *location)
{
   // CheckFile() returns kTRUE on success and kFALSE on failure.  In
   // case the file exists but is not cached, CheckFile() returns
   // kFALSE and errno is set to EAGAIN.

   TString pathString = GetDcapPath(path);
   path = pathString.Data();

   dc_errno = 0;

   if (dc_check(path, location) == 0)
      return kTRUE;

   if (dc_errno != 0)
      gSystem->SetErrorStr(dc_strerror(dc_errno));

   return kFALSE;
}

//______________________________________________________________________________
void TDCacheFile::SetOpenTimeout(UInt_t n)
{
   // Set file open timeout.

   dc_setOpenTimeout(n);
}

//______________________________________________________________________________
void TDCacheFile::SetOnError(OnErrorAction a)
{
   // Set on error handler.

   dc_setOnError(a);
}

//______________________________________________________________________________
void TDCacheFile::SetReplyHostName(const char *host_name)
{
   // Set reply host name.

   dc_setReplyHostName((char*)host_name);
}

//______________________________________________________________________________
const char *TDCacheFile::GetDcapVersion()
{
   // Return dCache version string.

   return getDcapVersion();
}

//______________________________________________________________________________
Int_t TDCacheFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
{
   // Interface to system open. All arguments like in POSIX open.

   // often there is a filewall on front of storage system.
   // let clients connect to the data servers
   // if it's an old dCache version, pool will try to connect to the client
   // (if it's fine with firewall)

   dc_setClientActive();

   dc_errno = 0;

   Int_t rc = dc_open(pathname, flags, (Int_t) mode);

   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return rc;
}

//______________________________________________________________________________
Int_t TDCacheFile::SysClose(Int_t fd)
{
   // Interface to system close. All arguments like in POSIX close.

   dc_errno = 0;

   Int_t rc = dc_close(fd);

   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return rc;
}

//______________________________________________________________________________
Int_t TDCacheFile::SysRead(Int_t fd, void *buf, Int_t len)
{
   // Interface to system read. All arguments like in POSIX read.

   fOffset += len;

   dc_errno = 0;

   Int_t rc = dc_read(fd, buf, len);

   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return rc;
}

//______________________________________________________________________________
Int_t TDCacheFile::SysWrite(Int_t fd, const void *buf, Int_t len)
{
   // Interface to system write. All arguments like in POSIX write.

   fOffset += len;

   dc_errno = 0;

   Int_t rc =  dc_write(fd, (char *)buf, len);

   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return rc;
}

//______________________________________________________________________________
Long64_t TDCacheFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
{
   // Interface to system seek. All arguments like in POSIX lseek.

   if (whence == SEEK_SET && offset == fOffset) return offset;

   dc_errno = 0;

   Long64_t rc = dc_lseek64(fd, offset, whence);

   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   } else
      fOffset = rc;

   return rc;
}

//______________________________________________________________________________
Int_t TDCacheFile::SysSync(Int_t fd)
{
   // Interface to system sync. All arguments like in POSIX fsync.
   // dCache always keep it's files sync'ed, so there's no need to
   // sync() them manually.

   Int_t rc;
   dc_errno = 0;

   rc = dc_fsync(fd);
   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return rc;
}

//______________________________________________________________________________
Int_t TDCacheFile::SysStat(Int_t, Long_t *id, Long64_t *size,
                           Long_t *flags, Long_t *modtime)
{
   // Get info about a file: id, size, flags, modification time.
   // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
   // Size    is the file size
   // Flags   is file type: 0 is regular file, bit 0 set executable,
   //                       bit 1 set directory, bit 2 set special file
   //                       (socket, fifo, pipe, etc.)
   // Modtime is modification time.
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   // If in read mode, uses the cached file status, if available, to avoid
   // costly dc_stat() call.

   struct stat64 & statbuf = fStatBuffer; // reference the cache

   if (fOption != "READ" || !fStatCached) {
      // We are not in read mode, or the file status information is not yet
      // in the cache. Update or read the status information with dc_stat().

      const char *path = GetName();
      TString pathString = GetDcapPath(path);
      path = pathString.Data();

      if (path && (dc_stat64(path, &statbuf) >= 0)) {
         fStatCached = kTRUE;
      }
   }

   if (fStatCached) {
      if (id)
         *id = (statbuf.st_dev << 24) + statbuf.st_ino;
      if (size)
         *size = statbuf.st_size;
      if (modtime)
         *modtime = statbuf.st_mtime;
      if (flags) {
         *flags = 0;
         if (statbuf.st_mode & ((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
            *flags |= 1;
         if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
            *flags |= 2;
         if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
             (statbuf.st_mode & S_IFMT) != S_IFDIR)
            *flags |= 4;
      }
      return 0;
   }
   return 1;
}

//______________________________________________________________________________
void TDCacheFile::ResetErrno() const
{
   // Method resetting the dc_errno and errno.

   dc_errno = 0;
   TSystem::ResetErrno();
}

//______________________________________________________________________________
TString TDCacheFile::GetDcapPath(const char *path)
{
   // Transform the input path into a path usuable by the dcap C library,
   // i.e either dcap://nodename.org/where/filename.root or
   // /pnfs/where/filename.root

   if (!strncmp(path, DCACHE_PREFIX, DCACHE_PREFIX_LEN)) {
      path += DCACHE_PREFIX_LEN;
   }
   if (!strncmp(path, DCAP_PREFIX, DCAP_PREFIX_LEN)) {
      path += DCAP_PREFIX_LEN;
   }
   TString pathString(path);
   if (!strncmp(path, "///", 3)) {
      path += 2;
      pathString = path;
   }
   if (!strncmp(path, "//", 2)) {
      pathString = DCAP_PREFIX + pathString;
   }
   return pathString;
}


//______________________________________________________________________________
TDCacheSystem::TDCacheSystem() : TSystem("-DCache", "DCache Helper System")
{
   // Create helper class that allows directory access via dCache.

   // name must start with '-' to bypass the TSystem singleton check
   SetName("DCache");

   fDirp = 0;
}

//______________________________________________________________________________
int TDCacheSystem::MakeDirectory(const char *path)
{
   // Create a directory.

   Int_t rc;
   dc_errno = 0;
   TString pathString = TDCacheFile::GetDcapPath(path);
   path = pathString.Data();

   rc = dc_mkdir(path, 0755);
   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return rc;
}

//______________________________________________________________________________
void *TDCacheSystem::OpenDirectory(const char *path)
{
   // Open a directory.

   dc_errno = 0;
   TString pathString = TDCacheFile::GetDcapPath(path);
   path = pathString.Data();

   fDirp = dc_opendir(path);
   if (fDirp == 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return fDirp;
}

//______________________________________________________________________________
void TDCacheSystem::FreeDirectory(void * dirp)
{
   // Close a directory.

   Int_t rc;
   dc_errno = 0;

   rc = dc_closedir((DIR *)dirp);
   if (rc < 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   fDirp = 0;
   return;
}

//______________________________________________________________________________
const char *TDCacheSystem::GetDirEntry(void * dirp)
{
   // Get a directory entry.

   struct dirent *ent;
   dc_errno = 0;

   ent = dc_readdir((DIR *)dirp);
   if (ent == 0) {
      if (dc_errno != 0)
         gSystem->SetErrorStr(dc_strerror(dc_errno));
   }

   return !ent ? 0 : ent->d_name;
}

//______________________________________________________________________________
Bool_t TDCacheSystem::AccessPathName(const char *path, EAccessMode mode)
{
   // Returns FALSE if one can access a file using the specified access mode.
   // Mode is the same as for the Unix access(2) function.
   // Attention, bizarre convention of return value!!

   TString pathString = TDCacheFile::GetDcapPath(path);
   path = pathString.Data();

   return dc_access(path, mode);
}

//______________________________________________________________________________
int TDCacheSystem::GetPathInfo(const char *path, FileStat_t &buf)
{
   // Get info about a file. Info is returned in the form of a FileStat_t
   // structure (see TSystem.h).
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   TString pathString = TDCacheFile::GetDcapPath(path);
   path = pathString.Data();

   struct stat64 sbuf;

   if (path && (dc_stat64(path, &sbuf) >= 0)) {

      buf.fDev    = sbuf.st_dev;
      buf.fIno    = sbuf.st_ino;
      buf.fMode   = sbuf.st_mode;
      buf.fUid    = sbuf.st_uid;
      buf.fGid    = sbuf.st_gid;
      buf.fSize   = sbuf.st_size;
      buf.fMtime  = sbuf.st_mtime;
      buf.fIsLink = kFALSE;

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