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

[libvirt] [PATCH 03/13] Refactor domain events to handle multiple event types



The internal domain events APIs are designed to handle the lifecycle
events. This needs to be refactored to allow arbitrary new event
types to be handled.

 * The signature of virDomainEventDispatchFunc changes to use
   virConnectDomainEventGenericCallback instead of the lifecycle
   event specific virConnectDomainEventCallback
 * Every registered callback gains a unique ID to allow its
   removal based on ID, instead of function pointer
 * Every registered callback gains an 'eventID' to allow callbacks
   for different types of events to be distinguished
 * virDomainEventDispatch is adapted to filter out callbacks
   whose eventID does not match the eventID of the event being
   dispatched
 * virDomainEventDispatch is adapted to filter based on the
   domain name and uuid, if this filter is set for a callback.
 * virDomainEvent type/detail fields are moved into a union to
   allow different data fields for other types of events to be
   added later

* src/conf/domain_event.h, src/conf/domain_event.c: Refactor
  to allow handling of different types of events
* src/lxc/lxc_driver.c, src/qemu/qemu_driver.c,
  src/remote/remote_driver.c, src/test/test_driver.c,
  src/xen/xen_driver.c: Change dispatch function signature
  to use virConnectDomainEventGenericCallback
---
 src/conf/domain_event.c    |  178 +++++++++++++++++++++++++++++++++-----------
 src/conf/domain_event.h    |    5 +-
 src/lxc/lxc_driver.c       |    2 +-
 src/qemu/qemu_driver.c     |    2 +-
 src/remote/remote_driver.c |    2 +-
 src/test/test_driver.c     |    2 +-
 src/xen/xen_driver.c       |    2 +-
 7 files changed, 142 insertions(+), 51 deletions(-)

diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index b520232..9d47eeb 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -35,20 +35,36 @@
     virReportErrorHelper(conn, VIR_FROM_THIS, code, __FILE__,       \
                          __FUNCTION__, __LINE__, __VA_ARGS__)
 
+struct _virDomainMeta {
+    int id;
+    char *name;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+};
+typedef struct _virDomainMeta virDomainMeta;
+typedef virDomainMeta *virDomainMetaPtr;
+
 struct _virDomainEventCallback {
+    int callbackID;
+    int eventID;
     virConnectPtr conn;
-    virConnectDomainEventCallback cb;
+    virDomainMetaPtr dom;
+    virConnectDomainEventGenericCallback cb;
     void *opaque;
     virFreeCallback freecb;
     int deleted;
 };
 
 struct _virDomainEvent {
-    int id;
-    char *name;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    int type;
-    int detail;
+    int eventID;
+
+    virDomainMeta dom;
+
+    union {
+        struct {
+            int type;
+            int detail;
+        } lifecycle;
+    } data;
 };
 
 /**
@@ -72,6 +88,8 @@ virDomainEventCallbackListFree(virDomainEventCallbackListPtr list)
     }
     VIR_FREE(list);
 }
+
+
 /**
  * virDomainEventCallbackListRemove:
  * @conn: pointer to the connection
@@ -87,8 +105,9 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
 {
     int i;
     for (i = 0 ; i < cbList->count ; i++) {
-        if(cbList->callbacks[i]->cb == callback &&
-           cbList->callbacks[i]->conn == conn) {
+        if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
+            cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
+            cbList->callbacks[i]->conn == conn) {
             virFreeCallback freecb = cbList->callbacks[i]->freecb;
             if (freecb)
                 (*freecb)(cbList->callbacks[i]->opaque);
@@ -116,6 +135,7 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
     return -1;
 }
 
+
 /**
  * virDomainEventCallbackListRemoveConn:
  * @conn: pointer to the connection
@@ -131,7 +151,7 @@ virDomainEventCallbackListRemoveConn(virConnectPtr conn,
     int old_count = cbList->count;
     int i;
     for (i = 0 ; i < cbList->count ; i++) {
-        if(cbList->callbacks[i]->conn == conn) {
+        if (cbList->callbacks[i]->conn == conn) {
             virFreeCallback freecb = cbList->callbacks[i]->freecb;
             if (freecb)
                 (*freecb)(cbList->callbacks[i]->opaque);
@@ -154,14 +174,16 @@ virDomainEventCallbackListRemoveConn(virConnectPtr conn,
     return 0;
 }
 
+
 int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
                                          virDomainEventCallbackListPtr cbList,
                                          virConnectDomainEventCallback callback)
 {
     int i;
     for (i = 0 ; i < cbList->count ; i++) {
-        if (cbList->callbacks[i]->conn == conn &&
-            cbList->callbacks[i]->cb == callback) {
+        if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
+            cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
+            cbList->callbacks[i]->conn == conn) {
             cbList->callbacks[i]->deleted = 1;
             return 0;
         }
@@ -172,6 +194,7 @@ int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
     return -1;
 }
 
+
 int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
 {
     int old_count = cbList->count;
@@ -200,6 +223,7 @@ int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
     return 0;
 }
 
+
 /**
  * virDomainEventCallbackListAdd:
  * @conn: pointer to the connection
@@ -217,7 +241,7 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
                               virFreeCallback freecb)
 {
     virDomainEventCallbackPtr event;
-    int n;
+    int i;
 
     /* Check incoming */
     if ( !cbList ) {
@@ -225,9 +249,10 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
     }
 
     /* check if we already have this callback on our list */
