Re: The splitlevel=1 mechanism.

From: Rene Brun (Rene.Brun@cern.ch)
Date: Wed Jun 09 1999 - 09:41:12 MEST


Hi Maurik,

The restrictions about the split mode listed at the URL:
    http://root.cern.ch/root/HowtoWriteTree.html
concern the automatic split mode. The last section of this URL says:
  "Making branches by hand

  If you are not happy with the way the automatic split algorithm works,
you can   create branches yourself by invoking directly the
TTree::Branch function." 

Obviously, we encourage people to create classes such that the automatic
split algorithm can be applied.
When you run in "NON-SPLIT" mode, the Streamer function for the
referenced
object is called.
When you run in SPLIT mode, each data member of the referenced object
is written to a separate branch.
 - If Root encounters a basic type, it does not need to invoke a
Streamer
   function (which one?). It can directly write this member to the
branch
   buffer.
 - same for a static array (eg, Int_t array[12])
 - If a member is a pointer to TObject* or derived, the corresponding
Streamer
   is called to stream this object in its branch buffer.
 - If a member is a pointer to a TClonesArray, each member of the class
   referenced by the TClonesArray is written to a separate branch. No
need
   for a Streamer in this case.

Rene Brun 
Maurik Holtrop wrote:
> 
> Hello Rene,
> 
> Thank you for the reply. I re-read the documentation you reccommended, and
> still don't understand through what method the classes are serialized when
> split_level=1. From my tests I think it is not the Streamer method.
> 
> The documentation states:
> "In split mode, a data member cannot be a pointer to an array of basic
> types."
> "In split mode, a data member cannot be a C structure."
> 
> So an array of structures is definetely out of the question with the
> standard code. But can I write my own?
> If I can not, is there a way to make writing a tree of my objects more
> efficient than the "create" "write" "delete" cycle that is currently used?
> 
> The full code for my classes (the one with the pointer into a big memory
> array) can be found at:
> http://improv.unh.edu/root_problem.txt. This file is a concat of 4 files:
> TBOSBankHeader.h and .cc and TBOSRoot.h and .cc.
> 
> Your help is much appreciated,
> 
>     Maurik Holtrop
> 
> P.S. Here is some example code.
> 
> Instead of the full class, I send you an example wich illustrates that the
> Streamer function of a class does not get called when writing the clas with
> split_level=1. This example however, works perfectly fine. When split level
> =1 the variables are written to disk through some other mechanism. However,
> for classes (unlike this example) that *need* a highly customized streamer,
> this means writing won't work.
> 
> The following macro (write.C) will print 10 times "Streamer called" when
> split level is 0, but not when split level is 1.
> 
> /////////////////////////// write.C:
> {
> tempa *part=new tempa(1,2.);
> TFile hfile("split.root","RECREATE","Demo ROOT file");
> TTree *tree = new TTree("T","An example");
> tree->Branch("tempa","tempa",&part,10240,0);
> 
> for(int i=0; i<10; i++){
>   part.i=i;
>   part.x=i*i*10.;
>   tree->Fill();
> }
> tree->Print();
> hfile.Write();
> hfile.Close();
> }
> 
> ////////////////////// test2.cc
> #include "test2.h"
> 
> ClassImp(tempa)
> 
> ostream &operator<<(ostream &os,tempa &b)
> {
>   os << "  Int: " << b.i;
>   os << "  Float: " << b.x;
>   os << "  C: " << b.str << endl;
>   return(os);
> }
> 
> void tempa::Streamer(TBuffer &R__b)
> {
>    // Stream an object of class tempa.
>   cerr << "Streamer called\n";
> 
>    if (R__b.IsReading()) {
>       Version_t R__v = R__b.ReadVersion(); if (R__v) { }
>       TObject::Streamer(R__b);
>       R__b >> i;
>       R__b >> x;
>       R__b.ReadStaticArray(str);
>    } else {
>       R__b.WriteVersion(tempa::IsA());
>       TObject::Streamer(R__b);
>       R__b << i;
>       R__b << x;
>       R__b.WriteArray(str, 256);
>    }
> }
> 
> ///////////////////// test2.h
> #ifndef __CINT__
> #include "TObject.h"
> #endif
> 
> #include <iostream.h>
> 
> class tempa : public TObject{
> 
>  public:
>   int i;
>   float x;
>   char str[256];
>  public:
> 
>   tempa(){ cout << "******** tempa constructor called\n";};
>   ~tempa(){cout << "######## tempa destructor called\n";};
>   tempa(int a,float b){
>     i=a;
>     x=b;
>     strcpy(str,"Initialized with constructor.");
>   }
> 
>   void Print(){
>     cout << (*this) << endl;
>   }
> 
>   friend ostream &operator<<(ostream &os,tempa &b);
> 
>   ClassDef(tempa,1)
> };
> 
>   ------------------------------------------------------------------------
> 
>   Maurik Holtrop <maurik.holtrop@unh.edu>
>   UNH Nuclear Physics
> 
>   Maurik Holtrop
>   UNH Nuclear Physics  <maurik.holtrop@unh.edu>
>   9 Library Way        Fax: (603) 862-2998
>   Lee                  Home: (603) 659-8765
>   NH                   Work: (603) 862-2019
>   03824                Netscape Conference Address
>   USA
>   Additional Information:
>   Last Name     Holtrop
>   First Name    Maurik
>   Version       2.1



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:34 MET