[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: Tue, 21 Oct 2008 15:11:08 -0400
[PATCH 01/12] Domain Events - Public API
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
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 35b80d0..7f784c6 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -993,6 +993,156 @@ char * virStorageVolGetPath (virStorageVolPtr vol);
virDomainPtr virDomainCreateLinux (virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
+
+/*
+ * Domain Event Notification
+ */
+
+/**
+ * virDomainEventType:
+ *
+ * a virDomainEventType is emitted during domain lifecycle events
+ */
+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;
+
+/**
+ * virConnectDomainEventCallback:
+ * @conn: virConnect connection
+ * @dom: The domain on which the event occured
+ * @event: The specfic virDomainEventType which occured
+ * @opaque: opaque user data
+ *
+ * A callback function to be registered, and called when a domain event occurs
+ */
+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);
+
+/*
+ * Events Implementation
+ */
+
+/**
+ * virEventHandleType:
+ *
+ * a virEventHandleType is used similar to POLLxxx FD events, but is specific
+ * to libvirt. A client app must translate to, and from POLL events when using
+ * this construct.
+ */
+typedef enum {
+ VIR_EVENT_HANDLE_READABLE = (1 << 0),
+ VIR_EVENT_HANDLE_WRITABLE = (1 << 1),
+ VIR_EVENT_HANDLE_ERROR = (1 << 2),
+ VIR_EVENT_HANDLE_HANGUP = (1 << 3),
+} virEventHandleType;
+
+/**
+ * virEventHandleCallback: callback for receiving file handle events
+ *
+ * @fd: file handle on which the event occurred
+ * @events: bitset of events from virEventHandleType constants
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventHandleCallback)(int fd, virEventHandleType events,
+ void *opaque);
+
+/**
+ * virEventAddHandleFunc:
+ * @fd: file descriptor to listen on
+ * @event: events on which to fire the callback
+ * @cb: the callback to be called
+ * @opaque: user data to pass to the callback
+ *
+ * Part of the EventImpl, this callback Adds a file handle callback to
+ * listen for specific events
+ */
+typedef int (*virEventAddHandleFunc)(int fd, virEventHandleType event,
+ virEventHandleCallback cb, void *opaque);
+
+/**
+ * virEventUpdateHandleFunc:
+ * @fd: file descriptor to modify
+ * @event: new events to listen on
+ *
+ * Part of the EventImpl, this user-provided callback is notified when
+ * events to listen on change
+ */
+typedef void (*virEventUpdateHandleFunc)(int fd, virEventHandleType event);
+
+/**
+ * virEventRemoveHandleFunc:
+ * @fd: file descriptor to stop listening on
+ *
+ * Part of the EventImpl, this user-provided callback is notified when
+ * an fd is no longer being listened on
+ */
+typedef int (*virEventRemoveHandleFunc)(int fd);
+
+/**
+ * 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);
+
+/**
+ * virEventAddTimeoutFunc:
+ * @timeout: The timeout to monitor
+ * @cb: the callback to call when timeout has expired
+ * @opaque: user data to pass to the callback
+ *
+ * Part of the EventImpl, this user-defined callback handles adding an
+ * event timeout.
+ *
+ * Returns a timer value
+ */
+typedef int (*virEventAddTimeoutFunc)(int timeout, virEventTimeoutCallback cb,
+ void *opaque);
+
+/**
+ * virEventUpdateTimeoutFunc:
+ * @timer: the timer to modify
+ * @timeout: the new timeout value
+ *
+ * Part of the EventImpl, this user-defined callback updates an
+ * event timeout.
+ */
+typedef void (*virEventUpdateTimeoutFunc)(int timer, int timeout);
+
+/**
+ * virEventRemoveTimeoutFunc:
+ * @timer: the timer to remove
+ *
+ * Part of the EventImpl, this user-defined callback removes a timer
+ *
+ * Returns 0 on success, -1 on failure
+ */
+typedef int (*virEventRemoveTimeoutFunc)(int timer);
+
+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..1cd9ca9 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -993,6 +993,156 @@ char * virStorageVolGetPath (virStorageVolPtr vol);
virDomainPtr virDomainCreateLinux (virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
+
+/*
+ * Domain Event Notification
+ */
+
+/**
+ * virDomainEventType:
+ *
+ * a virDomainEventType is emitted during domain lifecycle events
+ */
+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;
+
+/**
+ * virConnectDomainEventCallback:
+ * @conn: virConnect connection
+ * @dom: The domain on which the event occured
+ * @event: The specfic virDomainEventType which occured
+ * @opaque: opaque user data
+ *
+ * A callback function to be registered, and called when a domain event occurs
+ */
+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);
+
+/*
+ * Events Implementation
+ */
+
+/**
+ * virEventHandleType:
+ *
+ * a virEventHandleType is used similar to POLLxxx FD events, but is specific
+ * to libvirt. A client app must translate to, and from POLL events when using
+ * this construct.
+ */
+typedef enum {
+ VIR_EVENT_HANDLE_READABLE = (1 << 0),
+ VIR_EVENT_HANDLE_WRITABLE = (1 << 1),
+ VIR_EVENT_HANDLE_ERROR = (1 << 2),
+ VIR_EVENT_HANDLE_HANGUP = (1 << 3),
+} virEventHandleType;
+
+/**
+ * virEventHandleCallback: callback for receiving file handle events
+ *
+ * @fd: file handle on which the event occurred
+ * @events: bitset of events from virEventHandleType constants
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventHandleCallback)(int fd, virEventHandleType events,
+ void *opaque);
+
+/**
+ * virEventAddHandleFunc:
+ * @fd: file descriptor to listen on
+ * @event: events on which to fire the callback
+ * @cb: the callback to be called
+ * @opaque: user data to pass to the callback
+ *
+ * Part of the EventImpl, this callback Adds a file handle callback to
+ * listen for specific events
+ */
+typedef int (*virEventAddHandleFunc)(int fd, virEventHandleType event,
+ virEventHandleCallback cb, void *opaque);
+
+/**
+ * virEventUpdateHandleFunc:
+ * @fd: file descriptor to modify
+ * @event: new events to listen on
+ *
+ * Part of the EventImpl, this user-provided callback is notified when
+ * events to listen on change
+ */
+typedef void (*virEventUpdateHandleFunc)(int fd, virEventHandleType event);
+
+/**
+ * virEventRemoveHandleFunc:
+ * @fd: file descriptor to stop listening on
+ *
+ * Part of the EventImpl, this user-provided callback is notified when
+ * an fd is no longer being listened on
+ */
+typedef int (*virEventRemoveHandleFunc)(int fd);
+
+/**
+ * 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);
+
+/**
+ * virEventAddTimeoutFunc:
+ * @timeout: The timeout to monitor
+ * @cb: the callback to call when timeout has expired
+ * @opaque: user data to pass to the callback
+ *
+ * Part of the EventImpl, this user-defined callback handles adding an
+ * event timeout.
+ *
+ * Returns a timer value
+ */
+typedef int (*virEventAddTimeoutFunc)(int timeout, virEventTimeoutCallback cb,
+ void *opaque);
+
+/**
+ * virEventUpdateTimeoutFunc:
+ * @timer: the timer to modify
+ * @timeout: the new timeout value
+ *
+ * Part of the EventImpl, this user-defined callback updates an
+ * event timeout.
+ */
+typedef void (*virEventUpdateTimeoutFunc)(int timer, int timeout);
+
+/**
+ * virEventRemoveTimeoutFunc:
+ * @timer: the timer to remove
+ *
+ * Part of the EventImpl, this user-defined callback removes a timer
+ *
+ * Returns 0 on success, -1 on failure
+ */
+typedef int (*virEventRemoveTimeoutFunc)(int timer);
+
+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..8ff1fa6 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -16,6 +16,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/poll.h>
#include <unistd.h>
#include <assert.h>
#ifdef HAVE_SYS_WAIT_H
@@ -5345,3 +5346,280 @@ void virStringListFree(virStringList *list)
list = p;
}
}
+
+/*
+ * Domain Event Notification
+ */
+
+/**
+ * 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;
+}
+
+/**
+ * __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);
+}
+/**
+ * __virDomainEventCallbackListRemove:
+ * @conn: pointer to the connection
+ * @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:
+ * @conn: pointer to the connection
+ * @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: pointer to the 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)
+{
+ 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;
+
+ /* 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;
+}
+
+
+int
+__virEventHandleTypeToPollEvent(virEventHandleType events)
+{
+ int ret = 0;
+ if(events & VIR_EVENT_HANDLE_READABLE)
+ ret |= POLLIN;
+ if(events & VIR_EVENT_HANDLE_WRITABLE)
+ ret |= POLLOUT;
+ if(events & VIR_EVENT_HANDLE_ERROR)
+ ret |= POLLERR;
+ if(events & VIR_EVENT_HANDLE_HANGUP)
+ ret |= POLLHUP;
+ return ret;
+}
+
+virEventHandleType
+__virPollEventToEventHandleType(int events)
+{
+ virEventHandleType ret = 0;
+ if(events & POLLIN)
+ ret |= VIR_EVENT_HANDLE_READABLE;
+ if(events & POLLOUT)
+ ret |= VIR_EVENT_HANDLE_WRITABLE;
+ if(events & POLLERR)
+ ret |= VIR_EVENT_HANDLE_ERROR;
+ if(events & POLLHUP)
+ ret |= VIR_EVENT_HANDLE_HANGUP;
+ return ret;
+}
diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version
index 3cc4505..0297c9c 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,7 @@
__virReallocN;
__virFree;
+ __virEventHandleTypeToPollEvent;
+ __virPollEventToEventHandleType;
local: *;
};
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]