-    for (n=0; n < cbList->count; n++) {
-        if(cbList->callbacks[n]->cb == callback &&
-           conn == cbList->callbacks[n]->conn) {
+    for (i = 0 ; i < cbList->count ; i++) {
+        if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
+            cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
+            cbList->callbacks[i]->conn == conn) {
             eventReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
                              _("event callback already tracked"));
             return -1;
@@ -239,13 +264,13 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
         return -1;
     }
     event->conn = conn;
-    event->cb = callback;
+    event->cb = VIR_DOMAIN_EVENT_CALLBACK(callback);
+    event->eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
     event->opaque = opaque;
     event->freecb = freecb;
 
     /* Make space on list */
-    n = cbList->count;
-    if (VIR_REALLOC_N(cbList->callbacks, n + 1) < 0) {
+    if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0) {
         virReportOOMError();
         VIR_FREE(event);
         return -1;
@@ -253,15 +278,27 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
 
     event->conn->refs++;
 
-    cbList->callbacks[n] = event;
+    cbList->callbacks[cbList->count] = event;
     cbList->count++;
-    return 0;
+
+    event->callbackID = cbList->nextID++;
+
+    return event->callbackID;
 }
 
 
 int virDomainEventCallbackListCount(virDomainEventCallbackListPtr cbList)
 {
-    return cbList->count;
+    int i;
+    int count = 0;
+
+    for (i = 0 ; i < cbList->count ; i++) {
+        if (cbList->callbacks[i]->deleted)
+            continue;
+        count++;
+    }
+
+    return count;
 }
 
 
@@ -270,7 +307,7 @@ void virDomainEventFree(virDomainEventPtr event)
     if (!event)
         return;
 
-    VIR_FREE(event->name);
+    VIR_FREE(event->dom.name);
     VIR_FREE(event);
 }
 
@@ -287,9 +324,10 @@ virDomainEventQueuePtr virDomainEventQueueNew(void)
     return ret;
 }
 
-virDomainEventPtr virDomainEventNew(int id, const char *name,
-                                    const unsigned char *uuid,
-                                    int type, int detail)
+static virDomainEventPtr virDomainEventNewInternal(int eventID,
+                                                   int id,
+                                                   const char *name,
+                                                   const unsigned char *uuid)
 {
     virDomainEventPtr event;
 
@@ -298,15 +336,29 @@ virDomainEventPtr virDomainEventNew(int id, const char *name,
         return NULL;
     }
 
-    event->type = type;
-    event->detail = detail;
-    if (!(event->name = strdup(name))) {
+    event->eventID = eventID;
+    if (!(event->dom.name = strdup(name))) {
         virReportOOMError();
         VIR_FREE(event);
         return NULL;
     }
-    event->id = id;
-    memcpy(event->uuid, uuid, VIR_UUID_BUFLEN);
+    event->dom.id = id;
+    memcpy(event->dom.uuid, uuid, VIR_UUID_BUFLEN);
+
+    return event;
+}
+
+virDomainEventPtr virDomainEventNew(int id, const char *name,
+                                    const unsigned char *uuid,
+                                    int type, int detail)
+{
+    virDomainEventPtr event = virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+                                                        id, name, uuid);
+
+    if (event) {
+        event->data.lifecycle.type = type;
+        event->data.lifecycle.detail = detail;
+    }
 
     return event;
 }
@@ -414,19 +466,57 @@ virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
 
 void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
