On 09/03/22 18:30, Richard W.M. Jones wrote: > On Fri, Sep 02, 2022 at 05:14:24PM -0500, Eric Blake wrote: >> I was trying to write a test that determined whether a failure was due >> to a short-circuit test on the client side or an actual failure >> returned by the server. Such a test is a lot easier if we can watch >> status counters increase according to how much traffic goes over the >> wire. We may add more stats later (for example, how many bytes were >> written by nbd_[aio_]pread, or even how many times we had to grab the >> lock as part of an nbd_* command); or even to reset the counters for >> determining the protocol overhead around a particular set of I/O >> options, but this is a fun start. >> >> In this patch, update an example to serve as a compile time test of >> the new API; the next patch will add a runtime test of some simple >> uses while also checking the language bindings. >> --- >> docs/libnbd.pod | 20 ++++++++ >> generator/API.ml | 78 +++++++++++++++++++++++++++++- >> lib/handle.c | 28 +++++++++++ >> examples/strict-structured-reads.c | 13 ++++- >> 4 files changed, 135 insertions(+), 4 deletions(-) >> >> diff --git a/docs/libnbd.pod b/docs/libnbd.pod >> index 7a01179a..d256cd65 100644 >> --- a/docs/libnbd.pod >> +++ b/docs/libnbd.pod >> @@ -940,6 +940,26 @@ should return C<1> on all control paths, even when >> handling errors >> (note that with automatic retirement, assigning into C<error> is >> pointless as there is no later API to see that value). >> >> +=head1 STATISTICS COUNTERS >> + >> +Libnbd tracks several statistics counters, useful for tracking how >> +much traffic was sent over the connection. The counters track the >> +number of bytes sent and received, as well as the number of protocol >> +chunks (a group of bytes delineated by a magic number). >> + >> + printf ("bytes: sent=%" PRIu64 " received=%" PRIu64, >> + nbd_stats_bytes_sent (nbd), nbd_stats_bytes_received (nbd)); >> + printf ("chunks: sent=%" PRIu64 " received=%" PRIu64, >> + nbd_stats_chunks_sent (nbd), nbd_stats_chunks_received (nbd)); > > You probably also want to note that if TLS is enabled these don't > relate closely to either bytes or packets sent. > >> +Note that if a command fails early at the client without needing to >> +consult the server, the counters will not be incremented; conversely, >> +the chunk counts can increase by more than one for a single API call >> +(for example, L<nbd_opt_go(3)> defaults to sending a two-option >> +sequence of C<NBD_OPT_SET_META_CONTEXT> and C<NBD_OPT_GO>, and the >> +server in turn replies with multiple C<NBD_REP_INFO> before concluding >> +with C<NBD_REP_ACK>). > > The trouble is that by writing this down, we need to keep supporting > this. If you don't write it down, but it's implicit in our tests then > we can change the API later if it turns out to be hard to support. So > my preference would be to simply delete this paragraph and similar > below ...
We ought to be able to document the (originally) intended purpose of a feature such that it does not come with "support strings attached". Commit messages are good, code comments are good too, yes, but what about explicit documentation? E.g. "p2v-hacking.pod" is a great thing. Anyway I don't insist; I just thought (without realizing the "support strings attached") that exactly those paragraphs were the nicest touch ;) So either way: Acked-by: Laszlo Ersek <ler...@redhat.com> Laszlo > >> =head1 SIGNALS >> >> Libnbd does not install signal handlers. It attempts to disable >> diff --git a/generator/API.ml b/generator/API.ml >> index e4e2ea0a..dbfde284 100644 >> --- a/generator/API.ml >> +++ b/generator/API.ml >> @@ -307,6 +307,70 @@ "clear_debug_callback", { >> callback was associated this does nothing."; >> }; >> >> + "stats_bytes_sent", { >> + default_call with >> + args = []; ret = RUInt64; >> + may_set_error = false; >> + shortdesc = "statistics of bytes sent over socket so far"; >> + longdesc = "\ >> +Return the number of bytes that the client has sent to the server."; >> + see_also = [Link "stats_chunks_sent"; >> + Link "stats_bytes_received"; Link "stats_chunks_received"]; >> + }; >> + >> + "stats_chunks_sent", { >> + default_call with >> + args = []; ret = RUInt64; >> + may_set_error = false; >> + shortdesc = "statistics of chunks sent over socket so far"; >> + longdesc = "\ >> +Return the number of chunks that the client has sent to the >> +server, where a chunk is a group of bytes delineated by a magic >> +number that cannot be further subdivided without breaking the >> +protocol. >> + >> +This number increments when a request is sent to the server; >> +it is unchanged for an API that fails during initial client-side >> +sanity checking (see L<nbd_set_strict_mode(3)>), and can >> +increment by more than one for APIs that wrap multiple >> +underlying requests (such as L<nbd_opt_go(3)>)."; > > ^ This one. > >> + see_also = [Link "stats_bytes_sent"; >> + Link "stats_bytes_received"; Link "stats_chunks_received"; >> + Link "set_strict_mode"]; >> + }; >> + >> + "stats_bytes_received", { >> + default_call with >> + args = []; ret = RUInt64; >> + may_set_error = false; >> + shortdesc = "statistics of bytes received over socket so far"; >> + longdesc = "\ >> +Return the number of bytes that the client has received from the server."; >> + see_also = [Link "stats_chunks_received"; >> + Link "stats_bytes_sent"; Link "stats_chunks_sent"]; >> + }; >> + >> + "stats_chunks_received", { >> + default_call with >> + args = []; ret = RUInt64; >> + may_set_error = false; >> + shortdesc = "statistics of chunks received over socket so far"; >> + longdesc = "\ >> +Return the number of chunks that the client has received from the >> +server, where a chunk is a group of bytes delineated by a magic >> +number that cannot be further subdivided without breaking the >> +protocol. >> + >> +This number increments when a reply is received from the server; >> +it is unchanged for an API that fails during initial client-side >> +sanity checking (see L<nbd_set_strict_mode(3)>), and can >> +increment by more than one when the server utilizes structured >> +replies (see L<nbd_get_structured_replies_negotiated(3)>)."; > > ^ This one. > >> + see_also = [Link "stats_bytes_received"; >> + Link "stats_bytes_sent"; Link "stats_chunks_sent"; >> + Link "get_structured_replies_negotiated"]; >> + }; >> + >> "set_handle_name", { >> default_call with >> args = [ String "handle_name" ]; ret = RErr; >> @@ -945,8 +1009,14 @@ "set_strict_mode", { >> such, when attempting to relax only one specific bit while keeping >> remaining checks at the client side, it is wiser to first call >> L<nbd_get_strict_mode(3)> and modify that value, rather than >> -blindly setting a constant value."; >> - see_also = [Link "get_strict_mode"; Link "set_handshake_flags"]; >> +blindly setting a constant value. >> + >> +When commands are not being attempted in parallel, it is possible >> +to observe whether a given command was filtered at the client >> +or triggered a server response by whether the statistics >> +counters increase (such as L<nbd_stats_bytes_sent(3)>)."; > > ^ This one. > >> + see_also = [Link "get_strict_mode"; Link "set_handshake_flags"; >> + Link "stats_bytes_sent"; Link "stats_bytes_received"]; >> }; >> >> "get_strict_mode", { >> @@ -3274,6 +3344,10 @@ let first_version = >> (* Added in 1.15.x development cycle, will be stable and supported in >> 1.16. *) >> "poll2", (1, 16); >> "supports_vsock", (1, 16); >> + "stats_bytes_sent", (1, 16); >> + "stats_chunks_sent", (1, 16); >> + "stats_bytes_received", (1, 16); >> + "stats_chunks_received", (1, 16); >> >> (* These calls are proposed for a future version of libnbd, but >> * have not been added to any released version so far. >> diff --git a/lib/handle.c b/lib/handle.c >> index 7fcdc8cd..d4426260 100644 >> --- a/lib/handle.c >> +++ b/lib/handle.c >> @@ -548,3 +548,31 @@ nbd_unlocked_set_uri_allow_local_file (struct >> nbd_handle *h, bool allow) >> h->uri_allow_local_file = allow; >> return 0; >> } >> + >> +/* NB: may_set_error = false. */ >> +uint64_t >> +nbd_unlocked_stats_bytes_sent (struct nbd_handle *h) >> +{ >> + return h->bytes_sent; >> +} >> + >> +/* NB: may_set_error = false. */ >> +uint64_t >> +nbd_unlocked_stats_chunks_sent (struct nbd_handle *h) >> +{ >> + return h->chunks_sent; >> +} >> + >> +/* NB: may_set_error = false. */ >> +uint64_t >> +nbd_unlocked_stats_bytes_received (struct nbd_handle *h) >> +{ >> + return h->bytes_received; >> +} >> + >> +/* NB: may_set_error = false. */ >> +uint64_t >> +nbd_unlocked_stats_chunks_received (struct nbd_handle *h) >> +{ >> + return h->chunks_received; >> +} >> diff --git a/examples/strict-structured-reads.c >> b/examples/strict-structured-reads.c >> index 6ea17006..b56a4825 100644 >> --- a/examples/strict-structured-reads.c >> +++ b/examples/strict-structured-reads.c >> @@ -4,6 +4,10 @@ >> * qemu-nbd -f $format -k $sock -r image >> * ./strict-structured-reads $sock >> * >> + * With nbdkit (but less useful until nbdkit learns to send holes): >> + * >> + * nbdkit -U- sparse-random 1G --run './strict-structured-reads >> "$unixsocket"' >> + * > > Is this hunk meant to be included? > >> * This will perform read randomly over the image and check that all >> * structured replies comply with the NBD spec (chunks may be out of >> * order or interleaved, but no read succeeds unless chunks cover the >> @@ -257,8 +261,11 @@ main (int argc, char *argv[]) >> exit (EXIT_FAILURE); >> } >> >> - nbd_close (nbd); >> - >> + printf ("traffic:\n"); >> + printf (" bytes sent: %10" PRIu64 "\n", nbd_stats_bytes_sent (nbd)); >> + printf (" bytes received: %10" PRIu64 "\n", nbd_stats_bytes_received >> (nbd)); >> + printf (" chunks sent: %10" PRIu64 "\n", nbd_stats_chunks_sent (nbd)); >> + printf (" chunks received: %10" PRIu64 "\n", nbd_stats_chunks_received >> (nbd)); >> printf ("totals:\n"); >> printf (" data chunks: %10d\n", total_data_chunks); >> printf (" data bytes: %10" PRId64 "\n", total_data_bytes); >> @@ -270,5 +277,7 @@ main (int argc, char *argv[]) >> printf (" bytes read: %10" PRId64 "\n", total_bytes); >> printf (" compliant: %10d\n", total_success); >> >> + nbd_close (nbd); >> + >> exit (EXIT_SUCCESS); >> } >> -- > > Rich. > _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs