Uploaded image for project: 'ROOT'
  1. ROOT
  2. ROOT-5035

Custom converter not called correctly on member variables



    • Type: Bug
    • Status: In Progress (View Workflow)
    • Priority: Medium
    • Resolution: Unresolved
    • Affects Version/s: 5.34/00, 6.00.00
    • Fix Version/s: None
    • Component/s: I/O
    • Labels:
    • Environment:



      Dear developers,

      Unfortunately I managed to find a new issue with the custom ROOT streamers/converters.

      Just in short, as Philippe should be well aware of the ATLAS use case: In the ATLAS EDM we use completely independent classes for writing information to files, and to actually do work in a compiled program. We call this the transient/persistent separation. Right now I'm trying to make use of the new custom ROOT streamer functionality in upgrading our data file format.

      One very prominent use case for us is to store smart pointers into files. We store a very minimal amount of information into the file, and based on this we re-create the pointer relationships between the objects when reading the file back. To do this efficiently, the transient objects have an internal state, as they try to only do time consuming operations when they really need to.

      Instead of going into the actual scenario in which I discovered the issue, I've put together a small piece of code (attached) to demonstrate the issue. It holds two classes (PersistentClass and TransientClass) that represent the same logical entity. TransientClass has the same variables as PersistentClass, but adds a few transient-only cache variables as well. To teach ROOT that these classes can be translated into each other, and that the transient class's cache has to be cleared after each read, I added this to my LinkDef.h file:

      #pragma read sourceClass="PersistentClass" version="[1-]" \
      targetClass="TransientClass" \
      source="" target="" code="{ newObj->Reset(); }"

      This actually works nicely. When I read back a branch that was written using PersistentClass, using a TransientClass object, everything behaves as expected.

      But I actually want to do something more complicated. I added two container classes, that each hold a single instance of PersistentClass and TransientClass. I called these classes PersistentHolder and TransientHolder. Since they practically only differ in their class names, and their only member objects should be possible to translate into each other, I added the following into my LinkDef.h file:

      #pragma read sourceClass="PersistentHolder" version="[1-]" \

      Now, I can even read a branch that was written using PersistentHolder, using a TransientHolder object. The basic variables of the TransientClass member object are even correctly read. But the Reset() function is never called on the member object of TransientHolder, so the member object doesn't behave correctly after the first event.

      Since all of this is the bleeding edge part of ROOT I/O, I can easily imagine that there is some issue in the I/O code that prevents the custom streamer to be called correctly. I hope that using the provided example code it will be possible to find the problem, as this functionality would be extremely important for ATLAS.





            pcanal Philippe Canal
            krasznaa Attila Krasznahorkay
            0 Vote for this issue
            4 Start watching this issue