]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
QEMU domain event thread safety
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 4 Dec 2008 21:09:20 +0000 (21:09 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 4 Dec 2008 21:09:20 +0000 (21:09 +0000)
ChangeLog
src/domain_event.c
src/domain_event.h
src/libvirt_sym.version.in
src/qemu_conf.h
src/qemu_driver.c
src/remote_internal.c
src/xen_inotify.c
src/xen_unified.c
src/xen_unified.h
src/xs_internal.c

index 43d1410b6b8832e211e596ac414a717bba292224..b2e7e3b0eb44bceb08035c9c77b06357981565c9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Thu Dec  4 21:09:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
+
+       QEMU domain events thread safety
+       * src/domain_event.c, src/domain_event.h: Add convenient
+       methods for dispatching a list of events, and a single
+       event to a list of callbacks. Change signature of push
+       method to take a pre-allocated virDomainEventPtr object
+       * src/libvirt_sym.version.in: Export new event methods
+       to daemon code / drivers
+       * src/qemu_conf.h, src/qemu_driver.c: Make event dispatch
+       threadsafe by doing asynchronously
+       * src/remote_internal.c, src/xen_inotify.c, src/xen_unified.c,
+       src/xen_unified.h, src/xs_internal.c: Update for changes in
+       domain event APIs
+
 Thu Dec  4 21:05:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * src/qemu_conf.h: Add a driver lock variable
index d5f54158c60522a1b11e6f74f4925310b23a730a..daa6fd5f8edcec1593a5a7cfc2a810d5d140e4b6 100644 (file)
@@ -125,6 +125,49 @@ 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) {
+            cbList->callbacks[i]->deleted = 1;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
+{
+    int old_count = cbList->count;
+    int i;
+    for (i = 0 ; i < cbList->count ; i++) {
+        if (cbList->callbacks[i]->deleted) {
+            virFreeCallback freecb = cbList->callbacks[i]->freecb;
+            if (freecb)
+                (*freecb)(cbList->callbacks[i]->opaque);
+            virUnrefConnect(cbList->callbacks[i]->conn);
+            VIR_FREE(cbList->callbacks[i]);
+
+            if (i < (cbList->count - 1))
+                memmove(cbList->callbacks + i,
+                        cbList->callbacks + i + 1,
+                        sizeof(*(cbList->callbacks)) *
+                                (cbList->count - (i + 1)));
+            cbList->count--;
+            i--;
+        }
+    }
+    if (cbList->count < old_count &&
+        VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) {
+        ; /* Failure to reduce memory allocation isn't fatal */
+    }
+    return 0;
+}
+
 /**
  * virDomainEventCallbackListAdd:
  * @conn: pointer to the connection
@@ -182,6 +225,62 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
     return 0;
 }
 
+void virDomainEventFree(virDomainEventPtr event)
+{
+    if (!event)
+        return;
+
+    VIR_FREE(event->name);
+    VIR_FREE(event);
+}
+
+
+virDomainEventQueuePtr virDomainEventQueueNew(void)
+{
+    virDomainEventQueuePtr ret;
+
+    if (VIR_ALLOC(ret) < 0)
+        return NULL;
+
+    return ret;
+}
+
+virDomainEventPtr virDomainEventNew(int id, const char *name,
+                                    const unsigned char *uuid,
+                                    int type, int detail)
+{
+    virDomainEventPtr event;
+
+    if (VIR_ALLOC(event) < 0)
+        return NULL;
+
+    event->type = type;
+    event->detail = detail;
+    if (!(event->name = strdup(name))) {
+        VIR_FREE(event);
+        return NULL;
+    }
+    event->id = id;
+    memcpy(event->uuid, uuid, VIR_UUID_BUFLEN);
+
+    return event;
+}
+
+virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail)
+{
+    return virDomainEventNew(dom->id, dom->name, dom->uuid, type, detail);
+}
+
+virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail)
+{
+    return virDomainEventNewFromDef(obj->def, type, detail);
+}
+
+virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail)
+{
+    return virDomainEventNew(def->id, def->name, def->uuid, type, detail);
+}
+
 /**
  * virDomainEventQueueFree:
  * @queue: pointer to the queue
@@ -192,14 +291,18 @@ void
 virDomainEventQueueFree(virDomainEventQueuePtr queue)
 {
     int i;
-    for ( i=0 ; i<queue->count ; i++ ) {
-        VIR_FREE(queue->events[i]);
+    if (!queue)
+        return;
+
+    for (i = 0; i < queue->count ; i++) {
+        virDomainEventFree(queue->events[i]);
     }
+    VIR_FREE(queue->events);
     VIR_FREE(queue);
 }
 
 /**
- * virDomainEventCallbackQueuePop:
+ * virDomainEventQueuePop:
  * @evtQueue: the queue of events
  *
  * Internal function to pop off, and return the front of the queue
@@ -208,7 +311,7 @@ virDomainEventQueueFree(virDomainEventQueuePtr queue)
  * Returns: virDomainEventPtr on success NULL on failure.
  */
 virDomainEventPtr
-virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
+virDomainEventQueuePop(virDomainEventQueuePtr evtQueue)
 {
     virDomainEventPtr ret;
 
@@ -232,9 +335,8 @@ virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
 }
 
 /**
- * virDomainEventCallbackQueuePush:
+ * virDomainEventQueuePush:
  * @evtQueue: the dom event queue
- * @dom: the domain to add
  * @event: the event to add
  *
  * Internal function to push onto the back of an virDomainEventQueue
@@ -242,37 +344,76 @@ virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
  * Returns: 0 on success, -1 on failure
  */
 int
-virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue,
-                                virDomainPtr dom,
-                                int event,
-                                int detail)
+virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
+                        virDomainEventPtr event)
 {
-    virDomainEventPtr domEvent;
-
-    /* Check incoming */
-    if ( !evtQueue ) {
-        return -1;
-    }
-
-    /* Allocate new event */
-    if (VIR_ALLOC(domEvent) < 0) {
-        DEBUG0("Error allocating event");
+    if (!evtQueue) {
         return -1;
     }
-    domEvent->dom = dom;
-    domEvent->event = event;
-    domEvent->detail = detail;
 
     /* Make space on queue */
     if (VIR_REALLOC_N(evtQueue->events,
                       evtQueue->count + 1) < 0) {
         DEBUG0("Error reallocating queue");
-        VIR_FREE(domEvent);
         return -1;
     }
 
-    evtQueue->events[evtQueue->count] = domEvent;
+    evtQueue->events[evtQueue->count] = event;
     evtQueue->count++;
     return 0;
 }
 
+
+void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
+                                       virDomainEventPtr event,
+                                       virConnectDomainEventCallback 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);
+    }
+}
+
+
+void virDomainEventDispatch(virDomainEventPtr event,
+                            virDomainEventCallbackListPtr callbacks,
+                            virDomainEventDispatchFunc dispatch,
+                            void *opaque)
+{
+    int i;
+    /* Cache this now, since we may be dropping the lock,
+       and have more callbacks added. We're guarenteed not
+       to have any removed */
+    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);
+        }
+    }
+}
+
+
+void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
+                                 virDomainEventCallbackListPtr callbacks,
+                                 virDomainEventDispatchFunc dispatch,
+                                 void *opaque)
+{
+    int i;
+
+    for (i = 0 ; i < queue->count ; i++) {
+        virDomainEventDispatch(queue->events[i], callbacks, dispatch, opaque);
+        virDomainEventFree(queue->events[i]);
+    }
+    VIR_FREE(queue->events);
+    queue->count = 0;
+}
index 32ae0dbc4798b5e10de15b803a2d663e05219fbd..f29e42e77faaec2ad83a19da581d38c1fd0f9075 100644 (file)
 
 #include "internal.h"
 
