split/non-split difference in SetAddress()

From: Andrei Salnikov (salnikov@SLAC.stanford.edu)
Date: Wed Sep 15 1999 - 00:28:54 MEST


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