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
This commit is contained in:
Cole Robinson 2011-01-05 17:51:45 -05:00
parent aaf2b70bae
commit 227d67ca00
3 changed files with 118 additions and 3 deletions

View File

@ -557,10 +557,21 @@ virDomainEventStateFree(virDomainEventStatePtr state)
virEventRemoveTimeout(state->timer); 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 virDomainEventStatePtr
virDomainEventStateNew(virEventTimeoutCallback timeout_cb, virDomainEventStateNew(virEventTimeoutCallback timeout_cb,
void *timeout_opaque, void *timeout_opaque,
virFreeCallback timeout_free) virFreeCallback timeout_free,
bool requireTimer)
{ {
virDomainEventStatePtr state = NULL; virDomainEventStatePtr state = NULL;
@ -582,8 +593,15 @@ virDomainEventStateNew(virEventTimeoutCallback timeout_cb,
timeout_cb, timeout_cb,
timeout_opaque, timeout_opaque,
timeout_free)) < 0) { timeout_free)) < 0) {
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; goto error;
} }
}
return state; return state;
@ -1059,3 +1077,74 @@ void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
VIR_FREE(queue->events); VIR_FREE(queue->events);
queue->count = 0; 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);
}

View File

@ -182,7 +182,8 @@ void virDomainEventStateFree(virDomainEventStatePtr state);
virDomainEventStatePtr virDomainEventStatePtr
virDomainEventStateNew(virEventTimeoutCallback timeout_cb, virDomainEventStateNew(virEventTimeoutCallback timeout_cb,
void *timeout_opaque, void *timeout_opaque,
virFreeCallback timeout_free) virFreeCallback timeout_free,
bool requireTimer)
ATTRIBUTE_NONNULL(1); ATTRIBUTE_NONNULL(1);
typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn, typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
@ -205,4 +206,25 @@ void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
virDomainEventDispatchFunc dispatch, virDomainEventDispatchFunc dispatch,
void *opaque); 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 #endif

View File

@ -389,8 +389,12 @@ virDomainEventRTCChangeNewFromObj;
virDomainEventRebootNew; virDomainEventRebootNew;
virDomainEventRebootNewFromDom; virDomainEventRebootNewFromDom;
virDomainEventRebootNewFromObj; virDomainEventRebootNewFromObj;
virDomainEventStateDeregister;
virDomainEventStateDeregisterAny;
virDomainEventStateFlush;
virDomainEventStateFree; virDomainEventStateFree;
virDomainEventStateNew; virDomainEventStateNew;
virDomainEventStateQueue;
virDomainEventWatchdogNewFromDom; virDomainEventWatchdogNewFromDom;
virDomainEventWatchdogNewFromObj; virDomainEventWatchdogNewFromObj;