diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index d204c80ece..d619fd745a 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1439,10 +1439,10 @@ cleanup: static int -lxcDomainEventRegister (virConnectPtr conn, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) +lxcDomainEventRegister(virConnectPtr conn, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) { lxc_driver_t *driver = conn->privateData; int ret; @@ -1455,9 +1455,10 @@ lxcDomainEventRegister (virConnectPtr conn, return ret; } + static int -lxcDomainEventDeregister (virConnectPtr conn, - virConnectDomainEventCallback callback) +lxcDomainEventDeregister(virConnectPtr conn, + virConnectDomainEventCallback callback) { lxc_driver_t *driver = conn->privateData; int ret; @@ -1474,6 +1475,49 @@ lxcDomainEventDeregister (virConnectPtr conn, return ret; } + +static int +lxcDomainEventRegisterAny(virConnectPtr conn, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) +{ + lxc_driver_t *driver = conn->privateData; + int ret; + + lxcDriverLock(driver); + ret = virDomainEventCallbackListAddID(conn, + driver->domainEventCallbacks, + dom, eventID, + callback, opaque, freecb); + lxcDriverUnlock(driver); + + return ret; +} + + +static int +lxcDomainEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + lxc_driver_t *driver = conn->privateData; + int ret; + + lxcDriverLock(driver); + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDeleteID(conn, driver->domainEventCallbacks, + callbackID); + else + ret = virDomainEventCallbackListRemoveID(conn, driver->domainEventCallbacks, + callbackID); + lxcDriverUnlock(driver); + + return ret; +} + + static void lxcDomainEventDispatchFunc(virConnectPtr conn, virDomainEventPtr event, virConnectDomainEventGenericCallback cb, @@ -2460,8 +2504,8 @@ static virDriver lxcDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ - NULL, /* domainEventRegisterAny */ - NULL, /* domainEventDeregisterAny */ + lxcDomainEventRegisterAny, /* domainEventRegisterAny */ + lxcDomainEventDeregisterAny, /* domainEventDeregisterAny */ }; static virStateDriver lxcStateDriver = { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 576cb6d2f7..cfd82da17d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7966,10 +7966,10 @@ cleanup: static int -qemudDomainEventRegister (virConnectPtr conn, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) +qemuDomainEventRegister(virConnectPtr conn, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) { struct qemud_driver *driver = conn->privateData; int ret; @@ -7982,9 +7982,10 @@ qemudDomainEventRegister (virConnectPtr conn, return ret; } + static int -qemudDomainEventDeregister (virConnectPtr conn, - virConnectDomainEventCallback callback) +qemuDomainEventDeregister(virConnectPtr conn, + virConnectDomainEventCallback callback) { struct qemud_driver *driver = conn->privateData; int ret; @@ -8001,6 +8002,49 @@ qemudDomainEventDeregister (virConnectPtr conn, return ret; } + +static int +qemuDomainEventRegisterAny(virConnectPtr conn, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) +{ + struct qemud_driver *driver = conn->privateData; + int ret; + + qemuDriverLock(driver); + ret = virDomainEventCallbackListAddID(conn, + driver->domainEventCallbacks, + dom, eventID, + callback, opaque, freecb); + qemuDriverUnlock(driver); + + return ret; +} + + +static int +qemuDomainEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + struct qemud_driver *driver = conn->privateData; + int ret; + + qemuDriverLock(driver); + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDeleteID(conn, driver->domainEventCallbacks, + callbackID); + else + ret = virDomainEventCallbackListRemoveID(conn, driver->domainEventCallbacks, + callbackID); + qemuDriverUnlock(driver); + + return ret; +} + + static void qemuDomainEventDispatchFunc(virConnectPtr conn, virDomainEventPtr event, virConnectDomainEventGenericCallback cb, @@ -9659,8 +9703,8 @@ static virDriver qemuDriver = { qemudDomainMemoryPeek, /* domainMemoryPeek */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ - qemudDomainEventRegister, /* domainEventRegister */ - qemudDomainEventDeregister, /* domainEventDeregister */ + qemuDomainEventRegister, /* domainEventRegister */ + qemuDomainEventDeregister, /* domainEventDeregister */ qemudDomainMigratePrepare2, /* domainMigratePrepare2 */ qemudDomainMigrateFinish2, /* domainMigrateFinish2 */ qemudNodeDeviceDettach, /* nodeDeviceDettach */ @@ -9676,8 +9720,8 @@ static virDriver qemuDriver = { qemuDomainGetJobInfo, /* domainGetJobInfo */ qemuDomainAbortJob, /* domainAbortJob */ qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ - NULL, /* domainEventRegisterAny */ - NULL, /* domainEventDeregisterAny */ + qemuDomainEventRegisterAny, /* domainEventRegisterAny */ + qemuDomainEventDeregisterAny, /* domainEventDeregisterAny */ }; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index ada206edc3..204265f286 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5053,10 +5053,10 @@ out: /* Domain event implementations */ static int -testDomainEventRegister (virConnectPtr conn, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) +testDomainEventRegister(virConnectPtr conn, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) { testConnPtr driver = conn->privateData; int ret; @@ -5069,9 +5069,10 @@ testDomainEventRegister (virConnectPtr conn, return ret; } + static int -testDomainEventDeregister (virConnectPtr conn, - virConnectDomainEventCallback callback) +testDomainEventDeregister(virConnectPtr conn, + virConnectDomainEventCallback callback) { testConnPtr driver = conn->privateData; int ret; @@ -5088,6 +5089,47 @@ testDomainEventDeregister (virConnectPtr conn, return ret; } + +static int +testDomainEventRegisterAny(virConnectPtr conn, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) +{ + testConnPtr driver = conn->privateData; + int ret; + + testDriverLock(driver); + ret = virDomainEventCallbackListAddID(conn, driver->domainEventCallbacks, + dom, eventID, + callback, opaque, freecb); + testDriverUnlock(driver); + + return ret; +} + +static int +testDomainEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + testConnPtr driver = conn->privateData; + int ret; + + testDriverLock(driver); + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDeleteID(conn, driver->domainEventCallbacks, + callbackID); + else + ret = virDomainEventCallbackListRemoveID(conn, driver->domainEventCallbacks, + callbackID); + testDriverUnlock(driver); + + return ret; +} + + static void testDomainEventDispatchFunc(virConnectPtr conn, virDomainEventPtr event, virConnectDomainEventGenericCallback cb, @@ -5245,8 +5287,8 @@ static virDriver testDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ - NULL, /* domainEventRegisterAny */ - NULL, /* domainEventDeregisterAny */ + testDomainEventRegisterAny, /* domainEventRegisterAny */ + testDomainEventDeregisterAny, /* domainEventDeregisterAny */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index cb71f354f1..2e81f42d51 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -5431,6 +5431,107 @@ static int vboxDomainEventDeregister (virConnectPtr conn, return ret; } +static int vboxDomainEventRegisterAny(virConnectPtr conn, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) { + VBOX_OBJECT_CHECK(conn, int, -1); + int vboxRet = -1; + nsresult rc; + + /* Locking has to be there as callbacks are not + * really fully thread safe + */ + vboxDriverLock(data); + + if (data->vboxCallback == NULL) { + data->vboxCallback = vboxAllocCallbackObj(); + if (data->vboxCallback != NULL) { + rc = data->vboxObj->vtbl->RegisterCallback(data->vboxObj, data->vboxCallback); + if (NS_SUCCEEDED(rc)) { + vboxRet = 0; + } + } + } else { + vboxRet = 0; + } + + /* Get the vbox file handle and add a event handle to it + * so that the events can be passed down to the user + */ + if (vboxRet == 0) { + if (data->fdWatch < 0) { + PRInt32 vboxFileHandle; + vboxFileHandle = data->vboxQueue->vtbl->GetEventQueueSelectFD(data->vboxQueue); + + data->fdWatch = virEventAddHandle(vboxFileHandle, VIR_EVENT_HANDLE_READABLE, vboxReadCallback, NULL, NULL); + } + + if (data->fdWatch >= 0) { + /* Once a callback is registered with virtualbox, use a list + * to store the callbacks registered with libvirt so that + * later you can iterate over them + */ + + ret = virDomainEventCallbackListAddID(conn, data->domainEventCallbacks, + dom, eventID, + callback, opaque, freecb); + DEBUG("virDomainEventCallbackListAddID (ret = %d) ( conn: %p, " + "data->domainEventCallbacks: %p, callback: %p, opaque: %p, " + "freecb: %p )", ret, conn, data->domainEventCallbacks, callback, + opaque, freecb); + } + } + + vboxDriverUnlock(data); + + if (ret >= 0) { + return ret; + } else { + if (data->vboxObj && data->vboxCallback) { + data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback); + } + return -1; + } +} + +static int vboxDomainEventDeregisterAny(virConnectPtr conn, + int callbackID) { + VBOX_OBJECT_CHECK(conn, int, -1); + + /* 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); + + 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); + + /* Remove the Event file handle on which we are listening as well */ + virEventRemoveHandle(data->fdWatch); + data->fdWatch = -1; + } + } + + vboxDriverUnlock(data); + + return ret; +} + #endif /* !(VBOX_API_VERSION == 2002) */ /** @@ -7062,8 +7163,13 @@ virDriver NAME(Driver) = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ +#if VBOX_API_VERSION == 2002 NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ +#else + vboxDomainEventRegisterAny, /* domainEventRegisterAny */ + vboxDomainEventDeregisterAny, /* domainEventDeregisterAny */ +#endif }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index ccb5faea96..f4e65c44f8 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1656,11 +1656,12 @@ xenUnifiedNodeGetFreeMemory (virConnectPtr conn) return(0); } + static int -xenUnifiedDomainEventRegister (virConnectPtr conn, - virConnectDomainEventCallback callback, - void *opaque, - void (*freefunc)(void *)) +xenUnifiedDomainEventRegister(virConnectPtr conn, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freefunc) { GET_PRIVATE (conn); @@ -1680,9 +1681,10 @@ xenUnifiedDomainEventRegister (virConnectPtr conn, return (ret); } + static int -xenUnifiedDomainEventDeregister (virConnectPtr conn, - virConnectDomainEventCallback callback) +xenUnifiedDomainEventDeregister(virConnectPtr conn, + virConnectDomainEventCallback callback) { int ret; GET_PRIVATE (conn); @@ -1706,6 +1708,59 @@ xenUnifiedDomainEventDeregister (virConnectPtr conn, } +static int +xenUnifiedDomainEventRegisterAny(virConnectPtr conn, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback callback, + void *opaque, + virFreeCallback freefunc) +{ + GET_PRIVATE (conn); + + int ret; + xenUnifiedLock(priv); + + if (priv->xsWatch == -1) { + xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + xenUnifiedUnlock(priv); + return -1; + } + + ret = virDomainEventCallbackListAddID(conn, priv->domainEventCallbacks, + dom, eventID, + callback, opaque, freefunc); + + xenUnifiedUnlock(priv); + return (ret); +} + +static int +xenUnifiedDomainEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + int ret; + GET_PRIVATE (conn); + xenUnifiedLock(priv); + + if (priv->xsWatch == -1) { + xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + xenUnifiedUnlock(priv); + return -1; + } + + if (priv->domainEventDispatching) + ret = virDomainEventCallbackListMarkDeleteID(conn, priv->domainEventCallbacks, + callbackID); + else + ret = virDomainEventCallbackListRemoveID(conn, priv->domainEventCallbacks, + callbackID); + + xenUnifiedUnlock(priv); + return ret; +} + + static int xenUnifiedNodeDeviceGetPciInfo (virNodeDevicePtr dev, unsigned *domain, @@ -1907,8 +1962,8 @@ static virDriver xenUnifiedDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ - NULL, /* domainEventRegisterAny */ - NULL, /* domainEventDeregisterAny */ + xenUnifiedDomainEventRegisterAny, /* domainEventRegisterAny */ + xenUnifiedDomainEventDeregisterAny, /* domainEventDeregisterAny */ }; /**