TH1 object reading failure due to new TH1 ClassVersionID

Hello,

Some software X saves serialized histograms in a database. Another software Y retrieve them, unserialize and use them. I have a problem because X is still using ROOT 5.30.06 and Y is using ROOT 5.33.02a. As a consequence I get the following error messages :
Error in TMessage::ReadClassBuffer: Could not find the StreamerInfo for version 6 of the class TH1, object skipped at offset 734
Error in TMessage::CheckByteCount: object of class TH1 read too few bytes: 2 instead of 716

Is there any way to handle this other than recompiling X ?
Thank you
Barth

Hello,

I have continued my investigations on this. I use TMessage to serialize and deserialize the object. I discovered the method EnableSchemaEvolution() that seemed to be exactly what I needed.
Unfortunately, this method is useful only if you use TMessage in conjunction with TSocket which takes care of sending the streamer info (someone said “tightly coupled” ?).

What I exactly do is

  TMessage message(kMESS_OBJECT);
  message.EnableSchemaEvolution(kTRUE);
  message.Reset();
  message.WriteObject(obj); // obj is a TH1F here, could be any TObject

  // put the serialized object in the TMysqlStatement object created beforehand
  statement->SetBinary(2, message.Buffer(), message.Length(), message.Length())

How can I send the streamerinfo to the database ?

Thank you
Barth

Replying to myself once more…

On the “client” side, I can get rid of the error if I load a TFile containing a TH1F before trying to deserialize my database object. It makes sense as the StreamerInfo is retained in memory after reading the TFile.

Knowing that I read the object from database like this

r = statement->GetBinary(0, blob, blobSize); // retrieve the data
TMessage mess;
 mess.SetBuffer(blob, blobSize, kFALSE);
 mess.SetReadMode();
 mess.Reset();
 void* mo =  mess.ReadObjectAny(mess.GetClass());

how could I get the StreamerInfo that I need without reading a TFile written by a previous version of ROOT ?

Thank you in advance for your help,
Barth

Hi Barth,

You should store the TStreamerInfo in the database and then you can retrieve them as needed from the client.

[quote]Unfortunately, this method is useful only if you use TMessage in conjunction with TSocket which takes care of sending the streamer info (someone said “tightly coupled” ?).[/quote]I am not sure what you mean by ‘useful only’, you should be to reuse the feature for own purpose. Once enabled and after the streaming, you can retrieve the list of StreamerInfo used in the message by calling TMessage::GetStreamerInfos. TSocket::SendStreamerInfos is an example on how to optimize the uploading (trying to reduce the amount of duplication).

Cheers,
Philippe.

Hello Philippe,

Actually, at the time I wrote the post TMessage::GetStreamerInfos was not available. Fons kindly implemented it following my Savannah ticket (savannah.cern.ch/bugs/?func=det … m_id=94297).

I can now store the streamer info in the database and use it.

I meant that TMessage::EnableSchemaEvolution() does nothing by itself which is not clear when simply looking at the interface of the class. Its sole purpose (afaik) is to raise a flag that is used by TSocket. When I looked at the API I thought that I could use this method and I would magically get the streamer included with the message. I was naive :wink:

Thank you for your reply,
Barth