[libvirt] [PATCH 02/12] client rpc: Use event loop for writing
Daniel P. Berrange
berrange at redhat.com
Wed Jun 13 08:30:30 UTC 2012
On Wed, Jun 13, 2012 at 01:29:20AM +0200, Jiri Denemark wrote:
> Normally, when every call has a thread associated with it, the thread
> may get the buck and be in charge of sending all calls until its own
> call is done. When we introduced non-blocking calls, we had to add
> special handling of new non-blocking calls. This patch uses event loop
> to send data if there is no thread to get the buck so that any
> non-blocking calls left in the queue are properly sent without having to
> handle them specially. It also avoids adding even more cruft to client
> IO loop in the following patches.
>
> With this change in, non-blocking calls may see unpredictable delays in
> delivery when the client has no event loop registered. However, the only
> non-blocking calls we have are keepalives and we already require event
> loop for them.
Is that 'see unpredictable delays' part really correct. AFAIK, there
should be a pretty well defined "delay" - it'll be processed on the very
next iteration of the event - assuming the socket is writable. I don't
really thing this is a delay at all in fact.
> ---
> src/rpc/virnetclient.c | 35 +++++++++++++++++++++++++++++++----
> 1 file changed, 31 insertions(+), 4 deletions(-)
>
> diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
> index c62e045..3e661d2 100644
> --- a/src/rpc/virnetclient.c
> +++ b/src/rpc/virnetclient.c
> @@ -1470,12 +1470,30 @@ error:
> }
>
>
> +static bool
> +virNetClientIOUpdateEvents(virNetClientCallPtr call,
> + void *opaque)
> +{
> + int *events = opaque;
> +
> + if (call->mode == VIR_NET_CLIENT_MODE_WAIT_TX)
> + *events |= VIR_EVENT_HANDLE_WRITABLE;
> +
> + return false;
> +}
> +
> +
> static void virNetClientIOUpdateCallback(virNetClientPtr client,
> bool enableCallback)
> {
> int events = 0;
> - if (enableCallback)
> +
> + if (enableCallback) {
> events |= VIR_EVENT_HANDLE_READABLE;
> + virNetClientCallMatchPredicate(client->waitDispatch,
> + virNetClientIOUpdateEvents,
> + &events);
> + }
>
> virNetSocketUpdateIOCallback(client->sock, events);
> }
> @@ -1670,11 +1688,20 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
> goto done;
> }
>
> - if (virNetClientIOHandleInput(client) < 0) {
> - VIR_WARN("Something went wrong during async message processing");
> - virNetSocketRemoveIOCallback(sock);
> + if (events & VIR_EVENT_HANDLE_WRITABLE) {
> + if (virNetClientIOHandleOutput(client) < 0)
> + virNetSocketRemoveIOCallback(sock);
> + }
> +
> + if (events & VIR_EVENT_HANDLE_READABLE) {
> + if (virNetClientIOHandleInput(client) < 0)
> + virNetSocketRemoveIOCallback(sock);
> }
>
> + /* Remove completed calls or signal their threads. */
> + virNetClientCallRemovePredicate(&client->waitDispatch,
> + virNetClientIOEventLoopRemoveDone,
> + NULL);
> done:
> virNetClientUnlock(client);
> }
ACK, I always thought we should be doing this :-)
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list