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));
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);
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);
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);
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);
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));
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);
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));
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);
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++) {
}
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);
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));
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);
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);
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));
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);
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));
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);
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);
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);
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);
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);
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));
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);
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;
void *opaque ATTRIBUTE_UNUSED)
{
struct daemonClientPrivate *priv;
- size_t i;
if (VIR_ALLOC(priv) < 0)
return NULL;
return NULL;
}
- for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++)
- priv->domainEventCallbackID[i] = -1;
-
virNetServerClientSetCloseHook(client, remoteClientCloseFunc);
return priv;
}
***************************/
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);
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);
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);
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;
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);
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);
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);
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;