Index: tree/tree/src/TTreeCache.cxx
===================================================================
--- tree/tree/src/TTreeCache.cxx	(revision 1)
+++ tree/tree/src/TTreeCache.cxx	(working copy)
@@ -259,7 +259,15 @@
    fOwner(0),
    fTree(0),
    fIsLearning(kTRUE),
-   fIsManual(kFALSE)
+   fIsManual(kFALSE),
+   fBEntryMin(0),
+   fBEntryMax(1),
+   fBEntryCurrent(-1),
+   fBEntryNext(-1),
+   fEntryStart(0),
+   fEntryEnd(0),
+   fOneTime(kFALSE),
+   fBIsLearning(kTRUE)
 {
    // Default Constructor.
 }
@@ -280,7 +288,15 @@
    fOwner(tree),
    fTree(0),
    fIsLearning(kTRUE),
-   fIsManual(kFALSE)
+   fIsManual(kFALSE),
+   fBEntryMin(0),
+   fBEntryMax(tree->GetEntriesFast()),
+   fBEntryCurrent(-1),
+   fBEntryNext(-1),
+   fEntryStart(-1),
+   fEntryEnd(-1),
+   fOneTime(kFALSE),
+   fBIsLearning(kTRUE)
 {
    // Constructor.
 
@@ -424,11 +440,13 @@
 {
    // Fill the cache buffer with the branches in the cache.
 
-
    if (fNbranches <= 0) return kFALSE;
    TTree *tree = ((TBranch*)fBranches->UncheckedAt(0))->GetTree();
    Long64_t entry = tree->GetReadEntry();
    
+   if (fEntryEnd > 0)
+     entry = fEntryEnd;
+   
    // If the entry is in the range we previously prefetched, there is 
    // no point in retrying.   Note that this will also return false
    // during the training phase (fEntryNext is then set intentional to 
@@ -460,6 +478,10 @@
 
    fEntryCurrent = entry;
    
+   //set the values of the current block
+   fEntryStart = fEntryCurrent;
+   fEntryEnd = fEntryNext;
+       
    // Check if owner has a TEventList set. If yes we optimize for this
    // Special case reading only the baskets containing entries in the
    // list.
@@ -508,11 +530,111 @@
       }
       if (gDebug > 0) printf("Entry: %lld, registering baskets branch %s, fEntryNext=%lld, fNseek=%d, fNtot=%d\n",entry,((TBranch*)fBranches->UncheckedAt(i))->GetName(),fEntryNext,fNseek,fNtot);
    }
+
+   //printf("**FillBuffer FINISH **:: entry = %lld \n", entry);
+
    fIsLearning = kFALSE;
    return kTRUE;
 }
 
 //_____________________________________________________________________________
+Bool_t TTreeCache::FillSecondBuffer()
+{
+  // Fill the cache buffer with the branches in the cache.                                                                                                  
+
+  if (fNbranches <= 0) return kFALSE;
+  TTree *tree = ((TBranch*)fBranches->UncheckedAt(0))->GetTree();
+  Long64_t entry = fEntryEnd;
+
+  fBEntryCurrent = entry;
+  fEntryStart = entry;
+
+  // If the entry is in the range we previously prefetched, there is                                                                                        
+  // no point in retrying.   Note that this will also return false                                                                                          
+  // during the training phase (lEntryNext is then set intentional to                                                                                       
+  // the end of the training phase).                                                                                                                        
+
+  // Triggered by the user, not the learning phase                                                                                                          
+  if (entry == -1)  entry = 0;
+
+  // Estimate number of entries that can fit in the cache compare it                                                                                        
+  // to the original value of fBufferSize not to the real one                                                                                               
+  Long64_t autoFlush = tree->GetAutoFlush();
+  if (autoFlush > 0) {
+    //case when the tree autoflush has been set                                                                                                             
+    Int_t averageEntrySize = tree->GetZipBytes()/tree->GetEntries();
+    Int_t nauto = fBufferSizeMin/(averageEntrySize*autoFlush);
+    if (nauto < 1) nauto = 1;
+    fBEntryNext = entry - entry%autoFlush + nauto*autoFlush;
+  } else {
+    //case of old files before November 9 2009                                                                                                              
+    if (fZipBytes==0) {
+      fBEntryNext = entry + tree->GetEntries();;
+    } else {
+      fBEntryNext = entry + tree->GetEntries()*fBufferSizeMin/fZipBytes;
+    }
+  }
+  if (fBEntryMax <= 0) fBEntryMax = tree->GetEntries();
+  if (fBEntryNext > fBEntryMax) fBEntryNext = fBEntryMax+1;
+
+  fEntryEnd = fBEntryNext;
+
+  // Check if owner has a TEventList set. If yes we optimize for this                                                                                       
+  // Special case reading only the baskets containing entries in the                                                                                        
+  // list.                                                                                                                                                  
+
+  TEventList *elist = fOwner->GetEventList();
+  Long64_t chainOffset = 0;
+  if (elist) {
+    if (fOwner->IsA() ==TChain::Class()) {
+      TChain *chain = (TChain*)fOwner;
+      Int_t t = chain->GetTreeNumber();
+      chainOffset = chain->GetTreeOffset()[t];
+    }
+  }
+
+  //clear the buffer elements                                                                                                                               
+  TFileCacheRead::SecondPrefetch(0,0);
+
+  //store baskets                                                                                                                                           
+  for (Int_t i=0;i<fNbranches;i++) {
+    TBranch *b = (TBranch*)fBranches->UncheckedAt(i);
+    if (b->GetDirectory()==0) continue;
+    if (b->GetDirectory()->GetFile() != fFile) continue;
+    Int_t nb = b->GetMaxBaskets();
+    Int_t *lbaskets   = b->GetBasketBytes();
+    Long64_t *entries = b->GetBasketEntry();
+    if (!lbaskets || !entries) continue;
+    //we have found the branch. We now register all its baskets                                                                                             
+    //from the requested offset to the basket below fEntrymax                                                                                               
+    Int_t blistsize = b->GetListOfBaskets()->GetSize();
+    for (Int_t j=0;j<nb;j++) {
+      // This basket has already been read, skip it                                                                                                         
+      if (j<blistsize && b->GetListOfBaskets()->UncheckedAt(j)) continue;
+
+      Long64_t pos = b->GetBasketSeek(j);
+      Int_t len = lbaskets[j];
+      if (pos <= 0 || len <= 0) continue;
+      //important: do not try to read lEntryNext, otherwise you jump to the next autoflush                                                                  
+      if (entries[j] >= fBEntryNext) continue;
+      if (entries[j] < entry && (j<nb-1 && entries[j+1] <= entry)) continue;
+      if (elist) {
+        Long64_t emax = fBEntryMax;
+        if (j<nb-1) emax = entries[j+1]-1;
+        if (!elist->ContainsRange(entries[j]+chainOffset,emax+chainOffset)) continue;
+      }
+      TFileCacheRead::SecondPrefetch(pos, len);
+    }
+  }
+
+  //printf("**FillSecondBuffer FINISH **:: entry = %lld \n", entry);                        
+
+  fBIsLearning = kFALSE;
+  return kTRUE;
+}
+
+
+//_____________________________________________________________________________
 Double_t TTreeCache::GetEfficiency() const
 {
    // Give the total efficiency of the cache... defined as the ratio
@@ -593,6 +715,26 @@
    TFileCacheRead::Print(option);
 }
 
+
+//____________________________________________________________________________________
+//decide which of the two buffers to use for prefetch                                 
+void TTreeCache::DecideBufferFill(){
+
+  TTree *tree = ((TBranch*)fBranches->UncheckedAt(0))->GetTree();
+  Long64_t entry = tree->GetReadEntry();
+
+  if (entry >= fEntryStart){
+    if (fEntryStart == fBEntryCurrent){
+      //use first block for prefetching                                                                                                                     
+      FillBuffer();
+    }
+    else if (fEntryStart == fEntryCurrent){
+      //use the second block for prefetching                                                                                                                
+      FillSecondBuffer();
+    }
+  }
+}
+
 //_____________________________________________________________________________
 Int_t TTreeCache::ReadBuffer(char *buf, Long64_t pos, Int_t len)
 {
@@ -608,10 +750,12 @@
 
    //Is request already in the cache?
    if (TFileCacheRead::ReadBuffer(buf,pos,len) == 1){
+      DecideBufferFill();
       fNReadOk++;
       return 1;
    }
 
+   //NOT REALLY USED 
    //not found in cache. Do we need to fill the cache?
    Bool_t bufferFilled = FillBuffer();
    if (bufferFilled) {
@@ -705,9 +849,14 @@
       fIsLearning = kFALSE;
    }
    fIsManual = kTRUE;
+  
+   //fill the buffers only once during learning
+   if (!fOneTime){
    FillBuffer();
-
+     FillSecondBuffer();
+     fOneTime = kTRUE;
 }
+}
 
 //_____________________________________________________________________________
 void TTreeCache::UpdateBranches(TTree *tree, Bool_t owner)