-
 #ifndef __DOMAIN_EVENT_H__
 #define __DOMAIN_EVENT_H__
 
+#include "domain_conf.h"
+
 struct _virDomainEventCallback {
     virConnectPtr conn;
     virConnectDomainEventCallback cb;
     void *opaque;
     virFreeCallback freecb;
-
+    int deleted;
 };
 typedef struct _virDomainEventCallback virDomainEventCallback;
 typedef virDomainEventCallback *virDomainEventCallbackPtr;
@@ -58,13 +59,20 @@ int virDomainEventCallbackListRemove(virConnectPtr conn,
 int virDomainEventCallbackListRemoveConn(virConnectPtr conn,
                                          virDomainEventCallbackListPtr cbList);
 
+int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
+                                         virDomainEventCallbackListPtr cbList,
+                                         virConnectDomainEventCallback callback);
+int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList);
+
 /**
  * Dispatching domain events that come in while
  * in a call / response rpc
  */
 struct _virDomainEvent {
-    virDomainPtr dom;
-    int event;
+    int id;
+    char *name;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    int type;
     int detail;
 };
 typedef struct _virDomainEvent virDomainEvent;
@@ -77,15 +85,40 @@ struct _virDomainEventQueue {
 typedef struct _virDomainEventQueue virDomainEventQueue;
 typedef virDomainEventQueue *virDomainEventQueuePtr;
 
-int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue,
-                                    virDomainPtr dom,
-                                    int event,
-                                    int detail);
+virDomainEventQueuePtr virDomainEventQueueNew(void);
+
+virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail);
+virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail);
+virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail);
+virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail);
+
+int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
+                            virDomainEventPtr event);
 
 virDomainEventPtr
-virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue);
+virDomainEventQueuePop(virDomainEventQueuePtr evtQueue);
 
+void virDomainEventFree(virDomainEventPtr event);
 void virDomainEventQueueFree(virDomainEventQueuePtr queue);
 
+typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
+                                           virDomainEventPtr event,
+                                           virConnectDomainEventCallback cb,
+                                           void *cbopaque,
+                                           void *opaque);
+void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
+                                       virDomainEventPtr event,
+                                       virConnectDomainEventCallback cb,
+                                       void *cbopaque,
+                                       void *opaque);
+
+void virDomainEventDispatch(virDomainEventPtr event,
+                            virDomainEventCallbackListPtr cbs,
+                            virDomainEventDispatchFunc dispatch,
+                            void *opaque);
+void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
+                                 virDomainEventCallbackListPtr cbs,
+                                 virDomainEventDispatchFunc dispatch,
+                                 void *opaque);
 
 #endif
