<!-- 
RSS generated by JIRA (8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d) at Wed Feb 07 20:10:28 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>OpenDaylight JIRA</title>
    <link>https://jira.opendaylight.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>8.20.10</version>
        <build-number>820010</build-number>
        <build-date>22-06-2022</build-date>
    </build-info>


<item>
            <title>[MDSAL-667] Binding DTO bindingHashCode() is inconsistent with augmentations</title>
                <link>https://jira.opendaylight.org/browse/MDSAL-667</link>
                <project id="10137" key="MDSAL">mdsal</project>
                    <description>&lt;p&gt;eOur implementation of bindingHashCode() is wrong as demonstrated (but not reported) in &lt;a href=&quot;https://jira.opendaylight.org/browse/OPNFLWPLUG-930&quot; title=&quot;Inconsistent flow IDs between flows in config and operational data stores&quot; class=&quot;issue-link&quot; data-issue-key=&quot;OPNFLWPLUG-930&quot;&gt;&lt;del&gt;OPNFLWPLUG-930&lt;/del&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our implementation treats augmentations attached to a particular object as a Map and performs:&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt; prime = 31;
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt; result = 1;
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;result = prime * result + obj.augmentations().hashCode();
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&lt;span class=&quot;code-keyword&quot;&gt;return&lt;/span&gt; result;&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This looks okay and works in most situations, but unfortunately it breaks down when equivalent augmentations are involved.&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;Equivalent augmentations come from the combination of our design choice, where we do not follow the effective YANG model, but rather a declared/effective hybrid. In this hybrid world, we generate interfaces for groupings and use composition of those to model &apos;uses foo&apos; inheritence. This leads to improved data mobility, as we have a common construct which is shared by all instantiations of a particular grouping. It also reduces the number of generated classes by a combinatoric factor.&lt;/p&gt;

&lt;p&gt;Unfortunately this does not play nicely with the concept of augmentations, as these operate on effective model, but has a tangled story when it comes to manifestations. One of the tangles is evident openflowplugin-extension-nicira-match.yang, where we are augmenting multiple (hopefully all) use sites of a grouping with the same content &#8211; effectively saying that the original grouping should have an extension, in this case should include &apos;all-matches-grouping&apos;:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt; &#160;&#160;&#160;augment &quot;/sal-flow:add-flow/sal-flow:input/sal-flow:match/ext-gen:extension-list/ext-gen:extension&quot; {
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;ext:augment-identifier &quot;nx-aug-match-rpc-add-flow&quot;;
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;uses all-matches-grouping;
 &#160;&#160;&#160;}

 &#160;&#160;&#160;augment &quot;/sal-flow:remove-flow/sal-flow:input/sal-flow:match/ext-gen:extension-list/ext-gen:extension&quot; {
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;ext:augment-identifier &quot;nx-aug-match-rpc-remove-flow&quot;;
 &#160;&#160;&#160;&#160;&#160;&#160;&#160;uses all-matches-grouping;
 &#160;&#160;&#160;}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With these we have a number of classes generated for the same augment, and since we are pointing to a grouping, their type indicates they are augmentations of the same construct (in the hybrid world) but they are distinct in effective world.&lt;/p&gt;

&lt;p&gt;This breaks down type safety, as these augments can be used interchangeably and can be transported all over the place via composition of the grouping.&lt;/p&gt;

&lt;p&gt;This, obviously, is not acceptable in YANG instantiated world, as represented via NormalizedNode structures &#8211; and therefore mdsal-binding-dom-codec has to deal with interpreting augmentations correctly. As a side-effect, incidental augmentation misuse morphs to the correct augmentation when we reconstruct a DTO from NormalizedNodes &#8211; and we have to deal with aliases in DataObjectCodecContext.mismatchedAugmentationByClass().&lt;/p&gt;

&lt;p&gt;We therefore cannot use the augment&apos;s class identity in either hashCode() nor equals() implementation, simply because if we happen to have a mismatched augmentation, storing the object and then reading it back will result in an object which does not hash (nor compare) as equal.&lt;/p&gt;

&lt;p&gt;Our hashing (and equality) contract must not short-circuit to Map.hashCode()/equals(), but rather treat the attached augmentations as a Set &#8211; for both hashCode() and equivalence purposes.&lt;/p&gt;</description>
                <environment></environment>
        <key id="34108">MDSAL-667</key>
            <summary>Binding DTO bindingHashCode() is inconsistent with augmentations</summary>
                <type id="10104" iconUrl="https://jira.opendaylight.org/secure/viewavatar?size=xsmall&amp;avatarId=10303&amp;avatarType=issuetype">Bug</type>
                                            <priority id="3" iconUrl="https://jira.opendaylight.org/images/icons/priorities/major.svg">Medium</priority>
                        <status id="10003" iconUrl="https://jira.opendaylight.org/images/icons/status_generic.gif" description="">Confirmed</status>
                    <statusCategory id="2" key="new" colorName="blue-gray"/>
                                    <resolution id="-1">Unresolved</resolution>
                                        <assignee username="-1">Unassigned</assignee>
                                    <reporter username="rovarga">Robert Varga</reporter>
                        <labels>
                            <label>pt</label>
                    </labels>
                <created>Tue, 15 Jun 2021 07:23:05 +0000</created>
                <updated>Wed, 1 Dec 2021 12:27:00 +0000</updated>
                                                                            <component>Binding codegen</component>
                        <due></due>
                            <votes>0</votes>
                                    <watches>1</watches>
                                                                                                                <comments>
                            <comment id="69304" author="rovarga" created="Tue, 15 Jun 2021 12:15:52 +0000"  >&lt;p&gt;There is a problem with implementing equality contract, though, as at least one of the participants in an foo.equals(bar) invocation must be able to translate the invocation. This is possible for binding-dom-codec, as it has the corresponding schema and class world view, but is problematic for generated code due to incomplete view of the world with split-compilation.&lt;/p&gt;

&lt;p&gt;One possible approach to solving this would be to explictly mark augmentation equivalence for this sort of use case with a yang-ext.yang extension, such as:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;extension augment-equivalent {
  argument augment-reference;
}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and the block above could be:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;prefix foo;
augment &quot;/sal-flow:add-flow/sal-flow:input/sal-flow:match/ext-gen:extension-list/ext-gen:extension&quot; {
  ext:augment-identifier &quot;nx-aug-match-rpc-add-flow&quot;;
  uses all-matches-grouping;
}
augment &quot;/sal-flow:remove-flow/sal-flow:input/sal-flow:match/ext-gen:extension-list/ext-gen:extension&quot; {
  ext:augment-equivalent &quot;nx-aug-match-rpc-add-flow&quot;;
  uses all-matches-grouping;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The cross-module use case is also supported with proper prefix handling, i.e. &quot;foo:nx-aug-match-rpc-add-flow&quot;. Augmentations tagged with augment-equivalent would not have a generated class, but rather would be checked at codegen (and runtime) for compatibility with the referenced augmentation (which must be tagged with augment-identifier, obviously) and be reused.&lt;/p&gt;

&lt;p&gt;This side-steps the problem by eliminating the secondary classes, not completely solving it.&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10000">
                    <name>Blocks</name>
                                                                <inwardlinks description="is blocked by">
                                        <issuelink>
            <issuekey id="34117">YANGTOOLS-1299</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="28198">OPNFLWPLUG-930</issuekey>
        </issuelink>
                            </outwardlinks>
                                                        </issuelinktype>
                    </issuelinks>
                <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                            <customfield id="customfield_11400" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|i03ycf:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                </customfields>
    </item>
</channel>
</rss>