From 227d67ca00b40ece42709149d392a047a7270e82 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Wed, 5 Jan 2011 17:51:45 -0500 Subject: [PATCH] domain_event: Add common domain event queue/flush helpers The same code for queueing, flushing, and deregistering events exists in multiple drivers, which will soon use these common functions. v2: Adjust libvirt_private.syms isDispatching bool fixes NONNULL tagging v3: Add requireTimer parameter to virDomainEventStateNew --- src/conf/domain_event.c | 93 +++++++++++++++++++++++++++++++++++++++- src/conf/domain_event.h | 24 ++++++++++- src/libvirt_private.syms | 4 ++ 3 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 2771887693..b85765ebba 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -557,10 +557,21 @@ virDomainEventStateFree(virDomainEventStatePtr state) virEventRemoveTimeout(state->timer); } +/** + * virDomainEventStateNew: + * @timeout_cb: virEventTimeoutCallback to call when timer expires + * @timeout_opaque: Data for timeout_cb + * @timeout_free: Optional virFreeCallback for freeing timeout_opaque + * @requireTimer: If true, return an error if registering the timer fails. + * This is fatal for drivers that sit behind the daemon + * (qemu, lxc), since there should always be a event impl + * registered. + */ virDomainEventStatePtr virDomainEventStateNew(virEventTimeoutCallback timeout_cb, void *timeout_opaque, - virFreeCallback timeout_free) + virFreeCallback timeout_free, + bool requireTimer) { virDomainEventStatePtr state = NULL; @@ -582,7 +593,14 @@ virDomainEventStateNew(virEventTimeoutCallback timeout_cb, timeout_cb, timeout_opaque, timeout_free)) < 0) { - goto error; + if (requireTimer == false) { + VIR_DEBUG("virEventAddTimeout failed: No addTimeoutImpl defined. " + "continuing without events."); + } else { + eventReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not initialize domain event timer")); + goto error; + } } return state; @@ -1059,3 +1077,74 @@ void virDomainEventQueueDispatch(virDomainEventQueuePtr queue, VIR_FREE(queue->events); queue->count = 0; } + +void +virDomainEventStateQueue(virDomainEventStatePtr state, + virDomainEventPtr event) +{ + if (state->timer < 0) { + virDomainEventFree(event); + return; + } + + if (virDomainEventQueuePush(state->queue, event) < 0) { + VIR_DEBUG("Error adding event to queue"); + virDomainEventFree(event); + } + + if (state->queue->count == 1) + virEventUpdateTimeout(state->timer, 0); +} + +void +virDomainEventStateFlush(virDomainEventStatePtr state, + virDomainEventDispatchFunc dispatchFunc, + void *opaque) +{ + virDomainEventQueue tempQueue; + + state->isDispatching = true; + + /* Copy the queue, so we're reentrant safe when dispatchFunc drops the + * driver lock */ + tempQueue.count = state->queue->count; + tempQueue.events = state->queue->events; + state->queue->count = 0; + state->queue->events = NULL; + + virEventUpdateTimeout(state->timer, -1); + virDomainEventQueueDispatch(&tempQueue, + state->callbacks, + dispatchFunc, + opaque); + + /* Purge any deleted callbacks */ + virDomainEventCallbackListPurgeMarked(state->callbacks); + + state->isDispatching = false; +} + +int +virDomainEventStateDeregister(virConnectPtr conn, + virDomainEventStatePtr state, + virConnectDomainEventCallback callback) +{ + if (state->isDispatching) + return virDomainEventCallbackListMarkDelete(conn, + state->callbacks, callback); + else + return virDomainEventCallbackListRemove(conn, state->callbacks, callback); +} + +int +virDomainEventStateDeregisterAny(virConnectPtr conn, + virDomainEventStatePtr state, + int callbackID) +{ + if (state->isDispatching) + return virDomainEventCallbackListMarkDeleteID(conn, + state->callbacks, callbackID); + else + return virDomainEventCallbackListRemoveID(conn, + state->callbacks, callbackID); +} diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index 2ac3ecc98c..efc05f9359 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -182,7 +182,8 @@ void virDomainEventStateFree(virDomainEventStatePtr state); virDomainEventStatePtr virDomainEventStateNew(virEventTimeoutCallback timeout_cb, void *timeout_opaque, - virFreeCallback timeout_free) + virFreeCallback timeout_free, + bool requireTimer) ATTRIBUTE_NONNULL(1); typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn, @@ -205,4 +206,25 @@ void virDomainEventQueueDispatch(virDomainEventQueuePtr queue, virDomainEventDispatchFunc dispatch, void *opaque); + +void +virDomainEventStateQueue(virDomainEventStatePtr state, + virDomainEventPtr event) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +void +virDomainEventStateFlush(virDomainEventStatePtr state, + virDomainEventDispatchFunc dispatchFunc, + void *opaque) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int +virDomainEventStateDeregister(virConnectPtr conn, + virDomainEventStatePtr state, + virConnectDomainEventCallback callback) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int +virDomainEventStateDeregisterAny(virConnectPtr conn, + virDomainEventStatePtr state, + int callbackID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d4ad0c80db..c98efdcfaf 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -389,8 +389,12 @@ virDomainEventRTCChangeNewFromObj; virDomainEventRebootNew; virDomainEventRebootNewFromDom; virDomainEventRebootNewFromObj; +virDomainEventStateDeregister; +virDomainEventStateDeregisterAny; +virDomainEventStateFlush; virDomainEventStateFree; virDomainEventStateNew; +virDomainEventStateQueue; virDomainEventWatchdogNewFromDom; virDomainEventWatchdogNewFromObj; -- GitLab