/*
<img src="gif/file_layout.gif">
*/
//End_Html
#include "RConfig.h"
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#ifndef WIN32
#   include <unistd.h>
#else
#   define ssize_t int
#   include <io.h>
#   include <sys/types.h>
#endif
#include "Bytes.h"
#include "Riostream.h"
#include "Strlen.h"
#include "TArrayC.h"
#include "TClass.h"
#include "TClassTable.h"
#include "TDatime.h"
#include "TError.h"
#include "TFile.h"
#include "TFileCacheRead.h"
#include "TFileCacheWrite.h"
#include "TFree.h"
#include "TInterpreter.h"
#include "TKey.h"
#include "TPluginManager.h"
#include "TProcessUUID.h"
#include "TRegexp.h"
#include "TROOT.h"
#include "TStreamerInfo.h"
#include "TSystem.h"
#include "TTimeStamp.h"
#include "TVirtualPerfStats.h"
#include "TArchiveFile.h"
#include "TEnv.h"
#include "TVirtualMonitoring.h"
#include "TVirtualMutex.h"
#include "TMathBase.h"
#include "TObjString.h"
#include "TStopwatch.h"
#include <cmath>
TFile *gFile;                 
Long64_t TFile::fgBytesRead  = 0;
Long64_t TFile::fgBytesWrite = 0;
Long64_t TFile::fgFileCounter = 0;
Int_t    TFile::fgReadCalls = 0;
Bool_t   TFile::fgReadInfo = kTRUE;
TList   *TFile::fgAsyncOpenRequests = 0;
TString  TFile::fgCacheFileDir;
Bool_t   TFile::fgCacheFileForce = kFALSE;
Bool_t   TFile::fgCacheFileDisconnected = kTRUE;
UInt_t   TFile::fgOpenTimeout = TFile::kEternalTimeout;
Bool_t   TFile::fgOnlyStaged = 0;
const Int_t kBEGIN = 100;
ClassImp(TFile)
TFile::TFile() : TDirectoryFile(), fInfoCache(0)
{
   
   fD               = -1;
   fFree            = 0;
   fWritten         = 0;
   fSumBuffer       = 0;
   fSum2Buffer      = 0;
   fClassIndex      = 0;
   fProcessIDs      = 0;
   fNProcessIDs     = 0;
   fOffset          = 0;
   fArchive         = 0;
   fCacheRead       = 0;
   fCacheWrite      = 0;
   fArchiveOffset   = 0;
   fReadCalls       = 0;
   fNoAnchorInName  = kFALSE;
   fIsRootFile      = kTRUE;
   fIsArchive       = kFALSE;
   fInitDone        = kFALSE;
   fMustFlush       = kTRUE;
   fAsyncHandle     = 0;
   fAsyncOpenStatus = kAOSNotAsync;
   SetBit(kBinaryFile, kTRUE);
   if (gDebug)
      Info("TFile", "default ctor");
}
TFile::TFile(const char *fname1, Option_t *option, const char *ftitle, Int_t compress)
           : TDirectoryFile(), fUrl(fname1,kTRUE), fInfoCache(0)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   if (!gROOT)
      ::Fatal("TFile::TFile", "ROOT system not initialized");
   
   TString sfname1 = fname1;
   fNoAnchorInName = kFALSE;
   if (sfname1.Index("?") != kNPOS) {
      TString s = sfname1(0, sfname1.Index("?"));
      SetName(s);
      fNoAnchorInName = kTRUE;
   } else
      SetName(fname1);
   SetTitle(ftitle);
   
   fname1 = fUrl.GetFile();
   
   fIsRootFile = kTRUE;
   if (strstr(fUrl.GetOptions(), "filetype=raw"))
      fIsRootFile = kFALSE;
   
   fInitDone   = kFALSE;
   fMustFlush  = kTRUE;
   
   fAsyncHandle = 0;
   fAsyncOpenStatus = kAOSNotAsync;
   TDirectoryFile::Build(this, 0);
   fD            = -1;
   fFree         = 0;
   fVersion      = gROOT->GetVersionInt();  
   fUnits        = 4;
   fOption       = option;
   fCompress     = compress;
   fWritten      = 0;
   fSumBuffer    = 0;
   fSum2Buffer   = 0;
   fBytesRead    = 0;
   fBytesWrite   = 0;
   fClassIndex   = 0;
   fSeekInfo     = 0;
   fNbytesInfo   = 0;
   fProcessIDs   = 0;
   fNProcessIDs  = 0;
   fOffset       = 0;
   fCacheRead    = 0;
   fCacheWrite   = 0;
   fReadCalls    = 0;
   SetBit(kBinaryFile, kTRUE);
   fOption.ToUpper();
   fArchiveOffset = 0;
   fIsArchive     = kFALSE;
   fArchive = TArchiveFile::Open(fUrl.GetUrl(), this);
   if (fArchive) {
      fname1 = fArchive->GetArchiveName();
      
      
      if (!strlen(fArchive->GetMemberName()))
         fIsArchive = kTRUE;
   }
   if (fOption == "NET")
      return;
   if (fOption == "WEB") {
      fOption   = "READ";
      fWritable = kFALSE;
      return;
   }
   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";
   }
   Bool_t devnull = kFALSE;
   if (!fname1 || !strlen(fname1)) {
      Error("TFile", "file name is not specified");
      goto zombie;
   }
   
   if (!strcmp(fname1, "/dev/null") &&
       !gSystem->AccessPathName(fname1, kWritePermission)) {
      devnull  = kTRUE;
      create   = kTRUE;
      recreate = kFALSE;
      update   = kFALSE;
      read     = kFALSE;
      fOption  = "CREATE";
      SetBit(kDevNull);
   }
   const char *fname;
   if ((fname = gSystem->ExpandPathName(fname1))) {
      SetName(fname);
      delete [] (char*)fname;
      fRealName = GetName();
      fname = fRealName.Data();
   } else {
      Error("TFile", "error expanding path %s", fname1);
      goto zombie;
   }
   if (recreate) {
      if (!gSystem->AccessPathName(fname, kFileExists))
         gSystem->Unlink(fname);
      recreate = kFALSE;
      create   = kTRUE;
      fOption  = "CREATE";
   }
   if (create && !devnull && !gSystem->AccessPathName(fname, kFileExists)) {
      Error("TFile", "file %s already exists", fname);
      goto zombie;
   }
   if (update) {
      if (gSystem->AccessPathName(fname, kFileExists)) {
         update = kFALSE;
         create = kTRUE;
      }
      if (update && gSystem->AccessPathName(fname, kWritePermission)) {
         Error("TFile", "no write permission, could not open file %s", fname);
         goto zombie;
      }
   }
   if (read) {
      if (gSystem->AccessPathName(fname, kFileExists)) {
         Error("TFile", "file %s does not exist", fname);
         goto zombie;
      }
      if (gSystem->AccessPathName(fname, kReadPermission)) {
         Error("TFile", "no read permission, could not open file %s", fname);
         goto zombie;
      }
   }
   
   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("TFile", "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) {
         SysError("TFile", "file %s can not be opened for reading", fname);
         goto zombie;
      }
      fWritable = kFALSE;
   }
   Init(create);
   return;
