I was wondering why this never made it to the list - seems I just sent
it to Michal... So here's what I sent...
John
On 05/16/2017 05:34 PM, John Ferlan wrote:
On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This is just a wrapper over new functions that have been just
> introduced: virStreamRecvFlags(), virStreamRecvHole(). It's very
> similar to virStreamRecvAll() except it handles sparse streams
> well.
>
> Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
> ---
> include/libvirt/libvirt-stream.h | 33 ++++++++++-
> src/libvirt-stream.c | 123 +++++++++++++++++++++++++++++++++++++++
> src/libvirt_public.syms | 1 +
> 3 files changed, 154 insertions(+), 3 deletions(-)
>
[...]
> diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
> index bedb6159a..6bf4c4f29 100644
> --- a/src/libvirt-stream.c
> +++ b/src/libvirt-stream.c
> @@ -668,6 +668,129 @@ virStreamRecvAll(virStreamPtr stream,
> }
>
>
> +/**
> + * virStreamSparseRecvAll:
> + * @stream: pointer to the stream object
> + * @handler: sink callback for writing data to application
> + * @holeHandler: stream hole callback for skipping holes
> + * @opaque: application defined data
> + *
> + * Receive the entire data stream, sending the data to the
> + * requested data sink @handler and calling the skip @holeHandler
> + * to generate holes for sparse stream targets. This is simply a
> + * convenient alternative to virStreamRecvFlags, for apps that do
> + * blocking-I/O.
> + *
> + * An example using this with a hypothetical file download
> + * API looks like:
> + *
> + * int mysink(virStreamPtr st, const char *buf, int nbytes, void *opaque) {
> + * int *fd = opaque;
> + *
> + * return write(*fd, buf, nbytes);
> + * }
> + *
> + * int myskip(virStreamPtr st, long long offset, void *opaque) {
> + * int *fd = opaque;
> + *
I think this is where perhaps the example of lseek in "off_t" chunks of
"long long offset" would be applicable... Perhaps why I ended up in the
off_t rathole before.
> + * return lseek(*fd, offset, SEEK_CUR) == (off_t) -1 ? -1 : 0;
> + * }
> + *
> + * virStreamPtr st = virStreamNew(conn, 0);
> + * int fd = open("demo.iso", O_WRONLY);
> + *
> + * virConnectDownloadSparseFile(conn, st);
^^ This API doesn't exist... Of course neither did
virConnectDownloadFile from whence you copied the example. Maybe both
should be 'adjusted'.
Reviewed-by: John Ferlan <jferlan(a)redhat.com>
John
> + * if (virStreamSparseRecvAll(st, mysink, myskip, &fd) < 0) {
> + * ...report an error ...
> + * goto done;
> + * }
> + * if (virStreamFinish(st) < 0)
> + * ...report an error...
> + * virStreamFree(st);
> + * close(fd);
> + *
> + * Note that @opaque data is shared between both @handler and
> + * @holeHandler callbacks.
> + *
> + * Returns 0 if all the data was successfully received. The caller
> + * should invoke virStreamFinish(st) to flush the stream upon
> + * success and then virStreamFree(st).
> + *
> + * Returns -1 upon any error, with virStreamAbort() already
> + * having been called, so the caller need only call virStreamFree().
> + */
[...]