
On 07/20/2012 08:21 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Define a new virConnectSetCloseCallback() public API which allows registering a callback to be invoked when the connection to a hypervisor is closed. The callback is provided with the reason for the close, which may be 'error', 'eof' or 'keepalive'.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- include/libvirt/libvirt.h.in | 40 +++++++++++++++++++++------- src/datatypes.c | 4 +++ src/datatypes.h | 5 ++++ src/libvirt.c | 60 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 6 +++++ 5 files changed, 105 insertions(+), 10 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index e34438c..85d8c8a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -49,6 +49,17 @@ extern "C" { * defines VIR_ENUM_SENTINELS. Enumerations for bit values do not * have a *_LAST value, but additional bits may be defined. */
+/* + * virFreeCallback: + * @opaque: opaque user data provided at registration + * + * Type for a domain event callback when the event is deregistered and + * need to be freed, @opaque is provided along with the callback at + * registration time + */ +typedef void (*virFreeCallback)(void *opaque);
We're now using this for more than just domain events; the comment needs a slight update. Maybe: Type for a callback cleanup function to be paired with a callback. This function will be called as a final chance to clean up the @opaque registered with the primary callback, at the time when the primary callback is deregistered.
+++ b/src/datatypes.c @@ -115,6 +115,10 @@ virReleaseConnect(virConnectPtr conn) {
virMutexLock(&conn->lock);
+ if (conn->closeOpaque && + conn->closeFreeCallback) + conn->closeFreeCallback(conn->closeOpaque);
I'm still not sure I like filtering on NULL opaque. Our other uses of a virFreeCallback include src/fdstream.c:virFDStreamRemoveCallback, and there we call fdst->ff without regards to whether fdst->opaque is null.
+int virConnectSetCloseCallback(virConnectPtr conn, + virConnectCloseFunc cb, + void *opaque, + virFreeCallback freecb) +{ + VIR_DEBUG("conn=%p", conn); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + virMutexLock(&conn->lock); + + if (conn->closeCallback) { + virLibConnError(VIR_ERR_OPERATION_INVALID, "%s", + _("A close callback is already registered")); + goto error; + }
Do we want to allow deregistration of a close callback (we have virConnectDomainEventDeregister, after all). -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org