index 9aa1497f7cf0e4d320f14ee0f21ef88b4c431fbd..ece4058354642847e9ce427aa0d2c2e99943199f 100644 (file)
@@ -383,9 +383,21 @@ LIBVIRT_PRIVATE_@VERSION@ {
        virDomainEventCallbackListFree;
        virDomainEventCallbackListRemove;
        virDomainEventCallbackListRemoveConn;
+       virDomainEventCallbackListMarkDelete;
+       virDomainEventCallbackListPurgeMarked;
+       virDomainEventQueueNew;
        virDomainEventQueueFree;
-       virDomainEventCallbackQueuePop;
-       virDomainEventCallbackQueuePush;
+       virDomainEventQueuePop;
+       virDomainEventQueuePush;
+       virDomainEventNew;
+       virDomainEventNewFromDom;
+       virDomainEventNewFromObj;
+       virDomainEventNewFromDef;
+       virDomainEventFree;
+       virDomainEventDispatchDefaultFunc;
+       virDomainEventDispatch;
+       virDomainEventQueueDispatch;
+
 
 
        /* driver.h */
index 58ea321b45c205763502e2a6c1d49b29f1210b93..36d09d15dc458c1e88035b133ce77090412a11b7 100644 (file)
@@ -71,6 +71,9 @@ struct qemud_driver {
 
     /* An array of callbacks */
     virDomainEventCallbackListPtr domainEventCallbacks;
+    virDomainEventQueuePtr domainEventQueue;
+    int domainEventTimer;
+    int domainEventDispatching;
 };
 
 /* Port numbers used for KVM migration. */
index cc7b6c0368a7e6361115192853f8d47dbb7f722e..7c45122630aabc57cf6e5fd6a4fe51d4c2e3a2a3 100644 (file)
@@ -115,10 +115,10 @@ static int qemudSetNonBlock(int fd) {
 }
 
 
-static void qemudDomainEventDispatch (struct qemud_driver *driver,
-                                      virDomainObjPtr vm,
-                                      int event,
-                                      int detail);
+
+static void qemuDomainEventFlush(int timer, void *opaque);
+static void qemuDomainEventQueue(struct qemud_driver *driver,
+                                 virDomainEventPtr event);
 
 static void qemudDispatchVMEvent(int watch,
                                  int fd,
@@ -160,8 +160,12 @@ qemudAutostartConfigs(struct qemud_driver *driver) {
                          vm->def->name,
                          err ? err->message : NULL);
             } else {
-                qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED,
-                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
+                virDomainEventPtr event =
+                    virDomainEventNewFromObj(vm,
+                                             VIR_DOMAIN_EVENT_STARTED,
+                                             VIR_DOMAIN_EVENT_STARTED_BOOTED);
+                if (event)
+                    qemuDomainEventQueue(driver, event);
             }
         }
         virDomainObjUnlock(vm);
@@ -192,6 +196,12 @@ qemudStartup(void) {
     /* Init callback list */
     if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
         goto out_of_memory;
+    if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
+        goto out_of_memory;
+
+    if ((qemu_driver->domainEventTimer =
+         virEventAddTimeout(-1, qemuDomainEventFlush, qemu_driver, NULL)) < 0)
+        goto error;
 
     if (!uid) {
         if (asprintf(&qemu_driver->logDir,
@@ -265,10 +275,14 @@ static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
 {
     struct qemud_driver *driver = opaque;
 
-    if (newVM)
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_DEFINED,
-                                 VIR_DOMAIN_EVENT_DEFINED_ADDED);
+    if (newVM) {
+        virDomainEventPtr event =
+            virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_DEFINED,
+                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
+        if (event)
+            qemuDomainEventQueue(driver, event);
+    }
 }
 
 /**
@@ -359,6 +373,10 @@ qemudShutdown(void) {
 
     /* Free domain callback list */
     virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
+    virDomainEventQueueFree(qemu_driver->domainEventQueue);
+
+    if (qemu_driver->domainEventTimer != -1)
+        virEventRemoveTimeout(qemu_driver->domainEventTimer);
 
     if (qemu_driver->brctl)
         brShutdown(qemu_driver->brctl);
@@ -1075,6 +1093,7 @@ static void
 qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
     struct qemud_driver *driver = opaque;
     virDomainObjPtr vm = NULL;
+    virDomainEventPtr event = NULL;
     unsigned int i;
     int quit = 0, failed = 0;
 
@@ -1107,12 +1126,12 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
     }
 
     if (failed || quit) {
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_STOPPED,
+                                         quit ?
+                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
+                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
         qemudShutdownVMDaemon(NULL, driver, vm);
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_STOPPED,
-                                 quit ?
-                                 VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
-                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
         if (!vm->persistent) {
             virDomainRemoveInactive(&driver->domains,
                                     vm);
@@ -1123,6 +1142,8 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
 }
 
@@ -1591,6 +1612,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
     virDomainDefPtr def;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
 
     qemuDriverLock(driver);
     if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
@@ -1627,9 +1649,10 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
         vm = NULL;
         goto cleanup;
     }
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STARTED,
-                             VIR_DOMAIN_EVENT_STARTED_BOOTED);
+
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STARTED,
+                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
     if (dom) dom->id = vm->def->id;
@@ -1638,6 +1661,8 @@ cleanup:
     virDomainDefFree(def);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return dom;
 }
@@ -1648,6 +1673,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
     char *info;
     virDomainObjPtr vm;
     int ret = -1;
+    virDomainEventPtr event = NULL;
 
     qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
@@ -1670,9 +1696,9 @@ static int qemudDomainSuspend(virDomainPtr dom) {
         }
         vm->state = VIR_DOMAIN_PAUSED;
         qemudDebug("Reply %s", info);
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_SUSPENDED,
-                                 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_SUSPENDED,
+                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
         VIR_FREE(info);
     }
     ret = 0;
