ROOT logo
// @(#)root/tree:$Id: 4e77188fbf1e7fd026a984989de66663c49b12fc $
// Author: Rene Brun   19/01/96
/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TBasket.h"
#include "TBufferFile.h"
#include "TTree.h"
#include "TBranch.h"
#include "TFile.h"
#include "TBufferFile.h"
#include "TMath.h"
#include "TTreeCache.h"
#include "TVirtualPerfStats.h"
#include "TTimeStamp.h"
#include "RZip.h"

// TODO: Copied from TBranch.cxx
#if (__GNUC__ >= 3) || defined(__INTEL_COMPILER)
#if !defined(R__unlikely)
  #define R__unlikely(expr) __builtin_expect(!!(expr), 0)
#endif
#if !defined(R__likely)
  #define R__likely(expr) __builtin_expect(!!(expr), 1)
#endif
#else
  #define R__unlikely(expr) expr
  #define R__likely(expr) expr
#endif

const UInt_t kDisplacementMask = 0xFF000000;  // In the streamer the two highest bytes of
                                              // the fEntryOffset are used to stored displacement.

ClassImp(TBasket)

//_______________________________________________________________________
//
//  Manages buffers for branches of a Tree.
//  See picture in TTree.
//

//_______________________________________________________________________
TBasket::TBasket() : fCompressedBufferRef(0), fOwnsCompressedBuffer(kFALSE), fLastWriteBufferSize(0)
{
   // Default contructor.

   fDisplacement  = 0;
   fEntryOffset   = 0;
   fBufferRef     = 0;
   fBuffer        = 0;
   fHeaderOnly    = kFALSE;
   fBufferSize    = 0;
   fNevBufSize    = 0;
   fNevBuf        = 0;
   fLast          = 0;
   fBranch        = 0;
}

//_______________________________________________________________________
TBasket::TBasket(TDirectory *motherDir) : TKey(motherDir),fCompressedBufferRef(0), fOwnsCompressedBuffer(kFALSE), fLastWriteBufferSize(0)
{
   // Constructor used during reading.
   fDisplacement  = 0;
   fEntryOffset   = 0;
   fBufferRef     = 0;
   fBuffer        = 0;
   fHeaderOnly    = kFALSE;
   fBufferSize    = 0;
   fNevBufSize    = 0;
   fNevBuf        = 0;
   fLast          = 0;
   fBranch        = 0;
}

//_______________________________________________________________________
TBasket::TBasket(const char *name, const char *title, TBranch *branch) : 
   TKey(branch->GetDirectory()),fCompressedBufferRef(0), fOwnsCompressedBuffer(kFALSE), fLastWriteBufferSize(0)
{
   // Basket normal constructor, used during writing.

   SetName(name);
   SetTitle(title);
   fClassName   = "TBasket";
   fBufferSize  = branch->GetBasketSize();
   fNevBufSize  = branch->GetEntryOffsetLen();
   fNevBuf      = 0;
   fEntryOffset = 0;
   fDisplacement= 0;
   fBuffer      = 0;
   fBufferRef   = new TBufferFile(TBuffer::kWrite, fBufferSize);
   fVersion    += 1000;
   if (branch->GetDirectory()) {
      TFile *file = branch->GetFile();
      fBufferRef->SetParent(file);
   }
   fHeaderOnly  = kTRUE;
   fLast        = 0; // Must initialize before calling Streamer()
   if (branch->GetTree()) {
      fCompressedBufferRef = branch->GetTree()->GetTransientBuffer(fBufferSize);
      fOwnsCompressedBuffer = kFALSE;
      if (!fCompressedBufferRef) {
         fCompressedBufferRef = new TBufferFile(TBuffer::kRead, fBufferSize);
         fOwnsCompressedBuffer = kTRUE;
      }
   }
   Streamer(*fBufferRef);
   fKeylen      = fBufferRef->Length();
   fObjlen      = fBufferSize - fKeylen;
   fLast        = fKeylen;
   fBuffer      = 0;
   fBranch      = branch;
   fHeaderOnly  = kFALSE;
   if (fNevBufSize) {
      fEntryOffset = new Int_t[fNevBufSize];
      for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
   }
   branch->GetTree()->IncrementTotalBuffers(fBufferSize);
}

//_______________________________________________________________________
TBasket::~TBasket()
{
   // Basket destructor.

   if (fDisplacement) delete [] fDisplacement;
   if (fEntryOffset)  delete [] fEntryOffset;
   if (fBufferRef) delete fBufferRef;
   fBufferRef = 0;
   fBuffer = 0;
   fDisplacement= 0;
   fEntryOffset = 0;
   // Note we only delete the compressed buffer if we own it
   if (fCompressedBufferRef && fOwnsCompressedBuffer) {
      delete fCompressedBufferRef;
      fCompressedBufferRef = 0;
   }
}

//_______________________________________________________________________
void TBasket::AdjustSize(Int_t newsize)
{
   // Increase the size of the current fBuffer up to newsize.

   if (fBuffer == fBufferRef->Buffer()) {
      fBufferRef->Expand(newsize);
      fBuffer = fBufferRef->Buffer();
   } else {
      fBufferRef->Expand(newsize);
   }
   fBranch->GetTree()->IncrementTotalBuffers(newsize-fBufferSize);
   fBufferSize  = newsize;
}

//_______________________________________________________________________
Long64_t TBasket::CopyTo(TFile *to) 
{
   // Copy the basket of this branch onto the file to.

   fBufferRef->SetWriteMode();
   Int_t nout = fNbytes - fKeylen;
   fBuffer = fBufferRef->Buffer();
   Create(nout, to);
   fBufferRef->SetBufferOffset(0);
   fHeaderOnly = kTRUE;
   Streamer(*fBufferRef);
   fHeaderOnly = kFALSE;
   Int_t nBytes = WriteFileKeepBuffer(to);

   return nBytes>0 ? nBytes : -1;
}

//_______________________________________________________________________
void TBasket::DeleteEntryOffset()
{
   //  Delete fEntryOffset array.

   if (fEntryOffset) delete [] fEntryOffset;
   fEntryOffset = 0;
   fNevBufSize  = 0;
}


//_______________________________________________________________________
Int_t TBasket::DropBuffers()
{
   // Drop buffers of this basket if it is not the current basket.
   if (!fBuffer && !fBufferRef) return 0;

   if (fDisplacement) delete [] fDisplacement;
   if (fEntryOffset)  delete [] fEntryOffset;
   if (fBufferRef)    delete fBufferRef;
   if (fCompressedBufferRef && fOwnsCompressedBuffer) delete fCompressedBufferRef;
   fBufferRef   = 0;
   fCompressedBufferRef = 0;
   fBuffer      = 0;
   fDisplacement= 0;
   fEntryOffset = 0;
   fBranch->GetTree()->IncrementTotalBuffers(-fBufferSize);
   return fBufferSize;
}

//_______________________________________________________________________
Int_t TBasket::GetEntryPointer(Int_t entry)
{
   // Get pointer to buffer for internal entry.

   Int_t offset;
   if (fEntryOffset) offset = fEntryOffset[entry];
   else              offset = fKeylen + entry*fNevBufSize;
   fBufferRef->SetBufferOffset(offset);
   return offset;
}

//_______________________________________________________________________
Int_t TBasket::LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree)
{ 
   // Load basket buffers in memory without unziping.
   // This function is called by TTreeCloner.
   // The function returns 0 in case of success, 1 in case of error.

   if (fBufferRef) {
      // Reuse the buffer if it exist.
      fBufferRef->Reset();

      // We use this buffer both for reading and writing, we need to
      // make sure it is properly sized for writing.
      fBufferRef->SetWriteMode();
      if (fBufferRef->BufferSize() < len) {
         fBufferRef->Expand(len);
      }
      fBufferRef->SetReadMode();
   } else {
      fBufferRef = new TBufferFile(TBuffer::kRead, len);
   }
   fBufferRef->SetParent(file);
   char *buffer = fBufferRef->Buffer();
   file->Seek(pos);
   TFileCacheRead *pf = file->GetCacheRead(tree);
   if (pf) {
      TVirtualPerfStats* temp = gPerfStats;
      if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
      Int_t st = pf->ReadBuffer(buffer,pos,len);
      if (st < 0) {
         return 1;
      } else if (st == 0) {
         // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
         file->Seek(pos);
         // If we are using a TTreeCache, disable reading from the default cache
         // temporarily, to force reading directly from file
         TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
         if (fc) fc->Disable();
         Int_t ret = file->ReadBuffer(buffer,len);
         if (fc) fc->Enable();
         pf->AddNoCacheBytesRead(len);
         pf->AddNoCacheReadCalls(1);
         if (ret) {
            return 1;
         }
      }
      gPerfStats = temp;
      // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
      file->SetOffset(pos + len);
   } else {
      TVirtualPerfStats* temp = gPerfStats;
      if (tree->GetPerfStats() != 0) gPerfStats = tree->GetPerfStats();
      if (file->ReadBuffer(buffer,len)) {
         gPerfStats = temp;
         return 1; //error while reading
      }
      else gPerfStats = temp;
   }

   fBufferRef->SetReadMode();
   fBufferRef->SetBufferOffset(0);
   Streamer(*fBufferRef);

   return 0;
}

