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;
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. */
}
}
- 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,
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;
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,
/* 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;
}
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,
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,
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"));
/* 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;
}
}
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,
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;
}
{
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.