@@ -1680,6 +1706,12 @@ static int qemudDomainSuspend(virDomainPtr dom) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+
+    if (event) {
+        qemuDriverLock(driver);
+        qemuDomainEventQueue(driver, event);
+        qemuDriverUnlock(driver);
+    }
     return ret;
 }
 
@@ -1689,6 +1721,7 @@ static int qemudDomainResume(virDomainPtr dom) {
     char *info;
     virDomainObjPtr vm;
     int ret = -1;
+    virDomainEventPtr event = NULL;
 
     qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
@@ -1712,9 +1745,9 @@ static int qemudDomainResume(virDomainPtr dom) {
         }
         vm->state = VIR_DOMAIN_RUNNING;
         qemudDebug("Reply %s", info);
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_RESUMED,
-                                 VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_RESUMED,
+                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
         VIR_FREE(info);
     }
     ret = 0;
@@ -1722,6 +1755,11 @@ static int qemudDomainResume(virDomainPtr dom) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event) {
+        qemuDriverLock(driver);
+        qemuDomainEventQueue(driver, event);
+        qemuDriverUnlock(driver);
+    }
     return ret;
 }
 
@@ -1761,6 +1799,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
     struct qemud_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
     int ret = -1;
+    virDomainEventPtr event = NULL;
 
     qemuDriverLock(driver);
     vm  = virDomainFindByID(&driver->domains, dom->id);
@@ -1771,9 +1810,9 @@ static int qemudDomainDestroy(virDomainPtr dom) {
     }
 
     qemudShutdownVMDaemon(dom->conn, driver, vm);
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STOPPED,
-                             VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STOPPED,
+                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
     if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
@@ -1784,6 +1823,8 @@ static int qemudDomainDestroy(virDomainPtr dom) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -2053,6 +2094,7 @@ static int qemudDomainSave(virDomainPtr dom,
     char *xml = NULL;
     struct qemud_save_header header;
     int ret = -1;
+    virDomainEventPtr event = NULL;
 
     memset(&header, 0, sizeof(header));
     memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@@ -2154,9 +2196,9 @@ static int qemudDomainSave(virDomainPtr dom,
 
     /* Shut it down */
     qemudShutdownVMDaemon(dom->conn, driver, vm);
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STOPPED,
-                             VIR_DOMAIN_EVENT_STOPPED_SAVED);
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STOPPED,
+                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
     if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
@@ -2175,6 +2217,8 @@ cleanup:
         unlink(path);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -2412,6 +2456,7 @@ static int qemudDomainRestore(virConnectPtr conn,
     int ret = -1;
     char *xml = NULL;
     struct qemud_save_header header;
+    virDomainEventPtr event = NULL;
 
     qemuDriverLock(driver);
     /* Verify the header and read the XML */
@@ -2495,9 +2540,9 @@ static int qemudDomainRestore(virConnectPtr conn,
         goto cleanup;
     }
 
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STARTED,
-                             VIR_DOMAIN_EVENT_STARTED_RESTORED);
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STARTED,
+                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
 
     /* If it was running before, resume it now. */
     if (header.was_running) {
@@ -2519,6 +2564,8 @@ cleanup:
         close(fd);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -2599,6 +2646,7 @@ static int qemudDomainStart(virDomainPtr dom) {
     struct qemud_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
     int ret = -1;
+    virDomainEventPtr event = NULL;
 
     qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -2612,13 +2660,18 @@ static int qemudDomainStart(virDomainPtr dom) {
 
     ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL);
     if (ret != -1)
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_STARTED,
-                                 VIR_DOMAIN_EVENT_STARTED_BOOTED);
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_STARTED,
+                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
 
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event) {
+        qemuDriverLock(driver);
+        qemuDomainEventQueue(driver, event);
+        qemuDriverUnlock(driver);
+    }
     return ret;
 }
 
@@ -2628,6 +2681,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     virDomainDefPtr def;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
     int newVM = 1;
 
     qemuDriverLock(driver);
@@ -2657,11 +2711,11 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
         goto cleanup;
     }
 
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_DEFINED,
-                             newVM ?
-                             VIR_DOMAIN_EVENT_DEFINED_ADDED :
-                             VIR_DOMAIN_EVENT_DEFINED_UPDATED);
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_DEFINED,
+                                     newVM ?
+                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
+                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
     if (dom) dom->id = vm->def->id;
@@ -2669,6 +2723,8 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return dom;
 }
@@ -2676,6 +2732,7 @@ cleanup:
 static int qemudDomainUndefine(virDomainPtr dom) {
     struct qemud_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     int ret = -1;
 
     qemuDriverLock(driver);
@@ -2702,9 +2759,9 @@ static int qemudDomainUndefine(virDomainPtr dom) {
     if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0)
         goto cleanup;
 
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_UNDEFINED,
-                             VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_UNDEFINED,
+                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
 
     virDomainRemoveInactive(&driver->domains,
                             vm);
@@ -2714,6 +2771,8 @@ static int qemudDomainUndefine(virDomainPtr dom) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -3709,41 +3768,69 @@ qemudDomainEventDeregister (virConnectPtr conn,
     int ret;
 
     qemuDriverLock(driver);
-    ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
-                                           callback);
+    if (driver->domainEventDispatching)
+        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
+                                                   callback);
+    else
+        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
+                                               callback);
     qemuDriverUnlock(driver);
 
     return ret;
 }
 
