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 <[email protected]>
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
[email protected]
https://listman.redhat.com/mailman/listinfo/libguestfs