//*CMZ :  2.23/04 02/10/99  12.25.35  by  Rene Brun
//*CMZ :  2.22/07 30/06/99  11.37.44  by  Rene Brun
//*CMZ :  2.22/06 17/06/99  09.42.13  by  Rene Brun
//*CMZ :  2.22/02 20/05/99  18.10.52  by  Rene Brun
//*CMZ :  2.22/01 18/05/99  12.37.47  by  Rene Brun
//*-- Author :    Rene Brun   19/01/96
//*KEEP,CopyRight,T=C.
/*************************************************************************
 * Copyright(c) 1995-1999, The ROOT System, All rights reserved.         *
 * Authors: Rene Brun and Fons Rademakers.                               *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/AA_LICENSE.                      *
 * For the list of contributors see $ROOTSYS/AA_CREDITS.                 *
 *************************************************************************/
//*KEND.

//*KEEP,TBasket,T=C++.
#include "TBasket.h"
//*KEEP,TTree.
#include "TTree.h"
//*KEEP,TBranch,T=C++.
#include "TBranch.h"
//*KEEP,TFile.
#include "TFile.h"
//*KEEP,TMath.
#include "TMath.h"
//*KEND.

R__EXTERN  TBranch *gBranch;

extern "C" void mmzip (Int_t cxlevel, Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout);
extern "C" void mmuzip(Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout);

ClassImp(TBasket)

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

//_______________________________________________________________________
 TBasket::TBasket()
{
//               Default contructor
   fEntryOffset   = 0;
   fZipBuffer     = 0;
   fBufferRef     = 0;
   fBuffer        = 0;
   fWritingBuffer = kFALSE;
}

//_______________________________________________________________________
 TBasket::TBasket(const Text_t *name, const Text_t *title, TBranch *branch)
{
//            Basket normal constructor
//
//
   SetName(name);
   SetTitle(title);
   fClassName   = "TBasket";
   fBufferSize  = branch->GetBasketSize();
   fNevBufSize  = branch->GetEntryOffsetLen();
   fNevBuf      = 0;
   fEntryOffset = 0;  //Must be set to 0 before calling Sizeof
   fBuffer      = 0;  //Must be set to 0 before calling Sizeof
   fBufferRef   = new TBuffer(TBuffer::kWrite, fBufferSize);
   fWritingBuffer = kTRUE;
   fLast        = 0; // RDK: Must initialize before calling Streamer()
   Streamer(*fBufferRef);
   fKeylen      = fBufferRef->Length();
   fObjlen      = fBufferSize - fKeylen;
   fLast        = fKeylen;
   fBuffer      = 0;
   fBranch      = branch;
   fZipBuffer   = 0;
   fWritingBuffer = kFALSE;
   if (fNevBufSize) fEntryOffset = new Int_t[fNevBufSize];
   branch->GetTree()->IncrementTotalBuffers(fBufferSize);
}

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

   if (fEntryOffset) delete [] fEntryOffset;
   if (fZipBuffer)   delete [] fZipBuffer;
//   if (fBufferRef)   delete fBufferRef; //this is done in the TKey destructor
//   fBufferRef   = 0;
   fEntryOffset = 0;
   fZipBuffer   = 0;
}

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

   char *newbuf = (char*)TStorage::ReAlloc(fBuffer,newsize,fBufferSize);
   fBufferSize  = newsize;
   fBuffer      = newbuf;
}


//_______________________________________________________________________
 Int_t TBasket::DropBuffers()
{
//      Drop buffers of this basket if it is not the current basket

   if (!fBuffer && !fBufferRef) return 0;
//   delete [] fBuffer;
   if (fEntryOffset) delete [] fEntryOffset;
   if (fBufferRef)   delete fBufferRef;
   fBufferRef   = 0;
   fBuffer      = 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;
}

//_______________________________________________________________________
 void TBasket::Print(Option_t *option)
{
//            Print Basket parameters
//
   TNamed::Print(option);
}

