From bc898df2c74fe3c8efedfbbd430737bac950e65e Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 4 Dec 2008 21:09:20 +0000 Subject: [PATCH] QEMU domain event thread safety --- ChangeLog | 15 ++ src/domain_event.c | 191 ++++++++++++++++++++++---- src/domain_event.h | 51 +++++-- src/libvirt_sym.version.in | 16 ++- src/qemu_conf.h | 3 + src/qemu_driver.c | 271 +++++++++++++++++++++++++------------ src/remote_internal.c | 79 +++++------ src/xen_inotify.c | 137 +++++++++++-------- src/xen_unified.c | 30 ++-- src/xen_unified.h | 4 +- src/xs_internal.c | 56 ++++---- 11 files changed, 569 insertions(+), 284 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43d1410b6b..b2e7e3b0eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Thu Dec 4 21:09:41 GMT 2008 Daniel P. Berrange + + 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 * src/qemu_conf.h: Add a driver lock variable diff --git a/src/domain_event.c b/src/domain_event.c index d5f54158c6..daa6fd5f8e 100644 --- a/src/domain_event.c +++ b/src/domain_event.c @@ -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 ; icount ; 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 ) { + if (!evtQueue) { return -1; } - /* Allocate new event */ - if (VIR_ALLOC(domEvent) < 0) { - DEBUG0("Error allocating event"); - 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; +} diff --git a/src/domain_event.h b/src/domain_event.h index 32ae0dbc47..f29e42e77f 100644 --- a/src/domain_event.h +++ b/src/domain_event.h @@ -22,16 +22,17 @@ #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 diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in index 9aa1497f7c..ece4058354 100644 --- a/src/libvirt_sym.version.in +++ b/src/libvirt_sym.version.in @@ -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 */ diff --git a/src/qemu_conf.h b/src/qemu_conf.h index 58ea321b45..36d09d15dc 100644 --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -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. */ diff --git a/src/qemu_driver.c b/src/qemu_driver.c index cc7b6c0368..7c45122630 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -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; + struct qemud_driver *driver = opaque; - cbList = driver->domainEventCallbacks; + /* Drop the lock whle dispatching, for sake of re-entrancy */ + qemuDriverUnlock(driver); + virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); + qemuDriverLock(driver); +} - 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); - } - } - } +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; } diff --git a/src/remote_internal.c b/src/remote_internal.c index 7bf8766a86..1d0c5ac337 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -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); } diff --git a/src/xen_inotify.c b/src/xen_inotify.c index a7ecef0a46..9d433e4708 100644 --- a/src/xen_inotify.c +++ b/src/xen_inotify.c @@ -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; icount; 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; +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); +} - dom = useXenConfigCache ? xenInotifyXenCacheLookup(conn, filename) : - xenInotifyXendDomainsDirLookup(conn, filename); +static virDomainEventPtr +xenInotifyDomainEventFromFile(virConnectPtr conn, + const char *filename, + int type, int detail) { + virDomainEventPtr event; + char *name = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; - 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; + 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))) { - virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("looking up dom")); - continue; - } + 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")); - xenUnifiedDomainEventDispatch(conn->privateData, dom, - VIR_DOMAIN_EVENT_DEFINED, - VIR_DOMAIN_EVENT_DEFINED_ADDED); } } diff --git a/src/xen_unified.c b/src/xen_unified.c index ca05d75313..a60bc799f4 100644 --- a/src/xen_unified.c +++ b/src/xen_unified.c @@ -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 || !priv->domainEventCallbacks) + return; - if(!priv) return; - - cbList = priv->domainEventCallbacks; - if(!cbList) 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); } diff --git a/src/xen_unified.h b/src/xen_unified.h index 831cefc3c4..f81b014445 100644 --- a/src/xen_unified.h +++ b/src/xen_unified.h @@ -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__ */ diff --git a/src/xs_internal.c b/src/xs_internal.c index ae773805d2..184cfe5bd5 100644 --- a/src/xs_internal.c +++ b/src/xs_internal.c @@ -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); + 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); - virUnrefDomain(dom); - removed = 1; - } + /* Remove from the list */ + xenUnifiedRemoveDomainInfo(activeDomainList, + activeDomainList->doms[j]->id, + activeDomainList->doms[j]->name, + activeDomainList->doms[j]->uuid); + + removed = 1; } }