On Sat, Sep 05, 2020 at 08:40:57PM -0500, Eric Blake wrote:
Natural fallout after my recent testsuite additions that fixed a
couple of ocaml bugs in the setters. However, on at least the OCaml
code, I'm not sure what we should do if a newer libnbd ever returns a
bit that an older NBD.mli was not expecting at the time the OCaml
compiler ran (see below). I'm also not sure if there is a more
efficient way to avoid outputting Val_FOO() converters for types not
referenced in REnum/RFlags than my hack of __attribute__((unused)).
Hence I'll wait for a review on these.
Now, for the future compatibility lesson, promised above.
nbd_get_handshake_flags is documented as potentially returning
additional bits from a newer libnbd than what the current client code
was compiled against. How? Let's say a future NBD protocol addition
adds LIBNBD_HANDSHAKE_FLAG_64BIT (as that one might actually be a way
that we implement 64-bit requests...). Presumably, once the NBD
protocol defines it and future libnbd implements it, then future
libnbd will default to setting that bit during nbd_create(). An older
C client that did:
flags = nbd_get_handshake_flags (nbd) & ~LIBNBD_HANDSHAKE_FLAG_NO_ZEROES;
nbd_set_handshake_flags (nbd, flags);
will still run (even though flags contains a bit that was not known at
the time the C app was compiled, the libnbd call that checks that all
input bits are known is from the newer libnbd that recognizes
LIBNBD_HANDSHAKE_FLAG_64BIT as valid). But an OCaml client compiled
against the older interface has no OCaml value to represent the new
bit from the getter, nor any way to specify that new bit to the setter
that is expecting a list of only the old variant type. Maybe we want
the generator to produce a full list of 31 variants per 'flags' type,
using placeholders for all bits not currently in use, to make it
easier to receive an unknown bit from the getter and turn around to
re-supply it to the setter? In such a setup, libnbd would still be
rejecting input of out-of-range bits in relation to what libnbd knew
at its compilation time.
While placeholders could be used, a more natural way is to extend the
flags type (in OCaml) to:
type t =
| FIXED_NEWSTYLE
| NO_ZEROES
| UNKNOWN_FLAG of int
where the unknown (at the time of compilation) flags would be
encoded as UNKNOWN_FLAG + the bit index of the unknown flag. eg:
[ FIXED_NEWSTYLE; UNKNOWN_FLAG 2 ] => 1 | (1<<2)
(1<<3) | 2 => [ UNKNOWN_FLAG 3; NO_ZEROES ]
Even though we distribute the OCaml bindings with libnbd it's
conceivable this could be useful because OCaml bindings are generally
statically linked into the final binary so you could get a newer
libnbd.so.0 / old binary with old OCaml bindings scenario.
Rich.
Eric Blake (3):
generator: Introduce REnum/RFlags return types
golang: Typesafe returns for REnum/RFlags
ocaml: Typesafe returns for REnum/RFlags
generator/API.ml | 16 ++++--
generator/API.mli | 2 +
generator/C.ml | 20 ++++---
generator/GoLang.ml | 13 ++++-
generator/OCaml.ml | 55 +++++++++++++++++++
generator/Python.ml | 2 +
ocaml/tests/test_110_defaults.ml | 5 +-
ocaml/tests/test_120_set_non_defaults.ml | 4 +-
.../libnbd/libnbd_110_defaults_test.go | 6 +-
.../libnbd_120_set_non_defaults_test.go | 2 +-
10 files changed, 102 insertions(+), 23 deletions(-)
--
2.28.0
_______________________________________________
Libguestfs mailing list
Libguestfs(a)redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top