//_______________________________________________________________________
 void TBasket::ReadBasketBuffers()
{
//*-*-*-*-*-*-*-*-*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.

   TDirectory *cursav = gDirectory;
   fBranch->GetDirectory()->cd();

   if (fBranch->GetTree()->MemoryFull(fBufferSize)) fBranch->DropBaskets();

   fBufferRef = new TBuffer(TBuffer::kRead, fObjlen+fKeylen);
   if (fObjlen > fNbytes-fKeylen) {
      fBuffer = new char[fNbytes];
      TKey::ReadFile();                    //Read object structure from file
      memcpy(fBufferRef->Buffer(),fBuffer,fKeylen);
      char *objbuf = fBufferRef->Buffer() + fKeylen;
      Int_t nin = fNbytes-fKeylen;
      Int_t nout;
      mmuzip(&nin, &fBuffer[fKeylen], &fObjlen, objbuf, &nout);
      if (nout != fObjlen) Error("Read", "fObjlen = %d, nout = %d", fObjlen, nout);
      delete [] fBuffer;
      fBuffer = 0;
   } else {
      fBuffer = fBufferRef->Buffer();
      TKey::ReadFile();                    // Remember, TBasket inherits from TKey
   }
   cursav->cd();

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

//        read offsets table
   if (!fBranch->GetEntryOffsetLen()) return;
   delete [] fEntryOffset;
   fEntryOffset = 0;
   fBufferRef->SetBufferOffset(fLast);
   fBufferRef->ReadArray(fEntryOffset);
}

//_______________________________________________________________________
 void TBasket::ReadBasketBuffers(char *buf)
{
//*-*-*-*-*-*-*-*-*Read basket buffers in memory and cleanup*-*-*-*-*-*-*
//*-*              =========================================
//
//       Read a basket buffer from buf. Check if buffers of previous ReadBasket
//       should not be dropped. Remember, we keep buffers
//       in memory up to fMaxVirtualSize.
   TDirectory *cursav = gDirectory;
   fBranch->GetDirectory()->cd();

   if (fBranch->GetTree()->MemoryFull(fBufferSize)) fBranch->DropBaskets();

   fBufferRef = new TBuffer(TBuffer::kRead, fObjlen+fKeylen);
   if (fObjlen > fNbytes-fKeylen) {
      fBuffer = new char[fNbytes];
      memcpy(fBufferRef->Buffer(),buf,fKeylen);
      char *objbuf = fBufferRef->Buffer() + fKeylen;
      Int_t nin = fNbytes-fKeylen;
      Int_t nout;
      mmuzip(&nin, &buf[fKeylen], &fObjlen, objbuf, &nout);
      if (nout != fObjlen) Error("Read", "fObjlen = %d, nout = %d", fObjlen, nout);
      delete [] fBuffer;
      fBuffer = 0;
   } else {
      fBuffer = fBufferRef->Buffer();
      memcpy(fBuffer,buf,fNbytes);
   }
   cursav->cd();

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

//        read offsets table
   if (!fBranch->GetEntryOffsetLen()) return;
   delete [] fEntryOffset;
   fEntryOffset = 0;
   fBufferRef->SetBufferOffset(fLast);
   fBufferRef->ReadArray(fEntryOffset);

}

//_______________________________________________________________________
 void TBasket::Reset(Option_t *)
{

}

