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?
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);
}
}