[ 
https://issues.apache.org/jira/browse/AVRO-1474?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13981471#comment-13981471
 ] 

Ramana Suvarapu commented on AVRO-1474:
---------------------------------------

Please see the email below for more details and attached is the patch to fix 
this issue.



From: Suvarapu, Venkata - GMRT-GET 
Sent: Friday, April 25, 2014 9:52 AM
To: 'Thiruvalluvan MG'
Cc: 'Srinidhi S'
Subject: RE: Resolving decoder bug's fix

Hi Thiru,

Just to make it clear that ResolvingGrammarGenerator::getWriterProduction 
function doesn’t work with Schemas with Symbollic nodes. Because Production to 
actual node of Symbollic node is not going to be available in the 
node->production map created within getWriterProduction() method. If Schema 
contains nested schema for its child nodes then the function works.

Thanks,
Ramana

From: Suvarapu, Venkata - GMRT-GET 
Sent: Thursday, April 24, 2014 7:42 PM
To: 'Thiruvalluvan MG'
Cc: 'Srinidhi S'; Ye, Xiaolu - GMRT-EST
Subject: RE: Resolving decoder bug's fix

Hi Thiru,

I debugged the code and found the root cause for the issue. I suspect that 
ProductionPtr ResolvingGrammarGenerator::getWriterProduction method has a bug.
Let’s say writer record schema has following additional and reader schema 
doesn’t have this field.  

{
                                                "name": "optionalNestedrecord",
                                                "type": ["null", "Nested"],
                                                "default": null

                                }
When resolving the Writer and Readers record fields, Since this field is not 
there in reader schema, ResolveRecords does skip the Production of this node 
and ProductionPtr for this field will be retrieved by calling 
getWriterProduction(). 

ProductionPtr ResolvingGrammarGenerator::getWriterProduction(
    const NodePtr& n, const map<NodePtr, ProductionPtr>& m2)
{
    const NodePtr& nn = (n->type() == AVRO_SYMBOLIC) ?
        static_cast<const NodeSymbolic& >(*n).getNode() : n;         
    map<NodePtr, ProductionPtr>::const_iterator it2 = m2.find(nn);
                return (it2 != m2.end()) ? it2->second :
                                ValidatingGrammarGenerator::generate(nn);
}

In the above code, when nn is not found in m2, it calls 
ValidatingGrammarGenerator::generate(nn) to generate the ProductionPtr and this 
function uses new node->production map instead of m2 which is already processed 
during the first pass.

I think this is not correct. We should call ProductionPtr result = 
ValidatingGrammarGenerator::doGenerate(nn, m2) to generate the ProductionPtr.

The reason for this is that in my above example schema, optionalNestedrecord is 
union schema and since it doesn’t exists in m2, it generates the new production 
using new node->production map. Since “Nested” node is not going to be 
available in new map, it will generates  null production. Later point of time, 
this is causing 
boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr>
 > at memory location 0x00b5d3b0 exception during the performing skip operation 
when decoding the record using reader schema. But If m2 is used , “Nested” node 
is guaranteed to  be available in m2 and that value is used instead of null or 
empty production.

Modified function
ProductionPtr ResolvingGrammarGenerator::getWriterProduction(
    const NodePtr& n, map<NodePtr, ProductionPtr>& m2)
{
    const NodePtr& nn = (n->type() == AVRO_SYMBOLIC) ?
        static_cast<const NodeSymbolic& >(*n).getNode() : n;  

       map<NodePtr, ProductionPtr>::const_iterator it2 = m2.find(nn);
       if (it2 != m2.end())
              return it2->second;
       else
       {
              ProductionPtr result = ValidatingGrammarGenerator::doGenerate(nn, 
m2);
              fixup(result, m2);
              return result;       
       }

       
}


I tested the fix locally and it seems to be working.  But I had to modify 
qualifiers of arguments of few functions in the code to make it compile. 
Attached is the patch for this fix and please review it and see it makes sense.

