This patch continues the earlier conversion made for network events, with a goal of introducing server-side event filtering in a later patch. Actual behavior is unchanged without further RPC changes. * daemon/libvirtd.h (daemonClientPrivate): Alter the tracking of domain events. * daemon/remote.c (remoteClientInitHook, remoteClientFreeFunc) (remoteRelayDomainEvent*) (remoteDispatchConnectDomainEventRegister) (remoteDispatchConnectDomainEventRegisterAny): Track domain callbacks dynamically. --- daemon/libvirtd.h | 3 +- daemon/remote.c | 436 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 266 insertions(+), 173 deletions(-) diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index a260ea1..c4f1f27 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -51,7 +51,8 @@ struct daemonClientPrivate { /* Hold while accessing any data except conn */ virMutex lock; - int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST]; + daemonClientEventCallbackPtr *domainEventCallbacks; + size_t ndomainEventCallbacks; daemonClientEventCallbackPtr *networkEventCallbacks; size_t nnetworkEventCallbacks; diff --git a/daemon/remote.c b/daemon/remote.c index d2aafbe..f0b9922 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -127,19 +127,21 @@ remoteEventCallbackFree(void *opaque) VIR_FREE(opaque); } -static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int event, - int detail, - void *opaque) +static int +remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int event, + int detail, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_lifecycle_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain lifecycle event %d %d", event, detail); + VIR_DEBUG("Relaying domain lifecycle event %d %d, callback %d", + event, detail, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -147,30 +149,32 @@ static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, data.event = event; data.detail = detail; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data); return 0; } -static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - void *opaque) +static int +remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_reboot_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain reboot event %s %d", dom->name, dom->id); + VIR_DEBUG("Relaying domain reboot event %s %d, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_REBOOT, (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data); @@ -178,25 +182,27 @@ static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - long long offset, - void *opaque) +static int +remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + long long offset, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_rtc_change_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain rtc change event %s %d %lld", dom->name, dom->id, offset); + VIR_DEBUG("Relaying domain rtc change event %s %d %lld, callback %d", + dom->name, dom->id, offset, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.offset = offset; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data); @@ -204,25 +210,27 @@ static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int action, - void *opaque) +static int +remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int action, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_watchdog_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain watchdog event %s %d %d", dom->name, dom->id, action); + VIR_DEBUG("Relaying domain watchdog event %s %d %d, callback %d", + dom->name, dom->id, action, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_WATCHDOG, (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data); @@ -230,20 +238,23 @@ static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - void *opaque) +static int +remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_io_error_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain io error %s %d %s %s %d", dom->name, dom->id, srcPath, devAlias, action); + VIR_DEBUG("Relaying domain io error %s %d %s %s %d, callback %d", + dom->name, dom->id, srcPath, devAlias, action, + callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -253,7 +264,7 @@ static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_IO_ERROR, (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data); @@ -265,22 +276,24 @@ error: } -static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - const char *reason, - void *opaque) +static int +remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + const char *reason, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_io_error_reason_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain io error %s %d %s %s %d %s", - dom->name, dom->id, srcPath, devAlias, action, reason); + VIR_DEBUG("Relaying domain io error %s %d %s %s %d %s, callback %d", + dom->name, dom->id, srcPath, devAlias, action, reason, + callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -292,7 +305,7 @@ static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUS make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data); @@ -306,26 +319,28 @@ error: } -static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject, - void *opaque) +static int +remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_graphics_msg data; size_t i; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s - %d %s %s - %s", dom->name, dom->id, phase, + VIR_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s - %d %s %s - %s, callback %d", + dom->name, dom->id, phase, local->family, local->service, local->node, remote->family, remote->service, remote->node, - authScheme); + authScheme, callback->callbackID); VIR_DEBUG("Subject %d", subject->nidentity); for (i = 0; i < subject->nidentity; i++) { @@ -355,7 +370,7 @@ static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, } make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_GRAPHICS, (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data); @@ -377,21 +392,22 @@ error: return -1; } -static int remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *path, - int type, - int status, - void *opaque) +static int +remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *path, + int type, + int status, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_block_job_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain block job event %s %d %s %i, %i", - dom->name, dom->id, path, type, status); + VIR_DEBUG("Relaying domain block job event %s %d %s %i, %i, callback %d", + dom->name, dom->id, path, type, status, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -401,7 +417,7 @@ static int remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, data.status = status; make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB, (xdrproc_t)xdr_remote_domain_event_block_job_msg, &data); @@ -412,23 +428,25 @@ error: } -static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - void *opaque) +static int +remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_control_error_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain control error %s %d", dom->name, dom->id); + VIR_DEBUG("Relaying domain control error %s %d, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR, (xdrproc_t)xdr_remote_domain_event_control_error_msg, &data); @@ -436,23 +454,25 @@ static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSE } -static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason, - void *opaque) +static int +remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason, + void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_disk_change_msg data; char **oldSrcPath_p = NULL, **newSrcPath_p = NULL; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain %s %d disk change %s %s %s %d", - dom->name, dom->id, oldSrcPath, newSrcPath, devAlias, reason); + VIR_DEBUG("Relaying domain %s %d disk change %s %s %s %d, callback %d", + dom->name, dom->id, oldSrcPath, newSrcPath, devAlias, reason, + callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -474,7 +494,7 @@ static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE, (xdrproc_t)xdr_remote_domain_event_disk_change_msg, &data); @@ -487,19 +507,21 @@ error: } -static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *devAlias, - int reason, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *devAlias, + int reason, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_tray_change_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain %s %d tray change devAlias: %s reason: %d", - dom->name, dom->id, devAlias, reason); + VIR_DEBUG("Relaying domain %s %d tray change devAlias: %s reason: %d, callback %d", + dom->name, dom->id, devAlias, reason, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -510,53 +532,59 @@ static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE, (xdrproc_t)xdr_remote_domain_event_tray_change_msg, &data); return 0; } -static int remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmwakeup_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain %s %d system pmwakeup", dom->name, dom->id); + VIR_DEBUG("Relaying domain %s %d system pmwakeup, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP, (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg, &data); return 0; } -static int remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmsuspend_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain %s %d system pmsuspend", dom->name, dom->id); + VIR_DEBUG("Relaying domain %s %d system pmsuspend, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND, (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg, &data); @@ -569,20 +597,21 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long long actual, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_balloon_change_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain balloon change event %s %d %lld", dom->name, dom->id, actual); + VIR_DEBUG("Relaying domain balloon change event %s %d %lld, callback %d", + dom->name, dom->id, actual, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); data.actual = actual; - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE, (xdrproc_t)xdr_remote_domain_event_balloon_change_msg, &data); @@ -590,23 +619,26 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { - virNetServerClientPtr client = opaque; +static int +remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_pmsuspend_disk_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain %s %d system pmsuspend-disk", dom->name, dom->id); + VIR_DEBUG("Relaying domain %s %d system pmsuspend-disk, callback %d", + dom->name, dom->id, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK, (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg, &data); @@ -619,14 +651,14 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, const char *devAlias, void *opaque) { - virNetServerClientPtr client = opaque; + daemonClientEventCallbackPtr callback = opaque; remote_domain_event_device_removed_msg data; - if (!client) + if (callback->callbackID < 0) return -1; - VIR_DEBUG("Relaying domain device removed event %s %d %s", - dom->name, dom->id, devAlias); + VIR_DEBUG("Relaying domain device removed event %s %d %s, callback %d", + dom->name, dom->id, devAlias, callback->callbackID); /* build return data */ memset(&data, 0, sizeof(data)); @@ -636,7 +668,7 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); - remoteDispatchObjectEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(callback->client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, (xdrproc_t)xdr_remote_domain_event_device_removed_msg, &data); @@ -720,14 +752,19 @@ void remoteClientFreeFunc(void *data) virIdentitySetCurrent(sysident); - for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++) { - if (priv->domainEventCallbackID[i] != -1) { - VIR_DEBUG("Deregistering to relay remote events %zu", i); - virConnectDomainEventDeregisterAny(priv->conn, - priv->domainEventCallbackID[i]); + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + int callbackID = priv->domainEventCallbacks[i]->callbackID; + if (callbackID < 0) { + VIR_WARN("unexpected incomplete domain callback %zu", i); + continue; } - priv->domainEventCallbackID[i] = -1; + VIR_DEBUG("Deregistering remote domain event relay %d", + callbackID); + priv->domainEventCallbacks[i]->callbackID = -1; + if (virConnectDomainEventDeregisterAny(priv->conn, callbackID) < 0) + VIR_WARN("unexpected domain event deregister failure"); } + VIR_FREE(priv->domainEventCallbacks); for (i = 0; i < priv->nnetworkEventCallbacks; i++) { int callbackID = priv->networkEventCallbacks[i]->callbackID; @@ -766,7 +803,6 @@ void *remoteClientInitHook(virNetServerClientPtr client, void *opaque ATTRIBUTE_UNUSED) { struct daemonClientPrivate *priv; - size_t i; if (VIR_ALLOC(priv) < 0) return NULL; @@ -777,9 +813,6 @@ void *remoteClientInitHook(virNetServerClientPtr client, return NULL; } - for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++) - priv->domainEventCallbackID[i] = -1; - virNetServerClientSetCloseHook(client, remoteClientCloseFunc); return priv; } @@ -3143,13 +3176,15 @@ cleanup: ***************************/ static int remoteDispatchConnectDomainEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_register_ret *ret ATTRIBUTE_UNUSED) { int callbackID; int rv = -1; + daemonClientEventCallbackPtr callback = NULL; + daemonClientEventCallbackPtr ref; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3160,23 +3195,41 @@ remoteDispatchConnectDomainEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED virMutexLock(&priv->lock); - if (priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] != -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d already registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE); + /* If we call register first, we could append a complete callback + * to our array, but on OOM append failure, we'd have to then hope + * deregister works to undo our register. So instead we append an + * incomplete callback to our array, then register, then fix up + * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on + * success, we use 'ref' to save a copy of the pointer. */ + if (VIR_ALLOC(callback) < 0) + goto cleanup; + callback->client = client; + callback->eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE; + callback->callbackID = -1; + ref = callback; + if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, + callback) < 0) goto cleanup; - } if ((callbackID = virConnectDomainEventRegisterAny(priv->conn, NULL, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), - client, NULL)) < 0) + ref, + remoteEventCallbackFree)) < 0) { + VIR_SHRINK_N(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, 1); + callback = ref; goto cleanup; + } - priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = callbackID; + ref->callbackID = callbackID; rv = 0; cleanup: + VIR_FREE(callback); if (rv < 0) virNetMessageSaveError(rerr); virMutexUnlock(&priv->lock); @@ -3185,12 +3238,14 @@ cleanup: static int remoteDispatchConnectDomainEventDeregister(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_deregister_ret *ret ATTRIBUTE_UNUSED) { + int callbackID = -1; int rv = -1; + size_t i; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3201,16 +3256,25 @@ remoteDispatchConnectDomainEventDeregister(virNetServerPtr server ATTRIBUTE_UNUS virMutexLock(&priv->lock); - if (priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d not registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE); + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + if (priv->domainEventCallbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE) { + callbackID = priv->domainEventCallbacks[i]->callbackID; + break; + } + } + + if (callbackID < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("domain event %d not registered"), + VIR_DOMAIN_EVENT_ID_LIFECYCLE); goto cleanup; } - if (virConnectDomainEventDeregisterAny(priv->conn, - priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE]) < 0) + if (virConnectDomainEventDeregisterAny(priv->conn, callbackID) < 0) goto cleanup; - priv->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = -1; + VIR_DELETE_ELEMENT(priv->domainEventCallbacks, i, + priv->ndomainEventCallbacks); rv = 0; @@ -3332,13 +3396,15 @@ cleanup: static int remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_register_any_args *args) { int callbackID; int rv = -1; + daemonClientEventCallbackPtr callback = NULL; + daemonClientEventCallbackPtr ref; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3355,23 +3421,41 @@ remoteDispatchConnectDomainEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNU goto cleanup; } - if (priv->domainEventCallbackID[args->eventID] != -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d already registered"), args->eventID); + /* If we call register first, we could append a complete callback + * to our array, but on OOM append failure, we'd have to then hope + * deregister works to undo our register. So instead we append an + * incomplete callback to our array, then register, then fix up + * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on + * success, we use 'ref' to save a copy of the pointer. */ + if (VIR_ALLOC(callback) < 0) + goto cleanup; + callback->client = client; + callback->eventID = args->eventID; + callback->callbackID = -1; + ref = callback; + if (VIR_APPEND_ELEMENT(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, + callback) < 0) goto cleanup; - } if ((callbackID = virConnectDomainEventRegisterAny(priv->conn, NULL, args->eventID, domainEventCallbacks[args->eventID], - client, NULL)) < 0) + ref, + remoteEventCallbackFree)) < 0) { + VIR_SHRINK_N(priv->domainEventCallbacks, + priv->ndomainEventCallbacks, 1); + callback = ref; goto cleanup; + } - priv->domainEventCallbackID[args->eventID] = callbackID; + ref->callbackID = callbackID; rv = 0; cleanup: + VIR_FREE(callback); if (rv < 0) virNetMessageSaveError(rerr); virMutexUnlock(&priv->lock); @@ -3381,13 +3465,14 @@ cleanup: static int remoteDispatchConnectDomainEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetServerClientPtr client, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, remote_connect_domain_event_deregister_any_args *args) { int callbackID = -1; int rv = -1; + size_t i; struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); @@ -3404,16 +3489,23 @@ remoteDispatchConnectDomainEventDeregisterAny(virNetServerPtr server ATTRIBUTE_U goto cleanup; } - callbackID = priv->domainEventCallbackID[args->eventID]; + for (i = 0; i < priv->ndomainEventCallbacks; i++) { + if (priv->domainEventCallbacks[i]->eventID == args->eventID) { + callbackID = priv->domainEventCallbacks[i]->callbackID; + break; + } + } if (callbackID < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain event %d not registered"), args->eventID); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("domain event %d not registered"), args->eventID); goto cleanup; } if (virConnectDomainEventDeregisterAny(priv->conn, callbackID) < 0) goto cleanup; - priv->domainEventCallbackID[args->eventID] = -1; + VIR_DELETE_ELEMENT(priv->domainEventCallbacks, i, + priv->ndomainEventCallbacks); rv = 0; -- 1.8.4.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list