On Tue, Jul 24, 2012 at 14:17:01 +0100, Daniel P. Berrange wrote: > From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> > > Define new virConnect{Register,Unregister}CloseCallback() public APIs > which allows registering/unregistering 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'. The virConnectCloseReason enum also mentions 'client' reason. > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index fcef461..d9f0397 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in ... > @@ -1148,6 +1166,27 @@ int virConnectSetKeepAlive(virConnectPtr conn, > int interval, > unsigned int count); > > +typedef enum { > + VIR_CONNECT_CLOSE_REASON_ERROR = 0, /* Misc I/O error */ > + VIR_CONNECT_CLOSE_REASON_EOF = 1, /* End-of-file from server */ > + VIR_CONNECT_CLOSE_REASON_KEEPALIVE = 2, /* Keepalive timer triggered */ > + VIR_CONNECT_CLOSE_REASON_CLIENT = 3, /* Client requested it */ > + > +# ifdef VIR_ENUM_SENTINELS > + VIR_CONNECT_CLOSE_REASON_LAST > +# endif > +} virConnectCloseReason; ... > diff --git a/src/libvirt.c b/src/libvirt.c > index 8315b4f..9cfabc5 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -18613,6 +18613,117 @@ error: > > > /** > + * virConnectRegisterCloseCallback: > + * @conn: pointer to connection object > + * @cb: callback to invoke upon close > + * @opaque: user data to pass to @cb > + * @freecb: callback to free @opaque > + * > + * Registers a callback to be invoked when the connection > + * is closed. This callback is invoked when there is any > + * condition that causes the socket connection to the > + * hypervisor to be closed. > + * > + * This function is only applicable to hypervisor drivers > + * which maintain a persistent open connection. Drivers > + * which open a new connection for every operation will > + * not invoke this. > + * > + * The @freecb must not invoke any other libvirt public > + * APIs, since it is not called from a re-entrant safe > + * context. > + * > + * Returns 0 on success, -1 on error > + */ > +int virConnectRegisterCloseCallback(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); > + > + virCheckNonNullArgGoto(cb, error); > + > + if (conn->closeCallback) { > + virLibConnError(VIR_ERR_OPERATION_INVALID, "%s", > + _("A close callback is already registered")); > + goto error; > + } > + > + conn->closeCallback = cb; > + conn->closeOpaque = opaque; > + conn->closeFreeCallback = freecb; > + > + virMutexUnlock(&conn->lock); > + > + return 0; > + > +error: > + virMutexUnlock(&conn->lock); > + virDispatchError(NULL); > + return -1; > +} > + > +/** > + * virConnectUnregisterCloseCallback: > + * @conn: pointer to connection object > + * @cb: pointer to the current registered callback > + * > + * Unregisters the callback previously set with the > + * virConnectRegisterCloseCallback method. The callback > + * will no longer received notifications when the connection s/received/receive/ > + * closes. Is it worth noting that freecb() is called on opaque or is it obvious enough? > + * > + * Returns 0 on success, -1 on error > + */ > +int virConnectUnregisterCloseCallback(virConnectPtr conn, > + virConnectCloseFunc cb) > +{ > + VIR_DEBUG("conn=%p", conn); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT(conn)) { > + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); > + virDispatchError(NULL); > + return -1; > + } > + > + virMutexLock(&conn->lock); > + > + virCheckNonNullArgGoto(cb, error); > + > + if (conn->closeCallback != cb) { > + virLibConnError(VIR_ERR_OPERATION_INVALID, "%s", > + _("A different callback was requested")); > + goto error; > + } > + > + conn->closeCallback = NULL; > + if (conn->closeFreeCallback) > + conn->closeFreeCallback(conn->closeOpaque); I'd also reset closeFreeCallback and closeOpaque to NULL to avoid accessing them by mistake in the future. > + > + virMutexUnlock(&conn->lock); > + > + return 0; > + > +error: > + virMutexUnlock(&conn->lock); > + virDispatchError(NULL); > + return -1; > +} > + > +/** > * virDomainSetBlockIoTune: > * @dom: pointer to domain object > * @disk: path to the block device, or device shorthand ... ACK with nits fixed or ignored as not being worth it. Jirka -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list