//_______________________________________________________________________
void TBasket::MoveEntries(Int_t dentries)
{
   // Remove the first dentries of this basket, moving entries at
   // dentries to the start of the buffer.

   Int_t i;

   if (dentries >= fNevBuf) return;
   Int_t bufbegin;
   Int_t moved;

   if (fEntryOffset) {
      bufbegin = fEntryOffset[dentries];
      moved = bufbegin-GetKeylen();

      // First store the original location in the fDisplacement array
      // and record the new start offset

      if (!fDisplacement) {
         fDisplacement = new Int_t[fNevBufSize];
      }
      for (i = 0; i<(fNevBufSize-dentries); ++i) {
         fDisplacement[i] = fEntryOffset[i+dentries];
         fEntryOffset[i]  = fEntryOffset[i+dentries] - moved;
      }
      for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
         fDisplacement[i] = 0;      
         fEntryOffset[i]  = 0;
      }

   } else {
      // If there is no EntryOffset array, this means
      // that each entry has the same size and that 
      // it does not point to other objects (hence there
      // is no need for a displacement array).
      bufbegin = GetKeylen() + dentries*fNevBufSize;
      moved = bufbegin-GetKeylen();
   }
   TBuffer *buf = GetBufferRef();
   char *buffer = buf->Buffer();
   memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
   buf->SetBufferOffset(buf->Length()-moved);
   fNevBuf -= dentries;
}

#define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
//_______________________________________________________________________
Int_t TBasket::ReadBasketBuffersUncompressedCase()
{
   // By-passing buffer unzipping has been requested and is
   // possible (only 1 entry in this basket). 
   fBuffer = fBufferRef->Buffer();

   // Make sure that the buffer is set at the END of the data
   fBufferRef->SetBufferOffset(fNbytes);

   // Indicate that this buffer is weird.
   fBufferRef->SetBit(TBufferFile::kNotDecompressed);

   // Usage of this mode assume the existance of only ONE
   // entry in this basket.
   delete [] fEntryOffset; fEntryOffset = 0;
   delete [] fDisplacement; fDisplacement = 0;

   fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
   return 0;
}

//_______________________________________________________________________
Int_t TBasket::ReadBasketBuffersUnzip(char* buffer, Int_t size, Bool_t mustFree, TFile* file)
{
   // We always create the TBuffer for the basket but it hold the buffer from the cache.
   if (fBufferRef) {
      fBufferRef->SetBuffer(buffer, size, mustFree);
      fBufferRef->SetReadMode();
      fBufferRef->Reset();
   } else {
      fBufferRef = new TBufferFile(TBuffer::kRead, size, buffer, mustFree);
   }
   fBufferRef->SetParent(file);

   Streamer(*fBufferRef);

   if (IsZombie()) {
      return -1;
   }

   Bool_t oldCase = OLD_CASE_EXPRESSION;

   if ((fObjlen > fNbytes-fKeylen || oldCase) && TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1)) {
      return TBasket::ReadBasketBuffersUncompressedCase();
   }

   fBuffer = fBufferRef->Buffer();
   return fObjlen+fKeylen;
}

//_______________________________________________________________________
static inline TBuffer* R__InitializeReadBasketBuffer(TBuffer* bufferRef, Int_t len, TFile* file)
{
   // Initialize a buffer for reading if it is not already initialized

   TBuffer* result;
   if (R__likely(bufferRef)) {
      bufferRef->SetReadMode();
      Int_t curBufferSize = bufferRef->BufferSize();
      if (curBufferSize < len) {
         // Experience shows that giving 5% "wiggle-room" decreases churn.
         bufferRef->Expand(Int_t(len*1.05));
      }
      bufferRef->Reset();
      result = bufferRef;
   } else {
      result = new TBufferFile(TBuffer::kRead, len);
   }
   result->SetParent(file);
   return result;
}

//_______________________________________________________________________
void inline TBasket::InitializeCompressedBuffer(Int_t len, TFile* file)
{
   // Initialize the compressed buffer; either from the TTree or create a local one.

   Bool_t compressedBufferExists = fCompressedBufferRef != NULL;
   fCompressedBufferRef = R__InitializeReadBasketBuffer(fCompressedBufferRef, len, file);
   if (R__unlikely(!compressedBufferExists)) {
      fOwnsCompressedBuffer = kTRUE;
   }
}

