[libvirt] [PATCH 7/7] remote: Use virDomainEventState helpers
Daniel P. Berrange
berrange at redhat.com
Fri May 13 09:26:32 UTC 2011
On Thu, May 12, 2011 at 01:14:31PM -0400, Cole Robinson wrote:
> One functionality change here is that we no longer force enable the event
> timeout for every queued event, only enable it for the first event after
> the queue has been flushed. This is how other drivers have already done it,
> and I haven't encountered problems in practice.
>
> v3:
> Adjust for new virDomainEventStateNew argument
>
> Signed-off-by: Cole Robinson <crobinso at redhat.com>
> ---
> .gnulib | 2 +-
> src/remote/remote_driver.c | 163 +++++++++++++++++---------------------------
> 2 files changed, 64 insertions(+), 101 deletions(-)
>
> diff --git a/.gnulib b/.gnulib
> index 64a5e38..a6676cc 160000
> --- a/.gnulib
> +++ b/.gnulib
> @@ -1 +1 @@
> -Subproject commit 64a5e38bced6c8f5117efbed95cdfd8ca133ed54
> +Subproject commit a6676cca6498ce67c5a3c8d7221b8d6c30b61dc4
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index c50ff25..1d64a63 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -184,15 +184,7 @@ struct private_data {
> unsigned int bufferLength;
> unsigned int bufferOffset;
>
> - /* The list of domain event callbacks */
> - virDomainEventCallbackListPtr callbackList;
> - /* The queue of domain events generated
> - during a call / response rpc */
> - virDomainEventQueuePtr domainEvents;
> - /* Timer for flushing domainEvents queue */
> - int eventFlushTimer;
> - /* Flag if we're in process of dispatching */
> - int domainEventDispatching;
> + virDomainEventStatePtr domainEventState;
>
> /* Self-pipe to wakeup threads waiting in poll() */
> int wakeupSendFD;
> @@ -264,6 +256,7 @@ static void make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWF
> static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
> void remoteDomainEventFired(int watch, int fd, int event, void *data);
> void remoteDomainEventQueueFlush(int timer, void *opaque);
> +void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event);
> /*----------------------------------------------------------------------*/
>
> /* Helper functions for remoteOpen. */
> @@ -913,17 +906,6 @@ doRemoteOpen (virConnectPtr conn,
> }
> }
>
> - if(VIR_ALLOC(priv->callbackList)<0) {
> - virReportOOMError();
> - goto failed;
> - }
> -
> - if(VIR_ALLOC(priv->domainEvents)<0) {
> - virReportOOMError();
> - goto failed;
> - }
> -
> - VIR_DEBUG("Adding Handler for remote events");
> /* Set up a callback to listen on the socket data */
> if ((priv->watch = virEventAddHandle(priv->sock,
> VIR_EVENT_HANDLE_READABLE,
> @@ -931,18 +913,21 @@ doRemoteOpen (virConnectPtr conn,
> conn, NULL)) < 0) {
> VIR_DEBUG("virEventAddHandle failed: No addHandleImpl defined."
> " continuing without events.");
> - } else {
> + priv->watch = -1;
> + }
>
> - VIR_DEBUG("Adding Timeout for remote event queue flushing");
> - if ( (priv->eventFlushTimer = virEventAddTimeout(-1,
> - remoteDomainEventQueueFlush,
> - conn, NULL)) < 0) {
> - VIR_DEBUG("virEventAddTimeout failed: No addTimeoutImpl defined. "
> - "continuing without events.");
> - virEventRemoveHandle(priv->watch);
> - priv->watch = -1;
> - }
> + priv->domainEventState = virDomainEventStateNew(remoteDomainEventQueueFlush,
> + conn,
> + NULL,
> + false);
> + if (!priv->domainEventState) {
> + goto failed;
> + }
> + if (priv->domainEventState->timer < 0 && priv->watch != -1) {
> + virEventRemoveHandle(priv->watch);
> + priv->watch = -1;
> }
> +
> /* Successful. */
> retcode = VIR_DRV_OPEN_SUCCESS;
>
> @@ -1559,12 +1544,13 @@ verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
> static int
> doRemoteClose (virConnectPtr conn, struct private_data *priv)
> {
> - if (priv->eventFlushTimer >= 0) {
> - /* Remove timeout */
> - virEventRemoveTimeout(priv->eventFlushTimer);
> - /* Remove handle for remote events */
> + /* Remove timer before closing the connection, to avoid possible
> + * remoteDomainEventFired with a free'd connection */
> + if (priv->domainEventState->timer >= 0) {
> + virEventRemoveTimeout(priv->domainEventState->timer);
> virEventRemoveHandle(priv->watch);
> priv->watch = -1;
> + priv->domainEventState->timer = -1;
> }
>
> if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
> @@ -1605,11 +1591,7 @@ retry:
> /* See comment for remoteType. */
> VIR_FREE(priv->type);
>
> - /* Free callback list */
> - virDomainEventCallbackListFree(priv->callbackList);
> -
> - /* Free queued events */
> - virDomainEventQueueFree(priv->domainEvents);
> + virDomainEventStateFree(priv->domainEventState);
>
> return 0;
> }
> @@ -3800,17 +3782,20 @@ static int remoteDomainEventRegister(virConnectPtr conn,
>
> remoteDriverLock(priv);
>
> - if (priv->eventFlushTimer < 0) {
> + if (priv->domainEventState->timer < 0) {
> remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
> goto done;
> }
> - if (virDomainEventCallbackListAdd(conn, priv->callbackList,
> +
> + if (virDomainEventCallbackListAdd(conn, priv->domainEventState->callbacks,
> callback, opaque, freecb) < 0) {
> remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
> goto done;
> }
>
> - if (virDomainEventCallbackListCountID(conn, priv->callbackList, VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 1) {
> + if (virDomainEventCallbackListCountID(conn,
> + priv->domainEventState->callbacks,
> + VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 1) {
> /* Tell the server when we are the first callback deregistering */
> if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER,
> (xdrproc_t) xdr_void, (char *) NULL,
> @@ -3833,21 +3818,14 @@ static int remoteDomainEventDeregister(virConnectPtr conn,
>
> remoteDriverLock(priv);
>
> - if (priv->domainEventDispatching) {
> - if (virDomainEventCallbackListMarkDelete(conn, priv->callbackList,
> - callback) < 0) {
> - remoteError(VIR_ERR_RPC, "%s", _("marking cb for deletion"));
> - goto done;
> - }
> - } else {
> - if (virDomainEventCallbackListRemove(conn, priv->callbackList,
> - callback) < 0) {
> - remoteError(VIR_ERR_RPC, "%s", _("removing cb from list"));
> - goto done;
> - }
> - }
> + if (virDomainEventStateDeregister(conn,
> + priv->domainEventState,
> + callback) < 0)
> + goto done;
>
> - if (virDomainEventCallbackListCountID(conn, priv->callbackList, VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 0) {
> + if (virDomainEventCallbackListCountID(conn,
> + priv->domainEventState->callbacks,
> + VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 0) {
> /* Tell the server when we are the last callback deregistering */
> if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER,
> (xdrproc_t) xdr_void, (char *) NULL,
> @@ -4723,12 +4701,13 @@ static int remoteDomainEventRegisterAny(virConnectPtr conn,
>
> remoteDriverLock(priv);
>
> - if (priv->eventFlushTimer < 0) {
> + if (priv->domainEventState->timer < 0) {
> remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
> goto done;
> }
>
> - if ((callbackID = virDomainEventCallbackListAddID(conn, priv->callbackList,
> + if ((callbackID = virDomainEventCallbackListAddID(conn,
> + priv->domainEventState->callbacks,
> dom, eventID,
> callback, opaque, freecb)) < 0) {
> remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
> @@ -4737,13 +4716,17 @@ static int remoteDomainEventRegisterAny(virConnectPtr conn,
>
> /* If this is the first callback for this eventID, we need to enable
> * events on the server */
> - if (virDomainEventCallbackListCountID(conn, priv->callbackList, eventID) == 1) {
> + if (virDomainEventCallbackListCountID(conn,
> + priv->domainEventState->callbacks,
> + eventID) == 1) {
> args.eventID = eventID;
>
> if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY,
> (xdrproc_t) xdr_remote_domain_events_register_any_args, (char *) &args,
> (xdrproc_t) xdr_void, (char *)NULL) == -1) {
> - virDomainEventCallbackListRemoveID(conn, priv->callbackList, callbackID);
> + virDomainEventCallbackListRemoveID(conn,
> + priv->domainEventState->callbacks,
> + callbackID);
> goto done;
> }
> }
> @@ -4766,28 +4749,23 @@ static int remoteDomainEventDeregisterAny(virConnectPtr conn,
>
> remoteDriverLock(priv);
>
> - if ((eventID = virDomainEventCallbackListEventID(conn, priv->callbackList, callbackID)) < 0) {
> + if ((eventID = virDomainEventCallbackListEventID(conn,
> + priv->domainEventState->callbacks,
> + callbackID)) < 0) {
> remoteError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
> goto done;
> }
>
> - if (priv->domainEventDispatching) {
> - if (virDomainEventCallbackListMarkDeleteID(conn, priv->callbackList,
> - callbackID) < 0) {
> - remoteError(VIR_ERR_RPC, "%s", _("marking cb for deletion"));
> - goto done;
> - }
> - } else {
> - if (virDomainEventCallbackListRemoveID(conn, priv->callbackList,
> - callbackID) < 0) {
> - remoteError(VIR_ERR_RPC, "%s", _("removing cb from list"));
> - goto done;
> - }
> - }
> + if (virDomainEventStateDeregisterAny(conn,
> + priv->domainEventState,
> + callbackID) < 0)
> + goto done;
>
> /* If that was the last callback for this eventID, we need to disable
> * events on the server */
> - if (virDomainEventCallbackListCountID(conn, priv->callbackList, eventID) == 0) {
> + if (virDomainEventCallbackListCountID(conn,
> + priv->domainEventState->callbacks,
> + eventID) == 0) {
> args.eventID = eventID;
>
> if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY,
> @@ -5553,13 +5531,7 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
> if (!event)
> return -1;
>
> - if (virDomainEventQueuePush(priv->domainEvents,
> - event) < 0) {
> - VIR_DEBUG("Error adding event to queue");
> - virDomainEventFree(event);
> - }
> - virEventUpdateTimeout(priv->eventFlushTimer, 0);
> -
> + remoteDomainEventQueue(priv, event);
> return 0;
> }
>
> @@ -6230,31 +6202,22 @@ remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
> {
> virConnectPtr conn = opaque;
> struct private_data *priv = conn->privateData;
> - virDomainEventQueue tempQueue;
>
> - remoteDriverLock(priv);
>
> + remoteDriverLock(priv);
> VIR_DEBUG("Event queue flush %p", conn);
> - priv->domainEventDispatching = 1;
> -
> - /* Copy the queue, so we're reentrant safe */
> - tempQueue.count = priv->domainEvents->count;
> - tempQueue.events = priv->domainEvents->events;
> - priv->domainEvents->count = 0;
> - priv->domainEvents->events = NULL;
> -
> - virEventUpdateTimeout(priv->eventFlushTimer, -1);
> - virDomainEventQueueDispatch(&tempQueue, priv->callbackList,
> - remoteDomainEventDispatchFunc, priv);
> -
> - /* Purge any deleted callbacks */
> - virDomainEventCallbackListPurgeMarked(priv->callbackList);
> -
> - priv->domainEventDispatching = 0;
>
> + virDomainEventStateFlush(priv->domainEventState,
> + remoteDomainEventDispatchFunc,
> + priv);
> remoteDriverUnlock(priv);
> }
>
> +void
> +remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
> +{
> + virDomainEventStateQueue(priv->domainEventState, event);
> +}
>
> /* get_nonnull_domain and get_nonnull_network turn an on-wire
> * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
ACK
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