Thanks,
Ramana

From: Suvarapu, Venkata - GMRT-GET 
Sent: Wednesday, April 23, 2014 11:57 PM
To: Thiruvalluvan MG
Cc: 'Srinidhi S'; Ye, Xiaolu - GMRT-EST
Subject: RE: Resolving decoder bug

Hi Thiru,

Attached are writer and reader schema. In writer schema I added new field 
“optionalNestedrecord”
to RootRecord which is optional and default value is null.  This field doesn’t 
exist in Reader schema.

{
                                                "name": "optionalNestedrecord",
                                                "type": ["null", "Nested"],
                                                "default": null

                                }

When I populate this field in writers RootRecord and when I tried to 
deserialize using reader schema, It’s throwing following exception.

boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr>
 > at memory location 0x00b5d3b0..

This exception is thrown in the following section of void skip(Decoder& d) of 
Symbol.hh 

case Symbol::sSymbolic:
{
                    ProductionPtr pp(
                        t.extra<boost::weak_ptr<Production> >());
                    parsingStack.pop();
                    append(pp);
}

Steps to reproduce:
1.      Use the attached files to regenerate bigrecord types for both reader 
and writer
2.      In writer RootRecord, populate  optionalNestedrecord  and encode it
3.      Using ResolvingDecoder and using reader schema, try to deserialize 
encoded writer’s record and you will see this exception.

I attached theses schema to AVRO-1474 jira. 
Please take a look into this. 

Thanks,
Ramana

On Wed, Apr 23, 2014 at 7:41 PM, Srinidhi S <[email protected]> wrote:
Hi Thiru

I found a bug with latest patch.  Here is the scenario.

writer record schema has optional field which is defined as union [null, 
another record] and here "another record" is defined as Symbolic to schema 
instead of actual definition of full record schema.

If reader schema doesn't have this field and writer populates this field and 
try to decode writer's record using reader schema it's throwing boost::bad_ptr 
exception. The exception is thrown from symbol class where it's trying to 
extract extra info from Production for Symbollic.


I have a test case to reproduce this issue and I will send it in my next email.

Thanks
Venkat







> C++ resolvind decoder doesn't work when reader schema has more fields than 
> writer schema
> ----------------------------------------------------------------------------------------
>
>                 Key: AVRO-1474
>                 URL: https://issues.apache.org/jira/browse/AVRO-1474
>             Project: Avro
>          Issue Type: Bug
>          Components: c++
>    Affects Versions: 1.7.6
>            Reporter: Ramana Suvarapu
>            Assignee: Thiruvalluvan M. G.
>         Attachments: AVRO-1474.patch, bigrecord, bigrecord_r, reader, writer
>
>
> When reader schema has more number of fields than writer schema, C++ 
> implementation of resolving decoder is throwing exception "throwing exception 
> "Don't know how to handle excess fields for reader.” with out checking 
> whether fields are optional or fields have default values.
> Attached are reader and writer schemas. Record in reader schema has 2 
> additional fields than writer schema. One field is required field but it has 
> default value and another one is optional field (union of null and string). 
> Since one has default value and another is optional both reader and writer 
> schemas are supposed to be compatible. 
>  
> {"name": "defaultField", "type": "string", "default": "DEFAULT", 
> "declared":"true"},     
> {"name": "optionalField", "type": ["string", "null"],"declared":"true"},
>  
> main()
> {
>   avro::ValidSchema readerSchema = load("reader.json");
>   avro::ValidSchema writerSchema = load("writer.json");
>   avro::DecoderPtr d = avro::resolvingDecoder(writerSchema, 
> readerSchema,avro::binaryDecoder());
> }
>  
> But when I tried to create resolving decoder, I am getting "Don't know how to 
> handle excess fields for reader.” But Java implementation works.  
> Also field ordering is not working. 
> The same issue is reported in AVRO-1360.



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to