Hi

On Wed, Sep 30, 2020 at 11:34 AM Markus Armbruster <arm...@redhat.com>
wrote:

> Marc-André Lureau <marcandre.lur...@gmail.com> writes:
>
> > Hi
> >
> > On Tue, Sep 29, 2020 at 3:01 PM Paolo Bonzini <pbonz...@redhat.com>
> wrote:
> [...]
> >> Marc-André, we are totally in agreement about that!  The problem is that
> >> you have already decided what the solution looks like, and that's what
> >> I'm not sure about because your solution also implies completely
> >> revisiting the schema.
> >>
> >
> > Did I? Which schema change are you (or I) implying? Versioning the
> > interface? It's necessary at the client level, unless everything is
> > dynamic, after introspection, which makes automated static bindings
> > impractical.
>
> I disagree with "necessary".
>
> A client can use a specific version of QMP, and still talk to a server
> with a different version, because we designed that capability into QMP.
>

 "A client can use a specific version of QMP" == versioning on the client
side

>
> You absolutely can create bindings for a specific version of QMP for the
> client if you want.  Just make sure the client as a whole obeys the
> rules of the QMP game laid down in qmp-spec.txt and qapi-code-gen.txt.
>
> >> I say there are many candidates (the ones I know are Protobuf and
> >> Flexbuffers) for serialization and many candidates for transport (REST
> >> and gRPC to begin with) in addition to the two {QMP,JSON} and
> >> {DBus,DBus} tuples.  We should at least look at how they do code
> >> generation before deciding that JSON is bad and DBus is good.
> >>
> >
> > Contrary to what you believe I am not focusing so much on DBus here :) It
> > took about 200 loc to bind it, effortlessly (compared to sys<->rs
> > conversion). All it does is to expose the same API we have in the
> generated
> > C somehow (similar static types & functions - not all as a{sv} opaque
> > dictionaries).
>
> Two points.
>
> 1. Opaque dictionaries are far from the only way to do keyword arguments
> in a language that lacks them.
>

Oh one can always be creative. The point is trying to stay idiomatic in the
target language.


>
> 2. The API we generate for C is not exactly wonderful.
>
> Behold this beauty:
>
>     void qmp_block_commit(bool has_job_id, const char *job_id, const char
> *device, bool has_base_node, const char *base_node, bool has_base, const
> char *base, bool has_top_node, const char *top_node, bool has_top, const
> char *top, bool has_backing_file, const char *backing_file, bool has_speed,
> int64_t speed, bool has_on_error, BlockdevOnError on_error, bool
> has_filter_node_name, const char *filter_node_name, bool has_auto_finalize,
> bool auto_finalize, bool has_auto_dismiss, bool auto_dismiss, Error **errp);
>
> It's gotten so bad we added a second way to do the C API:
>
>     void qmp_drive_backup(DriveBackup *arg, Error **errp);
>
> Turns out
>
>     DriveBackup arg = {
>         ... initialize the optionals you need ...
>     }
>     qmp_drive_backup(&arg, &err);
>
> is a lot easier on the eyes than passing 29 positional arguments.
>
>
So is writing the function arguments with indentation. Then I don't see
much difference between a long list of arguments in a struct and that
function. The main difference is that you make it easy to pass those
arguments down. But often, you want to pass a subset, you don't want to
pass the whole context as it may lead to bad design / bugs.

This could be viewed as a work-around for C's lack of positional
> parameters.
>
>
Or a badly designed QMP command.

Even more fun:
>
>     void qmp_blockdev_add(BlockdevOptions *arg, Error **errp);
>
> BlockdevOptions is a tagged union.
>
> This could be viewed as a work-around for C's lack of function
> overloading.
>
>
Or a badly designed QMP command ?

> It's easy for QEMU to generate a good static binding for C, because the
> > version always matches. For a client, you wouldn't be able to write a
> > similar idiomatic API in C, Rust, Python or Go, unfortunately.
>
> I disagree.  You won't be able to write good bindings using just
> positional parameters.  Not even if you add restrictions on how we can
> evolve QMP.  And no, I do not consider the C bindings we create for QEMU
> itself "good".  They're the best we could do, and good enough.
>
>
Sure they could be better, they are still quite idiomatic for C.

When you do bindings for another language, do bindings for that
> language, not C bindings in that language.
>
>
Yes

Regardless of bindings, the client as a whole should obey the rules of
> the QMP game laid down in qmp-spec.txt and qapi-code-gen.txt.  If these
> rules have become counter-productive, then it's time to replace QMP
> wholesale.
>
> Do not attempt to force a square peg into a round hole.  If we must have
> square pegs, design a square hole, and retire the round hole.
>
>
Hmm? I am trying to make the hole a bit more regular...

> Iow, I am not trying to sell DBus, I would like to make it easier to bind
> > QMP in general. (although I do believe that DBus is a better protocol
> than
> > QMP for local IPC, yes. And gRPC is probably better for remoting)
> >
> >> I would rather make those problems solved at the server level, that
> >> > doesn't require any change to QMP today, just a more careful
> >> > consideration when making changes (and probably some tools to help
> >> > enforce some stability).
> >>
> >> Problem is, "more careful consideration when making changes" is not a
> >> small thing.  And other RPCs have evolved in a completely different
> >> space (REST APIs for web services) that have chosen the same tradeoffs
> >> as QMP, so why should we not learn from them?
> >>
> >>
> > I don't buy that generalization. A very recent protocol in this space,
> that
> > aims to be a good low-level RPC on Linux (for containers, cloud etc) is
> > varlink. (In many ways, we could compare it to QMP, but it lacks some
> > important features, like events)
> >
> > varlink does non-optional members and versioning the same way I propose
> > here, for what I could tell. Although they use JSON, and have similar
> > transport "benefits", this basic rule allow them to have very decent
> > automated binding in various languages, without resorting to unorthodox
> > solutions, ex:
> > https://github.com/varlink/rust/blob/master/examples/example/src/main.rs
>
> Paolo pointed out successful protocols that make tradeoffs similar to
> QMP to support the idea that these tradeoffs can make sense and are
> workable.
>
> Pointing out other, dissimilar protocols is not a convincing
> counter-argument :)
>

It's relevant. Did you study varlink a bit? It's so close to QMP, you will
find it hard to point out real dissimilarities.


-- 
Marc-André Lureau

Reply via email to