[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