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
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
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 2771887..b85765e 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 2ac3ecc..efc05f9 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 d4ad0c8..c98efdc 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;
--
1.7.4.4