mirror of https://gitee.com/openkylin/libvirt.git
Extracted common parts of domain_event.[ch] to object_event.[ch]
This commit is contained in:
parent
f88241608a
commit
620103feaf
|
@ -21,6 +21,7 @@ src/conf/network_conf.c
|
||||||
src/conf/node_device_conf.c
|
src/conf/node_device_conf.c
|
||||||
src/conf/nwfilter_conf.c
|
src/conf/nwfilter_conf.c
|
||||||
src/conf/nwfilter_params.c
|
src/conf/nwfilter_params.c
|
||||||
|
src/conf/object_event.c
|
||||||
src/conf/secret_conf.c
|
src/conf/secret_conf.c
|
||||||
src/conf/snapshot_conf.c
|
src/conf/snapshot_conf.c
|
||||||
src/conf/storage_conf.c
|
src/conf/storage_conf.c
|
||||||
|
|
|
@ -241,6 +241,10 @@ DOMAIN_CONF_SOURCES = \
|
||||||
conf/domain_nwfilter.c conf/domain_nwfilter.h \
|
conf/domain_nwfilter.c conf/domain_nwfilter.h \
|
||||||
conf/snapshot_conf.c conf/snapshot_conf.h
|
conf/snapshot_conf.c conf/snapshot_conf.h
|
||||||
|
|
||||||
|
OBJECT_EVENT_SOURCES = \
|
||||||
|
conf/object_event.c conf/object_event.h \
|
||||||
|
conf/object_event_private.h
|
||||||
|
|
||||||
DOMAIN_EVENT_SOURCES = \
|
DOMAIN_EVENT_SOURCES = \
|
||||||
conf/domain_event.c conf/domain_event.h
|
conf/domain_event.c conf/domain_event.h
|
||||||
|
|
||||||
|
@ -292,6 +296,7 @@ DEVICE_CONF_SOURCES = \
|
||||||
CONF_SOURCES = \
|
CONF_SOURCES = \
|
||||||
$(NETDEV_CONF_SOURCES) \
|
$(NETDEV_CONF_SOURCES) \
|
||||||
$(DOMAIN_CONF_SOURCES) \
|
$(DOMAIN_CONF_SOURCES) \
|
||||||
|
$(OBJECT_EVENT_SOURCES) \
|
||||||
$(DOMAIN_EVENT_SOURCES) \
|
$(DOMAIN_EVENT_SOURCES) \
|
||||||
$(NETWORK_CONF_SOURCES) \
|
$(NETWORK_CONF_SOURCES) \
|
||||||
$(NWFILTER_CONF_SOURCES) \
|
$(NWFILTER_CONF_SOURCES) \
|
||||||
|
@ -2021,6 +2026,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \
|
||||||
util/virutil.c \
|
util/virutil.c \
|
||||||
util/viruuid.c \
|
util/viruuid.c \
|
||||||
conf/domain_event.c \
|
conf/domain_event.c \
|
||||||
|
conf/object_event.c \
|
||||||
rpc/virnetsocket.c \
|
rpc/virnetsocket.c \
|
||||||
rpc/virnetsocket.h \
|
rpc/virnetsocket.h \
|
||||||
rpc/virnetmessage.h \
|
rpc/virnetmessage.h \
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2013 Red Hat, Inc.
|
* Copyright (C) 2010-2013 Red Hat, Inc.
|
||||||
* Copyright (C) 2008 VirtualIron
|
* Copyright (C) 2008 VirtualIron
|
||||||
|
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -24,6 +25,8 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include "domain_event.h"
|
#include "domain_event.h"
|
||||||
|
#include "object_event.h"
|
||||||
|
#include "object_event_private.h"
|
||||||
#include "virlog.h"
|
#include "virlog.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
|
@ -32,59 +35,6 @@
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_NONE
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
#define VIR_OBJECT_EVENT_CALLBACK(cb) ((virConnectObjectEventGenericCallback)(cb))
|
|
||||||
|
|
||||||
struct _virObjectMeta {
|
|
||||||
int id;
|
|
||||||
char *name;
|
|
||||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
||||||
};
|
|
||||||
typedef struct _virObjectMeta virObjectMeta;
|
|
||||||
typedef virObjectMeta *virObjectMetaPtr;
|
|
||||||
|
|
||||||
typedef struct _virObjectEventQueue virObjectEventQueue;
|
|
||||||
typedef virObjectEventQueue *virObjectEventQueuePtr;
|
|
||||||
|
|
||||||
struct _virObjectEventCallbackList {
|
|
||||||
unsigned int nextID;
|
|
||||||
unsigned int count;
|
|
||||||
virObjectEventCallbackPtr *callbacks;
|
|
||||||
};
|
|
||||||
typedef struct _virObjectEventCallbackList virObjectEventCallbackList;
|
|
||||||
typedef virObjectEventCallbackList *virObjectEventCallbackListPtr;
|
|
||||||
|
|
||||||
struct _virObjectEventQueue {
|
|
||||||
unsigned int count;
|
|
||||||
virObjectEventPtr *events;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _virObjectEventState {
|
|
||||||
/* The list of domain event callbacks */
|
|
||||||
virObjectEventCallbackListPtr callbacks;
|
|
||||||
/* The queue of object events */
|
|
||||||
virObjectEventQueuePtr queue;
|
|
||||||
/* Timer for flushing events queue */
|
|
||||||
int timer;
|
|
||||||
/* Flag if we're in process of dispatching */
|
|
||||||
bool isDispatching;
|
|
||||||
virMutex lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _virObjectEventCallback {
|
|
||||||
int callbackID;
|
|
||||||
int eventID;
|
|
||||||
virConnectPtr conn;
|
|
||||||
virObjectMetaPtr meta;
|
|
||||||
virConnectObjectEventGenericCallback cb;
|
|
||||||
void *opaque;
|
|
||||||
virFreeCallback freecb;
|
|
||||||
int deleted;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static virClassPtr virObjectEventClass;
|
|
||||||
static virClassPtr virClassForObjectEvent(void);
|
|
||||||
|
|
||||||
static virClassPtr virDomainEventClass;
|
static virClassPtr virDomainEventClass;
|
||||||
static virClassPtr virDomainEventLifecycleClass;
|
static virClassPtr virDomainEventLifecycleClass;
|
||||||
|
@ -98,7 +48,7 @@ static virClassPtr virDomainEventTrayChangeClass;
|
||||||
static virClassPtr virDomainEventBalloonChangeClass;
|
static virClassPtr virDomainEventBalloonChangeClass;
|
||||||
static virClassPtr virDomainEventDeviceRemovedClass;
|
static virClassPtr virDomainEventDeviceRemovedClass;
|
||||||
|
|
||||||
static void virObjectEventDispose(void *obj);
|
|
||||||
static void virDomainEventDispose(void *obj);
|
static void virDomainEventDispose(void *obj);
|
||||||
static void virDomainEventLifecycleDispose(void *obj);
|
static void virDomainEventLifecycleDispose(void *obj);
|
||||||
static void virDomainEventRTCChangeDispose(void *obj);
|
static void virDomainEventRTCChangeDispose(void *obj);
|
||||||
|
@ -111,11 +61,6 @@ static void virDomainEventTrayChangeDispose(void *obj);
|
||||||
static void virDomainEventBalloonChangeDispose(void *obj);
|
static void virDomainEventBalloonChangeDispose(void *obj);
|
||||||
static void virDomainEventDeviceRemovedDispose(void *obj);
|
static void virDomainEventDeviceRemovedDispose(void *obj);
|
||||||
|
|
||||||
struct _virObjectEvent {
|
|
||||||
virObject parent;
|
|
||||||
int eventID;
|
|
||||||
virObjectMeta meta;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _virDomainEvent {
|
struct _virDomainEvent {
|
||||||
virObjectEvent parent;
|
virObjectEvent parent;
|
||||||
|
@ -222,26 +167,6 @@ typedef struct _virDomainEventDeviceRemoved virDomainEventDeviceRemoved;
|
||||||
typedef virDomainEventDeviceRemoved *virDomainEventDeviceRemovedPtr;
|
typedef virDomainEventDeviceRemoved *virDomainEventDeviceRemovedPtr;
|
||||||
|
|
||||||
|
|
||||||
static int virObjectEventOnceInit(void)
|
|
||||||
{
|
|
||||||
if (!(virObjectEventClass =
|
|
||||||
virClassNew(virClassForObject(),
|
|
||||||
"virObjectEvent",
|
|
||||||
sizeof(virObjectEvent),
|
|
||||||
virObjectEventDispose)))
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_ONCE_GLOBAL_INIT(virObjectEvent)
|
|
||||||
|
|
||||||
virClassPtr virClassForObjectEvent(void)
|
|
||||||
{
|
|
||||||
if (virObjectEventInitialize() < 0)
|
|
||||||
return NULL;
|
|
||||||
return virObjectEventClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int virDomainEventsOnceInit(void)
|
static int virDomainEventsOnceInit(void)
|
||||||
{
|
{
|
||||||
if (!(virDomainEventClass =
|
if (!(virDomainEventClass =
|
||||||
|
@ -315,26 +240,6 @@ static int virDomainEventsOnceInit(void)
|
||||||
|
|
||||||
VIR_ONCE_GLOBAL_INIT(virDomainEvents)
|
VIR_ONCE_GLOBAL_INIT(virDomainEvents)
|
||||||
|
|
||||||
static int virObjectEventGetEventID(void *anyobj)
|
|
||||||
{
|
|
||||||
virObjectEventPtr obj = anyobj;
|
|
||||||
|
|
||||||
if (!virObjectIsClass(obj, virClassForObjectEvent())) {
|
|
||||||
VIR_WARN("Object %p (%s) is not a virObjectEvent instance",
|
|
||||||
obj, obj ? virClassName(obj->parent.klass) : "(unknown)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return obj->eventID;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virObjectEventDispose(void *obj)
|
|
||||||
{
|
|
||||||
virObjectEventPtr event = obj;
|
|
||||||
|
|
||||||
VIR_DEBUG("obj=%p", event);
|
|
||||||
|
|
||||||
VIR_FREE(event->meta.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virDomainEventDispose(void *obj)
|
static void virDomainEventDispose(void *obj)
|
||||||
{
|
{
|
||||||
|
@ -437,29 +342,6 @@ static void virDomainEventDeviceRemovedDispose(void *obj)
|
||||||
VIR_FREE(event->devAlias);
|
VIR_FREE(event->devAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventCallbackListFree:
|
|
||||||
* @list: event callback list head
|
|
||||||
*
|
|
||||||
* Free the memory in the domain event callback list
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
virObjectEventCallbackListFree(virObjectEventCallbackListPtr list)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
if (!list)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i=0; i<list->count; i++) {
|
|
||||||
virFreeCallback freecb = list->callbacks[i]->freecb;
|
|
||||||
if (freecb)
|
|
||||||
(*freecb)(list->callbacks[i]->opaque);
|
|
||||||
VIR_FREE(list->callbacks[i]);
|
|
||||||
}
|
|
||||||
VIR_FREE(list->callbacks);
|
|
||||||
VIR_FREE(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainEventCallbackListRemove:
|
* virDomainEventCallbackListRemove:
|
||||||
|
@ -512,56 +394,6 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventCallbackListRemoveID:
|
|
||||||
* @conn: pointer to the connection
|
|
||||||
* @cbList: the list
|
|
||||||
* @callback: the callback to remove
|
|
||||||
*
|
|
||||||
* Internal function to remove a callback from a virObjectEventCallbackListPtr
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
virObjectEventCallbackListRemoveID(virConnectPtr conn,
|
|
||||||
virObjectEventCallbackListPtr cbList,
|
|
||||||
int callbackID)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (cbList->callbacks[i]->callbackID == callbackID &&
|
|
||||||
cbList->callbacks[i]->conn == conn) {
|
|
||||||
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
|
||||||
if (freecb)
|
|
||||||
(*freecb)(cbList->callbacks[i]->opaque);
|
|
||||||
virObjectUnref(cbList->callbacks[i]->conn);
|
|
||||||
VIR_FREE(cbList->callbacks[i]);
|
|
||||||
|
|
||||||
if (i < (cbList->count - 1))
|
|
||||||
memmove(cbList->callbacks + i,
|
|
||||||
cbList->callbacks + i + 1,
|
|
||||||
sizeof(*(cbList->callbacks)) *
|
|
||||||
(cbList->count - (i + 1)));
|
|
||||||
|
|
||||||
if (VIR_REALLOC_N(cbList->callbacks,
|
|
||||||
cbList->count - 1) < 0) {
|
|
||||||
; /* Failure to reduce memory allocation isn't fatal */
|
|
||||||
}
|
|
||||||
cbList->count--;
|
|
||||||
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (!cbList->callbacks[i]->deleted)
|
|
||||||
ret++;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("could not find event callback for removal"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
||||||
virObjectEventCallbackListPtr cbList,
|
virObjectEventCallbackListPtr cbList,
|
||||||
|
@ -588,162 +420,6 @@ virDomainEventCallbackListMarkDelete(virConnectPtr conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
virObjectEventCallbackListMarkDeleteID(virConnectPtr conn,
|
|
||||||
virObjectEventCallbackListPtr cbList,
|
|
||||||
int callbackID)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (cbList->callbacks[i]->callbackID == callbackID &&
|
|
||||||
cbList->callbacks[i]->conn == conn) {
|
|
||||||
cbList->callbacks[i]->deleted = 1;
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (!cbList->callbacks[i]->deleted)
|
|
||||||
ret++;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("could not find event callback for deletion"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
virObjectEventCallbackListPurgeMarked(virObjectEventCallbackListPtr cbList)
|
|
||||||
{
|
|
||||||
int old_count = cbList->count;
|
|
||||||
int n;
|
|
||||||
for (n = 0; n < cbList->count; n++) {
|
|
||||||
if (cbList->callbacks[n]->deleted) {
|
|
||||||
virFreeCallback freecb = cbList->callbacks[n]->freecb;
|
|
||||||
if (freecb)
|
|
||||||
(*freecb)(cbList->callbacks[n]->opaque);
|
|
||||||
virObjectUnref(cbList->callbacks[n]->conn);
|
|
||||||
VIR_FREE(cbList->callbacks[n]);
|
|
||||||
|
|
||||||
if (n < (cbList->count - 1))
|
|
||||||
memmove(cbList->callbacks + n,
|
|
||||||
cbList->callbacks + n + 1,
|
|
||||||
sizeof(*(cbList->callbacks)) *
|
|
||||||
(cbList->count - (n + 1)));
|
|
||||||
cbList->count--;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cbList->count < old_count &&
|
|
||||||
VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) {
|
|
||||||
; /* Failure to reduce memory allocation isn't fatal */
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventCallbackListAddID:
|
|
||||||
* @conn: pointer to the connection
|
|
||||||
* @cbList: the list
|
|
||||||
* @uuid: the uuid of the object to filter on
|
|
||||||
* @name: the name of the object to filter on
|
|
||||||
* @id: the ID of the object to filter on
|
|
||||||
* @eventID: the event ID
|
|
||||||
* @callback: the callback to add
|
|
||||||
* @opaque: opaque data tio pass to callback
|
|
||||||
* @callbackID: filled with callback ID
|
|
||||||
*
|
|
||||||
* Internal function to add a callback from a virObjectEventCallbackListPtr
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
virObjectEventCallbackListAddID(virConnectPtr conn,
|
|
||||||
virObjectEventCallbackListPtr cbList,
|
|
||||||
unsigned char uuid[VIR_UUID_BUFLEN],
|
|
||||||
const char *name,
|
|
||||||
int id,
|
|
||||||
int eventID,
|
|
||||||
virConnectObjectEventGenericCallback callback,
|
|
||||||
void *opaque,
|
|
||||||
virFreeCallback freecb,
|
|
||||||
int *callbackID)
|
|
||||||
{
|
|
||||||
virObjectEventCallbackPtr event;
|
|
||||||
size_t i;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
/* Check incoming */
|
|
||||||
if (!cbList) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if we already have this callback on our list */
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (cbList->callbacks[i]->cb == VIR_OBJECT_EVENT_CALLBACK(callback) &&
|
|
||||||
cbList->callbacks[i]->eventID == eventID &&
|
|
||||||
cbList->callbacks[i]->conn == conn &&
|
|
||||||
((uuid && cbList->callbacks[i]->meta &&
|
|
||||||
memcmp(cbList->callbacks[i]->meta->uuid,
|
|
||||||
uuid, VIR_UUID_BUFLEN) == 0) ||
|
|
||||||
(!uuid && !cbList->callbacks[i]->meta))) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("event callback already tracked"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Allocate new event */
|
|
||||||
if (VIR_ALLOC(event) < 0)
|
|
||||||
goto error;
|
|
||||||
event->conn = conn;
|
|
||||||
event->cb = callback;
|
|
||||||
event->eventID = eventID;
|
|
||||||
event->opaque = opaque;
|
|
||||||
event->freecb = freecb;
|
|
||||||
|
|
||||||
if (name && uuid && id > 0) {
|
|
||||||
if (VIR_ALLOC(event->meta) < 0)
|
|
||||||
goto error;
|
|
||||||
if (VIR_STRDUP(event->meta->name, name) < 0)
|
|
||||||
goto error;
|
|
||||||
memcpy(event->meta->uuid, uuid, VIR_UUID_BUFLEN);
|
|
||||||
event->meta->id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make space on list */
|
|
||||||
if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
virObjectRef(event->conn);
|
|
||||||
|
|
||||||
cbList->callbacks[cbList->count] = event;
|
|
||||||
cbList->count++;
|
|
||||||
|
|
||||||
event->callbackID = cbList->nextID++;
|
|
||||||
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (cbList->callbacks[i]->eventID == eventID &&
|
|
||||||
cbList->callbacks[i]->conn == conn &&
|
|
||||||
!cbList->callbacks[i]->deleted)
|
|
||||||
ret++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callbackID)
|
|
||||||
*callbackID = event->callbackID;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (event) {
|
|
||||||
if (event->meta)
|
|
||||||
VIR_FREE(event->meta->name);
|
|
||||||
VIR_FREE(event->meta);
|
|
||||||
}
|
|
||||||
VIR_FREE(event);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainEventCallbackListAdd:
|
* virDomainEventCallbackListAdd:
|
||||||
* @conn: pointer to the connection
|
* @conn: pointer to the connection
|
||||||
|
@ -767,184 +443,6 @@ virDomainEventCallbackListAdd(virConnectPtr conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
virObjectEventCallbackListEventID(virConnectPtr conn,
|
|
||||||
virObjectEventCallbackListPtr cbList,
|
|
||||||
int callbackID)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < cbList->count; i++) {
|
|
||||||
if (cbList->callbacks[i]->deleted)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (cbList->callbacks[i]->callbackID == callbackID &&
|
|
||||||
cbList->callbacks[i]->conn == conn)
|
|
||||||
return cbList->callbacks[i]->eventID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventQueueClear:
|
|
||||||
* @queue: pointer to the queue
|
|
||||||
*
|
|
||||||
* Removes all elements from the queue
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
virObjectEventQueueClear(virObjectEventQueuePtr queue)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
if (!queue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < queue->count; i++) {
|
|
||||||
virObjectUnref(queue->events[i]);
|
|
||||||
}
|
|
||||||
VIR_FREE(queue->events);
|
|
||||||
queue->count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventQueueFree:
|
|
||||||
* @queue: pointer to the queue
|
|
||||||
*
|
|
||||||
* Free the memory in the queue. We process this like a list here
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
virObjectEventQueueFree(virObjectEventQueuePtr queue)
|
|
||||||
{
|
|
||||||
if (!queue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
virObjectEventQueueClear(queue);
|
|
||||||
VIR_FREE(queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
static virObjectEventQueuePtr
|
|
||||||
virObjectEventQueueNew(void)
|
|
||||||
{
|
|
||||||
virObjectEventQueuePtr ret;
|
|
||||||
|
|
||||||
ignore_value(VIR_ALLOC(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventStateLock(virObjectEventStatePtr state)
|
|
||||||
{
|
|
||||||
virMutexLock(&state->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventStateUnlock(virObjectEventStatePtr state)
|
|
||||||
{
|
|
||||||
virMutexUnlock(&state->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventStateFree:
|
|
||||||
* @list: virObjectEventStatePtr to free
|
|
||||||
*
|
|
||||||
* Free a virObjectEventStatePtr and its members, and unregister the timer.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
virObjectEventStateFree(virObjectEventStatePtr state)
|
|
||||||
{
|
|
||||||
if (!state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
virObjectEventCallbackListFree(state->callbacks);
|
|
||||||
virObjectEventQueueFree(state->queue);
|
|
||||||
|
|
||||||
if (state->timer != -1)
|
|
||||||
virEventRemoveTimeout(state->timer);
|
|
||||||
|
|
||||||
virMutexDestroy(&state->lock);
|
|
||||||
VIR_FREE(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void virObjectEventStateFlush(virObjectEventStatePtr state);
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
|
|
||||||
{
|
|
||||||
virObjectEventStatePtr state = opaque;
|
|
||||||
|
|
||||||
virObjectEventStateFlush(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventStateNew:
|
|
||||||
*/
|
|
||||||
virObjectEventStatePtr
|
|
||||||
virObjectEventStateNew(void)
|
|
||||||
{
|
|
||||||
virObjectEventStatePtr state = NULL;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(state) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (virMutexInit(&state->lock) < 0) {
|
|
||||||
virReportSystemError(errno, "%s",
|
|
||||||
_("unable to initialize state mutex"));
|
|
||||||
VIR_FREE(state);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_ALLOC(state->callbacks) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (!(state->queue = virObjectEventQueueNew()))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
state->timer = -1;
|
|
||||||
|
|
||||||
return state;
|
|
||||||
|
|
||||||
error:
|
|
||||||
virObjectEventStateFree(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *virObjectEventNew(virClassPtr klass,
|
|
||||||
int eventID,
|
|
||||||
int id,
|
|
||||||
const char *name,
|
|
||||||
const unsigned char *uuid)
|
|
||||||
{
|
|
||||||
virObjectEventPtr event;
|
|
||||||
|
|
||||||
if (virObjectEventInitialize() < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!virClassIsDerivedFrom(klass, virObjectEventClass)) {
|
|
||||||
virReportInvalidArg(klass,
|
|
||||||
_("Class %s must derive from virObjectEvent"),
|
|
||||||
virClassName(klass));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(event = virObjectNew(klass)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
event->eventID = eventID;
|
|
||||||
|
|
||||||
if (VIR_STRDUP(event->meta.name, name) < 0) {
|
|
||||||
VIR_FREE(event);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
event->meta.id = id;
|
|
||||||
memcpy(event->meta.uuid, uuid, VIR_UUID_BUFLEN);
|
|
||||||
|
|
||||||
VIR_DEBUG("obj=%p", event);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *virDomainEventNew(virClassPtr klass,
|
static void *virDomainEventNew(virClassPtr klass,
|
||||||
int eventID,
|
int eventID,
|
||||||
int id,
|
int id,
|
||||||
|
@ -953,7 +451,7 @@ static void *virDomainEventNew(virClassPtr klass,
|
||||||
{
|
{
|
||||||
virDomainEventPtr event;
|
virDomainEventPtr event;
|
||||||
|
|
||||||
if (virObjectEventInitialize() < 0)
|
if (virDomainEventsInitialize() < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!virClassIsDerivedFrom(klass, virDomainEventClass)) {
|
if (!virClassIsDerivedFrom(klass, virDomainEventClass)) {
|
||||||
|
@ -1611,42 +1109,8 @@ virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
|
||||||
devAlias);
|
devAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventQueuePush:
|
|
||||||
* @evtQueue: the object event queue
|
|
||||||
* @event: the event to add
|
|
||||||
*
|
|
||||||
* Internal function to push to the back of a virObjectEventQueue
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, -1 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
virObjectEventQueuePush(virObjectEventQueuePtr evtQueue,
|
|
||||||
virObjectEventPtr event)
|
|
||||||
{
|
|
||||||
if (!evtQueue) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make space on queue */
|
void
|
||||||
if (VIR_REALLOC_N(evtQueue->events,
|
|
||||||
evtQueue->count + 1) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
evtQueue->events[evtQueue->count] = event;
|
|
||||||
evtQueue->count++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*virObjectEventDispatchFunc)(virConnectPtr conn,
|
|
||||||
virObjectEventPtr event,
|
|
||||||
virConnectObjectEventGenericCallback cb,
|
|
||||||
void *cbopaque,
|
|
||||||
void *opaque);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||||
virObjectEventPtr event,
|
virObjectEventPtr event,
|
||||||
virConnectDomainEventGenericCallback cb,
|
virConnectDomainEventGenericCallback cb,
|
||||||
|
@ -1830,207 +1294,6 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int virObjectEventDispatchMatchCallback(virObjectEventPtr event,
|
|
||||||
virObjectEventCallbackPtr cb)
|
|
||||||
{
|
|
||||||
if (!cb)
|
|
||||||
return 0;
|
|
||||||
if (cb->deleted)
|
|
||||||
return 0;
|
|
||||||
if (cb->eventID != virObjectEventGetEventID(event))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (cb->meta) {
|
|
||||||
/* Deliberately 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 truly reliable ID we can use*/
|
|
||||||
|
|
||||||
if (memcmp(event->meta.uuid, cb->meta->uuid, VIR_UUID_BUFLEN) == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventDispatch(virObjectEventPtr event,
|
|
||||||
virObjectEventCallbackListPtr callbacks,
|
|
||||||
virObjectEventDispatchFunc dispatch,
|
|
||||||
void *opaque)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
/* Cache this now, since we may be dropping the lock,
|
|
||||||
and have more callbacks added. We're guaranteed not
|
|
||||||
to have any removed */
|
|
||||||
int cbCount = callbacks->count;
|
|
||||||
|
|
||||||
for (i = 0; i < cbCount; i++) {
|
|
||||||
if (!virObjectEventDispatchMatchCallback(event, callbacks->callbacks[i]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
(*dispatch)(callbacks->callbacks[i]->conn,
|
|
||||||
event,
|
|
||||||
callbacks->callbacks[i]->cb,
|
|
||||||
callbacks->callbacks[i]->opaque,
|
|
||||||
opaque);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventQueueDispatch(virObjectEventQueuePtr queue,
|
|
||||||
virObjectEventCallbackListPtr callbacks,
|
|
||||||
virObjectEventDispatchFunc dispatch,
|
|
||||||
void *opaque)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < queue->count; i++) {
|
|
||||||
virObjectEventDispatch(queue->events[i], callbacks, dispatch, opaque);
|
|
||||||
virObjectUnref(queue->events[i]);
|
|
||||||
}
|
|
||||||
VIR_FREE(queue->events);
|
|
||||||
queue->count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
virObjectEventStateQueue(virObjectEventStatePtr state,
|
|
||||||
virObjectEventPtr event)
|
|
||||||
{
|
|
||||||
if (state->timer < 0) {
|
|
||||||
virObjectUnref(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
virObjectEventStateLock(state);
|
|
||||||
|
|
||||||
if (virObjectEventQueuePush(state->queue, event) < 0) {
|
|
||||||
VIR_DEBUG("Error adding event to queue");
|
|
||||||
virObjectUnref(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->queue->count == 1)
|
|
||||||
virEventUpdateTimeout(state->timer, 0);
|
|
||||||
virObjectEventStateUnlock(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventStateDispatchFunc(virConnectPtr conn,
|
|
||||||
virObjectEventPtr event,
|
|
||||||
virConnectObjectEventGenericCallback cb,
|
|
||||||
void *cbopaque,
|
|
||||||
void *opaque)
|
|
||||||
{
|
|
||||||
virObjectEventStatePtr state = opaque;
|
|
||||||
virEventNamespaceID namespace = (event->eventID & 0xFF00) >> 8;
|
|
||||||
|
|
||||||
/* Drop the lock whle dispatching, for sake of re-entrancy */
|
|
||||||
virObjectEventStateUnlock(state);
|
|
||||||
switch (namespace)
|
|
||||||
{
|
|
||||||
case VIR_EVENT_NAMESPACE_DOMAIN:
|
|
||||||
virDomainEventDispatchDefaultFunc(conn, event,
|
|
||||||
VIR_DOMAIN_EVENT_CALLBACK(cb), cbopaque, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
virObjectEventStateLock(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
virObjectEventStateFlush(virObjectEventStatePtr state)
|
|
||||||
{
|
|
||||||
virObjectEventQueue tempQueue;
|
|
||||||
|
|
||||||
virObjectEventStateLock(state);
|
|
||||||
state->isDispatching = true;
|
|
||||||
|
|
||||||
/* Copy the queue, so we're reentrant safe when dispatchFunc drops the
|
|
||||||
* driver lock */
|
|
||||||
tempQueue.count = state->queue->count;
|
|
||||||
tempQueue.events = state->queue->events;
|
|
||||||
state->queue->count = 0;
|
|
||||||
state->queue->events = NULL;
|
|
||||||
virEventUpdateTimeout(state->timer, -1);
|
|
||||||
|
|
||||||
virObjectEventQueueDispatch(&tempQueue,
|
|
||||||
state->callbacks,
|
|
||||||
virObjectEventStateDispatchFunc,
|
|
||||||
state);
|
|
||||||
|
|
||||||
/* Purge any deleted callbacks */
|
|
||||||
virObjectEventCallbackListPurgeMarked(state->callbacks);
|
|
||||||
|
|
||||||
state->isDispatching = false;
|
|
||||||
virObjectEventStateUnlock(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventStateRegisterID:
|
|
||||||
* @conn: connection to associate with callback
|
|
||||||
* @state: domain event state
|
|
||||||
* @eventID: ID of the event type to register for
|
|
||||||
* @cb: function to remove from event
|
|
||||||
* @opaque: data blob to pass to callback
|
|
||||||
* @freecb: callback to free @opaque
|
|
||||||
* @callbackID: filled with callback ID
|
|
||||||
*
|
|
||||||
* Register the function @callbackID with connection @conn,
|
|
||||||
* from @state, for events of type @eventID.
|
|
||||||
*
|
|
||||||
* Returns: the number of callbacks now registered, or -1 on error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
virObjectEventStateRegisterID(virConnectPtr conn,
|
|
||||||
virObjectEventStatePtr state,
|
|
||||||
unsigned char *uuid,
|
|
||||||
const char *name,
|
|
||||||
int id,
|
|
||||||
int eventID,
|
|
||||||
virConnectObjectEventGenericCallback cb,
|
|
||||||
void *opaque,
|
|
||||||
virFreeCallback freecb,
|
|
||||||
int *callbackID)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
virObjectEventStateLock(state);
|
|
||||||
|
|
||||||
if ((state->callbacks->count == 0) &&
|
|
||||||
(state->timer == -1) &&
|
|
||||||
(state->timer = virEventAddTimeout(-1,
|
|
||||||
virObjectEventTimer,
|
|
||||||
state,
|
|
||||||
NULL)) < 0) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("could not initialize domain event timer"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = virObjectEventCallbackListAddID(conn, state->callbacks,
|
|
||||||
uuid, name, id, eventID, cb, opaque, freecb,
|
|
||||||
callbackID);
|
|
||||||
|
|
||||||
if (ret == -1 &&
|
|
||||||
state->callbacks->count == 0 &&
|
|
||||||
state->timer != -1) {
|
|
||||||
virEventRemoveTimeout(state->timer);
|
|
||||||
state->timer = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
virObjectEventStateUnlock(state);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainEventStateRegister:
|
* virDomainEventStateRegister:
|
||||||
* @conn: connection to associate with callback
|
* @conn: connection to associate with callback
|
||||||
|
@ -2155,67 +1418,3 @@ virDomainEventStateDeregister(virConnectPtr conn,
|
||||||
virObjectEventStateUnlock(state);
|
virObjectEventStateUnlock(state);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventStateDeregisterID:
|
|
||||||
* @conn: connection to associate with callback
|
|
||||||
* @state: object event state
|
|
||||||
* @callbackID: ID of the function to remove from event
|
|
||||||
*
|
|
||||||
* Unregister the function @callbackID with connection @conn,
|
|
||||||
* from @state, for events.
|
|
||||||
*
|
|
||||||
* Returns: the number of callbacks still registered, or -1 on error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
virObjectEventStateDeregisterID(virConnectPtr conn,
|
|
||||||
virObjectEventStatePtr state,
|
|
||||||
int callbackID)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
virObjectEventStateLock(state);
|
|
||||||
if (state->isDispatching)
|
|
||||||
ret = virObjectEventCallbackListMarkDeleteID(conn,
|
|
||||||
state->callbacks, callbackID);
|
|
||||||
else
|
|
||||||
ret = virObjectEventCallbackListRemoveID(conn,
|
|
||||||
state->callbacks, callbackID);
|
|
||||||
|
|
||||||
if (state->callbacks->count == 0 &&
|
|
||||||
state->timer != -1) {
|
|
||||||
virEventRemoveTimeout(state->timer);
|
|
||||||
state->timer = -1;
|
|
||||||
virObjectEventQueueClear(state->queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
virObjectEventStateUnlock(state);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* virObjectEventStateEventID:
|
|
||||||
* @conn: connection associated with the callback
|
|
||||||
* @state: object event state
|
|
||||||
* @callbackID: the callback to query
|
|
||||||
*
|
|
||||||
* Query what event ID type is associated with the
|
|
||||||
* callback @callbackID for connection @conn
|
|
||||||
*
|
|
||||||
* Returns 0 on success, -1 on error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
virObjectEventStateEventID(virConnectPtr conn,
|
|
||||||
virObjectEventStatePtr state,
|
|
||||||
int callbackID)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
virObjectEventStateLock(state);
|
|
||||||
ret = virObjectEventCallbackListEventID(conn,
|
|
||||||
state->callbacks, callbackID);
|
|
||||||
virObjectEventStateUnlock(state);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Red Hat, Inc.
|
* Copyright (C) 2012 Red Hat, Inc.
|
||||||
* Copyright (C) 2008 VirtualIron
|
* Copyright (C) 2008 VirtualIron
|
||||||
|
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -26,29 +27,10 @@
|
||||||
#ifndef __DOMAIN_EVENT_H__
|
#ifndef __DOMAIN_EVENT_H__
|
||||||
# define __DOMAIN_EVENT_H__
|
# define __DOMAIN_EVENT_H__
|
||||||
|
|
||||||
|
# include "object_event.h"
|
||||||
# include "domain_conf.h"
|
# include "domain_conf.h"
|
||||||
|
|
||||||
|
|
||||||
/** Event IDs are computed in the following way:
|
|
||||||
virEventNamespaceID << 8 + vir*EventId
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */
|
|
||||||
} virEventNamespaceID;
|
|
||||||
|
|
||||||
typedef struct _virObjectEventCallback virObjectEventCallback;
|
|
||||||
typedef virObjectEventCallback *virObjectEventCallbackPtr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatching domain events that come in while
|
|
||||||
* in a call / response rpc
|
|
||||||
*/
|
|
||||||
typedef struct _virObjectEvent virObjectEvent;
|
|
||||||
typedef virObjectEvent *virObjectEventPtr;
|
|
||||||
|
|
||||||
typedef struct _virObjectEventState virObjectEventState;
|
|
||||||
typedef virObjectEventState *virObjectEventStatePtr;
|
|
||||||
|
|
||||||
virObjectEventPtr virDomainEventLifecycleNew(int id,
|
virObjectEventPtr virDomainEventLifecycleNew(int id,
|
||||||
const char *name,
|
const char *name,
|
||||||
const unsigned char *uuid,
|
const unsigned char *uuid,
|
||||||
|
@ -149,27 +131,6 @@ virObjectEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj,
|
||||||
virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
|
virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
|
||||||
const char *devAlias);
|
const char *devAlias);
|
||||||
|
|
||||||
void virObjectEventStateFree(virObjectEventStatePtr state);
|
|
||||||
virObjectEventStatePtr
|
|
||||||
virObjectEventStateNew(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* virConnectObjectEventGenericCallback:
|
|
||||||
* @conn: the connection pointer
|
|
||||||
* @obj: the object pointer
|
|
||||||
* @opaque: application specified data
|
|
||||||
*
|
|
||||||
* A generic object event callback handler. Specific events usually
|
|
||||||
* have a customization with extra parameters
|
|
||||||
*/
|
|
||||||
typedef void (*virConnectObjectEventGenericCallback)(virConnectPtr conn,
|
|
||||||
void *obj,
|
|
||||||
void *opaque);
|
|
||||||
|
|
||||||
void
|
|
||||||
virObjectEventStateQueue(virObjectEventStatePtr state,
|
|
||||||
virObjectEventPtr event)
|
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
||||||
int virDomainEventStateRegister(virConnectPtr conn,
|
int virDomainEventStateRegister(virConnectPtr conn,
|
||||||
virObjectEventStatePtr state,
|
virObjectEventStatePtr state,
|
||||||
virConnectDomainEventCallback callback,
|
virConnectDomainEventCallback callback,
|
||||||
|
@ -190,27 +151,12 @@ virDomainEventStateDeregister(virConnectPtr conn,
|
||||||
virObjectEventStatePtr state,
|
virObjectEventStatePtr state,
|
||||||
virConnectDomainEventCallback callback)
|
virConnectDomainEventCallback callback)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||||
int
|
|
||||||
virObjectEventStateRegisterID(virConnectPtr conn,
|
void
|
||||||
virObjectEventStatePtr state,
|
virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||||
unsigned char *uuid,
|
virObjectEventPtr event,
|
||||||
const char *name,
|
virConnectDomainEventGenericCallback cb,
|
||||||
int id,
|
void *cbopaque,
|
||||||
int eventID,
|
void *opaque);
|
||||||
virConnectObjectEventGenericCallback cb,
|
|
||||||
void *opaque,
|
|
||||||
virFreeCallback freecb,
|
|
||||||
int *callbackID)
|
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(7);
|
|
||||||
int
|
|
||||||
virObjectEventStateDeregisterID(virConnectPtr conn,
|
|
||||||
virObjectEventStatePtr state,
|
|
||||||
int callbackID)
|
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
||||||
int
|
|
||||||
virObjectEventStateEventID(virConnectPtr conn,
|
|
||||||
virObjectEventStatePtr state,
|
|
||||||
int callbackID)
|
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,792 @@
|
||||||
|
/*
|
||||||
|
* object_event.c: object event queue processing helpers
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2013 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2008 VirtualIron
|
||||||
|
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Ben Guthro
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "domain_event.h"
|
||||||
|
#include "object_event.h"
|
||||||
|
#include "object_event_private.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
|
struct _virObjectEventQueue {
|
||||||
|
unsigned int count;
|
||||||
|
virObjectEventPtr *events;
|
||||||
|
};
|
||||||
|
|
||||||
|
static virClassPtr virObjectEventClass;
|
||||||
|
|
||||||
|
static void virObjectEventDispose(void *obj);
|
||||||
|
|
||||||
|
static int virObjectEventOnceInit(void)
|
||||||
|
{
|
||||||
|
if (!(virObjectEventClass =
|
||||||
|
virClassNew(virClassForObject(),
|
||||||
|
"virObjectEvent",
|
||||||
|
sizeof(virObjectEvent),
|
||||||
|
virObjectEventDispose)))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_ONCE_GLOBAL_INIT(virObjectEvent)
|
||||||
|
|
||||||
|
virClassPtr virClassForObjectEvent(void)
|
||||||
|
{
|
||||||
|
if (virObjectEventInitialize() < 0)
|
||||||
|
return NULL;
|
||||||
|
return virObjectEventClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
int virObjectEventGetEventID(void *anyobj)
|
||||||
|
{
|
||||||
|
virObjectEventPtr obj = anyobj;
|
||||||
|
|
||||||
|
if (!virObjectIsClass(obj, virClassForObjectEvent())) {
|
||||||
|
VIR_WARN("Object %p (%s) is not a virObjectEvent instance",
|
||||||
|
obj, obj ? virClassName(obj->parent.klass) : "(unknown)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return obj->eventID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virObjectEventDispose(void *obj)
|
||||||
|
{
|
||||||
|
virObjectEventPtr event = obj;
|
||||||
|
|
||||||
|
VIR_DEBUG("obj=%p", event);
|
||||||
|
|
||||||
|
VIR_FREE(event->meta.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventCallbackListFree:
|
||||||
|
* @list: event callback list head
|
||||||
|
*
|
||||||
|
* Free the memory in the domain event callback list
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
virObjectEventCallbackListFree(virObjectEventCallbackListPtr list)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i=0; i<list->count; i++) {
|
||||||
|
virFreeCallback freecb = list->callbacks[i]->freecb;
|
||||||
|
if (freecb)
|
||||||
|
(*freecb)(list->callbacks[i]->opaque);
|
||||||
|
VIR_FREE(list->callbacks[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(list->callbacks);
|
||||||
|
VIR_FREE(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventCallbackListRemoveID:
|
||||||
|
* @conn: pointer to the connection
|
||||||
|
* @cbList: the list
|
||||||
|
* @callback: the callback to remove
|
||||||
|
*
|
||||||
|
* Internal function to remove a callback from a virObjectEventCallbackListPtr
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virObjectEventCallbackListRemoveID(virConnectPtr conn,
|
||||||
|
virObjectEventCallbackListPtr cbList,
|
||||||
|
int callbackID)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (cbList->callbacks[i]->callbackID == callbackID &&
|
||||||
|
cbList->callbacks[i]->conn == conn) {
|
||||||
|
virFreeCallback freecb = cbList->callbacks[i]->freecb;
|
||||||
|
if (freecb)
|
||||||
|
(*freecb)(cbList->callbacks[i]->opaque);
|
||||||
|
virObjectUnref(cbList->callbacks[i]->conn);
|
||||||
|
VIR_FREE(cbList->callbacks[i]);
|
||||||
|
|
||||||
|
if (i < (cbList->count - 1))
|
||||||
|
memmove(cbList->callbacks + i,
|
||||||
|
cbList->callbacks + i + 1,
|
||||||
|
sizeof(*(cbList->callbacks)) *
|
||||||
|
(cbList->count - (i + 1)));
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(cbList->callbacks,
|
||||||
|
cbList->count - 1) < 0) {
|
||||||
|
; /* Failure to reduce memory allocation isn't fatal */
|
||||||
|
}
|
||||||
|
cbList->count--;
|
||||||
|
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (!cbList->callbacks[i]->deleted)
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("could not find event callback for removal"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virObjectEventCallbackListMarkDeleteID(virConnectPtr conn,
|
||||||
|
virObjectEventCallbackListPtr cbList,
|
||||||
|
int callbackID)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (cbList->callbacks[i]->callbackID == callbackID &&
|
||||||
|
cbList->callbacks[i]->conn == conn) {
|
||||||
|
cbList->callbacks[i]->deleted = 1;
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (!cbList->callbacks[i]->deleted)
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("could not find event callback for deletion"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virObjectEventCallbackListPurgeMarked(virObjectEventCallbackListPtr cbList)
|
||||||
|
{
|
||||||
|
int old_count = cbList->count;
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < cbList->count; n++) {
|
||||||
|
if (cbList->callbacks[n]->deleted) {
|
||||||
|
virFreeCallback freecb = cbList->callbacks[n]->freecb;
|
||||||
|
if (freecb)
|
||||||
|
(*freecb)(cbList->callbacks[n]->opaque);
|
||||||
|
virObjectUnref(cbList->callbacks[n]->conn);
|
||||||
|
VIR_FREE(cbList->callbacks[n]);
|
||||||
|
|
||||||
|
if (n < (cbList->count - 1))
|
||||||
|
memmove(cbList->callbacks + n,
|
||||||
|
cbList->callbacks + n + 1,
|
||||||
|
sizeof(*(cbList->callbacks)) *
|
||||||
|
(cbList->count - (n + 1)));
|
||||||
|
cbList->count--;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cbList->count < old_count &&
|
||||||
|
VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) {
|
||||||
|
; /* Failure to reduce memory allocation isn't fatal */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventCallbackListAddID:
|
||||||
|
* @conn: pointer to the connection
|
||||||
|
* @cbList: the list
|
||||||
|
* @uuid: the uuid of the object to filter on
|
||||||
|
* @name: the name of the object to filter on
|
||||||
|
* @id: the ID of the object to filter on
|
||||||
|
* @eventID: the event ID
|
||||||
|
* @callback: the callback to add
|
||||||
|
* @opaque: opaque data tio pass to callback
|
||||||
|
* @callbackID: filled with callback ID
|
||||||
|
*
|
||||||
|
* Internal function to add a callback from a virObjectEventCallbackListPtr
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virObjectEventCallbackListAddID(virConnectPtr conn,
|
||||||
|
virObjectEventCallbackListPtr cbList,
|
||||||
|
unsigned char uuid[VIR_UUID_BUFLEN],
|
||||||
|
const char *name,
|
||||||
|
int id,
|
||||||
|
int eventID,
|
||||||
|
virConnectObjectEventGenericCallback callback,
|
||||||
|
void *opaque,
|
||||||
|
virFreeCallback freecb,
|
||||||
|
int *callbackID)
|
||||||
|
{
|
||||||
|
virObjectEventCallbackPtr event;
|
||||||
|
size_t i;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Check incoming */
|
||||||
|
if (!cbList) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we already have this callback on our list */
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (cbList->callbacks[i]->cb == VIR_OBJECT_EVENT_CALLBACK(callback) &&
|
||||||
|
cbList->callbacks[i]->eventID == eventID &&
|
||||||
|
cbList->callbacks[i]->conn == conn &&
|
||||||
|
((uuid && cbList->callbacks[i]->meta &&
|
||||||
|
memcmp(cbList->callbacks[i]->meta->uuid,
|
||||||
|
uuid, VIR_UUID_BUFLEN) == 0) ||
|
||||||
|
(!uuid && !cbList->callbacks[i]->meta))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("event callback already tracked"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Allocate new event */
|
||||||
|
if (VIR_ALLOC(event) < 0)
|
||||||
|
goto error;
|
||||||
|
event->conn = conn;
|
||||||
|
event->cb = callback;
|
||||||
|
event->eventID = eventID;
|
||||||
|
event->opaque = opaque;
|
||||||
|
event->freecb = freecb;
|
||||||
|
|
||||||
|
if (name && uuid && id > 0) {
|
||||||
|
if (VIR_ALLOC(event->meta) < 0)
|
||||||
|
goto error;
|
||||||
|
if (VIR_STRDUP(event->meta->name, name) < 0)
|
||||||
|
goto error;
|
||||||
|
memcpy(event->meta->uuid, uuid, VIR_UUID_BUFLEN);
|
||||||
|
event->meta->id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make space on list */
|
||||||
|
if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
virObjectRef(event->conn);
|
||||||
|
|
||||||
|
cbList->callbacks[cbList->count] = event;
|
||||||
|
cbList->count++;
|
||||||
|
|
||||||
|
event->callbackID = cbList->nextID++;
|
||||||
|
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (cbList->callbacks[i]->eventID == eventID &&
|
||||||
|
cbList->callbacks[i]->conn == conn &&
|
||||||
|
!cbList->callbacks[i]->deleted)
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbackID)
|
||||||
|
*callbackID = event->callbackID;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (event) {
|
||||||
|
if (event->meta)
|
||||||
|
VIR_FREE(event->meta->name);
|
||||||
|
VIR_FREE(event->meta);
|
||||||
|
}
|
||||||
|
VIR_FREE(event);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virObjectEventCallbackListEventID(virConnectPtr conn,
|
||||||
|
virObjectEventCallbackListPtr cbList,
|
||||||
|
int callbackID)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < cbList->count; i++) {
|
||||||
|
if (cbList->callbacks[i]->deleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cbList->callbacks[i]->callbackID == callbackID &&
|
||||||
|
cbList->callbacks[i]->conn == conn)
|
||||||
|
return cbList->callbacks[i]->eventID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventQueueClear:
|
||||||
|
* @queue: pointer to the queue
|
||||||
|
*
|
||||||
|
* Removes all elements from the queue
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
virObjectEventQueueClear(virObjectEventQueuePtr queue)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!queue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < queue->count; i++) {
|
||||||
|
virObjectUnref(queue->events[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(queue->events);
|
||||||
|
queue->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventQueueFree:
|
||||||
|
* @queue: pointer to the queue
|
||||||
|
*
|
||||||
|
* Free the memory in the queue. We process this like a list here
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
virObjectEventQueueFree(virObjectEventQueuePtr queue)
|
||||||
|
{
|
||||||
|
if (!queue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
virObjectEventQueueClear(queue);
|
||||||
|
VIR_FREE(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static virObjectEventQueuePtr
|
||||||
|
virObjectEventQueueNew(void)
|
||||||
|
{
|
||||||
|
virObjectEventQueuePtr ret;
|
||||||
|
|
||||||
|
ignore_value(VIR_ALLOC(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventStateLock(virObjectEventStatePtr state)
|
||||||
|
{
|
||||||
|
virMutexLock(&state->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventStateUnlock(virObjectEventStatePtr state)
|
||||||
|
{
|
||||||
|
virMutexUnlock(&state->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventStateFree:
|
||||||
|
* @list: virObjectEventStatePtr to free
|
||||||
|
*
|
||||||
|
* Free a virObjectEventStatePtr and its members, and unregister the timer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
virObjectEventStateFree(virObjectEventStatePtr state)
|
||||||
|
{
|
||||||
|
if (!state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
virObjectEventCallbackListFree(state->callbacks);
|
||||||
|
virObjectEventQueueFree(state->queue);
|
||||||
|
|
||||||
|
if (state->timer != -1)
|
||||||
|
virEventRemoveTimeout(state->timer);
|
||||||
|
|
||||||
|
virMutexDestroy(&state->lock);
|
||||||
|
VIR_FREE(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virObjectEventStateFlush(virObjectEventStatePtr state);
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
|
||||||
|
{
|
||||||
|
virObjectEventStatePtr state = opaque;
|
||||||
|
|
||||||
|
virObjectEventStateFlush(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventStateNew:
|
||||||
|
*/
|
||||||
|
virObjectEventStatePtr
|
||||||
|
virObjectEventStateNew(void)
|
||||||
|
{
|
||||||
|
virObjectEventStatePtr state = NULL;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(state) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (virMutexInit(&state->lock) < 0) {
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("unable to initialize state mutex"));
|
||||||
|
VIR_FREE(state);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC(state->callbacks) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(state->queue = virObjectEventQueueNew()))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
state->timer = -1;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virObjectEventStateFree(state);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *virObjectEventNew(virClassPtr klass,
|
||||||
|
int eventID,
|
||||||
|
int id,
|
||||||
|
const char *name,
|
||||||
|
const unsigned char *uuid)
|
||||||
|
{
|
||||||
|
virObjectEventPtr event;
|
||||||
|
|
||||||
|
if (virObjectEventInitialize() < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!virClassIsDerivedFrom(klass, virObjectEventClass)) {
|
||||||
|
virReportInvalidArg(klass,
|
||||||
|
_("Class %s must derive from virObjectEvent"),
|
||||||
|
virClassName(klass));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(event = virObjectNew(klass)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
event->eventID = eventID;
|
||||||
|
|
||||||
|
if (VIR_STRDUP(event->meta.name, name) < 0) {
|
||||||
|
VIR_FREE(event);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
event->meta.id = id;
|
||||||
|
memcpy(event->meta.uuid, uuid, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
|
VIR_DEBUG("obj=%p", event);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventQueuePush:
|
||||||
|
* @evtQueue: the object event queue
|
||||||
|
* @event: the event to add
|
||||||
|
*
|
||||||
|
* Internal function to push to the back of a virObjectEventQueue
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virObjectEventQueuePush(virObjectEventQueuePtr evtQueue,
|
||||||
|
virObjectEventPtr event)
|
||||||
|
{
|
||||||
|
if (!evtQueue) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make space on queue */
|
||||||
|
if (VIR_REALLOC_N(evtQueue->events,
|
||||||
|
evtQueue->count + 1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
evtQueue->events[evtQueue->count] = event;
|
||||||
|
evtQueue->count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*virObjectEventDispatchFunc)(virConnectPtr conn,
|
||||||
|
virObjectEventPtr event,
|
||||||
|
virConnectObjectEventGenericCallback cb,
|
||||||
|
void *cbopaque,
|
||||||
|
void *opaque);
|
||||||
|
|
||||||
|
|
||||||
|
static int virObjectEventDispatchMatchCallback(virObjectEventPtr event,
|
||||||
|
virObjectEventCallbackPtr cb)
|
||||||
|
{
|
||||||
|
if (!cb)
|
||||||
|
return 0;
|
||||||
|
if (cb->deleted)
|
||||||
|
return 0;
|
||||||
|
if (cb->eventID != virObjectEventGetEventID(event))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (cb->meta) {
|
||||||
|
/* Deliberately 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 truly reliable ID we can use*/
|
||||||
|
|
||||||
|
if (memcmp(event->meta.uuid, cb->meta->uuid, VIR_UUID_BUFLEN) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virObjectEventDispatch(virObjectEventPtr event,
|
||||||
|
virObjectEventCallbackListPtr callbacks,
|
||||||
|
virObjectEventDispatchFunc dispatch,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
/* Cache this now, since we may be dropping the lock,
|
||||||
|
and have more callbacks added. We're guaranteed not
|
||||||
|
to have any removed */
|
||||||
|
int cbCount = callbacks->count;
|
||||||
|
|
||||||
|
for (i = 0; i < cbCount; i++) {
|
||||||
|
if (!virObjectEventDispatchMatchCallback(event, callbacks->callbacks[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(*dispatch)(callbacks->callbacks[i]->conn,
|
||||||
|
event,
|
||||||
|
callbacks->callbacks[i]->cb,
|
||||||
|
callbacks->callbacks[i]->opaque,
|
||||||
|
opaque);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virObjectEventQueueDispatch(virObjectEventQueuePtr queue,
|
||||||
|
virObjectEventCallbackListPtr callbacks,
|
||||||
|
virObjectEventDispatchFunc dispatch,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < queue->count; i++) {
|
||||||
|
virObjectEventDispatch(queue->events[i], callbacks, dispatch, opaque);
|
||||||
|
virObjectUnref(queue->events[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(queue->events);
|
||||||
|
queue->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventStateQueue(virObjectEventStatePtr state,
|
||||||
|
virObjectEventPtr event)
|
||||||
|
{
|
||||||
|
if (state->timer < 0) {
|
||||||
|
virObjectUnref(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virObjectEventStateLock(state);
|
||||||
|
|
||||||
|
if (virObjectEventQueuePush(state->queue, event) < 0) {
|
||||||
|
VIR_DEBUG("Error adding event to queue");
|
||||||
|
virObjectUnref(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->queue->count == 1)
|
||||||
|
virEventUpdateTimeout(state->timer, 0);
|
||||||
|
virObjectEventStateUnlock(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virObjectEventStateDispatchFunc(virConnectPtr conn,
|
||||||
|
virObjectEventPtr event,
|
||||||
|
virConnectObjectEventGenericCallback cb,
|
||||||
|
void *cbopaque,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virObjectEventStatePtr state = opaque;
|
||||||
|
virEventNamespaceID namespace = (event->eventID & 0xFF00) >> 8;
|
||||||
|
|
||||||
|
/* Drop the lock whle dispatching, for sake of re-entrancy */
|
||||||
|
virObjectEventStateUnlock(state);
|
||||||
|
switch (namespace)
|
||||||
|
{
|
||||||
|
case VIR_EVENT_NAMESPACE_DOMAIN:
|
||||||
|
virDomainEventDispatchDefaultFunc(conn, event,
|
||||||
|
VIR_DOMAIN_EVENT_CALLBACK(cb), cbopaque, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
virObjectEventStateLock(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virObjectEventStateFlush(virObjectEventStatePtr state)
|
||||||
|
{
|
||||||
|
virObjectEventQueue tempQueue;
|
||||||
|
|
||||||
|
virObjectEventStateLock(state);
|
||||||
|
state->isDispatching = true;
|
||||||
|
|
||||||
|
/* Copy the queue, so we're reentrant safe when dispatchFunc drops the
|
||||||
|
* driver lock */
|
||||||
|
tempQueue.count = state->queue->count;
|
||||||
|
tempQueue.events = state->queue->events;
|
||||||
|
state->queue->count = 0;
|
||||||
|
state->queue->events = NULL;
|
||||||
|
virEventUpdateTimeout(state->timer, -1);
|
||||||
|
|
||||||
|
virObjectEventQueueDispatch(&tempQueue,
|
||||||
|
state->callbacks,
|
||||||
|
virObjectEventStateDispatchFunc,
|
||||||
|
state);
|
||||||
|
|
||||||
|
/* Purge any deleted callbacks */
|
||||||
|
virObjectEventCallbackListPurgeMarked(state->callbacks);
|
||||||
|
|
||||||
|
state->isDispatching = false;
|
||||||
|
virObjectEventStateUnlock(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventStateRegisterID:
|
||||||
|
* @conn: connection to associate with callback
|
||||||
|
* @state: domain event state
|
||||||
|
* @eventID: ID of the event type to register for
|
||||||
|
* @cb: function to remove from event
|
||||||
|
* @opaque: data blob to pass to callback
|
||||||
|
* @freecb: callback to free @opaque
|
||||||
|
* @callbackID: filled with callback ID
|
||||||
|
*
|
||||||
|
* Register the function @callbackID with connection @conn,
|
||||||
|
* from @state, for events of type @eventID.
|
||||||
|
*
|
||||||
|
* Returns: the number of callbacks now registered, or -1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virObjectEventStateRegisterID(virConnectPtr conn,
|
||||||
|
virObjectEventStatePtr state,
|
||||||
|
unsigned char *uuid,
|
||||||
|
const char *name,
|
||||||
|
int id,
|
||||||
|
int eventID,
|
||||||
|
virConnectObjectEventGenericCallback cb,
|
||||||
|
void *opaque,
|
||||||
|
virFreeCallback freecb,
|
||||||
|
int *callbackID)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
virObjectEventStateLock(state);
|
||||||
|
|
||||||
|
if ((state->callbacks->count == 0) &&
|
||||||
|
(state->timer == -1) &&
|
||||||
|
(state->timer = virEventAddTimeout(-1,
|
||||||
|
virObjectEventTimer,
|
||||||
|
state,
|
||||||
|
NULL)) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("could not initialize domain event timer"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virObjectEventCallbackListAddID(conn, state->callbacks,
|
||||||
|
uuid, name, id, eventID, cb, opaque, freecb,
|
||||||
|
callbackID);
|
||||||
|
|
||||||
|
if (ret == -1 &&
|
||||||
|
state->callbacks->count == 0 &&
|
||||||
|
state->timer != -1) {
|
||||||
|
virEventRemoveTimeout(state->timer);
|
||||||
|
state->timer = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectEventStateUnlock(state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventStateDeregisterID:
|
||||||
|
* @conn: connection to associate with callback
|
||||||
|
* @state: object event state
|
||||||
|
* @callbackID: ID of the function to remove from event
|
||||||
|
*
|
||||||
|
* Unregister the function @callbackID with connection @conn,
|
||||||
|
* from @state, for events.
|
||||||
|
*
|
||||||
|
* Returns: the number of callbacks still registered, or -1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virObjectEventStateDeregisterID(virConnectPtr conn,
|
||||||
|
virObjectEventStatePtr state,
|
||||||
|
int callbackID)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
virObjectEventStateLock(state);
|
||||||
|
if (state->isDispatching)
|
||||||
|
ret = virObjectEventCallbackListMarkDeleteID(conn,
|
||||||
|
state->callbacks, callbackID);
|
||||||
|
else
|
||||||
|
ret = virObjectEventCallbackListRemoveID(conn,
|
||||||
|
state->callbacks, callbackID);
|
||||||
|
|
||||||
|
if (state->callbacks->count == 0 &&
|
||||||
|
state->timer != -1) {
|
||||||
|
virEventRemoveTimeout(state->timer);
|
||||||
|
state->timer = -1;
|
||||||
|
virObjectEventQueueClear(state->queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
virObjectEventStateUnlock(state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virObjectEventStateEventID:
|
||||||
|
* @conn: connection associated with the callback
|
||||||
|
* @state: object event state
|
||||||
|
* @callbackID: the callback to query
|
||||||
|
*
|
||||||
|
* Query what event ID type is associated with the
|
||||||
|
* callback @callbackID for connection @conn
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virObjectEventStateEventID(virConnectPtr conn,
|
||||||
|
virObjectEventStatePtr state,
|
||||||
|
int callbackID)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
virObjectEventStateLock(state);
|
||||||
|
ret = virObjectEventCallbackListEventID(conn,
|
||||||
|
state->callbacks, callbackID);
|
||||||
|
virObjectEventStateUnlock(state);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* object_event.h: object event queue processing helpers
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2008 VirtualIron
|
||||||
|
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Ben Guthro
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#ifndef __OBJECT_EVENT_H__
|
||||||
|
# define __OBJECT_EVENT_H__
|
||||||
|
|
||||||
|
/** Event IDs are computed in the following way:
|
||||||
|
virEventNamespaceID << 8 + vir*EventId
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */
|
||||||
|
} virEventNamespaceID;
|
||||||
|
|
||||||
|
typedef struct _virObjectEventCallback virObjectEventCallback;
|
||||||
|
typedef virObjectEventCallback *virObjectEventCallbackPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatching domain events that come in while
|
||||||
|
* in a call / response rpc
|
||||||
|
*/
|
||||||
|
typedef struct _virObjectEvent virObjectEvent;
|
||||||
|
typedef virObjectEvent *virObjectEventPtr;
|
||||||
|
|
||||||
|
typedef struct _virObjectEventState virObjectEventState;
|
||||||
|
typedef virObjectEventState *virObjectEventStatePtr;
|
||||||
|
|
||||||
|
|
||||||
|
void virObjectEventStateFree(virObjectEventStatePtr state);
|
||||||
|
virObjectEventStatePtr
|
||||||
|
virObjectEventStateNew(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* virConnectObjectEventGenericCallback:
|
||||||
|
* @conn: the connection pointer
|
||||||
|
* @obj: the object pointer
|
||||||
|
* @opaque: application specified data
|
||||||
|
*
|
||||||
|
* A generic object event callback handler. Specific events usually
|
||||||
|
* have a customization with extra parameters
|
||||||
|
*/
|
||||||
|
typedef void (*virConnectObjectEventGenericCallback)(virConnectPtr conn,
|
||||||
|
void *obj,
|
||||||
|
void *opaque);
|
||||||
|
|
||||||
|
# define VIR_OBJECT_EVENT_CALLBACK(cb) ((virConnectObjectEventGenericCallback)(cb))
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventStateQueue(virObjectEventStatePtr state,
|
||||||
|
virObjectEventPtr event)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
int
|
||||||
|
virObjectEventStateRegisterID(virConnectPtr conn,
|
||||||
|
virObjectEventStatePtr state,
|
||||||
|
unsigned char *uuid,
|
||||||
|
const char *name,
|
||||||
|
int id,
|
||||||
|
int eventID,
|
||||||
|
virConnectObjectEventGenericCallback cb,
|
||||||
|
void *opaque,
|
||||||
|
virFreeCallback freecb,
|
||||||
|
int *callbackID)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(7);
|
||||||
|
int
|
||||||
|
virObjectEventStateDeregisterID(virConnectPtr conn,
|
||||||
|
virObjectEventStatePtr state,
|
||||||
|
int callbackID)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
int
|
||||||
|
virObjectEventStateEventID(virConnectPtr conn,
|
||||||
|
virObjectEventStatePtr state,
|
||||||
|
int callbackID)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* object_event_private.h: object event queue processing helpers
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2008 VirtualIron
|
||||||
|
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Ben Guthro
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
|
||||||
|
#ifndef __OBJECT_EVENT_PRIVATE_H__
|
||||||
|
# define __OBJECT_EVENT_PRIVATE_H__
|
||||||
|
|
||||||
|
struct _virObjectMeta {
|
||||||
|
int id;
|
||||||
|
char *name;
|
||||||
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||||
|
};
|
||||||
|
typedef struct _virObjectMeta virObjectMeta;
|
||||||
|
typedef virObjectMeta *virObjectMetaPtr;
|
||||||
|
|
||||||
|
struct _virObjectEventCallbackList {
|
||||||
|
unsigned int nextID;
|
||||||
|
unsigned int count;
|
||||||
|
virObjectEventCallbackPtr *callbacks;
|
||||||
|
};
|
||||||
|
typedef struct _virObjectEventCallbackList virObjectEventCallbackList;
|
||||||
|
typedef virObjectEventCallbackList *virObjectEventCallbackListPtr;
|
||||||
|
|
||||||
|
typedef struct _virObjectEventQueue virObjectEventQueue;
|
||||||
|
typedef virObjectEventQueue *virObjectEventQueuePtr;
|
||||||
|
|
||||||
|
struct _virObjectEventState {
|
||||||
|
/* The list of domain event callbacks */
|
||||||
|
virObjectEventCallbackListPtr callbacks;
|
||||||
|
/* The queue of object events */
|
||||||
|
virObjectEventQueuePtr queue;
|
||||||
|
/* Timer for flushing events queue */
|
||||||
|
int timer;
|
||||||
|
/* Flag if we're in process of dispatching */
|
||||||
|
bool isDispatching;
|
||||||
|
virMutex lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _virObjectEventCallback {
|
||||||
|
int callbackID;
|
||||||
|
int eventID;
|
||||||
|
virConnectPtr conn;
|
||||||
|
virObjectMetaPtr meta;
|
||||||
|
virConnectObjectEventGenericCallback cb;
|
||||||
|
void *opaque;
|
||||||
|
virFreeCallback freecb;
|
||||||
|
int deleted;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _virObjectEvent {
|
||||||
|
virObject parent;
|
||||||
|
int eventID;
|
||||||
|
virObjectMeta meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
virClassPtr virClassForObjectEvent(void);
|
||||||
|
|
||||||
|
int virObjectEventGetEventID(void *anyobj);
|
||||||
|
|
||||||
|
int
|
||||||
|
virObjectEventCallbackListAddID(virConnectPtr conn,
|
||||||
|
virObjectEventCallbackListPtr cbList,
|
||||||
|
unsigned char *uuid,
|
||||||
|
const char *name,
|
||||||
|
int id,
|
||||||
|
int eventID,
|
||||||
|
virConnectObjectEventGenericCallback callback,
|
||||||
|
void *opaque,
|
||||||
|
virFreeCallback freecb,
|
||||||
|
int *callbackID);
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventQueueClear(virObjectEventQueuePtr queue);
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventStateLock(virObjectEventStatePtr state);
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventStateUnlock(virObjectEventStatePtr state);
|
||||||
|
|
||||||
|
void
|
||||||
|
virObjectEventTimer(int timer, void *opaque);
|
||||||
|
|
||||||
|
void *virObjectEventNew(virClassPtr klass,
|
||||||
|
int eventID,
|
||||||
|
int id,
|
||||||
|
const char *name,
|
||||||
|
const unsigned char *uuid);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -452,12 +452,6 @@ virDomainEventTrayChangeNewFromDom;
|
||||||
virDomainEventTrayChangeNewFromObj;
|
virDomainEventTrayChangeNewFromObj;
|
||||||
virDomainEventWatchdogNewFromDom;
|
virDomainEventWatchdogNewFromDom;
|
||||||
virDomainEventWatchdogNewFromObj;
|
virDomainEventWatchdogNewFromObj;
|
||||||
virObjectEventStateDeregisterID;
|
|
||||||
virObjectEventStateEventID;
|
|
||||||
virObjectEventStateFree;
|
|
||||||
virObjectEventStateNew;
|
|
||||||
virObjectEventStateQueue;
|
|
||||||
virObjectEventStateRegisterID;
|
|
||||||
|
|
||||||
|
|
||||||
# conf/domain_nwfilter.h
|
# conf/domain_nwfilter.h
|
||||||
|
@ -629,6 +623,15 @@ virNWFilterVarValueGetNthValue;
|
||||||
virNWFilterVarValueGetSimple;
|
virNWFilterVarValueGetSimple;
|
||||||
|
|
||||||
|
|
||||||
|
# conf/object_event.h
|
||||||
|
virObjectEventStateDeregisterID;
|
||||||
|
virObjectEventStateEventID;
|
||||||
|
virObjectEventStateFree;
|
||||||
|
virObjectEventStateNew;
|
||||||
|
virObjectEventStateQueue;
|
||||||
|
virObjectEventStateRegisterID;
|
||||||
|
|
||||||
|
|
||||||
# conf/secret_conf.h
|
# conf/secret_conf.h
|
||||||
virSecretDefFormat;
|
virSecretDefFormat;
|
||||||
virSecretDefFree;
|
virSecretDefFree;
|
||||||
|
|
Loading…
Reference in New Issue