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];