00001 // @(#)root/io:$Id: TFileCacheWrite.cxx 23122 2008-04-10 14:56:30Z rdm $ 00002 // Author: Rene Brun 18/05/2006 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 ////////////////////////////////////////////////////////////////////////// 00013 // // 00014 // TFileCacheWrite : a cache when writing files over the network // 00015 // // 00016 // A caching system to speed up network I/O, i.e. when there is // 00017 // no operating system caching support (like the buffer cache for // 00018 // local disk I/O). The cache makes sure that every I/O is done with // 00019 // a (large) fixed length buffer thereby avoiding many small I/O's. // 00020 // Currently the write cache system is used by the classes TNetFile, // 00021 // TXNetFile and TWebFile (via TFile::WriteBuffers()). // 00022 // // 00023 // The write cache is automatically created when writing a remote file // 00024 // (created in TFile::Open()). // 00025 // // 00026 ////////////////////////////////////////////////////////////////////////// 00027 00028 00029 #include "TFile.h" 00030 #include "TFileCacheWrite.h" 00031 00032 ClassImp(TFileCacheWrite) 00033 00034 //______________________________________________________________________________ 00035 TFileCacheWrite::TFileCacheWrite() : TObject() 00036 { 00037 // Default Constructor. 00038 00039 fBufferSize = 0; 00040 fNtot = 0; 00041 fSeekStart = 0; 00042 fFile = 0; 00043 fBuffer = 0; 00044 fRecursive = kFALSE; 00045 } 00046 00047 //_____________________________________________________________________________ 00048 TFileCacheWrite::TFileCacheWrite(TFile *file, Int_t buffersize) 00049 : TObject() 00050 { 00051 // Creates a TFileCacheWrite data structure. 00052 // The write cache will be connected to file. 00053 // The size of the cache will be buffersize, 00054 // if buffersize < 10000 a default size of 512 Kbytes is used 00055 00056 if (buffersize < 10000) buffersize = 512000; 00057 fBufferSize = buffersize; 00058 fSeekStart = 0; 00059 fNtot = 0; 00060 fFile = file; 00061 fRecursive = kFALSE; 00062 fBuffer = new char[fBufferSize]; 00063 if (file) file->SetCacheWrite(this); 00064 if (gDebug > 0) Info("TFileCacheWrite","Creating a write cache with buffersize=%d bytes",buffersize); 00065 } 00066 00067 //_____________________________________________________________________________ 00068 TFileCacheWrite::~TFileCacheWrite() 00069 { 00070 // Destructor. 00071 00072 delete [] fBuffer; 00073 } 00074 00075 //_____________________________________________________________________________ 00076 Bool_t TFileCacheWrite::Flush() 00077 { 00078 // Flush the current write buffer to the file. 00079 // Returns kTRUE in case of error. 00080 00081 if (!fNtot) return kFALSE; 00082 fFile->Seek(fSeekStart); 00083 //printf("Flushing buffer at fSeekStart=%lld, fNtot=%d\n",fSeekStart,fNtot); 00084 fRecursive = kTRUE; 00085 Bool_t status = fFile->WriteBuffer(fBuffer, fNtot); 00086 fRecursive = kFALSE; 00087 fNtot = 0; 00088 return status; 00089 } 00090 00091 //_____________________________________________________________________________ 00092 void TFileCacheWrite::Print(Option_t *option) const 00093 { 00094 // Print class internal structure. 00095 00096 TString opt = option; 00097 printf("Write cache for file %s\n",fFile->GetName()); 00098 printf("Size of write cache: %d bytes to be written at %lld\n",fNtot,fSeekStart); 00099 opt.ToLower(); 00100 } 00101 00102 //_____________________________________________________________________________ 00103 Int_t TFileCacheWrite::ReadBuffer(char *buf, Long64_t pos, Int_t len) 00104 { 00105 // Called by the read cache to check if the requested data is not 00106 // in the write cache buffer. 00107 // Returns -1 if data not in write cache, 00108 // 0 otherwise. 00109 00110 if (pos < fSeekStart || pos+len > fSeekStart+fNtot) return -1; 00111 memcpy(buf,fBuffer+pos-fSeekStart,len); 00112 return 0; 00113 } 00114 00115 //_____________________________________________________________________________ 00116 Int_t TFileCacheWrite::WriteBuffer(const char *buf, Long64_t pos, Int_t len) 00117 { 00118 // Write buffer at position pos in the write buffer. 00119 // The function returns 1 if the buffer has been successfully entered into the write buffer. 00120 // The function returns 0 in case WriteBuffer() was recusively called via Flush(). 00121 // The function returns -1 in case of error. 00122 00123 if (fRecursive) return 0; 00124 00125 //printf("TFileCacheWrite::WriteBuffer, pos=%lld, len=%d, fSeekStart=%lld, fNtot=%d\n",pos,len,fSeekStart,fNtot); 00126 00127 if (fSeekStart + fNtot != pos) { 00128 //we must flush the current cache 00129 if (Flush()) return -1; //failure 00130 } 00131 if (fNtot + len >= fBufferSize) { 00132 if (Flush()) return -1; //failure 00133 if (len >= fBufferSize) { 00134 //buffer larger than the cache itself: direct write to file 00135 fRecursive = kTRUE; 00136 if (fFile->WriteBuffer(buf,len)) return -1; // failure 00137 fRecursive = kFALSE; 00138 return 1; 00139 } 00140 } 00141 if (!fNtot) fSeekStart = pos; 00142 memcpy(fBuffer+fNtot,buf,len); 00143 fNtot += len; 00144 00145 return 1; 00146 } 00147 00148 //_____________________________________________________________________________ 00149 void TFileCacheWrite::SetFile(TFile *file) 00150 { 00151 // Set the file using this cache. 00152 // Any write not yet flushed will be lost. 00153 00154 fFile = file; 00155 }