QEMU domain event thread safety

This commit is contained in:
Daniel P. Berrange 2008-12-04 21:09:20 +00:00
parent 3527f16a94
commit bc898df2c7
11 changed files with 569 additions and 284 deletions

View File

@ -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> Thu Dec 4 21:05:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/qemu_conf.h: Add a driver lock variable * src/qemu_conf.h: Add a driver lock variable

View File

@ -125,6 +125,49 @@ virDomainEventCallbackListRemoveConn(virConnectPtr conn,
return 0; 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: * virDomainEventCallbackListAdd:
* @conn: pointer to the connection * @conn: pointer to the connection
@ -182,6 +225,62 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
return 0; 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: * virDomainEventQueueFree:
* @queue: pointer to the queue * @queue: pointer to the queue
@ -192,14 +291,18 @@ void
virDomainEventQueueFree(virDomainEventQueuePtr queue) virDomainEventQueueFree(virDomainEventQueuePtr queue)
{ {
int i; int i;
for ( i=0 ; i<queue->count ; i++ ) { if (!queue)
VIR_FREE(queue->events[i]); return;
for (i = 0; i < queue->count ; i++) {
virDomainEventFree(queue->events[i]);
} }
VIR_FREE(queue->events);
VIR_FREE(queue); VIR_FREE(queue);
} }
/** /**
* virDomainEventCallbackQueuePop: * virDomainEventQueuePop:
* @evtQueue: the queue of events * @evtQueue: the queue of events
* *
* Internal function to pop off, and return the front of the queue * 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. * Returns: virDomainEventPtr on success NULL on failure.
*/ */
virDomainEventPtr virDomainEventPtr
virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue) virDomainEventQueuePop(virDomainEventQueuePtr evtQueue)
{ {
virDomainEventPtr ret; virDomainEventPtr ret;
@ -232,9 +335,8 @@ virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
} }
/** /**
* virDomainEventCallbackQueuePush: * virDomainEventQueuePush:
* @evtQueue: the dom event queue * @evtQueue: the dom event queue
* @dom: the domain to add
* @event: the event to add * @event: the event to add
* *
* Internal function to push onto the back of an virDomainEventQueue * Internal function to push onto the back of an virDomainEventQueue
@ -242,37 +344,76 @@ virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
* Returns: 0 on success, -1 on failure * Returns: 0 on success, -1 on failure
*/ */
int int
virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
virDomainPtr dom, virDomainEventPtr event)
int event,
int detail)
{ {
virDomainEventPtr domEvent; if (!evtQueue) {
/* Check incoming */
if ( !evtQueue ) {
return -1; 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 */ /* Make space on queue */
if (VIR_REALLOC_N(evtQueue->events, if (VIR_REALLOC_N(evtQueue->events,
evtQueue->count + 1) < 0) { evtQueue->count + 1) < 0) {
DEBUG0("Error reallocating queue"); DEBUG0("Error reallocating queue");
VIR_FREE(domEvent);
return -1; return -1;
} }
evtQueue->events[evtQueue->count] = domEvent; evtQueue->events[evtQueue->count] = event;
evtQueue->count++; evtQueue->count++;
return 0; 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;
}

View File

@ -22,16 +22,17 @@
#include "internal.h" #include "internal.h"
#ifndef __DOMAIN_EVENT_H__ #ifndef __DOMAIN_EVENT_H__
#define __DOMAIN_EVENT_H__ #define __DOMAIN_EVENT_H__
#include "domain_conf.h"
struct _virDomainEventCallback { struct _virDomainEventCallback {
virConnectPtr conn; virConnectPtr conn;
virConnectDomainEventCallback cb; virConnectDomainEventCallback cb;
void *opaque; void *opaque;
virFreeCallback freecb; virFreeCallback freecb;
int deleted;
}; };
typedef struct _virDomainEventCallback virDomainEventCallback; typedef struct _virDomainEventCallback virDomainEventCallback;
typedef virDomainEventCallback *virDomainEventCallbackPtr; typedef virDomainEventCallback *virDomainEventCallbackPtr;
@ -58,13 +59,20 @@ int virDomainEventCallbackListRemove(virConnectPtr conn,
int virDomainEventCallbackListRemoveConn(virConnectPtr conn, int virDomainEventCallbackListRemoveConn(virConnectPtr conn,
virDomainEventCallbackListPtr cbList); virDomainEventCallbackListPtr cbList);
int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
virDomainEventCallbackListPtr cbList,
virConnectDomainEventCallback callback);
int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList);
/** /**
* Dispatching domain events that come in while * Dispatching domain events that come in while
* in a call / response rpc * in a call / response rpc
*/ */
struct _virDomainEvent { struct _virDomainEvent {
virDomainPtr dom; int id;
int event; char *name;
unsigned char uuid[VIR_UUID_BUFLEN];
int type;
int detail; int detail;
}; };
typedef struct _virDomainEvent virDomainEvent; typedef struct _virDomainEvent virDomainEvent;
@ -77,15 +85,40 @@ struct _virDomainEventQueue {
typedef struct _virDomainEventQueue virDomainEventQueue; typedef struct _virDomainEventQueue virDomainEventQueue;
typedef virDomainEventQueue *virDomainEventQueuePtr; typedef virDomainEventQueue *virDomainEventQueuePtr;
int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, virDomainEventQueuePtr virDomainEventQueueNew(void);
virDomainPtr dom,
int event, virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail);
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 virDomainEventPtr
virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue); virDomainEventQueuePop(virDomainEventQueuePtr evtQueue);
void virDomainEventFree(virDomainEventPtr event);
void virDomainEventQueueFree(virDomainEventQueuePtr queue); 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 #endif

View File

@ -383,9 +383,21 @@ LIBVIRT_PRIVATE_@VERSION@ {
virDomainEventCallbackListFree; virDomainEventCallbackListFree;
virDomainEventCallbackListRemove; virDomainEventCallbackListRemove;
virDomainEventCallbackListRemoveConn; virDomainEventCallbackListRemoveConn;
virDomainEventCallbackListMarkDelete;
virDomainEventCallbackListPurgeMarked;
virDomainEventQueueNew;
virDomainEventQueueFree; virDomainEventQueueFree;
virDomainEventCallbackQueuePop; virDomainEventQueuePop;
virDomainEventCallbackQueuePush; virDomainEventQueuePush;
virDomainEventNew;
virDomainEventNewFromDom;
virDomainEventNewFromObj;
virDomainEventNewFromDef;
virDomainEventFree;
virDomainEventDispatchDefaultFunc;
virDomainEventDispatch;
virDomainEventQueueDispatch;
/* driver.h */ /* driver.h */

View File

@ -71,6 +71,9 @@ struct qemud_driver {
/* An array of callbacks */ /* An array of callbacks */
virDomainEventCallbackListPtr domainEventCallbacks; virDomainEventCallbackListPtr domainEventCallbacks;
virDomainEventQueuePtr domainEventQueue;
int domainEventTimer;
int domainEventDispatching;
}; };
/* Port numbers used for KVM migration. */ /* Port numbers used for KVM migration. */

View File

@ -115,10 +115,10 @@ static int qemudSetNonBlock(int fd) {
} }
static void qemudDomainEventDispatch (struct qemud_driver *driver,
virDomainObjPtr vm, static void qemuDomainEventFlush(int timer, void *opaque);
int event, static void qemuDomainEventQueue(struct qemud_driver *driver,
int detail); virDomainEventPtr event);
static void qemudDispatchVMEvent(int watch, static void qemudDispatchVMEvent(int watch,
int fd, int fd,
@ -160,8 +160,12 @@ qemudAutostartConfigs(struct qemud_driver *driver) {
vm->def->name, vm->def->name,
err ? err->message : NULL); err ? err->message : NULL);
} else { } else {
qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED, virDomainEventPtr event =
VIR_DOMAIN_EVENT_STARTED_BOOTED); virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_BOOTED);
if (event)
qemuDomainEventQueue(driver, event);
} }
} }
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
@ -192,6 +196,12 @@ qemudStartup(void) {
/* Init callback list */ /* Init callback list */
if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0) if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
goto out_of_memory; 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 (!uid) {
if (asprintf(&qemu_driver->logDir, if (asprintf(&qemu_driver->logDir,
@ -265,10 +275,14 @@ static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
{ {
struct qemud_driver *driver = opaque; struct qemud_driver *driver = opaque;
if (newVM) if (newVM) {
qemudDomainEventDispatch(driver, vm, virDomainEventPtr event =
VIR_DOMAIN_EVENT_DEFINED, virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_DEFINED_ADDED); VIR_DOMAIN_EVENT_DEFINED,
VIR_DOMAIN_EVENT_DEFINED_ADDED);
if (event)
qemuDomainEventQueue(driver, event);
}
} }
/** /**
@ -359,6 +373,10 @@ qemudShutdown(void) {
/* Free domain callback list */ /* Free domain callback list */
virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks); virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
virDomainEventQueueFree(qemu_driver->domainEventQueue);
if (qemu_driver->domainEventTimer != -1)
virEventRemoveTimeout(qemu_driver->domainEventTimer);
if (qemu_driver->brctl) if (qemu_driver->brctl)
brShutdown(qemu_driver->brctl); brShutdown(qemu_driver->brctl);
@ -1075,6 +1093,7 @@ static void
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) { qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
struct qemud_driver *driver = opaque; struct qemud_driver *driver = opaque;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
virDomainEventPtr event = NULL;
unsigned int i; unsigned int i;
int quit = 0, failed = 0; int quit = 0, failed = 0;
@ -1107,12 +1126,12 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
} }
if (failed || quit) { 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); 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) { if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
@ -1123,6 +1142,8 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
} }
@ -1591,6 +1612,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
virDomainDefPtr def; virDomainDefPtr def;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL; virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
if (!(def = virDomainDefParseString(conn, driver->caps, xml))) if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
@ -1627,9 +1649,10 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
vm = NULL; vm = NULL;
goto cleanup; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_STARTED, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED_BOOTED); VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_BOOTED);
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
@ -1638,6 +1661,8 @@ cleanup:
virDomainDefFree(def); virDomainDefFree(def);
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return dom; return dom;
} }
@ -1648,6 +1673,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
char *info; char *info;
virDomainObjPtr vm; virDomainObjPtr vm;
int ret = -1; int ret = -1;
virDomainEventPtr event = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
vm = virDomainFindByID(&driver->domains, dom->id); vm = virDomainFindByID(&driver->domains, dom->id);
@ -1670,9 +1696,9 @@ static int qemudDomainSuspend(virDomainPtr dom) {
} }
vm->state = VIR_DOMAIN_PAUSED; vm->state = VIR_DOMAIN_PAUSED;
qemudDebug("Reply %s", info); qemudDebug("Reply %s", info);
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED,
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
VIR_FREE(info); VIR_FREE(info);
} }
ret = 0; ret = 0;
@ -1680,6 +1706,12 @@ static int qemudDomainSuspend(virDomainPtr dom) {
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event) {
qemuDriverLock(driver);
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver);
}
return ret; return ret;
} }
@ -1689,6 +1721,7 @@ static int qemudDomainResume(virDomainPtr dom) {
char *info; char *info;
virDomainObjPtr vm; virDomainObjPtr vm;
int ret = -1; int ret = -1;
virDomainEventPtr event = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
vm = virDomainFindByID(&driver->domains, dom->id); vm = virDomainFindByID(&driver->domains, dom->id);
@ -1712,9 +1745,9 @@ static int qemudDomainResume(virDomainPtr dom) {
} }
vm->state = VIR_DOMAIN_RUNNING; vm->state = VIR_DOMAIN_RUNNING;
qemudDebug("Reply %s", info); qemudDebug("Reply %s", info);
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_RESUMED, VIR_DOMAIN_EVENT_RESUMED,
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
VIR_FREE(info); VIR_FREE(info);
} }
ret = 0; ret = 0;
@ -1722,6 +1755,11 @@ static int qemudDomainResume(virDomainPtr dom) {
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event) {
qemuDriverLock(driver);
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver);
}
return ret; return ret;
} }
@ -1761,6 +1799,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
int ret = -1; int ret = -1;
virDomainEventPtr event = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
vm = virDomainFindByID(&driver->domains, dom->id); vm = virDomainFindByID(&driver->domains, dom->id);
@ -1771,9 +1810,9 @@ static int qemudDomainDestroy(virDomainPtr dom) {
} }
qemudShutdownVMDaemon(dom->conn, driver, vm); qemudShutdownVMDaemon(dom->conn, driver, vm);
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_DESTROYED); VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
if (!vm->persistent) { if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
@ -1784,6 +1823,8 @@ static int qemudDomainDestroy(virDomainPtr dom) {
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
@ -2053,6 +2094,7 @@ static int qemudDomainSave(virDomainPtr dom,
char *xml = NULL; char *xml = NULL;
struct qemud_save_header header; struct qemud_save_header header;
int ret = -1; int ret = -1;
virDomainEventPtr event = NULL;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@ -2154,9 +2196,9 @@ static int qemudDomainSave(virDomainPtr dom,
/* Shut it down */ /* Shut it down */
qemudShutdownVMDaemon(dom->conn, driver, vm); qemudShutdownVMDaemon(dom->conn, driver, vm);
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_SAVED); VIR_DOMAIN_EVENT_STOPPED_SAVED);
if (!vm->persistent) { if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
@ -2175,6 +2217,8 @@ cleanup:
unlink(path); unlink(path);
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
@ -2412,6 +2456,7 @@ static int qemudDomainRestore(virConnectPtr conn,
int ret = -1; int ret = -1;
char *xml = NULL; char *xml = NULL;
struct qemud_save_header header; struct qemud_save_header header;
virDomainEventPtr event = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
/* Verify the header and read the XML */ /* Verify the header and read the XML */
@ -2495,9 +2540,9 @@ static int qemudDomainRestore(virConnectPtr conn,
goto cleanup; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_RESTORED); VIR_DOMAIN_EVENT_STARTED_RESTORED);
/* If it was running before, resume it now. */ /* If it was running before, resume it now. */
if (header.was_running) { if (header.was_running) {
@ -2519,6 +2564,8 @@ cleanup:
close(fd); close(fd);
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
@ -2599,6 +2646,7 @@ static int qemudDomainStart(virDomainPtr dom) {
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
int ret = -1; int ret = -1;
virDomainEventPtr event = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid); vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@ -2612,13 +2660,18 @@ static int qemudDomainStart(virDomainPtr dom) {
ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL); ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL);
if (ret != -1) if (ret != -1)
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_BOOTED); VIR_DOMAIN_EVENT_STARTED_BOOTED);
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event) {
qemuDriverLock(driver);
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver);
}
return ret; return ret;
} }
@ -2628,6 +2681,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
virDomainDefPtr def; virDomainDefPtr def;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL; virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
int newVM = 1; int newVM = 1;
qemuDriverLock(driver); qemuDriverLock(driver);
@ -2657,11 +2711,11 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
goto cleanup; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_DEFINED, VIR_DOMAIN_EVENT_DEFINED,
newVM ? newVM ?
VIR_DOMAIN_EVENT_DEFINED_ADDED : VIR_DOMAIN_EVENT_DEFINED_ADDED :
VIR_DOMAIN_EVENT_DEFINED_UPDATED); VIR_DOMAIN_EVENT_DEFINED_UPDATED);
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
@ -2669,6 +2723,8 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return dom; return dom;
} }
@ -2676,6 +2732,7 @@ cleanup:
static int qemudDomainUndefine(virDomainPtr dom) { static int qemudDomainUndefine(virDomainPtr dom) {
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainEventPtr event = NULL;
int ret = -1; int ret = -1;
qemuDriverLock(driver); qemuDriverLock(driver);
@ -2702,9 +2759,9 @@ static int qemudDomainUndefine(virDomainPtr dom) {
if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0) if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0)
goto cleanup; goto cleanup;
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_UNDEFINED, VIR_DOMAIN_EVENT_UNDEFINED,
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
@ -2714,6 +2771,8 @@ static int qemudDomainUndefine(virDomainPtr dom) {
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
@ -3709,41 +3768,69 @@ qemudDomainEventDeregister (virConnectPtr conn,
int ret; int ret;
qemuDriverLock(driver); qemuDriverLock(driver);
ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, if (driver->domainEventDispatching)
callback); ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
callback);
else
ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
callback);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
static void qemudDomainEventDispatch (struct qemud_driver *driver, static void qemuDomainEventDispatchFunc(virConnectPtr conn,
virDomainObjPtr vm, virDomainEventPtr event,
int event, virConnectDomainEventCallback cb,
int detail) void *cbopaque,
void *opaque)
{ {
int i; struct qemud_driver *driver = opaque;
virDomainEventCallbackListPtr cbList;
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++) { static void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
if(cbList->callbacks[i] && cbList->callbacks[i]->cb) { {
virConnectPtr conn = cbList->callbacks[i]->conn; struct qemud_driver *driver = opaque;
virDomainPtr dom = virGetDomain(conn, vm->def->name, virDomainEventQueue tempQueue;
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);
}
}
}
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. */ /* Migration support. */
@ -3771,6 +3858,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
char hostname [HOST_NAME_MAX+1]; char hostname [HOST_NAME_MAX+1];
char migrateFrom [64]; char migrateFrom [64];
const char *p; const char *p;
virDomainEventPtr event = NULL;
int ret = -1;; int ret = -1;;
*uri_out = NULL; *uri_out = NULL;
@ -3892,9 +3980,10 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
} }
goto cleanup; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_STARTED, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED_MIGRATED); VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_MIGRATED);
ret = 0; ret = 0;
cleanup: cleanup:
@ -3904,6 +3993,8 @@ cleanup:
} }
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
@ -3920,6 +4011,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
{ {
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainEventPtr event = NULL;
char *safe_uri; char *safe_uri;
char cmd[HOST_NAME_MAX+50]; char cmd[HOST_NAME_MAX+50];
char *info = NULL; char *info = NULL;
@ -3946,9 +4038,12 @@ qemudDomainMigratePerform (virDomainPtr dom,
DEBUG ("stop reply: %s", info); DEBUG ("stop reply: %s", info);
VIR_FREE(info); VIR_FREE(info);
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED,
VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED); VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
if (event)
qemuDomainEventQueue(driver, event);
event = NULL;
} }
if (resource > 0) { if (resource > 0) {
@ -3987,9 +4082,10 @@ qemudDomainMigratePerform (virDomainPtr dom,
/* Clean up the source domain. */ /* Clean up the source domain. */
qemudShutdownVMDaemon (dom->conn, driver, vm); qemudShutdownVMDaemon (dom->conn, driver, vm);
qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_STOPPED, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED); VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
if (!vm->persistent) { if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, vm); virDomainRemoveInactive(&driver->domains, vm);
vm = NULL; vm = NULL;
@ -4000,6 +4096,8 @@ cleanup:
VIR_FREE(info); VIR_FREE(info);
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
@ -4017,6 +4115,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
struct qemud_driver *driver = dconn->privateData; struct qemud_driver *driver = dconn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainPtr dom = NULL; virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
char *info = NULL; char *info = NULL;
qemuDriverLock(driver); qemuDriverLock(driver);
@ -4034,14 +4133,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid); dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
VIR_FREE(info); VIR_FREE(info);
vm->state = VIR_DOMAIN_RUNNING; vm->state = VIR_DOMAIN_RUNNING;
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_RESUMED, VIR_DOMAIN_EVENT_RESUMED,
VIR_DOMAIN_EVENT_RESUMED_MIGRATED); VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
} else { } else {
qemudShutdownVMDaemon (dconn, driver, vm); qemudShutdownVMDaemon (dconn, driver, vm);
qemudDomainEventDispatch(driver, vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_FAILED); VIR_DOMAIN_EVENT_STOPPED_FAILED);
if (!vm->persistent) { if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, vm); virDomainRemoveInactive(&driver->domains, vm);
vm = NULL; vm = NULL;
@ -4051,6 +4150,8 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
cleanup: cleanup:
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return dom; return dom;
} }

