[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/7] 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

Signed-off-by: Cole Robinson <crobinso 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]