qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: jsnow@redhat.com, qemu-devel@nongnu.org
Subject: Re: [PATCH v2 4/6] qapi: Apply aliases in qobject-input-visitor
Date: Thu, 18 Feb 2021 17:10:07 +0100	[thread overview]
Message-ID: <20210218161007.GA10998@merkur.fritz.box> (raw)
In-Reply-To: <87o8ghebrb.fsf@dusky.pond.sub.org>

Am 18.02.2021 um 14:39 hat Markus Armbruster geschrieben:
> Kevin Wolf <kwolf@redhat.com> writes:
> 
> > Am 17.02.2021 um 16:32 hat Markus Armbruster geschrieben:
> >> Kevin Wolf <kwolf@redhat.com> writes:
> >> 
> >> > When looking for an object in a struct in the external representation,
> >> > check not only the currently visited struct, but also whether an alias
> >> > in the current StackObject matches and try to fetch the value from the
> >> > alias then. Providing two values for the same object through different
> >> > aliases is an error.
> >> >
> >> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> >> 
> >> Looking just at qobject_input_try_get_object() for now.
> >
> > :-(
> >
> > This patch doesn't even feel that complicated to me.
> 
> I suspect it's just me having an unusually obtuse week.
> 
> The code is straightforward enough.  What I'm missing is a bit of "how
> does this accomplish the goal" and "why is this safe" here and there.
> 
> > Old: Get the value from the QDict of the current StackObject with the
> > given name.
> >
> > New: First do alias resolution (with find_object_member), which results
> > in a StackObject and a name, and that's the QDict and key where you get
> > the value from.
> 
> This part I understand.
> 
> We simultaneously walk the QAPI type and the input QObject, consuming
> input as we go.
> 
> Whenever the walk leaves a QAPI object type, we check the corresponding
> QObject has been consumed completely.
> 
> With aliases, we additionally look for input in a certain enclosing
> input object (i.e. up the recursion stack).  If found, consume.
> 
> > Minor complication: Aliases can refer to members of nested objects that
> > may not be provided in the input. But we want these to work.
> >
> > For example, my chardev series defines aliases to flatten
> > SocketAddressLegacy (old syntax, I haven't rebased it yet):
> >
> > { 'union': 'SocketAddressLegacy',
> >   'data': {
> >     'inet': 'InetSocketAddress',
> >     'unix': 'UnixSocketAddress',
> >     'vsock': 'VsockSocketAddress',
> >     'fd': 'String' },
> >   'aliases': [
> >     {'source': ['data']},
> >     {'alias': 'fd', 'source': ['data', 'str']}
> >   ]}
> >
> > Of course, the idea is that this input should work:
> >
> > { 'type': 'inet', 'hostname': 'localhost', 'port': '1234' }
> >
> > However, without implicit objects, parsing 'data' fails because it
> > expects an object, but none is given (we specified all of its members on
> > the top level through aliases). What we would have to give is:
> >
> > { 'type': 'inet', 'hostname': 'localhost', 'port': '1234', 'data': {} }
> >
> > And _that_ would work. Visiting 'data' succeeds because we now have the
> > object that the visitor expects, and when visiting its members, the
> > aliases fill in all of the mandatory values.
> >
> > So what this patch does is to implicitly assume the 'data': {} instead
> > of erroring out when we know that aliases exist that can still provide
> > values for the content of 'data'.
> 
> Aliases exist than can still provide, but will they?  What if input is
> 
>     {"type": "inet"}
> 
> ?
> 
> Your explanation makes me guess this is equivalent to
> 
>     {"type": "inet", "data": {}}
> 
> which fails the visit, because mandatory members of "data" are missing.
> Fine.

Okay, if you want the gory details, then the answer is yes for this
case, but it depends.

If we're aliasing a single member, then we can easily check whether the
alias is actually specified. If it's not in the input, no implicit
object.

But in our example, it is a wildcard alias and we don't know yet which
aliases it will use. This depends on what the visitor for the implicit
object will do (future tense).

> If we make the members optional, it succeeds: qobject_input_optional()
> checks both the regular and the aliased input, finds neither, and
> returns false.  Still fine.
> 
> What if "data" is optional, too?  Hmmm...

Yes, don't use optional objects in the middle of the path of a wildcard
alias unless there is no semantic difference between empty object and
absent object. This is documented in the code, but it might actually
still be missing from qapi-code-gen.txt.

> Example:
> 
>     { 'struct': 'Outer',
>       'data': { '*inner': 'Inner' },
> 
>     { 'struct': 'Inner',
>       'data': { '*true-name': 'str' } }
> 
> For input {}, we get an Outer object with
> 
>     .has_inner = false,
>     .inner = NULL
> 
> Now add
> 
>       'aliases': [ { 'name': 'alias-name',
>                      'source': [ 'inner', 'true-name' ] } ] }
> 
> What do we get now?  Is it
> 
>      .has_inner = true,
>      .inner = { .has_true_name = false,
>                 .true_name = NULL }
> 
> perhaps?

I think this is the result you would get if you had used a wildcard
alias. But since you used a single-member alias, we would see that
'alias-name' is not in the input and actually still return the original
result:

    .has_inner = false,
    .inner = NULL

Kevin



  reply	other threads:[~2021-02-18 16:11 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-11 18:31 [PATCH v2 0/6] qapi: Add support for aliases Kevin Wolf
2021-02-11 18:31 ` [PATCH v2 1/6] qapi: Add interfaces for alias support to Visitor Kevin Wolf
2021-02-16 11:56   ` Markus Armbruster
2021-02-11 18:31 ` [PATCH v2 2/6] qapi: Remember alias definitions in qobject-input-visitor Kevin Wolf
2021-02-16 12:06   ` Markus Armbruster
2021-02-11 18:31 ` [PATCH v2 3/6] qapi: Simplify full_name_nth() " Kevin Wolf
2021-02-16 12:22   ` Markus Armbruster
2021-02-11 18:31 ` [PATCH v2 4/6] qapi: Apply aliases " Kevin Wolf
2021-02-17 15:32   ` Markus Armbruster
2021-02-17 17:50     ` Kevin Wolf
2021-02-18 13:39       ` Markus Armbruster
2021-02-18 16:10         ` Kevin Wolf [this message]
2021-02-19  9:11           ` Markus Armbruster
2021-02-19 13:07             ` Markus Armbruster
2021-02-19 14:42   ` Markus Armbruster
2021-02-24  8:28   ` Markus Armbruster
2021-02-11 18:31 ` [PATCH v2 5/6] qapi: Add support for aliases Kevin Wolf
2021-02-16 15:43   ` Markus Armbruster
2021-02-17 15:23   ` Markus Armbruster
2021-02-17 16:17     ` Kevin Wolf
2021-02-18 10:26       ` Markus Armbruster
2021-02-11 18:31 ` [PATCH v2 6/6] tests/qapi-schema: Test cases " Kevin Wolf
2021-02-16 15:14   ` Markus Armbruster
2021-02-16 15:31     ` Kevin Wolf
2021-02-16 16:14       ` Markus Armbruster
2021-02-17 12:23         ` Markus Armbruster
2021-02-24  8:45 ` [PATCH v2 0/6] qapi: Add support " Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210218161007.GA10998@merkur.fritz.box \
    --to=kwolf@redhat.com \
    --cc=armbru@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).