//_______________________________________________________________________
Int_t TBasket::ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file)
{
   // Read basket buffers in memory and cleanup.
   //
   // Read a basket buffer. Check if buffers of previous ReadBasket
   // should not be dropped. Remember, we keep buffers in memory up to
   // fMaxVirtualSize.
   // The function returns 0 in case of success, 1 in case of error
   // This function was modified with the addition of the parallel
   // unzipping, it will try to get the unzipped file from the cache
   // receiving only a pointer to that buffer (so we shall not
   // delete that pointer), although we get a new buffer in case
   // it's not found in the cache.
   // There is a lot of code duplication but it was necesary to assure
   // the expected behavior when there is no cache.

   if(!fBranch->GetDirectory()) {
      return -1;
   }  

   Bool_t oldCase;
   char *rawUncompressedBuffer, *rawCompressedBuffer;
   Int_t uncompressedBufferLen;

   // See if the cache has already unzipped the buffer for us.
   TFileCacheRead *pf = file->GetCacheRead(fBranch->GetTree());
   if (pf) {
      Int_t res = -1;
      Bool_t free = kTRUE;
      char *buffer;
      res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
      if (R__unlikely(res >= 0)) {
         len = ReadBasketBuffersUnzip(buffer, res, free, file);
         // Note that in the kNotDecompressed case, the above function will return 0;
         // In such a case, we should stop processing
         if (len <= 0) return -len;
         goto AfterBuffer;
      }
   }

   // Determine which buffer to use, so that we can avoid a memcpy in case of 
   // the basket was not compressed.
   TBuffer* readBufferRef;
   if (R__unlikely(fBranch->GetCompressionLevel()==0)) {
      readBufferRef = fBufferRef;
   } else {
      readBufferRef = fCompressedBufferRef;
   }

   // fBufferSize is likely to be change in the Streamer call (below)
   // and we will re-add the new size later on.
   fBranch->GetTree()->IncrementTotalBuffers(-fBufferSize);

   // Initialize the buffer to hold the compressed data.
   readBufferRef = R__InitializeReadBasketBuffer(readBufferRef, len, file);
   if (!readBufferRef) {
      Error("ReadBasketBuffers", "Unable to allocate buffer.");
      return 1;
   }
   
   if (pf) {
      TVirtualPerfStats* temp = gPerfStats;
      if (fBranch->GetTree()->GetPerfStats() != 0) gPerfStats = fBranch->GetTree()->GetPerfStats();
      Int_t st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
      if (st < 0) {
         return 1;
      } else if (st == 0) {
         // Read directly from file, not from the cache
         // If we are using a TTreeCache, disable reading from the default cache
         // temporarily, to force reading directly from file
         TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
         if (fc) fc->Disable();
         Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
         if (fc) fc->Enable();
         pf->AddNoCacheBytesRead(len);
         pf->AddNoCacheReadCalls(1);
         if (ret) {
            return 1;
         }
      }
      gPerfStats = temp;
   } else {
      // Read from the file and unstream the header information.
      TVirtualPerfStats* temp = gPerfStats;
      if (fBranch->GetTree()->GetPerfStats() != 0) gPerfStats = fBranch->GetTree()->GetPerfStats();
      if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
         gPerfStats = temp;
         return 1;
      }
      else gPerfStats = temp;
   }
   Streamer(*readBufferRef);
   if (IsZombie()) {
      return 1;
   }

   rawCompressedBuffer = readBufferRef->Buffer();

   // Are we done?
   if (R__unlikely(readBufferRef == fBufferRef)) // We expect most basket to be compressed.
   {
      if (R__likely(fObjlen+fKeylen == fNbytes)) {
         // The basket was really not compressed as expected.
         goto AfterBuffer;
      } else {
         // Well, somehow the buffer was compressed anyway, we have the compressed data in the uncompressed buffer
         // Make sure the compressed buffer is initialized, and memcpy.
         InitializeCompressedBuffer(len, file);
         if (!fCompressedBufferRef) {
            Error("ReadBasketBuffers", "Unable to allocate buffer.");
            return 1;
         }
         fBufferRef->Reset();
         rawCompressedBuffer = fCompressedBufferRef->Buffer();
         memcpy(rawCompressedBuffer, fBufferRef->Buffer(), len);
      }
   }

   // Initialize buffer to hold the uncompressed data
   // Note that in previous versions we didn't allocate buffers until we verified
   // the zip headers; this is no longer beforehand as the buffer lifetime is scoped
   // to the TBranch.
   uncompressedBufferLen = len > fObjlen+fKeylen ? len : fObjlen+fKeylen;
   fBufferRef = R__InitializeReadBasketBuffer(fBufferRef, uncompressedBufferLen, file);
   rawUncompressedBuffer = fBufferRef->Buffer();
   fBuffer = rawUncompressedBuffer;

   oldCase = OLD_CASE_EXPRESSION;
   // Case where ROOT thinks the buffer is compressed.  Copy over the key and uncompress the object
   if (fObjlen > fNbytes-fKeylen || oldCase) {
      if (R__unlikely(TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1))) {
         return ReadBasketBuffersUncompressedCase();
      }

      // Optional monitor for zip time profiling.
      Double_t start = 0;
      if (R__unlikely(gPerfStats)) {
         start = TTimeStamp();
      }

      memcpy(rawUncompressedBuffer, rawCompressedBuffer, fKeylen);
      char *rawUncompressedObjectBuffer = rawUncompressedBuffer+fKeylen;
      UChar_t *rawCompressedObjectBuffer = (UChar_t*)rawCompressedBuffer+fKeylen;
      Int_t nin, nbuf;
      Int_t nout = 0, noutot = 0, nintot = 0;

      // Unzip all the compressed objects in the compressed object buffer.
      while (1) {
         // Check the header for errors.
         if (R__unlikely(R__unzip_header(&nin, rawCompressedObjectBuffer, &nbuf) != 0)) {
            Error("ReadBasketBuffers", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
            break;
         }
         if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
            //buffer was very likely not compressed in an old version
            memcpy(rawUncompressedBuffer+fKeylen, rawCompressedObjectBuffer+fKeylen, fObjlen);
            goto AfterBuffer;
         }

         R__unzip(&nin, rawCompressedObjectBuffer, &nbuf, (unsigned char*) rawUncompressedObjectBuffer, &nout);
         if (!nout) break;
         noutot += nout;
         nintot += nin;
         if (noutot >= fObjlen) break;
         rawCompressedObjectBuffer += nin;
         rawUncompressedObjectBuffer += nout;
      }

      // Make sure the uncompressed numbers are consistent with header.
      if (R__unlikely(noutot != fObjlen)) {
         Error("ReadBasketBuffers", "fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
         fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
         return 1;
      }
      len = fObjlen+fKeylen;
      TVirtualPerfStats* temp = gPerfStats;
      if (fBranch->GetTree()->GetPerfStats() != 0) gPerfStats = fBranch->GetTree()->GetPerfStats();
      if (R__unlikely(gPerfStats)) {
         gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
      }
      gPerfStats = temp;
   } else {
      // Nothing is compressed - copy over wholesale.
      memcpy(rawUncompressedBuffer, rawCompressedBuffer, len);
   }

AfterBuffer:

   fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);

   // Read offsets table if needed.
   if (!fBranch->GetEntryOffsetLen()) {
      return 0;
   }
   delete [] fEntryOffset;
   fEntryOffset = 0;
   fBufferRef->SetBufferOffset(fLast);
   fBufferRef->ReadArray(fEntryOffset);
   if (!fEntryOffset) {
      fEntryOffset = new Int_t[fNevBuf+1];
      fEntryOffset[0] = fKeylen;
      Warning("ReadBasketBuffers","basket:%s has fNevBuf=%d but fEntryOffset=0, pos=%lld, len=%d, fNbytes=%d, fObjlen=%d, trying to repair",GetName(),fNevBuf,pos,len,fNbytes,fObjlen);
      return 0;
   }
   // Read the array of diplacement if any.
   delete [] fDisplacement;
   fDisplacement = 0; 
   if (fBufferRef->Length() != len) {
      // There is more data in the buffer!  It is the displacement
      // array.  If len is less than TBuffer::kMinimalSize the actual
      // size of the buffer is too large, so we can not use the
      // fBufferRef->BufferSize()
      fBufferRef->ReadArray(fDisplacement);
   }        

   return 0;
}

//_______________________________________________________________________
Int_t TBasket::ReadBasketBytes(Long64_t pos, TFile *file)
{
   // Read basket buffers in memory and cleanup
   //
   // Read first bytes of a logical record starting at position pos
   // return record length (first 4 bytes of record).

   const Int_t len = 128;
   char buffer[len];
   Int_t keylen;
   file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
   fKeylen = keylen;
   return fNbytes;
}

//_______________________________________________________________________
void TBasket::Reset()
{
   // Reset the basket to the starting state. i.e. as it was after calling
   // the constructor (and potentially attaching a TBuffer.)
   // Reduce memory used by fEntryOffset and the TBuffer if needed ..

   // Name, Title, fClassName, fBranch 
   // stay the same.

   // Downsize the buffer if needed.
   Int_t curSize = fBufferRef->BufferSize();
   // fBufferLen at this point is already reset, so use indirect measurements
   Int_t curLen = (GetObjlen() + GetKeylen());
   Long_t newSize = -1;
   if (curSize > 2*curLen)
   {
      Long_t curBsize = fBranch->GetBasketSize();      
      if (curSize > 2*curBsize ) {
         Long_t avgSize = (Long_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket())); // Average number of bytes per basket so far
         if (curSize > 2*avgSize) {
            newSize = curBsize;
            if (curLen > newSize) {
               newSize = curLen;
            }
            if (avgSize > newSize) {
               newSize = avgSize;
            }
            newSize = newSize + 512 - newSize%512;  // Wiggle room and alignment (512 is same as in OptimizeBaskets)
         }
      }
   }
   /*
      Philippe has asked us to keep this turned off until we finish memory fragmentation studies.
   // If fBufferRef grew since we last saw it, shrink it to 105% of the occupied size
   if (curSize > fLastWriteBufferSize) {
      if (newSize == -1) {
         newSize = Int_t(1.05*Float_t(fBufferRef->Length()));
      }
      fLastWriteBufferSize = newSize;
   }
   */
   if (newSize != -1) {
      fBufferRef->Expand(newSize,kFALSE);     // Expand without copying the existing data.
   }
   
   TKey::Reset();

   Int_t newNevBufSize = fBranch->GetEntryOffsetLen();
   if (newNevBufSize==0) {
      delete [] fEntryOffset;
      fEntryOffset = 0;
   } else if (newNevBufSize != fNevBufSize) {
      delete [] fEntryOffset;
      fEntryOffset = new Int_t[newNevBufSize];
   } else if (!fEntryOffset) {
      fEntryOffset = new Int_t[newNevBufSize];
   }
   fNevBufSize = newNevBufSize;

   fNevBuf      = 0;
   Int_t *storeEntryOffset = fEntryOffset;
   fEntryOffset = 0; 
   Int_t *storeDisplacement = fDisplacement;
   fDisplacement= 0; 
   fBuffer      = 0;

   fBufferRef->Reset();
   fBufferRef->SetWriteMode();

   fHeaderOnly  = kTRUE;
   fLast        = 0;  //Must initialize before calling Streamer()

   Streamer(*fBufferRef);

   fKeylen      = fBufferRef->Length();
   fObjlen      = fBufferSize - fKeylen;
   fLast        = fKeylen;
   fBuffer      = 0;
   fHeaderOnly  = kFALSE;
   fDisplacement= storeDisplacement;
   fEntryOffset = storeEntryOffset;
   if (fNevBufSize) {
      for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
   }   
}

