Re: split/non-split difference in SetAddress()

From: Rene Brun (Rene.Brun@cern.ch)
Date: Wed Sep 15 1999 - 17:36:44 MEST


Hi Andy,
I appreciate the fact that you have been able to understand very deeply
the way the Tree/Branch mechanism works. Your analysis is perfectly
correct.
Now back to your question.
You can have a perfectly symmetric mechanism between split and non-plit
mode
if instead of:
  ClassBaseA* theObjectPointer_ = 0;
 (ie letting Root instantiate the object itself)
you make yourself an instance of the object.
I understand your argument about schema evolution and that you do not
know
a priori (I assume at compilation time) what your current class derived
from ClassBaseA will be. However, I assume that you must have a
mechanism
at run time to find out if you have a ClassA_001 or a ClassA_00N .
With Root you can create an instance of an object by knowing only
its class name, say "ClassA__003". Proceed as follows:
  - Get a pointer to the Root TClass object (RTTI) for this class
    TClass *cl = gROOT->GetClass("ClassA_003");
  - Create an instance of the object with:
    ClassBaseA* theObjectPointer_ = (ClassBaseA*)cl->New();
  - Now you can set the branch address
      theBranch_ -> SetAddress ( (void*)(&theObjectPointer_) ) ;

When the object already exists, Root input in split mode will not
destroy
the already existing object, theObjectPointer will always have the same
value.
In non-split mode, we have no choice but to delete the previous object
at the branch address because the new object has not the same size than
the previous object in general.


Rene Brun

Andrei Salnikov wrote:
> 
> Hi all,
> 
> I'm stuck with one of the SetAddress() features of the TBranchObject. I'm
> trying to implement what may be called a "schema evolution". Idea, which
> worked nice with other persistent data stores, is rather simple - for each
> new version of the persistent data we create a separate class definition
> with different name. So for each persistent data item we have a number of
> persitent classes (e.g. ClassA_001, ClassA_002, etc.) which have a common
> base class (say ClassBaseA) defining an interface sufficient for dealing
> with the data. As the schema evolves we have different trees having
> different concrete classes. Dealing with this in universal approach means
> accessing data in the tree throught the common base class. . This implies
> that we cannot allocate memory for the objects, as we do not know concrete
> type of the objects, ROOT should do it instead. Wery nice, I tried something
> like that:
> 
> //    Reader.h
> class Reader {
>    // ......
>    ClassBaseA* theObjectPointer_ ;
> };
> 
> // Reader.cc
> ClassBaseA*
> Reader::read( int eventIndex )
> {
>    if ( address_is_not_set_yet ) {
>       theObjectPointer_ = 0 ;
>       theBranch_ -> SetAddress ( (void*)(&theObjectPointer_) ) ;
>       say_address_is_set_now() ;
>    }
>    int nbytes = theBranch_ -> GetEntry( eventIndex ) ;
> 
>    return nbytes>0 ? theObjectPointer_ : 0 ;   // return null if no success
> }
> 
> It worked OK for objects written in non-split mode but failed read objects
> written in split mode. Although it did not fail completely - GetEntry()
> returned numbers grater that 0, but it did not set theObjectPointer_ to any
> value - the pointer remained 0 all the time. After digging in the ROOT code
> I was able to conclude that it really works in that way - when calling
> SetAddress() with pointer set to 0 for branch written in split mode, it
> creates an object internaly and all later reads put the data in that
> internal object, without passing pointer to this object back to the user.
> For the branches written in non-split mode situation is somewhat different
> (why?) - it creates new object for every read operation and changes the
> pointer so that it points to this new object. I can't really understand why
> is this difference in approaches, does it really must be like that? Can't we
> make the behavior more uniform across split and non-split branches?
> 
>   Cheers,
>   Andy.



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