All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrangé" <berrange@redhat.com>
To: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: libvir-list@redhat.com, "Ján Tomko" <jtomko@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] QMP; unsigned 64-bit ints; JSON standards compliance
Date: Mon, 13 May 2019 13:35:42 +0100	[thread overview]
Message-ID: <20190513123542.GJ15029@redhat.com> (raw)
In-Reply-To: <20190513122933.GC2786@work-vm>

On Mon, May 13, 2019 at 01:29:34PM +0100, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berrange@redhat.com) wrote:
> > On Wed, May 08, 2019 at 02:44:07PM +0200, Markus Armbruster wrote:
> > > Daniel P. Berrangé <berrange@redhat.com> writes:
> > > 
> > > > On Tue, May 07, 2019 at 10:47:06AM +0200, Markus Armbruster wrote:
> > > >
> > > >> >> > I can think of some options:
> > > >> >> > 
> > > >> >> >   1. Encode unsigned 64-bit integers as signed 64-bit integers.
> > > >> >> > 
> > > >> >> >      This follows the example that most C libraries map JSON ints
> > > >> >> >      to 'long long int'. This is still relying on undefined
> > > >> >> >      behaviour as apps don't need to support > 2^53-1.
> > > >> >> > 
> > > >> >> >      Apps would need to cast back to 'unsigned long long' for
> > > >> >> >      those QMP fields they know are supposed to be unsigned.
> > > >> 
> > > >> Ugly.  It's also what we did until v2.10, August 2017.  QMP's input
> > > >> direction still does it, for backward compatibility.
> > > >> 
> > > >> >> > 
> > > >> >> > 
> > > >> >> >   2. Encode all 64-bit integers as a pair of 32-bit integers.
> > > >> >> >     
> > > >> >> >      This is fully compliant with the JSON spec as each half
> > > >> >> >      is fully within the declared limits. App has to split or
> > > >> >> >      assemble the 2 pieces from/to a signed/unsigned 64-bit
> > > >> >> >      int as needed.
> > > >> 
> > > >> Differently ugly.
> > > >> 
> > > >> >> > 
> > > >> >> > 
> > > >> >> >   3. Encode all 64-bit integers as strings
> > > >> >> > 
> > > >> >> >      The application has todo all parsing/formatting client
> > > >> >> >      side.
> > > >> 
> > > >> Yet another ugly.
> > > >> 
> > > >> >> > 
> > > >> >> > 
> > > >> >> > None of these changes are backwards compatible, so I doubt we could make
> > > >> >> > the change transparently in QMP.  Instead we would have to have a
> > > >> >> > QMP greeting message capability where the client can request enablement
> > > >> >> > of the enhanced integer handling.
> > > >> 
> > > >> We might be able to do option 1 without capability negotiation.  v2.10's
> > > >> change from option 1 to what we have now produced zero complaints.
> > > >> 
> > > >> On the other hand, we made that change for a reason, so we may want a
> > > >> "send large integers as negative integers" capability regardless.
> > > >> 
> > > >> >> > 
> > > >> >> > Any of the three options above would likely work for libvirt, but I
> > > >> >> > would have a slight preference for either 2 or 3, so that we become
> > > >> >> > 100% standards compliant.
> > > >> 
> > > >> There's no such thing.  You mean "we maximize interoperability with
> > > >> common implementations of JSON".
> > > >
> > > > s/common/any/
> > > 
> > > info: error correction applied, future applications will be silent ;-P
> > > 
> > > >> Let's talk implementation for a bit.
> > > >> 
> > > >> Encoding and decoding integers in funny ways should be fairly easy in
> > > >> the QObject visitors.  The generated QMP marshallers all use them.
> > > >> Trouble is a few commands still bypass the generated marshallers, and
> > > >> mess with the QObject themselves:
> > > >> 
> > > >> * query-qmp-schema: minor hack explained in qmp_query_qmp_schema()'s
> > > >>   comment.  Should be harmless.
> > > >> 
> > > >> * netdev_add: not QAPIfied.  Eric's patches to QAPIfy it got stuck
> > > >>   because they reject some abuses like passing numbers and bools as
> > > >>   strings.
> > > >> 
> > > >> * device_add: not QAPIfied.  We're not sure QAPIfication is feasible.
> > > >> 
> > > >> netdev_add and device_add both use qemu_opts_from_qdict().  Perhaps we
> > > >> could hack that to mirror what the QObject visitor do.
> > > >> 
> > > >> Else, we might have to do it in the JSON parser.  Should be possible,
> > > >> but I'd rather not.
> > > >> 
> > > >> >> My preference would be 3 with the strings defined as being
> > > >> >> %x lower case hex formated with a 0x prefix and no longer than 18 characters
> > > >> >> ("0x" + 16 nybbles). Zero padding allowed but not required.
> > > >> >> It's readable and unambiguous when dealing with addresses; I don't want
> > > >> >> to have to start decoding (2) by hand when debugging.
> > > >> >
> > > >> > Yep, that's a good point about readability.
> > > >> 
> > > >> QMP sending all integers in decimal is inconvenient for some values,
> > > >> such as addresses.  QMP sending all (large) integers in hexadecimal
> > > >> would be inconvenient for other values.
> > > >> 
> > > >> Let's keep it simple & stupid.  If you want sophistication, JSON is the
> > > >> wrong choice.
> > > >> 
> > > >> 
> > > >> Option 1 feels simplest.
> > > >
> > > > But will still fail with any JSON impl that uses double precision floating
> > > > point for integers as it will loose precision.
> > > >
> > > >> Option 2 feels ugliest.  Less simple, more interoperable than option 1.
> > > >
> > > > If we assume any JSON impl can do 32-bit integers without loss of
> > > > precision, then I think we can say it is guaranteed portable, but
> > > > it is certainly horrible / ugly.
> > > >
> > > >> Option 3 is like option 2, just not quite as ugly.
> > > >
> > > > I think option 3 can be guaranteed to be loss-less with /any/ JSON impl
> > > > that exists, since you're delegating all string -> int conversion to
> > > > the application code taking the JSON parser/formatter out of the equation.
> > > 
> > > Double-checking: do you propose to encode *all* numbers as strings, or
> > > just certain "problematic" numbers?
> > > 
> > > If the latter, I guess your idea of "problematic" is "not representable
> > > exactly as double precision floating-point".
> > 
> > We have a few options
> > 
> >  1. Use string format for values > 2^53-1, int format below that
> >  2. Use string format for all fields which are 64-bit ints whether
> >     signed or unsigned
> >  3. Use string format for all fields which are integers, even 32-bit
> >     ones
> > 
> > I would probably suggest option 2. It would make the QEMU impl quite
> > easy IIUC, we we'd just change the QAPI visitor's impl for the int64
> > and uint64 fields to use string format (when the right capability is
> > negotiated by QMP).
> > 
> > I include 3 only for completeness - I don't think there's a hugely
> > compelling reason to mess with 32-bit ints.
> 
> What about when the size is architecture dependent?