-                                       virConnectDomainEventCallback cb,
+                                       virConnectDomainEventGenericCallback cb,
                                        void *cbopaque,
                                        void *opaque ATTRIBUTE_UNUSED)
 {
-    virDomainPtr dom = virGetDomain(conn, event->name, event->uuid);
-    if (dom) {
-        dom->id = event->id;
-        (*cb)(conn, dom, event->type, event->detail, cbopaque);
-        virDomainFree(dom);
+    virDomainPtr dom = virGetDomain(conn, event->dom.name, event->dom.uuid);
+    if (!dom)
+        return;
+    dom->id = event->dom.id;
+
+    switch (event->eventID) {
+    case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
+        ((virConnectDomainEventCallback)cb)(conn, dom,
+                                            event->data.lifecycle.type,
+                                            event->data.lifecycle.detail,
+                                            cbopaque);
+        break;
+
+    default:
+        VIR_WARN("Unexpected event ID %d", event->eventID);
+        break;
     }
+
+    virDomainFree(dom);
 }
 
 
+static int virDomainEventDispatchMatchCallback(virDomainEventPtr event,
+                                               virDomainEventCallbackPtr cb)
+{
+    if (!cb)
+        return 0;
+    if (cb->deleted)
+        return 0;
+    if (cb->eventID != event->eventID)
+        return 0;
+
+    if (cb->dom) {
+        /* Delibrately ignoring 'id' for matching, since that
+         * will cause problems when a domain switches between
+         * running & shutoff states */
+
+        if (STREQ(event->dom.name, cb->dom->name) &&
+            (memcmp(event->dom.uuid, cb->dom->uuid, VIR_UUID_BUFLEN) == 0))
+            return 1;
+
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
 void virDomainEventDispatch(virDomainEventPtr event,
                             virDomainEventCallbackListPtr callbacks,
                             virDomainEventDispatchFunc dispatch,
@@ -439,14 +529,14 @@ void virDomainEventDispatch(virDomainEventPtr event,
     int cbCount = callbacks->count;
 
     for (i = 0 ; i < cbCount ; i++) {
-        if (callbacks->callbacks[i] &&
-            !callbacks->callbacks[i]->deleted) {
-            (*dispatch)(callbacks->callbacks[i]->conn,
-                        event,
-                        callbacks->callbacks[i]->cb,
-                        callbacks->callbacks[i]->opaque,
-                        opaque);
-        }
+        if (!virDomainEventDispatchMatchCallback(event, callbacks->callbacks[i]))
+            continue;
+
+        (*dispatch)(callbacks->callbacks[i]->conn,
+                    event,
+                    callbacks->callbacks[i]->cb,
+                    callbacks->callbacks[i]->opaque,
+                    opaque);
     }
 }
 
diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
index 5d8faee..8658631 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -31,6 +31,7 @@ typedef struct _virDomainEventCallback virDomainEventCallback;
 typedef virDomainEventCallback *virDomainEventCallbackPtr;
 
 struct _virDomainEventCallbackList {
+    unsigned int nextID;
     unsigned int count;
     virDomainEventCallbackPtr *callbacks;
 };
@@ -96,12 +97,12 @@ void virDomainEventQueueFree(virDomainEventQueuePtr queue);
 
 typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
                                            virDomainEventPtr event,
-                                           virConnectDomainEventCallback cb,
+                                           virConnectDomainEventGenericCallback cb,
                                            void *cbopaque,
                                            void *opaque);
 void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
-                                       virConnectDomainEventCallback cb,
+                                       virConnectDomainEventGenericCallback cb,
                                        void *cbopaque,
                                        void *opaque);
 
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 41d66bf..592663d 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1470,7 +1470,7 @@ lxcDomainEventDeregister (virConnectPtr conn,
 
 static void lxcDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
-                                       virConnectDomainEventCallback cb,
+                                       virConnectDomainEventGenericCallback cb,
                                        void *cbopaque,
                                        void *opaque)
 {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 81b4f36..d522c43 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7979,7 +7979,7 @@ qemudDomainEventDeregister (virConnectPtr conn,
 
 static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                         virDomainEventPtr event,
-                                        virConnectDomainEventCallback cb,
+                                        virConnectDomainEventGenericCallback cb,
                                         void *cbopaque,
                                         void *opaque)
 {
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 7013a05..2c3a70e 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8891,7 +8891,7 @@ done:
 
 static void remoteDomainEventDispatchFunc(virConnectPtr conn,
                                           virDomainEventPtr event,
-                                          virConnectDomainEventCallback cb,
+                                          virConnectDomainEventGenericCallback cb,
                                           void *cbopaque,
                                           void *opaque)
 {
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index d58086e..9c26a03 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -5091,7 +5091,7 @@ testDomainEventDeregister (virConnectPtr conn,
 
 static void testDomainEventDispatchFunc(virConnectPtr conn,
                                         virDomainEventPtr event,
-                                        virConnectDomainEventCallback cb,
+                                        virConnectDomainEventGenericCallback cb,
                                         void *cbopaque,
                                         void *opaque)
 {
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 9839858..bf28d43 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -2041,7 +2041,7 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
 static void
 xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
                                   virDomainEventPtr event,
-                                  virConnectDomainEventCallback cb,
+                                  virConnectDomainEventGenericCallback cb,
                                   void *cbopaque,
                                   void *opaque)
 {
-- 
1.6.6.1


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