[libvirt] [PATCH 1/2] esx: Add libcurl based stream driver

Matthias Bolte matthias.bolte at googlemail.com
Tue Oct 7 20:35:46 UTC 2014


2014-03-31 15:46 GMT+02:00 Michal Privoznik <mprivozn at redhat.com>:
>
> On 30.03.2014 21:03, Matthias Bolte wrote:
>>
>> This allows to implement libvirt functions that use streams, such as
>> virDoaminScreenshot, without the need to store the downloaded data in
>> a temporary file first. The stream driver directly interacts with
>> libcurl to send and receive data.
>>
>> The driver uses the libcurl multi interface that allows to do a transfer
>> in multiple curl_multi_perform() calls. The easy interface would do the
>> whole transfer in a single curl_easy_perform() call. This doesn't work
>> with the libvirt stream API that is driven by multiple calls to the
>> virStreamSend() and virStreamRecv() functions.
>>
>> The curl_multi_wait() function is used to do blocking operations. But it
>> was added in libcurl 7.28.0. For older versions it is emulated using the
>> socket callback of the multi interface.
>>
>> The current driver only supports blocking operations. There is already
>> some code in place for non-blocking mode but it's incomplete. As you can
>> tell from the copyright date I implemeted this in 2012, but never came
>> around to publish it then. I did some work in 2013 and now it's 2014 and
>> I don't want to hold it back any longer.
>> ---
>>   po/POTFILES.in       |   1 +
>>   src/Makefile.am      |   1 +
>>   src/esx/esx_stream.c | 478 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   src/esx/esx_stream.h |  32 ++++
>>   src/esx/esx_vi.c     | 222 +++++++++++++++++++++++-
>>   src/esx/esx_vi.h     |  19 +-
>>   6 files changed, 749 insertions(+), 4 deletions(-)
>>   create mode 100644 src/esx/esx_stream.c
>>   create mode 100644 src/esx/esx_stream.h
>>
>>
>
>> +static int
>> +esxStreamClose(virStreamPtr stream, bool finish)
>> +{
>> +    int result = 0;
>> +    esxStreamPrivate *priv = stream->privateData;
>> +
>> +    if (!priv)
>> +        return 0;
>> +
>> +    virMutexLock(&priv->curl->lock);
>> +
>> +    if (finish && priv->backlog_used > 0) {
>
>
> I think you want to unlock the curl lock here.
>

No, because there is no return statement in the if block, so the
unlock call after the if block is sufficient.

>>
>> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> +                       _("Stream has untransferred data left"));
>> +        result = -1;
>> +    }
>> +
>> +    stream->privateData = NULL;
>> +
>> +    virMutexUnlock(&priv->curl->lock);
>> +
>> +    esxFreeStreamPrivate(&priv);
>> +
>> +    return result;
>> +}
>> +
>
>
>> diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
>> index 6188139..ba34bfd 100644
>> --- a/src/esx/esx_vi.c
>> +++ b/src/esx/esx_vi.c
>> @@ -2,7 +2,7 @@
>>    * esx_vi.c: client for the VMware VI API 2.5 to manage ESX hosts
>>    *
>>    * Copyright (C) 2010-2012 Red Hat, Inc.
>> - * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte at googlemail.com>
>> + * Copyright (C) 2009-2012, 2014 Matthias Bolte <matthias.bolte at googlemail.com>
>>    *
>>    * This library is free software; you can redistribute it and/or
>>    * modify it under the terms of the GNU Lesser General Public
>> @@ -22,6 +22,7 @@
>>
>>   #include <config.h>
>>
>> +#include <poll.h>
>>   #include <libxml/parser.h>
>>   #include <libxml/xpathInternals.h>
>>
>> @@ -662,6 +663,68 @@ esxVI_SharedCURL_Remove(esxVI_SharedCURL *shared, esxVI_CURL *curl)
>>    * MultiCURL
>>    */
>>
>> +#if ESX_EMULATE_CURL_MULTI_WAIT
>> +
>> +static int
>> +esxVI_MultiCURL_SocketCallback(CURL *handle ATTRIBUTE_UNUSED,
>> +                               curl_socket_t fd, int action,
>> +                               void *callback_opaque,
>> +                               void *socket_opaque ATTRIBUTE_UNUSED)
>> +{
>> +    esxVI_MultiCURL *multi = callback_opaque;
>> +    size_t i;
>> +    struct pollfd *pollfd = NULL;
>> +    struct pollfd dummy;
>> +
>> +    if (action & CURL_POLL_REMOVE) {
>> +        for (i = 0; i < multi->npollfds; ++i) {
>> +            if (multi->pollfds[i].fd == fd) {
>> +                VIR_DELETE_ELEMENT(multi->pollfds, i, multi->npollfds);
>> +                break;
>> +            }
>> +        }
>> +    } else {
>> +        for (i = 0; i < multi->npollfds; ++i) {
>> +            if (multi->pollfds[i].fd == fd) {
>> +                pollfd = &multi->pollfds[i];
>> +                break;
>> +            }
>> +        }
>> +
>> +        if (pollfd == NULL) {
>> +            if (VIR_APPEND_ELEMENT(multi->pollfds, multi->npollfds, dummy) < 0) {
>> +                return 0;
>
>
> Okay, this is strange. But I see why you can't return -1. From the curl_multi_socket() documentation:
>
> "The callback MUST return 0."

I added a comment about this now.

>> +            }
>> +
>> +            pollfd = &multi->pollfds[multi->npollfds - 1];
>> +        }
>> +
>> +        pollfd->fd = fd;
>> +        pollfd->events = 0;
>> +
>> +        if (action & CURL_POLL_IN)
>> +            pollfd->events |= POLLIN;
>> +
>> +        if (action & CURL_POLL_OUT)
>> +            pollfd->events |= POLLOUT;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>
>
> ACK with the nits fixed.
>
> Michal

Thanks, pushed... finally :)

-- 
Matthias Bolte
http://photron.blogspot.com




More information about the libvir-list mailing list