mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
Refactor domain events to handle multiple event types
The internal domain events APIs are designed to handle the lifecycle events. This needs to be refactored to allow arbitrary new event types to be handled. * The signature of virDomainEventDispatchFunc changes to use virConnectDomainEventGenericCallback instead of the lifecycle event specific virConnectDomainEventCallback * Every registered callback gains a unique ID to allow its removal based on ID, instead of function pointer * Every registered callback gains an 'eventID' to allow callbacks for different types of events to be distinguished * virDomainEventDispatch is adapted to filter out callbacks whose eventID does not match the eventID of the event being dispatched * virDomainEventDispatch is adapted to filter based on the domain name and uuid, if this filter is set for a callback. * virDomainEvent type/detail fields are moved into a union to allow different data fields for other types of events to be added later * src/conf/domain_event.h, src/conf/domain_event.c: Refactor to allow handling of different types of events * src/lxc/lxc_driver.c, src/qemu/qemu_driver.c, src/remote/remote_driver.c, src/test/test_driver.c, src/xen/xen_driver.c: Change dispatch function signature to use virConnectDomainEventGenericCallback
This commit is contained in:
parent
ea7dc33786
commit
747c536370
@ -35,20 +35,36 @@
|
|||||||
virReportErrorHelper(conn, VIR_FROM_THIS, code, __FILE__, \
|
virReportErrorHelper(conn, VIR_FROM_THIS, code, __FILE__, \
|
||||||
__FUNCTION__, __LINE__, __VA_ARGS__)
|
__FUNCTION__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
struct _virDomainMeta {
|
||||||
|
int id;
|
||||||
|
char *name;
|
||||||
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||||
|
};
|
||||||
|
typedef struct _virDomainMeta virDomainMeta;
|
||||||
|
typedef virDomainMeta *virDomainMetaPtr;
|
||||||
|
|
||||||
struct _virDomainEventCallback {
|
struct _virDomainEventCallback {
|
||||||
|
int callbackID;
|
||||||
|
int eventID;
|
||||||
virConnectPtr conn;
|
virConnectPtr conn;
|
||||||
virConnectDomainEventCallback cb;
|
virDomainMetaPtr dom;
|
||||||
|
virConnectDomainEventGenericCallback cb;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
virFreeCallback freecb;
|
virFreeCallback freecb;
|
||||||
int deleted;
|
int deleted;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _virDomainEvent {
|
struct _virDomainEvent {
|
||||||
int id;
|
int eventID;
|
||||||
char *name;
|
|
||||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
virDomainMeta dom;
|
||||||
int type;
|
|
||||||
int detail;
|
union {
|
||||||
|
struct {
|
||||||
|
int type;
|
||||||
|
int detail;
|
||||||
|
} lifecycle;
|
||||||
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,6 +88,8 @@ virDomainEventCallbackListFree(virDomainEventCallbackListPtr list)
|
|||||||
}
|
}
|
||||||
VIR_FREE(list);
|
VIR_FREE(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainEventCallbackListRemove:
|
* virDomainEventCallbackListRemove:
|
||||||
* @conn: pointer to the connection
|
* @conn: pointer to the connection
|
||||||
@ -87,8 +105,9 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0 ; i < cbList->count ; i++) {
|
for (i = 0 ; i < cbList->count ; i++) {
|
||||||
if(cbList->callbacks[i]->cb == callback &&
|
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
|
||||||
cbList->callbacks[i]->conn == conn) {
|
cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
|
||||||
|
cbList->callbacks[i]->conn == conn) {
|
||||||
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
||||||
if (freecb)
|
if (freecb)
|
||||||
(*freecb)(cbList->callbacks[i]->opaque);
|
(*freecb)(cbList->callbacks[i]->opaque);
|
||||||
@ -116,6 +135,7 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainEventCallbackListRemoveConn:
|
* virDomainEventCallbackListRemoveConn:
|
||||||
* @conn: pointer to the connection
|
* @conn: pointer to the connection
|
||||||
@ -131,7 +151,7 @@ virDomainEventCallbackListRemoveConn(virConnectPtr conn,
|
|||||||
int old_count = cbList->count;
|
int old_count = cbList->count;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0 ; i < cbList->count ; i++) {
|
for (i = 0 ; i < cbList->count ; i++) {
|
||||||
if(cbList->callbacks[i]->conn == conn) {
|
if (cbList->callbacks[i]->conn == conn) {
|
||||||
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
||||||
if (freecb)
|
if (freecb)
|
||||||
(*freecb)(cbList->callbacks[i]->opaque);
|
(*freecb)(cbList->callbacks[i]->opaque);
|
||||||
@ -154,14 +174,16 @@ virDomainEventCallbackListRemoveConn(virConnectPtr conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
||||||
virDomainEventCallbackListPtr cbList,
|
virDomainEventCallbackListPtr cbList,
|
||||||
virConnectDomainEventCallback callback)
|
virConnectDomainEventCallback callback)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0 ; i < cbList->count ; i++) {
|
for (i = 0 ; i < cbList->count ; i++) {
|
||||||
if (cbList->callbacks[i]->conn == conn &&
|
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
|
||||||
cbList->callbacks[i]->cb == callback) {
|
cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
|
||||||
|
cbList->callbacks[i]->conn == conn) {
|
||||||
cbList->callbacks[i]->deleted = 1;
|
cbList->callbacks[i]->deleted = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -172,6 +194,7 @@ int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
|
int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
|
||||||
{
|
{
|
||||||
int old_count = cbList->count;
|
int old_count = cbList->count;
|
||||||
@ -200,6 +223,7 @@ int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainEventCallbackListAdd:
|
* virDomainEventCallbackListAdd:
|
||||||
* @conn: pointer to the connection
|
* @conn: pointer to the connection
|
||||||
@ -217,7 +241,7 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
|
|||||||
virFreeCallback freecb)
|
virFreeCallback freecb)
|
||||||
{
|
{
|
||||||
virDomainEventCallbackPtr event;
|
virDomainEventCallbackPtr event;
|
||||||
int n;
|
int i;
|
||||||
|
|
||||||
/* Check incoming */
|
/* Check incoming */
|
||||||
if ( !cbList ) {
|
if ( !cbList ) {
|
||||||
@ -225,9 +249,10 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if we already have this callback on our list */
|
/* check if we already have this callback on our list */
|
||||||
for (n=0; n < cbList->count; n++) {
|
for (i = 0 ; i < cbList->count ; i++) {
|
||||||
if(cbList->callbacks[n]->cb == callback &&
|
if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
|
||||||
conn == cbList->callbacks[n]->conn) {
|
cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE &&
|
||||||
|
cbList->callbacks[i]->conn == conn) {
|
||||||
eventReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
eventReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("event callback already tracked"));
|
_("event callback already tracked"));
|
||||||
return -1;
|
return -1;
|
||||||
@ -239,13 +264,13 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
event->conn = conn;
|
event->conn = conn;
|
||||||
event->cb = callback;
|
event->cb = VIR_DOMAIN_EVENT_CALLBACK(callback);
|
||||||
|
event->eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
|
||||||
event->opaque = opaque;
|
event->opaque = opaque;
|
||||||
event->freecb = freecb;
|
event->freecb = freecb;
|
||||||
|
|
||||||
/* Make space on list */
|
/* Make space on list */
|
||||||
n = cbList->count;
|
if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0) {
|
||||||
if (VIR_REALLOC_N(cbList->callbacks, n + 1) < 0) {
|
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
VIR_FREE(event);
|
VIR_FREE(event);
|
||||||
return -1;
|
return -1;
|
||||||
@ -253,15 +278,27 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
|
|||||||
|
|
||||||
event->conn->refs++;
|
event->conn->refs++;
|
||||||
|
|
||||||
cbList->callbacks[n] = event;
|
cbList->callbacks[cbList->count] = event;
|
||||||
cbList->count++;
|
cbList->count++;
|
||||||
return 0;
|
|
||||||
|
event->callbackID = cbList->nextID++;
|
||||||
|
|
||||||
|
return event->callbackID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int virDomainEventCallbackListCount(virDomainEventCallbackListPtr cbList)
|
int virDomainEventCallbackListCount(virDomainEventCallbackListPtr cbList)
|
||||||
{
|
{
|
||||||
return cbList->count;
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (i = 0 ; i < cbList->count ; i++) {
|
||||||
|
if (cbList->callbacks[i]->deleted)
|
||||||
|
continue;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -270,7 +307,7 @@ void virDomainEventFree(virDomainEventPtr event)
|
|||||||
if (!event)
|
if (!event)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VIR_FREE(event->name);
|
VIR_FREE(event->dom.name);
|
||||||
VIR_FREE(event);
|
VIR_FREE(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,9 +324,10 @@ virDomainEventQueuePtr virDomainEventQueueNew(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
virDomainEventPtr virDomainEventNew(int id, const char *name,
|
static virDomainEventPtr virDomainEventNewInternal(int eventID,
|
||||||
const unsigned char *uuid,
|
int id,
|
||||||
int type, int detail)
|
const char *name,
|
||||||
|
const unsigned char *uuid)
|
||||||
{
|
{
|
||||||
virDomainEventPtr event;
|
virDomainEventPtr event;
|
||||||
|
|
||||||
@ -298,15 +336,29 @@ virDomainEventPtr virDomainEventNew(int id, const char *name,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->type = type;
|
event->eventID = eventID;
|
||||||
event->detail = detail;
|
if (!(event->dom.name = strdup(name))) {
|
||||||
if (!(event->name = strdup(name))) {
|
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
VIR_FREE(event);
|
VIR_FREE(event);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
event->id = id;
|
event->dom.id = id;
|
||||||
memcpy(event->uuid, uuid, VIR_UUID_BUFLEN);
|
memcpy(event->dom.uuid, uuid, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
virDomainEventPtr virDomainEventNew(int id, const char *name,
|
||||||
|
const unsigned char *uuid,
|
||||||
|
int type, int detail)
|
||||||
|
{
|
||||||
|
virDomainEventPtr event = virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
||||||
|
id, name, uuid);
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
event->data.lifecycle.type = type;
|
||||||
|
event->data.lifecycle.detail = detail;
|
||||||
|
}
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
@ -414,19 +466,58 @@ virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
|
|||||||
|
|
||||||
void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque ATTRIBUTE_UNUSED)
|
void *opaque ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
virDomainPtr dom = virGetDomain(conn, event->name, event->uuid);
|
virDomainPtr dom = virGetDomain(conn, event->dom.name, event->dom.uuid);
|
||||||
if (dom) {
|
if (!dom)
|
||||||
dom->id = event->id;
|
return;
|
||||||
(*cb)(conn, dom, event->type, event->detail, cbopaque);
|
dom->id = event->dom.id;
|
||||||
virDomainFree(dom);
|
|
||||||
|
switch (event->eventID) {
|
||||||
|
case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
|
||||||
|
((virConnectDomainEventCallback)cb)(conn, dom,
|
||||||
|
event->data.lifecycle.type,
|
||||||
|
event->data.lifecycle.detail,
|
||||||
|
cbopaque);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
VIR_WARN("Unexpected event ID %d", event->eventID);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virDomainFree(dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int virDomainEventDispatchMatchCallback(virDomainEventPtr event,
|
||||||
|
virDomainEventCallbackPtr cb)
|
||||||
|
{
|
||||||
|
if (!cb)
|
||||||
|
return 0;
|
||||||
|
if (cb->deleted)
|
||||||
|
return 0;
|
||||||
|
if (cb->eventID != event->eventID)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (cb->dom) {
|
||||||
|
/* Delibrately ignoring 'id' for matching, since that
|
||||||
|
* will cause problems when a domain switches between
|
||||||
|
* running & shutoff states & ignoring 'name' since
|
||||||
|
* Xen sometimes renames guests during migration, thus
|
||||||
|
* leaving 'uuid' as the only truely reliable ID we can use*/
|
||||||
|
|
||||||
|
if (memcmp(event->dom.uuid, cb->dom->uuid, VIR_UUID_BUFLEN) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void virDomainEventDispatch(virDomainEventPtr event,
|
void virDomainEventDispatch(virDomainEventPtr event,
|
||||||
virDomainEventCallbackListPtr callbacks,
|
virDomainEventCallbackListPtr callbacks,
|
||||||
virDomainEventDispatchFunc dispatch,
|
virDomainEventDispatchFunc dispatch,
|
||||||
@ -439,14 +530,14 @@ void virDomainEventDispatch(virDomainEventPtr event,
|
|||||||
int cbCount = callbacks->count;
|
int cbCount = callbacks->count;
|
||||||
|
|
||||||
for (i = 0 ; i < cbCount ; i++) {
|
for (i = 0 ; i < cbCount ; i++) {
|
||||||
if (callbacks->callbacks[i] &&
|
if (!virDomainEventDispatchMatchCallback(event, callbacks->callbacks[i]))
|
||||||
!callbacks->callbacks[i]->deleted) {
|
continue;
|
||||||
(*dispatch)(callbacks->callbacks[i]->conn,
|
|
||||||
event,
|
(*dispatch)(callbacks->callbacks[i]->conn,
|
||||||
callbacks->callbacks[i]->cb,
|
event,
|
||||||
callbacks->callbacks[i]->opaque,
|
callbacks->callbacks[i]->cb,
|
||||||
opaque);
|
callbacks->callbacks[i]->opaque,
|
||||||
}
|
opaque);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ typedef struct _virDomainEventCallback virDomainEventCallback;
|
|||||||
typedef virDomainEventCallback *virDomainEventCallbackPtr;
|
typedef virDomainEventCallback *virDomainEventCallbackPtr;
|
||||||
|
|
||||||
struct _virDomainEventCallbackList {
|
struct _virDomainEventCallbackList {
|
||||||
|
unsigned int nextID;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
virDomainEventCallbackPtr *callbacks;
|
virDomainEventCallbackPtr *callbacks;
|
||||||
};
|
};
|
||||||
@ -96,12 +97,12 @@ void virDomainEventQueueFree(virDomainEventQueuePtr queue);
|
|||||||
|
|
||||||
typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
|
typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
@ -1476,7 +1476,7 @@ lxcDomainEventDeregister (virConnectPtr conn,
|
|||||||
|
|
||||||
static void lxcDomainEventDispatchFunc(virConnectPtr conn,
|
static void lxcDomainEventDispatchFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -8003,7 +8003,7 @@ qemudDomainEventDeregister (virConnectPtr conn,
|
|||||||
|
|
||||||
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
|
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -8953,7 +8953,7 @@ done:
|
|||||||
|
|
||||||
static void remoteDomainEventDispatchFunc(virConnectPtr conn,
|
static void remoteDomainEventDispatchFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -5090,7 +5090,7 @@ testDomainEventDeregister (virConnectPtr conn,
|
|||||||
|
|
||||||
static void testDomainEventDispatchFunc(virConnectPtr conn,
|
static void testDomainEventDispatchFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -2042,7 +2042,7 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
|
|||||||
static void
|
static void
|
||||||
xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
|
xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
|
||||||
virDomainEventPtr event,
|
virDomainEventPtr event,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
void *cbopaque,
|
void *cbopaque,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user