[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
[libvirt] Re: [PATCH 01/12] Domain Events - Public API
- From: Ben Guthro <bguthro virtualiron com>
- To: libvir-list redhat com
- Subject: [libvirt] Re: [PATCH 01/12] Domain Events - Public API
- Date: Fri, 17 Oct 2008 11:53:53 -0400
This patch does the following:
-implements the Event register/deregister code
-Adds some callback lists, and queue functions used by drivers
-Move EventImpl definitions into the public
include/libvirt/libvirt.h | 59 +++++++++
include/libvirt/libvirt.h.in | 59 +++++++++
src/libvirt.c | 256 +++++++++++++++++++++++++++++++++++++++++++
src/libvirt_sym.version | 9 +
4 files changed, 381 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 35b80d0..53ad6b7 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -993,6 +993,65 @@ char * virStorageVolGetPath (virStorageVolPtr vol);
virDomainPtr virDomainCreateLinux (virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
+
+/*
+ * Domain Event Notification
+ */
+
+typedef enum {
+ VIR_DOMAIN_EVENT_ADDED,
+ VIR_DOMAIN_EVENT_REMOVED,
+ VIR_DOMAIN_EVENT_STARTED,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_RESUMED,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_SAVED,
+ VIR_DOMAIN_EVENT_RESTORED,
+} virDomainEventType;
+
+typedef int (*virConnectDomainEventCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ int event,
+ void *opaque);
+
+int virConnectDomainEventRegister(virConnectPtr conn,
+ virConnectDomainEventCallback cb,
+ void *opaque);
+
+int virConnectDomainEventDeregister(virConnectPtr conn,
+ virConnectDomainEventCallback cb);
+
+/**
+ * virEventHandleCallback: callback for receiving file handle events
+ *
+ * @fd: file handle on which the event occurred
+ * @events: bitset of events from POLLnnn constants
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
+
+typedef int (*virEventAddHandleFunc)(int, int, virEventHandleCallback, void *);
+typedef void (*virEventUpdateHandleFunc)(int, int);
+typedef int (*virEventRemoveHandleFunc)(int);
+
+/**
+ * virEventTimeoutCallback: callback for receiving timer events
+ *
+ * @timer: timer id emitting the event
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventTimeoutCallback)(int timer, void *opaque);
+
+typedef int (*virEventAddTimeoutFunc)(int, virEventTimeoutCallback, void *);
+typedef void (*virEventUpdateTimeoutFunc)(int, int);
+typedef int (*virEventRemoveTimeoutFunc)(int);
+
+void virEventRegisterImpl(virEventAddHandleFunc addHandle,
+ virEventUpdateHandleFunc updateHandle,
+ virEventRemoveHandleFunc removeHandle,
+ virEventAddTimeoutFunc addTimeout,
+ virEventUpdateTimeoutFunc updateTimeout,
+ virEventRemoveTimeoutFunc removeTimeout);
#ifdef __cplusplus
}
#endif
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 3624367..6af5329 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -993,6 +993,65 @@ char * virStorageVolGetPath (virStorageVolPtr vol);
virDomainPtr virDomainCreateLinux (virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
+
+/*
+ * Domain Event Notification
+ */
+
+typedef enum {
+ VIR_DOMAIN_EVENT_ADDED,
+ VIR_DOMAIN_EVENT_REMOVED,
+ VIR_DOMAIN_EVENT_STARTED,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_RESUMED,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_SAVED,
+ VIR_DOMAIN_EVENT_RESTORED,
+} virDomainEventType;
+
+typedef int (*virConnectDomainEventCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ int event,
+ void *opaque);
+
+int virConnectDomainEventRegister(virConnectPtr conn,
+ virConnectDomainEventCallback cb,
+ void *opaque);
+
+int virConnectDomainEventDeregister(virConnectPtr conn,
+ virConnectDomainEventCallback cb);
+
+/**
+ * virEventHandleCallback: callback for receiving file handle events
+ *
+ * @fd: file handle on which the event occurred
+ * @events: bitset of events from POLLnnn constants
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
+
+typedef int (*virEventAddHandleFunc)(int, int, virEventHandleCallback, void *);
+typedef void (*virEventUpdateHandleFunc)(int, int);
+typedef int (*virEventRemoveHandleFunc)(int);
+
+/**
+ * virEventTimeoutCallback: callback for receiving timer events
+ *
+ * @timer: timer id emitting the event
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventTimeoutCallback)(int timer, void *opaque);
+
+typedef int (*virEventAddTimeoutFunc)(int, virEventTimeoutCallback, void *);
+typedef void (*virEventUpdateTimeoutFunc)(int, int);
+typedef int (*virEventRemoveTimeoutFunc)(int);
+
+void virEventRegisterImpl(virEventAddHandleFunc addHandle,
+ virEventUpdateHandleFunc updateHandle,
+ virEventRemoveHandleFunc removeHandle,
+ virEventAddTimeoutFunc addTimeout,
+ virEventUpdateTimeoutFunc updateTimeout,
+ virEventRemoveTimeoutFunc removeTimeout);
#ifdef __cplusplus
}
#endif
diff --git a/src/libvirt.c b/src/libvirt.c
index ca2675a..33df94e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5345,3 +5345,259 @@ void virStringListFree(virStringList *list)
list = p;
}
}
+
+/*
+ * Domain Event Notification
+ */
+
+/**
+ * virDomainEventCallbackListFree:
+ * @list: event callback list head
+ *
+ * Free the memory in the domain event callback list
+ */
+void virDomainEventCallbackListFree(virDomainEventCallbackListPtr list)
+{
+ int i;
+ for(i=0; i<list->count;i++) {
+ VIR_FREE(list->callbacks[i]);
+ }
+ VIR_FREE(list);
+}
+
+/**
+ * virConnectDomainEventRegister:
+ * @conn: pointer to the connection
+ * @cb: callback to the function handling domain events
+ * @opaque: opaque data to pass on to the callback
+ *
+ * Adds a Domain Event Callback
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int virConnectDomainEventRegister(virConnectPtr conn,
+ virConnectDomainEventCallback cb,
+ void *opaque)
+{
+ /* Registering for a domain callback will enable delivery by default */
+ if (conn->driver && conn->driver->domainEventRegister)
+ return conn->driver->domainEventRegister (conn, cb, opaque);
+ return -1;
+}
+
+/**
+ * virConnectDomainEventDeregister:
+ * @conn: pointer to the connection
+ * @cb: callback to the function handling domain events
+ *
+ * Removes a Domain Event Callback
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int virConnectDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback cb)
+{
+ /* De-registering for a domain callback will disable delivery of this event type*/
+ if (conn->driver && conn->driver->domainEventDeregister)
+ return conn->driver->domainEventDeregister (conn, cb);
+
+ return -1;
+}
+
+/**
+ * virDispatchDomainEvent:
+ * @dom: the domain
+ * @event: the domain event code
+ *
+ * Internal function by which drivers to dispatch domain events.
+ */
+void virDispatchDomainEvent(virDomainPtr dom,
+ int event)
+{
+ if (dom->conn && dom->conn->driver &&
+ dom->conn->driver->domainEventDispatch)
+ dom->conn->driver->domainEventDispatch(dom, event);
+}
+
+/**
+ * virDomainEventCallbackListRemove:
+ * @cbList: the list
+ * @callback: the callback to remove
+ *
+ * Internal function to remove a callback from a virDomainEventCallbackListPtr
+ */
+int __virDomainEventCallbackListRemove(virConnectPtr conn,
+ virDomainEventCallbackListPtr cbList,
+ virConnectDomainEventCallback callback)
+{
+ int i;
+ for (i = 0 ; i < cbList->count ; i++) {
+ if(cbList->callbacks[i]->cb == callback &&
+ cbList->callbacks[i]->conn == conn) {
+ virUnrefConnect(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--;
+
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/**
+ * virDomainEventCallbackListAdd:
+ * @cbList: the list
+ * @callback: the callback to add
+ * @opaque: opaque data tio pass to callback
+ *
+ * Internal function to add a callback from a virDomainEventCallbackListPtr
+ */
+int __virDomainEventCallbackListAdd(virConnectPtr conn,
+ virDomainEventCallbackListPtr cbList,
+ virConnectDomainEventCallback callback,
+ void *opaque)
+{
+ virDomainEventCallbackPtr event;
+ int n;
+
+ /* Check incoming */
+ if ( !cbList ) {
+ return -1;
+ }
+
+ /* check if we already have this callback on our list */
+ for( n=0; n < cbList->count; n++ )
+ {
+ if(cbList->callbacks[n]->cb == callback &&
+ conn == cbList->callbacks[n]->conn) {
+ DEBUG0("WARNING: Callback already tracked");
+ return -1;
+ }
+ }
+ /* Allocate new event */
+ if (VIR_ALLOC(event) < 0) {
+ DEBUG0("Error allocating event");
+ return -1;
+ }
+ event->conn = conn;
+ event->cb = callback;
+ event->opaque = opaque;
+
+ /* Make space on list */
+ n = cbList->count;
+ if (VIR_REALLOC_N(cbList->callbacks,
+ n + 1) < 0) {
+ DEBUG0("Error reallocating list");
+ VIR_FREE(event);
+ return -1;
+ }
+
+ event->conn->refs++;
+
+ cbList->callbacks[n] = event;
+ cbList->count++;
+ return 0;
+}
+
+/**
+ * virDomainEventQueueFree:
+ * @queue: fron of queue
+ *
+ * Free the memory in the queue. We process this like a list here
+ */
+void virDomainEventQueueFree(virDomainEventQueuePtr queue)
+{
+ int i;
+ for(i=0; i<queue->count;i++) {
+ VIR_FREE(queue->events[i]);
+ }
+ VIR_FREE(queue);
+}
+
+/**
+ * virDomainEventCallbackQueuePop:
+ * @evtQueue: the queue of events
+ *
+ * Internal function to pop off, and return the front of the queue
+ * NOTE: The caller is responsible for freeing the returned object
+ *
+ * Returns: virDomainEventPtr on success NULL on failure.
+ */
+virDomainEventPtr virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
+{
+ virDomainEventPtr ret;
+
+ if(!evtQueue || evtQueue->count == 0 )
+ return NULL;
+
+ ret = evtQueue->events[0];
+
+ memmove(evtQueue->events,
+ evtQueue->events + 1,
+ sizeof(*(evtQueue->events)) *
+ (evtQueue->count - 1));
+
+ if (VIR_REALLOC_N(evtQueue->events,
+ evtQueue->count - 1) < 0) {
+ ; /* Failure to reduce memory allocation isn't fatal */
+ }
+ evtQueue->count--;
+
+ return ret;
+}
+
+/**
+ * virDomainEventCallbackQueuePush:
+ * @evtQueue: the dom event queue
+ * @dom: the domain to add
+ * @event: the event to add
+ *
+ * Internal function to push onto the back of an virDomainEventQueue
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue,
+ virDomainPtr dom,
+ virDomainEventType event,
+ virConnectDomainEventCallback cb,
+ void *opaque)
+{
+ virDomainEventPtr domEvent;
+
+ /* Check incoming */
+ if ( !evtQueue ) {
+ return -1;
+ }
+
+ /* Allocate new event */
+ if (VIR_ALLOC(domEvent) < 0) {
+ DEBUG0("Error allocating event");
+ return -1;
+ }
+ domEvent->dom = dom;
+ domEvent->event = event;
+ domEvent->cb = cb;
+ domEvent->opaque = opaque;
+
+ /* Make space on queue */
+ if (VIR_REALLOC_N(evtQueue->events,
+ evtQueue->count + 1) < 0) {
+ DEBUG0("Error reallocating queue");
+ VIR_FREE(domEvent);
+ return -1;
+ }
+
+ evtQueue->events[evtQueue->count] = domEvent;
+ evtQueue->count++;
+ return 0;
+}
diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version
index 3cc4505..5776cf9 100644
--- a/src/libvirt_sym.version
+++ b/src/libvirt_sym.version
@@ -147,6 +147,10 @@
virStorageVolGetXMLDesc;
virStorageVolGetPath;
+ virEventRegisterImpl;
+ virConnectDomainEventRegister;
+ virConnectDomainEventDeregister;
+
/* Symbols with __ are private only
for use by the libvirtd daemon.
They are not part of stable ABI
@@ -167,8 +171,6 @@
__virGetStoragePool;
__virGetStorageVol;
- __virEventRegisterImpl;
-
__virStateInitialize;
__virStateCleanup;
__virStateReload;
@@ -198,5 +200,8 @@
__virReallocN;
__virFree;
+ __virDomainEventCallbackListFree;
+ __virDomainEventCallbackListAdd;
+ __virDomainEventCallbackListRemove;
local: *;
};
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]