All of lore.kernel.org
 help / color / mirror / Atom feed
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
>>
>>>>
>>>
>>

  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.