mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
Add public API to register a callback to be invoked on connection close
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', 'client' or 'keepalive'. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
1679353496
commit
6ed5a1b9bd
@ -61,6 +61,24 @@ extern "C" {
|
|||||||
* defines VIR_ENUM_SENTINELS. Enumerations for bit values do not
|
* defines VIR_ENUM_SENTINELS. Enumerations for bit values do not
|
||||||
* have a *_LAST value, but additional bits may be defined. */
|
* have a *_LAST value, but additional bits may be defined. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* virFreeCallback:
|
||||||
|
* @opaque: opaque user data provided at registration
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* It is forbidden to call any other libvirt APIs from an
|
||||||
|
* implementation of this callback, since it can be invoked
|
||||||
|
* from a context which is not re-entrant safe. Failure to
|
||||||
|
* abide by this requirement may lead to application deadlocks
|
||||||
|
* or crashes.
|
||||||
|
*/
|
||||||
|
typedef void (*virFreeCallback)(void *opaque);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virConnect:
|
* virConnect:
|
||||||
*
|
*
|
||||||
@ -1160,6 +1178,27 @@ int virConnectSetKeepAlive(virConnectPtr conn,
|
|||||||
int interval,
|
int interval,
|
||||||
unsigned int count);
|
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;
|
||||||
|
|
||||||
|
typedef void (*virConnectCloseFunc)(virConnectPtr conn,
|
||||||
|
int reason,
|
||||||
|
void *opaque);
|
||||||
|
|
||||||
|
int virConnectRegisterCloseCallback(virConnectPtr conn,
|
||||||
|
virConnectCloseFunc cb,
|
||||||
|
void *opaque,
|
||||||
|
virFreeCallback freecb);
|
||||||
|
int virConnectUnregisterCloseCallback(virConnectPtr conn,
|
||||||
|
virConnectCloseFunc cb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Capabilities of the connection / driver.
|
* Capabilities of the connection / driver.
|
||||||
@ -2875,16 +2914,6 @@ typedef int (*virConnectDomainEventCallback)(virConnectPtr conn,
|
|||||||
int detail,
|
int detail,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
int virConnectDomainEventRegister(virConnectPtr conn,
|
int virConnectDomainEventRegister(virConnectPtr conn,
|
||||||
virConnectDomainEventCallback cb,
|
virConnectDomainEventCallback cb,
|
||||||
void *opaque,
|
void *opaque,
|
||||||
|
@ -115,6 +115,9 @@ virReleaseConnect(virConnectPtr conn) {
|
|||||||
|
|
||||||
virMutexLock(&conn->lock);
|
virMutexLock(&conn->lock);
|
||||||
|
|
||||||
|
if (conn->closeFreeCallback)
|
||||||
|
conn->closeFreeCallback(conn->closeOpaque);
|
||||||
|
|
||||||
virResetError(&conn->err);
|
virResetError(&conn->err);
|
||||||
|
|
||||||
virURIFree(conn->uri);
|
virURIFree(conn->uri);
|
||||||
|
@ -187,6 +187,11 @@ struct _virConnect {
|
|||||||
virErrorFunc handler; /* associated handlet */
|
virErrorFunc handler; /* associated handlet */
|
||||||
void *userData; /* the user data */
|
void *userData; /* the user data */
|
||||||
|
|
||||||
|
/* Per-connection close callback */
|
||||||
|
virConnectCloseFunc closeCallback;
|
||||||
|
void *closeOpaque;
|
||||||
|
virFreeCallback closeFreeCallback;
|
||||||
|
|
||||||
int refs; /* reference count */
|
int refs; /* reference count */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
114
src/libvirt.c
114
src/libvirt.c
@ -18624,6 +18624,120 @@ 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 receive notifications when the connection
|
||||||
|
* closes. If a virFreeCallback was provided at time of
|
||||||
|
* registration, it will be invoked
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
conn->closeFreeCallback = NULL;
|
||||||
|
conn->closeOpaque = NULL;
|
||||||
|
|
||||||
|
virMutexUnlock(&conn->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virMutexUnlock(&conn->lock);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainSetBlockIoTune:
|
* virDomainSetBlockIoTune:
|
||||||
* @dom: pointer to domain object
|
* @dom: pointer to domain object
|
||||||
|
@ -547,6 +547,8 @@ LIBVIRT_0.9.13 {
|
|||||||
LIBVIRT_0.9.14 {
|
LIBVIRT_0.9.14 {
|
||||||
global:
|
global:
|
||||||
virDomainGetHostname;
|
virDomainGetHostname;
|
||||||
|
virConnectRegisterCloseCallback;
|
||||||
|
virConnectUnregisterCloseCallback;
|
||||||
} LIBVIRT_0.9.13;
|
} LIBVIRT_0.9.13;
|
||||||
|
|
||||||
# .... define new API here using predicted next version number ....
|
# .... define new API here using predicted next version number ....
|
||||||
|
Loading…
Reference in New Issue
Block a user