//_______________________________________________________________________
void TBasket::SetReadMode()
{
   // Set read mode of basket.

   fLast = fBufferRef->Length();
   fBufferRef->SetReadMode();
}

//_______________________________________________________________________
void TBasket::SetWriteMode()
{
   // Set write mode of basket.

   fBufferRef->SetWriteMode();
   fBufferRef->SetBufferOffset(fLast);
}

//_______________________________________________________________________
void TBasket::Streamer(TBuffer &b)
{
   // Stream a class object.

   char flag;
   if (b.IsReading()) {
      TKey::Streamer(b); //this must be first
      Version_t v = b.ReadVersion();
      b >> fBufferSize;
      b >> fNevBufSize;
      if (fNevBufSize < 0) {
         Error("Streamer","The value of fNevBufSize is incorrect (%d) ; trying to recover by setting it to zero",fNevBufSize);
         MakeZombie();
         fNevBufSize = 0;
      }
      b >> fNevBuf;
      b >> fLast;
      b >> flag;
      if (fLast > fBufferSize) fBufferSize = fLast;
      if (!flag) {
         return;
      }
      if (flag%10 != 2) {
         delete [] fEntryOffset;
         fEntryOffset = new Int_t[fNevBufSize];
         if (fNevBuf) b.ReadArray(fEntryOffset);
         if (20<flag && flag<40) {
            for(int i=0; i<fNevBuf; i++){
               fEntryOffset[i] &= ~kDisplacementMask;
            }
         }
         if (flag>40) {
            fDisplacement = new Int_t[fNevBufSize];
            b.ReadArray(fDisplacement);
         }
      }
      if (flag == 1 || flag > 10) {
         fBufferRef = new TBufferFile(TBuffer::kRead,fBufferSize);
         fBufferRef->SetParent(b.GetParent());
         char *buf  = fBufferRef->Buffer();
         if (v > 1) b.ReadFastArray(buf,fLast);
         else       b.ReadArray(buf);
         fBufferRef->SetBufferOffset(fLast);
         // This is now done in the TBranch streamer since fBranch might not
         // yet be set correctly.
         //   fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
      }
   } else {
      TKey::Streamer(b);   //this must be first
      b.WriteVersion(TBasket::IsA());
      if (fBufferRef) {
         Int_t curLast = fBufferRef->Length();
         if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
      }
      if (fLast > fBufferSize) fBufferSize = fLast;

//   static TStopwatch timer;
//   timer.Start(kFALSE);

//       //  Check may be fEntryOffset is equidistant
//       //  This attempts by Victor fails :(
//       int equidist = 0;
//       if (1 && fEntryOffset && fNevBuf>=3) {
//          equidist = 1;
//          int dist = fEntryOffset[1]-fEntryOffset[0];
//          int curr = fEntryOffset[1];
//          for (int i=1;i<fNevBuf;i++,curr+=dist) {
//             if (fEntryOffset[i]==curr) continue;
//             equidist = 0;
//             break;
//          }
//          if (equidist) {
//             fNevBufSize=dist;
//             delete [] fEntryOffset; fEntryOffset = 0;
//          }
//           if (equidist) {
//              fprintf(stderr,"detected an equidistant case fNbytes==%d fLast==%d\n",fNbytes,fLast);
//           }
//       }
//  also he add (a little further
//       if (!fEntryOffset || equidist)  flag  = 2;

//   timer.Stop();
//   Double_t rt1 = timer.RealTime();
//   Double_t cp1 = timer.CpuTime();
//   fprintf(stderr,"equidist cost :  RT=%6.2f s  Cpu=%6.2f s\n",rt1,cp1);

      b << fBufferSize;
      b << fNevBufSize;
      b << fNevBuf;
      b << fLast;
      if (fHeaderOnly) {
         flag = 0;
         b << flag;
      } else {
         flag = 1;
         if (!fEntryOffset)  flag  = 2;
         if (fBufferRef)     flag += 10;
         if (fDisplacement)  flag += 40;
         b << flag;

         if (fEntryOffset && fNevBuf) {
            b.WriteArray(fEntryOffset, fNevBuf);
            if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
         }
         if (fBufferRef) {
            char *buf  = fBufferRef->Buffer();
            b.WriteFastArray(buf, fLast);
         }
      }
   }
}

//_______________________________________________________________________
void TBasket::Update(Int_t offset, Int_t skipped)
{
   // Update basket header and EntryOffset table.

   if (fEntryOffset) {
      if (fNevBuf+1 >= fNevBufSize) {
         Int_t newsize = TMath::Max(10,2*fNevBufSize);
         Int_t *newoff = TStorage::ReAllocInt(fEntryOffset, newsize,
                                              fNevBufSize);
         if (fDisplacement) {
            Int_t *newdisp = TStorage::ReAllocInt(fDisplacement, newsize,
                                                  fNevBufSize);
            fDisplacement = newdisp;
         }
         fEntryOffset  = newoff;
         fNevBufSize   = newsize;

         //Update branch only for the first 10 baskets
         if (fBranch->GetWriteBasket() < 10) {
            fBranch->SetEntryOffsetLen(newsize);
         }
      }
      fEntryOffset[fNevBuf] = offset;

      if (skipped!=offset && !fDisplacement){
         fDisplacement = new Int_t[fNevBufSize];
         for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
      }
      if (fDisplacement) {
         fDisplacement[fNevBuf] = skipped;
         fBufferRef->SetBufferDisplacement(skipped);
      }
   }

   fNevBuf++;
}

