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 | 294 +++++++++++++++++++++++++++++++++++-------------------
2 files changed, 194 insertions(+), 103 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 5baf0b6..be0af3d 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -192,13 +192,15 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn,
int detail,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_lifecycle_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -206,7 +208,7 @@ remoteRelayDomainEventLifecycle(virConnectPtr conn,
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);
@@ -218,19 +220,21 @@ remoteRelayDomainEventReboot(virConnectPtr conn,
virDomainPtr dom,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_reboot_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -244,20 +248,22 @@ remoteRelayDomainEventRTCChange(virConnectPtr conn,
long long offset,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_rtc_change_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -271,20 +277,22 @@ remoteRelayDomainEventWatchdog(virConnectPtr conn,
int action,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_watchdog_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -300,13 +308,16 @@ remoteRelayDomainEventIOError(virConnectPtr conn,
int action,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_io_error_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -316,7 +327,7 @@ remoteRelayDomainEventIOError(virConnectPtr conn,
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);
@@ -337,14 +348,16 @@ remoteRelayDomainEventIOErrorReason(virConnectPtr conn,
const char *reason,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_io_error_reason_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -356,7 +369,7 @@ remoteRelayDomainEventIOErrorReason(virConnectPtr conn,
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);
@@ -380,17 +393,19 @@ remoteRelayDomainEventGraphics(virConnectPtr conn,
virDomainEventGraphicsSubjectPtr subject,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_graphics_msg data;
size_t i;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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++) {
@@ -420,7 +435,7 @@ remoteRelayDomainEventGraphics(virConnectPtr conn,
}
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);
@@ -450,14 +465,15 @@ remoteRelayDomainEventBlockJob(virConnectPtr conn,
int status,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_block_job_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -467,7 +483,7 @@ remoteRelayDomainEventBlockJob(virConnectPtr conn,
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);
@@ -483,19 +499,21 @@ remoteRelayDomainEventControlError(virConnectPtr conn,
virDomainPtr dom,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_control_error_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -512,15 +530,17 @@ remoteRelayDomainEventDiskChange(virConnectPtr conn,
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 || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -542,7 +562,7 @@ remoteRelayDomainEventDiskChange(virConnectPtr conn,
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);
@@ -562,14 +582,15 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn,
int reason,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_tray_change_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -580,7 +601,7 @@ remoteRelayDomainEventTrayChange(virConnectPtr conn,
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);
@@ -593,19 +614,21 @@ remoteRelayDomainEventPMWakeup(virConnectPtr conn,
int reason ATTRIBUTE_UNUSED,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_pmwakeup_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -618,19 +641,21 @@ remoteRelayDomainEventPMSuspend(virConnectPtr conn,
int reason ATTRIBUTE_UNUSED,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_pmsuspend_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -643,20 +668,22 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn,
unsigned long long actual,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_balloon_change_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -670,19 +697,21 @@ remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn,
int reason ATTRIBUTE_UNUSED,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_pmsuspend_disk_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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);
@@ -695,14 +724,15 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn,
const char *devAlias,
void *opaque)
{
- virNetServerClientPtr client = opaque;
+ daemonClientEventCallbackPtr callback = opaque;
remote_domain_event_device_removed_msg data;
- if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom))
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
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));
@@ -712,7 +742,7 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn,
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);
@@ -797,14 +827,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;
@@ -843,7 +878,6 @@ void *remoteClientInitHook(virNetServerClientPtr client,
void *opaque ATTRIBUTE_UNUSED)
{
struct daemonClientPrivate *priv;
- size_t i;
if (VIR_ALLOC(priv) < 0)
return NULL;
@@ -854,9 +888,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;
}
@@ -3220,13 +3251,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);
@@ -3237,23 +3270,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);
@@ -3262,12 +3313,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);
@@ -3278,16 +3331,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;
@@ -3409,13 +3471,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);
@@ -3432,23 +3496,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);
@@ -3458,13 +3540,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);
@@ -3481,16 +3564,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.5.3