View File

@ -5484,59 +5484,62 @@ remoteRegister (void)
* *
* Read the event data off the wire * Read the event data off the wire
*/ */
static int static virDomainEventPtr
remoteDomainReadEvent(virConnectPtr conn, XDR *xdr, remoteDomainReadEvent(virConnectPtr conn, XDR *xdr)
virDomainPtr *dom, int *event, int *detail)
{ {
remote_domain_event_ret ret; remote_domain_event_ret ret;
virDomainPtr dom;
virDomainEventPtr event = NULL;
memset (&ret, 0, sizeof ret); memset (&ret, 0, sizeof ret);
/* unmarshall parameters, and process it*/ /* unmarshall parameters, and process it*/
if (! xdr_remote_domain_event_ret(xdr, &ret) ) { if (! xdr_remote_domain_event_ret(xdr, &ret) ) {
error (conn, VIR_ERR_RPC, error (conn, VIR_ERR_RPC,
_("remoteDomainProcessEvent: unmarshalling ret")); _("remoteDomainProcessEvent: unmarshalling ret"));
return -1; return NULL;
} }
*dom = get_nonnull_domain(conn,ret.dom); dom = get_nonnull_domain(conn,ret.dom);
*event = ret.event; if (!dom)
*detail = ret.detail; return NULL;
return 0; event = virDomainEventNewFromDom(dom, ret.event, ret.detail);
virDomainFree(dom);
return event;
} }
static void static void
remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr) remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr)
{ {
virDomainPtr dom;
int event, detail, i;
struct private_data *priv = conn->privateData; struct private_data *priv = conn->privateData;
virDomainEventPtr event;
if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) { event = remoteDomainReadEvent(conn, xdr);
DEBUG0("Calling domain event callbacks (no queue)"); if (!event)
for(i=0 ; i < priv->callbackList->count ; i++) { return;
if (priv->callbackList->callbacks[i] )
priv->callbackList->callbacks[i]->cb( DEBUG0("Calling domain event callbacks (no queue)");
conn, dom, event, detail, virDomainEventDispatch(event, priv->callbackList,
priv->callbackList->callbacks[i]->opaque); virDomainEventDispatchDefaultFunc, NULL);
} virDomainEventFree(event);
}
} }
static void static void
remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr) remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr)
{ {
virDomainPtr dom;
int event, detail;
struct private_data *priv = conn->privateData; struct private_data *priv = conn->privateData;
virDomainEventPtr event;
if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) event = remoteDomainReadEvent(conn, xdr);
{ if (!event)
if( virDomainEventCallbackQueuePush(priv->domainEvents, return;
dom, event, detail) < 0 ) {
DEBUG("%s", "Error adding event to queue"); if (virDomainEventQueuePush(priv->domainEvents,
} event) < 0)
} DEBUG0("Error adding event to queue");
virDomainEventFree(event);
} }
/** remoteDomainEventFired: /** remoteDomainEventFired:
@ -5618,26 +5621,10 @@ remoteDomainEventFired(int watch,
void void
remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
{ {
int i;
virDomainEventPtr domEvent;
void *user_data = NULL;
virConnectPtr conn = opaque; virConnectPtr conn = opaque;
struct private_data *priv = conn->privateData; struct private_data *priv = conn->privateData;
while( (domEvent = virDomainEventCallbackQueuePop(priv->domainEvents)) ) { virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList,
DEBUG(" Flushing %p", domEvent); virDomainEventDispatchDefaultFunc, NULL);
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);
}
virEventUpdateTimeout(priv->eventFlushTimer, -1); virEventUpdateTimeout(priv->eventFlushTimer, -1);
} }

View File

@ -92,30 +92,33 @@ struct xenUnifiedDriver xenInotifyDriver = {
NULL, /* domainSetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */
}; };
static virDomainPtr static int
xenInotifyXenCacheLookup(virConnectPtr conn, const char *filename) { xenInotifyXenCacheLookup(const char *filename,
char **name, unsigned char *uuid) {
xenXMConfCachePtr entry; xenXMConfCachePtr entry;
virDomainPtr dom;
if (!(entry = virHashLookup(xenXMGetConfigCache(), filename))) { if (!(entry = virHashLookup(xenXMGetConfigCache(), filename))) {
DEBUG("No config found for %s", filename); DEBUG("No config found for %s", filename);
return NULL; return -1;
} }
if(!(dom = virGetDomain(conn, entry->def->name, *name = strdup(entry->def->name);
(unsigned char*)entry->def->uuid))) { memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN);
if (!*name) {
DEBUG0("Error getting dom from def"); DEBUG0("Error getting dom from def");
return NULL; return -1;
} }
return dom; return 0;
} }
static virDomainPtr static int
xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) { xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename,
char **name, unsigned char *uuid) {
int i; int i;
virDomainPtr dom; virDomainPtr dom;
const char *uuid_str; const char *uuid_str;
unsigned char uuid[VIR_UUID_BUFLEN]; unsigned char rawuuid[VIR_UUID_BUFLEN];
/* xend is managing domains. we will get /* xend is managing domains. we will get
* a filename in the manner: * a filename in the manner:
@ -123,57 +126,70 @@ xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) {
*/ */
uuid_str = filename + strlen(LIBVIRTD_DOMAINS_DIR) + 1; 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, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"parsing uuid %s", uuid_str); "parsing uuid %s", uuid_str);
return (NULL); return -1;
} }
/* call directly into xend here, as driver may not yet /* call directly into xend here, as driver may not yet
be set during open while we are building our be set during open while we are building our
initial list of domains */ initial list of domains */
DEBUG("Looking for dom with uuid: %s", uuid_str); 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. /* If we are here, the domain has gone away.
search for, and create a domain from the stored search for, and create a domain from the stored
list info */ list info */
for (i=0; i<configInfoList->count; i++) { for (i=0; i<configInfoList->count; i++) {
if (!memcmp(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) { if (!memcmp(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
if(!(dom = virGetDomain(conn, configInfoList->doms[i]->name, *name = strdup(configInfoList->doms[i]->name);
configInfoList->doms[i]->uuid))) { if (!*name) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"finding dom for %s", uuid_str); "finding dom for %s", uuid_str);
return NULL; return -1;
} }
memcpy(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN);
DEBUG0("Found dom on list"); DEBUG0("Found dom on list");
return dom; return 0;
} }
} }
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("finding dom on config list")); "%s", _("finding dom on config list"));
return NULL; return -1;
} }
if (!(*name = strdup(dom->name)))
return -1;
memcpy(uuid, dom->uuid, VIR_UUID_BUFLEN);
virDomainFree(dom);
/* succeeded too find domain by uuid */ /* succeeded too find domain by uuid */
return dom; return 0;
} }
static virDomainPtr static int
xenInotifyDomainLookup(virConnectPtr conn, const char *filename) { xenInotifyDomainLookup(virConnectPtr conn,
virDomainPtr dom; const char *filename,
virDomainInfo info; char **name, unsigned char *uuid) {
if (useXenConfigCache)
return xenInotifyXenCacheLookup(filename, name, uuid);
else
return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
}
dom = useXenConfigCache ? xenInotifyXenCacheLookup(conn, filename) : static virDomainEventPtr
xenInotifyXendDomainsDirLookup(conn, filename); xenInotifyDomainEventFromFile(virConnectPtr conn,
const char *filename,
int type, int detail) {
virDomainEventPtr event;
char *name = NULL;
unsigned char uuid[VIR_UUID_BUFLEN];
if(dom) { if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0)
if ( (useXenConfigCache ? xenXMDomainGetInfo(dom, &info) : return NULL;
xenDaemonDomainGetInfo(dom, &info)) < 0)
dom->id = -1; event = virDomainEventNew(-1, name, uuid, type, detail);
else VIR_FREE(name);
dom->id = (info.state == VIR_DOMAIN_SHUTOFF) ? -1 : dom->id; return event;
return dom;
}
return NULL;
} }
static int static int
@ -215,21 +231,22 @@ xenInotifyXendDomainsDirRemoveEntry(virConnectPtr conn ATTRIBUTE_UNUSED,
static int static int
xenInotifyXendDomainsDirAddEntry(virConnectPtr conn, xenInotifyXendDomainsDirAddEntry(virConnectPtr conn,
const char *fname) { const char *fname) {
virDomainPtr dom = xenInotifyDomainLookup(conn, fname); char *name = NULL;
if(!dom) { unsigned char uuid[VIR_UUID_BUFLEN];
if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Error looking up domain")); "%s", _("Error looking up domain"));
return -1; return -1;
} }
if( xenUnifiedAddDomainInfo(configInfoList, if( xenUnifiedAddDomainInfo(configInfoList,
dom->id, dom->name, dom->uuid) < 0) { -1, name, uuid) < 0) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Error adding file to config cache")); "%s", _("Error adding file to config cache"));
virUnrefDomain(dom); VIR_FREE(name);
return -1; return -1;
} }
virUnrefDomain(dom); VIR_FREE(name);
return 0; return 0;
} }
@ -260,7 +277,6 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
char *tmp, *name; char *tmp, *name;
virConnectPtr conn = (virConnectPtr) data; virConnectPtr conn = (virConnectPtr) data;
xenUnifiedPrivatePtr priv = NULL; xenUnifiedPrivatePtr priv = NULL;
virDomainPtr dom = NULL;
DEBUG0("got inotify event"); DEBUG0("got inotify event");
@ -300,16 +316,15 @@ reread:
snprintf(fname, 1024, "%s/%s", configDir, name); snprintf(fname, 1024, "%s/%s", configDir, name);
if (e->mask & (IN_DELETE | IN_MOVED_FROM)) { 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, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("looking up dom")); "%s", _("looking up dom"));
continue;
}
xenUnifiedDomainEventDispatch(conn->privateData, dom,
VIR_DOMAIN_EVENT_UNDEFINED,
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) { if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
@ -317,21 +332,23 @@ reread:
return; return;
} }
} else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) { } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
virDomainEventPtr event;
if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) { if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Error adding file to config cache")); "%s", _("Error adding file to config cache"));
return; return;
} }
if (!(dom = xenInotifyDomainLookup(conn, fname))) { event = xenInotifyDomainEventFromFile(conn, fname,
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, VIR_DOMAIN_EVENT_DEFINED,
"%s", _("looking up dom")); VIR_DOMAIN_EVENT_DEFINED_ADDED);
continue;
} 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);
} }
} }