//_______________________________________________________________________
Int_t TBasket::WriteBuffer()
{
   // Write buffer of this basket on the current file.
   //
   // The function returns the number of bytes committed to the memory.
   // If a write error occurs, the number of bytes returned is -1.
   // If no data are written, the number of bytes returned is 0.
   //

   const Int_t kWrite = 1;

   TFile *file = fBranch->GetFile(kWrite);
   if (!file) return 0;
   if (!file->IsWritable()) { 
      return -1;
   }
   fMotherDir = file; // fBranch->GetDirectory();

   if (R__unlikely(fBufferRef->TestBit(TBufferFile::kNotDecompressed))) {
      // Read the basket information that was saved inside the buffer.
      Bool_t writing = fBufferRef->IsWriting();
      fBufferRef->SetReadMode();
      fBufferRef->SetBufferOffset(0);

      Streamer(*fBufferRef);
      if (writing) fBufferRef->SetWriteMode();
      Int_t nout = fNbytes - fKeylen;

      fBuffer = fBufferRef->Buffer();

      Create(nout,file);
      fBufferRef->SetBufferOffset(0);
      fHeaderOnly = kTRUE;

      Streamer(*fBufferRef);         //write key itself again
      int nBytes = WriteFileKeepBuffer();
      fHeaderOnly = kFALSE;
      return nBytes>0 ? fKeylen+nout : -1;
   }

   // Transfer fEntryOffset table at the end of fBuffer.
   fLast = fBufferRef->Length();
   if (fEntryOffset) {
      // Note: We might want to investigate the compression gain if we 
      // transform the Offsets to fBuffer in entry length to optimize 
      // compression algorithm.  The aggregate gain on a (random) CMS files
      // is around 5.5%. So the code could something like:
      //      for(Int_t z = fNevBuf; z > 0; --z) {
      //         if (fEntryOffset[z]) fEntryOffset[z] = fEntryOffset[z] - fEntryOffset[z-1];
      //      }
      fBufferRef->WriteArray(fEntryOffset,fNevBuf+1);
      if (fDisplacement) {
         fBufferRef->WriteArray(fDisplacement,fNevBuf+1);
         delete [] fDisplacement; fDisplacement = 0;
      }
   }

   Int_t lbuf, nout, noutot, bufmax, nzip;
   lbuf       = fBufferRef->Length();
   fObjlen    = lbuf - fKeylen;

   fHeaderOnly = kTRUE;
   fCycle = fBranch->GetWriteBasket();
   Int_t cxlevel = fBranch->GetCompressionLevel();
   Int_t cxAlgorithm = fBranch->GetCompressionAlgorithm();
   if (cxlevel > 0) {
      Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
      Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
      InitializeCompressedBuffer(buflen, file);
      if (!fCompressedBufferRef) {
         Warning("WriteBuffer", "Unable to allocate the compressed buffer");
         return -1;
      }
      fCompressedBufferRef->SetWriteMode();
      fBuffer = fCompressedBufferRef->Buffer();
      char *objbuf = fBufferRef->Buffer() + fKeylen;
      char *bufcur = &fBuffer[fKeylen];
      noutot = 0;
      nzip   = 0;
      for (Int_t i = 0; i < nbuffers; ++i) {
         if (i == nbuffers - 1) bufmax = fObjlen - nzip;
         else bufmax = kMAXZIPBUF;
         //compress the buffer
         R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);

         // test if buffer has really been compressed. In case of small buffers 
         // when the buffer contains random data, it may happen that the compressed
         // buffer is larger than the input. In this case, we write the original uncompressed buffer
         if (nout == 0 || nout >= fObjlen) {
            nout = fObjlen;
            // We used to delete fBuffer here, we no longer want to since
            // the buffer (held by fCompressedBufferRef) might be re-used later.
            fBuffer = fBufferRef->Buffer();
            Create(fObjlen,file);
            fBufferRef->SetBufferOffset(0);

            Streamer(*fBufferRef);         //write key itself again
            if ((nout+fKeylen)>buflen) {
               Warning("WriteBuffer","Possible memory corruption due to compression algorithm, wrote %d bytes past the end of a block of %d bytes. fNbytes=%d, fObjLen=%d, fKeylen=%d",
                  (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
            }
            goto WriteFile;
         }
         bufcur += nout;
         noutot += nout;
         objbuf += kMAXZIPBUF;
         nzip   += kMAXZIPBUF;
      }
      nout = noutot;
      Create(noutot,file);
      fBufferRef->SetBufferOffset(0);

      Streamer(*fBufferRef);         //write key itself again
      memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
   } else {
      fBuffer = fBufferRef->Buffer();
      Create(fObjlen,file);
      fBufferRef->SetBufferOffset(0);

      Streamer(*fBufferRef);         //write key itself again
      nout = fObjlen;
   }

WriteFile:
   Int_t nBytes = WriteFileKeepBuffer();
   fHeaderOnly = kFALSE;
   return nBytes>0 ? fKeylen+nout : -1;
}

 TBasket.cxx:1
 TBasket.cxx:2
 TBasket.cxx:3
 TBasket.cxx:4
 TBasket.cxx:5
 TBasket.cxx:6
 TBasket.cxx:7
 TBasket.cxx:8
 TBasket.cxx:9
 TBasket.cxx:10
 TBasket.cxx:11
 TBasket.cxx:12
 TBasket.cxx:13
 TBasket.cxx:14
 TBasket.cxx:15
 TBasket.cxx:16
 TBasket.cxx:17
 TBasket.cxx:18
 TBasket.cxx:19
 TBasket.cxx:20
 TBasket.cxx:21
 TBasket.cxx:22
 TBasket.cxx:23
 TBasket.cxx:24
 TBasket.cxx:25
 TBasket.cxx:26
 TBasket.cxx:27
 TBasket.cxx:28
 TBasket.cxx:29
 TBasket.cxx:30
 TBasket.cxx:31
 TBasket.cxx:32
 TBasket.cxx:33
 TBasket.cxx:34
 TBasket.cxx:35
 TBasket.cxx:36
 TBasket.cxx:37
 TBasket.cxx:38
 TBasket.cxx:39
 TBasket.cxx:40
 TBasket.cxx:41
 TBasket.cxx:42
 TBasket.cxx:43
 TBasket.cxx:44
 TBasket.cxx:45
 TBasket.cxx:46
 TBasket.cxx:47
 TBasket.cxx:48
 TBasket.cxx:49
 TBasket.cxx:50
 TBasket.cxx:51
 TBasket.cxx:52
 TBasket.cxx:53
 TBasket.cxx:54
 TBasket.cxx:55
 TBasket.cxx:56
 TBasket.cxx:57
 TBasket.cxx:58
 TBasket.cxx:59
 TBasket.cxx:60
 TBasket.cxx:61
 TBasket.cxx:62
 TBasket.cxx:63
 TBasket.cxx:64
 TBasket.cxx:65
 TBasket.cxx:66
 TBasket.cxx:67
 TBasket.cxx:68
 TBasket.cxx:69
 TBasket.cxx:70
 TBasket.cxx:71
 TBasket.cxx:72
 TBasket.cxx:73
 TBasket.cxx:74
 TBasket.cxx:75
 TBasket.cxx:76
 TBasket.cxx:77
 TBasket.cxx:78
 TBasket.cxx:79
 TBasket.cxx:80
 TBasket.cxx:81
 TBasket.cxx:82
 TBasket.cxx:83
 TBasket.cxx:84
 TBasket.cxx:85
 TBasket.cxx:86
 TBasket.cxx:87
 TBasket.cxx:88
 TBasket.cxx:89
 TBasket.cxx:90
 TBasket.cxx:91
 TBasket.cxx:92
 TBasket.cxx:93
 TBasket.cxx:94
 TBasket.cxx:95
 TBasket.cxx:96
 TBasket.cxx:97
 TBasket.cxx:98
 TBasket.cxx:99
 TBasket.cxx:100
 TBasket.cxx:101
 TBasket.cxx:102
 TBasket.cxx:103
 TBasket.cxx:104
 TBasket.cxx:105
 TBasket.cxx:106
 TBasket.cxx:107
 TBasket.cxx:108
 TBasket.cxx:109
 TBasket.cxx:110
 TBasket.cxx:111
 TBasket.cxx:112
 TBasket.cxx:113
 TBasket.cxx:114
 TBasket.cxx:115
 TBasket.cxx:116
 TBasket.cxx:117
 TBasket.cxx:118
 TBasket.cxx:119
 TBasket.cxx:120
 TBasket.cxx:121
 TBasket.cxx:122
 TBasket.cxx:123
 TBasket.cxx:124
 TBasket.cxx:125
 TBasket.cxx:126
 TBasket.cxx:127
 TBasket.cxx:128
 TBasket.cxx:129
 TBasket.cxx:130
 TBasket.cxx:131
 TBasket.cxx:132
 TBasket.cxx:133
 TBasket.cxx:134
 TBasket.cxx:135
 TBasket.cxx:136
 TBasket.cxx:137
 TBasket.cxx:138
 TBasket.cxx:139
 TBasket.cxx:140
 TBasket.cxx:141
 TBasket.cxx:142
 TBasket.cxx:143
 TBasket.cxx:144
 TBasket.cxx:145
 TBasket.cxx:146
 TBasket.cxx:147
 TBasket.cxx:148
 TBasket.cxx:149
 TBasket.cxx:150
 TBasket.cxx:151
 TBasket.cxx:152
 TBasket.cxx:153
 TBasket.cxx:154
 TBasket.cxx:155
 TBasket.cxx:156
 TBasket.cxx:157
 TBasket.cxx:158
 TBasket.cxx:159
 TBasket.cxx:160
 TBasket.cxx:161
 TBasket.cxx:162
 TBasket.cxx:163
 TBasket.cxx:164
 TBasket.cxx:165
 TBasket.cxx:166
 TBasket.cxx:167
 TBasket.cxx:168
 TBasket.cxx:169
 TBasket.cxx:170
 TBasket.cxx:171
 TBasket.cxx:172
 TBasket.cxx:173
 TBasket.cxx:174
 TBasket.cxx:175
 TBasket.cxx:176
 TBasket.cxx:177
 TBasket.cxx:178
 TBasket.cxx:179
 TBasket.cxx:180
 TBasket.cxx:181
 TBasket.cxx:182
 TBasket.cxx:183
 TBasket.cxx:184
 TBasket.cxx:185
 TBasket.cxx:186
 TBasket.cxx:187
 TBasket.cxx:188
 TBasket.cxx:189
 TBasket.cxx:190
 TBasket.cxx:191
 TBasket.cxx:192
 TBasket.cxx:193
 TBasket.cxx:194
 TBasket.cxx:195
 TBasket.cxx:196
 TBasket.cxx:197
 TBasket.cxx:198
 TBasket.cxx:199
 TBasket.cxx:200
 TBasket.cxx:201
 TBasket.cxx:202
 TBasket.cxx:203
 TBasket.cxx:204
 TBasket.cxx:205
 TBasket.cxx:206
 TBasket.cxx:207
 TBasket.cxx:208
 TBasket.cxx:209
 TBasket.cxx:210
 TBasket.cxx:211
 TBasket.cxx:212
 TBasket.cxx:213
 TBasket.cxx:214
 TBasket.cxx:215
 TBasket.cxx:216
 TBasket.cxx:217
 TBasket.cxx:218
 TBasket.cxx:219
 TBasket.cxx:220
 TBasket.cxx:221
 TBasket.cxx:222
 TBasket.cxx:223
 TBasket.cxx:224
 TBasket.cxx:225
 TBasket.cxx:226
 TBasket.cxx:227
 TBasket.cxx:228
 TBasket.cxx:229
 TBasket.cxx:230
 TBasket.cxx:231
 TBasket.cxx:232
 TBasket.cxx:233
 TBasket.cxx:234
 TBasket.cxx:235
 TBasket.cxx:236
 TBasket.cxx:237
 TBasket.cxx:238
 TBasket.cxx:239
 TBasket.cxx:240
 TBasket.cxx:241
 TBasket.cxx:242
 TBasket.cxx:243
 TBasket.cxx:244
 TBasket.cxx:245
 TBasket.cxx:246
 TBasket.cxx:247
 TBasket.cxx:248
 TBasket.cxx:249
 TBasket.cxx:250
 TBasket.cxx:251
 TBasket.cxx:252
 TBasket.cxx:253
 TBasket.cxx:254
 TBasket.cxx:255
 TBasket.cxx:256
 TBasket.cxx:257
 TBasket.cxx:258
 TBasket.cxx:259
 TBasket.cxx:260
 TBasket.cxx:261
 TBasket.cxx:262
 TBasket.cxx:263
 TBasket.cxx:264
 TBasket.cxx:265
 TBasket.cxx:266
 TBasket.cxx:267
 TBasket.cxx:268
 TBasket.cxx:269
 TBasket.cxx:270
 TBasket.cxx:271
 TBasket.cxx:272
 TBasket.cxx:273
 TBasket.cxx:274
 TBasket.cxx:275
 TBasket.cxx:276
 TBasket.cxx:277
 TBasket.cxx:278
 TBasket.cxx:279
 TBasket.cxx:280
 TBasket.cxx:281
 TBasket.cxx:282
 TBasket.cxx:283
 TBasket.cxx:284
 TBasket.cxx:285
 TBasket.cxx:286
 TBasket.cxx:287
 TBasket.cxx:288
 TBasket.cxx:289
 TBasket.cxx:290
 TBasket.cxx:291
 TBasket.cxx:292
 TBasket.cxx:293
 TBasket.cxx:294
 TBasket.cxx:295
 TBasket.cxx:296
 TBasket.cxx:297
 TBasket.cxx:298
 TBasket.cxx:299
 TBasket.cxx:300
 TBasket.cxx:301
 TBasket.cxx:302
 TBasket.cxx:303
 TBasket.cxx:304
 TBasket.cxx:305
 TBasket.cxx:306
 TBasket.cxx:307
 TBasket.cxx:308
 TBasket.cxx:309
 TBasket.cxx:310
 TBasket.cxx:311
 TBasket.cxx:312
 TBasket.cxx:313
 TBasket.cxx:314
 TBasket.cxx:315
 TBasket.cxx:316
 TBasket.cxx:317
 TBasket.cxx:318
 TBasket.cxx:319
 TBasket.cxx:320
 TBasket.cxx:321
 TBasket.cxx:322
 TBasket.cxx:323
 TBasket.cxx:324
 TBasket.cxx:325
 TBasket.cxx:326
 TBasket.cxx:327
 TBasket.cxx:328
 TBasket.cxx:329
 TBasket.cxx:330
 TBasket.cxx:331
 TBasket.cxx:332
 TBasket.cxx:333
 TBasket.cxx:334
 TBasket.cxx:335
 TBasket.cxx:336
 TBasket.cxx:337
 TBasket.cxx:338
 TBasket.cxx:339
 TBasket.cxx:340
 TBasket.cxx:341
 TBasket.cxx:342
 TBasket.cxx:343
 TBasket.cxx:344
 TBasket.cxx:345
 TBasket.cxx:346
 TBasket.cxx:347
 TBasket.cxx:348
 TBasket.cxx:349
 TBasket.cxx:350
 TBasket.cxx:351
 TBasket.cxx:352
 TBasket.cxx:353
 TBasket.cxx:354
 TBasket.cxx:355
 TBasket.cxx:356
 TBasket.cxx:357
 TBasket.cxx:358
 TBasket.cxx:359
 TBasket.cxx:360
 TBasket.cxx:361
 TBasket.cxx:362
 TBasket.cxx:363
 TBasket.cxx:364
 TBasket.cxx:365
 TBasket.cxx:366
 TBasket.cxx:367
 TBasket.cxx:368
 TBasket.cxx:369
 TBasket.cxx:370
 TBasket.cxx:371
 TBasket.cxx:372
 TBasket.cxx:373
 TBasket.cxx:374
 TBasket.cxx:375
 TBasket.cxx:376
 TBasket.cxx:377
 TBasket.cxx:378
 TBasket.cxx:379
 TBasket.cxx:380
 TBasket.cxx:381
 TBasket.cxx:382
 TBasket.cxx:383
 TBasket.cxx:384
 TBasket.cxx:385
 TBasket.cxx:386
 TBasket.cxx:387
 TBasket.cxx:388
 TBasket.cxx:389
 TBasket.cxx:390
 TBasket.cxx:391
 TBasket.cxx:392
 TBasket.cxx:393
 TBasket.cxx:394
 TBasket.cxx:395
 TBasket.cxx:396
 TBasket.cxx:397
 TBasket.cxx:398
 TBasket.cxx:399
 TBasket.cxx:400
 TBasket.cxx:401
 TBasket.cxx:402
 TBasket.cxx:403
 TBasket.cxx:404
 TBasket.cxx:405
 TBasket.cxx:406
 TBasket.cxx:407
 TBasket.cxx:408
 TBasket.cxx:409
 TBasket.cxx:410
 TBasket.cxx:411
 TBasket.cxx:412
 TBasket.cxx:413
 TBasket.cxx:414
 TBasket.cxx:415
 TBasket.cxx:416
 TBasket.cxx:417
 TBasket.cxx:418
 TBasket.cxx:419
 TBasket.cxx:420
 TBasket.cxx:421
 TBasket.cxx:422
 TBasket.cxx:423
 TBasket.cxx:424
 TBasket.cxx:425
 TBasket.cxx:426
 TBasket.cxx:427
 TBasket.cxx:428
 TBasket.cxx:429
 TBasket.cxx:430
 TBasket.cxx:431
 TBasket.cxx:432
 TBasket.cxx:433
 TBasket.cxx:434
 TBasket.cxx:435
 TBasket.cxx:436
 TBasket.cxx:437
 TBasket.cxx:438
 TBasket.cxx:439
 TBasket.cxx:440
 TBasket.cxx:441
 TBasket.cxx:442
 TBasket.cxx:443
 TBasket.cxx:444
 TBasket.cxx:445
 TBasket.cxx:446
 TBasket.cxx:447
 TBasket.cxx:448
 TBasket.cxx:449
 TBasket.cxx:450
 TBasket.cxx:451
 TBasket.cxx:452
 TBasket.cxx:453
 TBasket.cxx:454
 TBasket.cxx:455
 TBasket.cxx:456
 TBasket.cxx:457
 TBasket.cxx:458
 TBasket.cxx:459
 TBasket.cxx:460
 TBasket.cxx:461
 TBasket.cxx:462
 TBasket.cxx:463
 TBasket.cxx:464
 TBasket.cxx:465
 TBasket.cxx:466
 TBasket.cxx:467
 TBasket.cxx:468
 TBasket.cxx:469
 TBasket.cxx:470
 TBasket.cxx:471
 TBasket.cxx:472
 TBasket.cxx:473
 TBasket.cxx:474
 TBasket.cxx:475
 TBasket.cxx:476
 TBasket.cxx:477
 TBasket.cxx:478
 TBasket.cxx:479
 TBasket.cxx:480
 TBasket.cxx:481
 TBasket.cxx:482
 TBasket.cxx:483
 TBasket.cxx:484
 TBasket.cxx:485
 TBasket.cxx:486
 TBasket.cxx:487
 TBasket.cxx:488
 TBasket.cxx:489
 TBasket.cxx:490
 TBasket.cxx:491
 TBasket.cxx:492
 TBasket.cxx:493
 TBasket.cxx:494
 TBasket.cxx:495
 TBasket.cxx:496
 TBasket.cxx:497
 TBasket.cxx:498
 TBasket.cxx:499
 TBasket.cxx:500
 TBasket.cxx:501
 TBasket.cxx:502
 TBasket.cxx:503
 TBasket.cxx:504
 TBasket.cxx:505
 TBasket.cxx:506
 TBasket.cxx:507
 TBasket.cxx:508
 TBasket.cxx:509
 TBasket.cxx:510
 TBasket.cxx:511
 TBasket.cxx:512
 TBasket.cxx:513
 TBasket.cxx:514
 TBasket.cxx:515
 TBasket.cxx:516
 TBasket.cxx:517
 TBasket.cxx:518
 TBasket.cxx:519
 TBasket.cxx:520
 TBasket.cxx:521
 TBasket.cxx:522
 TBasket.cxx:523
 TBasket.cxx:524
 TBasket.cxx:525
 TBasket.cxx:526
 TBasket.cxx:527
 TBasket.cxx:528
 TBasket.cxx:529
 TBasket.cxx:530
 TBasket.cxx:531
 TBasket.cxx:532
 TBasket.cxx:533
 TBasket.cxx:534
 TBasket.cxx:535
 TBasket.cxx:536
 TBasket.cxx:537
 TBasket.cxx:538
 TBasket.cxx:539
 TBasket.cxx:540
 TBasket.cxx:541
 TBasket.cxx:542
 TBasket.cxx:543
 TBasket.cxx:544
 TBasket.cxx:545
 TBasket.cxx:546
 TBasket.cxx:547
 TBasket.cxx:548
 TBasket.cxx:549
 TBasket.cxx:550
 TBasket.cxx:551
 TBasket.cxx:552
 TBasket.cxx:553
 TBasket.cxx:554
 TBasket.cxx:555
 TBasket.cxx:556
 TBasket.cxx:557
 TBasket.cxx:558
 TBasket.cxx:559
 TBasket.cxx:560
 TBasket.cxx:561
 TBasket.cxx:562
 TBasket.cxx:563
 TBasket.cxx:564
 TBasket.cxx:565
 TBasket.cxx:566
 TBasket.cxx:567
 TBasket.cxx:568
 TBasket.cxx:569
 TBasket.cxx:570
 TBasket.cxx:571
 TBasket.cxx:572
 TBasket.cxx:573
 TBasket.cxx:574
 TBasket.cxx:575
 TBasket.cxx:576
 TBasket.cxx:577
 TBasket.cxx:578
 TBasket.cxx:579
 TBasket.cxx:580
 TBasket.cxx:581
 TBasket.cxx:582
 TBasket.cxx:583
 TBasket.cxx:584
 TBasket.cxx:585
 TBasket.cxx:586
 TBasket.cxx:587
 TBasket.cxx:588
 TBasket.cxx:589
 TBasket.cxx:590
 TBasket.cxx:591
 TBasket.cxx:592
 TBasket.cxx:593
 TBasket.cxx:594
 TBasket.cxx:595
 TBasket.cxx:596
 TBasket.cxx:597
 TBasket.cxx:598
 TBasket.cxx:599
 TBasket.cxx:600
 TBasket.cxx:601
 TBasket.cxx:602
 TBasket.cxx:603
 TBasket.cxx:604
 TBasket.cxx:605
 TBasket.cxx:606
 TBasket.cxx:607
 TBasket.cxx:608
 TBasket.cxx:609
 TBasket.cxx:610
 TBasket.cxx:611
 TBasket.cxx:612
 TBasket.cxx:613
 TBasket.cxx:614
 TBasket.cxx:615
 TBasket.cxx:616
 TBasket.cxx:617
 TBasket.cxx:618
 TBasket.cxx:619
 TBasket.cxx:620
 TBasket.cxx:621
 TBasket.cxx:622
 TBasket.cxx:623
 TBasket.cxx:624
 TBasket.cxx:625
 TBasket.cxx:626
 TBasket.cxx:627
 TBasket.cxx:628
 TBasket.cxx:629
 TBasket.cxx:630
 TBasket.cxx:631
 TBasket.cxx:632
 TBasket.cxx:633
 TBasket.cxx:634
 TBasket.cxx:635
 TBasket.cxx:636
 TBasket.cxx:637
 TBasket.cxx:638
 TBasket.cxx:639
 TBasket.cxx:640
 TBasket.cxx:641
 TBasket.cxx:642
 TBasket.cxx:643
 TBasket.cxx:644
 TBasket.cxx:645
 TBasket.cxx:646
 TBasket.cxx:647
 TBasket.cxx:648
 TBasket.cxx:649
 TBasket.cxx:650
 TBasket.cxx:651
 TBasket.cxx:652
 TBasket.cxx:653
 TBasket.cxx:654
 TBasket.cxx:655
 TBasket.cxx:656
 TBasket.cxx:657
 TBasket.cxx:658
 TBasket.cxx:659
 TBasket.cxx:660
 TBasket.cxx:661
 TBasket.cxx:662
 TBasket.cxx:663
 TBasket.cxx:664
 TBasket.cxx:665
 TBasket.cxx:666
 TBasket.cxx:667
 TBasket.cxx:668
 TBasket.cxx:669
 TBasket.cxx:670
 TBasket.cxx:671
 TBasket.cxx:672
 TBasket.cxx:673
 TBasket.cxx:674
 TBasket.cxx:675
 TBasket.cxx:676
 TBasket.cxx:677
 TBasket.cxx:678
 TBasket.cxx:679
 TBasket.cxx:680
 TBasket.cxx:681
 TBasket.cxx:682
 TBasket.cxx:683
 TBasket.cxx:684
 TBasket.cxx:685
 TBasket.cxx:686
 TBasket.cxx:687
 TBasket.cxx:688
 TBasket.cxx:689
 TBasket.cxx:690
 TBasket.cxx:691
 TBasket.cxx:692
 TBasket.cxx:693
 TBasket.cxx:694
 TBasket.cxx:695
 TBasket.cxx:696
 TBasket.cxx:697
 TBasket.cxx:698
 TBasket.cxx:699
 TBasket.cxx:700
 TBasket.cxx:701
 TBasket.cxx:702
 TBasket.cxx:703
 TBasket.cxx:704
 TBasket.cxx:705
 TBasket.cxx:706
 TBasket.cxx:707
 TBasket.cxx:708
 TBasket.cxx:709
 TBasket.cxx:710
 TBasket.cxx:711
 TBasket.cxx:712
 TBasket.cxx:713
 TBasket.cxx:714
 TBasket.cxx:715
 TBasket.cxx:716
 TBasket.cxx:717
 TBasket.cxx:718
 TBasket.cxx:719
 TBasket.cxx:720
 TBasket.cxx:721
 TBasket.cxx:722
 TBasket.cxx:723
 TBasket.cxx:724
 TBasket.cxx:725
 TBasket.cxx:726
 TBasket.cxx:727
 TBasket.cxx:728
 TBasket.cxx:729
 TBasket.cxx:730
 TBasket.cxx:731
 TBasket.cxx:732
 TBasket.cxx:733
 TBasket.cxx:734
 TBasket.cxx:735
 TBasket.cxx:736
 TBasket.cxx:737
 TBasket.cxx:738
 TBasket.cxx:739
 TBasket.cxx:740
 TBasket.cxx:741
 TBasket.cxx:742
 TBasket.cxx:743
 TBasket.cxx:744
 TBasket.cxx:745
 TBasket.cxx:746
 TBasket.cxx:747
 TBasket.cxx:748
 TBasket.cxx:749
 TBasket.cxx:750
 TBasket.cxx:751
 TBasket.cxx:752
 TBasket.cxx:753
 TBasket.cxx:754
 TBasket.cxx:755
 TBasket.cxx:756
 TBasket.cxx:757
 TBasket.cxx:758
 TBasket.cxx:759
 TBasket.cxx:760
 TBasket.cxx:761
 TBasket.cxx:762
 TBasket.cxx:763
 TBasket.cxx:764
 TBasket.cxx:765
 TBasket.cxx:766
 TBasket.cxx:767
 TBasket.cxx:768
 TBasket.cxx:769
 TBasket.cxx:770
 TBasket.cxx:771
 TBasket.cxx:772
 TBasket.cxx:773
 TBasket.cxx:774
 TBasket.cxx:775
 TBasket.cxx:776
 TBasket.cxx:777
 TBasket.cxx:778
 TBasket.cxx:779
 TBasket.cxx:780
 TBasket.cxx:781
 TBasket.cxx:782
 TBasket.cxx:783
 TBasket.cxx:784
 TBasket.cxx:785
 TBasket.cxx:786
 TBasket.cxx:787
 TBasket.cxx:788
 TBasket.cxx:789
 TBasket.cxx:790
 TBasket.cxx:791
 TBasket.cxx:792
 TBasket.cxx:793
 TBasket.cxx:794
 TBasket.cxx:795
 TBasket.cxx:796
 TBasket.cxx:797
 TBasket.cxx:798
 TBasket.cxx:799
 TBasket.cxx:800
 TBasket.cxx:801
 TBasket.cxx:802
 TBasket.cxx:803
 TBasket.cxx:804
 TBasket.cxx:805
 TBasket.cxx:806
 TBasket.cxx:807
 TBasket.cxx:808
 TBasket.cxx:809
 TBasket.cxx:810
 TBasket.cxx:811
 TBasket.cxx:812
 TBasket.cxx:813
 TBasket.cxx:814
 TBasket.cxx:815
 TBasket.cxx:816
 TBasket.cxx:817
 TBasket.cxx:818
 TBasket.cxx:819
 TBasket.cxx:820
 TBasket.cxx:821
 TBasket.cxx:822
 TBasket.cxx:823
 TBasket.cxx:824
 TBasket.cxx:825
 TBasket.cxx:826
 TBasket.cxx:827
 TBasket.cxx:828
 TBasket.cxx:829
 TBasket.cxx:830
 TBasket.cxx:831
 TBasket.cxx:832
 TBasket.cxx:833
 TBasket.cxx:834
 TBasket.cxx:835
 TBasket.cxx:836
 TBasket.cxx:837
 TBasket.cxx:838
 TBasket.cxx:839
 TBasket.cxx:840
 TBasket.cxx:841
 TBasket.cxx:842
 TBasket.cxx:843
 TBasket.cxx:844
 TBasket.cxx:845
 TBasket.cxx:846
 TBasket.cxx:847
 TBasket.cxx:848
 TBasket.cxx:849
 TBasket.cxx:850
 TBasket.cxx:851
 TBasket.cxx:852
 TBasket.cxx:853
 TBasket.cxx:854
 TBasket.cxx:855
 TBasket.cxx:856
 TBasket.cxx:857
 TBasket.cxx:858
 TBasket.cxx:859
 TBasket.cxx:860
 TBasket.cxx:861
 TBasket.cxx:862
 TBasket.cxx:863
 TBasket.cxx:864
 TBasket.cxx:865
 TBasket.cxx:866
 TBasket.cxx:867
 TBasket.cxx:868
 TBasket.cxx:869
 TBasket.cxx:870
 TBasket.cxx:871
 TBasket.cxx:872
 TBasket.cxx:873
 TBasket.cxx:874
 TBasket.cxx:875
 TBasket.cxx:876
 TBasket.cxx:877
 TBasket.cxx:878
 TBasket.cxx:879
 TBasket.cxx:880
 TBasket.cxx:881
 TBasket.cxx:882
 TBasket.cxx:883
 TBasket.cxx:884
 TBasket.cxx:885
 TBasket.cxx:886
 TBasket.cxx:887
 TBasket.cxx:888
 TBasket.cxx:889
 TBasket.cxx:890
 TBasket.cxx:891
 TBasket.cxx:892
 TBasket.cxx:893
 TBasket.cxx:894
 TBasket.cxx:895
 TBasket.cxx:896
 TBasket.cxx:897
 TBasket.cxx:898
 TBasket.cxx:899
 TBasket.cxx:900
 TBasket.cxx:901
 TBasket.cxx:902
 TBasket.cxx:903
 TBasket.cxx:904
 TBasket.cxx:905
 TBasket.cxx:906
 TBasket.cxx:907
 TBasket.cxx:908
 TBasket.cxx:909
 TBasket.cxx:910
 TBasket.cxx:911
 TBasket.cxx:912
 TBasket.cxx:913
 TBasket.cxx:914
 TBasket.cxx:915
 TBasket.cxx:916
 TBasket.cxx:917
 TBasket.cxx:918
 TBasket.cxx:919
 TBasket.cxx:920
 TBasket.cxx:921
 TBasket.cxx:922
 TBasket.cxx:923
 TBasket.cxx:924
 TBasket.cxx:925
 TBasket.cxx:926
 TBasket.cxx:927
 TBasket.cxx:928
 TBasket.cxx:929
 TBasket.cxx:930
 TBasket.cxx:931
 TBasket.cxx:932
 TBasket.cxx:933
 TBasket.cxx:934
 TBasket.cxx:935
 TBasket.cxx:936
 TBasket.cxx:937
 TBasket.cxx:938
 TBasket.cxx:939
 TBasket.cxx:940
 TBasket.cxx:941
 TBasket.cxx:942
 TBasket.cxx:943
 TBasket.cxx:944
 TBasket.cxx:945
 TBasket.cxx:946
 TBasket.cxx:947
 TBasket.cxx:948
 TBasket.cxx:949
 TBasket.cxx:950
 TBasket.cxx:951
 TBasket.cxx:952
 TBasket.cxx:953
 TBasket.cxx:954
 TBasket.cxx:955
 TBasket.cxx:956
 TBasket.cxx:957
 TBasket.cxx:958
 TBasket.cxx:959
 TBasket.cxx:960
 TBasket.cxx:961
 TBasket.cxx:962
 TBasket.cxx:963
 TBasket.cxx:964
 TBasket.cxx:965
 TBasket.cxx:966
 TBasket.cxx:967
 TBasket.cxx:968
 TBasket.cxx:969
 TBasket.cxx:970
 TBasket.cxx:971
 TBasket.cxx:972
 TBasket.cxx:973
 TBasket.cxx:974
 TBasket.cxx:975
 TBasket.cxx:976
 TBasket.cxx:977
 TBasket.cxx:978
 TBasket.cxx:979
 TBasket.cxx:980
 TBasket.cxx:981
 TBasket.cxx:982
 TBasket.cxx:983
 TBasket.cxx:984
 TBasket.cxx:985
 TBasket.cxx:986
 TBasket.cxx:987
 TBasket.cxx:988
 TBasket.cxx:989
 TBasket.cxx:990
 TBasket.cxx:991
 TBasket.cxx:992
 TBasket.cxx:993
 TBasket.cxx:994
 TBasket.cxx:995
 TBasket.cxx:996
 TBasket.cxx:997
 TBasket.cxx:998
 TBasket.cxx:999
 TBasket.cxx:1000
 TBasket.cxx:1001
 TBasket.cxx:1002
 TBasket.cxx:1003
 TBasket.cxx:1004
 TBasket.cxx:1005
 TBasket.cxx:1006
 TBasket.cxx:1007
 TBasket.cxx:1008
 TBasket.cxx:1009
 TBasket.cxx:1010
 TBasket.cxx:1011
 TBasket.cxx:1012
 TBasket.cxx:1013
 TBasket.cxx:1014
 TBasket.cxx:1015
 TBasket.cxx:1016
 TBasket.cxx:1017
 TBasket.cxx:1018
 TBasket.cxx:1019
 TBasket.cxx:1020
 TBasket.cxx:1021
 TBasket.cxx:1022
 TBasket.cxx:1023
 TBasket.cxx:1024
 TBasket.cxx:1025
 TBasket.cxx:1026
 TBasket.cxx:1027
 TBasket.cxx:1028
 TBasket.cxx:1029
 TBasket.cxx:1030
 TBasket.cxx:1031
 TBasket.cxx:1032
 TBasket.cxx:1033
 TBasket.cxx:1034
 TBasket.cxx:1035
 TBasket.cxx:1036
 TBasket.cxx:1037
 TBasket.cxx:1038