Smoothly updating Streamer Format

Hi all,

recently I implemented some checks in our build system to spot mismatching ClassDef versions and to my horror I found a few classes which use the old Streamer version without a plus at the end of the classname in the linkdef.h

Now as far as I understand this basically disables evolution of the class as the contents are just stored as a blob in the file. Luckily these classes are just storing some conditions data and are not used or modified very often but I would like to remedy this to allow for future changes in these classes.

So I would like to switch to the new streamer version but still be able to read the existing files:

  • keep the class structure as it is
  • add the + in the linkdef.h
  • be able to read files containing old and current version of the class.

Is there a way where I can define how to read these old objects manually? Or is the best bet just to rename the classes and start from scratch?

Cheers,

Martin


ROOT Version: 6.20


@pcanal I afraid to do a misleading suggestion, could you please help here?

Hi Martin,

It depends on the content of the classes. If no array and no STL collection are involved then simply doing:

  • keep the class structure as it is
  • add the + in the linkdef.h
    should lead to:
  • be able to read files containing old and current version of the class.

If there are arrays or collections, the it might still work. If not, then you will to:

  • Generate the dictionary without the + in the linkdef.
  • Extract from the dictionary the Streamer member functions that are implemented there.
  • Generate the dictionary with the + in the linkdef.
  • Extract from the dictionary the Streamer member functions that are implement there. (Or just note their pattern
  • Add to your source class an Streamer member function
  • Replace the + by a - in the linkdef

Note: The major drawback of using the - in the LinkDef is that the objects are not longer split by default (you an over-ride is by class SomeClassName::Class()->SetCanSplit(true);

The new Streamer will look something like:

void SomeClassName::Streamer(TBuffer& b)
{
   if (b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = b.ReadVersion(&R__s, &R__c);
      if (R__v < class_version_number_when_you_notice_the_problem) {
        // Copy/paste of the Steamer method produce by the LinkDef with the +
      } else {
         b.ReadClassBuffer(SomeClassName::Class(), this, R__v, R__s, R__c);
     }
   } else {
     b.WriteClassBuffer(SomeClassName::Class(), this);
   }
}
1 Like

Thanks @pcanal, this is exactly the information I wanted. We can properly decide what to do now :smiley:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.