-static void qemudDomainEventDispatch (struct qemud_driver *driver,
-                                      virDomainObjPtr vm,
-                                      int event,
-                                      int detail)
+static void qemuDomainEventDispatchFunc(virConnectPtr conn,
+                                        virDomainEventPtr event,
+                                        virConnectDomainEventCallback cb,
+                                        void *cbopaque,
+                                        void *opaque)
 {
-    int i;
-    virDomainEventCallbackListPtr cbList;
-
-    cbList = driver->domainEventCallbacks;
-
-    for(i=0 ; i < cbList->count ; i++) {
-        if(cbList->callbacks[i] && cbList->callbacks[i]->cb) {
-            virConnectPtr conn = cbList->callbacks[i]->conn;
-            virDomainPtr dom = virGetDomain(conn, vm->def->name,
-                                            vm->def->uuid);
-            if (dom) {
-                dom->id = virDomainIsActive(vm) ? vm->def->id : -1;
-                DEBUG("Dispatching callback %p %p event %d detail %d",
-                      cbList->callbacks[i],
-                      cbList->callbacks[i]->cb, event, detail);
-                cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
-                                         dom, event, detail,
-                                         cbList->callbacks[i]->opaque);
-                virDomainFree(dom);
-            }
-        }
-    }
+    struct qemud_driver *driver = opaque;
 
+    /* Drop the lock whle dispatching, for sake of re-entrancy */
+    qemuDriverUnlock(driver);
+    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+    qemuDriverLock(driver);
+}
+
+static void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
+{
+    struct qemud_driver *driver = opaque;
+    virDomainEventQueue tempQueue;
+
+    qemuDriverLock(driver);
+
+    driver->domainEventDispatching = 1;
+
+    /* Copy the queue, so we're reentrant safe */
+    tempQueue.count = driver->domainEventQueue->count;
+    tempQueue.events = driver->domainEventQueue->events;
+    driver->domainEventQueue->count = 0;
+    driver->domainEventQueue->events = NULL;
+
+    virEventUpdateTimeout(driver->domainEventTimer, -1);
+    virDomainEventQueueDispatch(&tempQueue,
+                                driver->domainEventCallbacks,
+                                qemuDomainEventDispatchFunc,
+                                driver);
+
+    /* Purge any deleted callbacks */
+    virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);
+
+    driver->domainEventDispatching = 0;
+    qemuDriverUnlock(driver);
+}
+
+
+/* driver must be locked before calling */
+static void qemuDomainEventQueue(struct qemud_driver *driver,
+                                 virDomainEventPtr event)
+{
+    if (virDomainEventQueuePush(driver->domainEventQueue,
+                                event) < 0)
+        virDomainEventFree(event);
+    if (qemu_driver->domainEventQueue->count == 1)
+        virEventUpdateTimeout(driver->domainEventTimer, 0);
 }
 
 /* Migration support. */
@@ -3771,6 +3858,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
     char hostname [HOST_NAME_MAX+1];
     char migrateFrom [64];
     const char *p;
+    virDomainEventPtr event = NULL;
     int ret = -1;;
 
     *uri_out = NULL;
@@ -3892,9 +3980,10 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
         }
         goto cleanup;
     }
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STARTED,
-                             VIR_DOMAIN_EVENT_STARTED_MIGRATED);
+
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STARTED,
+                                     VIR_DOMAIN_EVENT_STARTED_MIGRATED);
     ret = 0;
 
 cleanup:
