TBranchRef.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TBranchRef.cxx 37275 2010-12-04 21:32:11Z pcanal $
00002 // Author: Rene Brun   19/08/2004
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, 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 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // A branch containing and managing a TRefTable for TRef autoloading.   //
00015 // It loads the TBranch containing a referenced object when requested   //
00016 // by TRef::GetObject(), so the reference can be resolved. The          //
00017 // information which branch to load is stored by TRefTable. Once a      //
00018 // TBranch has read the TBranchRef's current entry it will not be told  //
00019 // to re-read, in case the use has changed objects read from the        //
00020 // branch.                                                              //
00021 //                                                                      //
00022 //                                                                      //
00023 // *** LIMITATION ***                                                   //
00024 // Note that this does NOT allow for autoloading of references spanning //
00025 // different entries. The TBranchRef's current entry has to correspond  //
00026 // to the entry of the TBranch containing the referenced object.        //
00027 //                                                                      //
00028 // The TRef cannot be stored in a top-level branch which is a           //
00029 // TBranchObject for the auto-loading to work. E.g. you cannot store    //
00030 // the TRefs in TObjArray, and create a top-level branch storing this   //
00031 // TObjArray.                                                           //
00032 //                                                                      //
00033 //////////////////////////////////////////////////////////////////////////
00034 
00035 #include "TBranchRef.h"
00036 #include "TTree.h"
00037 #include "TBasket.h"
00038 #include "TFile.h"
00039 #include "TFriendElement.h"
00040 
00041 ClassImp(TBranchRef)
00042 
00043 //______________________________________________________________________________
00044 TBranchRef::TBranchRef(): TBranch()
00045 {
00046    // Default constructor.
00047 
00048    fRefTable   = 0;
00049    fReadLeaves = (ReadLeaves_t)&TBranchRef::ReadLeavesImpl;
00050 }
00051 
00052 
00053 //______________________________________________________________________________
00054 TBranchRef::TBranchRef(TTree *tree)
00055     :TBranch()
00056 {
00057    // Main constructor called by TTree::BranchRef.
00058 
00059    if (!tree) return;
00060    SetName("TRefTable");
00061    SetTitle("List of branch numbers with referenced objects");
00062    fRefTable = new TRefTable(this,100);
00063 
00064    fCompress       = 1;
00065    fBasketSize     = 32000;
00066    fAddress        = 0;
00067    fBasketBytes    = new Int_t[fMaxBaskets];
00068    fBasketEntry    = new Long64_t[fMaxBaskets];
00069    fBasketSeek     = new Long64_t[fMaxBaskets];
00070 
00071    for (Int_t i=0;i<fMaxBaskets;i++) {
00072       fBasketBytes[i] = 0;
00073       fBasketEntry[i] = 0;
00074       fBasketSeek[i]  = 0;
00075    }
00076 
00077    fTree       = tree;
00078    fMother     = this;
00079    fDirectory  = fTree->GetDirectory();
00080    fFileName   = "";
00081    fReadLeaves = (ReadLeaves_t)&TBranchRef::ReadLeavesImpl;
00082 }
00083 
00084 
00085 //______________________________________________________________________________
00086 TBranchRef::~TBranchRef()
00087 {
00088    // Typical destructor.
00089 
00090    delete fRefTable;
00091 }
00092 
00093 //______________________________________________________________________________
00094 void TBranchRef::Clear(Option_t *option)
00095 {
00096   // Clear entries in the TRefTable.
00097 
00098    if (fRefTable) fRefTable->Clear(option);
00099 }
00100 
00101 //______________________________________________________________________________
00102 Int_t TBranchRef::Fill()
00103 {
00104   // Fill the branch basket with the referenced objects parent numbers.
00105 
00106    Int_t nbytes = TBranch::Fill();
00107    return nbytes;
00108 }
00109 
00110 //______________________________________________________________________________
00111 void TBranchRef::FillLeaves(TBuffer &b)
00112 {
00113    // This function called by TBranch::Fill overloads TBranch::FillLeaves.
00114 
00115    if (!fRefTable) fRefTable = new TRefTable(this,100);
00116    fRefTable->FillBuffer(b);
00117 }
00118 
00119 //______________________________________________________________________________
00120 Bool_t TBranchRef::Notify()
00121 {
00122    // This function is called by TRefTable::Notify, itself called by
00123    // TRef::GetObject.
00124    // The function reads the branch containing the object referenced
00125    // by the TRef.
00126 
00127    if (!fRefTable) fRefTable = new TRefTable(this,100);
00128    UInt_t uid = fRefTable->GetUID();
00129    TProcessID* context = fRefTable->GetUIDContext();
00130    GetEntry(fReadEntry);
00131    TBranch *branch = (TBranch*)fRefTable->GetParent(uid, context);
00132    if (branch) {
00133       // don't re-read, the user might have changed some object
00134       if (branch->GetReadEntry() != fReadEntry)
00135          branch->GetEntry(fReadEntry);
00136    } else {
00137       //scan the TRefTable of possible friend Trees
00138       TList *friends = fTree->GetListOfFriends();
00139       if (!friends) return kTRUE;
00140       TObjLink *lnk = friends->FirstLink();
00141       while (lnk) {
00142          TFriendElement* elem = (TFriendElement*)lnk->GetObject();
00143          TTree *tree = elem->GetTree();
00144          TBranchRef *bref = tree->GetBranchRef();
00145          if (bref) {
00146             bref->GetEntry(fReadEntry);
00147             branch = (TBranch*)bref->GetRefTable()->GetParent(uid, context);
00148             if (branch) {
00149                // don't re-read, the user might have changed some object
00150                if (branch->GetReadEntry() != fReadEntry)
00151                   branch->GetEntry(fReadEntry);
00152                return kTRUE;
00153             }
00154          }
00155          lnk = lnk->Next();
00156       }
00157    }
00158    return kTRUE;
00159 }
00160 
00161 //______________________________________________________________________________
00162 void TBranchRef::Print(Option_t *option) const
00163 {
00164   // Print the TRefTable branch.
00165 
00166    TBranch::Print(option);
00167 }
00168 
00169 //______________________________________________________________________________
00170 void TBranchRef::ReadLeavesImpl(TBuffer &b)
00171 {
00172    // This function called by TBranch::GetEntry overloads TBranch::ReadLeaves.
00173 
00174    if (!fRefTable) fRefTable = new TRefTable(this,100);
00175    fRefTable->ReadBuffer(b);
00176 }
00177 
00178 //______________________________________________________________________________
00179 void TBranchRef::Reset(Option_t *option)
00180 {
00181   //    Existing buffers are deleted
00182   //    Entries, max and min are reset
00183   //    TRefTable is cleared.
00184 
00185    TBranch::Reset(option);
00186    if (!fRefTable) fRefTable = new TRefTable(this,100);
00187    fRefTable->Reset();
00188 }
00189 
00190 //______________________________________________________________________________
00191 Int_t TBranchRef::SetParent(const TObject* object, Int_t branchID)
00192 {
00193    // -- Set the current parent branch.
00194    //
00195    // This function is called by TBranchElement::GetEntry()
00196    // and TBranchElement::Fill() when reading or writing
00197    // branches that may contain referenced objects.
00198    //
00199    if (!fRefTable) {
00200       fRefTable = new TRefTable(this, 100);
00201    }
00202    TRefTable::SetRefTable(fRefTable);
00203    return fRefTable->SetParent(object, branchID);
00204 }
00205 

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