On Tue, Nov 01, 2011 at 03:46:06PM +0100, Jiri Denemark wrote: > From: Michal Privoznik <mprivozn@xxxxxxxxxx> > > If daemon is using SASL it reads client data into a cache. This cache is > big (usually 65KB) and can thus contain 2 or more messages. However, > on socket event we can dispatch only one message. So if we read two > messages at once, the second will not be dispatched as the socket event > goes away with filling the cache. > Moreover, when dispatching the cache we need to remember to take care > of client max requests limit. > --- > src/rpc/virnetserverclient.c | 29 ++++++++++++++++++++++++++++- > 1 files changed, 28 insertions(+), 1 deletions(-) > > diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c > index 1256f0f..2f5ae8f 100644 > --- a/src/rpc/virnetserverclient.c > +++ b/src/rpc/virnetserverclient.c > @@ -72,6 +72,8 @@ struct _virNetServerClient > #if HAVE_SASL > virNetSASLSessionPtr sasl; > #endif > + int sockTimer; /* Timer to be fired upon cached data, > + * so we jump out from poll() immediately */ > > /* Count of messages in the 'tx' queue, > * and the server worker pool queue > @@ -103,6 +105,7 @@ struct _virNetServerClient > > static void virNetServerClientDispatchEvent(virNetSocketPtr sock, int events, void *opaque); > static void virNetServerClientUpdateEvent(virNetServerClientPtr client); > +static void virNetServerClientDispatchRead(virNetServerClientPtr client); > > static void virNetServerClientLock(virNetServerClientPtr client) > { > @@ -204,6 +207,9 @@ static void virNetServerClientUpdateEvent(virNetServerClientPtr client) > mode = virNetServerClientCalculateHandleMode(client); > > virNetSocketUpdateIOCallback(client->sock, mode); > + > + if (client->rx && virNetSocketHasCachedData(client->sock)) > + virEventUpdateTimeout(client->sockTimer, 0); > } > > > @@ -293,6 +299,19 @@ virNetServerClientCheckAccess(virNetServerClientPtr client) > return 0; > } > > +static void virNetServerClientSockTimerFunc(int timer, > + void *opaque) > +{ > + virNetServerClientPtr client = opaque; > + virNetServerClientLock(client); > + virEventUpdateTimeout(timer, -1); > + /* Although client->rx != NULL when this timer is enabled, it might have > + * changed since the client was unlocked in the meantime. */ > + if (client->rx) > + virNetServerClientDispatchRead(client); > + virNetServerClientUnlock(client); > +} > + > > virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, > int auth, > @@ -319,6 +338,11 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, > client->tlsCtxt = tls; > client->nrequests_max = nrequests_max; > > + client->sockTimer = virEventAddTimeout(-1, virNetServerClientSockTimerFunc, > + client, NULL); > + if (client->sockTimer < 0) > + goto error; > + > if (tls) > virNetTLSContextRef(tls); > > @@ -557,6 +581,8 @@ void virNetServerClientFree(virNetServerClientPtr client) > #if HAVE_SASL > virNetSASLSessionFree(client->sasl); > #endif > + if (client->sockTimer > 0) > + virEventRemoveTimeout(client->sockTimer); > virNetTLSSessionFree(client->tls); > virNetTLSContextFree(client->tlsCtxt); > virNetSocketFree(client->sock); > @@ -990,7 +1016,8 @@ virNetServerClientDispatchEvent(virNetSocketPtr sock, int events, void *opaque) > } else { > if (events & VIR_EVENT_HANDLE_WRITABLE) > virNetServerClientDispatchWrite(client); > - if (events & VIR_EVENT_HANDLE_READABLE) > + if (events & VIR_EVENT_HANDLE_READABLE && > + client->rx) > virNetServerClientDispatchRead(client); > } > } ACK this looks good 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list