@@ -3904,6 +3993,8 @@ cleanup:
     }
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -3920,6 +4011,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
 {
     struct qemud_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     char *safe_uri;
     char cmd[HOST_NAME_MAX+50];
     char *info = NULL;
@@ -3946,9 +4038,12 @@ qemudDomainMigratePerform (virDomainPtr dom,
         DEBUG ("stop reply: %s", info);
         VIR_FREE(info);
 
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_SUSPENDED,
-                                 VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_SUSPENDED,
+                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
+        if (event)
+            qemuDomainEventQueue(driver, event);
+        event = NULL;
     }
 
     if (resource > 0) {
@@ -3987,9 +4082,10 @@ qemudDomainMigratePerform (virDomainPtr dom,
 
     /* Clean up the source domain. */
     qemudShutdownVMDaemon (dom->conn, driver, vm);
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STOPPED,
-                             VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
+
+    event = virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_STOPPED,
+                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
     if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains, vm);
         vm = NULL;
@@ -4000,6 +4096,8 @@ cleanup:
     VIR_FREE(info);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -4017,6 +4115,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
     struct qemud_driver *driver = dconn->privateData;
     virDomainObjPtr vm;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
     char *info = NULL;
 
     qemuDriverLock(driver);
@@ -4034,14 +4133,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
         dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
         VIR_FREE(info);
         vm->state = VIR_DOMAIN_RUNNING;
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_RESUMED,
-                                 VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_RESUMED,
+                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
     } else {
         qemudShutdownVMDaemon (dconn, driver, vm);
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_STOPPED,
-                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
+        event = virDomainEventNewFromObj(vm,
+                                         VIR_DOMAIN_EVENT_STOPPED,
+                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
         if (!vm->persistent) {
             virDomainRemoveInactive(&driver->domains, vm);
             vm = NULL;
@@ -4051,6 +4150,8 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
     qemuDriverUnlock(driver);
     return dom;
 }
index 7bf8766a86810f6c25f91ed36c08c014d1104d38..1d0c5ac337dda379834bc0470b91fa4a290b3f10 100644 (file)
@@ -5484,59 +5484,62 @@ remoteRegister (void)
  *
  * Read the event data off the wire
  */
-static int
-remoteDomainReadEvent(virConnectPtr conn, XDR *xdr,
-                      virDomainPtr *dom, int *event, int *detail)
+static virDomainEventPtr
+remoteDomainReadEvent(virConnectPtr conn, XDR *xdr)
 {
     remote_domain_event_ret ret;
+    virDomainPtr dom;
+    virDomainEventPtr event = NULL;
     memset (&ret, 0, sizeof ret);
 
     /* unmarshall parameters, and process it*/
     if (! xdr_remote_domain_event_ret(xdr, &ret) ) {
         error (conn, VIR_ERR_RPC,
                _("remoteDomainProcessEvent: unmarshalling ret"));
-        return -1;
+        return NULL;
     }
 
-    *dom = get_nonnull_domain(conn,ret.dom);
-    *event = ret.event;
-    *detail = ret.detail;
+    dom = get_nonnull_domain(conn,ret.dom);
+    if (!dom)
+        return NULL;
 
-    return 0;
+    event = virDomainEventNewFromDom(dom, ret.event, ret.detail);
+
+    virDomainFree(dom);
+    return event;
 }
 
 static void
 remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr)
 {
-    virDomainPtr dom;
-    int event, detail, i;
     struct private_data *priv = conn->privateData;
+    virDomainEventPtr event;
 
-    if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) {
-        DEBUG0("Calling domain event callbacks (no queue)");
-        for(i=0 ; i < priv->callbackList->count ; i++) {
-            if (priv->callbackList->callbacks[i] )
-                priv->callbackList->callbacks[i]->cb(
-                    conn, dom, event, detail,
-                    priv->callbackList->callbacks[i]->opaque);
-        }
-    }
+    event = remoteDomainReadEvent(conn, xdr);
+    if (!event)
+        return;
+
+    DEBUG0("Calling domain event callbacks (no queue)");
+    virDomainEventDispatch(event, priv->callbackList,
+                           virDomainEventDispatchDefaultFunc, NULL);
+    virDomainEventFree(event);
 }
 
 static void
 remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr)
 {
-    virDomainPtr dom;
-    int event, detail;
     struct private_data *priv = conn->privateData;
+    virDomainEventPtr event;
 
-    if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail))
-    {
-        if( virDomainEventCallbackQueuePush(priv->domainEvents,
-                                            dom, event, detail) < 0 ) {
-            DEBUG("%s", "Error adding event to queue");
-        }
-    }
+    event = remoteDomainReadEvent(conn, xdr);
+    if (!event)
+        return;
+
+    if (virDomainEventQueuePush(priv->domainEvents,
+                                event) < 0)
+        DEBUG0("Error adding event to queue");
+
+    virDomainEventFree(event);
 }
 
 /** remoteDomainEventFired:
@@ -5618,26 +5621,10 @@ remoteDomainEventFired(int watch,
 void
 remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
 {
-    int i;
-    virDomainEventPtr domEvent;
-    void *user_data = NULL;
     virConnectPtr conn = opaque;
     struct private_data *priv = conn->privateData;
 
-    while( (domEvent = virDomainEventCallbackQueuePop(priv->domainEvents)) ) {
-        DEBUG("   Flushing %p", domEvent);
-        for (i=0 ; i < priv->callbackList->count ; i++) {
-           if( priv->callbackList->callbacks[i] ) {
-               user_data = priv->callbackList->callbacks[i]->opaque;
-               priv->callbackList->callbacks[i]->cb(domEvent->dom->conn,
-                                                    domEvent->dom,
-                                                    domEvent->event,
-                                                    domEvent->detail,
-                                                    user_data);
-           }
-        }
-        VIR_FREE(domEvent);
-    }
-
+    virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList,
+                                virDomainEventDispatchDefaultFunc, NULL);
     virEventUpdateTimeout(priv->eventFlushTimer, -1);
 }
index a7ecef0a465990cababc5e8f5c81db86ab15a07b..9d433e47084799dabb8c240bb8ad15567d8c78a5 100644 (file)
@@ -92,30 +92,33 @@ struct xenUnifiedDriver xenInotifyDriver = {
     NULL, /* domainSetSchedulerParameters */
 };
 