zombie:
   
   MakeZombie();
   gDirectory = gROOT;
}
TFile::TFile(const TFile &file) : TDirectoryFile(), fInfoCache(0)
{
   
   ((TFile&)file).Copy(*this);
}
TFile::~TFile()
{
   
   Close();
   SafeDelete(fProcessIDs);
   SafeDelete(fFree);
   SafeDelete(fArchive);
   SafeDelete(fInfoCache);
   SafeDelete(fAsyncHandle);
   SafeDelete(fCacheRead);
   SafeDelete(fCacheWrite);
   R__LOCKGUARD2(gROOTMutex);
   gROOT->GetListOfFiles()->Remove(this);
   gROOT->GetUUIDs()->RemoveUUID(GetUniqueID());
   if (gDebug)
      Info("~TFile", "dtor called for %s [%d]", GetName(),this);
}
void TFile::Init(Bool_t create)
{
   
   
   
   
   if (fInitDone)
      
      return;
   fInitDone = kTRUE;
   if (fArchive) {
      if (fOption != "READ") {
         Error("Init", "archive %s can only be opened in read mode", GetName());
         delete fArchive;
         fArchive = 0;
         fIsArchive = kFALSE;
         goto zombie;
      }
      fArchive->OpenArchive();
      if (fIsArchive) return;
      
      if (!fNoAnchorInName)
         if (!strchr(GetName(),'#'))
            SetName(Form("%s#%s", GetName(), fArchive->GetMemberName()));
      if (fArchive->SetCurrentMember() != -1)
         fArchiveOffset = fArchive->GetMemberFilePosition();
      else {
         Error("Init", "member %s not found in archive %s",
               fArchive->GetMemberName(), fArchive->GetArchiveName());
         delete fArchive;
         fArchive = 0;
         fIsArchive = kFALSE;
         goto zombie;
      }
   }
   if (!fIsRootFile) {
      gDirectory = gROOT;
      return;
   }
   Int_t nfree;
   fBEGIN = (Long64_t)kBEGIN;    
   
   cd();
   if (create) {
      
      fFree        = new TList;
      fEND         = fBEGIN;    
      new TFree(fFree, fBEGIN, Long64_t(kStartBigFile));  
      
      Int_t namelen= TNamed::Sizeof();
      Int_t nbytes = namelen + TDirectoryFile::Sizeof();
      TKey *key    = new TKey(fName, fTitle, IsA(), nbytes, this);
      fNbytesName  = key->GetKeylen() + namelen;
      fSeekDir     = key->GetSeekKey();
      fSeekFree    = 0;
      fNbytesFree  = 0;
      WriteHeader();
      char *buffer = key->GetBuffer();
      TNamed::FillBuffer(buffer);
      TDirectoryFile::FillBuffer(buffer);
      key->WriteFile();
      delete key;
   } else {
      
      char *header = new char[kBEGIN];
      Seek(0);
      ReadBuffer(header, kBEGIN);
      
      if (strncmp(header, "root", 4)) {
         Error("Init", "%s not a ROOT file", GetName());
         delete [] header;
         goto zombie;
      }
      char *buffer = header + 4;    
      frombuf(buffer, &fVersion);
      Int_t headerLength;
      frombuf(buffer, &headerLength);
      fBEGIN = (Long64_t)headerLength;
      if (fVersion < 1000000) { 
         Int_t send,sfree,sinfo;
         frombuf(buffer, &send);         fEND     = (Long64_t)send;
         frombuf(buffer, &sfree);        fSeekFree= (Long64_t)sfree;
         frombuf(buffer, &fNbytesFree);
         frombuf(buffer, &nfree);
         frombuf(buffer, &fNbytesName);
         frombuf(buffer, &fUnits );
         frombuf(buffer, &fCompress);
         frombuf(buffer, &sinfo);        fSeekInfo = (Long64_t)sinfo;
         frombuf(buffer, &fNbytesInfo);
      } else { 
         frombuf(buffer, &fEND);
         frombuf(buffer, &fSeekFree);
         frombuf(buffer, &fNbytesFree);
         frombuf(buffer, &nfree);
         frombuf(buffer, &fNbytesName);
         frombuf(buffer, &fUnits );
         frombuf(buffer, &fCompress);
         frombuf(buffer, &fSeekInfo);
         frombuf(buffer, &fNbytesInfo);
      }
      fSeekDir = fBEGIN;
      delete [] header;
      
      if (fWritable) {
         fFree = new TList;
         if (fSeekFree > fBEGIN) {
            ReadFree();
         } else {
            Warning("Init","file %s probably not closed, cannot read free segments",GetName());
         }
      }
      
      Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof();
      header       = new char[nbytes];
      buffer       = header;
      Seek(fBEGIN);
      ReadBuffer(buffer,nbytes);
      buffer = header+fNbytesName;
      Version_t version,versiondir;
      frombuf(buffer,&version); versiondir = version%1000;
      fDatimeC.ReadBuffer(buffer);
      fDatimeM.ReadBuffer(buffer);
      frombuf(buffer, &fNbytesKeys);
      frombuf(buffer, &fNbytesName);
      Int_t nk = sizeof(Int_t) +sizeof(Version_t) +2*sizeof(Int_t)+2*sizeof(Short_t)
                +2*sizeof(Int_t);
      if (version > 1000) {
         frombuf(buffer, &fSeekDir);
         frombuf(buffer, &fSeekParent);
         frombuf(buffer, &fSeekKeys);
      } else {
         Int_t sdir,sparent,skeys;
         frombuf(buffer, &sdir);    fSeekDir    = (Long64_t)sdir;
         frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
         frombuf(buffer, &skeys);   fSeekKeys   = (Long64_t)skeys;
      }
      if (versiondir > 1) fUUID.ReadBuffer(buffer);
      
      buffer = header+nk;
      TString cname;
      cname.ReadBuffer(buffer);
      cname.ReadBuffer(buffer); 
      fTitle.ReadBuffer(buffer);
      delete [] header;
      if (fNbytesName < 10 || fNbytesName > 10000) {
         Error("Init","cannot read directory info of file %s", GetName());
         goto zombie;
      }
      
      Long64_t size;
      if ((size = GetSize()) == -1) {
         Error("Init", "cannot stat the file %s", GetName());
         goto zombie;
      }
      
      if (fSeekKeys > fBEGIN && fEND <= size) {
         
         TDirectoryFile::ReadKeys();
         gDirectory = this;
         if (!GetNkeys()) Recover();
      } else if ((fBEGIN+nbytes == fEND) && (fEND == size)) {
         
         Warning("Init","file %s has no keys", GetName());
         gDirectory = this;
      } else {
         
         if (fEND > size) {
            Error("Init","file %s is truncated at %lld bytes: should be %lld, trying to recover",
                  GetName(), size, fEND);
         } else {
            Warning("Init","file %s probably not closed, trying to recover",
                    GetName());
         }
         Int_t nrecov = Recover();
         if (nrecov) {
            Warning("Init", "successfully recovered %d keys", nrecov);
         } else {
            Warning("Init", "no keys recovered, file has been made a Zombie");
            goto zombie;
         }
      }
   }
   {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfFiles()->Add(this);
      gROOT->GetUUIDs()->AddUUID(fUUID,this);
      
      Int_t lenIndex = gROOT->GetListOfStreamerInfo()->GetSize()+1;
      if (lenIndex < 5000) lenIndex = 5000;
      fClassIndex = new TArrayC(lenIndex);
      if (fgReadInfo && fSeekInfo > fBEGIN) ReadStreamerInfo();
   }
   
   {
      TIter next(fKeys);
      TKey *key;
      while ((key = (TKey*)next())) {
         if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++;
      }
      fProcessIDs = new TObjArray(fNProcessIDs+1);
      return;
   }
zombie:
   
   MakeZombie();
   gDirectory = gROOT;
}
void TFile::Close(Option_t *option)
{
   
   
   
   
   
   
   
   
   TString opt = option;
   opt.ToLower();
   if (!IsOpen()) return;
   if (gMonitoringWriter && (!fWritable))
      gMonitoringWriter->SendFileReadProgress(this,true);
   if (fIsArchive || !fIsRootFile) {
      FlushWriteCache();
      SysClose(fD);
      fD = -1;
      return;
   }
   if (IsWritable()) {
      WriteStreamerInfo();
   }
   delete fClassIndex;
   fClassIndex = 0;
   
   
   
   TDirectoryFile::Close();
   if (IsWritable()) {
      TFree *f1 = (TFree*)fFree->First();
      if (f1) {
         WriteFree();       
         WriteHeader();     
      }
   }
   FlushWriteCache();
   
   if (fFree) {
      fFree->Delete();
   }
   if (IsOpen()) {
      SysClose(fD);
      fD = -1;
   }
   fWritable = kFALSE;
   
   TList pidDeleted;
   TIter next(fProcessIDs);
   TProcessID *pid;
   while ((pid = (TProcessID*)next())) {
      if (!pid->DecrementCount()) {
         if (pid != TProcessID::GetSessionProcessID()) pidDeleted.Add(pid);
      } else if(opt.Contains("r")) {
         pid->Clear();
      }
   }
   pidDeleted.Delete();
   R__LOCKGUARD2(gROOTMutex);
   gROOT->GetListOfFiles()->Remove(this);
   gROOT->GetListOfBrowsers()->RecursiveRemove(this);
}
TKey* TFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize)
{
   
   return new TKey(obj, name, bufsize, mother);
}
TKey* TFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize)
{
   
   return new TKey(obj, cl, name, bufsize, mother);
}
void TFile::Delete(const char *namecycle)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   if (gDebug)
      Info("Delete", "deleting name = %s", namecycle);
   TDirectoryFile::Delete(namecycle);
}
void TFile::Draw(Option_t *option)
{
   
   
   GetList()->R__FOR_EACH(TObject,Draw)(option);
}
void TFile::DrawMap(const char *keys, Option_t *option)
{
   
   TPluginHandler *h;
   if ((h = gROOT->GetPluginManager()->FindHandler("TFileDrawMap"))) {
      if (h->LoadPlugin() == -1)
         return;
      h->ExecPlugin(3, this, keys, option);
   }
}
void TFile::Flush()
{
   
   if (IsOpen() && fWritable) {
      FlushWriteCache();
      if (SysSync(fD) < 0) {
         
         SetBit(kWriteError); SetWritable(kFALSE);
         SysError("Flush", "error flushing file %s", GetName());
      }
   }
}
Bool_t TFile::FlushWriteCache()
{
   
   
   if (fCacheWrite && IsOpen() && fWritable)
      return fCacheWrite->Flush();
   return kFALSE;
}
void TFile::FillBuffer(char *&buffer)
{
   
   
   Version_t version = TFile::Class_Version();
   tobuf(buffer, version);
}
Int_t TFile::GetBestBuffer() const
{
   
   
   
   
   if (!fWritten) return TBuffer::kInitialSize;
   Double_t mean = fSumBuffer/fWritten;
   Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer -mean*mean);
   return (Int_t)(mean + sqrt(rms2));
}
Float_t TFile::GetCompressionFactor()
{
   
   
   
   Short_t  keylen;
   UInt_t   datime;
   Int_t    nbytes, objlen, nwh = 64;
   char    *header = new char[fBEGIN];
   char    *buffer;
   Long64_t   idcur = fBEGIN;
   Float_t comp,uncomp;
   comp = uncomp = fBEGIN;
   while (idcur < fEND-100) {
      Seek(idcur);
      ReadBuffer(header, nwh);
      buffer=header;
      frombuf(buffer, &nbytes);
      if (nbytes < 0) {
         idcur -= nbytes;
         Seek(idcur);
         continue;
      }
      if (nbytes == 0) break; 
      Version_t versionkey;
      frombuf(buffer, &versionkey);
      frombuf(buffer, &objlen);
      frombuf(buffer, &datime);
      frombuf(buffer, &keylen);
      if (!objlen) objlen = nbytes-keylen;
      comp   += nbytes;
      uncomp += keylen + objlen;
      idcur  += nbytes;
   }
   delete [] header;
   return uncomp/comp;
}
Int_t TFile::GetErrno() const
{
   
   return TSystem::GetErrno();
}
void TFile::ResetErrno() const
{
   
   TSystem::ResetErrno();
}
TFileCacheRead *TFile::GetCacheRead() const
{
   
   return fCacheRead;
}
TFileCacheWrite *TFile::GetCacheWrite() const
{
   
   return fCacheWrite;
}
Int_t TFile::GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
{
   
   
   
   
   
   
   
   
   
   
   
   
   if (first < fBEGIN) return 0;
   if (first > fEND)   return 0;
   Seek(first);
   Int_t nread = maxbytes;
   if (first+maxbytes > fEND) nread = fEND-maxbytes;
   if (nread < 4) {
      Warning("GetRecordHeader","%s: parameter maxbytes = %d must be >= 4",
              GetName(), nread);
      return nread;
   }
   ReadBuffer(buf,nread);
   Version_t versionkey;
   Short_t  klen;
   UInt_t   datime;
   Int_t    nb,olen;
   char *buffer = buf;
   frombuf(buffer,&nb);
   nbytes = nb;
   if (nb < 0) return nread;
   
   const Int_t headerSize = 16;
   if (nread < headerSize) return nread;
   frombuf(buffer, &versionkey);
   frombuf(buffer, &olen);
   frombuf(buffer, &datime);
   frombuf(buffer, &klen);
   if (!olen) olen = nbytes-klen;
   objlen = olen;
   keylen = klen;
   return nread;
}
Long64_t TFile::GetSize() const
{
   
   
   Long64_t size;
   if (fArchive && fArchive->GetMember()) {
      size = fArchive->GetMember()->GetDecompressedSize();
   } else {
      Long_t id, flags, modtime;
      if (const_cast<TFile*>(this)->SysStat(fD, &id, &size, &flags, &modtime)) {
         Error("GetSize", "cannot stat the file %s", GetName());
         return -1;
      }
   }
   return size;
}
const TList *TFile::GetStreamerInfoCache()
{
   
   return fInfoCache ?  fInfoCache : (fInfoCache=GetStreamerInfoList());
}
TList *TFile::GetStreamerInfoList()
{
   
   
   
   
   
   
   
   
   
   
   TList *list = 0;
   if (fSeekInfo) {
      TDirectory::TContext ctx(gDirectory,this); 
      TKey *key = new TKey(this);
      char *buffer = new char[fNbytesInfo+1];
      char *buf    = buffer;
      Seek(fSeekInfo);
      ReadBuffer(buf,fNbytesInfo);
      key->ReadKeyBuffer(buf);
      list = (TList*)key->ReadObj();
      if (list) list->SetOwner();
      delete [] buffer;
      delete key;
   } else {
      list = (TList*)Get("StreamerInfo"); 
   }
   if (list == 0) {
      Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s",
           GetName());
      return 0;
   }
   return list;
}
void TFile::ls(Option_t *option) const
{
   
   
   
   
   TROOT::IndentLevel();
   cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<endl;
   TROOT::IncreaseDirLevel();
   TDirectoryFile::ls(option);
   TROOT::DecreaseDirLevel();
}
Bool_t TFile::IsOpen() const
{
   
   return fD == -1 ? kFALSE : kTRUE;
}
void TFile::MakeFree(Long64_t first, Long64_t last)
{
   
   
   
   
   
   
   
   TFree *f1      = (TFree*)fFree->First();
   if (!f1) return;
   TFree *newfree = f1->AddFree(fFree,first,last);
   if(!newfree) return;
   Long64_t nfirst = newfree->GetFirst();
   Long64_t nlast  = newfree->GetLast();
   Long64_t nbytesl= nlast-nfirst+1;
   if (nbytesl > 2000000000) nbytesl = 2000000000;
   Int_t nbytes    = -Int_t (nbytesl);
   Int_t nb        = sizeof(Int_t);
   char * buffer   = new char[nb];
   char * psave    = buffer;
   tobuf(buffer, nbytes);
   if (last == fEND-1) fEND = nfirst;
   Seek(nfirst);
   WriteBuffer(psave, nb);
   Flush();
   delete [] psave;
}
void TFile::Map()
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   Short_t  keylen,cycle;
   UInt_t   datime;
   Int_t    nbytes,date,time,objlen,nwheader;
   Long64_t seekkey,seekpdir;
   char    *buffer;
   char     nwhc;
   Long64_t idcur = fBEGIN;
   nwheader = 64;
   Int_t nread = nwheader;
   char header[kBEGIN];
   char classname[512];
   while (idcur < fEND) {
      Seek(idcur);
      if (idcur+nread >= fEND) nread = fEND-idcur-1;
      ReadBuffer(header, nread);
      buffer=header;
      frombuf(buffer, &nbytes);
      if (!nbytes) {
         Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
         break;
      }
      if (nbytes < 0) {
         Printf("Address = %lld\tNbytes = %d\t=====G A P===========", idcur, nbytes);
         idcur -= nbytes;
         Seek(idcur);
         continue;
      }
      Version_t versionkey;
      frombuf(buffer, &versionkey);
      frombuf(buffer, &objlen);
      frombuf(buffer, &datime);
      frombuf(buffer, &keylen);
      frombuf(buffer, &cycle);
      if (versionkey > 1000) {
         frombuf(buffer, &seekkey);
         frombuf(buffer, &seekpdir);
      } else {
         Int_t skey,sdir;
         frombuf(buffer, &skey);  seekkey  = (Long64_t)skey;
         frombuf(buffer, &sdir);  seekpdir = (Long64_t)sdir;
      }
      frombuf(buffer, &nwhc);
      int i;
      for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
      classname[(int)nwhc] = '\0'; 
      if (idcur == fSeekFree) strcpy(classname,"FreeSegments");
      if (idcur == fSeekInfo) strcpy(classname,"StreamerInfo");
      if (idcur == fSeekKeys) strcpy(classname,"KeysList");
      TDatime::GetDateTime(datime, date, time);
      if (objlen != nbytes-keylen) {
         Float_t cx = Float_t(objlen+keylen)/Float_t(nbytes);
         
         Printf("%d/%06d  At:%lld  N=%-8d  %-14s CX = %5.2f",date,time,idcur,nbytes,classname,cx);
      } else {
         
         Printf("%d/%06d  At:%lld  N=%-8d  %-14s",date,time,idcur,nbytes,classname);
      }
      idcur += nbytes;
   }
   
   Printf("%d/%06d  At:%lld  N=%-8d  %-14s",date,time,idcur,1,"END");
}
void TFile::Paint(Option_t *option)
{
   
   GetList()->R__FOR_EACH(TObject,Paint)(option);
}
void TFile::Print(Option_t *option) const
{
   
   Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
   GetList()->R__FOR_EACH(TObject,Print)(option);
}
Bool_t TFile::ReadBuffer(char *buf, Int_t len)
{
   
   
   if (IsOpen()) {
      Int_t st;
      if ((st = ReadBufferViaCache(buf, len))) {
         if (st == 2)
            return kTRUE;
         return kFALSE;
      }
      ssize_t siz;
      Double_t start = 0;
      if (gPerfStats != 0) start = TTimeStamp();
      if (gMonitoringWriter)
         gMonitoringWriter->SendFileReadProgress(this);
      while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
         ResetErrno();
      if (siz < 0) {
         SysError("ReadBuffer", "error reading from file %s", GetName());
         return kTRUE;
      }
      if (siz != len) {
         Error("ReadBuffer", "error reading all requested bytes from file %s, got %d of %d",
               GetName(), siz, len);
         return kTRUE;
      }
      fBytesRead  += siz;
      fgBytesRead += siz;
      fReadCalls++;
      fgReadCalls++;
      if (gPerfStats != 0) {
         gPerfStats->FileReadEvent(this, len, double(TTimeStamp())-start);
      }
      return kFALSE;
   }
   return kTRUE;
}
Bool_t TFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
{
   
   
   
   
   
   Int_t k = 0;
   Bool_t result = kTRUE;
   TFileCacheRead *old = fCacheRead;
   fCacheRead = 0;
   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;
}
Int_t TFile::ReadBufferViaCache(char *buf, Int_t len)
{
   
   
   
   Long64_t off = GetRelOffset();
   if (fCacheRead) {
      Int_t st = fCacheRead->ReadBuffer(buf, off, len);
      if (st < 0)
         return 2;  
      else if (st == 1) {
         
         Seek(off + len);
         return 1;
      }
      
      Seek(off);
   } else {
      
      if (fWritable && fCacheWrite) {
         if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
            Seek(off + len);
            return 1;
         }
         
         Seek(off);
      }
   }
   return 0;
}
void TFile::ReadFree()
{
   
   
   
   
   TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
   headerfree->ReadFile();
   char *buffer = headerfree->GetBuffer();
   headerfree->ReadKeyBuffer(buffer);
   buffer = headerfree->GetBuffer();
   while (1) {
      TFree *afree = new TFree();
      afree->ReadBuffer(buffer);
      fFree->Add(afree);
      if (afree->GetLast() > fEND) break;
   }
   delete headerfree;
}
TProcessID  *TFile::ReadProcessID(UShort_t pidf)
{
   
   
   TProcessID *pid = 0;
   TObjArray *pids = GetListOfProcessIDs();
   if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
   if (pid) {
      pid->CheckInit();
      return pid;
   }
   
   
   char pidname[32];
   sprintf(pidname,"ProcessID%d",pidf);
   TDirectory *dirsav = gDirectory;
   this->cd();
   pid = (TProcessID *)Get(pidname);
   if (dirsav) dirsav->cd();
   if (gDebug > 0) {
      printf("ReadProcessID, name=%s, file=%s, pid=%lx\n",pidname,GetName(),(Long_t)pid);
   }
   if (!pid) {
      
      return pid;
   }
      
   TObjArray *pidslist = TProcessID::GetPIDs();
   TIter next(pidslist);
   TProcessID *p;
   while ((p = (TProcessID*)next())) {
      if (!strcmp(p->GetTitle(),pid->GetTitle())) {
         delete pid;
         pids->AddAtAndExpand(p,pidf);
         p->IncrementCount();
         return p;
      }
   }
   pids->AddAtAndExpand(pid,pidf);
   pid->IncrementCount();
   pidslist->Add(pid);
   Int_t ind = pidslist->IndexOf(pid);
   pid->SetUniqueID((UInt_t)ind);
   return pid;
}
Int_t TFile::Recover()
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   Short_t  keylen,cycle;
   UInt_t   datime;
   Int_t    nbytes,date,time,objlen,nwheader;
   Long64_t seekkey,seekpdir;
   char     header[1024];
   char    *buffer, *bufread;
   char     nwhc;
   Long64_t idcur = fBEGIN;
   Long64_t size;
   if ((size = GetSize()) == -1) {
      Error("Recover", "cannot stat the file %s", GetName());
      return 0;
   }
   fEND = Long64_t(size);
   if (fWritable && !fFree) fFree  = new TList;
   TKey *key;
   Int_t nrecov = 0;
   nwheader = 1024;
   Int_t nread = nwheader;
   while (idcur < fEND) {
      Seek(idcur);
      if (idcur+nread >= fEND) nread = fEND-idcur-1;
      ReadBuffer(header, nread);
      buffer  = header;
      bufread = header;
      frombuf(buffer, &nbytes);
      if (!nbytes) {
         Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
         break;
      }
      if (nbytes < 0) {
         idcur -= nbytes;
         if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
         Seek(idcur);
         continue;
      }
      Version_t versionkey;
      frombuf(buffer, &versionkey);
      frombuf(buffer, &objlen);
      frombuf(buffer, &datime);
      frombuf(buffer, &keylen);
      frombuf(buffer, &cycle);
      if (versionkey > 1000) {
         frombuf(buffer, &seekkey);
         frombuf(buffer, &seekpdir);
      } else {
         Int_t skey,sdir;
         frombuf(buffer, &skey);  seekkey  = (Long64_t)skey;
         frombuf(buffer, &sdir);  seekpdir = (Long64_t)sdir;
      }
      frombuf(buffer, &nwhc);
      char *classname = 0;
      if (nwhc <= 0 || nwhc > 100) break;
      classname = new char[nwhc+1];
      int i;
      for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
      classname[nwhc] = '\0';
      TDatime::GetDateTime(datime, date, time);
      if (seekpdir == fSeekDir && strcmp(classname,"TFile") && strcmp(classname,"TBasket")) {
         key = new TKey(this);
         key->ReadKeyBuffer(bufread);
         if (!strcmp(key->GetName(),"StreamerInfo")) {
            fSeekInfo = seekkey;
            SafeDelete(fInfoCache);
            fNbytesInfo = nbytes;
         } else {
            AppendKey(key);
            nrecov++;
            SetBit(kRecovered);
            Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
         }
      }
      delete [] classname;
      idcur += nbytes;
   }
   if (fWritable) {
      Long64_t max_file_size = Long64_t(kStartBigFile);
      if (max_file_size < fEND) max_file_size = fEND+1000000000;
      new TFree(fFree,fEND,max_file_size);
      if (nrecov) Write();
   }
   return nrecov;
}
Int_t TFile::ReOpen(Option_t *mode)
{
   
   
   
   
   
   
   
   cd();
   TString opt = mode;
   opt.ToUpper();
   if (opt != "READ" && opt != "UPDATE") {
      Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
      return 1;
   }
   if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
      return 1;
   if (opt == "READ") {
      
      
      if (IsOpen() && IsWritable()) {
         WriteStreamerInfo();
         
         Save();
         TFree *f1 = (TFree*)fFree->First();
         if (f1) {
            WriteFree();       
            WriteHeader();     
         }
         FlushWriteCache();
         
         if (fFree) {
            fFree->Delete();
            SafeDelete(fFree);
         }
         SysClose(fD);
         fD = -1;
         SetWritable(kFALSE);
      }
      
      fOption = opt;    
#ifndef WIN32
      fD = SysOpen(fRealName, O_RDONLY, 0644);
#else
      fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
#endif
      if (fD == -1) {
         SysError("ReOpen", "file %s can not be opened in read mode", GetName());
         return -1;
      }
      SetWritable(kFALSE);
   } else {
      
      
      if (IsOpen()) {
         SysClose(fD);
         fD = -1;
      }
      
      fOption = opt;    
#ifndef WIN32
      fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0644);
#else
      fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
#endif
      if (fD == -1) {
         SysError("ReOpen", "file %s can not be opened in update mode", GetName());
         return -1;
      }
      SetWritable(kTRUE);
      fFree = new TList;
      if (fSeekFree > fBEGIN)
         ReadFree();
      else
         Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
   }
   return 0;
}
void TFile::Seek(Long64_t offset, ERelativeTo pos)
{
   
   int whence = 0;
   switch (pos) {
      case kBeg:
         whence = SEEK_SET;
         offset += fArchiveOffset;
         break;
      case kCur:
         whence = SEEK_CUR;
         break;
      case kEnd:
         whence = SEEK_END;
         
         if (fArchiveOffset)
            Error("Seek", "seeking from end in archive is not (yet) supported");
         break;
   }
   Long64_t retpos;
   if ((retpos = SysSeek(fD, offset, whence)) < 0)
      SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
               offset, GetName(), retpos);
   
   fOffset = retpos;
}
void TFile::SetCompressionLevel(Int_t level)
{
   
   
   
   
   
   
   
   
   
   
   
   
   if (level < 0) level = 0;
   if (level > 9) level = 9;
   fCompress = level;
}
void TFile::SetCacheRead(TFileCacheRead *cache)
{
   
   fCacheRead = cache;
}
void TFile::SetCacheWrite(TFileCacheWrite *cache)
{
   
   
   if (!cache && fCacheWrite) delete fCacheWrite;
   fCacheWrite = cache;
}
Int_t TFile::Sizeof() const
{
   
   return 0;
}
void TFile::Streamer(TBuffer &b)
{
   
   if (b.IsReading()) {
      b.ReadVersion();  
   } else {
      b.WriteVersion(TFile::IsA());
   }
}
void TFile::SumBuffer(Int_t bufsize)
{
   
   fWritten++;
   fSumBuffer  += bufsize;
   fSum2Buffer += bufsize*bufsize;
}
void TFile::UseCache(Int_t , Int_t )
{
   
   
   
   
}
Int_t TFile::Write(const char *, Int_t opt, Int_t bufsiz)
{
   
   
   
   
   
   
   
   
   
   if (!IsWritable()) {
      if (!TestBit(kWriteError)) {
         
         Warning("Write", "file %s not opened in write mode", GetName());
      }
      return 0;
   }
   TDirectory *cursav = gDirectory;
   cd();
   if (gDebug) {
      if (!GetTitle() || strlen(GetTitle()) == 0)
         Info("Write", "writing name = %s", GetName());
      else
         Info("Write", "writing name = s title = %s", GetName(), GetTitle());
   }
   fMustFlush = kFALSE;
   Int_t nbytes = TDirectoryFile::Write(0, opt, bufsiz); 
   WriteStreamerInfo();
   WriteFree();                       
   WriteHeader();                     
   fMustFlush = kTRUE;
   cursav->cd();
   return nbytes;
}
Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
{
   
   Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
   return const_cast<TFile*>(this)->Write(n, opt, bufsize);
}
Bool_t TFile::WriteBuffer(const char *buf, Int_t len)
{
   
   
   if (IsOpen() && fWritable) {
      Int_t st;
      if ((st = WriteBufferViaCache(buf, len))) {
         if (st == 2)
            return kTRUE;
         return kFALSE;
      }
      ssize_t siz;
      gSystem->IgnoreInterrupt();
      while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR)
         ResetErrno();
      gSystem->IgnoreInterrupt(kFALSE);
      if (siz < 0) {
         
         SetBit(kWriteError); SetWritable(kFALSE);
         SysError("WriteBuffer", "error writing to file %s (%d)", GetName(), siz);
         return kTRUE;
      }
      if (siz != len) {
         SetBit(kWriteError);
         Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %d of %d",
               GetName(), siz, len);
         return kTRUE;
      }
      fBytesWrite  += siz;
      fgBytesWrite += siz;
      return kFALSE;
   }
   return kTRUE;
}
Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len)
{
   
   
   if (!fCacheWrite) return 0;
   Int_t st;
   Long64_t off = GetRelOffset();
   if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
      SetBit(kWriteError);
      Error("WriteBuffer", "error writing to cache");
      return 2;
   }
   if (st > 0) {
      
      Seek(off + len);
      return 1;
   }
   return 0;
}
void TFile::WriteFree()
{
   
   
   
   
   if (fSeekFree != 0){
      MakeFree(fSeekFree, fSeekFree + fNbytesFree -1);
   }
   Int_t nbytes = 0;
   TFree *afree;
   TIter next (fFree);
   while ((afree = (TFree*) next())) {
      nbytes += afree->Sizeof();
   }
   if (!nbytes) return;
   TKey *key    = new TKey(fName,fTitle,IsA(),nbytes,this);
   if (key->GetSeekKey() == 0) {
      delete key;
      return;
   }
   char *buffer = key->GetBuffer();
   next.Reset();
   while ((afree = (TFree*) next())) {
      afree->FillBuffer(buffer);
   }
   fNbytesFree = key->GetNbytes();
   fSeekFree   = key->GetSeekKey();
   key->WriteFile();
   delete key;
}
void TFile::WriteHeader()
{
   
   SafeDelete(fInfoCache);
   TFree *lastfree = (TFree*)fFree->Last();
   if (lastfree) fEND  = lastfree->GetFirst();
   const char *root = "root";
   char *psave  = new char[fBEGIN];
   char *buffer = psave;
   Int_t nfree  = fFree->GetSize();
   memcpy(buffer, root, 4); buffer += 4;
   Int_t version = fVersion;
   if (fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
   tobuf(buffer, version);
   tobuf(buffer, (Int_t)fBEGIN);
   if (version < 1000000) {
      tobuf(buffer, (Int_t)fEND);
      tobuf(buffer, (Int_t)fSeekFree);
      tobuf(buffer, fNbytesFree);
      tobuf(buffer, nfree);
      tobuf(buffer, fNbytesName);
      tobuf(buffer, fUnits);
      tobuf(buffer, fCompress);
      tobuf(buffer, (Int_t)fSeekInfo);
      tobuf(buffer, fNbytesInfo);
   } else {
      tobuf(buffer, fEND);
      tobuf(buffer, fSeekFree);
      tobuf(buffer, fNbytesFree);
      tobuf(buffer, nfree);
      tobuf(buffer, fNbytesName);
      tobuf(buffer, fUnits);
      tobuf(buffer, fCompress);
      tobuf(buffer, fSeekInfo);
      tobuf(buffer, fNbytesInfo);
   }
   fUUID.FillBuffer(buffer);
   Int_t nbytes  = buffer - psave;
   Seek(0);
   WriteBuffer(psave, nbytes);
   Flush();
   delete [] psave;
}
void TFile::MakeProject(const char *dirname, const char * ,
                        Option_t *option)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   TString opt = option;
   opt.ToLower();
   void *dir = gSystem->OpenDirectory(dirname);
   char *path = new char[4000];
   if (opt.Contains("update")) {
      
      if (dir == 0) {
         gSystem->mkdir(dirname);
      }
   } else if (opt.Contains("recreate")) {
      
      if (dir == 0) {
         gSystem->mkdir(dirname);
      }
      
      while (dir) {
         const char *afile = gSystem->GetDirEntry(dir);
         if (afile == 0) break;
         if (strcmp(afile,".") == 0) continue;
         if (strcmp(afile,"..") == 0) continue;
         sprintf(path,"%s/%s",dirname,afile);
         gSystem->Unlink(path);
      }
   } else {
      
      
      if (dir) {
         Error("MakeProject","cannot create directory %s, already existing",dirname);
         delete [] path;
         return;
      }
      gSystem->mkdir(dirname);
   }
   
   
   TList *list = 0;
   if (fSeekInfo) {
      TKey *key = new TKey(this);
      char *buffer = new char[fNbytesInfo+1];
      char *buf    = buffer;
      Seek(fSeekInfo);
      ReadBuffer(buf,fNbytesInfo);
      key->ReadKeyBuffer(buf);
      list = (TList*)key->ReadObj();
      delete [] buffer;
      delete key;
   } else {
      list = (TList*)Get("StreamerInfo"); 
   }
   if (list == 0) {
      Error("MakeProject","file %s has no StreamerInfo", GetName());
      delete [] path;
      return;
   }
   
   TStreamerInfo *info;
   TIter next(list);
   Int_t ngener = 0;
   while ((info = (TStreamerInfo*)next())) {
      ngener += info->GenerateHeaderFile(dirname);
   }
   list->Delete();
   delete list;
   printf("MakeProject has generated %d classes in %s\n",ngener,dirname);
   
   if (!opt.Contains("+")) { delete [] path; return;}
   
   
#ifdef WIN32
   sprintf(path,"%s/make.cmd",dirname);
#else
   sprintf(path,"%s/MAKE",dirname);
#endif
#ifdef R__WINGCC
   FILE *fpMAKE = fopen(path,"wb");
#else
   FILE *fpMAKE = fopen(path,"w");
#endif
   if (!fpMAKE) {
      Error("MakeProject", "cannot open file %s", path);
      delete [] path;
      return;
   }
   
   fprintf(fpMAKE,"rootcint -f %sProjectDict.cxx -c %s ",dirname,gSystem->GetIncludePath());
   
   
   sprintf(path,"%s/LinkDef.h",dirname);
#ifdef R__WINGCC
   FILE *fp = fopen(path,"wb");
#else
   FILE *fp = fopen(path,"w");
#endif
   if (!fp) {
      Error("MakeProject", "cannot open path file %s", path);
      delete [] path;
      return;
   }
   fprintf(fp,"#ifdef __CINT__\n");
   fprintf(fp,"#pragma link off all globals;\n");
   fprintf(fp,"#pragma link off all classes;\n");
   fprintf(fp,"#pragma link off all functions;\n");
   fprintf(fp,"\n");
   dir = gSystem->OpenDirectory(dirname);
   while (dir) {
      const char *afile = gSystem->GetDirEntry(dir);
      if (afile == 0) break;
      if(strcmp(afile,"LinkDef.h") == 0) continue;
      if(strstr(afile,"ProjectDict.h") != 0) continue;
      strcpy(path,afile);
      char *h = strstr(path,".h");
      if (!h) continue;
      *h = 0;
      fprintf(fp,"#pragma link C++ class %s+;\n",path);
      if (strstr(afile,"<")) continue; 
      fprintf(fpMAKE,"%s ",afile);
   }
   fprintf(fp,"#endif\n");
   fclose(fp);
   fprintf(fpMAKE,"LinkDef.h \n");
   
   TString sdirname(dirname);
   TString cmd = gSystem->GetMakeSharedLib();
   cmd.ReplaceAll("$SourceFiles",sdirname+"ProjectDict.cxx");
   cmd.ReplaceAll("$ObjectFiles",sdirname+"ProjectDict."+gSystem->GetObjExt());
   cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + dirname);
   cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
   cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
   cmd.ReplaceAll("$LibName",sdirname);
   cmd.ReplaceAll("$BuildDir",".");
   fprintf(fpMAKE,"%s\n",cmd.Data());
   fclose(fpMAKE);
   printf("%s/MAKE file has been generated\n",dirname);
   
   strcpy(path,gSystem->WorkingDirectory());
   gSystem->ChangeDirectory(dirname);
