TBranch.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TBranch.cxx 38060 2011-02-13 21:17:54Z pcanal $
00002 // Author: Rene Brun   12/01/96
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TBranch.h"
00013 
00014 #include "TBasket.h"
00015 #include "TBranchBrowsable.h"
00016 #include "TBrowser.h"
00017 #include "TClass.h"
00018 #include "TBufferFile.h"
00019 #include "TClonesArray.h"
00020 #include "TFile.h"
00021 #include "TLeaf.h"
00022 #include "TLeafB.h"
00023 #include "TLeafC.h"
00024 #include "TLeafD.h"
00025 #include "TLeafF.h"
00026 #include "TLeafI.h"
00027 #include "TLeafL.h"
00028 #include "TLeafO.h"
00029 #include "TLeafObject.h"
00030 #include "TLeafS.h"
00031 #include "TMessage.h"
00032 #include "TROOT.h"
00033 #include "TSystem.h"
00034 #include "TMath.h"
00035 #include "TTree.h"
00036 #include "TTreeCache.h"
00037 #include "TTreeCacheUnzip.h"
00038 #include "TVirtualPad.h"
00039 
00040 #include <cstddef>
00041 #include <string.h>
00042 #include <stdio.h>
00043 
00044 R__EXTERN TTree* gTree;
00045 
00046 Int_t TBranch::fgCount = 0;
00047 
00048 
00049 //////////////////////////////////////////////////////////////////////////
00050 //                                                                      //
00051 // A TTree is a list of TBranches                                       //
00052 //                                                                      //
00053 // A TBranch supports:                                                  //
00054 //   - The list of TLeaf describing this branch.                        //
00055 //   - The list of TBasket (branch buffers).                            //
00056 //                                                                      //
00057 //       See TBranch structure in TTree.                                //
00058 //                                                                      //
00059 // See also specialized branches:                                       //
00060 //     TBranchObject in case the branch is one object                   //
00061 //     TBranchClones in case the branch is an array of clone objects    //
00062 //////////////////////////////////////////////////////////////////////////
00063 
00064 ClassImp(TBranch)
00065 
00066 //______________________________________________________________________________
00067 TBranch::TBranch()
00068 : TNamed()
00069 , TAttFill(0, 1001)
00070 , fCompress(0)
00071 , fBasketSize(32000)
00072 , fEntryOffsetLen(1000)
00073 , fWriteBasket(0)
00074 , fEntryNumber(0)
00075 , fOffset(0)
00076 , fMaxBaskets(10)
00077 , fNBaskets(0)
00078 , fSplitLevel(0)
00079 , fNleaves(0)
00080 , fReadBasket(0)
00081 , fReadEntry(-1)
00082 , fEntries(0)
00083 , fFirstEntry(0)
00084 , fTotBytes(0)
00085 , fZipBytes(0)
00086 , fBranches()
00087 , fLeaves()
00088 , fBaskets(fMaxBaskets)
00089 , fBasketBytes(0)
00090 , fBasketEntry(0)
00091 , fBasketSeek(0)
00092 , fTree(0)
00093 , fMother(0)
00094 , fParent(0)
00095 , fAddress(0)
00096 , fDirectory(0)
00097 , fFileName("")
00098 , fEntryBuffer(0)
00099 , fBrowsables(0)
00100 , fSkipZip(kFALSE)
00101 , fReadLeaves(&TBranch::ReadLeavesImpl)
00102 {
00103    // Default constructor.  Used for I/O by default.
00104 
00105 }
00106 
00107 //______________________________________________________________________________
00108 TBranch::TBranch(TTree *tree, const char* name, void* address, const char* leaflist, Int_t basketsize, Int_t compress)
00109 : TNamed(name, leaflist)
00110 , TAttFill(0, 1001)
00111 , fCompress(compress)
00112 , fBasketSize((basketsize < 100) ? 100 : basketsize)
00113 , fEntryOffsetLen(0)
00114 , fWriteBasket(0)
00115 , fEntryNumber(0)
00116 , fOffset(0)
00117 , fMaxBaskets(10)
00118 , fNBaskets(0)
00119 , fSplitLevel(0)
00120 , fNleaves(0)
00121 , fReadBasket(0)
00122 , fReadEntry(-1)
00123 , fEntries(0)
00124 , fFirstEntry(0)
00125 , fTotBytes(0)
00126 , fZipBytes(0)
00127 , fBranches()
00128 , fLeaves()
00129 , fBaskets(fMaxBaskets)
00130 , fBasketBytes(0)
00131 , fBasketEntry(0)
00132 , fBasketSeek(0)
00133 , fTree(tree)
00134 , fMother(0)
00135 , fParent(0)
00136 , fAddress((char*) address)
00137 , fDirectory(fTree->GetDirectory())
00138 , fFileName("")
00139 , fEntryBuffer(0)
00140 , fBrowsables(0)
00141 , fSkipZip(kFALSE)
00142 , fReadLeaves(&TBranch::ReadLeavesImpl)
00143 {
00144    //*-*-*-*-*-*-*-*-*-*-*-*-*Create a Branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00145    //*-*                =====================
00146    //
00147    //       * address is the address of the first item of a structure.
00148    //       * leaflist is the concatenation of all the variable names and types
00149    //         separated by a colon character :
00150    //         The variable name and the variable type are separated by a slash (/).
00151    //         The variable type may be 0,1 or 2 characters. If no type is given,
00152    //         the type of the variable is assumed to be the same as the previous
00153    //         variable. If the first variable does not have a type, it is assumed
00154    //         of type F by default. The list of currently supported types is given below:
00155    //            - C : a character string terminated by the 0 character
00156    //            - B : an 8 bit signed integer (Char_t)
00157    //            - b : an 8 bit unsigned integer (UChar_t)
00158    //            - S : a 16 bit signed integer (Short_t)
00159    //            - s : a 16 bit unsigned integer (UShort_t)
00160    //            - I : a 32 bit signed integer (Int_t)
00161    //            - i : a 32 bit unsigned integer (UInt_t)
00162    //            - F : a 32 bit floating point (Float_t)
00163    //            - D : a 64 bit floating point (Double_t)
00164    //            - L : a 64 bit signed integer (Long64_t)
00165    //            - l : a 64 bit unsigned integer (ULong64_t)
00166    //
00167    //         By default, a variable will be copied to the buffer with the number of
00168    //         bytes specified in the type descriptor character. However, if the type
00169    //         consists of 2 characters, the second character is an integer that
00170    //         specifies the number of bytes to be used when copying the variable
00171    //         to the output buffer. Example:
00172    //             X         ; variable X, type Float_t
00173    //             Y/I       : variable Y, type Int_t
00174    //             Y/I2      ; variable Y, type Int_t converted to a 16 bits integer
00175    //
00176    //    Note that the TTree will assume that all the item are contiguous in memory.
00177    //    On some platform, this is not always true of the member of a struct or a class,
00178    //    due to padding and alignment.  Sorting your data member in order of decreasing
00179    //    sizeof usually leads to their being contiguous in memory.
00180    //
00181    //       * bufsize is the buffer size in bytes for this branch
00182    //         The default value is 32000 bytes and should be ok for most cases.
00183    //         You can specify a larger value (eg 256000) if your Tree is not split
00184    //         and each entry is large (Megabytes)
00185    //         A small value for bufsize is optimum if you intend to access
00186    //         the entries in the Tree randomly and your Tree is in split mode.
00187    //
00188    //   See an example of a Branch definition in the TTree constructor.
00189    //
00190    //   Note that in case the data type is an object, this branch can contain
00191    //   only this object.
00192    //
00193    //    Note that this function is invoked by TTree::Branch
00194    //
00195    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00196 
00197    Init(name,leaflist,compress);
00198 }
00199 
00200 //______________________________________________________________________________
00201 TBranch::TBranch(TBranch *parent, const char* name, void* address, const char* leaflist, Int_t basketsize, Int_t compress)
00202 : TNamed(name, leaflist)
00203 , TAttFill(0, 1001)
00204 , fCompress(compress)
00205 , fBasketSize((basketsize < 100) ? 100 : basketsize)
00206 , fEntryOffsetLen(0)
00207 , fWriteBasket(0)
00208 , fEntryNumber(0)
00209 , fOffset(0)
00210 , fMaxBaskets(10)
00211 , fNBaskets(0)
00212 , fSplitLevel(0)
00213 , fNleaves(0)
00214 , fReadBasket(0)
00215 , fReadEntry(-1)
00216 , fEntries(0)
00217 , fFirstEntry(0)
00218 , fTotBytes(0)
00219 , fZipBytes(0)
00220 , fBranches()
00221 , fLeaves()
00222 , fBaskets(fMaxBaskets)
00223 , fBasketBytes(0)
00224 , fBasketEntry(0)
00225 , fBasketSeek(0)
00226 , fTree(parent ? parent->GetTree() : 0)
00227 , fMother(parent ? parent->GetMother() : 0)
00228 , fParent(parent)
00229 , fAddress((char*) address)
00230 , fDirectory(fTree ? fTree->GetDirectory() : 0)
00231 , fFileName("")
00232 , fEntryBuffer(0)
00233 , fBrowsables(0)
00234 , fSkipZip(kFALSE)
00235 , fReadLeaves(&TBranch::ReadLeavesImpl)
00236 {
00237    //*-*-*-*-*-*-*-*-*-*-*-*-*Create a Branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00238    //*-*                =====================
00239    //
00240    //       * address is the address of the first item of a structure
00241    //         or the address of a pointer to an object (see example).
00242    //       * leaflist is the concatenation of all the variable names and types
00243    //         separated by a colon character :
00244    //         The variable name and the variable type are separated by a slash (/).
00245    //         The variable type may be 0,1 or 2 characters. If no type is given,
00246    //         the type of the variable is assumed to be the same as the previous
00247    //         variable. If the first variable does not have a type, it is assumed
00248    //         of type F by default. The list of currently supported types is given below:
00249    //            - C : a character string terminated by the 0 character
00250    //            - B : an 8 bit signed integer (Char_t)
00251    //            - b : an 8 bit unsigned integer (UChar_t)
00252    //            - S : a 16 bit signed integer (Short_t)
00253    //            - s : a 16 bit unsigned integer (UShort_t)
00254    //            - I : a 32 bit signed integer (Int_t)
00255    //            - i : a 32 bit unsigned integer (UInt_t)
00256    //            - F : a 32 bit floating point (Float_t)
00257    //            - D : a 64 bit floating point (Double_t)
00258    //            - L : a 64 bit signed integer (Long64_t)
00259    //            - l : a 64 bit unsigned integer (ULong64_t)
00260    //
00261    //         By default, a variable will be copied to the buffer with the number of
00262    //         bytes specified in the type descriptor character. However, if the type
00263    //         consists of 2 characters, the second character is an integer that
00264    //         specifies the number of bytes to be used when copying the variable
00265    //         to the output buffer. Example:
00266    //             X         ; variable X, type Float_t
00267    //             Y/I       : variable Y, type Int_t
00268    //             Y/I2      ; variable Y, type Int_t converted to a 16 bits integer
00269    //
00270    //   See an example of a Branch definition in the TTree constructor.
00271    //
00272    //   Note that in case the data type is an object, this branch can contain
00273    //   only this object.
00274    //
00275    //    Note that this function is invoked by TTree::Branch
00276    //
00277    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00278 
00279    Init(name,leaflist,compress);
00280 }
00281 
00282 void TBranch::Init(const char* name, const char* leaflist, Int_t compress)
00283 {
00284    // Initialization routine called from the constructor.  This should NOT be made virtual.
00285 
00286    if ((compress == -1) && fTree->GetDirectory()) {
00287       TFile* bfile = fTree->GetDirectory()->GetFile();
00288       if (bfile) {
00289          fCompress = bfile->GetCompressionLevel();
00290       }
00291    }
00292 
00293    fBasketBytes = new Int_t[fMaxBaskets];
00294    fBasketEntry = new Long64_t[fMaxBaskets];
00295    fBasketSeek  = new Long64_t[fMaxBaskets];
00296 
00297    for (Int_t i = 0; i < fMaxBaskets; ++i) {
00298       fBasketBytes[i] = 0;
00299       fBasketEntry[i] = 0;
00300       fBasketSeek[i] = 0;
00301    }
00302 
00303    //
00304    // Decode the leaflist (search for : as separator).
00305    //
00306 
00307    char* nameBegin = const_cast<char*>(leaflist);
00308    Int_t offset = 0;
00309    // FIXME: Make these string streams instead.
00310    char* leafname = new char[640];
00311    char* leaftype = new char[320];
00312    // Note: The default leaf type is a float.
00313    strlcpy(leaftype, "F",320);
00314    char* pos = const_cast<char*>(leaflist);
00315    const char* leaflistEnd = leaflist + strlen(leaflist);
00316    for (; pos <= leaflistEnd; ++pos) {
00317       // -- Scan leaf specification and create leaves.
00318       if ((*pos == ':') || (*pos == 0)) {
00319          // -- Reached end of a leaf spec, create a leaf.
00320          Int_t lenName = pos - nameBegin;
00321          char* ctype = 0;
00322          if (lenName) {
00323             strncpy(leafname, nameBegin, lenName);
00324             leafname[lenName] = 0;
00325             ctype = strstr(leafname, "/");
00326             if (ctype) {
00327                *ctype = 0;
00328                strlcpy(leaftype, ctype + 1,320);
00329             }
00330          }
00331          if (lenName == 0 || ctype == leafname) {
00332             Warning("TBranch","No name was given to the leaf number '%d' in the leaflist of the branch '%s'.",fNleaves,name);
00333             snprintf(leafname,640,"__noname%d",fNleaves);
00334          }
00335          TLeaf* leaf = 0;
00336          if (*leaftype == 'C') {
00337             leaf = new TLeafC(this, leafname, leaftype);
00338          } else if (*leaftype == 'O') {
00339             leaf = new TLeafO(this, leafname, leaftype);
00340          } else if (*leaftype == 'B') {
00341             leaf = new TLeafB(this, leafname, leaftype);
00342          } else if (*leaftype == 'b') {
00343             leaf = new TLeafB(this, leafname, leaftype);
00344             leaf->SetUnsigned();
00345          } else if (*leaftype == 'S') {
00346             leaf = new TLeafS(this, leafname, leaftype);
00347          } else if (*leaftype == 's') {
00348             leaf = new TLeafS(this, leafname, leaftype);
00349             leaf->SetUnsigned();
00350          } else if (*leaftype == 'I') {
00351             leaf = new TLeafI(this, leafname, leaftype);
00352          } else if (*leaftype == 'i') {
00353             leaf = new TLeafI(this, leafname, leaftype);
00354             leaf->SetUnsigned();
00355          } else if (*leaftype == 'F') {
00356             leaf = new TLeafF(this, leafname, leaftype);
00357          } else if (*leaftype == 'f') {
00358             leaf = new TLeafF(this, leafname, leaftype);
00359          } else if (*leaftype == 'L') {
00360             leaf = new TLeafL(this, leafname, leaftype);
00361          } else if (*leaftype == 'l') {
00362             leaf = new TLeafL(this, leafname, leaftype);
00363             leaf->SetUnsigned();
00364          } else if (*leaftype == 'D') {
00365             leaf = new TLeafD(this, leafname, leaftype);
00366          } else if (*leaftype == 'd') {
00367             leaf = new TLeafD(this, leafname, leaftype);
00368          }
00369          if (!leaf) {
00370             Error("TLeaf", "Illegal data type for %s/%s", name, leaflist);
00371             delete[] leaftype;
00372             delete [] leafname;
00373             MakeZombie();
00374             return;
00375          }
00376          if (leaf->IsZombie()) {
00377             delete leaf;
00378             leaf = 0;
00379             Error("TBranch", "Illegal leaf: %s/%s", name, leaflist);
00380             delete [] leafname;
00381             delete[] leaftype;
00382             MakeZombie();
00383             return;
00384          }
00385          leaf->SetBranch(this);
00386          leaf->SetAddress((char*) (fAddress + offset));
00387          leaf->SetOffset(offset);
00388          if (leaf->GetLeafCount()) {
00389             // -- Leaf is a varying length array, we need an offset array.
00390             fEntryOffsetLen = 1000;
00391          }
00392          if (leaf->InheritsFrom(TLeafC::Class())) {
00393             // -- Leaf is a character string, we need an offset array.
00394             fEntryOffsetLen = 1000;
00395          }
00396          ++fNleaves;
00397          fLeaves.Add(leaf);
00398          fTree->GetListOfLeaves()->Add(leaf);
00399          if (*pos == 0) {
00400             // -- We reached the end of the leaf specification.
00401             break;
00402          }
00403          nameBegin = pos + 1;
00404          offset += leaf->GetLenType() * leaf->GetLen();
00405       }
00406    }
00407    delete[] leafname;
00408    leafname = 0;
00409    delete[] leaftype;
00410    leaftype = 0;
00411 
00412 }
00413 
00414 //______________________________________________________________________________
00415 TBranch::~TBranch()
00416 {
00417    // Destructor.
00418 
00419    delete fBrowsables;
00420    fBrowsables = 0;
00421 
00422    // Note: We do *not* have ownership of the buffer.
00423    fEntryBuffer = 0;
00424 
00425    delete [] fBasketSeek;
00426    fBasketSeek  = 0;
00427 
00428    delete [] fBasketEntry;
00429    fBasketEntry = 0;
00430 
00431    delete [] fBasketBytes;
00432    fBasketBytes = 0;
00433 
00434    fBaskets.Delete();
00435    fNBaskets = 0;
00436 
00437    // Remove our leaves from our tree's list of leaves.
00438    if (fTree) {
00439       TObjArray* lst = fTree->GetListOfLeaves();
00440       if (lst && lst->GetLast()!=-1) {
00441          lst->RemoveAll(&fLeaves);
00442       }
00443    }
00444    // And delete our leaves.
00445    fLeaves.Delete();
00446 
00447    fBranches.Delete();
00448 
00449    // If we are in a directory and that directory is not the same
00450    // directory that our tree is in, then try to find an open file
00451    // with the name fFileName.  If we find one, delete that file.
00452    // We are attempting to close any alternate file which we have
00453    // been directed to write our baskets to.
00454    // FIXME: We make no attempt to check if someone else might be
00455    //        using this file.  This is very user hostile.  A violation
00456    //        of the principle of least surprises.
00457    //
00458    // Warning. Must use FindObject by name instead of fDirectory->GetFile()
00459    // because two branches may point to the same file and the file
00460    // may have already been deleted in the previous branch.
00461    if (fDirectory && (!fTree || fDirectory != fTree->GetDirectory())) {
00462       TString bFileName( GetRealFileName() );
00463 
00464       TFile* file = (TFile*)gROOT->GetListOfFiles()->FindObject(bFileName);
00465       if (file){
00466          file->Close();
00467          delete file;
00468          file = 0;
00469       }
00470    }
00471 
00472    fTree = 0;
00473    fDirectory = 0;
00474 }
00475 
00476 //______________________________________________________________________________
00477 void TBranch::AddBasket(TBasket& b, Bool_t ondisk, Long64_t startEntry)
00478 {
00479    // Add the basket to this branch.
00480 
00481    // Warning: if the basket are not 'flushed/copied' in the same
00482    // order as they were created, this will induce a slow down in
00483    // the insert (since we'll need to move all the record that are
00484    // entere 'too early').
00485    // Warning we also assume that the __current__ write basket is
00486    // not present (aka has been removed).
00487 
00488    TBasket *basket = &b;
00489 
00490    basket->SetBranch(this);
00491 
00492    if (fWriteBasket >= fMaxBaskets) {
00493       ExpandBasketArrays();
00494    }
00495    Int_t where = fWriteBasket;
00496 
00497    if (where && startEntry < fBasketEntry[where-1]) {
00498       // Need to find the right location and move the possible baskets
00499 
00500       if (!ondisk) {
00501          Warning("AddBasket","The assumption that out-of-order basket only comes from disk based ntuple is false.");
00502       }
00503 
00504       if (startEntry < fBasketEntry[0]) {
00505          where = 0;
00506       } else {
00507          for(Int_t i=fWriteBasket-1; i>=0; --i) {
00508             if (fBasketEntry[i] < startEntry) {
00509                where = i+1;
00510                break;
00511             } else if (fBasketEntry[i] == startEntry) {
00512                Error("AddBasket","An out-of-order basket matches the entry number of an existing basket.");
00513             }
00514          }
00515       }
00516 
00517       if (where < fWriteBasket) {
00518          // We shall move the content of the array
00519          for (Int_t j=fWriteBasket; j > where; --j) {
00520             fBasketEntry[j] = fBasketEntry[j-1];
00521             fBasketBytes[j] = fBasketBytes[j-1];
00522             fBasketSeek[j]  = fBasketSeek[j-1];
00523          }
00524       }
00525    }
00526    fBasketEntry[where] = startEntry;
00527 
00528    if (ondisk) {
00529       fBasketBytes[where] = basket->GetNbytes();  // not for in mem
00530       fBasketSeek[where] = basket->GetSeekKey();  // not for in mem
00531       fBaskets.AddAtAndExpand(0,fWriteBasket);
00532       ++fWriteBasket;
00533    } else {
00534       ++fNBaskets;
00535       fBaskets.AddAtAndExpand(basket,fWriteBasket);
00536       fTree->IncrementTotalBuffers(basket->GetBufferSize());
00537    }
00538 
00539    fEntries += basket->GetNevBuf();
00540    fEntryNumber += basket->GetNevBuf();
00541    if (ondisk) {
00542       fTotBytes += basket->GetObjlen() + basket->GetKeylen() ;
00543       fZipBytes += basket->GetNbytes();
00544       fTree->AddTotBytes(basket->GetObjlen() + basket->GetKeylen());
00545       fTree->AddZipBytes(basket->GetNbytes());
00546    }
00547 }
00548 
00549 //______________________________________________________________________________
00550 void TBranch::AddLastBasket(Long64_t startEntry)
00551 {
00552    // Add the start entry of the write basket (not yet created)
00553 
00554    if (fWriteBasket >= fMaxBaskets) {
00555       ExpandBasketArrays();
00556    }
00557    Int_t where = fWriteBasket;
00558 
00559    if (where && startEntry < fBasketEntry[where-1]) {
00560       // Need to find the right location and move the possible baskets
00561 
00562       Fatal("AddBasket","The last basket must have the highest entry number (%s/%lld/%d).",GetName(),startEntry,fWriteBasket);
00563 
00564    }
00565    fBasketEntry[where] = startEntry;
00566    fBaskets.AddAtAndExpand(0,fWriteBasket);
00567 }
00568 
00569 //______________________________________________________________________________
00570 void TBranch::Browse(TBrowser* b)
00571 {
00572    // Browser interface.
00573 
00574    if (fNleaves > 1) {
00575       fLeaves.Browse(b);
00576    } else {
00577       // Get the name and strip any extra brackets
00578       // in order to get the full arrays.
00579       TString name = GetName();
00580       Int_t pos = name.First('[');
00581       if (pos!=kNPOS) name.Remove(pos);
00582 
00583       GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
00584       if (gPad) gPad->Update();
00585    }
00586 }
00587 
00588  //______________________________________________________________________________
00589 void TBranch::DeleteBaskets(Option_t* option)
00590 {
00591    // Loop on all branch baskets. If the file where branch buffers reside is
00592    // writable, free the disk space associated to the baskets of the branch,
00593    // then call Reset(). If the option contains "all", delete also the baskets
00594    // for the subbranches.
00595    // The branch is reset.
00596    // NOTE that this function must be used with extreme care. Deleting branch baskets
00597    // fragments the file and may introduce inefficiencies when adding new entries
00598    // in the Tree or later on when reading the Tree.
00599 
00600    TString opt = option;
00601    opt.ToLower();
00602    TFile *file = GetFile(0);
00603 
00604    if(fDirectory && (fDirectory != gROOT) && fDirectory->IsWritable()) {
00605       for(Int_t i=0; i<fWriteBasket; i++) {
00606          if (fBasketSeek[i]) file->MakeFree(fBasketSeek[i],fBasketSeek[i]+fBasketBytes[i]-1);
00607       }
00608    }
00609 
00610    // process subbranches
00611    if (opt.Contains("all")) {
00612       TObjArray *lb = GetListOfBranches();
00613       Int_t nb = lb->GetEntriesFast();
00614       for (Int_t j = 0; j < nb; j++) {
00615          TBranch* branch = (TBranch*) lb->UncheckedAt(j);
00616          if (branch) branch->DeleteBaskets("all");
00617       }
00618    }
00619    DropBaskets("all");
00620    Reset();
00621 }
00622 
00623 //______________________________________________________________________________
00624 void TBranch::DropBaskets(Option_t* options)
00625 {
00626    // Loop on all branch baskets. Drop all baskets from memory except readbasket.
00627    // If the option contains "all", drop all baskets including
00628    // read- and write-baskets (unless they are not stored individually on disk).
00629    // The option "all" also lead to DropBaskets being called on the sub-branches.
00630 
00631    Bool_t all = kFALSE;
00632    if (options && options[0]) {
00633       TString opt = options;
00634       opt.ToLower();
00635       if (opt.Contains("all")) all = kTRUE;
00636    }
00637 
00638    TBasket *basket;
00639    Int_t nbaskets = fBaskets.GetEntriesFast();
00640 
00641    if ( (fNBaskets>1) || all ) {
00642       //slow case
00643       for (Int_t i=0;i<nbaskets;i++) {
00644          basket = (TBasket*)fBaskets.UncheckedAt(i);
00645          if (!basket) continue;
00646          if ((i == fReadBasket || i == fWriteBasket) && !all) continue;
00647          if (fBasketBytes[i]==0) continue; // Since it is not on file, we can read it back.
00648          basket->DropBuffers();
00649          --fNBaskets;
00650          fBaskets.RemoveAt(i);
00651          delete basket;
00652       }
00653 
00654       // process subbranches
00655       if (all) {
00656          TObjArray *lb = GetListOfBranches();
00657          Int_t nb = lb->GetEntriesFast();
00658          for (Int_t j = 0; j < nb; j++) {
00659             TBranch* branch = (TBranch*) lb->UncheckedAt(j);
00660             if (!branch) continue;
00661             branch->DropBaskets("all");
00662          }
00663       }
00664    } else {
00665       //fast case
00666       if (nbaskets > 0) {
00667          Int_t i = fBaskets.GetLast();
00668          basket = (TBasket*)fBaskets.UncheckedAt(i);
00669          if (basket && fBasketBytes[i]!=0) {
00670             basket->DropBuffers();
00671             delete basket;
00672             fBaskets.AddAt(0,i);
00673             fBaskets.SetLast(-1);
00674             fNBaskets = 0;
00675          }
00676       }
00677    }
00678 
00679 }
00680 
00681 //______________________________________________________________________________
00682 void TBranch::ExpandBasketArrays()
00683 {
00684    // Increase BasketEntry buffer of a minimum of 10 locations
00685    // and a maximum of 50 per cent of current size.
00686 
00687    Int_t newsize = TMath::Max(10,Int_t(1.5*fMaxBaskets));
00688    fBasketBytes  = TStorage::ReAllocInt(fBasketBytes, newsize, fMaxBaskets);
00689    fBasketEntry  = (Long64_t*)TStorage::ReAlloc(fBasketEntry,
00690                                                 newsize*sizeof(Long64_t),fMaxBaskets*sizeof(Long64_t));
00691    fBasketSeek   = (Long64_t*)TStorage::ReAlloc(fBasketSeek,
00692                                                 newsize*sizeof(Long64_t),fMaxBaskets*sizeof(Long64_t));
00693 
00694    fMaxBaskets   = newsize;
00695 
00696    fBaskets.Expand(newsize);
00697 
00698    for (Int_t i=fWriteBasket;i<fMaxBaskets;i++) {
00699       fBasketBytes[i] = 0;
00700       fBasketEntry[i] = 0;
00701       fBasketSeek[i]  = 0;
00702    }
00703 }
00704 
00705 //______________________________________________________________________________
00706 Int_t TBranch::Fill()
00707 {
00708    // Loop on all leaves of this branch to fill Basket buffer.
00709    //
00710    // The function returns the number of bytes committed to the memory basket.
00711    // If a write error occurs, the number of bytes returned is -1.
00712    // If no data are written, because e.g. the branch is disabled,
00713    // the number of bytes returned is 0.
00714    //
00715 
00716    if (TestBit(kDoNotProcess)) {
00717       return 0;
00718    }
00719 
00720    TBasket* basket = GetBasket(fWriteBasket);
00721    if (!basket) {
00722       basket = fTree->CreateBasket(this); //  create a new basket
00723       if (!basket) return 0;
00724       ++fNBaskets;
00725       fBaskets.AddAtAndExpand(basket,fWriteBasket);
00726    }
00727    TBuffer* buf = basket->GetBufferRef();
00728 
00729    // Fill basket buffer.
00730 
00731    Int_t nsize  = 0;
00732 
00733    if (buf->IsReading()) {
00734       basket->SetWriteMode();
00735    }
00736 
00737    buf->ResetMap();
00738 
00739    Int_t lold = buf->Length();
00740    Int_t objectStart = 0;
00741    Int_t last = 0;
00742    Int_t lnew = 0;
00743    Int_t nbytes = 0;
00744 
00745    if (fEntryBuffer) {
00746       if (fEntryBuffer->IsA() == TMessage::Class()) {
00747          objectStart = 8;
00748       }
00749       if (fEntryBuffer->TestBit(TBufferFile::kNotDecompressed)) {
00750          // The buffer given as input as not been decompressed.
00751          if (basket->GetNevBuf()) {
00752             // If the basket already contains entry we need to close it
00753             // out. (This is because we can only transfer full compressed
00754             // buffer)
00755             WriteBasket(basket,fWriteBasket);
00756             // And restart from scratch
00757             return Fill();
00758          }
00759          Int_t startpos = fEntryBuffer->Length();
00760          fEntryBuffer->SetBufferOffset(0);
00761          static TBasket toread_fLast;
00762          fEntryBuffer->SetReadMode();
00763          toread_fLast.Streamer(*fEntryBuffer);
00764          fEntryBuffer->SetWriteMode();
00765          last = toread_fLast.GetLast();
00766          // last now contains the decompressed number of bytes.
00767          fEntryBuffer->SetBufferOffset(startpos);
00768          buf->SetBufferOffset(0);
00769          buf->SetBit(TBufferFile::kNotDecompressed);
00770          basket->Update(lold);
00771       } else {
00772          // We are required to copy starting at the version number (so not
00773          // including the class name.
00774          // See if byte count is here, if not it class still be a newClass
00775          const UInt_t kNewClassTag = 0xFFFFFFFF;
00776          const UInt_t kByteCountMask = 0x40000000;  // OR the byte count with this
00777          UInt_t tag = 0;
00778          UInt_t startpos = fEntryBuffer->Length();
00779          fEntryBuffer->SetBufferOffset(objectStart);
00780          *fEntryBuffer >> tag;
00781          if (tag & kByteCountMask) {
00782             *fEntryBuffer >> tag;
00783          }
00784          if (tag == kNewClassTag) {
00785             UInt_t maxsize = 256;
00786             char* s = new char[maxsize];
00787             Int_t name_start = fEntryBuffer->Length();
00788             fEntryBuffer->ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
00789             while (strlen(s) == (maxsize - 1)) {
00790                // The classname is too large, try again with a large buffer.
00791                fEntryBuffer->SetBufferOffset(name_start);
00792                maxsize *= 2;
00793                delete[] s;
00794                s = new char[maxsize];
00795                fEntryBuffer->ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end
00796             }
00797          } else {
00798             fEntryBuffer->SetBufferOffset(objectStart);
00799          }
00800          objectStart = fEntryBuffer->Length();
00801          fEntryBuffer->SetBufferOffset(startpos);
00802          basket->Update(lold, objectStart - fEntryBuffer->GetBufferDisplacement());
00803       }
00804       fEntries++;
00805       fEntryNumber++;
00806       UInt_t len = 0;
00807       UInt_t startpos = fEntryBuffer->Length();
00808       if (startpos > UInt_t(objectStart)) {
00809          // We assume this buffer have just been directly filled
00810          // the current position in the buffer indicates the end of the object!
00811          len = fEntryBuffer->Length() - objectStart;
00812       } else {
00813          // The buffer have been acquired either via TSocket or via
00814          // TBuffer::SetBuffer(newloc,newsize)
00815          // Only the actual size of the memory buffer gives us an hint about where
00816          // the object ends.
00817          len = fEntryBuffer->BufferSize() - objectStart;
00818       }
00819       buf->WriteBuf(fEntryBuffer->Buffer() + objectStart, len);
00820       if (fEntryBuffer->TestBit(TBufferFile::kNotDecompressed)) {
00821          // The original buffer came pre-compressed and thus the buffer Length
00822          // does not really show the really object size
00823          // lnew = nbytes = basket->GetLast();
00824          nbytes = last;
00825          lnew = last;
00826       } else {
00827          lnew = buf->Length();
00828          nbytes = lnew - lold;
00829       }
00830    } else {
00831       basket->Update(lold);
00832       ++fEntries;
00833       ++fEntryNumber;
00834       FillLeaves(*buf);
00835       lnew = buf->Length();
00836       nbytes = lnew - lold;
00837    }
00838 
00839    if (fEntryOffsetLen) {
00840       Int_t nevbuf = basket->GetNevBuf();
00841       // Total size in bytes of EntryOffset table.
00842       nsize = nevbuf * sizeof(Int_t);
00843    } else {
00844       if (!basket->GetNevBufSize()) {
00845          basket->SetNevBufSize(nbytes);
00846       }
00847    }
00848 
00849    // Should we create a new basket?
00850    // fSkipZip force one entry per buffer (old stuff still maintained for CDF)
00851    // Transfer full compressed buffer only
00852 
00853    if ((fSkipZip && (lnew >= TBuffer::kMinimalSize)) || (buf->TestBit(TBufferFile::kNotDecompressed)) || ((lnew + (2 * nsize) + nbytes) >= fBasketSize)) {
00854       if (fTree->TestBit(TTree::kCircular)) {
00855          return nbytes;
00856       }
00857       Int_t nevbuf = basket->GetNevBuf();
00858       if (fEntryOffsetLen > 10 &&  (4*nevbuf) < fEntryOffsetLen ) {
00859          fEntryOffsetLen = nevbuf < 3 ? 10 : 4*nevbuf; // assume some fluctuations.
00860       } else if (fEntryOffsetLen && nevbuf > fEntryOffsetLen) {
00861          fEntryOffsetLen = 2*nevbuf; // assume some fluctuations.
00862       }
00863       Int_t nout = WriteBasket(basket,fWriteBasket);
00864       return (nout >= 0) ? nbytes : -1;
00865    }
00866    return nbytes;
00867 }
00868 
00869 //______________________________________________________________________________
00870 void TBranch::FillLeaves(TBuffer& b)
00871 {
00872    // Fill each of the leaf of the branch.
00873 
00874    for (Int_t i = 0; i < fNleaves; ++i) {
00875       TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
00876       leaf->FillBasket(b);
00877    }
00878 }
00879 
00880 //______________________________________________________________________________
00881 TBranch* TBranch::FindBranch(const char* name)
00882 {
00883    // -- Find the immediate sub-branch with passed name.
00884 
00885    // We allow the user to pass only the last dotted component of the name.
00886    std::string longnm;
00887    longnm.reserve(fName.Length()+strlen(name)+3);
00888    longnm = fName.Data();
00889    if (longnm[longnm.length()-1]==']') {
00890       std::size_t dim = longnm.find_first_of("[");
00891       if (dim != std::string::npos) {
00892          longnm.erase(dim);
00893       }
00894    }
00895    if (longnm[longnm.length()-1] != '.') {
00896       longnm += '.';
00897    }
00898    longnm += name;
00899    UInt_t namelen = strlen(name);
00900 
00901    Int_t nbranches = fBranches.GetEntries();
00902    TBranch* branch = 0;
00903    for(Int_t i = 0; i < nbranches; ++i) {
00904       branch = (TBranch*) fBranches.UncheckedAt(i);
00905 
00906       const char *brname = branch->fName.Data();
00907       UInt_t brlen = branch->fName.Length();
00908       if (brname[brlen-1]==']') {
00909          const char *dim = strchr(brname,'[');
00910          if (dim) {
00911             brlen = dim - brname;
00912          }
00913       }
00914       if (namelen == brlen /* same effective size */
00915           && strncmp(name,brname,brlen) == 0) {
00916          return branch;
00917       }
00918       if (brlen == (size_t)longnm.length()
00919           && strncmp(longnm.c_str(),brname,brlen) == 0) {
00920          return branch;
00921       }
00922    }
00923    return 0;
00924 }
00925 
00926 //______________________________________________________________________________
00927 TLeaf* TBranch::FindLeaf(const char* searchname)
00928 {
00929    // -- Find the leaf corresponding to the name 'searchname'.
00930 
00931    TString leafname;
00932    TString leaftitle;
00933    TString longname;
00934    TString longtitle;
00935 
00936    // We allow the user to pass only the last dotted component of the name.
00937    TIter next(GetListOfLeaves());
00938    TLeaf* leaf = 0;
00939    while ((leaf = (TLeaf*) next())) {
00940       leafname = leaf->GetName();
00941       Ssiz_t dim = leafname.First('[');
00942       if (dim >= 0) leafname.Remove(dim);
00943 
00944       if (leafname == searchname) return leaf;
00945 
00946       // The leaf element contains the branch name in its name, let's use the title.
00947       leaftitle = leaf->GetTitle();
00948       dim = leaftitle.First('[');
00949       if (dim >= 0) leaftitle.Remove(dim);
00950 
00951       if (leaftitle == searchname) return leaf;
00952 
00953       TBranch* branch = leaf->GetBranch();
00954       if (branch) {
00955         longname.Form("%s.%s",branch->GetName(),leafname.Data());
00956          dim = longname.First('[');
00957          if (dim>=0) longname.Remove(dim);
00958          if (longname == searchname) return leaf;
00959 
00960          // The leaf element contains the branch name in its name.
00961          longname.Form("%s.%s",branch->GetName(),searchname);
00962          if (longname==leafname) return leaf;
00963 
00964          longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
00965          dim = longtitle.First('[');
00966          if (dim>=0) longtitle.Remove(dim);
00967          if (longtitle == searchname) return leaf;
00968 
00969          // The following is for the case where the branch is only
00970          // a sub-branch.  Since we do not see it through
00971          // TTree::GetListOfBranches, we need to see it indirectly.
00972          // This is the less sturdy part of this search ... it may
00973          // need refining ...
00974          if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) return leaf;
00975       }
00976    }
00977    return 0;
00978 }
00979 
00980 
00981 //______________________________________________________________________________
00982 Int_t TBranch::FlushBaskets()
00983 {
00984    // Flush to disk all the baskets of this branch and any of subbranches.
00985    // Return the number of bytes written or -1 in case of write error.
00986 
00987    UInt_t nerror = 0;
00988    Int_t nbytes = 0;
00989 
00990    Int_t maxbasket = fWriteBasket + 1;
00991    // The following protection is not necessary since we should always
00992    // have fWriteBasket < fBasket.GetSize()
00993    //if (fBaskets.GetSize() < maxbasket) {
00994    //   maxbasket = fBaskets.GetSize();
00995    //}
00996    for(Int_t i=0; i != maxbasket; ++i) {
00997       if (fBaskets.UncheckedAt(i)) {
00998          Int_t nwrite = FlushOneBasket(i);
00999          if (nwrite<0) {
01000             ++nerror;
01001          } else {
01002             nbytes += nwrite;
01003          }
01004       }
01005    }
01006    Int_t len = fBranches.GetEntriesFast();
01007    for (Int_t i = 0; i < len; ++i) {
01008       TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
01009       if (!branch) {
01010          continue;
01011       }
01012       Int_t nwrite = branch->FlushBaskets();
01013       if (nwrite<0) {
01014          ++nerror;
01015       } else {
01016          nbytes += nwrite;
01017       }
01018    }
01019    if (nerror) {
01020       return -1;
01021    } else {
01022       return nbytes;
01023    }
01024 }
01025 
01026 //______________________________________________________________________________
01027 Int_t TBranch::FlushOneBasket(UInt_t ibasket)
01028 {
01029    // If we have a write basket in memory and it contains some entries and
01030    // has not yet been written to disk, we write it and delete it from memory.
01031    // Return the number of bytes written;
01032 
01033    Int_t nbytes = 0;
01034    if (fDirectory && fBaskets.GetEntries()) {
01035       TBasket *basket = (TBasket*)fBaskets.UncheckedAt(ibasket);
01036 
01037       if (basket) {
01038          if (basket->GetNevBuf()
01039              && fBasketSeek[ibasket]==0) {
01040             // If the basket already contains entry we need to close it out.
01041             // (This is because we can only transfer full compressed buffer)
01042 
01043             if (basket->GetBufferRef()->IsReading()) {
01044                basket->SetWriteMode();
01045             }
01046             nbytes = WriteBasket(basket,ibasket);
01047 
01048          } else {
01049             // If the basket is empty or has already been written.
01050             if ((Int_t)ibasket==fWriteBasket) {
01051                // Nothing to do.
01052             } else {
01053                basket->DropBuffers();
01054                delete basket;
01055                --fNBaskets;
01056                fBaskets[ibasket] = 0;
01057             }
01058           }
01059       }
01060    }
01061    return nbytes;
01062 }
01063 
01064 //______________________________________________________________________________
01065 TBasket* TBranch::GetBasket(Int_t basketnumber)
01066 {
01067    //*-*-*-*-*Return pointer to basket basketnumber in this Branch*-*-*-*-*-*
01068    //*-*      ====================================================
01069 
01070    static Int_t nerrors = 0;
01071 
01072       // reference to an existing basket in memory ?
01073    if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
01074    TBasket *basket = (TBasket*)fBaskets.UncheckedAt(basketnumber);
01075    if (basket) return basket;
01076    if (basketnumber == fWriteBasket) return 0;
01077 
01078    // create/decode basket parameters from buffer
01079    TFile *file = GetFile(0);
01080    if (file == 0) {
01081       return 0;
01082    }
01083    basket = GetFreshBasket();
01084 
01085    // fSkipZip is old stuff still maintained for CDF
01086    if (fSkipZip) basket->SetBit(TBufferFile::kNotDecompressed);
01087    if (fBasketBytes[basketnumber] == 0) {
01088       fBasketBytes[basketnumber] = basket->ReadBasketBytes(fBasketSeek[basketnumber],file);
01089    }
01090    //add branch to cache (if any)
01091    TFileCacheRead *pf = file->GetCacheRead();
01092    if (pf){
01093       if (pf->IsLearning()) pf->AddBranch(this);
01094       if (fSkipZip) pf->SetSkipZip();
01095    }
01096 
01097    //now read basket
01098    Int_t badread = basket->ReadBasketBuffers(fBasketSeek[basketnumber],fBasketBytes[basketnumber],file);
01099    if (badread || basket->GetSeekKey() != fBasketSeek[basketnumber]) {
01100       nerrors++;
01101       if (nerrors > 10) return 0;
01102       if (nerrors == 10) {
01103          printf(" file probably overwritten: stopping reporting error messages\n");
01104          if (fBasketSeek[basketnumber] > 2000000000) {
01105             printf("===>File is more than 2 Gigabytes\n");
01106             return 0;
01107          }
01108          if (fBasketSeek[basketnumber] > 1000000000) {
01109             printf("===>Your file is may be bigger than the maximum file size allowed on your system\n");
01110             printf("    Check your AFS maximum file size limit for example\n");
01111             return 0;
01112          }
01113       }
01114       Error("GetBasket","File: %s at byte:%lld, branch:%s, entry:%lld, badread=%d, nerrors=%d, basketnumber=%d",file->GetName(),basket->GetSeekKey(),GetName(),fReadEntry,badread,nerrors,basketnumber);
01115       return 0;
01116    }
01117 
01118    ++fNBaskets;
01119    fBaskets.AddAt(basket,basketnumber);
01120    return basket;
01121 }
01122 
01123 //______________________________________________________________________________
01124 Long64_t TBranch::GetBasketSeek(Int_t basketnumber) const
01125 {
01126    //*-*-*-*-*Return address of basket in the file*-*-*-*-*-*
01127    //*-*      ====================================
01128 
01129    if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
01130    return fBasketSeek[basketnumber];
01131 }
01132 
01133 //______________________________________________________________________________
01134 TList* TBranch::GetBrowsables() {
01135    // Returns (and, if 0, creates) browsable objects for this branch
01136    // See TVirtualBranchBrowsable::FillListOfBrowsables.
01137    if (fBrowsables) return fBrowsables;
01138    fBrowsables=new TList();
01139    TVirtualBranchBrowsable::FillListOfBrowsables(*fBrowsables, this);
01140    return fBrowsables;
01141 }
01142 
01143 //______________________________________________________________________________
01144 const char * TBranch::GetClassName() const 
01145 {
01146    // Return the name of the user class whose content is stored in this branch,
01147    // if any.  If this branch was created using the 'leaflist' technique, this
01148    // function returns an empty string.
01149 
01150    return "";
01151 }
01152 
01153 //______________________________________________________________________________
01154 const char* TBranch::GetIconName() const
01155 {
01156    // Return icon name depending on type of branch.
01157 
01158    if (IsFolder())
01159       return "TBranchElement-folder";
01160    else
01161       return "TBranchElement-leaf";
01162 }
01163 
01164 //______________________________________________________________________________
01165 Int_t TBranch::GetEntry(Long64_t entry, Int_t getall)
01166 {
01167    // Read all leaves of entry and return total number of bytes read.
01168    //
01169    // The input argument "entry" is the entry number in the current tree.
01170    // In case of a TChain, the entry number in the current Tree must be found
01171    // before calling this function. For example:
01172    //
01173    //     TChain* chain = ...;
01174    //     Long64_t localEntry = chain->LoadTree(entry);
01175    //     branch->GetEntry(localEntry);
01176    //
01177    // The function returns the number of bytes read from the input buffer.
01178    // If entry does not exist, the function returns 0.
01179    // If an I/O error occurs, the function returns -1.
01180    //
01181    // See IMPORTANT REMARKS in TTree::GetEntry.
01182    //
01183 
01184    if (TestBit(kDoNotProcess) && !getall) {
01185       return 0;
01186    }
01187    if ((entry < fFirstEntry) || (entry >= fEntryNumber)) {
01188       return 0;
01189    }
01190    Int_t nbytes = 0;
01191    Long64_t first = fBasketEntry[fReadBasket];
01192    Long64_t last = 0;
01193    if (fReadBasket == fWriteBasket) {
01194       last = fEntryNumber - 1;
01195    } else {
01196       last = fBasketEntry[fReadBasket+1] - 1;
01197    }
01198    // Are we still in the same ReadBasket?
01199    if ((entry < first) || (entry > last)) {
01200       fReadBasket = TMath::BinarySearch(fWriteBasket + 1, fBasketEntry, entry);
01201       if (fReadBasket < 0) {
01202          Error("In the branch %s, no basket contains the entry %d\n", GetName(), entry);
01203          return -1;
01204       }
01205       first = fBasketEntry[fReadBasket];
01206    }
01207    // We have found the basket containing this entry.
01208    // make sure basket buffers are in memory.
01209    TBasket* basket = (TBasket*) fBaskets.UncheckedAt(fReadBasket);
01210    if (!basket) {
01211       basket = GetBasket(fReadBasket);
01212       if (!basket) {
01213          return -1;
01214       }
01215    }
01216    basket->PrepareBasket(entry);
01217    TBuffer* buf = basket->GetBufferRef();
01218    // This test necessary to read very old Root files (NvE).
01219    if (!buf) {
01220       TFile* file = GetFile(0);
01221       basket->ReadBasketBuffers(fBasketSeek[fReadBasket], fBasketBytes[fReadBasket], file);
01222       buf = basket->GetBufferRef();
01223    }
01224    // Set entry offset in buffer and read data from all leaves.
01225    buf->ResetMap();
01226    if (!buf->IsReading()) {
01227       basket->SetReadMode();
01228    }
01229    Int_t* entryOffset = basket->GetEntryOffset();
01230    Int_t bufbegin = 0;
01231    if (entryOffset) {
01232       bufbegin = entryOffset[entry-first];
01233    } else {
01234       bufbegin = basket->GetKeylen() + ((entry - first) * basket->GetNevBufSize());
01235    }
01236    buf->SetBufferOffset(bufbegin);
01237    Int_t* displacement = basket->GetDisplacement();
01238    if (displacement) {
01239       buf->SetBufferDisplacement(displacement[entry-first]);
01240    } else {
01241       buf->SetBufferDisplacement();
01242    }
01243    // Remember which entry we are reading.
01244    fReadEntry = entry;
01245    (this->*fReadLeaves)(*buf);
01246    nbytes = buf->Length() - bufbegin;
01247    return nbytes;
01248 }
01249 
01250 //______________________________________________________________________________
01251 Int_t TBranch::GetEntryExport(Long64_t entry, Int_t /*getall*/, TClonesArray* li, Int_t nentries)
01252 {
01253    // Read all leaves of an entry and export buffers to real objects in a TClonesArray list.
01254    //
01255    // Returns total number of bytes read.
01256 
01257    if (TestBit(kDoNotProcess)) {
01258       return 0;
01259    }
01260    if ((entry < 0) || (entry >= fEntryNumber)) {
01261       return 0;
01262    }
01263    Int_t nbytes = 0;
01264    Long64_t first  = fBasketEntry[fReadBasket];
01265    Long64_t last = 0;
01266    if (fReadBasket == fWriteBasket) {
01267       last = fEntryNumber - 1;
01268    } else {
01269       last = fBasketEntry[fReadBasket+1] - 1;
01270    }
01271    // Are we still in the same ReadBasket?
01272    if ((entry < first) || (entry > last)) {
01273       fReadBasket = TMath::BinarySearch(fWriteBasket + 1, fBasketEntry, entry);
01274       first = fBasketEntry[fReadBasket];
01275    }
01276 
01277    // We have found the basket containing this entry.
01278    // Make sure basket buffers are in memory.
01279    TBasket* basket = GetBasket(fReadBasket);
01280    if (!basket) {
01281       return 0;
01282    }
01283    TBuffer* buf = basket->GetBufferRef();
01284    // Set entry offset in buffer and read data from all leaves.
01285    if (!buf->IsReading()) {
01286       basket->SetReadMode();
01287    }
01288    Int_t bufbegin = 0;
01289    Int_t* entryOffset = basket->GetEntryOffset();
01290    if (entryOffset) {
01291       bufbegin = entryOffset[entry-first];
01292    } else {
01293       bufbegin = basket->GetKeylen() + ((entry - first) * basket->GetNevBufSize());
01294    }
01295    buf->SetBufferOffset(bufbegin);
01296    Int_t* displacement = basket->GetDisplacement();
01297    if (displacement) {
01298       buf->SetBufferDisplacement(displacement[entry-first]);
01299    } else {
01300       buf->SetBufferDisplacement();
01301    }
01302    // Remember which entry we are reading.
01303    fReadEntry = entry;
01304    TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(0);
01305    leaf->ReadBasketExport(*buf, li, nentries);
01306    nbytes = buf->Length() - bufbegin;
01307    return nbytes;
01308 }
01309 
01310 //______________________________________________________________________________
01311 Int_t TBranch::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
01312 {
01313    // Fill expectedClass and expectedType with information on the data type of the 
01314    // object/values contained in this branch (and thus the type of pointers
01315    // expected to be passed to Set[Branch]Address
01316    // return 0 in case of success and > 0 in case of failure.
01317    
01318    expectedClass = 0;
01319    expectedType = kOther_t;
01320    TLeaf* l = (TLeaf*) GetListOfLeaves()->At(0);
01321    if (l) {
01322       expectedType = (EDataType) gROOT->GetType(l->GetTypeName())->GetType();
01323       return 0;
01324    } else {
01325       Error("GetExpectedType", "Did not find any leaves in %s",GetName());
01326       return 1;
01327    }
01328 }
01329 
01330 //______________________________________________________________________________
01331 TFile* TBranch::GetFile(Int_t mode)
01332 {
01333    // Return pointer to the file where branch buffers reside, returns 0
01334    // in case branch buffers reside in the same file as tree header.
01335    // If mode is 1 the branch buffer file is recreated.
01336 
01337    if (fDirectory) return fDirectory->GetFile();
01338 
01339    // check if a file with this name is in the list of Root files
01340    TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(fFileName.Data());
01341    if (file) {
01342       fDirectory = file;
01343       return file;
01344    }
01345 
01346    if (fFileName.Length() == 0) return 0;
01347 
01348    TString bFileName( GetRealFileName() );
01349 
01350    // Open file (new file if mode = 1)
01351    {
01352       TDirectory::TContext ctxt(0);
01353       if (mode) file = TFile::Open(bFileName, "recreate");
01354       else      file = TFile::Open(bFileName);
01355    }
01356    if (!file) return 0;
01357    if (file->IsZombie()) {delete file; return 0;}
01358    fDirectory = (TDirectory*)file;
01359    return file;
01360 }
01361 
01362 //______________________________________________________________________________
01363 TBasket* TBranch::GetFreshBasket()
01364 {
01365    // Return a fresh basket by either resusing an existing basket that needs
01366    // to be drop (according to TTree::MemoryFull) or create a new one.
01367    
01368    TBasket *basket = 0;  
01369    if (GetTree()->MemoryFull(0)) {
01370       if (fNBaskets==1) {
01371          // Steal the existing basket
01372          Int_t oldindex = fBaskets.GetLast();
01373          basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
01374          if (!basket) {
01375             fBaskets.SetLast(-2); // For recalculation of Last.
01376             oldindex = fBaskets.GetLast();
01377             basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
01378          }
01379          if (basket && fBasketBytes[oldindex]!=0) {
01380             fBaskets.AddAt(0,oldindex);
01381             fBaskets.SetLast(-1);
01382             fNBaskets = 0;
01383          } else {
01384             basket = fTree->CreateBasket(this);
01385          }            
01386       } else if (fNBaskets == 0) {
01387          // There is nothing to drop!
01388          basket = fTree->CreateBasket(this);
01389       } else {
01390          // Memory is full and there is more than one basket,
01391          // Let DropBaskets do it job.
01392          DropBaskets();
01393          basket = fTree->CreateBasket(this);
01394       }
01395    } else {
01396       basket = fTree->CreateBasket(this);
01397    }   
01398    return basket;
01399 }
01400 
01401 //______________________________________________________________________________
01402 TLeaf* TBranch::GetLeaf(const char* name) const
01403 {
01404    //*-*-*-*-*-*Return pointer to the 1st Leaf named name in thisBranch-*-*-*-*-*
01405    //*-*        =======================================================
01406 
01407    Int_t i;
01408    for (i=0;i<fNleaves;i++) {
01409       TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
01410       if (!strcmp(leaf->GetName(),name)) return leaf;
01411    }
01412    return 0;
01413 }
01414 
01415 //______________________________________________________________________________
01416 TString TBranch::GetRealFileName() const
01417 {
01418    if (fFileName.Length()==0) {
01419       return fFileName;
01420    }
01421    TString bFileName = fFileName;
01422 
01423    // check if branch file name is absolute or a URL (e.g. /castor/...,
01424    // root://host/..., rfio:/path/...)
01425    char *bname = gSystem->ExpandPathName(fFileName.Data());
01426    if (!gSystem->IsAbsoluteFileName(bname) && !strstr(bname, ":/") && fTree && fTree->GetCurrentFile()) {
01427 
01428       // if not, get filename where tree header is stored
01429       const char *tfn = fTree->GetCurrentFile()->GetName();
01430 
01431       // If it is an archive file we need a special treatment
01432       TUrl arc(tfn);
01433       if (strlen(arc.GetAnchor()) > 0) {
01434          arc.SetAnchor(gSystem->BaseName(fFileName));
01435          bFileName = arc.GetUrl();
01436       } else {
01437          // if this is an absolute path or a URL then prepend this path
01438          // to the branch file name
01439          char *tname = gSystem->ExpandPathName(tfn);
01440          if (gSystem->IsAbsoluteFileName(tname) || strstr(tname, ":/")) {
01441             bFileName = gSystem->DirName(tname);
01442             bFileName += "/";
01443             bFileName += fFileName;
01444          }
01445          delete [] tname;
01446       }
01447    }
01448    delete [] bname;
01449 
01450    return bFileName;
01451 }
01452 
01453 //______________________________________________________________________________
01454 Int_t TBranch::GetRow(Int_t)
01455 {
01456    //*-*-*-*-*Return all elements of one row unpacked in internal array fValues*-*
01457    //*-*      =================================================================
01458 
01459    return 1;
01460 }
01461 
01462 //______________________________________________________________________________
01463 Bool_t TBranch::GetMakeClass() const
01464 {
01465    // Return whether this branch is in a mode where the object are decomposed
01466    // or not (Also known as MakeClass mode).
01467    
01468    // Regular TBranch and TBrancObject can not be in makeClass mode
01469 
01470    return kFALSE;
01471 }
01472    
01473 //______________________________________________________________________________
01474 TBranch* TBranch::GetMother() const
01475 {
01476    // Get our top-level parent branch in the tree.
01477 
01478    if (fMother) return fMother;
01479 
01480    const TObjArray* array = fTree->GetListOfBranches();
01481    Int_t n = array->GetEntriesFast();
01482    for (Int_t i = 0; i < n; ++i) {
01483       TBranch* branch = (TBranch*) array->UncheckedAt(i);
01484       TBranch* parent = branch->GetSubBranch(this);
01485       if (parent) {
01486          const_cast<TBranch*>(this)->fMother = branch; // We can not yet use the 'mutable' keyword
01487          return branch;
01488       }
01489    }
01490    return 0;
01491 }
01492 
01493 //______________________________________________________________________________
01494 TBranch* TBranch::GetSubBranch(const TBranch* child) const
01495 {
01496    // Find the parent branch of child.
01497    // Return 0 if child is not in this branch hierarchy.
01498 
01499    // Handle error condition, if the parameter is us, we cannot find the parent.
01500    if (this == child) {
01501       // Note: We cast away any const-ness of "this".
01502       return (TBranch*) this;
01503    }
01504 
01505    if (child->fParent) {
01506       return child->fParent;
01507    }
01508 
01509    Int_t len = fBranches.GetEntriesFast();
01510    for (Int_t i = 0; i < len; ++i) {
01511       TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
01512       if (!branch) {
01513          continue;
01514       }
01515       if (branch == child) {
01516          // We are the direct parent of child.
01517          const_cast<TBranch*>(child)->fParent = (TBranch*)this; // We can not yet use the 'mutable' keyword
01518          // Note: We cast away any const-ness of "this".
01519          const_cast<TBranch*>(child)->fParent = (TBranch*)this; // We can not yet use the 'mutable' keyword
01520          return (TBranch*) this;
01521       }
01522       // FIXME: This is a tail-recursion!
01523       TBranch* parent = branch->GetSubBranch(child);
01524       if (parent) {
01525          return parent;
01526       }
01527    }
01528    // We failed to find the parent.
01529    return 0;
01530 }
01531 
01532 //______________________________________________________________________________
01533 Long64_t TBranch::GetTotalSize(Option_t * /*option*/) const
01534 {
01535    // Return total number of bytes in the branch (including current buffer)
01536 
01537    TObjArray &baskets( const_cast<TObjArray&>(fBaskets) );
01538    TBasket *writebasket = 0;
01539    if (fNBaskets == 1) {
01540       writebasket = (TBasket*)fBaskets.UncheckedAt(fWriteBasket);
01541       if (writebasket && writebasket->GetNevBuf()==0) {
01542          baskets[fWriteBasket] = 0;
01543       } else {
01544          writebasket = 0;
01545       }
01546    }
01547    TBufferFile b(TBuffer::kWrite,10000);
01548    TBranch::Class()->WriteBuffer(b,(TBranch*)this);
01549    if (writebasket) {
01550       baskets[fWriteBasket] = writebasket;         
01551    }
01552    Long64_t totbytes = 0;
01553    if (fZipBytes > 0) totbytes = fTotBytes;
01554    return totbytes + b.Length();
01555 }
01556 
01557 //______________________________________________________________________________
01558 Long64_t TBranch::GetTotBytes(Option_t *option) const
01559 {
01560    // Return total number of bytes in the branch (excluding current buffer)
01561    // if option ="*" includes all sub-branches of this branch too
01562 
01563    Long64_t totbytes = fTotBytes;
01564    if (!option) return totbytes;
01565    if (option[0] != '*') return totbytes;
01566    //scan sub-branches
01567    Int_t len = fBranches.GetEntriesFast();
01568    for (Int_t i = 0; i < len; ++i) {
01569       TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
01570       if (branch) totbytes += branch->GetTotBytes();
01571    }
01572    return totbytes;
01573 }
01574 
01575 //______________________________________________________________________________
01576 Long64_t TBranch::GetZipBytes(Option_t *option) const
01577 {
01578    // Return total number of zip bytes in the branch
01579    // if option ="*" includes all sub-branches of this branch too
01580 
01581    Long64_t zipbytes = fZipBytes;
01582    if (!option) return zipbytes;
01583    if (option[0] != '*') return zipbytes;
01584    //scan sub-branches
01585    Int_t len = fBranches.GetEntriesFast();
01586    for (Int_t i = 0; i < len; ++i) {
01587       TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
01588       if (branch) zipbytes += branch->GetZipBytes();
01589    }
01590    return zipbytes;
01591 }
01592 
01593 //______________________________________________________________________________
01594 Bool_t TBranch::IsAutoDelete() const
01595 {
01596    // Return kTRUE if an existing object in a TBranchObject must be deleted.
01597    return TestBit(kAutoDelete);
01598 }
01599 
01600 //______________________________________________________________________________
01601 Bool_t TBranch::IsFolder() const
01602 {
01603    // Return kTRUE if more than one leaf or browsables, kFALSE otherwise.
01604    if (fNleaves > 1) {
01605       return kTRUE;
01606    }
01607    TList* browsables = const_cast<TBranch*>(this)->GetBrowsables();
01608    return browsables && browsables->GetSize();
01609 }
01610 
01611 //______________________________________________________________________________
01612 void TBranch::KeepCircular(Long64_t maxEntries)
01613 {
01614    // keep a maximum of fMaxEntries in memory
01615 
01616    Int_t dentries = (Int_t) (fEntries - maxEntries);
01617    TBasket* basket = (TBasket*) fBaskets.UncheckedAt(0);
01618    basket->MoveEntries(dentries);
01619    fEntries = maxEntries;
01620    fEntryNumber = maxEntries;
01621    //loop on sub branches
01622    Int_t nb = fBranches.GetEntriesFast();
01623    for (Int_t i = 0; i < nb; ++i)  {
01624       TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
01625       branch->KeepCircular(maxEntries);
01626    }
01627 }
01628 
01629 //______________________________________________________________________________
01630 Int_t TBranch::LoadBaskets()
01631 {
01632    //  Baskets associated to this branch are forced to be in memory.
01633    //  You can call TTree::SetMaxVirtualSize(maxmemory) to instruct
01634    //  the system that the total size of the imported baskets does not
01635    //  exceed maxmemory bytes.
01636    //  The function returns the number of baskets that have been put in memory.
01637    //  This method may be called to force all baskets of one or more branches
01638    //  in memory when random access to entries in this branch is required.
01639    //  See also TTree::LoadBaskets to load all baskets of all branches in memory.
01640 
01641    Int_t nimported = 0;
01642    Int_t nbaskets = fWriteBasket;
01643    TFile *file = GetFile(0);
01644    TBasket *basket;
01645    for (Int_t i=0;i<nbaskets;i++) {
01646       basket = (TBasket*)fBaskets.UncheckedAt(i);
01647       if (basket) continue;
01648       basket = GetFreshBasket();
01649       if (fBasketBytes[i] == 0) {
01650          fBasketBytes[i] = basket->ReadBasketBytes(fBasketSeek[i],file);
01651       }
01652       Int_t badread = basket->ReadBasketBuffers(fBasketSeek[i],fBasketBytes[i],file);
01653       if (badread) {
01654          Error("Loadbaskets","Error while reading basket buffer %d of branch %s",i,GetName());
01655          return -1;
01656       }
01657       ++fNBaskets;
01658       fBaskets.AddAt(basket,i);
01659       nimported++;
01660    }
01661    return nimported;
01662 }
01663 
01664 //______________________________________________________________________________
01665 void TBranch::Print(Option_t*) const
01666 {
01667    // Print TBranch parameters
01668 
01669    const int kLINEND = 77;
01670    Float_t cx = 1;
01671 
01672    TString titleContent(GetTitle());
01673    if ( titleContent == GetName() ) {
01674       titleContent.Clear();
01675    }
01676    
01677    if (fLeaves.GetEntries() == 1) {
01678       if (titleContent[titleContent.Length()-2]=='/' && isalpha(titleContent[titleContent.Length()-1])) {
01679          // The type is already encoded.  Nothing to do.
01680       } else {
01681          TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
01682          if (titleContent.Length()) {
01683             titleContent.Prepend(" ");
01684          }
01685          // titleContent.Append("type: ");
01686          titleContent.Prepend(leaf->GetTypeName());
01687       }
01688    }
01689    Int_t titleLength = titleContent.Length();
01690 
01691    Int_t aLength = titleLength + strlen(GetName());
01692    aLength += (aLength / 54 + 1) * 80 + 100;
01693    if (aLength < 200) aLength = 200;
01694    char *bline = new char[aLength];
01695 
01696    Long64_t totBytes = GetTotalSize();
01697    if (fZipBytes) cx = (fTotBytes+0.00001)/fZipBytes;
01698    if (titleLength) snprintf(bline,aLength,"*Br%5d :%-9s : %-54s *",fgCount,GetName(),titleContent.Data());
01699    else             snprintf(bline,aLength,"*Br%5d :%-9s : %-54s *",fgCount,GetName()," ");
01700    if (strlen(bline) > UInt_t(kLINEND)) {
01701       char *tmp = new char[strlen(bline)+1];
01702       if (titleLength) strlcpy(tmp, titleContent.Data(),strlen(bline)+1);
01703       snprintf(bline,aLength,"*Br%5d :%-9s : ",fgCount,GetName());
01704       int pos = strlen (bline);
01705       int npos = pos;
01706       int beg=0, end;
01707       while (beg < titleLength) {
01708          for (end=beg+1; end < titleLength-1; end ++)
01709             if (tmp[end] == ':')  break;
01710          if (npos + end-beg+1 >= 78) {
01711             while (npos < kLINEND) {
01712                bline[pos ++] = ' ';
01713                npos ++;
01714             }
01715             bline[pos ++] = '*';
01716             bline[pos ++] = '\n';
01717             bline[pos ++] = '*';
01718             npos = 1;
01719             for (; npos < 12; npos ++)
01720                bline[pos ++] = ' ';
01721             bline[pos-2] = '|';
01722          }
01723          for (int n = beg; n <= end; n ++)
01724             bline[pos+n-beg] = tmp[n];
01725          pos += end-beg+1;
01726          npos += end-beg+1;
01727          beg = end+1;
01728       }
01729       while (npos < kLINEND) {
01730          bline[pos ++] = ' ';
01731          npos ++;
01732       }
01733       bline[pos ++] = '*';
01734       bline[pos] = '\0';
01735       delete[] tmp;
01736    }
01737    Printf("%s", bline);
01738    if (fTotBytes > 2000000000) {
01739       Printf("*Entries :%lld : Total  Size=%11lld bytes  File Size  = %lld *",fEntries,totBytes,fZipBytes);
01740    } else {
01741       if (fZipBytes > 0) {
01742          Printf("*Entries :%9lld : Total  Size=%11lld bytes  File Size  = %10lld *",fEntries,totBytes,fZipBytes);
01743       } else {
01744          if (fWriteBasket > 0) {
01745             Printf("*Entries :%9lld : Total  Size=%11lld bytes  All baskets in memory   *",fEntries,totBytes);
01746          } else {
01747             Printf("*Entries :%9lld : Total  Size=%11lld bytes  One basket in memory    *",fEntries,totBytes);
01748          }
01749       }
01750    }
01751    Printf("*Baskets :%9d : Basket Size=%11d bytes  Compression= %6.2f     *",fWriteBasket,fBasketSize,cx);
01752    Printf("*............................................................................*");
01753    delete [] bline;
01754    fgCount++;
01755 }
01756 
01757 //______________________________________________________________________________
01758 void TBranch::ReadBasket(TBuffer&)
01759 {
01760    // Loop on all leaves of this branch to read Basket buffer.
01761 
01762    //   fLeaves->ReadBasket(basket);
01763 }
01764 
01765 //______________________________________________________________________________
01766 void TBranch::ReadLeavesImpl(TBuffer& b)
01767 {
01768    // Loop on all leaves of this branch to read Basket buffer.
01769 
01770    for (Int_t i = 0; i < fNleaves; ++i) {
01771       TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
01772       leaf->ReadBasket(b);
01773    }
01774 }
01775 
01776 //______________________________________________________________________________
01777 void TBranch::Refresh(TBranch* b)
01778 {
01779    //  refresh this branch using new information in b
01780    //  This function is called by TTree::Refresh
01781 
01782    fEntryOffsetLen = b->fEntryOffsetLen;
01783    fWriteBasket    = b->fWriteBasket;
01784    fEntryNumber    = b->fEntryNumber;
01785    fMaxBaskets     = b->fMaxBaskets;
01786    fEntries        = b->fEntries;
01787    fTotBytes       = b->fTotBytes;
01788    fZipBytes       = b->fZipBytes;
01789    fReadBasket     = 0;
01790    delete [] fBasketBytes;
01791    delete [] fBasketEntry;
01792    delete [] fBasketSeek;
01793    fBasketBytes = new Int_t[fMaxBaskets];
01794    fBasketEntry = new Long64_t[fMaxBaskets];
01795    fBasketSeek  = new Long64_t[fMaxBaskets];
01796    Int_t i;
01797    for (i=0;i<fMaxBaskets;i++) {
01798       fBasketBytes[i] = b->fBasketBytes[i];
01799       fBasketEntry[i] = b->fBasketEntry[i];
01800       fBasketSeek[i]  = b->fBasketSeek[i];
01801    }
01802    fBaskets.Delete();
01803    Int_t nbaskets = b->fBaskets.GetSize();
01804    fBaskets.Expand(nbaskets);
01805    // If the current fWritebasket is in memory, take it (just swap)
01806    // from the Tree being read
01807    TBasket *basket = (TBasket*)b->fBaskets.UncheckedAt(fWriteBasket);
01808    fBaskets.AddAt(basket,fWriteBasket);
01809    if (basket) {
01810       fNBaskets = 1;
01811       --(b->fNBaskets);
01812       b->fBaskets.RemoveAt(fWriteBasket);
01813       basket->SetBranch(this);
01814    }
01815 }
01816 
01817 //______________________________________________________________________________
01818 void TBranch::Reset(Option_t*)
01819 {
01820    // Reset a Branch.
01821    //
01822    // Existing buffers are deleted.
01823    // Entries, max and min are reset.
01824    //
01825 
01826    fReadBasket = 0;
01827    fReadEntry = -1;
01828    fWriteBasket = 0;
01829    fEntries = 0;
01830    fTotBytes = 0;
01831    fZipBytes = 0;
01832    fEntryNumber = 0;
01833 
01834    if (fBasketBytes) {
01835       for (Int_t i = 0; i < fMaxBaskets; ++i) {
01836          fBasketBytes[i] = 0;
01837       }
01838    }
01839 
01840    if (fBasketEntry) {
01841       for (Int_t i = 0; i < fMaxBaskets; ++i) {
01842          fBasketEntry[i] = 0;
01843       }
01844    }
01845 
01846    if (fBasketSeek) {
01847       for (Int_t i = 0; i < fMaxBaskets; ++i) {
01848          fBasketSeek[i] = 0;
01849       }
01850    }
01851 
01852    fBaskets.Delete();
01853    fNBaskets = 0;
01854 }
01855 
01856 //______________________________________________________________________________
01857 void TBranch::ResetAddress()
01858 {
01859    // Reset the address of the branch.
01860 
01861    fAddress = 0;
01862 
01863    //  Reset last read entry number, we have will had new user object now.
01864    fReadEntry = -1;
01865 
01866    for (Int_t i = 0; i < fNleaves; ++i) {
01867       TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
01868       leaf->SetAddress(0);
01869    }
01870 
01871    Int_t nbranches = fBranches.GetEntriesFast();
01872    for (Int_t i = 0; i < nbranches; ++i)  {
01873       TBranch* abranch = (TBranch*) fBranches[i];
01874       // FIXME: This is a tail recursion.
01875       abranch->ResetAddress();
01876    }
01877 }
01878 
01879 //______________________________________________________________________________
01880 void TBranch::ResetCount()
01881 {
01882    // Static function resetting fgCount
01883    fgCount = 0;
01884 }
01885 
01886 //______________________________________________________________________________
01887 void TBranch::SetAddress(void* addr)
01888 {
01889    // Set address of this branch.
01890    if (TestBit(kDoNotProcess)) {
01891       return;
01892    }
01893    fReadEntry = -1;
01894    fAddress = (char*) addr;
01895    for (Int_t i = 0; i < fNleaves; ++i) {
01896       TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
01897       Int_t offset = leaf->GetOffset();
01898       if (TestBit(kIsClone)) {
01899          offset = 0;
01900       }
01901       if (fAddress) leaf->SetAddress(fAddress + offset);
01902       else leaf->SetAddress(0);
01903    }
01904 }
01905 
01906 //______________________________________________________________________________
01907 void TBranch::SetAutoDelete(Bool_t autodel)
01908 {
01909    // Set the automatic delete bit.
01910    //
01911    // This bit is used by TBranchObject::ReadBasket to decide if an object
01912    // referenced by a TBranchObject must be deleted or not before reading
01913    // a new entry.
01914    //
01915    // If autodel is kTRUE, this existing object will be deleted, a new object
01916    // created by the default constructor, then read from disk by the streamer.
01917    //
01918    // If autodel is kFALSE, the existing object is not deleted.  Root assumes
01919    // that the user is taking care of deleting any internal object or array
01920    // (this can be done in the streamer).
01921 
01922    if (autodel) {
01923       SetBit(kAutoDelete, 1);
01924    } else {
01925       SetBit(kAutoDelete, 0);
01926    }
01927 }
01928 
01929 //______________________________________________________________________________
01930 void TBranch::SetBasketSize(Int_t buffsize)
01931 {
01932    // Set the basket size
01933    // The function makes sure that the basket size is greater than fEntryOffsetlen
01934 
01935    if (buffsize < 100+fEntryOffsetLen) buffsize = 100+fEntryOffsetLen;
01936    fBasketSize = buffsize;
01937    TBasket *basket = (TBasket*)fBaskets[fWriteBasket];
01938    if (basket) {
01939       basket->AdjustSize(fBasketSize);
01940    }
01941 }
01942 
01943 //______________________________________________________________________________
01944 void TBranch::SetBufferAddress(TBuffer* buf)
01945 {
01946    // -- Set address of this branch directly from a TBuffer to avoid streaming.
01947    //
01948    // Note: We do not take ownership of the buffer.
01949    //
01950 
01951    // Check this is possible
01952    if ( (fNleaves != 1)
01953        || (strcmp("TLeafObject",fLeaves.UncheckedAt(0)->ClassName())!=0) ) {
01954       Error("TBranch::SetAddress","Filling from a TBuffer can only be done with a not split object branch.  Request ignored.");
01955    } else {
01956       fReadEntry = -1;
01957       // Note: We do not take ownership of the buffer.
01958       fEntryBuffer = buf;
01959    }
01960 }
01961 
01962 //______________________________________________________________________________
01963 void TBranch::SetCompressionLevel(Int_t level)
01964 {
01965    //*-*-*-*-*-*-*-*Set the branch/subbranches compression level
01966    //*-*            ============================================
01967 
01968    fCompress = level;
01969    Int_t nb = fBranches.GetEntriesFast();
01970 
01971    for (Int_t i=0;i<nb;i++) {
01972       TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
01973       branch->SetCompressionLevel(level);
01974    }
01975 }
01976 
01977 //______________________________________________________________________________
01978 void TBranch::SetEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
01979 {
01980    // Update the default value for the branch's fEntryOffsetLen if and only if
01981    // it was already non zero (and the new value is not zero)
01982    // If updateExisting is true, also update all the existing branches.
01983 
01984    if (fEntryOffsetLen && newdefault) {
01985       fEntryOffsetLen = newdefault;
01986    }
01987    if (updateExisting) {
01988       TIter next( GetListOfBranches() );
01989       TBranch *b;
01990       while ( ( b = (TBranch*)next() ) ) {
01991          b->SetEntryOffsetLen( newdefault, kTRUE );
01992       }
01993    }
01994 }
01995 
01996 //______________________________________________________________________________
01997 void TBranch::SetEntries(Long64_t entries)
01998 {
01999    // Set the number of entries in this branch.
02000 
02001    fEntries = entries;
02002    fEntryNumber = entries;
02003 }
02004 
02005 //______________________________________________________________________________
02006 void TBranch::SetFile(TFile* file)
02007 {
02008    // Set file where this branch writes/reads its buffers.
02009    // By default the branch buffers reside in the file where the
02010    // Tree was created.
02011    // If the file name where the tree was created is an absolute
02012    // path name or an URL (e.g. /castor/... or root://host/...)
02013    // and if the fname is not an absolute path name or an URL then
02014    // the path of the tree file is prepended to fname to make the
02015    // branch file relative to the tree file. In this case one can
02016    // move the tree + all branch files to a different location in
02017    // the file system and still access the branch files.
02018    // The ROOT file will be connected only when necessary.
02019    // If called by TBranch::Fill (via TBasket::WriteFile), the file
02020    // will be created with the option "recreate".
02021    // If called by TBranch::GetEntry (via TBranch::GetBasket), the file
02022    // will be opened in read mode.
02023    // To open a file in "update" mode or with a certain compression
02024    // level, use TBranch::SetFile(TFile *file).
02025 
02026    if (file == 0) file = fTree->GetCurrentFile();
02027    fDirectory = (TDirectory*)file;
02028    if (file == fTree->GetCurrentFile()) fFileName = "";
02029    else                                 fFileName = file->GetName();
02030 
02031    // Apply to all existing baskets.
02032    TIter nextb(GetListOfBaskets());
02033    TBasket *basket;
02034    while ((basket = (TBasket*)nextb())) {
02035       basket->SetParent(file);
02036    }
02037 
02038    // Apply to sub-branches as well.
02039    TIter next(GetListOfBranches());
02040    TBranch *branch;
02041    while ((branch = (TBranch*)next())) {
02042       branch->SetFile(file);
02043    }
02044 }
02045 
02046 //______________________________________________________________________________
02047 void TBranch::SetFile(const char* fname)
02048 {
02049    // Set file where this branch writes/reads its buffers.
02050    // By default the branch buffers reside in the file where the
02051    // Tree was created.
02052    // If the file name where the tree was created is an absolute
02053    // path name or an URL (e.g. /castor/... or root://host/...)
02054    // and if the fname is not an absolute path name or an URL then
02055    // the path of the tree file is prepended to fname to make the
02056    // branch file relative to the tree file. In this case one can
02057    // move the tree + all branch files to a different location in
02058    // the file system and still access the branch files.
02059    // The ROOT file will be connected only when necessary.
02060    // If called by TBranch::Fill (via TBasket::WriteFile), the file
02061    // will be created with the option "recreate".
02062    // If called by TBranch::GetEntry (via TBranch::GetBasket), the file
02063    // will be opened in read mode.
02064    // To open a file in "update" mode or with a certain compression
02065    // level, use TBranch::SetFile(TFile *file).
02066 
02067    fFileName  = fname;
02068    fDirectory = 0;
02069 
02070    //apply to sub-branches as well
02071    TIter next(GetListOfBranches());
02072    TBranch *branch;
02073    while ((branch = (TBranch*)next())) {
02074       branch->SetFile(fname);
02075    }
02076 }
02077 
02078 //______________________________________________________________________________
02079 Bool_t TBranch::SetMakeClass(Bool_t /* decomposeObj */)
02080 {
02081    // Set the branch in a mode where the object are decomposed
02082    // (Also known as MakeClass mode).
02083    // Return whether the setting was possible (it is not possible for
02084    // TBranch and TBranchObject).
02085    
02086    // Regular TBranch and TBrancObject can not be in makeClass mode
02087    return kFALSE;
02088 }
02089 
02090 //______________________________________________________________________________
02091 void TBranch::SetObject(void * /* obj */)
02092 {
02093    // Set object this branch is pointing to.
02094 
02095    if (TestBit(kDoNotProcess)) {
02096       return;
02097    }
02098    Warning("SetObject","is not supported in TBranch objects");
02099 }
02100 
02101 //______________________________________________________________________________
02102 void TBranch::SetStatus(Bool_t status)
02103 {
02104    // Set branch status to Process or DoNotProcess.
02105       
02106    if (status) ResetBit(kDoNotProcess);
02107    else        SetBit(kDoNotProcess);
02108 }
02109 
02110 //_______________________________________________________________________
02111 void TBranch::Streamer(TBuffer& b)
02112 {
02113    // Stream a class object
02114 
02115    if (b.IsReading()) {
02116       UInt_t R__s, R__c;
02117       fTree = gTree;
02118       fAddress = 0;
02119       gROOT->SetReadingObject(kTRUE);
02120       Version_t v = b.ReadVersion(&R__s, &R__c);
02121       if (v > 9) {
02122          b.ReadClassBuffer(TBranch::Class(), this, v, R__s, R__c);
02123 
02124          if (fWriteBasket>=fBaskets.GetSize()) {
02125             fBaskets.Expand(fWriteBasket+1);
02126          }
02127          fDirectory = 0;
02128          fNleaves = fLeaves.GetEntriesFast();
02129          for (Int_t i=0;i<fNleaves;i++) {
02130             TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
02131             leaf->SetBranch(this);
02132          }
02133 
02134          fNBaskets = fBaskets.GetEntries();
02135          for (Int_t j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
02136             TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
02137             if (bk) {
02138                bk->SetBranch(this);
02139                GetTree()->IncrementTotalBuffers(bk->GetBufferSize());
02140                ++n;
02141             }
02142          }
02143          if (fWriteBasket >= fMaxBaskets) {
02144             //old versions may need this fix
02145             ExpandBasketArrays();
02146             fBasketBytes[fWriteBasket] = fBasketBytes[fWriteBasket-1];
02147             fBasketEntry[fWriteBasket] = fEntries;
02148             fBasketSeek [fWriteBasket] = fBasketSeek [fWriteBasket-1];
02149 
02150          }
02151          if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
02152          gROOT->SetReadingObject(kFALSE);
02153          return;
02154       }
02155       //====process old versions before automatic schema evolution
02156       Int_t n,i,j,ijunk;
02157       if (v > 5) {
02158          Stat_t djunk;
02159          TNamed::Streamer(b);
02160          if (v > 7) TAttFill::Streamer(b);
02161          b >> fCompress;
02162          b >> fBasketSize;
02163          b >> fEntryOffsetLen;
02164          b >> fWriteBasket;
02165          b >> ijunk; fEntryNumber = (Long64_t)ijunk;
02166          b >> fOffset;
02167          b >> fMaxBaskets;
02168          if (v > 6) b >> fSplitLevel;
02169          b >> djunk; fEntries  = (Long64_t)djunk;
02170          b >> djunk; fTotBytes = (Long64_t)djunk;
02171          b >> djunk; fZipBytes = (Long64_t)djunk;
02172 
02173          fBranches.Streamer(b);
02174          fLeaves.Streamer(b);
02175          fBaskets.Streamer(b);
02176          fBasketBytes = new Int_t[fMaxBaskets];
02177          fBasketEntry = new Long64_t[fMaxBaskets];
02178          fBasketSeek  = new Long64_t[fMaxBaskets];
02179          Char_t isArray;
02180          b >> isArray;
02181          b.ReadFastArray(fBasketBytes,fMaxBaskets);
02182          b >> isArray;
02183          for (i=0;i<fMaxBaskets;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
02184          b >> isArray;
02185          for (i=0;i<fMaxBaskets;i++) {
02186             if (isArray == 2) b >> fBasketSeek[i];
02187             else              {Int_t bsize; b >> bsize; fBasketSeek[i] = (Long64_t)bsize;};
02188          }
02189          fFileName.Streamer(b);
02190          b.CheckByteCount(R__s, R__c, TBranch::IsA());
02191          fDirectory = 0;
02192          fNleaves = fLeaves.GetEntriesFast();
02193          for (i=0;i<fNleaves;i++) {
02194             TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
02195             leaf->SetBranch(this);
02196          }
02197          fNBaskets = fBaskets.GetEntries();
02198          for (j=fWriteBasket,n=0;j>0 && n<fNBaskets;--j) {
02199             TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
02200             if (bk) {
02201                bk->SetBranch(this);
02202                GetTree()->IncrementTotalBuffers(bk->GetBufferSize());
02203                ++n;
02204             }
02205          }
02206          if (fWriteBasket >= fMaxBaskets) {
02207             //old versions may need this fix
02208             ExpandBasketArrays();
02209             fBasketBytes[fWriteBasket] = fBasketBytes[fWriteBasket-1];
02210             fBasketEntry[fWriteBasket] = fEntries;
02211             fBasketSeek [fWriteBasket] = fBasketSeek [fWriteBasket-1];
02212 
02213          }
02214          // Check Byte Count is not needed since it was done in ReadBuffer
02215          if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
02216          gROOT->SetReadingObject(kFALSE);
02217          b.CheckByteCount(R__s, R__c, TBranch::IsA());
02218          return;
02219       }
02220       //====process very old versions
02221       Stat_t djunk;
02222       TNamed::Streamer(b);
02223       b >> fCompress;
02224       b >> fBasketSize;
02225       b >> fEntryOffsetLen;
02226       b >> fMaxBaskets;
02227       b >> fWriteBasket;
02228       b >> ijunk; fEntryNumber = (Long64_t)ijunk;
02229       b >> djunk; fEntries  = (Long64_t)djunk;
02230       b >> djunk; fTotBytes = (Long64_t)djunk;
02231       b >> djunk; fZipBytes = (Long64_t)djunk;
02232       b >> fOffset;
02233       fBranches.Streamer(b);
02234       fLeaves.Streamer(b);
02235       fNleaves = fLeaves.GetEntriesFast();
02236       for (i=0;i<fNleaves;i++) {
02237          TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
02238          leaf->SetBranch(this);
02239       }
02240       fBaskets.Streamer(b);
02241       Int_t nbaskets = fBaskets.GetEntries();
02242       for (j=fWriteBasket,n=0;j>0 && n<nbaskets;--j) {
02243          TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
02244          if (bk) {
02245             bk->SetBranch(this);
02246             GetTree()->IncrementTotalBuffers(bk->GetBufferSize());
02247             ++n;
02248          }
02249       }
02250       fBasketEntry = new Long64_t[fMaxBaskets];
02251       b >> n;
02252       for (i=0;i<n;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
02253       fBasketBytes = new Int_t[fMaxBaskets];
02254       if (v > 4) {
02255          n  = b.ReadArray(fBasketBytes);
02256       } else {
02257          for (n=0;n<fMaxBaskets;n++) fBasketBytes[n] = 0;
02258       }
02259       if (v < 2) {
02260          fBasketSeek = new Long64_t[fMaxBaskets];
02261          for (n=0;n<fWriteBasket;n++) {
02262             fBasketSeek[n] = GetBasket(n)->GetSeekKey();
02263          }
02264       } else {
02265          fBasketSeek = new Long64_t[fMaxBaskets];
02266          b >> n;
02267          for (n=0;n<fMaxBaskets;n++) {
02268             Int_t aseek;
02269             b >> aseek;
02270             fBasketSeek[n] = Long64_t(aseek);
02271          }
02272       }
02273       if (v > 2) {
02274          fFileName.Streamer(b);
02275       }
02276       fDirectory = 0;
02277       if (v < 4) SetAutoDelete(kTRUE);
02278       if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
02279       gROOT->SetReadingObject(kFALSE);
02280       b.CheckByteCount(R__s, R__c, TBranch::IsA());
02281       //====end of old versions
02282 
02283    } else {
02284       Int_t maxBaskets = fMaxBaskets;
02285       fMaxBaskets = fWriteBasket+1;
02286       if (fMaxBaskets < 10) fMaxBaskets=10;
02287       TBasket *writebasket = 0;
02288       if (fNBaskets == 1) {
02289          writebasket = (TBasket*)fBaskets.UncheckedAt(fWriteBasket);
02290          if (writebasket && writebasket->GetNevBuf()==0) {
02291             fBaskets[fWriteBasket] = 0;
02292          } else {
02293             writebasket = 0;
02294          }
02295       }
02296       b.WriteClassBuffer(TBranch::Class(),this);
02297       if (writebasket) {
02298          fBaskets[fWriteBasket] = writebasket;         
02299       }
02300       fMaxBaskets = maxBaskets;
02301    }
02302 }
02303 
02304 //_______________________________________________________________________
02305 Int_t TBranch::WriteBasket(TBasket* basket, Int_t where)
02306 {
02307    // Write the current basket to disk and return the number of bytes
02308    // written to the file.
02309 
02310    Int_t nout  = basket->WriteBuffer();    //  Write buffer
02311    fBasketBytes[where]  = basket->GetNbytes();
02312    fBasketSeek[where]   = basket->GetSeekKey();
02313    Int_t addbytes = basket->GetObjlen() + basket->GetKeylen();
02314    TBasket *reusebasket = 0;
02315    if (nout>0) {
02316       // The Basket was written so we can now safely reuse it.
02317       fBaskets[where] = 0;
02318 
02319       reusebasket = basket;
02320       reusebasket->Reset();
02321    }
02322    fZipBytes += nout;
02323    fTotBytes += addbytes;
02324    fTree->AddTotBytes(addbytes);
02325    fTree->AddZipBytes(nout);
02326 
02327    if (where==fWriteBasket) {
02328       ++fWriteBasket;
02329       if (fWriteBasket >= fMaxBaskets) {
02330          ExpandBasketArrays();
02331       }
02332       fBaskets.AddAtAndExpand(reusebasket,fWriteBasket);
02333       fBasketEntry[fWriteBasket] = fEntryNumber;
02334    } else {
02335       --fNBaskets;
02336       fBaskets[where] = 0;
02337       basket->DropBuffers();
02338       delete basket;
02339    }
02340 
02341    return nout;
02342 }
02343 
02344 //------------------------------------------------------------------------------
02345 void TBranch::SetFirstEntry(Long64_t entry)
02346 {
02347    //set the first entry number (case of TBranchSTL)
02348    fFirstEntry = entry;
02349    fEntries = 0;
02350    fEntryNumber = entry;
02351    if( fBasketEntry )
02352       fBasketEntry[0] = entry;
02353    for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i )
02354       ((TBranch*)fBranches[i])->SetFirstEntry( entry );
02355 }
02356 
02357 //______________________________________________________________________________
02358 void TBranch::SetupAddresses()
02359 {
02360    // -- If the branch address is not set,  we set all addresses starting with
02361    // the top level parent branch.  
02362    
02363    // Nothing to do for regular branch, the TLeaf already did it.
02364 }
02365 
02366 //______________________________________________________________________________
02367 void TBranch::UpdateFile()
02368 {
02369    // Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
02370    // with the current value of fTree->GetCurrentFile unless this branch has been
02371    // redirected to a different file.  Also update the sub-branches.
02372 
02373    TFile *file = fTree->GetCurrentFile();
02374    if (fFileName.Length() == 0) {
02375       fDirectory = file;
02376 
02377       // Apply to all existing baskets.
02378       TIter nextb(GetListOfBaskets());
02379       TBasket *basket;
02380       while ((basket = (TBasket*)nextb())) {
02381          basket->SetParent(file);
02382       }
02383    }
02384 
02385    // Apply to sub-branches as well.
02386    TIter next(GetListOfBranches());
02387    TBranch *branch;
02388    while ((branch = (TBranch*)next())) {
02389       branch->UpdateFile();
02390    }
02391 }

Generated on Tue Jul 5 15:33:34 2011 for ROOT_528-00b_version by  doxygen 1.5.1