virDomainEventCallbackListPtr cbList,
virConnectDomainEventCallback callback)
{
+ int ret = 0;
int i;
for (i = 0 ; i < cbList->count ; i++) {
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
}
cbList->count--;
- return 0;
+ for (i = 0 ; i < cbList->count ; i++) {
+ if (!cbList->callbacks[i]->deleted)
+ ret++;
+ }
+ return ret;
}
}
virDomainEventCallbackListPtr cbList,
int callbackID)
{
+ int ret = 0;
int i;
for (i = 0 ; i < cbList->count ; i++) {
if (cbList->callbacks[i]->callbackID == callbackID &&
}
cbList->count--;
- return 0;
+ for (i = 0 ; i < cbList->count ; i++) {
+ if (!cbList->callbacks[i]->deleted)
+ ret++;
+ }
+ return ret;
}
}
virDomainEventCallbackListPtr cbList,
virConnectDomainEventCallback callback)
{
+ int ret = 0;
int i;
for (i = 0 ; i < cbList->count ; i++) {
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
cbList->callbacks[i]->conn == conn) {
cbList->callbacks[i]->deleted = 1;
- return 0;
+ for (i = 0 ; i < cbList->count ; i++) {
+ if (!cbList->callbacks[i]->deleted)
+ ret++;
+ }
+ return ret;
}
}
virDomainEventCallbackListPtr cbList,
int callbackID)
{
+ int ret = 0;
int i;
for (i = 0 ; i < cbList->count ; i++) {
if (cbList->callbacks[i]->callbackID == callbackID &&
cbList->callbacks[i]->conn == conn) {
cbList->callbacks[i]->deleted = 1;
- return 0;
+ for (i = 0 ; i < cbList->count ; i++) {
+ if (!cbList->callbacks[i]->deleted)
+ ret++;
+ }
+ return ret;
}
}
virDomainEventStateUnlock(state);
}
+
+/**
+ * virDomainEventStateDeregister:
+ * @state: domain event state
+ * @conn: connection to associate with callback
+ * @callback: function to remove from event
+ *
+ * Unregister the function @callback with connection @conn,
+ * from @state, for lifecycle events.
+ *
+ * Returns: the number of lifecycle callbacks still registered, or -1 on error
+ */
int
virDomainEventStateDeregister(virConnectPtr conn,
virDomainEventStatePtr state,
return ret;
}
+
+/**
+ * virDomainEventStateDeregisterAny:
+ * @state: domain event state
+ * @conn: connection to associate with callback
+ * @callbackID: ID of the function to remove from event
+ *
+ * Unregister the function @callbackID with connection @conn,
+ * from @state, for lifecycle events.
+ *
+ * Returns: the number of lifecycle callbacks still registered, or -1 on error
+ */
int
virDomainEventStateDeregisterAny(virConnectPtr conn,
virDomainEventStatePtr state,
#else /* !(VBOX_API_VERSION == 2002) */
- /* An array of callbacks */
- virDomainEventCallbackListPtr domainEventCallbacks;
-
+ /* Async event handling */
+ virDomainEventStatePtr domainEvents;
int fdWatch;
- int domainEventDispatching;
# if VBOX_API_VERSION <= 3002
/* IVirtualBoxCallback is used in VirtualBox 3.x only */
#if VBOX_API_VERSION == 2002
/* No domainEventCallbacks in 2.2.* version */
#else /* !(VBOX_API_VERSION == 2002) */
- VIR_FREE(data->domainEventCallbacks);
+ virDomainEventStateFree(data->domainEvents);
#endif /* !(VBOX_API_VERSION == 2002) */
VIR_FREE(data);
}
+
+#if VBOX_API_VERSION == 2002
+ /* No domainEventCallbacks in 2.2.* version */
+#else /* !(VBOX_API_VERSION == 2002) */
+
+static void
+vboxDomainEventDispatchFunc(virConnectPtr conn,
+ virDomainEventPtr event,
+ virConnectDomainEventGenericCallback cb,
+ void *cbopaque,
+ void *opaque)
+{
+ vboxGlobalData *data = opaque;
+
+ /*
+ * Release the lock while the callback is running so that
+ * we're re-entrant safe for callback work - the callback
+ * may want to invoke other virt functions & we have already
+ * protected the one piece of state we have - the callback
+ * list
+ */
+ vboxDriverUnlock(data);
+ virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+ vboxDriverLock(data);
+}
+
+
+static void vboxDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ vboxGlobalData *data = conn->privateData;
+
+ vboxDriverLock(data);
+ virDomainEventStateFlush(data->domainEvents,
+ vboxDomainEventDispatchFunc,
+ data);
+ vboxDriverUnlock(data);
+}
+#endif /* !(VBOX_API_VERSION == 2002) */
+
+
static virDrvOpenStatus vboxOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
#else /* !(VBOX_API_VERSION == 2002) */
- if (VIR_ALLOC(data->domainEventCallbacks) < 0) {
- virReportOOMError();
+ if (!(data->domainEvents = virDomainEventStateNew(vboxDomainEventFlush,
+ data,
+ NULL,
+ true))) {
+ vboxUninitialize(data);
return VIR_DRV_OPEN_ERROR;
}
int event = 0;
int detail = 0;
- g_pVBoxGlobalData->domainEventDispatching = 1;
vboxDriverLock(g_pVBoxGlobalData);
VIR_DEBUG("IVirtualBoxCallback: %p, State: %d", pThis, state);
ev = virDomainEventNewFromDom(dom, event, detail);
- if (ev) {
- virDomainEventDispatch(ev,
- g_pVBoxGlobalData->domainEventCallbacks,
- virDomainEventDispatchDefaultFunc,
- NULL);
- virDomainEventFree(ev);
- }
+ if (ev)
+ virDomainEventStateQueue(g_pVBoxGlobalData->domainEvents, ev);
}
}
- virDomainEventCallbackListPurgeMarked(g_pVBoxGlobalData->domainEventCallbacks);
-
vboxDriverUnlock(g_pVBoxGlobalData);
- g_pVBoxGlobalData->domainEventDispatching = 0;
return NS_OK;
}
int event = 0;
int detail = 0;
- g_pVBoxGlobalData->domainEventDispatching = 1;
vboxDriverLock(g_pVBoxGlobalData);
VIR_DEBUG("IVirtualBoxCallback: %p, registered: %s", pThis, registered ? "true" : "false");
ev = virDomainEventNewFromDom(dom, event, detail);
- if (ev) {
- virDomainEventDispatch(ev,
- g_pVBoxGlobalData->domainEventCallbacks,
- virDomainEventDispatchDefaultFunc,
- NULL);
- virDomainEventFree(ev);
- }
+ if (ev)
+ virDomainEventStateQueue(g_pVBoxGlobalData->domainEvents, ev);
}
}
- virDomainEventCallbackListPurgeMarked(g_pVBoxGlobalData->domainEventCallbacks);
-
vboxDriverUnlock(g_pVBoxGlobalData);
- g_pVBoxGlobalData->domainEventDispatching = 0;
return NS_OK;
}
* later you can iterate over them
*/
- ret = virDomainEventCallbackListAdd(conn, data->domainEventCallbacks,
+ ret = virDomainEventCallbackListAdd(conn, data->domainEvents->callbacks,
callback, opaque, freecb);
VIR_DEBUG("virDomainEventCallbackListAdd (ret = %d) ( conn: %p, "
- "data->domainEventCallbacks: %p, callback: %p, opaque: %p, "
- "freecb: %p )", ret, conn, data->domainEventCallbacks, callback,
+ "data->domainEvents->callbacks: %p, callback: %p, opaque: %p, "
+ "freecb: %p )", ret, conn, data->domainEvents->callbacks, callback,
opaque, freecb);
}
}
static int vboxDomainEventDeregister (virConnectPtr conn,
virConnectDomainEventCallback callback) {
VBOX_OBJECT_CHECK(conn, int, -1);
+ int cnt;
/* Locking has to be there as callbacks are not
* really fully thread safe
*/
vboxDriverLock(data);
- if (data->domainEventDispatching)
- ret = virDomainEventCallbackListMarkDelete(conn, data->domainEventCallbacks,
- callback);
- else
- ret = virDomainEventCallbackListRemove(conn, data->domainEventCallbacks,
- callback);
+ cnt = virDomainEventStateDeregister(conn, data->domainEvents,
+ callback);
- if (data->vboxCallback) {
- /* check count here of how many times register was called
- * and only on the last de-register do the un-register call
- */
- if (data->domainEventCallbacks && virDomainEventCallbackListCount(data->domainEventCallbacks) == 0) {
- data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
- VBOX_RELEASE(data->vboxCallback);
+ if (data->vboxCallback && cnt == 0) {
+ data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
+ VBOX_RELEASE(data->vboxCallback);
- /* Remove the Event file handle on which we are listening as well */
- virEventRemoveHandle(data->fdWatch);
- data->fdWatch = -1;
- }
+ /* Remove the Event file handle on which we are listening as well */
+ virEventRemoveHandle(data->fdWatch);
+ data->fdWatch = -1;
}
vboxDriverUnlock(data);
* later you can iterate over them
*/
- ret = virDomainEventCallbackListAddID(conn, data->domainEventCallbacks,
+ ret = virDomainEventCallbackListAddID(conn, data->domainEvents->callbacks,
dom, eventID,
callback, opaque, freecb);
VIR_DEBUG("virDomainEventCallbackListAddID (ret = %d) ( conn: %p, "
- "data->domainEventCallbacks: %p, callback: %p, opaque: %p, "
- "freecb: %p )", ret, conn, data->domainEventCallbacks, callback,
+ "data->domainEvents->callbacks: %p, callback: %p, opaque: %p, "
+ "freecb: %p )", ret, conn, data->domainEvents->callbacks, callback,
opaque, freecb);
}
}
static int vboxDomainEventDeregisterAny(virConnectPtr conn,
int callbackID) {
VBOX_OBJECT_CHECK(conn, int, -1);
+ int cnt;
/* Locking has to be there as callbacks are not
* really fully thread safe
*/
vboxDriverLock(data);
- if (data->domainEventDispatching)
- ret = virDomainEventCallbackListMarkDeleteID(conn, data->domainEventCallbacks,
- callbackID);
- else
- ret = virDomainEventCallbackListRemoveID(conn, data->domainEventCallbacks,
- callbackID);
+ cnt = virDomainEventStateDeregisterAny(conn, data->domainEvents,
+ callbackID);
- if (data->vboxCallback) {
- /* check count here of how many times register was called
- * and only on the last de-register do the un-register call
- */
- if (data->domainEventCallbacks && virDomainEventCallbackListCount(data->domainEventCallbacks) == 0) {
- data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
- VBOX_RELEASE(data->vboxCallback);
+ if (data->vboxCallback && cnt == 0) {
+ data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
+ VBOX_RELEASE(data->vboxCallback);
- /* Remove the Event file handle on which we are listening as well */
- virEventRemoveHandle(data->fdWatch);
- data->fdWatch = -1;
- }
+ /* Remove the Event file handle on which we are listening as well */
+ virEventRemoveHandle(data->fdWatch);
+ data->fdWatch = -1;
}
vboxDriverUnlock(data);
xenUnifiedDomainGetVcpus (virDomainPtr dom,
virVcpuInfoPtr info, int maxinfo,
unsigned char *cpumaps, int maplen);
+static void xenDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque);
+
/* The five Xen drivers below us. */
static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
}
#endif
+
+
static virDrvOpenStatus
xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
{
int i, ret = VIR_DRV_OPEN_DECLINED;
xenUnifiedPrivatePtr priv;
- virDomainEventCallbackListPtr cbList;
#ifdef __sun
/*
return VIR_DRV_OPEN_ERROR;
}
- /* Allocate callback list */
- if (VIR_ALLOC(cbList) < 0) {
- virReportOOMError();
+ if (!(priv->domainEvents = virDomainEventStateNew(xenDomainEventFlush,
+ priv,
+ NULL,
+ false))) {
virMutexDestroy(&priv->lock);
VIR_FREE(priv);
return VIR_DRV_OPEN_ERROR;
}
conn->privateData = priv;
- priv->domainEventCallbacks = cbList;
-
priv->handle = -1;
priv->xendConfigVersion = -1;
priv->xshandle = NULL;
int i;
virCapabilitiesFree(priv->caps);
- virDomainEventCallbackListFree(priv->domainEventCallbacks);
+ virDomainEventStateFree(priv->domainEvents);
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i])
return -1;
}
- ret = virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
+ ret = virDomainEventCallbackListAdd(conn, priv->domainEvents->callbacks,
callback, opaque, freefunc);
xenUnifiedUnlock(priv);
return -1;
}
- if (priv->domainEventDispatching)
- ret = virDomainEventCallbackListMarkDelete(conn, priv->domainEventCallbacks,
- callback);
- else
- ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
- callback);
+ ret = virDomainEventStateDeregister(conn,
+ priv->domainEvents,
+ callback);
xenUnifiedUnlock(priv);
return ret;
return -1;
}
- ret = virDomainEventCallbackListAddID(conn, priv->domainEventCallbacks,
+ ret = virDomainEventCallbackListAddID(conn, priv->domainEvents->callbacks,
dom, eventID,
callback, opaque, freefunc);
return -1;
}
- if (priv->domainEventDispatching)
- ret = virDomainEventCallbackListMarkDeleteID(conn, priv->domainEventCallbacks,
- callbackID);
- else
- ret = virDomainEventCallbackListRemoveID(conn, priv->domainEventCallbacks,
- callbackID);
+ ret = virDomainEventStateDeregisterAny(conn,
+ priv->domainEvents,
+ callbackID);
xenUnifiedUnlock(priv);
return ret;
return -1;
}
+
static void
xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
virDomainEventPtr event,
xenUnifiedLock(priv);
}
+static void xenDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ xenUnifiedPrivatePtr priv = conn->privateData;
+
+ xenUnifiedLock(priv);
+ virDomainEventStateFlush(priv->domainEvents,
+ xenUnifiedDomainEventDispatchFunc,
+ priv);
+ xenUnifiedUnlock(priv);
+}
+
+
/**
* xenUnifiedDomainEventDispatch:
* @priv: the connection to dispatch events on
if (!priv)
return;
- priv->domainEventDispatching = 1;
-
- if (priv->domainEventCallbacks) {
- virDomainEventDispatch(event,
- priv->domainEventCallbacks,
- xenUnifiedDomainEventDispatchFunc,
- priv);
-
- /* Purge any deleted callbacks */
- virDomainEventCallbackListPurgeMarked(priv->domainEventCallbacks);
- }
-
- virDomainEventFree(event);
-
- priv->domainEventDispatching = 0;
+ virDomainEventStateQueue(priv->domainEvents, event);
}
void xenUnifiedLock(xenUnifiedPrivatePtr priv)