#ifndef WIN32
   gSystem->Exec("chmod +x MAKE");
#else
   
   chmod("make.cmd",00700);
#endif
   int res = !gSystem->Exec("MAKE");
   gSystem->ChangeDirectory(path);
   sprintf(path,"%s/%s.%s",dirname,dirname,gSystem->GetSoExt());
   if (res) printf("Shared lib %s has been generated\n",path);
   
   if (opt.Contains("++")) {
      res = !gSystem->Load(path);
      if (res) printf("Shared lib %s has been dynamically linked\n",path);
   }
   delete [] path;
}
void TFile::ReadStreamerInfo()
{
   
   
   
   
   
   TList *list = GetStreamerInfoList();
   if (!list) {
      MakeZombie();
      return;
   }
   list->SetOwner(kFALSE);
   if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
   
   TStreamerInfo *info;
   TIter next(list);
   while ((info = (TStreamerInfo*)next())) {
      if (info->IsA() != TStreamerInfo::Class()) {
         Warning("ReadStreamerInfo","%s: not a TStreamerInfo object", GetName());
         continue;
      }
      info->BuildCheck();
      Int_t uid = info->GetNumber();
      Int_t asize = fClassIndex->GetSize();
      if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
      if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
      else {
         printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
      }
      if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
   }
   fClassIndex->fArray[0] = 0;
   list->Clear();  
   delete list;
}
void TFile::SetReadStreamerInfo(Bool_t readinfo)
{
   
   
   
   
   
   
   
   
   fgReadInfo = readinfo;
}
void TFile::ShowStreamerInfo()
{
   
   TList *list = GetStreamerInfoList();
   if (!list) return;
   list->ls();
   delete list;
}
UShort_t TFile::WriteProcessID(TProcessID *pidd)
{
   
   
   TProcessID *pid = pidd;
   if (!pid) pid = TProcessID::GetPID();
   TObjArray *pids = GetListOfProcessIDs();
   Int_t npids = GetNProcessIDs();
   for (Int_t i=0;i<npids;i++) {
      if (pids->At(i) == pid) return (UShort_t)i;
   }
   TDirectory *dirsav = gDirectory;
   this->cd();
   this->SetBit(TFile::kHasReferences);
   pids->AddAtAndExpand(pid,npids);
   pid->IncrementCount();
   char name[32];
   sprintf(name,"ProcessID%d",npids);
   pid->Write(name);
   this->IncrementProcessIDs();
   if (gDebug > 0) {
      printf("WriteProcessID, name=%s, file=%s\n",name,GetName());
   }
   if (dirsav) dirsav->cd();
   return (UShort_t)npids;
}
void TFile::WriteStreamerInfo()
{
   
   
   
   
   if (!fWritable) return;
   if (!fClassIndex) return;
   
   if (fClassIndex->fArray[0] == 0) return;
   if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
   SafeDelete(fInfoCache);
   
   TIter next(gROOT->GetListOfStreamerInfo());
   TStreamerInfo *info;
   TList list;
   while ((info = (TStreamerInfo*)next())) {
      Int_t uid = info->GetNumber();
      if (fClassIndex->fArray[uid]) list.Add(info);
      if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
   }
   if (list.GetSize() == 0) return;
   fClassIndex->fArray[0] = 2; 
   
   Int_t compress = fCompress;
   fCompress = 1;
   TFile * fileSave = gFile;
   TDirectory *dirSave = gDirectory;
   gFile = this;
   gDirectory = this;
   
   if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
   
   TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
   fKeys->Remove(&key);
   fSeekInfo   = key.GetSeekKey();
   fNbytesInfo = key.GetNbytes();
   SumBuffer(key.GetObjlen());
   key.WriteFile(0);
   fClassIndex->fArray[0] = 0;
   gFile = fileSave;
   gDirectory = dirSave;
   fCompress = compress;
}
TFile *TFile::Open(const char *name, Option_t *option, const char *ftitle,
                   Int_t compress, Int_t netopt)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   TPluginHandler *h;
   TFile *f = 0;
   if (!option) option = "";
   
   const char *defaultreadoption = "READ";
   if (!strcasecmp(option, "CACHEREAD") ||
       ((!strcasecmp(option,"READ") || !strlen(option)) && fgCacheFileForce)) {
      if (fgCacheFileDir == "") {
         ::Warning("TFile::Open", "you want to read through a cache, but you have no valid cache directory set - reading remotely");
         ::Info("TFile::Open", "set cache directory using TFile::SetCacheFileDir()");
         option = defaultreadoption;
      } else {
         TUrl fileurl(name);
         TUrl tagurl;
         if ((!strcmp(fileurl.GetProtocol(), "file"))) {
            
            if (!fgCacheFileForce)
               ::Warning("TFile::Open", "you want to read through a cache, but you are reading local files - CACHEREAD disabled");
            option = defaultreadoption;
         } else {
            
            
            TString cachefilepath;
            TString cachefilepathbasedir;
            cachefilepath = fgCacheFileDir;
            cachefilepath += fileurl.GetFile();
            cachefilepathbasedir = gSystem->DirName(cachefilepath);
            if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
                (gSystem->AccessPathName(cachefilepathbasedir, kFileExists))) {
               ::Warning("TFile::Open","you want to read through a cache, but I cannot create the directory %s - CACHEREAD disabled", cachefilepathbasedir.Data());
               option = defaultreadoption;
            } else {
               
               if (strlen(fileurl.GetAnchor())) {
                  
                  cachefilepath += "__";
                  cachefilepath += fileurl.GetAnchor();
                  fileurl.SetAnchor("");
               }
               if (strstr(name,"zip=")) {
                  
                  TString urloptions = fileurl.GetOptions();
                  TString newoptions;
                  TObjArray *objOptions = urloptions.Tokenize("&");
                  Int_t optioncount = 0;
                  TString zipname;
                  for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
                     TString loption = ((TObjString*)objOptions->At(n))->GetName();
                     TObjArray *objTags = loption.Tokenize("=");
                     if (objTags->GetEntries() == 2) {
                        TString key   = ((TObjString*)objTags->At(0))->GetName();
                        TString value = ((TObjString*)objTags->At(1))->GetName();
                        if (key.CompareTo("zip", TString::kIgnoreCase)) {
                           if (optioncount!=0) {
                              newoptions += "&";
                              newoptions += key;
                              newoptions += "=";
                              newoptions += value;
                              optioncount++;
                           }
                        } else {
                           zipname = value;
                        }
                     }
                     delete objTags;
                  }
                  delete objOptions;
                  fileurl.SetOptions(newoptions.Data());
                  cachefilepath += "__";
                  cachefilepath += zipname;
                  fileurl.SetAnchor("");
               }
               Bool_t need2copy = kFALSE;
               
               Long_t id;
               Long64_t size;
               Long_t flags;
               Long_t modtime;
               if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
                  
                  if (!fgCacheFileDisconnected) {
                     char cacheblock[256];
                     char remotblock[256];
                     
                     TString cfurl;
                     cfurl = cachefilepath;
                     cfurl += "?filetype=raw";
                     TUrl rurl(name);
                     TString ropt = rurl.GetOptions();
                     ropt += "&filetype=raw";
                     rurl.SetOptions(ropt);
                     TFile *cachefile = TFile::Open(cfurl, "READ");
                     TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
                     cachefile->Seek(0);
                     remotfile->Seek(0);
                     if (!cachefile) {
                        need2copy = kTRUE;
                        ::Error("TFile::Open", "cannot open the cache file to check cache consistency");
                     }
                     if (!remotfile) {
                        ::Error("TFile::Open", "cannot open the remote file to check cache consistency");
                        return 0;
                     }
                     if ((!cachefile->ReadBuffer(cacheblock,256)) && (!remotfile->ReadBuffer(remotblock,256))) {
                        if (memcmp(cacheblock, remotblock, 256)) {
                           ::Warning("TFile::Open", "the header of the cache file differs from the remote file - forcing an update");
                           need2copy = kTRUE;
                        }
                     } else {
                        ::Warning("TFile::Open", "the header of the cache and/or remote file are not readable - forcing an update");
                        need2copy = kTRUE;
                     }
                     delete remotfile;
                     delete cachefile;
                  }
               } else {
                  need2copy = kTRUE;
               }
               
               Bool_t forcedcache = fgCacheFileForce;
               fgCacheFileForce = kFALSE;
               if (need2copy && !TFile::Cp(name, cachefilepath)) {
                  ::Warning("TFile::Open", "you want to read through a cache, but I cannot make a cache copy of %s - CACHEREAD disabled", cachefilepathbasedir.Data());
                  option = defaultreadoption;
                  fgCacheFileForce = forcedcache;
                  if (fgOpenTimeout != 0)
                     return 0;
               } else {
                  fgCacheFileForce = forcedcache;
                  ::Info("TFile::Open", "using local cache copy of %s [%s]", name, cachefilepath.Data());
                  
                  fileurl.SetProtocol("file");
                  fileurl.SetFile(cachefilepath);
                  tagurl = fileurl;
                  TString tagfile;
                  tagfile = cachefilepath;
                  tagfile += ".ROOT.cachefile";
                  tagurl.SetFile(tagfile);
                  
                  gSystem->Symlink(cachefilepath, tagfile);
                  return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
               }
            }
         }
      }
   }
   IncrementFileCounter();
   
   
   TUrl urlname(name, kTRUE);
   name = urlname.GetUrl();
   
   if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
      TIter nxr(fgAsyncOpenRequests);
      TFileOpenHandle *fh = 0;
      while ((fh = (TFileOpenHandle *)nxr()))
         if (fh->Matches(name))
            return TFile::Open(fh);
   }
   
   EFileType type = GetType(name, option);
   if (type == kLocal) {
      
      urlname.SetHost("");
      urlname.SetProtocol("file");
      f = new TFile(urlname.GetUrl(), option, ftitle, compress);
   } else if (type == kNet) {
      
      if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
         if (h->LoadPlugin() == -1)
            return 0;
         f = (TFile*) h->ExecPlugin(5, name, option, ftitle, compress, netopt);
      }
   } else if (type == kWeb) {
      
      if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
         if (h->LoadPlugin() == -1)
            return 0;
         f = (TFile*) h->ExecPlugin(1, name);
      }
   } else if (type == kFile) {
      
      if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
          h->LoadPlugin() == 0)
         f = (TFile*) h->ExecPlugin(4, name+5, option, ftitle, compress);
      else
         f = new TFile(name, option, ftitle, compress);
   } else {
      
      if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
         if (h->LoadPlugin() == -1)
            return 0;
         TClass *cl = TClass::GetClass(h->GetClass());
         if (cl && cl->InheritsFrom("TNetFile"))
            f = (TFile*) h->ExecPlugin(5, name, option, ftitle, compress, netopt);
         else
            f = (TFile*) h->ExecPlugin(4, name, option, ftitle, compress);
      } else
         
         f = new TFile(name, option, ftitle, compress);
   }
   if (f && f->IsZombie()) {
      delete f;
      f = 0;
   }
   
   
   if (type != kLocal && type != kFile &&
       f && f->IsWritable() && !f->IsRaw()) {
      new TFileCacheWrite(f, 1);
   }
   if (gMonitoringWriter && (!f->IsWritable()))
      gMonitoringWriter->SendFileReadProgress(f,true);
   return f;
}
TFileOpenHandle *TFile::AsyncOpen(const char *name, Option_t *option,
                                  const char *ftitle, Int_t compress,
                                  Int_t netopt)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   TFileOpenHandle *fh = 0;
   TPluginHandler *h;
   TFile *f = 0;
   Bool_t notfound = kTRUE;
   
   
   TUrl urlname(name, kTRUE);
   name = urlname.GetUrl();
   
   EFileType type = GetType(name, option);
   
   if (type == kNet) {
      
      if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
           !strcmp(h->GetClass(),"TXNetFile") && h->LoadPlugin() == 0) {
         f = (TFile*) h->ExecPlugin(6, name, option, ftitle, compress, netopt, kTRUE);
         notfound = kFALSE;
      }
   }
   if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
        !strcmp(h->GetClass(),"TAlienFile") && h->LoadPlugin() == 0) {
      f = (TFile*) h->ExecPlugin(5, name, option, ftitle, compress, kTRUE);
      notfound = kFALSE;
   }
   
   if (notfound) {
      SafeDelete(f);
      
      
      fh = new TFileOpenHandle(name, option, ftitle, compress, netopt);
   } else if (f) {
      
      fh = new TFileOpenHandle(f);
   }
   
   if (fh) {
      
      if (!fgAsyncOpenRequests)
         fgAsyncOpenRequests = new TList;
      fgAsyncOpenRequests->Add(fh);
   }
   
   return fh;
}
TFile *TFile::Open(TFileOpenHandle *fh)
{
   
   
   
   TFile *f = 0;
   
   if (fh && fgAsyncOpenRequests) {
      
      if ((f = fh->GetFile()) && !(f->IsZombie())) {
         
         Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
                      !strcmp(f->GetOption(),"RECREATE") ||
                      !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
         f->Init(cr);
      } else {
         
         f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
                         fh->GetCompress(), fh->GetNetOpt());
      }
      
      
      f->fAsyncHandle = fh;
      
      fgAsyncOpenRequests->Remove(fh);
   }
   
   return f;
}
Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
{
   
#if defined(R__WINGCC)
   
   
   return ::open(pathname, flags | O_BINARY, mode);
#elif defined(R__SEEK64)
   return ::open64(pathname, flags, mode);
#else
   return ::open(pathname, flags, mode);
#endif
}
Int_t TFile::SysClose(Int_t fd)
{
   
   return ::close(fd);
}
Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
{
   
   return ::read(fd, buf, len);
}
Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
{
   
   return ::write(fd, buf, len);
}
Long64_t TFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
{
   
   
   
#if defined (R__SEEK64)
   return ::lseek64(fd, offset, whence);
#elif defined(WIN32)
   return ::_lseeki64(fd, offset, whence);
#else
   return ::lseek(fd, offset, whence);
#endif
}
Int_t TFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags,
                     Long_t *modtime)
{
   
   
   
   return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
}
Int_t TFile::SysSync(Int_t fd)
{
   
   if (TestBit(kDevNull)) return 0;
#ifndef WIN32
   return ::fsync(fd);
#else
   return ::_commit(fd);
#endif
}
Long64_t TFile::GetBytesWritten() const
{
   
   return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
}
Long64_t TFile::GetFileBytesRead()
{
   
   return fgBytesRead;
}
Long64_t TFile::GetFileBytesWritten()
{
   
   
   return fgBytesWrite;
}
Int_t TFile::GetFileReadCalls()
{
   
   return fgReadCalls;
}
void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
Long64_t TFile::GetFileCounter() { return fgFileCounter; }
void TFile::IncrementFileCounter() { fgFileCounter++; }
Bool_t TFile::SetCacheFileDir(const char *cachedir, Bool_t operatedisconnected,
                              Bool_t forcecacheread )
{
   
   
   TString cached = cachedir;
   if (!cached.EndsWith("/"))
      cached += "/";
   if ((gSystem->Chmod(cached, 0700)) < 0) {
      
      gSystem->mkdir(cached, kTRUE);
      if (gSystem->AccessPathName(cached, kFileExists)) {
         ::Error("TFile::SetCacheFileDir", "no suffcient permissions on cache directory %s or cannot create it", cachedir);
         fgCacheFileDir = "";
         return kFALSE;
      }
      gSystem->Chmod(cached, 0700);
   }
   fgCacheFileDir          = cached;
   fgCacheFileDisconnected = operatedisconnected;
   fgCacheFileForce        = forcecacheread;
   return kTRUE;
}
const char *TFile::GetCacheFileDir()
{
   
   return fgCacheFileDir;
}
Bool_t TFile::ShrinkCacheFileDir(Long64_t shrinksize, Long_t cleanupinterval)
{
   
   
   
   
   char cmd[4096];
   if (fgCacheFileDir == "") {
      return kFALSE;
   }
   
   Long_t id;
   Long64_t size;
   Long_t flags;
   Long_t modtime;
   TString cachetagfile = fgCacheFileDir;
   cachetagfile += ".tag.ROOT.cache";
   if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
      
      Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
      if (lastcleanuptime < cleanupinterval) {
         ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
         return kTRUE;
      }
   }
   
   cachetagfile += "?filetype=raw";
   TFile *tagfile = 0;
   if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
      ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
      return kFALSE;
   }
   
   