View File

@ -1583,28 +1583,14 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
* *
*/ */
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv, void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
virDomainPtr dom, virDomainEventPtr event)
int event,
int detail)
{ {
int i; if (!priv || !priv->domainEventCallbacks)
virDomainEventCallbackListPtr cbList; return;
if(!priv) return; virDomainEventDispatch(event,
priv->domainEventCallbacks,
cbList = priv->domainEventCallbacks; virDomainEventDispatchDefaultFunc,
if(!cbList) return; NULL);
virDomainEventFree(event);
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);
}
}
}
} }

View File

@ -182,9 +182,7 @@ int xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
int id, char *name, int id, char *name,
unsigned char *uuid); unsigned char *uuid);
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv, void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
virDomainPtr dom, virDomainEventPtr event);
int event,
int detail);
unsigned long xenUnifiedVersion(void); unsigned long xenUnifiedVersion(void);
#endif /* __VIR_XEN_UNIFIED_H__ */ #endif /* __VIR_XEN_UNIFIED_H__ */

View File

@ -1215,7 +1215,7 @@ retry:
} }
if (!found) { if (!found) {
virDomainPtr dom; virDomainEventPtr event;
char *name; char *name;
unsigned char uuid[VIR_UUID_BUFLEN]; unsigned char uuid[VIR_UUID_BUFLEN];
@ -1229,21 +1229,15 @@ retry:
continue; continue;
} }
dom = virGetDomain(conn, name, uuid); event = virDomainEventNew(new_domids[i], name, uuid,
if (dom) { VIR_DOMAIN_EVENT_STARTED,
dom->id = new_domids[i]; VIR_DOMAIN_EVENT_STARTED_BOOTED);
if (event)
xenUnifiedDomainEventDispatch(priv, event);
/* This domain was not in the old list. Emit an event */ /* Add to the list */
xenUnifiedDomainEventDispatch(priv, dom, xenUnifiedAddDomainInfo(activeDomainList,
VIR_DOMAIN_EVENT_STARTED, new_domids[i], name, uuid);
VIR_DOMAIN_EVENT_STARTED_BOOTED);
/* Add to the list */
xenUnifiedAddDomainInfo(activeDomainList,
new_domids[i], name, uuid);
virUnrefDomain(dom);
}
VIR_FREE(name); VIR_FREE(name);
} }
@ -1299,24 +1293,22 @@ retry:
} }
if (!found) { if (!found) {
virDomainPtr dom = virGetDomain(conn, virDomainEventPtr event =
activeDomainList->doms[j]->name, virDomainEventNew(-1,
activeDomainList->doms[j]->uuid); activeDomainList->doms[j]->name,
if(dom) { activeDomainList->doms[j]->uuid,
dom->id = -1; VIR_DOMAIN_EVENT_STOPPED,
/* This domain was not in the new list. Emit an event */ VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
xenUnifiedDomainEventDispatch(priv, dom, if (event)
VIR_DOMAIN_EVENT_STOPPED, xenUnifiedDomainEventDispatch(priv, event);
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); /* Remove from the list */
removed = 1; xenUnifiedRemoveDomainInfo(activeDomainList,
} activeDomainList->doms[j]->id,
activeDomainList->doms[j]->name,
activeDomainList->doms[j]->uuid);
removed = 1;
} }
} }