The QAPI visitor for 'int' uses an 'int64_t' parameters, so I think
that will want to be string encoded, as if it was a 64-bit int, even
if built on a 32-bit platform.

> 
> > Option 1 is the bare minimum needed to ensure precision, but to me
> > it feels a bit dirty to say a given field will have different encoding
> > depending on the value. If apps need to deal with string encoding, they
> > might as well just use it for all values in a given field.
> 
> Yeh, 1 is horrid; it's too easy to miss a case which forgot to handle
>  the 2^53-1 because we hadn't forced a large value down that check.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


  reply	other threads:[~2019-05-13 12:37 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-30 13:19 [Qemu-devel] QMP; unsigned 64-bit ints; JSON standards compliance Daniel P. Berrangé
2019-04-30 13:19 ` Daniel P. Berrangé
2019-04-30 14:45 ` Dr. David Alan Gilbert
2019-04-30 14:45   ` Dr. David Alan Gilbert
2019-04-30 15:05   ` Daniel P. Berrangé
2019-04-30 15:05     ` Daniel P. Berrangé
2019-05-07  8:47     ` Markus Armbruster
2019-05-07  9:39       ` Daniel P. Berrangé
2019-05-07 16:32         ` Eric Blake
2019-05-08 12:37           ` Markus Armbruster
2019-05-08 12:44             ` Dr. David Alan Gilbert
2019-05-08 12:44         ` Markus Armbruster
2019-05-13 12:08           ` Daniel P. Berrangé
2019-05-13 12:29             ` Dr. David Alan Gilbert
2019-05-13 12:35               ` Daniel P. Berrangé [this message]
2019-05-13 14:10                 ` Markus Armbruster
2019-05-13 13:53             ` Markus Armbruster
2019-05-13 14:10               ` Daniel P. Berrangé
2019-05-13 15:15               ` [Qemu-devel] [libvirt] " Eric Blake
2019-05-14  6:02                 ` Markus Armbruster
2019-05-14  9:26                   ` Daniel P. Berrangé
2019-05-14  9:37                     ` Dr. David Alan Gilbert
2019-05-14  9:43                       ` Daniel P. Berrangé
2019-05-14  9:47                         ` Peter Krempa
2019-06-04  6:38 ` [Qemu-devel] " Markus Armbruster
2019-06-05 13:06   ` Daniel P. Berrangé

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=20190513123542.GJ15029@redhat.com \
    --to=berrange@redhat.com \
    --cc=armbru@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=jtomko@redhat.com \
    --cc=libvir-list@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.