-static virDomainPtr
-xenInotifyXenCacheLookup(virConnectPtr conn, const char *filename) {
+static int
+xenInotifyXenCacheLookup(const char *filename,
+                         char **name, unsigned char *uuid) {
     xenXMConfCachePtr entry;
-    virDomainPtr dom;
 
     if (!(entry = virHashLookup(xenXMGetConfigCache(), filename))) {
         DEBUG("No config found for %s", filename);
-        return NULL;
+        return -1;
     }
 
-    if(!(dom = virGetDomain(conn, entry->def->name,
-                    (unsigned char*)entry->def->uuid))) {
+    *name = strdup(entry->def->name);
+    memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN);
+
+    if (!*name) {
         DEBUG0("Error getting dom from def");
-        return NULL;
+        return -1;
     }
-    return dom;
+    return 0;
 }
 
-static virDomainPtr
-xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) {
+static int
+xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename,
+                               char **name, unsigned char *uuid) {
     int i;
     virDomainPtr dom;
     const char *uuid_str;
-    unsigned char uuid[VIR_UUID_BUFLEN];
+    unsigned char rawuuid[VIR_UUID_BUFLEN];
 
     /* xend is managing domains. we will get
     * a filename in the manner:
@@ -123,57 +126,70 @@ xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) {
     */
     uuid_str = filename + strlen(LIBVIRTD_DOMAINS_DIR) + 1;
 
-    if (virUUIDParse(uuid_str, uuid) < 0) {
+    if (virUUIDParse(uuid_str, rawuuid) < 0) {
         virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
                            "parsing uuid %s", uuid_str);
-        return (NULL);
+        return -1;
     }
     /* call directly into xend here, as driver may not yet
        be set during open while we are building our
        initial list of domains */
     DEBUG("Looking for dom with uuid: %s", uuid_str);
-    if(!(dom = xenDaemonLookupByUUID(conn, uuid))) {
+    /* XXX Should not have to go via a virDomainPtr obj instance */
+    if(!(dom = xenDaemonLookupByUUID(conn, rawuuid))) {
         /* If we are here, the domain has gone away.
            search for, and create a domain from the stored
            list info */
         for (i=0; i<configInfoList->count; i++) {
             if (!memcmp(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
-                if(!(dom = virGetDomain(conn, configInfoList->doms[i]->name,
-                                        configInfoList->doms[i]->uuid))) {
+                *name = strdup(configInfoList->doms[i]->name);
+                if (!*name) {
                     virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
                                        "finding dom for %s", uuid_str);
-                    return NULL;
+                    return -1;
                 }
+                memcpy(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN);
                 DEBUG0("Found dom on list");
-                return dom;
+                return 0;
             }
         }
         virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                       "%s", _("finding dom on config list"));
-        return NULL;
+                           "%s", _("finding dom on config list"));
+        return -1;
     }
 
+    if (!(*name = strdup(dom->name)))
+        return -1;
+    memcpy(uuid, dom->uuid, VIR_UUID_BUFLEN);
+    virDomainFree(dom);
     /* succeeded too find domain by uuid */
-    return dom;
+    return 0;
 }
 
-static virDomainPtr
-xenInotifyDomainLookup(virConnectPtr conn, const char *filename) {
-    virDomainPtr dom;
-    virDomainInfo info;
-
-    dom = useXenConfigCache ? xenInotifyXenCacheLookup(conn, filename) :
-                              xenInotifyXendDomainsDirLookup(conn, filename);
-
-    if(dom) {
-        if ( (useXenConfigCache ? xenXMDomainGetInfo(dom, &info) :
-                                  xenDaemonDomainGetInfo(dom, &info)) < 0)
-            dom->id = -1;
-        else
-            dom->id = (info.state == VIR_DOMAIN_SHUTOFF) ? -1 : dom->id;
-        return dom;
-    }
-    return NULL;
+static int
+xenInotifyDomainLookup(virConnectPtr conn,
+                       const char *filename,
+                       char **name, unsigned char *uuid) {
+    if (useXenConfigCache)
+        return xenInotifyXenCacheLookup(filename, name, uuid);
+    else
+        return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
+}
+
+static virDomainEventPtr
+xenInotifyDomainEventFromFile(virConnectPtr conn,
+                              const char *filename,
+                              int type, int detail) {
+    virDomainEventPtr event;
+    char *name = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+
+    if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0)
+        return NULL;
+
+    event = virDomainEventNew(-1, name, uuid, type, detail);
+    VIR_FREE(name);
+    return event;
 }
 
 static int
@@ -215,21 +231,22 @@ xenInotifyXendDomainsDirRemoveEntry(virConnectPtr conn ATTRIBUTE_UNUSED,
 static int
 xenInotifyXendDomainsDirAddEntry(virConnectPtr conn,
                                  const char *fname) {
-    virDomainPtr dom = xenInotifyDomainLookup(conn, fname);
-    if(!dom) {
+    char *name = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) {
         virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("Error looking up domain"));
+                           "%s", _("Error looking up domain"));
         return -1;
     }
 
     if( xenUnifiedAddDomainInfo(configInfoList,
-                                dom->id, dom->name, dom->uuid) < 0) {
+                                -1, name, uuid) < 0) {
         virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("Error adding file to config cache"));
-        virUnrefDomain(dom);
+        VIR_FREE(name);
         return -1;
     }
-    virUnrefDomain(dom);
+    VIR_FREE(name);
     return 0;
 }
 
@@ -260,7 +277,6 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
     char *tmp, *name;
     virConnectPtr conn = (virConnectPtr) data;
     xenUnifiedPrivatePtr priv = NULL;
-    virDomainPtr dom = NULL;
 
     DEBUG0("got inotify event");
 
@@ -300,16 +316,15 @@ reread:
         snprintf(fname, 1024, "%s/%s", configDir, name);
 
         if (e->mask & (IN_DELETE | IN_MOVED_FROM)) {
-            if (!(dom = xenInotifyDomainLookup(conn, fname))) {
+            virDomainEventPtr event =
+                xenInotifyDomainEventFromFile(conn, fname,
+                                              VIR_DOMAIN_EVENT_UNDEFINED,
+                                              VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
+            if (!event)
+                xenUnifiedDomainEventDispatch(conn->privateData, event);
+            else
                 virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("looking up dom"));
-                continue;
-            }
-
-            xenUnifiedDomainEventDispatch(conn->privateData, dom,
-                                          VIR_DOMAIN_EVENT_UNDEFINED,
-                                          VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
-
+                                   "%s", _("looking up dom"));
 
             if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
                 virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
@@ -317,21 +332,23 @@ reread:
                 return;
             }
         } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
+            virDomainEventPtr event;
             if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
                 virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Error adding file to config cache"));
                 return;
             }
 