#if defined(R__WIN32)
   sprintf(cmd, "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented");
#elif defined(R__MACOSX)
   sprintf(cmd, "perl -e 'my $cachepath = \"%s\"; my $cachesize = %lld;my $findcommand=\"find $cachepath -type f -exec stat -f \\\"\\%%a::\\%%N::\\%%z\\\" \\{\\} \\\\\\;\";my $totalsize=0;open FIND, \"$findcommand | sort -k 1 |\";while (<FIND>) { my ($accesstime, $filename, $filesize) = split \"::\",$_; $totalsize += $filesize;if ($totalsize > $cachesize) {if ( ( -e \"${filename}.ROOT.cachefile\" ) && ( -e \"${filename}\" ) ) {unlink \"$filename.ROOT.cachefile\";unlink \"$filename\";}}}close FIND;' ", fgCacheFileDir.Data(),shrinksize);
#else
   sprintf(cmd, "perl -e 'my $cachepath = \"%s\"; my $cachesize = %lld;my $findcommand=\"find $cachepath -type f -exec stat -c \\\"\\%%x::\\%%n::\\%%s\\\" \\{\\} \\\\\\;\";my $totalsize=0;open FIND, \"$findcommand | sort -k 1 |\";while (<FIND>) { my ($accesstime, $filename, $filesize) = split \"::\",$_; $totalsize += $filesize;if ($totalsize > $cachesize) {if ( ( -e \"${filename}.ROOT.cachefile\" ) && ( -e \"${filename}\" ) ) {unlink \"$filename.ROOT.cachefile\";unlink \"$filename\";}}}close FIND;' ", fgCacheFileDir.Data(),shrinksize);