Index: tree/tree/inc/TTreeCache.h
===================================================================
--- tree/tree/inc/TTreeCache.h	(revision 1)
+++ tree/tree/inc/TTreeCache.h	(working copy)
@@ -51,6 +51,17 @@
    Bool_t          fIsManual;    //! true if cache is StopLearningPhase was used
    static  Int_t fgLearnEntries; //Number of entries used for learning mode
 
+   Long64_t        fBEntryMin;
+   Long64_t        fBEntryMax;
+   Long64_t        fBEntryCurrent;  //! current lowest entry number from the second block
+   Long64_t        fBEntryNext;     //! next entry number from the second block
+
+   Long64_t        fEntryStart;     //! current lowest entry number from the block in use
+   Long64_t        fEntryEnd;       //! next entry number from the second block
+
+   Bool_t          fOneTime;        //used to call only once FillBuffer in the learning phase -- temporary 
+   Bool_t          fBIsLearning;    //! true if cache is in learning mode      
+
 private:
    TTreeCache(const TTreeCache &);            //this class cannot be copied
    TTreeCache& operator=(const TTreeCache &);
@@ -78,6 +89,9 @@
    virtual void        StopLearningPhase();
    virtual void        UpdateBranches(TTree *tree, Bool_t owner = kFALSE);
 
+   virtual Bool_t      FillSecondBuffer();     //! Function used to fill the second buffer with chunks
+   virtual void        DecideBufferFill();     //! Function used to decide on which of the two buffers to use
+
    ClassDef(TTreeCache,2)  //Specialization of TFileCacheRead for a TTree
 };
 
Index: net/netx/src/TXNetFile.cxx
===================================================================
--- net/netx/src/TXNetFile.cxx	(revision 1)
+++ net/netx/src/TXNetFile.cxx	(working copy)
@@ -615,10 +615,13 @@
    //  0 it looks like the block has not been prefetched
    // But we don't want it to return the buffer, to avoid recursion
    Int_t st = 0;
+
    if (GetCacheRead() && GetCacheRead()->IsAsyncReading()) {
-      st = ReadBufferViaCache(0, bufferLength);
-      if (st == 1)
-         fOffset -= bufferLength;
+      st = ReadBufferViaCache(buffer, bufferLength);
+      if (st == 1){
+	fOffset -= bufferLength;  //maybe remove this?!
+	 return kFALSE;
+      }
    } else {
       if (GetCacheRead()) {
          st = ReadBufferViaCache(buffer, bufferLength);
@@ -794,7 +797,7 @@
          Info("ReadBuffers", "%lld bytes of data read from a list of %d buffers",
               nr, nbuf);
 
-      if (GetCacheRead()->GetBufferSize() < nr)
+      if (GetCacheRead() && GetCacheRead()->GetBufferSize() < nr)
          Info("ReadBuffers", "%lld bytes of data read with a smaller (%d) TFileCacheRead buffer size?",
               nr, GetCacheRead()->GetBufferSize());
 
Index: io/io/src/TFileCacheRead.cxx
===================================================================
--- io/io/src/TFileCacheRead.cxx	(revision 1)
+++ io/io/src/TFileCacheRead.cxx	(working copy)
@@ -58,6 +58,23 @@
    fIsSorted    = kFALSE;
    fIsTransferred = kFALSE;
 
+   //values for the second prefetched block
+   fBNseek       = 0;
+   fBNtot        = 0;
+   fBNb          = 0;
+   fBSeekSize    = 0;
+   fBSeek        = 0;
+   fBSeekSort    = 0;
+   fBSeekIndex   = 0;
+   fBPos         = 0;
+   fBSeekLen     = 0;
+   fBSeekSortLen = 0;
+   fBSeekPos     = 0;
+   fBLen         = 0;
+
+   fBDone        = kFALSE;
+
+
    fAsyncReading = kFALSE;
 }
 
@@ -86,12 +103,27 @@
    fLen         = new Int_t[fSeekSize];
    fFile        = file;
 
+   //initialisation for the second block    
+   fBNseek       = 0;
+   fBNtot        = 0;
+   fBNb          = 0;
+   fBSeekSize    = 10000;
+   fBSeek        = new Long64_t[fBSeekSize];
+   fBSeekIndex   = new Int_t[fBSeekSize];
+   fBSeekSort    = new Long64_t[fBSeekSize];
+   fBPos         = new Long64_t[fBSeekSize];
+   fBSeekLen     = new Int_t[fBSeekSize];
+   fBSeekSortLen = new Int_t[fBSeekSize];
+   fBSeekPos     = new Int_t[fBSeekSize];
+   fBLen         = new Int_t[fBSeekSize];
+
+
    fBuffer = 0;
 
    fAsyncReading = gEnv->GetValue("TFile.AsyncReading", 1);
    if (fAsyncReading) {
       // Check if asynchronous reading is supported by this TFile specialization
-      fAsyncReading = kFALSE;
+      //fAsyncReading = kFALSE;
       if (file && !(file->ReadBufferAsync(0, 0)))
          fAsyncReading = kTRUE;
    }
@@ -102,6 +134,9 @@
 
    fIsSorted    = kFALSE;
    fIsTransferred = kFALSE;
+   fBIsSorted = kFALSE;
+   fBIsTransferred = kFALSE;
+
    if (file) file->SetCacheRead(this);
 }
 
@@ -119,6 +154,15 @@
    delete [] fSeekPos;
    delete [] fLen;
    delete [] fBuffer;
+
+   delete [] fBSeek;
+   delete [] fBSeekIndex;
+   delete [] fBSeekSort;
+   delete [] fBPos;
+   delete [] fBSeekLen;
+   delete [] fBSeekSortLen;
+   delete [] fBSeekPos;
+   delete [] fBLen;
 }
 
 //_____________________________________________________________________________
@@ -179,6 +223,64 @@
    fNtot += len;
 }
 
+
+//____________________________________________________________________________
+void TFileCacheRead::SecondPrefetch(Long64_t pos, Int_t len){
+ 
+  //add a new element and increase the size if necessary                                                                                            
+  fBIsSorted = kFALSE;
+  fBIsTransferred = kFALSE;
+  if (pos <= 0) {
+    fBNseek = 0;
+    fBNtot  = 0;
+    return;
+  }
+  if (fBNseek >= fBSeekSize) {
+    //reallocate buffers                                                                                                                                     
+    fBSeekSize *= 2;
+    Long64_t *aSeek        = new Long64_t[fBSeekSize];
+    Int_t    *aSeekIndex   = new Int_t[fBSeekSize];
+    Long64_t *aSeekSort    = new Long64_t[fBSeekSize];
+    Long64_t *aPos         = new Long64_t[fBSeekSize];
+    Int_t    *aSeekLen     = new Int_t[fBSeekSize];
+    Int_t    *aSeekSortLen = new Int_t[fBSeekSize];
+    Int_t    *aSeekPos     = new Int_t[fBSeekSize];
+    Int_t    *aLen         = new Int_t[fBSeekSize];
+    for (Int_t i=0;i<fBNseek;i++) {
+      aSeek[i]        = fBSeek[i];
+      aSeekIndex[i]   = fBSeekIndex[i];
+      aSeekSort[i]    = fBSeekSort[i];
+      aPos[i]         = fBPos[i];
+      aSeekLen[i]     = fBSeekLen[i];
+      aSeekSortLen[i] = fBSeekSortLen[i];
+      aSeekPos[i]     = fBSeekPos[i];
+      aLen[i]         = fBLen[i];
+    }
+    delete [] fBSeek;
+    delete [] fBSeekIndex;
+    delete [] fBSeekSort;
+    delete [] fBPos;
+    delete [] fBSeekLen;
+    delete [] fBSeekSortLen;
+    delete [] fBSeekPos;
+    delete [] fBLen;
+    fBSeek        = aSeek;
+    fBSeekIndex   = aSeekIndex;
+    fBSeekSort    = aSeekSort;
+    fBPos         = aPos;
+    fBSeekLen     = aSeekLen;
+    fBSeekSortLen = aSeekSortLen;
+    fBSeekPos     = aSeekPos;
+    fBLen         = aLen;
+  }
+
+  fBSeek[fBNseek] = pos;
+  fBSeekLen[fBNseek] = len;
+  fBNseek++;
+  fBNtot += len;
+}
+
+
 //_____________________________________________________________________________
 void TFileCacheRead::Print(Option_t *option) const
 {
@@ -224,6 +326,7 @@
    return ReadBufferExt(buf, pos, len, loc);
 }
 
