Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
---
src/datatypes.c | 31 +++++++--------------
src/datatypes.h | 4 +--
src/driver-hypervisor.h | 12 +++++++++
src/libvirt-host.c | 17 +++---------
src/remote/remote_driver.c | 67 +++++++++++++++++++++++++++++++++++++++++++---
5 files changed, 90 insertions(+), 41 deletions(-)
diff --git a/src/datatypes.c b/src/datatypes.c
index 3ea7dff..b353499 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -114,22 +114,10 @@ VIR_ONCE_GLOBAL_INIT(virDataTypes)
virConnectPtr
virGetConnect(void)
{
- virConnectPtr ret;
-
if (virDataTypesInitialize() < 0)
return NULL;
- if (!(ret = virObjectLockableNew(virConnectClass)))
- return NULL;
-
- if (!(ret->closeCallback =
virObjectLockableNew(virConnectCloseCallbackDataClass)))
- goto error;
-
- return ret;
-
- error:
- virObjectUnref(ret);
- return NULL;
+ return virObjectLockableNew(virConnectClass);
}
/**
@@ -150,14 +138,6 @@ virConnectDispose(void *obj)
virResetError(&conn->err);
virURIFree(conn->uri);
-
- if (conn->closeCallback) {
- virObjectLock(conn->closeCallback);
- conn->closeCallback->callback = NULL;
- virObjectUnlock(conn->closeCallback);
-
- virObjectUnref(conn->closeCallback);
- }
}
@@ -185,6 +165,15 @@ virConnectCloseCallbackDataDispose(void *obj)
virConnectCloseCallbackDataReset(obj);
}
+virConnectCloseCallbackDataPtr
+virNewConnectCloseCallbackData(void)
+{
+ if (virDataTypesInitialize() < 0)
+ return NULL;
+
+ return virObjectLockableNew(virConnectCloseCallbackDataClass);
+}
+
void virConnectCloseCallbackDataRegister(virConnectCloseCallbackDataPtr close,
virConnectPtr conn,
virConnectCloseFunc cb,
diff --git a/src/datatypes.h b/src/datatypes.h
index 2ee77cd..a1aecb4 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -396,9 +396,6 @@ struct _virConnect {
virError err; /* the last error */
virErrorFunc handler; /* associated handler */
void *userData; /* the user data */
-
- /* Per-connection close callback */
- virConnectCloseCallbackDataPtr closeCallback;
};
/**
@@ -601,6 +598,7 @@ virDomainSnapshotPtr virGetDomainSnapshot(virDomainPtr domain,
virAdmConnectPtr virAdmConnectNew(void);
+virConnectCloseCallbackDataPtr virNewConnectCloseCallbackData(void);
void virConnectCloseCallbackDataRegister(virConnectCloseCallbackDataPtr close,
virConnectPtr conn,
virConnectCloseFunc cb,
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index ae2ec4d..2cbd01b 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1212,6 +1212,16 @@ typedef int
const char *password,
unsigned int flags);
+typedef int
+(*virDrvConnectRegisterCloseCallback)(virConnectPtr conn,
+ virConnectCloseFunc cb,
+ void *opaque,
+ virFreeCallback freecb);
+
+typedef int
+(*virDrvConnectUnregisterCloseCallback)(virConnectPtr conn,
+ virConnectCloseFunc cb);
+
typedef struct _virHypervisorDriver virHypervisorDriver;
typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1443,6 +1453,8 @@ struct _virHypervisorDriver {
virDrvDomainGetFSInfo domainGetFSInfo;
virDrvDomainInterfaceAddresses domainInterfaceAddresses;
virDrvDomainSetUserPassword domainSetUserPassword;
+ virDrvConnectRegisterCloseCallback connectRegisterCloseCallback;
+ virDrvConnectUnregisterCloseCallback connectUnregisterCloseCallback;
};
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index b0597ee..24277b7 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1217,14 +1217,9 @@ virConnectRegisterCloseCallback(virConnectPtr conn,
virCheckConnectReturn(conn, -1);
virCheckNonNullArgGoto(cb, error);
- if (virConnectCloseCallbackDataGetCallback(conn->closeCallback) != NULL) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("A close callback is already registered"));
+ if (conn->driver->connectRegisterCloseCallback &&
+ conn->driver->connectRegisterCloseCallback(conn, cb, opaque, freecb) <
0)
goto error;
- }
-
- virConnectCloseCallbackDataRegister(conn->closeCallback, conn, cb,
- opaque, freecb);
return 0;
@@ -1257,13 +1252,9 @@ virConnectUnregisterCloseCallback(virConnectPtr conn,
virCheckConnectReturn(conn, -1);
virCheckNonNullArgGoto(cb, error);
- if (virConnectCloseCallbackDataGetCallback(conn->closeCallback) != cb) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("A different callback was requested"));
+ if (conn->driver->connectUnregisterCloseCallback &&
+ conn->driver->connectUnregisterCloseCallback(conn, cb) < 0)
goto error;
- }
-
- virConnectCloseCallbackDataUnregister(conn->closeCallback, cb);
return 0;
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index d9c54ab..9be78e2 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -96,6 +96,7 @@ struct private_data {
bool serverEventFilter; /* Does server support modern event filtering */
virObjectEventStatePtr eventState;
+ virConnectCloseCallbackDataPtr closeCallback;
};
enum {
@@ -963,11 +964,13 @@ doRemoteOpen(virConnectPtr conn,
goto failed;
}
- virObjectRef(conn->closeCallback);
-
+ if (!(priv->closeCallback = virNewConnectCloseCallbackData()))
+ goto failed;
+ // ref on behalf of netclient
+ virObjectRef(priv->closeCallback);
virNetClientSetCloseCallback(priv->client,
remoteClientCloseFunc,
- conn->closeCallback, virObjectFreeCallback);
+ priv->closeCallback, virObjectFreeCallback);
if (!(priv->remoteProgram = virNetClientProgramNew(REMOTE_PROGRAM,
REMOTE_PROTOCOL_VERSION,
@@ -1097,6 +1100,8 @@ doRemoteOpen(virConnectPtr conn,
virNetClientClose(priv->client);
virObjectUnref(priv->client);
priv->client = NULL;
+ virObjectUnref(priv->closeCallback);
+ priv->closeCallback = NULL;
#ifdef WITH_GNUTLS
virObjectUnref(priv->tls);
priv->tls = NULL;
@@ -1229,11 +1234,13 @@ doRemoteClose(virConnectPtr conn, struct private_data *priv)
virNetClientSetCloseCallback(priv->client,
NULL,
- conn->closeCallback, virObjectFreeCallback);
+ priv->closeCallback, virObjectFreeCallback);
virNetClientClose(priv->client);
virObjectUnref(priv->client);
priv->client = NULL;
+ virObjectUnref(priv->closeCallback);
+ priv->closeCallback = NULL;
virObjectUnref(priv->remoteProgram);
virObjectUnref(priv->lxcProgram);
virObjectUnref(priv->qemuProgram);
@@ -7881,6 +7888,56 @@ remoteDomainInterfaceAddresses(virDomainPtr dom,
return rv;
}
+static int
+remoteConnectRegisterCloseCallback(virConnectPtr conn,
+ virConnectCloseFunc cb,
+ void *opaque,
+ virFreeCallback freecb)
+{
+ struct private_data *priv = conn->privateData;
+ int ret = -1;
+
+ remoteDriverLock(priv);
+
+ if (virConnectCloseCallbackDataGetCallback(priv->closeCallback) != NULL) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("A close callback is already registered"));
+ goto cleanup;
+ }
+
+ virConnectCloseCallbackDataRegister(priv->closeCallback, conn, cb,
+ opaque, freecb);
+ ret = 0;
+
+ cleanup:
+ remoteDriverUnlock(priv);
+
+ return ret;
+}
+
+static int
+remoteConnectUnregisterCloseCallback(virConnectPtr conn,
+ virConnectCloseFunc cb)
+{
+ struct private_data *priv = conn->privateData;
+ int ret = -1;
+
+ remoteDriverLock(priv);
+
+ if (virConnectCloseCallbackDataGetCallback(priv->closeCallback) != cb) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("A different callback was requested"));
+ goto cleanup;
+ }
+
+ virConnectCloseCallbackDataUnregister(priv->closeCallback, cb);
+ ret = 0;
+
+ cleanup:
+ remoteDriverUnlock(priv);
+
+ return ret;
+}
static int
remoteDomainRename(virDomainPtr dom, const char *new_name, unsigned int flags)
@@ -8273,6 +8330,8 @@ static virHypervisorDriver hypervisor_driver = {
.domainInterfaceAddresses = remoteDomainInterfaceAddresses, /* 1.2.14 */
.domainSetUserPassword = remoteDomainSetUserPassword, /* 1.2.16 */
.domainRename = remoteDomainRename, /* 1.2.19 */
+ .connectRegisterCloseCallback = remoteConnectRegisterCloseCallback, /* 1.3.2 */
+ .connectUnregisterCloseCallback = remoteConnectUnregisterCloseCallback, /* 1.3.2 */
};
static virNetworkDriver network_driver = {
--
1.8.3.1