提交 6ed5a1b9 编写于 作者: D Daniel P. Berrange

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: NDaniel P. Berrange <berrange@redhat.com>
上级 16793534
......@@ -61,6 +61,24 @@ 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 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:
*
......@@ -1160,6 +1178,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;
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.
......@@ -2875,16 +2914,6 @@ typedef int (*virConnectDomainEventCallback)(virConnectPtr conn,
int detail,
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,
virConnectDomainEventCallback cb,
void *opaque,
......
......@@ -115,6 +115,9 @@ virReleaseConnect(virConnectPtr conn) {
virMutexLock(&conn->lock);
if (conn->closeFreeCallback)
conn->closeFreeCallback(conn->closeOpaque);
virResetError(&conn->err);
virURIFree(conn->uri);
......
......@@ -187,6 +187,11 @@ struct _virConnect {
virErrorFunc handler; /* associated handlet */
void *userData; /* the user data */
/* Per-connection close callback */
virConnectCloseFunc closeCallback;
void *closeOpaque;
virFreeCallback closeFreeCallback;
int refs; /* reference count */
};
......
......@@ -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:
* @dom: pointer to domain object
......
......@@ -547,6 +547,8 @@ LIBVIRT_0.9.13 {
LIBVIRT_0.9.14 {
global:
virDomainGetHostname;
virConnectRegisterCloseCallback;
virConnectUnregisterCloseCallback;
} LIBVIRT_0.9.13;
# .... define new API here using predicted next version number ....
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册