ROOT logo
// @(#)root/io:$Id$
// Author: Rene Brun   18/05/2006

/*************************************************************************
 * 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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TFileCacheWrite : a cache when writing files over the network        //
//                                                                      //
// A caching system to speed up network I/O, i.e. when there is         //
// no operating system caching support (like the buffer cache for       //
// local disk I/O). The cache makes sure that every I/O is done with    //
// a (large) fixed length buffer thereby avoiding many small I/O's.     //
// Currently the write cache system is used by the classes TNetFile,    //
// TXNetFile and TWebFile (via TFile::WriteBuffers()).                  //
//                                                                      //
// The write cache is automatically created when writing a remote file  //
// (created in TFile::Open()).                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


#include "TFile.h"
#include "TFileCacheWrite.h"

ClassImp(TFileCacheWrite)

//______________________________________________________________________________
TFileCacheWrite::TFileCacheWrite() : TObject()
{
   // Default Constructor.

   fBufferSize  = 0;
   fNtot        = 0;
   fSeekStart   = 0;
   fFile        = 0;
   fBuffer      = 0;
   fRecursive   = kFALSE;
}

//_____________________________________________________________________________
TFileCacheWrite::TFileCacheWrite(TFile *file, Int_t buffersize)
           : TObject()
{
   // Creates a TFileCacheWrite data structure.
   // The write cache will be connected to file.
   // The size of the cache will be buffersize,
   // if buffersize < 10000 a default size of 512 Kbytes is used

   if (buffersize < 10000) buffersize = 512000;
   fBufferSize  = buffersize;
   fSeekStart   = 0;
   fNtot        = 0;
   fFile        = file;
   fRecursive   = kFALSE;
   fBuffer      = new char[fBufferSize];
   if (file) file->SetCacheWrite(this);
   if (gDebug > 0) Info("TFileCacheWrite","Creating a write cache with buffersize=%d bytes",buffersize);
}

//_____________________________________________________________________________
TFileCacheWrite::~TFileCacheWrite()
{
   // Destructor.

   delete [] fBuffer;
}

//_____________________________________________________________________________
Bool_t TFileCacheWrite::Flush()
{
   // Flush the current write buffer to the file.
   // Returns kTRUE in case of error.

   if (!fNtot) return kFALSE;
   fFile->Seek(fSeekStart);
   //printf("Flushing buffer at fSeekStart=%lld, fNtot=%d\n",fSeekStart,fNtot);
   fRecursive = kTRUE;
   Bool_t status = fFile->WriteBuffer(fBuffer, fNtot);
   fRecursive = kFALSE;
   fNtot = 0;
   return status;
}

//_____________________________________________________________________________
void TFileCacheWrite::Print(Option_t *option) const
{
   // Print class internal structure.

   TString opt = option;
   printf("Write cache for file %s\n",fFile->GetName());
   printf("Size of write cache: %d bytes to be written at %lld\n",fNtot,fSeekStart);
   opt.ToLower();
}

//_____________________________________________________________________________
Int_t TFileCacheWrite::ReadBuffer(char *buf, Long64_t pos, Int_t len)
{
   // Called by the read cache to check if the requested data is not
   // in the write cache buffer.
   //        Returns -1 if data not in write cache,
   //        0 otherwise.

   if (pos < fSeekStart || pos+len > fSeekStart+fNtot) return -1;
   memcpy(buf,fBuffer+pos-fSeekStart,len);
   return 0;
}

//_____________________________________________________________________________
Int_t TFileCacheWrite::WriteBuffer(const char *buf, Long64_t pos, Int_t len)
{
   // Write buffer at position pos in the write buffer.
   // The function returns 1 if the buffer has been successfully entered into the write buffer.
   // The function returns 0 in case WriteBuffer() was recusively called via Flush().
   // The function returns -1 in case of error.

   if (fRecursive) return 0;

   //printf("TFileCacheWrite::WriteBuffer, pos=%lld, len=%d, fSeekStart=%lld, fNtot=%d\n",pos,len,fSeekStart,fNtot);

   if (fSeekStart + fNtot != pos) {
      //we must flush the current cache
      if (Flush()) return -1; //failure
   }
   if (fNtot + len >= fBufferSize) {
      if (Flush()) return -1; //failure
      if (len >= fBufferSize) {
         //buffer larger than the cache itself: direct write to file
         fRecursive = kTRUE;
         if (fFile->WriteBuffer(buf,len)) return -1;  // failure
         fRecursive = kFALSE;
         return 1;
      }
   }
   if (!fNtot) fSeekStart = pos;
   memcpy(fBuffer+fNtot,buf,len);
   fNtot += len;

   return 1;
}

//_____________________________________________________________________________
void TFileCacheWrite::SetFile(TFile *file)
{
   // Set the file using this cache.
   // Any write not yet flushed will be lost.

   fFile = file;
}
 TFileCacheWrite.cxx:1
 TFileCacheWrite.cxx:2
 TFileCacheWrite.cxx:3
 TFileCacheWrite.cxx:4
 TFileCacheWrite.cxx:5
 TFileCacheWrite.cxx:6
 TFileCacheWrite.cxx:7
 TFileCacheWrite.cxx:8
 TFileCacheWrite.cxx:9
 TFileCacheWrite.cxx:10
 TFileCacheWrite.cxx:11
 TFileCacheWrite.cxx:12
 TFileCacheWrite.cxx:13
 TFileCacheWrite.cxx:14
 TFileCacheWrite.cxx:15
 TFileCacheWrite.cxx:16
 TFileCacheWrite.cxx:17
 TFileCacheWrite.cxx:18
 TFileCacheWrite.cxx:19
 TFileCacheWrite.cxx:20
 TFileCacheWrite.cxx:21
 TFileCacheWrite.cxx:22
 TFileCacheWrite.cxx:23
 TFileCacheWrite.cxx:24
 TFileCacheWrite.cxx:25
 TFileCacheWrite.cxx:26
 TFileCacheWrite.cxx:27
 TFileCacheWrite.cxx:28
 TFileCacheWrite.cxx:29
 TFileCacheWrite.cxx:30
 TFileCacheWrite.cxx:31
 TFileCacheWrite.cxx:32
 TFileCacheWrite.cxx:33
 TFileCacheWrite.cxx:34
 TFileCacheWrite.cxx:35
 TFileCacheWrite.cxx:36
 TFileCacheWrite.cxx:37
 TFileCacheWrite.cxx:38
 TFileCacheWrite.cxx:39
 TFileCacheWrite.cxx:40
 TFileCacheWrite.cxx:41
 TFileCacheWrite.cxx:42
 TFileCacheWrite.cxx:43
 TFileCacheWrite.cxx:44
 TFileCacheWrite.cxx:45
 TFileCacheWrite.cxx:46
 TFileCacheWrite.cxx:47
 TFileCacheWrite.cxx:48
 TFileCacheWrite.cxx:49
 TFileCacheWrite.cxx:50
 TFileCacheWrite.cxx:51
 TFileCacheWrite.cxx:52
 TFileCacheWrite.cxx:53
 TFileCacheWrite.cxx:54
 TFileCacheWrite.cxx:55
 TFileCacheWrite.cxx:56
 TFileCacheWrite.cxx:57
 TFileCacheWrite.cxx:58
 TFileCacheWrite.cxx:59
 TFileCacheWrite.cxx:60
 TFileCacheWrite.cxx:61
 TFileCacheWrite.cxx:62
 TFileCacheWrite.cxx:63
 TFileCacheWrite.cxx:64
 TFileCacheWrite.cxx:65
 TFileCacheWrite.cxx:66
 TFileCacheWrite.cxx:67
 TFileCacheWrite.cxx:68
 TFileCacheWrite.cxx:69
 TFileCacheWrite.cxx:70
 TFileCacheWrite.cxx:71
 TFileCacheWrite.cxx:72
 TFileCacheWrite.cxx:73
 TFileCacheWrite.cxx:74
 TFileCacheWrite.cxx:75
 TFileCacheWrite.cxx:76
 TFileCacheWrite.cxx:77
 TFileCacheWrite.cxx:78
 TFileCacheWrite.cxx:79
 TFileCacheWrite.cxx:80
 TFileCacheWrite.cxx:81
 TFileCacheWrite.cxx:82
 TFileCacheWrite.cxx:83
 TFileCacheWrite.cxx:84
 TFileCacheWrite.cxx:85
 TFileCacheWrite.cxx:86
 TFileCacheWrite.cxx:87
 TFileCacheWrite.cxx:88
 TFileCacheWrite.cxx:89
 TFileCacheWrite.cxx:90
 TFileCacheWrite.cxx:91
 TFileCacheWrite.cxx:92
 TFileCacheWrite.cxx:93
 TFileCacheWrite.cxx:94
 TFileCacheWrite.cxx:95
 TFileCacheWrite.cxx:96
 TFileCacheWrite.cxx:97
 TFileCacheWrite.cxx:98
 TFileCacheWrite.cxx:99
 TFileCacheWrite.cxx:100
 TFileCacheWrite.cxx:101
 TFileCacheWrite.cxx:102
 TFileCacheWrite.cxx:103
 TFileCacheWrite.cxx:104
 TFileCacheWrite.cxx:105
 TFileCacheWrite.cxx:106
 TFileCacheWrite.cxx:107
 TFileCacheWrite.cxx:108
 TFileCacheWrite.cxx:109
 TFileCacheWrite.cxx:110
 TFileCacheWrite.cxx:111
 TFileCacheWrite.cxx:112
 TFileCacheWrite.cxx:113
 TFileCacheWrite.cxx:114
 TFileCacheWrite.cxx:115
 TFileCacheWrite.cxx:116
 TFileCacheWrite.cxx:117
 TFileCacheWrite.cxx:118
 TFileCacheWrite.cxx:119
 TFileCacheWrite.cxx:120
 TFileCacheWrite.cxx:121
 TFileCacheWrite.cxx:122
 TFileCacheWrite.cxx:123
 TFileCacheWrite.cxx:124
 TFileCacheWrite.cxx:125
 TFileCacheWrite.cxx:126
 TFileCacheWrite.cxx:127
 TFileCacheWrite.cxx:128
 TFileCacheWrite.cxx:129
 TFileCacheWrite.cxx:130
 TFileCacheWrite.cxx:131
 TFileCacheWrite.cxx:132
 TFileCacheWrite.cxx:133
 TFileCacheWrite.cxx:134
 TFileCacheWrite.cxx:135
 TFileCacheWrite.cxx:136
 TFileCacheWrite.cxx:137
 TFileCacheWrite.cxx:138
 TFileCacheWrite.cxx:139
 TFileCacheWrite.cxx:140
 TFileCacheWrite.cxx:141
 TFileCacheWrite.cxx:142
 TFileCacheWrite.cxx:143
 TFileCacheWrite.cxx:144
 TFileCacheWrite.cxx:145
 TFileCacheWrite.cxx:146
 TFileCacheWrite.cxx:147
 TFileCacheWrite.cxx:148
 TFileCacheWrite.cxx:149
 TFileCacheWrite.cxx:150
 TFileCacheWrite.cxx:151
 TFileCacheWrite.cxx:152
 TFileCacheWrite.cxx:153
 TFileCacheWrite.cxx:154
 TFileCacheWrite.cxx:155