//_______________________________________________________________________
 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()) {
      fBranch = gBranch;
      TKey::Streamer(b); //this must be first
      Version_t v = b.ReadVersion();
      b >> fBufferSize;
      b >> fNevBufSize;
      b >> fNevBuf;
      b >> fLast;
      b >> flag;
     if (!flag) return;
      if (flag%10 != 2) {
         delete [] fEntryOffset;
         fEntryOffset = new Int_t[fNevBufSize];
         if (fNevBuf) b.ReadArray(fEntryOffset);
      }
      if (flag == 1 || flag > 10) {
         fBufferRef = new TBuffer(TBuffer::kRead,fBufferSize);
         char *buf  = fBufferRef->Buffer();
         if (v > 1) b.ReadFastArray(buf,fLast);
         else       b.ReadArray(buf);
         fBufferRef->SetBufferOffset(fLast);
         fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
      }
   } else {
      TKey::Streamer(b);   //this must be first
      b.WriteVersion(TBasket::IsA());
      b << fBufferSize;
      b << fNevBufSize;
      b << fNevBuf;
      if (fBufferRef && !fWritingBuffer) fLast = fBufferRef->Length();
      b << fLast;
      flag = 1;
      if (!fEntryOffset)  flag  = 2;
      if (fBufferRef)     flag += 10;
      if (fWritingBuffer) flag  = 0;
      b << flag;
      if (fWritingBuffer) return;
      if (fEntryOffset && fNevBuf) {
         b.WriteArray(fEntryOffset, fNevBuf);
      }
      if (fBufferRef) {
         char *buf  = fBufferRef->Buffer();
         b.WriteFastArray(buf, fLast);
      }
   }
}

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

   if (fEntryOffset) {
      if (fNevBuf+1 >= fNevBufSize) {
         Int_t newsize = TMath::Max(10,2*fNevBufSize);
         Int_t *newoff = (Int_t*)TStorage::ReAlloc(fEntryOffset,
                               newsize*sizeof(Int_t),fNevBufSize*sizeof(Int_t));
         fEntryOffset  = newoff;
         fNevBufSize   = newsize;
         //Update branch only for the first 10 baskets
         if (fBranch->GetWriteBasket() < 10) fBranch->SetEntryOffsetLen(newsize);
      }
      fEntryOffset[fNevBuf] = offset;
   }

   fNevBuf++;
}

//_______________________________________________________________________
 Int_t TBasket::WriteBuffer()
{
//    Write buffer of this basket on the current file

   const Int_t kWrite = 1;
   TDirectory *cursav = gDirectory;
   TFile *file = fBranch->GetFile(kWrite);
   if (!file) return 0;

   fBranch->GetDirectory()->cd();
   if (gFile ? !gFile->IsWritable() : 1) { cursav->cd(); return 0;}
//*-*- Transfer fEntryOffset table at the end of fBuffer. Offsets to fBuffer
//     are transformed in entry length to optimize compression algorithm.
   fLast      = fBufferRef->Length();
   if (fEntryOffset) {
      fBufferRef->WriteArray(fEntryOffset,fNevBuf+1);
      delete [] fEntryOffset; fEntryOffset = 0;
   }

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

   fWritingBuffer = kTRUE;
   fCycle = fBranch->GetWriteBasket();
   Int_t cxlevel = fBranch->GetCompressionLevel();
   if (cxlevel) {
      if (cxlevel == 2) cxlevel--;
      Int_t buflen = fKeylen + fObjlen + 28; //add 28 bytes in case object is placed in a deleted gap
      fBuffer = new char[buflen];
      char *objbuf = fBufferRef->Buffer() + fKeylen;
      Int_t bufmax = buflen-fKeylen;
      mmzip(cxlevel, &fObjlen, objbuf, &bufmax, &fBuffer[fKeylen], &nout);
//printf("mmzip:%s, bufmax=%d, fObjlen=%d, fKeylen=%d, nout=%dn",GetName(),bufmax,fObjlen,fKeylen,nout);
      if (nout >= fObjlen) {
         delete [] fBuffer;
         fBuffer = fBufferRef->Buffer();
         Create(fObjlen);
         fBufferRef->SetBufferOffset(0);
         Streamer(*fBufferRef);         //write key itself again
         nout = fObjlen;
      } else {
         Create(nout);
         fBufferRef->SetBufferOffset(0);
         Streamer(*fBufferRef);         //write key itself again
         memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
         delete fBufferRef; fBufferRef = 0;
      }
   } else {
      fBuffer = fBufferRef->Buffer();
      Create(fObjlen);
      fBufferRef->SetBufferOffset(0);
      Streamer(*fBufferRef);         //write key itself again
      nout = fObjlen;
   }

//  TKey::WriteFile calls FillBuffer. TBasket inherits from TKey, hence
//  TBasket::FillBuffer is called.
   TKey::WriteFile(0);
   fWritingBuffer = kFALSE;

   cursav->cd();
   return fKeylen+nout;
}


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.