[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: *; };
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list