35 ClassImp(TFileCacheRead);
40 TFileCacheRead::TFileCacheRead() : TObject()
46 fNoCacheBytesRead = 0;
49 fNoCacheReadCalls = 0;
65 fIsTransferred = kFALSE;
81 fBIsTransferred=kFALSE;
83 fAsyncReading = kFALSE;
84 fEnablePrefetching = kFALSE;
92 TFileCacheRead::TFileCacheRead(TFile *file, Int_t buffersize, TObject *tree)
95 if (buffersize <=10000) fBufferSize = 100000;
96 else fBufferSize = buffersize;
98 fBufferSizeMin = fBufferSize;
101 fNoCacheBytesRead = 0;
104 fNoCacheReadCalls = 0;
109 fSeek =
new Long64_t[fSeekSize];
110 fSeekIndex =
new Int_t[fSeekSize];
111 fSeekSort =
new Long64_t[fSeekSize];
112 fPos =
new Long64_t[fSeekSize];
113 fSeekLen =
new Int_t[fSeekSize];
114 fSeekSortLen =
new Int_t[fSeekSize];
115 fSeekPos =
new Int_t[fSeekSize];
116 fLen =
new Int_t[fSeekSize];
124 fBSeek =
new Long64_t[fBSeekSize];
125 fBSeekIndex =
new Int_t[fBSeekSize];
126 fBSeekSort =
new Long64_t[fBSeekSize];
127 fBPos =
new Long64_t[fBSeekSize];
128 fBSeekLen =
new Int_t[fBSeekSize];
129 fBSeekSortLen =
new Int_t[fBSeekSize];
130 fBSeekPos =
new Int_t[fBSeekSize];
131 fBLen =
new Int_t[fBSeekSize];
135 fPrefetchedBlocks = 0;
139 fEnablePrefetching = gEnv->GetValue(
"TFile.AsyncPrefetching", 0);
141 if (fEnablePrefetching && file && strcmp(file->GetEndpointUrl()->GetProtocol(),
"file")){
142 SetEnablePrefetchingImpl(
true);
145 SetEnablePrefetchingImpl(
false);
149 fIsTransferred = kFALSE;
151 fBIsTransferred = kFALSE;
153 if (file) file->SetCacheRead(
this, tree);
159 TFileCacheRead::~TFileCacheRead()
161 SafeDelete(fPrefetch);
163 delete [] fSeekIndex;
167 delete [] fSeekSortLen;
173 delete [] fBSeekIndex;
174 delete [] fBSeekSort;
177 delete [] fBSeekSortLen;
188 void TFileCacheRead::Close(Option_t * )
201 void TFileCacheRead::Prefetch(Long64_t pos, Int_t len)
204 fIsTransferred = kFALSE;
210 if (fNseek >= fSeekSize) {
213 Long64_t *aSeek =
new Long64_t[fSeekSize];
214 Int_t *aSeekIndex =
new Int_t[fSeekSize];
215 Long64_t *aSeekSort =
new Long64_t[fSeekSize];
216 Long64_t *aPos =
new Long64_t[fSeekSize];
217 Int_t *aSeekLen =
new Int_t[fSeekSize];
218 Int_t *aSeekSortLen =
new Int_t[fSeekSize];
219 Int_t *aSeekPos =
new Int_t[fSeekSize];
220 Int_t *aLen =
new Int_t[fSeekSize];
221 for (Int_t i=0;i<fNseek;i++) {
223 aSeekIndex[i] = fSeekIndex[i];
224 aSeekSort[i] = fSeekSort[i];
226 aSeekLen[i] = fSeekLen[i];
227 aSeekSortLen[i] = fSeekSortLen[i];
228 aSeekPos[i] = fSeekPos[i];
232 delete [] fSeekIndex;
236 delete [] fSeekSortLen;
240 fSeekIndex = aSeekIndex;
241 fSeekSort = aSeekSort;
244 fSeekSortLen = aSeekSortLen;
250 fSeekLen[fNseek] = len;
258 void TFileCacheRead::SecondPrefetch(Long64_t pos, Int_t len){
266 if (fBNseek >= fBSeekSize) {
269 Long64_t *aSeek =
new Long64_t[fBSeekSize];
270 Int_t *aSeekIndex =
new Int_t[fBSeekSize];
271 Long64_t *aSeekSort =
new Long64_t[fBSeekSize];
272 Long64_t *aPos =
new Long64_t[fBSeekSize];
273 Int_t *aSeekLen =
new Int_t[fBSeekSize];
274 Int_t *aSeekSortLen =
new Int_t[fBSeekSize];
275 Int_t *aSeekPos =
new Int_t[fBSeekSize];
276 Int_t *aLen =
new Int_t[fBSeekSize];
277 for (Int_t i=0;i<fBNseek;i++) {
278 aSeek[i] = fBSeek[i];
279 aSeekIndex[i] = fBSeekIndex[i];
280 aSeekSort[i] = fBSeekSort[i];
282 aSeekLen[i] = fBSeekLen[i];
283 aSeekSortLen[i] = fBSeekSortLen[i];
284 aSeekPos[i] = fBSeekPos[i];
288 delete [] fBSeekIndex;
289 delete [] fBSeekSort;
292 delete [] fBSeekSortLen;
296 fBSeekIndex = aSeekIndex;
297 fBSeekSort = aSeekSort;
299 fBSeekLen = aSeekLen;
300 fBSeekSortLen = aSeekSortLen;
301 fBSeekPos = aSeekPos;
305 fBSeek[fBNseek] = pos;
306 fBSeekLen[fBNseek] = len;
325 void TFileCacheRead::Print(Option_t *option)
const
327 TString opt = option;
329 printf(
"Cached Reading.....................: %lld bytes in %d transactions\n",this->GetBytesRead(), this->GetReadCalls());
330 printf(
"Reading............................: %lld bytes in %d uncached transactions\n",this->GetNoCacheBytesRead(), this->GetNoCacheReadCalls());
331 printf(
"Readahead..........................: %d bytes with overhead = %lld bytes\n",TFile::GetReadaheadSize(),this->GetBytesReadExtra());
332 if (this->GetReadCalls() > 0)
333 printf(
"Average transaction................: %f Kbytes\n",0.001*Double_t(this->GetBytesRead())/Double_t(this->GetReadCalls()));
335 printf(
"Average transaction................: No read calls yet\n");
336 printf(
"Number of blocks in current cache..: %d, total size: %d\n",fNseek,fNtot);
338 printf(
"Prefetching .......................: %lli blocks\n", fPrefetchedBlocks);
339 printf(
"Prefetching Wait Time..............: %f seconds\n", fPrefetch->GetWaitTime() / 1e+6);
342 if (!opt.Contains(
"a"))
return;
343 for (Int_t i=0;i<fNseek;i++) {
344 if (fIsSorted && !opt.Contains(
"s")) {
345 printf(
"block: %5d, from: %lld to %lld, len = %d bytes\n",i,fSeekSort[i],fSeekSort[i]+fSeekSortLen[i],fSeekSortLen[i]);
347 printf(
"block: %5d, from: %lld to %lld, len = %d bytes\n",i,fSeek[i],fSeek[i]+fSeekLen[i],fSeekLen[i]);
350 printf (
"Number of long buffers = %d\n",fNb);
351 for (Int_t j=0;j<fNb;j++) {
352 printf(
"fPos[%d] = %lld, fLen = %d\n",j,fPos[j],fLen[j]);
363 Int_t TFileCacheRead::ReadBuffer(
char *buf, Long64_t pos, Int_t len)
365 Long64_t fileBytesRead0 = fFile->GetBytesRead();
366 Long64_t fileBytesReadExtra0 = fFile->GetBytesReadExtra();
367 Int_t fileReadCalls0 = fFile->GetReadCalls();
370 Int_t rc = ReadBufferExt(buf, pos, len, loc);
372 fBytesRead += fFile->GetBytesRead() - fileBytesRead0;
373 fBytesReadExtra += fFile->GetBytesReadExtra() - fileBytesReadExtra0;
374 fReadCalls += fFile->GetReadCalls() - fileReadCalls0;
381 Int_t TFileCacheRead::ReadBufferExt(
char *buf, Long64_t pos, Int_t len, Int_t &loc)
383 if (fEnablePrefetching)
384 return ReadBufferExtPrefetch(buf, pos, len, loc);
386 return ReadBufferExtNormal(buf, pos, len, loc);
393 Int_t TFileCacheRead::ReadBufferExtPrefetch(
char *buf, Long64_t pos, Int_t len, Int_t &loc)
395 if (fNseek > 0 && !fIsSorted) {
398 fPrefetch->ReadBlock(fPos, fLen, fNb);
400 fIsTransferred = kTRUE;
404 if (fBNseek > 0 && !fBIsSorted) {
407 fPrefetch->ReadBlock(fBPos, fBLen, fBNb);
413 if (TFileCacheWrite *cachew = fFile->GetCacheWrite()) {
414 if (cachew->ReadBuffer(buf,pos,len) == 0) {
415 fFile->SetOffset(pos+len);
422 loc = (Int_t)TMath::BinarySearch(fNseek,fSeekSort,pos);
425 if (loc >= 0 && loc < fNseek && pos == fSeekSort[loc]) {
426 if (buf && fPrefetch){
428 fPrefetch->ReadBuffer(buf, pos, len);
432 else if (buf && fPrefetch){
434 loc = (Int_t)TMath::BinarySearch(fBNseek, fBSeekSort, pos);
436 if (loc >= 0 && loc < fBNseek && pos == fBSeekSort[loc]){
437 if (fPrefetch->ReadBuffer(buf, pos, len)) {
453 Int_t TFileCacheRead::ReadBufferExtNormal(
char *buf, Long64_t pos, Int_t len, Int_t &loc)
455 if (fNseek > 0 && !fIsSorted) {
460 if (!fAsyncReading) {
462 if (fFile->ReadBuffers(fBuffer,fPos,fLen,fNb)) {
465 fIsTransferred = kTRUE;
472 fFile->ReadBuffers(0, 0, 0, 0);
473 if (fFile->ReadBuffers(0,fPos,fLen,fNb)) {
476 fIsTransferred = kTRUE;
482 if (TFileCacheWrite *cachew = fFile->GetCacheWrite()) {
483 if (cachew->ReadBuffer(buf,pos,len) == 0) {
484 fFile->SetOffset(pos+len);
498 loc = (Int_t)TMath::BinarySearch(fNseek,fSeekSort,pos);
501 if (loc >= 0 && loc < fNseek && pos == fSeekSort[loc]) {
506 if (fFile->ReadBuffer(buf, pos, len)) {
509 fFile->SetOffset(pos+len);
519 Info(
"ReadBuffer",
"pos=%lld, len=%d, retval=%d, loc=%d, "
520 "fseekSort[loc]=%lld, fSeekLen[loc]=%d",
521 pos, len, retval, loc, fSeekSort[loc], fSeekLen[loc]);
527 loc = (Int_t)TMath::BinarySearch(fNseek, fSeekSort, pos);
529 if (loc >= 0 && loc <fNseek && pos == fSeekSort[loc]) {
531 memcpy(buf,&fBuffer[fSeekPos[loc]],len);
532 fFile->SetOffset(pos+len);
544 void TFileCacheRead::SetFile(TFile *file, TFile::ECacheAction action)
551 if (file && file->ReadBufferAsync(0, 0)) {
552 fAsyncReading = kFALSE;
553 fBuffer =
new char[fBufferSize];
557 if (action == TFile::kDisconnect)
561 if (action == TFile::kDisconnect)
562 SecondPrefetch(0, 0);
563 fPrefetch->SetFile(file, action);
571 void TFileCacheRead::Sort()
574 TMath::Sort(fNseek,fSeek,fSeekIndex,kFALSE);
577 Int_t effectiveNseek = 0;
578 for (i=0;i<fNseek;i++) {
580 Int_t ind = fSeekIndex[i];
581 if (effectiveNseek!=0 && fSeek[ind]==fSeekSort[effectiveNseek-1])
583 if (fSeekSortLen[effectiveNseek-1] < fSeekLen[ind]) {
584 fSeekSortLen[effectiveNseek-1] = fSeekLen[ind];
588 fSeekSort[effectiveNseek] = fSeek[ind];
589 fSeekSortLen[effectiveNseek] = fSeekLen[ind];
592 fNseek = effectiveNseek;
593 if (fNtot > fBufferSizeMin) {
594 fBufferSize = fNtot + 100;
600 fBuffer =
new char[fBufferSize];
602 fPos[0] = fSeekSort[0];
603 fLen[0] = fSeekSortLen[0];
605 for (i=1;i<fNseek;i++) {
606 fSeekPos[i] = fSeekPos[i-1] + fSeekSortLen[i-1];
610 if ((fSeekSort[i] != fSeekSort[i-1]+fSeekSortLen[i-1]) ||
611 (fLen[nb] > 16000000)) {
613 fPos[nb] = fSeekSort[i];
614 fLen[nb] = fSeekSortLen[i];
616 fLen[nb] += fSeekSortLen[i];
629 void TFileCacheRead::SecondSort()
631 if (!fBNseek)
return;
632 TMath::Sort(fBNseek,fBSeek,fBSeekIndex,kFALSE);
635 Int_t effectiveNseek = 0;
636 for (i=0;i<fBNseek;i++) {
638 Int_t ind = fBSeekIndex[i];
639 if (effectiveNseek!=0 && fBSeek[ind]==fBSeekSort[effectiveNseek-1])
641 if (fBSeekSortLen[effectiveNseek-1] < fBSeekLen[ind]) {
642 fBSeekSortLen[effectiveNseek-1] = fBSeekLen[ind];
646 fBSeekSort[effectiveNseek] = fBSeek[ind];
647 fBSeekSortLen[effectiveNseek] = fBSeekLen[ind];
650 fBNseek = effectiveNseek;
651 if (fBNtot > fBufferSizeMin) {
652 fBufferSize = fBNtot + 100;
658 fBuffer =
new char[fBufferSize];
660 fBPos[0] = fBSeekSort[0];
661 fBLen[0] = fBSeekSortLen[0];
663 for (i=1;i<fBNseek;i++) {
664 fBSeekPos[i] = fBSeekPos[i-1] + fBSeekSortLen[i-1];
668 if ((fBSeekSort[i] != fBSeekSort[i-1]+fBSeekSortLen[i-1]) ||
669 (fBLen[nb] > 16000000)) {
671 fBPos[nb] = fBSeekSort[i];
672 fBLen[nb] = fBSeekSortLen[i];
674 fBLen[nb] += fBSeekSortLen[i];
683 TFilePrefetch* TFileCacheRead::GetPrefetchObj(){
684 return this->fPrefetch;
690 void TFileCacheRead::WaitFinishPrefetch()
692 if ( fEnablePrefetching && fPrefetch ) {
693 fPrefetch->WaitFinishPrefetch();
709 Int_t TFileCacheRead::SetBufferSize(Int_t buffersize)
711 if (buffersize <= 0)
return -1;
712 if (buffersize <=10000) buffersize = 100000;
714 if (buffersize == fBufferSize) {
715 fBufferSizeMin = buffersize;
719 Bool_t inval = kFALSE;
722 if (fNtot > buffersize) {
726 if (fBNtot > buffersize) {
727 SecondPrefetch(0, 0);
732 if (!fEnablePrefetching && !fAsyncReading) {
734 if (fIsTransferred) {
741 np =
new char[buffersize];
743 memcpy(np, pres, fNtot);
750 fBufferSizeMin = buffersize;
751 fBufferSize = buffersize;
771 void TFileCacheRead::SetEnablePrefetching(Bool_t setPrefetching)
773 SetEnablePrefetchingImpl(setPrefetching);
781 void TFileCacheRead::SetEnablePrefetchingImpl(Bool_t setPrefetching)
783 fEnablePrefetching = setPrefetching;
785 if (!fPrefetch && fEnablePrefetching) {
786 fPrefetch =
new TFilePrefetch(fFile);
787 const char* cacheDir = gEnv->GetValue(
"Cache.Directory",
"");
788 if (strcmp(cacheDir,
""))
789 if (!fPrefetch->SetCache((
char*) cacheDir))
790 fprintf(stderr,
"Error while trying to set the cache directory: %s.\n", cacheDir);
791 if (fPrefetch->ThreadStart()){
792 fprintf(stderr,
"Error stating prefetching thread. Disabling prefetching.\n");
793 fEnablePrefetching = 0;
795 }
else if (fPrefetch && !fEnablePrefetching) {
796 SafeDelete(fPrefetch);
801 if (fEnablePrefetching) {
802 fAsyncReading = kFALSE;
805 fAsyncReading = gEnv->GetValue(
"TFile.AsyncReading", 0);
808 fAsyncReading = kFALSE;
809 if (fFile && !(fFile->ReadBufferAsync(0, 0)))
810 fAsyncReading = kTRUE;
812 if (!fAsyncReading && fBuffer == 0) {
814 fBuffer =
new char[fBufferSize];