From: Anthony Liguori <anthony@codemonkey.ws>
To: Michael Roth <mdroth@linux.vnet.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Eric Blake <eblake@redhat.com>,
qemu-devel@nongnu.org, Luiz Capitulino <lcapitulino@redhat.com>
Subject: Re: [Qemu-devel] [RFC/RFA PATCH] qapi: detect extra members inside structs
Date: Mon, 19 Mar 2012 19:49:46 -0500 [thread overview]
Message-ID: <4F67D42A.8080400@codemonkey.ws> (raw)
In-Reply-To: <20120319234559.GB2994@illuin>
On 03/19/2012 06:45 PM, Michael Roth wrote:
>>> So IMO, returning arguments actually seems easier for both clients and the
>>> server, and is more resilient to downstream changes. It does require a more
>>> formal specification of the protocol though. Basically: "an option/field
>>> may not be supported in older/future versions of QEMU, so it is up to
>>> the client to check in advance by referencing the QAPI schema for their
>>> qemu version or programatically via get_schema(<command>)"
>>
>> The complexity of writing a client using get_schema() is close to staggering :-/
>
> I'm not sure, I mean, take libvirt, you need to marshall up the
> arguments anyway and put them into a QMP payload, so in that case the
> client developer is aware of the schema that they're coding against,
> and also understand the QAPI schema specification, and if the schema
> is nested then so is the client version of that "schema".
>
> So, conceptually at least, it seems like it wouldn't be that big a jump
> to maintain an internal representation of their schema to
> programatically check against the specification they were coding
> against, it's just the part where they then need to bake it into the
> client implementation that's a bit heavy-handed.
So let's work through a few examples. Today, you have to maintain a list of
commands returned from query-commands and check for set membership:
if 'query-netdev2' in commands:
qmp.query_netdev2(foo)
else:
qmp.query_netdev()
Pretty simple. If we have a schema representation, we'll need to be able to
check for arguments. That means we need a way to check if a command has an
argument. We could do this as nested lists:
if (commands.has_key('query-netdev') and
commands['query-netdev']['args'].has_key('interface')):
qmp.query_netdev(foo)
else:
qmp.query_netdev()
This is only really possible in a dynamically typed language, which sucks, but
let's ignore that for now. This is a bit more complicated but unfortunately,
it's not enough.
Because we can add members to structures and structures can be arguments. So we
really need a way to say:
1) Do we have the query-netdev command
2) Does it take a parameter called interface of type NetDevArgument
3) Does the NetDevArgument have a member called 'foo'.
But this actually can be arbitrarily deep in terms of complex. Maybe you make a
simple query language so you can execute schema queries in a single line.
So you have an interface definition that is the schema that describes an
unstructured wire protocol and a query language to determine when and how the
schema changes. If that doesn't ring a bell to you, congratulations, you've
invented SOAP.
The interface description in SOAP is WSDL and XPath is the query language.
Writing a SOAP client is a train wreck. It's so bad that even in dynamic
languages, people almost always use code generators.
A good RPC makes the client simple. If that means we need to take care when
introducing new interfaces, then it's a small price to pay for avoiding the
nightmares of an over engineered RPC like SOAP.
Regards,
Anthony Liguori
> Thinking about it more the, this does seem to be completely at odds with
> any future prospects of a libqmp, so that's a pretty big trade-off...
>
>>
>> Regards,
>>
>> Anthony Liguori
>>
>>>>
>>>
>>
next prev parent reply other threads:[~2012-03-20 0:49 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-19 19:29 [Qemu-devel] [RFC/RFA PATCH] qapi: detect extra members inside structs Paolo Bonzini
2012-03-19 19:34 ` Anthony Liguori
2012-03-19 19:51 ` Paolo Bonzini
2012-03-19 19:56 ` Anthony Liguori
2012-03-19 20:22 ` Eric Blake
2012-03-19 20:30 ` Anthony Liguori
2012-03-19 20:43 ` Luiz Capitulino
2012-03-19 22:29 ` Michael Roth
2012-03-19 22:38 ` Anthony Liguori
2012-03-19 23:45 ` Michael Roth
2012-03-20 0:49 ` Anthony Liguori [this message]
2012-03-20 12:15 ` Luiz Capitulino
2012-03-20 19:33 ` Anthony Liguori
2012-03-20 17:31 ` Paolo Bonzini
2012-03-20 0:28 ` Michael Roth
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=4F67D42A.8080400@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=eblake@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=pbonzini@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.