#endif
   tagfile->WriteBuffer(cmd, 4096);
   delete tagfile;
   if ((gSystem->Exec(cmd)) != 0) {
      ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
      return kFALSE;
   }
   return kTRUE;
}
UInt_t TFile::SetOpenTimeout(UInt_t timeout)
{
   
   UInt_t to = fgOpenTimeout;
   fgOpenTimeout = timeout;
   return to;
}
UInt_t TFile::GetOpenTimeout()
{
   
   return fgOpenTimeout;
}
Bool_t TFile::SetOnlyStaged(Bool_t onlystaged)
{
   
   
   
   Bool_t f = fgOnlyStaged;
   fgOnlyStaged = onlystaged;
   return f;
}
Bool_t TFile::GetOnlyStaged()
{
   
   return fgOnlyStaged;
}
Bool_t TFile::Matches(const char *url)
{
   
   
   
   
   
   TUrl u(url);
   
   if (!strcmp(u.GetFile(), fUrl.GetFile())) {
      
      if (u.GetPort() == fUrl.GetPort()) {
         if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
            
            return kTRUE;
         }
      }
   }
   
   return kFALSE;
}
Bool_t TFileOpenHandle::Matches(const char *url)
{
   
   
   if (fFile) {
      return fFile->Matches(url);
   } else if (fName.Length() > 0){
      
      TUrl u(url);
      TUrl uref(fName);
      if (!strcmp(u.GetFile(), uref.GetFile())) {
         
         if (u.GetPort() == uref.GetPort()) {
            
            if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
               
               return kTRUE;
            }
         }
      }
   }
   
   return kFALSE;
}
TFile::EFileType TFile::GetType(const char *name, Option_t *option)
{
   
   EFileType type = kDefault;
   TRegexp re("^root.*:");
   TString sname = name;
   if (sname.Index(re) != kNPOS) {
      
      
      type = kNet;
      
      
      
      
      
      
      const char *lfname = 0;
      Bool_t localFile = kFALSE;
      TUrl url(name);
      
      
      Bool_t forceRemote = gEnv->GetValue("TFile.ForceRemote", 0);
      TString opts = url.GetOptions();
      if (opts.Contains("remote=1"))
         forceRemote = kTRUE;
      else if (opts.Contains("remote=0"))
         forceRemote = kFALSE;
      if (!forceRemote) {
         TInetAddress a(gSystem->GetHostByName(url.GetHost()));
         TInetAddress b(gSystem->GetHostByName(gSystem->HostName()));
         if (!strcmp(a.GetHostName(), b.GetHostName())) {
            Bool_t read = kFALSE;
            TString opt = option;
            opt.ToUpper();
            if (opt == "" || opt == "READ") read = kTRUE;
            const char *fname = url.GetFile();
            if (fname[0] == '/' || fname[0] == '~' || fname[0] == '$')
               lfname = fname;
            else
               lfname = Form("%s/%s", gSystem->HomeDirectory(), fname);
            if (read) {
               char *fn;
               if ((fn = gSystem->ExpandPathName(lfname))) {
                  if (gSystem->AccessPathName(fn, kReadPermission))
                     read = kFALSE;
                  delete [] fn;
               }
            }
            Bool_t sameUser = kFALSE;
            UserGroup_t *u = gSystem->GetUserInfo();
            if (u && !strcmp(u->fUser, url.GetUser()))
               sameUser = kTRUE;
            delete u;
            if (read || sameUser)
               localFile = kTRUE;
         }
      }
      
      
      type = (localFile) ? kLocal : type;
   } else if (!strncmp(name, "http:", 5)) {
      
      
      type = kWeb;
   } else if (!strncmp(name, "file:", 5)) {
      
      
      type = kFile;
   }
   
   return type;
}
TFile::EAsyncOpenStatus TFile::GetAsyncOpenStatus(const char* name)
{
   
   
   if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
      TIter nxr(fgAsyncOpenRequests);
      TFileOpenHandle *fh = 0;
      while ((fh = (TFileOpenHandle *)nxr()))
         if (fh->Matches(name))
            return TFile::GetAsyncOpenStatus(fh);
   }
   
   TSeqCollection *of = gROOT->GetListOfFiles();
   if (of && (of->GetSize() > 0)) {
      TIter nxf(of);
      TFile *f = 0;
      while ((f = (TFile *)nxf()))
         if (f->Matches(name))
            return f->GetAsyncOpenStatus();
   }
   
   return kAOSNotAsync;
}
TFile::EAsyncOpenStatus TFile::GetAsyncOpenStatus(TFileOpenHandle *handle)
{
   
   if (handle && handle->fFile)
      if (!handle->fFile->IsZombie())
         return handle->fFile->GetAsyncOpenStatus();
      else
         return TFile::kAOSFailure;
   
   return TFile::kAOSNotAsync;
}
const TUrl *TFile::GetEndpointUrl(const char* name)
{
   
   
   
   if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
      TIter nxr(fgAsyncOpenRequests);
      TFileOpenHandle *fh = 0;
      while ((fh = (TFileOpenHandle *)nxr()))
         if (fh->Matches(name))
            if (fh->fFile)
               return fh->fFile->GetEndpointUrl();
   }
   
   TSeqCollection *of = gROOT->GetListOfFiles();
   if (of && (of->GetSize() > 0)) {
      TIter nxf(of);
      TFile *f = 0;
      while ((f = (TFile *)nxf()))
         if (f->Matches(name))
            return f->GetEndpointUrl();
   }
   
   return (const TUrl *)0;
}
void TFile::CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
{
   
   fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
   for (int l = 0; l < 20; l++) {
      if (size > 0) {
         if (l < 20*bytesread/size)
            fprintf(stderr, "=");
         else if (l == 20*bytesread/size)
            fprintf(stderr, ">");
         else if (l > 20*bytesread/size)
            fprintf(stderr, ".");
      } else
         fprintf(stderr, "=");
   }
   
   gSystem->ProcessEvents();
   watch.Stop();
   Double_t lCopy_time = watch.RealTime();
   fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
           100.0*(size?(bytesread/size):1), bytesread/lCopy_time/1048576.);
   watch.Continue();
}
Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
                 UInt_t buffersize)
{
   
   
   TStopwatch watch;
   Bool_t success = kFALSE;
   TUrl sURL(src, kTRUE);
   TUrl dURL(dst, kTRUE);
   TString oopt = "RECREATE";
   TString ourl = dURL.GetUrl();
   TString raw = "filetype=raw";
   TString opt = sURL.GetOptions();
   if (opt == "")
      opt = raw;
   else
      opt += "&&" + raw;
   sURL.SetOptions(opt);
   opt = dURL.GetOptions();
   if (opt == "")
      opt = raw;
   else
      opt += "&&" + raw;
   dURL.SetOptions(opt);
   char *copybuffer = 0;
   TFile *sfile = 0;
   TFile *dfile = 0;
   sfile = TFile::Open(sURL.GetUrl(), "READ");
   if (!sfile) {
      ::Error("TFile::Cp", "cannot open source file %s", src);
      goto copyout;
   }
   
   
   
   if (TFile::GetType(ourl, "") == TFile::kNet)
      if (gSystem->AccessPathName(ourl)) {
         oopt = "NEW";
         
         opt += "&mkpath=1";
         dURL.SetOptions(opt);
      }
   dfile = TFile::Open(dURL.GetUrl(), oopt);
   if (!dfile) {
      ::Error("TFile::Cp", "cannot open destination file %s", dst);
      goto copyout;
   }
   sfile->Seek(0);
   dfile->Seek(0);
   copybuffer = new char[buffersize];
   if (!copybuffer) {
      ::Error("TFile::Cp", "cannot allocate the copy buffer");
      goto copyout;
   }
   Bool_t   readop;
   Bool_t   writeop;
   Long64_t read;
   Long64_t written;
   Long64_t totalread;
   Long64_t filesize;
   Long64_t b00;
   filesize  = sfile->GetSize();
   totalread = 0;
   watch.Start();
   b00 = sfile->GetBytesRead();
   do {
      if (progressbar) CpProgress(totalread, filesize,watch);
      Long64_t b1 = sfile->GetBytesRead() - b00;
      Long64_t readsize;
      if (filesize - b1 > (Long64_t)buffersize) {
         readsize = buffersize;
      } else {
         readsize = filesize - b1;
      }
      Long64_t b0 = sfile->GetBytesRead();
      sfile->Seek(totalread,TFile::kBeg);
      readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
      read   = sfile->GetBytesRead() - b0;
      if (read < 0) {
         ::Error("TFile::Cp", "cannot read from source file %s", src);
         goto copyout;
      }
      Long64_t w0 = dfile->GetBytesWritten();
      writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
      written = dfile->GetBytesWritten() - w0;
      if (written != read) {
         ::Error("TFile::Cp", "cannot write %d bytes to destination file %s", read, dst);
         goto copyout;
      }
      totalread += read;
   } while (read == (Long64_t)buffersize);
   if (progressbar) {
      CpProgress(totalread, filesize,watch);
      fprintf(stderr, "\n");
   }
   success = kTRUE;
copyout:
   if (sfile) sfile->Close();
   if (dfile) dfile->Close();
   if (sfile) delete sfile;
   if (dfile) delete dfile;
   if (copybuffer) delete[] copybuffer;
   watch.Stop();
   watch.Reset();
   return success;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.