[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] Re: [PATCH 01/12] Domain Events - Public API



[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]