]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Refactor domain events to handle multiple event types
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 18 Mar 2010 14:06:09 +0000 (14:06 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 26 Mar 2010 13:52:14 +0000 (13:52 +0000)
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
src/conf/domain_event.h
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

index b520232a400dcd78102acfd4b2258d44c9776107..a44ab3de18289b1df2fd149160b536d80766431d 100644 (file)
     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,58 @@ 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 & ignoring 'name' since
+         * Xen sometimes renames guests during migration, thus
+         * leaving 'uuid' as the only truely reliable ID we can use*/
+
+        if (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 +530,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);
     }
 }
 
index 5d8faee59dcb0c6f15bdfec5c6988b7b250830cc..8658631d2e1e1309debe84328cbefe20396baa26 100644 (file)
@@ -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);
 
index ac53b4d499ca234a96c2b538fa3595ffbaa27480..d204c80ece9a790c9535bf481a1f87b55b9d9399 100644 (file)
@@ -1476,7 +1476,7 @@ lxcDomainEventDeregister (virConnectPtr conn,
 
 static void lxcDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
-                                       virConnectDomainEventCallback cb,
+                                       virConnectDomainEventGenericCallback cb,
                                        void *cbopaque,
                                        void *opaque)
 {
index e8d8c2f1c03d0d5eefee60d30a7377e673abff0d..576cb6d2f772fbd5433454d397f2a093c53d2c93 100644 (file)
@@ -8003,7 +8003,7 @@ qemudDomainEventDeregister (virConnectPtr conn,
 
 static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                         virDomainEventPtr event,
-                                        virConnectDomainEventCallback cb,
+                                        virConnectDomainEventGenericCallback cb,
                                         void *cbopaque,
                                         void *opaque)
 {
index 286e400fa0a24a16dac3b950413be7b9c59a2ed3..082ecb6527bf451c4a413b9b12c0b9520c0ef82a 100644 (file)
@@ -8953,7 +8953,7 @@ done:
 
 static void remoteDomainEventDispatchFunc(virConnectPtr conn,
                                           virDomainEventPtr event,
-                                          virConnectDomainEventCallback cb,
+                                          virConnectDomainEventGenericCallback cb,
                                           void *cbopaque,
                                           void *opaque)
 {
index 288ef69c704541c2bad302b6621cb7e9d907f5ed..ada206edc3fd6b4cc02bc764055ad380383b3d7a 100644 (file)
@@ -5090,7 +5090,7 @@ testDomainEventDeregister (virConnectPtr conn,
 
 static void testDomainEventDispatchFunc(virConnectPtr conn,
                                         virDomainEventPtr event,
-                                        virConnectDomainEventCallback cb,
+                                        virConnectDomainEventGenericCallback cb,
                                         void *cbopaque,
                                         void *opaque)
 {
index 71a0d6f0f6126819bf6b30fc46235d3d4639e889..ccb5faea96c9d10d1eec965075850ef20b3d3dff 100644 (file)
@@ -2042,7 +2042,7 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
 static void
 xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
                                   virDomainEventPtr event,
-                                  virConnectDomainEventCallback cb,
+                                  virConnectDomainEventGenericCallback cb,
                                   void *cbopaque,
                                   void *opaque)
 {