-            if (!(dom = xenInotifyDomainLookup(conn, fname))) {
+            event = xenInotifyDomainEventFromFile(conn, fname,
+                                                  VIR_DOMAIN_EVENT_DEFINED,
+                                                  VIR_DOMAIN_EVENT_DEFINED_ADDED);
+
+            if (event)
+                xenUnifiedDomainEventDispatch(conn->privateData, event);
+            else
                 virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("looking up dom"));
-                continue;
-            }
+                                   "%s", _("looking up dom"));
 
-            xenUnifiedDomainEventDispatch(conn->privateData, dom,
-                                          VIR_DOMAIN_EVENT_DEFINED,
-                                          VIR_DOMAIN_EVENT_DEFINED_ADDED);
         }
 
     }
index ca05d753139e97ec5d11cdd95303d9c0f5e996ae..a60bc799f498606792012904f9a67d5983af271e 100644 (file)
@@ -1583,28 +1583,14 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
  *
  */
 void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
-                                    virDomainPtr dom,
-                                    int event,
-                                    int detail)
+                                    virDomainEventPtr event)
 {
-    int i;
-    virDomainEventCallbackListPtr cbList;
-
-    if(!priv) return;
-
-    cbList = priv->domainEventCallbacks;
-    if(!cbList) return;
+    if (!priv || !priv->domainEventCallbacks)
+        return;
 
-    for(i=0 ; i < cbList->count ; i++) {
-        if(cbList->callbacks[i] && cbList->callbacks[i]->cb) {
-            if (dom) {
-                DEBUG("Dispatching callback %p %p event %d",
-                        cbList->callbacks[i],
-                        cbList->callbacks[i]->cb, event);
-                cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
-                                         dom, event, detail,
-                                         cbList->callbacks[i]->opaque);
-            }
-        }
-    }
+    virDomainEventDispatch(event,
+                           priv->domainEventCallbacks,
+                           virDomainEventDispatchDefaultFunc,
+                           NULL);
+    virDomainEventFree(event);
 }
index 831cefc3c4cbef61294433fd231fa54fc3adc274..f81b0144458111106c4e4135400e8df6cddab6ca 100644 (file)
@@ -182,9 +182,7 @@ int  xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
                                 int id, char *name,
                                 unsigned char *uuid);
 void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
-                                    virDomainPtr dom,
-                                    int event,
-                                    int detail);
+                                    virDomainEventPtr event);
 unsigned long xenUnifiedVersion(void);
 
 #endif /* __VIR_XEN_UNIFIED_H__ */
index ae773805d282c9300198dddb66e7009dca446242..184cfe5bd5a3cf91d2e28d79b5288b455eda0774 100644 (file)
@@ -1215,7 +1215,7 @@ retry:
         }
 
         if (!found) {
-            virDomainPtr dom;
+            virDomainEventPtr event;
             char *name;
             unsigned char uuid[VIR_UUID_BUFLEN];
 
@@ -1229,21 +1229,15 @@ retry:
                 continue;
             }
 
-            dom = virGetDomain(conn, name, uuid);
-            if (dom) {
-                dom->id = new_domids[i];
+            event = virDomainEventNew(new_domids[i], name, uuid,
+                                      VIR_DOMAIN_EVENT_STARTED,
+                                      VIR_DOMAIN_EVENT_STARTED_BOOTED);
+            if (event)
+                xenUnifiedDomainEventDispatch(priv, event);
 
-                /* This domain was not in the old list. Emit an event */
-                xenUnifiedDomainEventDispatch(priv, dom,
-                                              VIR_DOMAIN_EVENT_STARTED,
-                                              VIR_DOMAIN_EVENT_STARTED_BOOTED);
-
-                /* Add to the list */
-                xenUnifiedAddDomainInfo(activeDomainList,
-                                        new_domids[i], name, uuid);
-
-                virUnrefDomain(dom);
-            }
+            /* Add to the list */
+            xenUnifiedAddDomainInfo(activeDomainList,
+                                    new_domids[i], name, uuid);
 
             VIR_FREE(name);
         }
@@ -1299,24 +1293,22 @@ retry:
         }
 
         if (!found) {
-            virDomainPtr dom = virGetDomain(conn,
-                                            activeDomainList->doms[j]->name,
-                                            activeDomainList->doms[j]->uuid);
-            if(dom) {
-                dom->id = -1;
-                /* This domain was not in the new list. Emit an event */
-                xenUnifiedDomainEventDispatch(priv, dom,
-                                              VIR_DOMAIN_EVENT_STOPPED,
-                                              VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
-                 /* Remove from the list */
-                xenUnifiedRemoveDomainInfo(activeDomainList,
-                                           activeDomainList->doms[j]->id,
-                                           activeDomainList->doms[j]->name,
-                                           activeDomainList->doms[j]->uuid);
-
-                virUnrefDomain(dom);
-                removed = 1;
-            }
+            virDomainEventPtr event =
+                virDomainEventNew(-1,
+                                  activeDomainList->doms[j]->name,
+                                  activeDomainList->doms[j]->uuid,
+                                  VIR_DOMAIN_EVENT_STOPPED,
+                                  VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
+            if (event)
+                xenUnifiedDomainEventDispatch(priv, event);
+
+            /* Remove from the list */
+            xenUnifiedRemoveDomainInfo(activeDomainList,
+                                       activeDomainList->doms[j]->id,
+                                       activeDomainList->doms[j]->name,
+                                       activeDomainList->doms[j]->uuid);
+
+            removed = 1;
         }
     }