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