void *opaque;
virFreeCallback freecb;
bool deleted;
+ bool legacy; /* true if end user does not know callbackID */
};
static virClassPtr virObjectEventClass;
* Internal function to count how many callbacks remain registered for
* the given @eventID; knowing this allows the client side of the
* remote driver know when it must send an RPC to adjust the callbacks
- * on the server.
+ * on the server. Note that this function intentionally ignores
+ * the legacy field, since RPC calls use only a single callback on
+ * the server to manage both legacy and modern domain lifecycle events.
*/
static int
virObjectEventCallbackListCount(virConnectPtr conn,
* @klass: the base event class
* @eventID: the event ID
* @callback: the callback to locate
+ * @legacy: true if callback is tracked by function instead of callbackID
*
* Internal function to determine if @callback already has a
* callbackID in @cbList for the given @conn and other filters.
unsigned char uuid[VIR_UUID_BUFLEN],
virClassPtr klass,
int eventID,
- virConnectObjectEventGenericCallback callback)
+ virConnectObjectEventGenericCallback callback,
+ bool legacy)
{
int ret = -1;
size_t i;
cb->klass == klass &&
cb->eventID == eventID &&
cb->conn == conn &&
+ cb->legacy == legacy &&
((uuid && cb->meta &&
memcmp(cb->meta->uuid, uuid, VIR_UUID_BUFLEN) == 0) ||
(!uuid && !cb->meta))) {
/* check if we already have this callback on our list */
if (virObjectEventCallbackLookup(conn, cbList, uuid,
- klass, eventID, callback) != -1) {
+ klass, eventID, callback,
+ !callbackID) != -1) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("event callback already tracked"));
return -1;
if (callbackID)
*callbackID = event->callbackID;
+ else
+ event->legacy = true;
if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, event) < 0)
goto cleanup;
* @callback: function registered as a callback
*
* Returns the callbackID of @callback, or -1 with an error issued if the
- * function is not currently registered.
+ * function is not currently registered. This only finds functions
+ * registered via virConnectDomainEventRegister, even if modern style
+ * virConnectDomainEventRegisterAny also registers the same callback.
*/
int
virObjectEventStateCallbackID(virConnectPtr conn,
virObjectEventStateLock(state);
ret = virObjectEventCallbackLookup(conn, state->callbacks, NULL,
- klass, eventID, callback);
+ klass, eventID, callback, true);
virObjectEventStateUnlock(state);
if (ret < 0)
lifecycleEventCounter counter;
virDomainPtr dom;
int ret = -1;
- int id = -1;
+ int id1 = -1;
+ int id2 = -1;
bool registered = false;
lifecycleEventCounter_reset(&counter);
- /* Fun with mixing old and new API. Handler should be fired twice,
- * once for each registration. */
- if (!(dom = virDomainCreateXML(test->conn, domainDef, 0)))
+ /* Fun with mixing old and new API, also with global and
+ * per-domain. Handler should be fired three times, once for each
+ * registration. */
+ dom = virDomainCreateXML(test->conn, domainDef, 0);
+ if (dom == NULL)
goto cleanup;
- id = virConnectDomainEventRegisterAny(test->conn, dom,
- VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+ id1 = virConnectDomainEventRegisterAny(test->conn, dom,
+ VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(&domainLifecycleCb),
- &counter, NULL);
- if (id < 0)
+ &counter, NULL);
+ if (id1 < 0)
goto cleanup;
if (virDomainDestroy(dom) < 0)
goto cleanup;
&counter, NULL) != 0)
goto cleanup;
registered = true;
+ id2 = virConnectDomainEventRegisterAny(test->conn, NULL,
+ VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+ VIR_DOMAIN_EVENT_CALLBACK(&domainLifecycleCb),
+ &counter, NULL);
+ if (id2 < 0)
+ goto cleanup;
dom = virDomainCreateXML(test->conn, domainDef, 0);
if (dom == NULL || virEventRunDefaultImpl() < 0)
goto cleanup;
- if (counter.startEvents != 2 || counter.unexpectedEvents > 0)
+ if (counter.startEvents != 3 || counter.unexpectedEvents > 0)
goto cleanup;
if (virConnectDomainEventDeregister(test->conn, domainLifecycleCb) != 0)
goto cleanup;
registered = false;
- if (virConnectDomainEventDeregisterAny(test->conn, id) != 0)
+ if (virConnectDomainEventDeregisterAny(test->conn, id1) != 0)
goto cleanup;
- id = -1;
+ id1 = -1;
+ if (virConnectDomainEventDeregisterAny(test->conn, id2) != 0)
+ goto cleanup;
+ id2 = -1;
ret = 0;
cleanup:
- if (id >= 0)
- virConnectDomainEventDeregisterAny(test->conn, id);
+ if (id1 >= 0)
+ virConnectDomainEventDeregisterAny(test->conn, id1);
+ if (id2 >= 0)
+ virConnectDomainEventDeregisterAny(test->conn, id2);
if (registered)
virConnectDomainEventDeregister(test->conn, domainLifecycleCb);
if (dom != NULL) {