+
 //_____________________________________________________________________________
 Int_t TFileCacheRead::ReadBufferExt(char *buf, Long64_t pos, Int_t len, Int_t &loc)
 {
@@ -231,32 +334,58 @@
    // of the block in the internal buffer. This helps TTreeCacheUnzip to avoid
    // doing twice the binary search
 
+  //prefetch the first block                                                                                                                                
    if (fNseek > 0 && !fIsSorted) {
       Sort();
       loc = -1;
 
       // If ReadBufferAsync is not supported by this implementation...
       if (!fAsyncReading) {
-         // Then we use the vectored read to read everything now
+      
          if (fFile->ReadBuffers(fBuffer,fPos,fLen,fNb)) {
             return -1;
          }
          fIsTransferred = kTRUE;
-      } else {
-         // In any case, we'll start to request the chunks.
-         // This implementation simply reads all the chunks in advance
-         // in the async way.
-
-         // Use the async readv instead of single reads
-         fFile->ReadBuffers(0, 0, 0, 0); //Clear the XrdClient cache
-         if (fFile->ReadBuffers(0,fPos,fLen,fNb)) {
+    }
+    else { //async prefetching                                                                                                                              
+      //fFile->ReadBuffers(0, 0, 0, 0); //Clear the XrdClient cache                                                                                                 
+      // then we use the vectored read to read everything now                                                                                               
+      if (fFile->fPrefetch)
+        fFile->fPrefetch->ReadBlock(fPos, fLen, fNb);
+      else if (fFile->ReadBuffers(0,fPos,fLen,fNb)) {
+	//use old method
             return -1;
          }
          fIsTransferred = kTRUE;
       }
    }
 
-   // in case we are writing and reading to/from this file, we much check
+  //try to prefetch the second block                                                                                                                        
+  if (fBNseek > 0 && !fBIsSorted) {
+    SecondSort();
+    loc = -1;
+
+    // If ReadBufferAsync is not supported by this implementation...                                                                                        
+    if (!fAsyncReading) {
+
+      if (fFile->ReadBuffers(fBuffer,fBPos,fBLen,fBNb)) {
+	return -1;
+      }
+      fBIsTransferred = kTRUE;
+    }
+    else { //async prefetching                                                                                                                              
+      // fFile->ReadBuffers(0, 0, 0, 0); //Clear the XrdClient cache                                                                                           
+      // use vectored read to read everything now                                                                                               
+      if (fFile->fPrefetch)
+        fFile->fPrefetch->ReadBlock(fBPos, fBLen, fBNb);
+      else if (fFile->ReadBuffers(0,fBPos,fBLen,fBNb)) {
+        return -1;
+      }
+      fBIsTransferred = kTRUE;
+    }
+  }
+
+  // in case we are writing and reading to/from this file, we must check                                                                                    
    // if this buffer is in the write cache (not yet written to the file)
    if (TFileCacheWrite *cachew = fFile->GetCacheWrite()) {
       if (cachew->ReadBuffer(buf,pos,len) == 0) {
@@ -265,13 +394,38 @@
       }
    }
 
-   // If asynchronous reading is supported by this implementation...
+  // async reading                                                                                                                                      
    if (fAsyncReading) {
+    //try to prefetch from the first block                                                                                                                  
+    if (loc < 0)
+      loc = (Int_t)TMath::BinarySearch(fNseek,fSeekSort,pos);
 
+    if (loc >= 0 && loc <fNseek && pos == fSeekSort[loc]) {
+      if (buf && fFile->fPrefetch){
+        //prefetch with the new method                                                                                                                      
+        fFile->fPrefetch->ReadBuffer(buf, pos, len);
+      }
+      else if (buf){
+        //prefetch with the old method                                                                                                                      
+        memcpy(buf,&fBuffer[fSeekPos[loc]],len);
+      }
+
+      return 1;
+    }
+    else if (buf && fFile->fPrefetch){
+      //try to preferch from the second block                                                                                                               
+      loc = (Int_t)TMath::BinarySearch(fBNseek, fBSeekSort, pos);
+ 
+      if (loc >= 0 && loc < fBNseek && pos == fBSeekSort[loc]){
+        if (fFile->fPrefetch->ReadBuffer(buf, pos, len))
+          return 1;
+      }
+    }
+  }
+  else { //sync reading                                                                                                                                  
          // Now we dont have to look for it in the local buffer
          // if it's async, we expect that the communication library
          // will handle it more efficiently than we can do here
-
       Int_t retval;
       if (loc < 0)
          loc = (Int_t)TMath::BinarySearch(fNseek,fSeekSort,pos);
@@ -279,7 +433,6 @@
       // We use the internal list just to notify if the list is to be reconstructed
       if (loc >= 0 && loc < fNseek && pos == fSeekSort[loc]) {
          // Block found, the caller will get it
-         
          if (buf) {
             // disable cache to avoid infinite recursion
             fFile->SetCacheRead(0);
@@ -297,26 +450,15 @@
       }
 
       if (gDebug > 0)
-         Info("ReadBuffer","pos=%lld, len=%d, retval=%d, loc=%d, fseekSort[loc]=%lld, fSeekLen[loc]=%d", pos, len, retval, loc, fSeekSort[loc], fSeekLen[loc]);
-      
+      Info("ReadBuffer","pos=%lld, len=%d, retval=%d, loc=%d, fseekSort[loc]=%lld, fSeekLen[loc]=%d", pos, len, retval, loc, fSeekSort[loc], fSeekLen[loc]
+	   );
       return retval;
-   } else {
-
-      if (loc < 0)
-         loc = (Int_t)TMath::BinarySearch(fNseek,fSeekSort,pos);
-
-      if (loc >= 0 && loc <fNseek && pos == fSeekSort[loc]) {
-         if (buf) {
-            memcpy(buf,&fBuffer[fSeekPos[loc]],len);
-            fFile->SetOffset(pos+len);
          }
-         return 1;
-      }
-   }
 
    return 0;
 }
 
+
 //_____________________________________________________________________________
 void TFileCacheRead::SetFile(TFile *file)
 {
@@ -380,3 +522,51 @@
    fNb = nb+1;
    fIsSorted = kTRUE;
 }
+
+
+//_____________________________________________________________________________                                                                             
+void TFileCacheRead::SecondSort()
+{
+  // Sort buffers to be prefetched in increasing order of positions.                                                                                      
+  // Merge consecutive blocks if necessary.        
+  // Sort buffers to be prefetched in increasing order of positions. 
+  // Merge consecutive blocks if necessary.                                                                                                               
+
+  if (!fBNseek) return;
+  TMath::Sort(fBNseek,fBSeek,fBSeekIndex,kFALSE);
+  Int_t i;
+  Int_t nb = 0;
+  for (i=0;i<fBNseek;i++) {
+    Int_t ind = fBSeekIndex[i];
+    fBSeekSort[i] = fBSeek[ind];
+    fBSeekSortLen[i] = fBSeekLen[ind];
+  }
+  if (fBNtot > fBufferSizeMin) {
+    fBufferSize = fBNtot + 100;
+    delete [] fBuffer;
+    fBuffer = 0;
+    // If ReadBufferAsync is not supported by this implementation                                                                                           
+    // it means that we are using sync primitives, hence we need the local buffer                                                                           
+     if (!fAsyncReading)
+      fBuffer = new char[fBufferSize];
+}
+  fBPos[0]  = fBSeekSort[0];
+  fBLen[0]  = fBSeekSortLen[0];
+  fBSeekPos[0] = 0;
+  for (i=1;i<fBNseek;i++) {
+    fBSeekPos[i] = fBSeekPos[i-1] + fBSeekSortLen[i-1];
+    //in the test below 16 MBytes is pure empirirical and may depend on the file system.                                                                    
+    //increasing this number must be done with care, as it may increase                                                                                     
+    //the job real time (mismatch with OS buffers)                                                                                                          
+    if ((fBSeekSort[i] != fBSeekSort[i-1]+fBSeekSortLen[i-1]) ||
+        (fBLen[nb] > 16000000)) {
+      nb++;
+      fBPos[nb] = fBSeekSort[i];
+      fBLen[nb] = fBSeekSortLen[i];
+    } else {
+      fBLen[nb] += fBSeekSortLen[i];
+    }
+  }
+  fBNb = nb+1;
+  fBIsSorted = kTRUE;
+}
Index: io/io/src/TFilePrefetch.cxx
===================================================================
--- io/io/src/TFilePrefetch.cxx	(revision 0)
+++ io/io/src/TFilePrefetch.cxx	(revision 2)
@@ -0,0 +1,719 @@
+#include "TFilePrefetch.h"
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <cstdio>
+#include <cstdlib>
+#include <cctype>
+
+#define MAX_READ_SIZE	4                       //maximum size of the read list of blocks
+#define MAX_RECYCLE_SIZE 2                      //maximum size of the recycle list of blocks
+
+#define xtod(c) ((c>='0' && c<='9') ? c-'0' : ((c>='A' && c<='F') ? c-'A'+10 : ((c>='a' && c<='f') ? c-'a'+10 : 0)))
+
+using namespace std;
+
+ClassImp(TFilePrefetch)
+
+//____________________________________________________________________________________________
+//constructor for the class
+TFilePrefetch::TFilePrefetch(TFile* file){
+
+  this->consumer = 0;                               //thread init
+  this->f= file;
+  this->pathCache= NULL;
+  this->pendingBlocks = new TList();
+  this->readBlocks = new TList();
+  this->recycleBlocks = new TList();
+  this->accessReadList = new TCondition(0);
+  this->accessPendingList = new TCondition(0);
+  this->accessRecycleList = new TCondition(0);
+  this->newBlockAdded = new TCondition(0);
+  this->readBlockAdded = new TCondition(0);
+}
+
+
+//____________________________________________________________________________________________
+//class destructor
+TFilePrefetch::~TFilePrefetch(){
+
+  delete this->pendingBlocks;
+  delete this->readBlocks;
+  delete this->recycleBlocks;
+  delete this->accessPendingList;
+  delete this->accessReadList;
+  delete this->accessRecycleList;
+  delete this->newBlockAdded;
+  delete this->readBlockAdded;
+}
+
+//____________________________________________________________________________________________
+//read one block and insert it in prefetchBuffers
+void TFilePrefetch::ReadAsync(TFPBlock* block, Bool_t *inCache){
+
+  char* path = NULL;
+
+  //check if block in cache
+  if (this->CheckBlockInCache(path, block)){                 //if found in cache
+
+    printf("Reading from cache! \n");
+    block->SetBuffer(this->GetBlockFromCache(path, block->GetFullSize()));
+    *inCache = kTRUE;
+  }
+  else{
+
+    //using vector reads
+    printf("Reading from file!\n");
+    this->f->ReadBuffers(block->GetBuffer(), block->GetPos(), block->GetLen(), block->GetNoElem());
+    *inCache =kFALSE;
+  }
+
+  //free memory;
+  delete[] path;
+}
+
+
+//____________________________________________________________________________________________
+//read the blocks specified in prefetchBlocks
+void TFilePrefetch::ReadListOfBlocks(){
+
+  Bool_t inCache = kFALSE;
+  TFPBlock*  block = NULL;
+
+  while((block = this->GetPendingBlock())){       //read the blocks not read yet
+
+    this->ReadAsync(block, &inCache);
+    this->AddReadBlock(block);
+    if (!inCache)
+      this->SaveBlockInCache(block);
+   }
+}
+
+
+//____________________________________________________________________________________________
+//test if buffer is already prefetched and return it ==>  NOT USED YET
+Bool_t TFilePrefetch::ReadBuffer(char* buf, Long64_t* offset, Int_t* len, Int_t noBuf){
+
+  Bool_t found = true;
+  TFPBlock* blockObj = NULL;
+  TMutex *mutexBlocks = this->accessReadList->GetMutex();
+
+  while(1){
+
+    while (mutexBlocks->Lock() != 0)            //failed to lock
+      this->accessReadList->Wait();             //wait for signal
+
+    //TODO:binaray search for the block + modify the current search (it's not correct)
+
+    TIter iter(this->readBlocks);
+    while ((blockObj = static_cast<TFPBlock*>(iter.Next())) &&
+	   (blockObj->GetNoElem() == noBuf)){
+
+      found = true;
+      for(Int_t i=0; i < noBuf; i++)
+	if (offset[i] != blockObj->GetPos(i)){
+	  found = false ;
+	  break;
+	}
+
+      if (found)
+	break;
+    }
+
+    if (found)
+      break;
+
+    else {
+      //release the lock
+      mutexBlocks->UnLock();                    //unlock
+      this->accessReadList->Signal();           //signal unlock
+      this->readBlockAdded->Wait();
+    }
+  }
+
+  if (found){
+    //return the buffer found in list
+
+    //release the lock
+    mutexBlocks->UnLock();                     //unlock
+    this->accessReadList->Signal();            //signal unlock
+
+
+    Int_t auxInt = 0;                          //aux for internal buffer
+    Int_t auxExt = 0;                          //aux for external buffer
+    char* ptrInt = NULL, *ptrExt = NULL;
+
+    for(Int_t i=0; i < noBuf; i++){
+
+      ptrInt = blockObj->GetBuffer();
+      ptrInt += auxInt;
+
+      ptrExt = buf;
+      ptrExt += auxExt;
+
+      //read only the parts that you are interested in
+      memcpy(ptrExt, ptrInt, len[i]);
+
+      auxInt += blockObj->GetLen(i);
+      auxExt += len[i];
+    }
+  }
+  else{
+    //buffer not found, release the lock
+    mutexBlocks->UnLock();                     //unlock
+    this->accessReadList->Signal();            //signal unlock
+    blockObj= NULL;
+  }
+
+  return found;
+}
+
+
+//____________________________________________________________________________________________
+//search for a requested segment in the list of segments in a block and return the index
+Bool_t TFilePrefetch::BinarySearchReadList(TFPBlock* blockObj, Long64_t offset, Int_t len, Int_t* index){
+
+  Int_t first = 0, last = -1, mid = -1;
+  last = (Int_t) blockObj->GetNoElem()-1;
+
+  while (first <= last){
+
+    mid = first + (last - first) / 2;
+    if ((offset >= blockObj->GetPos(mid) && offset <= (blockObj->GetPos(mid) + blockObj->GetLen(mid))
+         && ( (offset + len) <= blockObj->GetPos(mid) + blockObj->GetLen(mid)))){
+
+      //if current segment good return index
+      *index = mid;
+      return true;
+    }
+    else if (blockObj->GetPos(mid) < offset){
+      //search in the right side left
+      first = mid + 1;
+    }
+    else{
+      //search in the left side left
+      last = mid - 1;
+    }
+  }
+  return false;
+}
+
+
+//____________________________________________________________________________________________
+//method used to read a segment of the block
+Bool_t TFilePrefetch::ReadBuffer(char* buf, Long64_t offset, Int_t len){
+
+  Bool_t found = false;
+  TFPBlock* blockObj = NULL;
+  TMutex *mutexBlocks = this->accessReadList->GetMutex();
+  Int_t index = -1;
+
+  while (1){
+
+    while (mutexBlocks->Lock() != 0)            //failed to lock
+      this->accessReadList->Wait();             //wait for signal
+
+    TIter iter(this->readBlocks);
+    while ((blockObj = (TFPBlock*) iter.Next())){
+
+      // binary serach in the list
+      index = -1;
+      if (this->BinarySearchReadList(blockObj, offset, len, &index)){
+	found = true;
+	break;
+      }    
+    }
+
+    if (found)
+      break;
+    else{
+      //release the lock
+      mutexBlocks->UnLock();                   //unlock
+      this->accessReadList->Signal();          //signal unlock
+      this->readBlockAdded->Wait();            //wait for a new block to be added
+    }
+  }
+
+  if (found){
+
+    Int_t auxInt = 0;                          //aux for internal buffer
+    char* ptrInt = NULL;                       //pointer to the buffer
+
+    for(Int_t i=0; i < blockObj->GetNoElem(); i++){
+
+      ptrInt = blockObj->GetBuffer();
+      ptrInt += auxInt;
+
+      //read only the parts that we are interested in
+      if (index == i){
+
+	ptrInt+= (offset - blockObj->GetPos(i));
+	memcpy(buf, ptrInt, len);
+	break;
+      }
+      auxInt += blockObj->GetLen(i);
+    }
+  }
+
+  //release the lock
+  mutexBlocks->UnLock();                       //unlock 			
+  this->accessReadList->Signal();              //signal unlock
+ 
+  return found;
+}
+
+
+//____________________________________________________________________________________________
+//add a new block to the list
+void TFilePrefetch::ReadBlock(Long64_t* offset, Int_t* len, Int_t nblock){
+
+  //create a TFPBlock object or recycle one and add it to the prefetchBlocks list
+  TFPBlock* block = CreateBlockObj(offset, len, nblock);
+  this->AddPendingBlock(block);
+}
+
+
+//____________________________________________________________________________________________
+//safe method to add a block to the pendingList
+void TFilePrefetch::AddPendingBlock(TFPBlock* block){
+
+  TMutex *mutexBlocks = this->accessPendingList->GetMutex();
+
+  while (mutexBlocks->Lock() != 0)           //failed to lock
+    this->accessPendingList->Wait();         //wait for signal
+
+  this->pendingBlocks->Add(block);
+
+  //release the lock
+  mutexBlocks->UnLock();                    //unlock
+  this->accessPendingList->Signal();        //signal unlock
+  this->newBlockAdded->Signal();            //signal the addition of a block
+
+}
+
+
+//____________________________________________________________________________________________
+//safe method to remove a block from the pendingList
+TFPBlock* TFilePrefetch::GetPendingBlock(){
+
+  TFPBlock* block = NULL;
+  TMutex *mutexBlocks = this->accessPendingList->GetMutex();
+
+  while (mutexBlocks->Lock() != 0)         //failed to lock
+    this->accessPendingList->Wait();       //wait for signal
+
+  if (this->pendingBlocks->GetSize()){
+
+    block = (TFPBlock*)this->pendingBlocks->First();
+    block = (TFPBlock*)this->pendingBlocks->Remove(block);
+  }
+  //release the lock
+  mutexBlocks->UnLock();                   //unlock
+  this->accessPendingList->Signal();       //signal unlock
+
+  return block;
+}
+
+
+//____________________________________________________________________________________________
+//safe method to add a block to the readList
+void TFilePrefetch::AddReadBlock(TFPBlock* block){
+
+  TMutex *mutexBlocks = this->accessReadList->GetMutex();
+
+  while (mutexBlocks->Lock() != 0)         //failed to lock
+    this->accessReadList->Wait();          //wait for signal
+
+  //add the block but check if it satisfies the size constraint
+  //if not move one block to the recycle list
+  if (this->readBlocks->GetSize() >= MAX_READ_SIZE){
+
+    //extract one block from READ list
+    TFPBlock* movedBlock = (TFPBlock*) this->readBlocks->First();
+    movedBlock = (TFPBlock*)this->readBlocks->Remove(movedBlock);
+
+    //insert it in the RECYCLE list
+    this->AddRecycleBlock(movedBlock);
+  }
+
+  //add the current block to the READ list
+  this->readBlocks->Add(block);
+
+  //release the lock
+  mutexBlocks->UnLock();                  //unlock
+  this->accessReadList->Signal();         //signal unlock
+  this->readBlockAdded->Signal();
+}
+
+
+//____________________________________________________________________________________________
+//safe method to remove a block from the readList
+//NOT USED - removes the block from the list when reading
+TFPBlock* TFilePrefetch::GetReadBlock(){
+
+  TFPBlock* block = NULL;
+  TMutex *mutexBlocks = this->accessReadList->GetMutex();
+
+  while (mutexBlocks->Lock() != 0)        //failed to lock
+    this->accessReadList->Wait();         //wait for signal
+
+  if (this->readBlocks->GetSize()){
+
+    block = (TFPBlock*)this->readBlocks->Last();
+    this->readBlocks->RemoveLast();
+  }
+  //release the lock
+  mutexBlocks->UnLock();                 //unlock
+  this->accessReadList->Signal();        //signal unlock
+
+  return block;
+}
+
+
+//____________________________________________________________________________________________
+//safe method to add a block to the recycleList
+void TFilePrefetch::AddRecycleBlock(TFPBlock* block){
+
+  TMutex *mutexBlocks = this->accessRecycleList->GetMutex();
+
+  while (mutexBlocks->Lock() != 0)      //failed to lock
+    this->accessRecycleList->Wait();    //wait for signal
+
+  if (this->recycleBlocks->GetSize() >= MAX_RECYCLE_SIZE){
+    //delete the block for good
+    delete block;
+  }
+  else
+    this->recycleBlocks->Add(block);
+
+  //release the lock
+  mutexBlocks->UnLock();                 //unlock
+  this->accessRecycleList->Signal();     //signal unlock
+}
+
+
+//____________________________________________________________________________________________
+//create a new block or recycle an old one
+TFPBlock* TFilePrefetch::CreateBlockObj(Long64_t* offset, Int_t* len, Int_t noblock){
+
+  TFPBlock* blockObj = NULL;
+
+  //synchronize access to the recycle list
+  TMutex *mutexRecycle = this->accessRecycleList->GetMutex();
+
+  while (mutexRecycle->Lock() != 0)        //failed to lock
+    this->accessRecycleList->Wait();       //wait for signal
+
+  if (this->recycleBlocks->GetSize()){
+
+    //reallocate an already used block
+    blockObj = static_cast<TFPBlock*>(this->recycleBlocks->First());
+    this->recycleBlocks->Remove(blockObj);
+
+    blockObj->ReallocBlock(offset, len, noblock);
+    
+    //release the lock
+    mutexRecycle->UnLock();                //unlock
+    this->accessRecycleList->Signal();     //signal unlock
+  }
+  else{
+    
+    //release the lock
+    mutexRecycle->UnLock();                //unlock
+    this->accessRecycleList->Signal();     //signal unlock
+
+    //create a new block from scratch
+    blockObj = new TFPBlock(offset, len, noblock);
+  }
+
+  return blockObj;
+}
+
+
+//____________________________________________________________________________________________
+//function used to start a generic thread
+Int_t TFilePrefetch::ThreadStart(void (*function)(void*)){
+
+  if((*function) == (&this->ConsumerThread)){
+
+    //Start consumer thread
+    this->consumer= new TThread("consumerThread",
+				(void(*) (void *))*function,
+				(void*) this);
+    this->consumer->Run();
+  }
+  return 1;
+}
+
+
+//____________________________________________________________________________________________
+//function used to kill the CONSUMER thread
+Int_t TFilePrefetch::ThreadStop(){
+
+  if(this->consumer){
+    printf( "Killing the consumer thread... \n");
+    TThread::Delete(this->consumer);
+    this->consumer=0;
+    return 0;
+  }
+  return 1;
+}
+
+
+//____________________________________________________________________________________________
+//actions executed by the CONSUMER thread
+void TFilePrefetch::ConsumerThread(void* arg){
+
+  TFilePrefetch* tmp = (TFilePrefetch*) arg;
+  
+  //enable cancelation 
+  TThread::SetCancelAsynchronous();
+  TThread::SetCancelOn();
+ 
+  while(1){
+
+    //read the blocks in buffers
+    tmp->ReadListOfBlocks();
+
+    //wait for the signal
+    tmp->newBlockAdded->Wait();
+  } 
+}
+
+
+//########################################################################################################################
+//########################################################################################################################
+//########################################################################################################################
+//########################################### CACHING PART ###############################################################
+//########################################################################################################################
+
+
+//____________________________________________________________________________________________
+//add the individual hex values to obtain a decimal value
+Int_t TFilePrefetch::SumHex(char *hex)
+{
+  Int_t result = 0;
+  char* ptr = hex;
+
+  for(Int_t i=0; i < (Int_t)strlen(hex); i++)
+    result += xtod(ptr[i]);
+
+  return result;
+}
+
+
+//____________________________________________________________________________________________
+//test if the block is in cache
+Bool_t TFilePrefetch::CheckBlockInCache(char*& path, TFPBlock* block){
+
+  Bool_t found = false;
+  TString fullPath;                            //path of the cached files
+  Int_t value = 0;
+  FileStat_t* stat = new FileStat_t();
+
+  //if cache directory not set return
+  if (!this->pathCache){
+    delete stat;
+    return false;
+  }
+  else
+    fullPath = *(this->pathCache);
+
+  //if directory doesn't exist then create it
+  if (gSystem->OpenDirectory(fullPath.Data()) == 0)
+    gSystem->mkdir(fullPath.Data());           //create directory
+
+  char* concatStr = new char[100];
+  TString fileName, dirName;
+
+  //dir is SHA1 value modulo 16; filename is the value of the SHA1(offset+len)
+  TMD5* md = new TMD5();
+
+  //add the position and length to the string
+  for (Int_t i=0; i < block->GetNoElem(); i++){
+    sprintf(concatStr, "%lld", block->GetPos(i));
+    md->Update((UChar_t*)concatStr, strlen(concatStr));
+  }
+
+  md->Final();
+
+  //file name will be the SHA1 value
+  fileName = md->AsString();
+
+  //convert it to Int_t and find the value MOD 16
+  value = this->SumHex((char *)fileName.Data());
+  value = value % 16;
+
+  sprintf(concatStr, "%i", value);
+  dirName = concatStr;
+
+  //construct the full path
+  fullPath += "/" + dirName + "/" + fileName;
+
+  //check if the file really exists
+  if (gSystem->GetPathInfo(fullPath.Data(), *stat) == 0){      //successful
+
+    path = new char[fullPath.Sizeof() + 1];
+    strcpy(path, fullPath.Data());
+    found = true;
+  }
+  else
+    found = false;
+
+  //free memory
+  delete[] concatStr;
+  delete stat;
+  delete md;
+
+  return found;
+}
+
+
+//____________________________________________________________________________________________
+//return a buffer from cache
+char* TFilePrefetch::GetBlockFromCache(char* path, Int_t length){
+
+  char*buffer = NULL;
+  TString strPath = path;
+
+  strPath += "?filetype=raw";
+
+  TFile* file = new TFile(strPath.Data());
+
+  buffer = (char*) calloc(length+1, sizeof(char));
+  file->ReadBuffer(buffer, 0, length);     //read entire file
+  
+  //free memory
+  delete file;
+  return buffer;
+}
+
+
+//____________________________________________________________________________________________
+//save the block content in cache
+void TFilePrefetch::SaveBlockInCache(TFPBlock* block){
+
+  TString fullPath;
+  TString fileName, dirName;
+  char* concatStr = new char[100];
+  Int_t value = 0;
+  TFile* file = NULL;
+
+  //if cache directory not set return
+  if (!this->pathCache){
+    delete[] concatStr;
+    return;
+  }
+  else
+    fullPath = *(this->pathCache);
+
+  //dir is SHA1 value modulo 16; filename is the value of the SHA1
+  TMD5* md = new TMD5();
+  FileStat_t* stat = new FileStat_t();
+
+  //add the position and length
+  for(Int_t i=0; i< block->GetNoElem(); i++){
+    sprintf(concatStr, "%lld", block->GetPos(i));
+    md->Update((UChar_t*)concatStr, strlen(concatStr));
+  }
+  md->Final();
+
+  //file name will be the SHA1 value
+  fileName  = md->AsString();
+
+  //convert it to Long64_t and find the value MOD 16
+  value = this->SumHex((char*)fileName.Data());
+  value = value % 16;
+
+  sprintf(concatStr, "%i", value);
+  dirName = concatStr;
+
+  //construct the full path to directory
+  fullPath += ("/" + dirName);
+
+  //if directory doesn't exist then create it
+  if (gSystem->OpenDirectory(fullPath.Data()) == 0)
+    gSystem->mkdir(fullPath.Data());             //create directory
+
+  //create full path to the file
+  fullPath += ("/" + fileName);
+
+  if (gSystem->GetPathInfo(fullPath.Data(), *stat) == 0){    //success
+    //open file for update
+    fullPath += "?filetype=raw";
+    file = TFile::Open(fullPath.Data(), "update");
+  }
+  else{
+    //create the file
+    fullPath += "?filetype=raw";
+    file = TFile::Open(fullPath.Data(), "new");
+  }
+
+  file->WriteBuffer(block->GetBuffer(), block->GetFullSize());
+  file->Close();
+
+  //free memory
+  file = 0;
+  delete file;
+  delete stat;
+  delete[] concatStr;
+  delete md;
+}
+
+
+//____________________________________________________________________________________________
+//used to validate the input pathCache
+Bool_t TFilePrefetch::CheckCachePath(char* locationCache){
+
+  Bool_t found = true;
+  TString path = locationCache;
+
+  TObjArray* obj = path.Tokenize(":");
+
+  if (obj->GetEntries() == 2){
+    TString protocol   = ((TObjString*)obj->At(0))->GetName();
+    TString directory  = ((TObjString*)obj->At(1))->GetName();
+
+    //check if protocol is correctly formed
+    if (!protocol.CompareTo("file", TString::kIgnoreCase) &&
+	!protocol.CompareTo("root", TString::kIgnoreCase) &&
+	!protocol.CompareTo("rfio", TString::kIgnoreCase))
+
+      found = false;
+    else{
+      //check if the path is correctly formed
+      for(Int_t i=0; i < directory.Sizeof()-1; i++)
+	if (!isdigit(directory[i]) && !isalpha(directory[i]) && directory[i]!='/'){
+	  found = false;
+	  break;
+	}
+    }
+  }
+  else
+    found = false;
+
+  return found;
+}
+
+
+//____________________________________________________________________________________________
+//set the path to the cache directory
+Bool_t TFilePrefetch::SetCache(char* path){
+
+  if (this->CheckCachePath(path)){
+    this->pathCache = new TString(path);
+
+    //check if the path exists
+    if (!gSystem->OpenDirectory(path)){	  //failure create the directory
+      printf("The path does not exist, but is created\n");;
+      gSystem->mkdir(path);
+    }
+  }
+  else{
+    printf("The path is not well-formed\n");
+    return false;
+  }
+  return true;
+}
+

Property changes on: io/io/src/TFilePrefetch.cxx
___________________________________________________________________
Added: svn:executable
   + *

Index: io/io/src/TVirtualFilePrefetch.cxx
===================================================================
--- io/io/src/TVirtualFilePrefetch.cxx	(revision 0)
+++ io/io/src/TVirtualFilePrefetch.cxx	(revision 2)
@@ -0,0 +1,7 @@
+
+#ifndef ROOT_TVirtualFilePrefetch
+#include "TVirtualFilePrefetch.h"
+#endif
+
+
+ClassImp(TVirtualFilePrefetch)
Index: io/io/src/TFile.cxx
===================================================================
--- io/io/src/TFile.cxx	(revision 1)
+++ io/io/src/TFile.cxx	(working copy)
@@ -164,6 +164,7 @@
    fMustFlush       = kTRUE;
    fAsyncHandle     = 0;
    fAsyncOpenStatus = kAOSNotAsync;
+   fPrefetch        = 0;
    SetBit(kBinaryFile, kTRUE);
 
    if (gDebug)
@@ -320,6 +321,32 @@
    fReadCalls    = 0;
    SetBit(kBinaryFile, kTRUE);
 
+   //initialise the prefetch object and set the cache directory
+   // start the thread only if the file is not local  
+   fPrefetch     = 0;
+
+   if (strcmp(fUrl.GetProtocol(), "file")){
+
+     fPrefetch = new TFilePrefetch(this);
+     TString str(fUrl.GetOptions());
+     TObjArray* objs = str.Tokenize("&");
+
+     for (Int_t i = 0; i < objs->GetEntries(); i++) {
+       TString optObj = ((TObjString*)objs->At(i))->GetName();
+       TObjArray *objTags = optObj.Tokenize("=");
+       if (objTags->GetEntries() == 2) {
+         TString key   = ((TObjString*)objTags->At(0))->GetName();
+         TString value = ((TObjString*)objTags->At(1))->GetName();
+         if (!key.CompareTo("CACHEDIR", TString::kIgnoreCase)) {
+	   cout << "The cache directory is: " << value << endl;
+	   fPrefetch->SetCache((char*)value.Data());
+	   break;
+         }
+       }
+     }
+     fPrefetch->ThreadStart(&fPrefetch->ConsumerThread);
+   }
+
    fOption.ToUpper();
 
    fArchiveOffset = 0;
@@ -466,9 +493,21 @@
 TFile::~TFile()
 {
    // File destructor.
+   if (fPrefetch){
+     //kill th consumer thread                                                                 
 
+     //enable cancelation
+     TThread::SetCancelAsynchronous();
+     TThread::SetCancelOn();
+                                                      
+     fPrefetch->ThreadStop();
+     
+     //reset inital state
+     TThread::SetCancelOff();
+     TThread::SetCancelDeferred();  
+   }
+
    Close();
-
    SafeDelete(fProcessIDs);
    SafeDelete(fFree);
    SafeDelete(fArchive);
@@ -1486,8 +1525,10 @@
    // 2 in case read via cache failed.
 
    Long64_t off = GetRelOffset();
+   //printf("RedaBufferViCache: fCacheRead = %p \n", fCacheRead);
    if (fCacheRead) {
       Int_t st = fCacheRead->ReadBuffer(buf, off, len);
+      
       if (st < 0)
          return 2;  // failure reading
       else if (st == 1) {
Index: io/io/src/TFPBlock.cxx
===================================================================
--- io/io/src/TFPBlock.cxx	(revision 0)
+++ io/io/src/TFPBlock.cxx	(revision 2)
@@ -0,0 +1,102 @@
+#include "TFPBlock.h"
+#include <cstdlib>
+
+ClassImp(TFPBlock)
+
+//__________________________________________________________________
+//constructor
+TFPBlock::TFPBlock(Long64_t* offset, Int_t* length, Int_t nb){
+
+  Int_t aux = 0;
+  
+  this->nblock = nb;
+  this->pos = new Long64_t[nb];
+  this->len = new Int_t[nb];
+ 
+  for (Int_t i=0; i < nb; i++){
+           this->pos[i] = offset[i];
+           this->len[i] = length[i];
+           aux += length[i]; 
+  }
+  this->fullSize = aux;
+  this->buffer = (char*) calloc(this->fullSize, sizeof(char));
+}
+
+//__________________________________________________________________
+//destructor
+TFPBlock::~TFPBlock(){
+
+  delete[] pos;
+  delete[] len;
+  free(buffer);
+}
+
+//__________________________________________________________________
+Long64_t* TFPBlock::GetPos(){
+
+  return this->pos;
+}
+
+//__________________________________________________________________
+Int_t* TFPBlock::GetLen(){
+
+  return this->len;
+}
+
+//__________________________________________________________________
+Int_t TFPBlock::GetFullSize(){
+
+  return this->fullSize;
+}
+
+//__________________________________________________________________
+Int_t TFPBlock::GetNoElem(){
+
+  return this->nblock;
+}
+
+//__________________________________________________________________
+Long64_t TFPBlock::GetPos(Int_t i){
+
+  return this->pos[i];
+}
+
+//__________________________________________________________________
+Int_t TFPBlock::GetLen(Int_t i){
+
+  return this->len[i];
+}
+
+//__________________________________________________________________
+char* TFPBlock::GetBuffer(){
+
+  return this->buffer;
+}
+
+//__________________________________________________________________
+void TFPBlock::SetBuffer(char* buf){
+
+  this->buffer = buf;
+}
+
+//__________________________________________________________________
+void TFPBlock::ReallocBlock(Long64_t* offset, Int_t* length, Int_t nb){
+
+  Int_t aux = 0;
+
+  this->nblock = nb;
+  this->pos = new Long64_t[nb];
+  this->len = new Int_t[nb];
+
+  for(Int_t i=0; i < nb; i++){
+
+    this->pos[i] = offset[i];
+    this->len[i] = length[i];
+    aux += this->len[i];
+  }
+
+  this->fullSize = aux;
+  this->buffer = (char*) realloc(this->buffer, this->fullSize);
+}
+
+

Property changes on: io/io/src/TFPBlock.cxx
___________________________________________________________________
Added: svn:executable
   + *

Index: io/io/inc/TVirtualFilePrefetch.h
===================================================================
--- io/io/inc/TVirtualFilePrefetch.h	(revision 0)
+++ io/io/inc/TVirtualFilePrefetch.h	(revision 2)
@@ -0,0 +1,52 @@
+
+#ifndef ROOT_TVirtualFilePrefetch
+#define ROOT_TVirtualFilePrefetch
+
+#ifndef ROOT_TObject
+#include "TObject.h"
+#endif
+
+#ifndef ROOT_TFPBlock
+#include "TFPBlock.h"
+#endif
+
+class TVirtualFilePrefetch : public TObject{
+
+ public:
+  TVirtualFilePrefetch(){ }
+  virtual ~TVirtualFilePrefetch(){ }                                  //! class destructor
+
+  virtual void        ReadAsync(TFPBlock*, Bool_t*) = 0;                       //! read just one block
+  virtual void        ReadListOfBlocks() = 0;                         //! read all the blocks in the list prefetchBlocks
+ 
+  //prefetchBlocks for the pendingList
+  virtual void        AddPendingBlock(TFPBlock*) = 0;
+  virtual TFPBlock   *GetPendingBlock() = 0;
+
+  //methods for the readList
+  virtual void        AddReadBlock(TFPBlock*) = 0;
+  virtual TFPBlock   *GetReadBlock() = 0;
+
+  //methods for the recycleList
+  virtual void        AddRecycleBlock(TFPBlock*) = 0;
+ 
+  //virtual void readBlock(Long64_t*, Int_t*, Int_t);                 //! called from exterior to introduce a block in the list
+  virtual Bool_t      ReadBuffer(char*, Long64_t*, Int_t*, Int_t) = 0;
+  virtual Bool_t      ReadBuffer(char*, Long64_t, Int_t) = 0;
+
+  virtual TFPBlock   *CreateBlockObj(Long64_t* , Int_t*, Int_t) = 0;  //! create a new buffer or recycle an old one
+
+  virtual Int_t       ThreadStart(void (*function)(void*)) = 0;       //! start thread
+  virtual Int_t       ThreadStop() = 0;                               //! stop threads
+
+  virtual Bool_t      SetCache(char*) = 0;                            //! set the location of the cache directory
+  virtual Bool_t      CheckCachePath(char*) = 0;                      //! used to validate the input pathCache
+  virtual Bool_t      CheckBlockInCache(char*&, TFPBlock*) = 0;       //! test if block is in cache
+  virtual char       *GetBlockFromCache(char*, Int_t) = 0;            //! get the block if in cache else return null
+  virtual void        SaveBlockInCache(TFPBlock*) = 0;                //! save the buffer content in cache
+
+  virtual Int_t       SumHex(char*) = 0;                              //! add the values from a hex rep. to produce an int
+
+  ClassDef(TVirtualFilePrefetch, 0);
+};
+#endif
Index: io/io/inc/TFile.h
===================================================================
--- io/io/inc/TFile.h	(revision 1)
+++ io/io/inc/TFile.h	(working copy)
@@ -27,6 +27,9 @@
 #ifndef ROOT_TUrl
 #include "TUrl.h"
 #endif
+#ifndef ROOT_TFilePrefetch
+#include "TFilePrefetch.h"
+#endif
 
 class TFree;
 class TArrayC;
@@ -36,8 +39,8 @@
 class TFileCacheWrite;
 class TProcessID;
 class TStopwatch;
+class TFilePrefetch;
 
-
 class TFile : public TDirectoryFile {
   friend class TDirectoryFile;
 
@@ -48,6 +51,8 @@
    // Open timeout constants
    enum EOpenTimeOut { kInstantTimeout = 0, kEternalTimeout = 999999999 };
 
+   TFilePrefetch   *fPrefetch;       //!Object that does the asynchronous reading in another thread
+
 protected:
    Double_t         fSumBuffer;      //Sum of buffer sizes of objects written so far
    Double_t         fSum2Buffer;     //Sum of squares of buffer sizes of objects written so far
Index: io/io/inc/TFPBlock.h
===================================================================
--- io/io/inc/TFPBlock.h	(revision 0)
+++ io/io/inc/TFPBlock.h	(revision 2)
@@ -0,0 +1,38 @@
+#ifndef ROOT_TFPBlock
+#define ROOT_TFPBlock
+
+#ifndef ROOT_TObject
+#include "TObject.h"
+#endif
+
+class TFPBlock : public TObject{
+
+public:
+
+  TFPBlock(Long64_t*, Int_t*, Int_t);                 //! constructor
+  ~TFPBlock();                                        //! destructor
+
+  Long64_t GetPos(Int_t);                             //! the position of the segment at a certain index
+  Int_t GetLen(Int_t);                                //! the length of a segment at a certain index   
+
+  Long64_t* GetPos();                                 //! a pointer to the array of positions
+  Int_t* GetLen();                                    //! a pointer to the array of lengths
+  Int_t GetFullSize();                                //! the full size of the buffer
+  Int_t GetNoElem();                                  //! number of segments in the block
+  char* GetBuffer();                                  //! pointer to the actual buffer
+
+  void SetBuffer(char*);                              //! set the value of the buffer
+  void ReallocBlock(Long64_t*, Int_t*, Int_t);        //! function used to reallocate the elemnts of the block
+                                                      //  given the size and the two arrays of postions and lengths
+
+private:
+  
+  Long64_t* pos;
+  Int_t* len;
+  Int_t nblock, fullSize;
+  char* buffer;
+
+  ClassDef(TFPBlock, 1);
+};
+#endif
+

Property changes on: io/io/inc/TFPBlock.h
___________________________________________________________________
Added: svn:executable
   + *

Index: io/io/inc/LinkDef.h
===================================================================
--- io/io/inc/LinkDef.h	(revision 1)
+++ io/io/inc/LinkDef.h	(working copy)
@@ -44,6 +44,10 @@
 #pragma link C++ options=version(0) class TVirtualObject-;
 #pragma link C++ options=version(0) class TVirtualArray-;
 
+#pragma link C++ class TFPBlock+;
+#pragma link C++ class TFilePrefetch+;
+#pragma link C++ options=version(0) class TVirtualFilePrefetch;
+
 #pragma link C++ namespace TStreamerInfoActions;
 #pragma link C++ class TStreamerInfoActions::TConfiguredAction+;
 #pragma link C++ class TStreamerInfoActions::TActionSequence+;
Index: io/io/inc/TFileCacheRead.h
===================================================================
--- io/io/inc/TFileCacheRead.h	(revision 1)
+++ io/io/inc/TFileCacheRead.h	(working copy)
@@ -54,6 +54,23 @@
    Bool_t        fIsSorted;       //True if fSeek array is sorted
    Bool_t        fIsTransferred;   //True when fBuffer contains something valid
 
+   //varibales and pointers for the second block prefetched
+   Int_t         fBNseek;
+   Int_t         fBNtot;
+   Int_t         fBNb;
+   Int_t         fBSeekSize;
+   Long64_t     *fBSeek;
+   Long64_t     *fBSeekSort;
+   Int_t        *fBSeekIndex;
+   Long64_t     *fBPos;
+   Int_t        *fBSeekLen;
+   Int_t        *fBSeekSortLen;
+   Int_t        *fBSeekPos;
+   Int_t        *fBLen;
+   Bool_t        fBIsSorted;
+   Bool_t        fBIsTransferred;
+   Bool_t        fBDone;           //Done with using the second block                       
+
 private:
    TFileCacheRead(const TFileCacheRead &);            //cannot be copied
    TFileCacheRead& operator=(const TFileCacheRead &);
@@ -75,7 +92,10 @@
    virtual void        SetFile(TFile *file);
    virtual void        SetSkipZip(Bool_t /*skip*/ = kTRUE) {} // This function is only used by TTreeCacheUnzip (ignore it)
    virtual void        Sort();
+   virtual void        SecondSort();                          //Method used to sort and merge the chunks in the second block
+   virtual void        SecondPrefetch(Long64_t, Int_t);       //Used to add chunks to the second block
 
+
    ClassDef(TFileCacheRead,1)  //TFile cache when reading
 };
 
Index: io/io/inc/TFilePrefetch.h
===================================================================
--- io/io/inc/TFilePrefetch.h	(revision 0)
+++ io/io/inc/TFilePrefetch.h	(revision 2)
@@ -0,0 +1,106 @@
+#ifndef ROOT_TFilePrefetch
+#define ROOT_TFilePrefetch
+
+#ifndef ROOT_TFile
+#include "TFile.h"
+#endif
+
+#ifndef ROOT_TThread
+#include "TThread.h"
+#endif
+
+#ifndef ROOT_TFPBlock
+#include "TFPBlock.h"
+#endif
+
+#ifndef ROOT_TCondition
+#include "TCondition.h"
+#endif
+
+#ifndef ROOT_TMD5
+#include "TMD5.h"
+#endif
+
+#ifndef ROOT_TObject
+#include "TObject.h"
+#endif
+
+#ifndef ROOT_TString
+#include "TString.h"
+#endif
+
+#ifndef ROOT_TObjString
+#include "TObjString.h"
+#endif
+
+#ifndef ROOT_TMutex
+#include "TMutex.h"
+#endif
+
+#ifndef ROOT_TObjArray
+#include "TObjArray.h"
+#endif
+
+#ifndef ROOT_TVirtualFilePrefetch
+#include "TVirtualFilePrefetch.h"
+#endif
+
+class TFilePrefetch : public TVirtualFilePrefetch {
+
+public:
+  
+  TFilePrefetch(TFile*);                                    //! constructor
+  ~TFilePrefetch();                                         //! destructor
+
+  void ReadAsync(TFPBlock*, Bool_t*);                                //! function that does the actual reading(lowest level)
+  void ReadListOfBlocks();                                  //! read all the blocks in the list prefetchBlocks
+
+  //for the pendingList
+  void AddPendingBlock(TFPBlock*);                          //! method to add a block to the pending list of blocks
+  TFPBlock* GetPendingBlock();                              //! retrieve a block from the list of pending blocks
+
+  //methods for the readList
+  void AddReadBlock(TFPBlock*);                             //! method to add a block to the list of read blocks
+  TFPBlock* GetReadBlock();                                 //! retrieve a block from the list of read blocks
+
+  //methods for the recycleList
+  void AddRecycleBlock(TFPBlock*);                          //! method to add a block to the list of recycled blocks
+ 
+  //prefecthBuffers
+  Bool_t ReadBuffer(char*, Long64_t*, Int_t*, Int_t);       //! test if buffer is prefetched and return it
+  Bool_t ReadBuffer(char*, Long64_t, Int_t);                //! test if segment if prefetched and return it
+ 
+  //manipulate blocks
+  void ReadBlock(Long64_t*, Int_t*, Int_t);                 //! submit a request from the main thread
+  TFPBlock* CreateBlockObj(Long64_t*, Int_t*, Int_t);       //! create a new block or recycle an old one
+
+  //threads
+  static void ConsumerThread(void*);                        //! actions executed by the consumer thread
+  Int_t ThreadStart(void (*function)(void*));               //! start thread
+  Int_t ThreadStop();                                       //! stop thread
+
+  //cache path
+  Bool_t SetCache(char*);                                   //! set the path to the cache directory
+  Bool_t CheckCachePath(char*);                             //! used to validate the input pathCache
+  Bool_t CheckBlockInCache(char*&, TFPBlock*);              //! test if block is in cache
+  char* GetBlockFromCache(char*, Int_t);                    //! get the block if in cache else return null
+  void SaveBlockInCache(TFPBlock*);                         //! save the buffer content in cache
+
+  Int_t SumHex(char*);                                      //! add the values from a hex rep. to produce an integer 
+  Bool_t BinarySearchReadList(TFPBlock*, Long64_t, Int_t, Int_t*);  //! search segments in a block corresponding to the current segment request
+
+private:
+
+  TFile* f;                                                 //! reference to the file
+  TList* pendingBlocks, *readBlocks, *recycleBlocks;        //! list of blocks to be prefetched
+  TThread* consumer;                                        //! thread reference
+  TCondition* accessPendingList,                            //! mutex for access to lists
+    *accessReadList,
+    *accessRecycleList,
+    *newBlockAdded,
+    *readBlockAdded;
+  TString* pathCache;                                       //! path to the cache directory
+
+  ClassDef(TFilePrefetch, 1);
+};
+#endif

Property changes on: io/io/inc/TFilePrefetch.h
___________________________________________________________________
Added: svn:executable
   + *

