[libvirt] [PATCH 05/13] Convert public datatypes to inherit from virObject

Daniel P. Berrange berrange at redhat.com
Wed Jul 11 13:35:45 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

This converts the following public API datatypes to use the
virObject infrastructure:

  virConnectPtr
  virDomainPtr
  virDomainSnapshotPtr
  virInterfacePtr
  virNetworkPtr
  virNodeDevicePtr
  virNWFilterPtr
  virSecretPtr
  virStreamPtr
  virStorageVolPtr
  virStoragePoolPtr

The code is significantly simplified, since the mutex in the
virConnectPtr object now only needs to be held when accessing
the per-connection virError object instance. All other operations
are completely lock free.

* src/datatypes.c, src/datatypes.h, src/libvirt.c: Convert
  public datatypes to use virObject
* src/conf/domain_event.c, src/phyp/phyp_driver.c,
  src/qemu/qemu_command.c, src/qemu/qemu_migration.c,
  src/qemu/qemu_process.c, src/storage/storage_driver.c,
  src/vbox/vbox_tmpl.c, src/xen/xend_internal.c,
  tests/qemuxml2argvtest.c, tests/qemuxmlnstest.c,
  tests/sexpr2xmltest.c, tests/xmconfigtest.c: Convert
  to use virObjectUnref/virObjectRef

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/conf/domain_event.c      |    8 +-
 src/datatypes.c              |  999 ++++++++++--------------------------------
 src/datatypes.h              |  264 ++++-------
 src/libvirt.c                |  127 ++----
 src/libvirt_private.syms     |   17 +-
 src/phyp/phyp_driver.c       |   14 +-
 src/qemu/qemu_command.c      |    2 +-
 src/qemu/qemu_migration.c    |    8 +-
 src/qemu/qemu_process.c      |    2 +-
 src/storage/storage_driver.c |    4 +-
 src/vbox/vbox_tmpl.c         |    2 +-
 src/xen/xend_internal.c      |    4 +-
 tests/qemuxml2argvtest.c     |   21 +-
 tests/qemuxmlnstest.c        |    2 +-
 tests/sexpr2xmltest.c        |    2 +-
 tests/xmconfigtest.c         |    4 +-
 16 files changed, 410 insertions(+), 1070 deletions(-)

diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index 3cfd940..be7ccbd 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -169,7 +169,7 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
             virFreeCallback freecb = cbList->callbacks[i]->freecb;
             if (freecb)
                 (*freecb)(cbList->callbacks[i]->opaque);
-            virUnrefConnect(cbList->callbacks[i]->conn);
+            virObjectUnref(cbList->callbacks[i]->conn);
             VIR_FREE(cbList->callbacks[i]);
 
             if (i < (cbList->count - 1))
@@ -219,7 +219,7 @@ virDomainEventCallbackListRemoveID(virConnectPtr conn,
             virFreeCallback freecb = cbList->callbacks[i]->freecb;
             if (freecb)
                 (*freecb)(cbList->callbacks[i]->opaque);
-            virUnrefConnect(cbList->callbacks[i]->conn);
+            virObjectUnref(cbList->callbacks[i]->conn);
             VIR_FREE(cbList->callbacks[i]);
 
             if (i < (cbList->count - 1))
@@ -309,7 +309,7 @@ virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
             virFreeCallback freecb = cbList->callbacks[i]->freecb;
             if (freecb)
                 (*freecb)(cbList->callbacks[i]->opaque);
-            virUnrefConnect(cbList->callbacks[i]->conn);
+            virObjectUnref(cbList->callbacks[i]->conn);
             VIR_FREE(cbList->callbacks[i]);
 
             if (i < (cbList->count - 1))
@@ -395,7 +395,7 @@ virDomainEventCallbackListAddID(virConnectPtr conn,
     if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0)
         goto no_memory;
 
-    event->conn->refs++;
+    virObjectRef(event->conn);
 
     cbList->callbacks[cbList->count] = event;
     cbList->count++;
diff --git a/src/datatypes.c b/src/datatypes.c
index d718170..8cac540 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -35,12 +35,55 @@
     virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \
                          __FUNCTION__, __LINE__, __VA_ARGS__)
 
-/************************************************************************
- *									*
- *			Domain and Connections allocations		*
- *									*
- ************************************************************************/
 
+virClassPtr virConnectClass;
+virClassPtr virDomainClass;
+virClassPtr virDomainSnapshotClass;
+virClassPtr virInterfaceClass;
+virClassPtr virNetworkClass;
+virClassPtr virNodeDeviceClass;
+virClassPtr virNWFilterClass;
+virClassPtr virSecretClass;
+virClassPtr virStreamClass;
+virClassPtr virStorageVolClass;
+virClassPtr virStoragePoolClass;
+
+static void virConnectDispose(void *obj);
+static void virDomainDispose(void *obj);
+static void virDomainSnapshotDispose(void *obj);
+static void virInterfaceDispose(void *obj);
+static void virNetworkDispose(void *obj);
+static void virNodeDeviceDispose(void *obj);
+static void virNWFilterDispose(void *obj);
+static void virSecretDispose(void *obj);
+static void virStreamDispose(void *obj);
+static void virStorageVolDispose(void *obj);
+static void virStoragePoolDispose(void *obj);
+
+static int virDataTypesOnceInit(void)
+{
+#define DECLARE_CLASS(basename)                                  \
+    if (!(basename ## Class = virClassNew(#basename,             \
+                                          sizeof(basename),      \
+                                          basename ## Dispose))) \
+        return -1;
+
+    DECLARE_CLASS(virConnect);
+    DECLARE_CLASS(virDomain);
+    DECLARE_CLASS(virDomainSnapshot);
+    DECLARE_CLASS(virInterface);
+    DECLARE_CLASS(virNetwork);
+    DECLARE_CLASS(virNodeDevice);
+    DECLARE_CLASS(virNWFilter);
+    DECLARE_CLASS(virSecret);
+    DECLARE_CLASS(virStream);
+    DECLARE_CLASS(virStorageVol);
+    DECLARE_CLASS(virStoragePool);
+
+    return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virDataTypes)
 
 /**
  * virGetConnect:
@@ -53,35 +96,28 @@ virConnectPtr
 virGetConnect(void) {
     virConnectPtr ret;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virReportOOMError();
-        goto failed;
-    }
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
+    if (!(ret = virObjectNew(virConnectClass)))
+        return NULL;
+
     if (virMutexInit(&ret->lock) < 0) {
         VIR_FREE(ret);
-        goto failed;
+        return NULL;
     }
 
-    ret->magic = VIR_CONNECT_MAGIC;
     ret->driver = NULL;
     ret->networkDriver = NULL;
     ret->privateData = NULL;
     ret->networkPrivateData = NULL;
     ret->interfacePrivateData = NULL;
 
-    ret->refs = 1;
     return ret;
-
-failed:
-    if (ret != NULL) {
-        virMutexDestroy(&ret->lock);
-        VIR_FREE(ret);
-    }
-    return NULL;
 }
 
 /**
- * virReleaseConnect:
+ * virConnectDispose:
  * @conn: the hypervisor connection to release
  *
  * Unconditionally release all memory associated with a connection.
@@ -89,14 +125,8 @@ failed:
  * be released prior to this returning. The connection obj must not
  * be used once this method returns.
  */
-static void
-virReleaseConnect(virConnectPtr conn) {
-    VIR_DEBUG("release connection %p", conn);
-
-    /* make sure to release the connection lock before we call the
-     * close callbacks, otherwise we will deadlock if an error
-     * is raised by any of the callbacks */
-    virMutexUnlock(&conn->lock);
+static void virConnectDispose(void *obj) {
+    virConnectPtr conn = obj;
 
     if (conn->networkDriver)
         conn->networkDriver->close(conn);
@@ -121,38 +151,8 @@ virReleaseConnect(virConnectPtr conn) {
 
     virMutexUnlock(&conn->lock);
     virMutexDestroy(&conn->lock);
-    VIR_FREE(conn);
 }
 
-/**
- * virUnrefConnect:
- * @conn: the hypervisor connection to unreference
- *
- * Unreference the connection. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefConnect(virConnectPtr conn) {
-    int refs;
-
-    if ((!VIR_IS_CONNECT(conn))) {
-        virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
-        return -1;
-    }
-    virMutexLock(&conn->lock);
-    VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-    conn->refs--;
-    refs = conn->refs;
-    if (refs == 0) {
-        virReleaseConnect(conn);
-        /* Already unlocked mutex */
-        return 0;
-    }
-    virMutexUnlock(&conn->lock);
-    return refs;
-}
 
 /**
  * virGetDomain:
@@ -163,14 +163,16 @@ virUnrefConnect(virConnectPtr conn) {
  * Lookup if the domain is already registered for that connection,
  * if yes return a new pointer to it, if no allocate a new structure,
  * and register it in the table. In any case a corresponding call to
- * virUnrefDomain() is needed to not leak data.
+ * virObjectUnref() is needed to not leak data.
  *
  * Returns a pointer to the domain, or NULL in case of failure
  */
 virDomainPtr
 virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     virDomainPtr ret = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
@@ -179,41 +181,26 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     virCheckNonNullArgReturn(name, NULL);
     virCheckNonNullArgReturn(uuid, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virDomainClass)))
+        return NULL;
 
-    virUUIDFormat(uuid, uuidstr);
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_DOMAIN_MAGIC;
-    ret->conn = conn;
+    ret->conn = virObjectRef(conn);
     ret->id = -1;
     memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
     return ret;
 
- error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 /**
- * virReleaseDomain:
+ * virDomainDispose:
  * @domain: the domain to release
  *
  * Unconditionally release all memory associated with a domain.
@@ -225,62 +212,20 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseDomain(virDomainPtr domain) {
-    virConnectPtr conn = domain->conn;
+virDomainDispose(void *obj) {
+    virDomainPtr domain = obj;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     virUUIDFormat(domain->uuid, uuidstr);
     VIR_DEBUG("release domain %p %s %s", domain, domain->name, uuidstr);
 
-    domain->magic = -1;
-    domain->id = -1;
     VIR_FREE(domain->name);
-    VIR_FREE(domain);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
-
-/**
- * virUnrefDomain:
- * @domain: the domain to unreference
- *
- * Unreference the domain. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefDomain(virDomainPtr domain) {
-    int refs;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibConnError(VIR_ERR_INVALID_DOMAIN, _("bad domain or no connection"));
-        return -1;
-    }
-    virMutexLock(&domain->conn->lock);
-    VIR_DEBUG("unref domain %p %s %d", domain, domain->name, domain->refs);
-    domain->refs--;
-    refs = domain->refs;
-    if (refs == 0) {
-        virReleaseDomain(domain);
-        /* Already unlocked mutex */
-        return 0;
-    }
 
-    virMutexUnlock(&domain->conn->lock);
-    return refs;
+    if (domain->conn)
+        virObjectUnref(domain->conn);
 }
 
+
 /**
  * virGetNetwork:
  * @conn: the hypervisor connection
@@ -290,14 +235,16 @@ virUnrefDomain(virDomainPtr domain) {
  * Lookup if the network is already registered for that connection,
  * if yes return a new pointer to it, if no allocate a new structure,
  * and register it in the table. In any case a corresponding call to
- * virUnrefNetwork() is needed to not leak data.
+ * virObjectUnref() is needed to not leak data.
  *
  * Returns a pointer to the network, or NULL in case of failure
  */
 virNetworkPtr
 virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     virNetworkPtr ret = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
@@ -306,40 +253,25 @@ virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     virCheckNonNullArgReturn(name, NULL);
     virCheckNonNullArgReturn(uuid, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virNetworkClass)))
+        return NULL;
 
-    virUUIDFormat(uuid, uuidstr);
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_NETWORK_MAGIC;
-    ret->conn = conn;
+    ret->conn = virObjectRef(conn);
     memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
     return ret;
 
- error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 /**
- * virReleaseNetwork:
+ * virNetworkDispose:
  * @network: the network to release
  *
  * Unconditionally release all memory associated with a network.
@@ -351,63 +283,21 @@ virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseNetwork(virNetworkPtr network) {
-    virConnectPtr conn = network->conn;
+virNetworkDispose(void *obj) {
+    virNetworkPtr network = obj;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     virUUIDFormat(network->uuid, uuidstr);
     VIR_DEBUG("release network %p %s %s", network, network->name, uuidstr);
 
-    network->magic = -1;
     VIR_FREE(network->name);
-    VIR_FREE(network);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
-
-/**
- * virUnrefNetwork:
- * @network: the network to unreference
- *
- * Unreference the network. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefNetwork(virNetworkPtr network) {
-    int refs;
 
-    if (!VIR_IS_CONNECTED_NETWORK(network)) {
-        virLibConnError(VIR_ERR_INVALID_NETWORK,
-                        _("bad network or no connection"));
-        return -1;
-    }
-    virMutexLock(&network->conn->lock);
-    VIR_DEBUG("unref network %p %s %d", network, network->name, network->refs);
-    network->refs--;
-    refs = network->refs;
-    if (refs == 0) {
-        virReleaseNetwork(network);
-        /* Already unlocked mutex */
-        return 0;
-    }
-
-    virMutexUnlock(&network->conn->lock);
-    return refs;
+    if (network->conn)
+        virObjectUnref(network->conn);
 }
 
 
+
 /**
  * virGetInterface:
  * @conn: the hypervisor connection
@@ -417,7 +307,7 @@ virUnrefNetwork(virNetworkPtr network) {
  * Lookup if the interface is already registered for that connection,
  * if yes return a new pointer to it (possibly updating the MAC
  * address), if no allocate a new structure, and register it in the
- * table. In any case a corresponding call to virUnrefInterface() is
+ * table. In any case a corresponding call to virObjectUnref() is
  * needed to not leak data.
  *
  * Returns a pointer to the interface, or NULL in case of failure
@@ -426,6 +316,9 @@ virInterfacePtr
 virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
     virInterfacePtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
         return NULL;
@@ -436,45 +329,26 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
     if (mac == NULL)
        mac = "";
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virInterfaceClass)))
+        return NULL;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->mac = strdup(mac);
-    if (ret->mac == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
+    if (!(ret->mac = strdup(mac)))
+        goto no_memory;
 
-    ret->magic = VIR_INTERFACE_MAGIC;
-    ret->conn = conn;
+    ret->conn = virObjectRef(conn);
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
     return ret;
 
- error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret->mac);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 /**
- * virReleaseInterface:
+ * virInterfaceDispose:
  * @interface: the interface to release
  *
  * Unconditionally release all memory associated with an interface.
@@ -486,58 +360,15 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseInterface(virInterfacePtr iface) {
-    virConnectPtr conn = iface->conn;
+virInterfaceDispose(void *obj) {
+    virInterfacePtr iface = obj;
     VIR_DEBUG("release interface %p %s", iface, iface->name);
 
-    iface->magic = -1;
     VIR_FREE(iface->name);
     VIR_FREE(iface->mac);
-    VIR_FREE(iface);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
-
-/**
- * virUnrefInterface:
- * @interface: the interface to unreference
- *
- * Unreference the interface. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefInterface(virInterfacePtr iface) {
-    int refs;
 
-    if (!VIR_IS_CONNECTED_INTERFACE(iface)) {
-        virLibConnError(VIR_ERR_INVALID_INTERFACE,
-                        _("bad interface or no connection"));
-        return -1;
-    }
-    virMutexLock(&iface->conn->lock);
-    VIR_DEBUG("unref interface %p %s %d", iface, iface->name, iface->refs);
-    iface->refs--;
-    refs = iface->refs;
-    if (refs == 0) {
-        virReleaseInterface(iface);
-        /* Already unlocked mutex */
-        return 0;
-    }
-
-    virMutexUnlock(&iface->conn->lock);
-    return refs;
+    if (iface->conn)
+        virObjectUnref(iface->conn);
 }
 
 
@@ -550,7 +381,7 @@ virUnrefInterface(virInterfacePtr iface) {
  * Lookup if the storage pool is already registered for that connection,
  * if yes return a new pointer to it, if no allocate a new structure,
  * and register it in the table. In any case a corresponding call to
- * virUnrefStoragePool() is needed to not leak data.
+ * virObjectUnref() is needed to not leak data.
  *
  * Returns a pointer to the network, or NULL in case of failure
  */
@@ -558,7 +389,9 @@ virStoragePoolPtr
 virGetStoragePool(virConnectPtr conn, const char *name,
                   const unsigned char *uuid) {
     virStoragePoolPtr ret = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
@@ -567,41 +400,26 @@ virGetStoragePool(virConnectPtr conn, const char *name,
     virCheckNonNullArgReturn(name, NULL);
     virCheckNonNullArgReturn(uuid, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virStoragePoolClass)))
+        return NULL;
 
-    virUUIDFormat(uuid, uuidstr);
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_STORAGE_POOL_MAGIC;
-    ret->conn = conn;
+    ret->conn = virObjectRef(conn);
     memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
     return ret;
 
-error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 /**
- * virReleaseStoragePool:
+ * virStoragePoolDispose:
  * @pool: the pool to release
  *
  * Unconditionally release all memory associated with a pool.
@@ -613,60 +431,17 @@ error:
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseStoragePool(virStoragePoolPtr pool) {
-    virConnectPtr conn = pool->conn;
+virStoragePoolDispose(void *obj) {
+    virStoragePoolPtr pool = obj;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     virUUIDFormat(pool->uuid, uuidstr);
     VIR_DEBUG("release pool %p %s %s", pool, pool->name, uuidstr);
 
-    pool->magic = -1;
     VIR_FREE(pool->name);
-    VIR_FREE(pool);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
 
-/**
- * virUnrefStoragePool:
- * @pool: the pool to unreference
- *
- * Unreference the pool. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefStoragePool(virStoragePoolPtr pool) {
-    int refs;
-
-    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
-        virLibConnError(VIR_ERR_INVALID_STORAGE_POOL,
-                        _("bad storage pool or no connection"));
-        return -1;
-    }
-    virMutexLock(&pool->conn->lock);
-    VIR_DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs);
-    pool->refs--;
-    refs = pool->refs;
-    if (refs == 0) {
-        virReleaseStoragePool(pool);
-        /* Already unlocked mutex */
-        return 0;
-    }
-
-    virMutexUnlock(&pool->conn->lock);
-    return refs;
+    if (pool->conn)
+        virObjectUnref(pool->conn);
 }
 
 
@@ -680,7 +455,7 @@ virUnrefStoragePool(virStoragePoolPtr pool) {
  * Lookup if the storage vol is already registered for that connection,
  * if yes return a new pointer to it, if no allocate a new structure,
  * and register it in the table. In any case a corresponding call to
- * virUnrefStorageVol() is needed to not leak data.
+ * virObjectUnref() is needed to not leak data.
  *
  * Returns a pointer to the storage vol, or NULL in case of failure
  */
@@ -689,6 +464,9 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name,
                  const char *key) {
     virStorageVolPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
         return NULL;
@@ -696,52 +474,29 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name,
     virCheckNonNullArgReturn(name, NULL);
     virCheckNonNullArgReturn(key, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virStorageVolClass)))
+        return NULL;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->pool = strdup(pool);
-    if (ret->pool == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->key = strdup(key);
-    if (ret->key == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_STORAGE_VOL_MAGIC;
-    ret->conn = conn;
+    if (!(ret->pool = strdup(pool)))
+        goto no_memory;
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
+    if (!(ret->key = strdup(key)))
+        goto no_memory;
+
+    ret->conn = virObjectRef(conn);
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
     return ret;
 
-error:
-    if (ret != NULL) {
-        VIR_FREE(ret->key);
-        VIR_FREE(ret->name);
-        VIR_FREE(ret->pool);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 /**
- * virReleaseStorageVol:
+ * virStorageVolDispose:
  * @vol: the vol to release
  *
  * Unconditionally release all memory associated with a vol.
@@ -753,59 +508,16 @@ error:
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseStorageVol(virStorageVolPtr vol) {
-    virConnectPtr conn = vol->conn;
+virStorageVolDispose(void *obj) {
+    virStorageVolPtr vol = obj;
     VIR_DEBUG("release vol %p %s", vol, vol->name);
 
-    vol->magic = -1;
     VIR_FREE(vol->key);
     VIR_FREE(vol->name);
     VIR_FREE(vol->pool);
-    VIR_FREE(vol);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
-
-/**
- * virUnrefStorageVol:
- * @vol: the vol to unreference
- *
- * Unreference the vol. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefStorageVol(virStorageVolPtr vol) {
-    int refs;
-
-    if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
-        virLibConnError(VIR_ERR_INVALID_STORAGE_VOL,
-                        _("bad storage volume or no connection"));
-        return -1;
-    }
-    virMutexLock(&vol->conn->lock);
-    VIR_DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs);
-    vol->refs--;
-    refs = vol->refs;
-    if (refs == 0) {
-        virReleaseStorageVol(vol);
-        /* Already unlocked mutex */
-        return 0;
-    }
 
-    virMutexUnlock(&vol->conn->lock);
-    return refs;
+    if (vol->conn)
+        virObjectUnref(vol->conn);
 }
 
 
@@ -817,7 +529,7 @@ virUnrefStorageVol(virStorageVolPtr vol) {
  * Lookup if the device is already registered for that connection,
  * if yes return a new pointer to it, if no allocate a new structure,
  * and register it in the table. In any case a corresponding call to
- * virUnrefNodeDevice() is needed to not leak data.
+ * virObjectUnref() is needed to not leak data.
  *
  * Returns a pointer to the node device, or NULL in case of failure
  */
@@ -826,44 +538,33 @@ virGetNodeDevice(virConnectPtr conn, const char *name)
 {
     virNodeDevicePtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
         return NULL;
     }
     virCheckNonNullArgReturn(name, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virNodeDeviceClass)))
+        return NULL;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_NODE_DEVICE_MAGIC;
-    ret->conn = conn;
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
-    return ret;
+    ret->conn = virObjectRef(conn);
 
-error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+    return ret;
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 /**
- * virReleaseNodeDevice:
+ * virNodeDeviceDispose:
  * @dev: the dev to release
  *
  * Unconditionally release all memory associated with a dev.
@@ -875,53 +576,15 @@ error:
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseNodeDevice(virNodeDevicePtr dev) {
-    virConnectPtr conn = dev->conn;
+virNodeDeviceDispose(void *obj) {
+    virNodeDevicePtr dev = obj;
     VIR_DEBUG("release dev %p %s", dev, dev->name);
 
-    dev->magic = -1;
     VIR_FREE(dev->name);
     VIR_FREE(dev->parent);
-    VIR_FREE(dev);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
 
-/**
- * virUnrefNodeDevice:
- * @dev: the dev to unreference
- *
- * Unreference the dev. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefNodeDevice(virNodeDevicePtr dev) {
-    int refs;
-
-    virMutexLock(&dev->conn->lock);
-    VIR_DEBUG("unref dev %p %s %d", dev, dev->name, dev->refs);
-    dev->refs--;
-    refs = dev->refs;
-    if (refs == 0) {
-        virReleaseNodeDevice(dev);
-        /* Already unlocked mutex */
-        return 0;
-    }
-
-    virMutexUnlock(&dev->conn->lock);
-    return refs;
+    if (dev->conn)
+        virObjectUnref(dev->conn);
 }
 
 
@@ -932,7 +595,7 @@ virUnrefNodeDevice(virNodeDevicePtr dev) {
  *
  * Lookup if the secret is already registered for that connection, if so return
  * a pointer to it, otherwise allocate a new structure, and register it in the
- * table. In any case a corresponding call to virUnrefSecret() is needed to not
+ * table. In any case a corresponding call to virObjectUnref() is needed to not
  * leak data.
  *
  * Returns a pointer to the secret, or NULL in case of failure
@@ -942,7 +605,9 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid,
              int usageType, const char *usageID)
 {
     virSecretPtr ret = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
@@ -951,39 +616,25 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid,
     virCheckNonNullArgReturn(uuid, NULL);
     virCheckNonNullArgReturn(usageID, NULL);
 
-    virMutexLock(&conn->lock);
-
-    virUUIDFormat(uuid, uuidstr);
+    if (!(ret = virObjectNew(virSecretClass)))
+        return NULL;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_SECRET_MAGIC;
-    ret->conn = conn;
     memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
     ret->usageType = usageType;
-    if (!(ret->usageID = strdup(usageID))) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
-    return ret;
+    if (!(ret->usageID = strdup(usageID)))
+        goto no_memory;
 
-error:
-    if (ret != NULL) {
-        VIR_FREE(ret->usageID);
-        VIR_FREE(ret);
-    }
+    ret->conn = virObjectRef(conn);
+
+    return ret;
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 /**
- * virReleaseSecret:
+ * virSecretDispose:
  * @secret: the secret to release
  *
  * Unconditionally release all memory associated with a secret.  The conn.lock
@@ -994,116 +645,41 @@ error:
  * released if its ref count hits zero.
  */
 static void
-virReleaseSecret(virSecretPtr secret) {
-    virConnectPtr conn = secret->conn;
+virSecretDispose(void *obj) {
+    virSecretPtr secret = obj;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     virUUIDFormat(secret->uuid, uuidstr);
     VIR_DEBUG("release secret %p %s", secret, uuidstr);
 
     VIR_FREE(secret->usageID);
-    secret->magic = -1;
-    VIR_FREE(secret);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
-/**
- * virUnrefSecret:
- * @secret: the secret to unreference
- *
- * Unreference the secret. If the use count drops to zero, the structure is
- * actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefSecret(virSecretPtr secret) {
-    int refs;
-
-    if (!VIR_IS_CONNECTED_SECRET(secret)) {
-        virLibConnError(VIR_ERR_INVALID_SECRET, _("bad secret or no connection"));
-        return -1;
-    }
-    virMutexLock(&secret->conn->lock);
-    VIR_DEBUG("unref secret %p %p %d", secret, secret->uuid, secret->refs);
-    secret->refs--;
-    refs = secret->refs;
-    if (refs == 0) {
-        virReleaseSecret(secret);
-        /* Already unlocked mutex */
-        return 0;
-    }
 
-    virMutexUnlock(&secret->conn->lock);
-    return refs;
+    if (secret->conn)
+        virObjectUnref(secret->conn);
 }
 
+
 virStreamPtr virGetStream(virConnectPtr conn) {
     virStreamPtr ret = NULL;
 
-    virMutexLock(&conn->lock);
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_STREAM_MAGIC;
-    ret->conn = conn;
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
-    return ret;
+    if (!(ret = virObjectNew(virStreamClass)))
+        return NULL;
 
-error:
-    virMutexUnlock(&conn->lock);
-    VIR_FREE(ret);
-    return NULL;
+    ret->conn = virObjectRef(conn);
+
+    return ret;
 }
 
 static void
-virReleaseStream(virStreamPtr st) {
-    virConnectPtr conn = st->conn;
+virStreamDispose(void *obj) {
+    virStreamPtr st = obj;
     VIR_DEBUG("release dev %p", st);
 
-    st->magic = -1;
-    VIR_FREE(st);
-
-    VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-    conn->refs--;
-    if (conn->refs == 0) {
-        virReleaseConnect(conn);
-        /* Already unlocked mutex */
-        return;
-    }
-
-    virMutexUnlock(&conn->lock);
-}
-
-int virUnrefStream(virStreamPtr st) {
-    int refs;
-
-    virMutexLock(&st->conn->lock);
-    VIR_DEBUG("unref stream %p %d", st, st->refs);
-    st->refs--;
-    refs = st->refs;
-    if (refs == 0) {
-        virReleaseStream(st);
-        /* Already unlocked mutex */
-        return 0;
-    }
-
-    virMutexUnlock(&st->conn->lock);
-    return refs;
+    if (st->conn)
+        virObjectUnref(st->conn);
 }
 
 
@@ -1116,14 +692,16 @@ int virUnrefStream(virStreamPtr st) {
  * Lookup if the network filter is already registered for that connection,
  * if yes return a new pointer to it, if no allocate a new structure,
  * and register it in the table. In any case a corresponding call to
- * virUnrefNWFilter() is needed to not leak data.
+ * virObjectUnref() is needed to not leak data.
  *
  * Returns a pointer to the network, or NULL in case of failure
  */
 virNWFilterPtr
 virGetNWFilter(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     virNWFilterPtr ret = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
@@ -1132,41 +710,26 @@ virGetNWFilter(virConnectPtr conn, const char *name, const unsigned char *uuid)
     virCheckNonNullArgReturn(name, NULL);
     virCheckNonNullArgReturn(uuid, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virNWFilterClass)))
+        return NULL;
 
-    virUUIDFormat(uuid, uuidstr);
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_NWFILTER_MAGIC;
-    ret->conn = conn;
     memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
 
-    conn->refs++;
-    ret->refs++;
-    virMutexUnlock(&conn->lock);
-    return ret;
+    ret->conn = virObjectRef(conn);
 
-error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+    return ret;
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 /**
- * virReleaseNWFilter:
+ * virNWFilterDispose:
  * @nwfilter: the nwfilter to release
  *
  * Unconditionally release all memory associated with a nwfilter.
@@ -1178,63 +741,17 @@ error:
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseNWFilter(virNWFilterPtr nwfilter)
-{
-    virConnectPtr conn = nwfilter->conn;
+virNWFilterDispose(void *obj) {
+    virNWFilterPtr nwfilter = obj;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     virUUIDFormat(nwfilter->uuid, uuidstr);
     VIR_DEBUG("release nwfilter %p %s %s", nwfilter, nwfilter->name, uuidstr);
 
-    nwfilter->magic = -1;
     VIR_FREE(nwfilter->name);
-    VIR_FREE(nwfilter);
-
-    if (conn) {
-        VIR_DEBUG("unref connection %p %d", conn, conn->refs);
-        conn->refs--;
-        if (conn->refs == 0) {
-            virReleaseConnect(conn);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&conn->lock);
-    }
-}
-
-
-/**
- * virUnrefNWFilter:
- * @nwfilter: the nwfilter to unreference
- *
- * Unreference the networkf itler. If the use count drops to zero, the
- * structure is actually freed.
- *
- * Returns the reference count or -1 in case of failure.
- */
-int
-virUnrefNWFilter(virNWFilterPtr nwfilter)
-{
-    int refs;
 
-    if (!VIR_IS_CONNECTED_NWFILTER(nwfilter)) {
-        virLibConnError(VIR_ERR_INVALID_NWFILTER,
-                        _("bad nwfilter or no connection"));
-        return -1;
-    }
-    virMutexLock(&nwfilter->conn->lock);
-    VIR_DEBUG("unref nwfilter %p %s %d", nwfilter, nwfilter->name,
-              nwfilter->refs);
-    nwfilter->refs--;
-    refs = nwfilter->refs;
-    if (refs == 0) {
-        virReleaseNWFilter(nwfilter);
-        /* Already unlocked mutex */
-        return 0;
-    }
-
-    virMutexUnlock(&nwfilter->conn->lock);
-    return refs;
+    if (nwfilter->conn)
+        virObjectUnref(nwfilter->conn);
 }
 
 
@@ -1243,84 +760,38 @@ virGetDomainSnapshot(virDomainPtr domain, const char *name)
 {
     virDomainSnapshotPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_DOMAIN(domain)) {
         virLibConnError(VIR_ERR_INVALID_DOMAIN, _("bad domain"));
         return NULL;
     }
     virCheckNonNullArgReturn(name, NULL);
 
-    virMutexLock(&domain->conn->lock);
+    if (!(ret = virObjectNew(virDomainSnapshotClass)))
+        return NULL;
 
-    if (VIR_ALLOC(ret) < 0) {
-        virMutexUnlock(&domain->conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->name = strdup(name);
-    if (ret->name == NULL) {
-        virMutexUnlock(&domain->conn->lock);
-        virReportOOMError();
-        goto error;
-    }
-    ret->magic = VIR_SNAPSHOT_MAGIC;
-    ret->domain = domain;
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
 
-    domain->refs++;
-    ret->refs++;
-    virMutexUnlock(&domain->conn->lock);
-    return ret;
+    ret->domain = virObjectRef(domain);
 
- error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+    return ret;
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 static void
-virReleaseDomainSnapshot(virDomainSnapshotPtr snapshot)
-{
-    virDomainPtr domain = snapshot->domain;
+virDomainSnapshotDispose(void *obj) {
+    virDomainSnapshotPtr snapshot = obj;
     VIR_DEBUG("release snapshot %p %s", snapshot, snapshot->name);
 
-    snapshot->magic = -1;
     VIR_FREE(snapshot->name);
-    VIR_FREE(snapshot);
-
-    if (domain) {
-        VIR_DEBUG("unref domain %p %d", domain, domain->refs);
-        domain->refs--;
-        if (domain->refs == 0) {
-            virReleaseDomain(domain);
-            /* Already unlocked mutex */
-            return;
-        }
-        virMutexUnlock(&domain->conn->lock);
-    }
-}
-
-int
-virUnrefDomainSnapshot(virDomainSnapshotPtr snapshot)
-{
-    int refs;
-
-    if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
-        virLibConnError(VIR_ERR_INVALID_DOMAIN_SNAPSHOT, _("not a snapshot"));
-        return -1;
-    }
-
-    virMutexLock(&snapshot->domain->conn->lock);
-    VIR_DEBUG("unref snapshot %p %s %d", snapshot, snapshot->name, snapshot->refs);
-    snapshot->refs--;
-    refs = snapshot->refs;
-    if (refs == 0) {
-        virReleaseDomainSnapshot(snapshot);
-        /* Already unlocked mutex */
-        return 0;
-    }
 
-    virMutexUnlock(&snapshot->domain->conn->lock);
-    return refs;
+    if (snapshot->domain)
+        virObjectUnref(snapshot->domain);
 }
diff --git a/src/datatypes.h b/src/datatypes.h
index fc284d2..343c807 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -26,118 +26,72 @@
 
 # include "driver.h"
 # include "threads.h"
-
-/**
- * VIR_CONNECT_MAGIC:
- *
- * magic value used to protect the API when pointers to connection structures
- * are passed down by the users.
- */
-# define VIR_CONNECT_MAGIC	0x4F23DEAD
-# define VIR_IS_CONNECT(obj)	((obj) && (obj)->magic==VIR_CONNECT_MAGIC)
-
-
-/**
- * VIR_DOMAIN_MAGIC:
- *
- * magic value used to protect the API when pointers to domain structures
- * are passed down by the users.
- */
-# define VIR_DOMAIN_MAGIC		0xDEAD4321
-# define VIR_IS_DOMAIN(obj)		((obj) && (obj)->magic==VIR_DOMAIN_MAGIC)
-# define VIR_IS_CONNECTED_DOMAIN(obj)	(VIR_IS_DOMAIN(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_NETWORK_MAGIC:
- *
- * magic value used to protect the API when pointers to network structures
- * are passed down by the users.
- */
-# define VIR_NETWORK_MAGIC		0xDEAD1234
-# define VIR_IS_NETWORK(obj)		((obj) && (obj)->magic==VIR_NETWORK_MAGIC)
-# define VIR_IS_CONNECTED_NETWORK(obj)	(VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_INTERFACE_MAGIC:
- *
- * magic value used to protect the API when pointers to interface structures
- * are passed down by the users.
- */
-# define VIR_INTERFACE_MAGIC		0xDEAD5309
-# define VIR_IS_INTERFACE(obj)		((obj) && (obj)->magic==VIR_INTERFACE_MAGIC)
-# define VIR_IS_CONNECTED_INTERFACE(obj)	(VIR_IS_INTERFACE(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_STORAGE_POOL_MAGIC:
- *
- * magic value used to protect the API when pointers to storage pool structures
- * are passed down by the users.
- */
-# define VIR_STORAGE_POOL_MAGIC		0xDEAD5678
-# define VIR_IS_STORAGE_POOL(obj)		((obj) && (obj)->magic==VIR_STORAGE_POOL_MAGIC)
-# define VIR_IS_CONNECTED_STORAGE_POOL(obj)	(VIR_IS_STORAGE_POOL(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_STORAGE_VOL_MAGIC:
- *
- * magic value used to protect the API when pointers to storage vol structures
- * are passed down by the users.
- */
-# define VIR_STORAGE_VOL_MAGIC		0xDEAD8765
-# define VIR_IS_STORAGE_VOL(obj)		((obj) && (obj)->magic==VIR_STORAGE_VOL_MAGIC)
-# define VIR_IS_CONNECTED_STORAGE_VOL(obj)	(VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_NODE_DEVICE_MAGIC:
- *
- * magic value used to protect the API when pointers to storage vol structures
- * are passed down by the users.
- */
-# define VIR_NODE_DEVICE_MAGIC                   0xDEAD5679
-# define VIR_IS_NODE_DEVICE(obj)                 ((obj) && (obj)->magic==VIR_NODE_DEVICE_MAGIC)
-# define VIR_IS_CONNECTED_NODE_DEVICE(obj)       (VIR_IS_NODE_DEVICE(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_SECRET_MAGIC:
- *
- * magic value used to protect the API when pointers to secret structures are
- * passed down by the users.
- */
-# define VIR_SECRET_MAGIC		0x5678DEAD
-# define VIR_IS_SECRET(obj)		((obj) && (obj)->magic==VIR_SECRET_MAGIC)
-# define VIR_IS_CONNECTED_SECRET(obj)	(VIR_IS_SECRET(obj) && VIR_IS_CONNECT((obj)->conn))
-
-
-/**
- * VIR_STREAM_MAGIC:
- *
- * magic value used to protect the API when pointers to stream structures
- * are passed down by the users.
- */
-# define VIR_STREAM_MAGIC                   0x1DEAD666
-# define VIR_IS_STREAM(obj)                 ((obj) && (obj)->magic==VIR_STREAM_MAGIC)
-# define VIR_IS_CONNECTED_STREAM(obj)       (VIR_IS_STREAM(obj) && VIR_IS_CONNECT((obj)->conn))
-
-
-/**
- * VIR_NWFILTER_MAGIC:
- *
- * magic value used to protect the API when pointers to network filter
- * pool structures are passed down by the users.
- */
-# define VIR_NWFILTER_MAGIC			0xDEAD7777
-# define VIR_IS_NWFILTER(obj)			((obj) && (obj)->magic==VIR_NWFILTER_MAGIC)
-# define VIR_IS_CONNECTED_NWFILTER(obj)		(VIR_IS_NWFILTER(obj) && VIR_IS_CONNECT((obj)->conn))
-
-/**
- * VIR_SNAPSHOT_MAGIC:
- *
- * magic value used to protect the API when pointers to snapshot structures
- * are passed down by the users.
- */
-# define VIR_SNAPSHOT_MAGIC                0x6666DEAD
-# define VIR_IS_SNAPSHOT(obj)              ((obj) && (obj)->magic==VIR_SNAPSHOT_MAGIC)
-# define VIR_IS_DOMAIN_SNAPSHOT(obj)    (VIR_IS_SNAPSHOT(obj) && VIR_IS_DOMAIN((obj)->domain))
+# include "virobject.h"
+
+extern virClassPtr virConnectClass;
+extern virClassPtr virDomainClass;
+extern virClassPtr virDomainSnapshotClass;
+extern virClassPtr virInterfaceClass;
+extern virClassPtr virNetworkClass;
+extern virClassPtr virNodeDeviceClass;
+extern virClassPtr virNWFilterClass;
+extern virClassPtr virSecretClass;
+extern virClassPtr virStreamClass;
+extern virClassPtr virStorageVolClass;
+extern virClassPtr virStoragePoolClass;
+
+# define VIR_IS_CONNECT(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virConnectClass))
+
+# define VIR_IS_DOMAIN(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virDomainClass))
+# define VIR_IS_CONNECTED_DOMAIN(obj) \
+    (VIR_IS_DOMAIN(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_NETWORK(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virNetworkClass))
+# define VIR_IS_CONNECTED_NETWORK(obj) \
+    (VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_INTERFACE(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virInterfaceClass))
+# define VIR_IS_CONNECTED_INTERFACE(obj) \
+    (VIR_IS_INTERFACE(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_STORAGE_POOL(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virStoragePoolClass))
+# define VIR_IS_CONNECTED_STORAGE_POOL(obj) \
+    (VIR_IS_STORAGE_POOL(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_STORAGE_VOL(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virStorageVolClass))
+# define VIR_IS_CONNECTED_STORAGE_VOL(obj) \
+    (VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_NODE_DEVICE(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virNodeDeviceClass))
+# define VIR_IS_CONNECTED_NODE_DEVICE(obj) \
+    (VIR_IS_NODE_DEVICE(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_SECRET(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virSecretClass))
+# define VIR_IS_CONNECTED_SECRET(obj) \
+    (VIR_IS_SECRET(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_STREAM(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virStreamClass))
+# define VIR_IS_CONNECTED_STREAM(obj) \
+    (VIR_IS_STREAM(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_NWFILTER(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virNWFilterClass))
+# define VIR_IS_CONNECTED_NWFILTER(obj)	\
+    (VIR_IS_NWFILTER(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_SNAPSHOT(obj) \
+    (virObjectIsClass((virObjectPtr)obj, virDomainSnapshotClass))
+# define VIR_IS_DOMAIN_SNAPSHOT(obj) \
+    (VIR_IS_SNAPSHOT(obj) && VIR_IS_DOMAIN((obj)->domain))
 
 /**
  * _virConnect:
@@ -145,11 +99,11 @@
  * Internal structure associated to a connection
  */
 struct _virConnect {
+    virObject object;
     /* All the variables from here, until the 'lock' declaration
      * are setup at time of connection open, and never changed
      * since. Thus no need to lock when accessing them
      */
-    unsigned int magic;     /* specific value to check */
     unsigned int flags;     /* a set of connection flags */
     virURIPtr uri;          /* connection URI */
 
@@ -186,8 +140,6 @@ struct _virConnect {
     virError err;           /* the last error */
     virErrorFunc handler;   /* associated handlet */
     void *userData;         /* the user data */
-
-    int refs;                 /* reference count */
 };
 
 /**
@@ -196,8 +148,7 @@ struct _virConnect {
 * Internal structure associated to a domain
 */
 struct _virDomain {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
+    virObject object;
     virConnectPtr conn;                  /* pointer back to the connection */
     char *name;                          /* the domain external name */
     int id;                              /* the domain ID */
@@ -210,8 +161,7 @@ struct _virDomain {
 * Internal structure associated to a domain
 */
 struct _virNetwork {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
+    virObject object;
     virConnectPtr conn;                  /* pointer back to the connection */
     char *name;                          /* the network external name */
     unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */
@@ -223,8 +173,7 @@ struct _virNetwork {
 * Internal structure associated to a physical host interface
 */
 struct _virInterface {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
+    virObject object;
     virConnectPtr conn;                  /* pointer back to the connection */
     char *name;                          /* the network external name */
     char *mac;                           /* the interface MAC address */
@@ -236,8 +185,7 @@ struct _virInterface {
 * Internal structure associated to a storage pool
 */
 struct _virStoragePool {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
+    virObject object;
     virConnectPtr conn;                  /* pointer back to the connection */
     char *name;                          /* the storage pool external name */
     unsigned char uuid[VIR_UUID_BUFLEN]; /* the storage pool unique identifier */
@@ -249,8 +197,7 @@ struct _virStoragePool {
 * Internal structure associated to a storage volume
 */
 struct _virStorageVol {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
+    virObject object;
     virConnectPtr conn;                  /* pointer back to the connection */
     char *pool;                          /* Pool name of owner */
     char *name;                          /* the storage vol external name */
@@ -263,8 +210,7 @@ struct _virStorageVol {
  * Internal structure associated with a node device
  */
 struct _virNodeDevice {
-    unsigned int magic;                 /* specific value to check */
-    int refs;                           /* reference count */
+    virObject object;
     virConnectPtr conn;                 /* pointer back to the connection */
     char *name;                         /* device name (unique on node) */
     char *parent;                       /* parent device name */
@@ -276,8 +222,7 @@ struct _virNodeDevice {
  * Internal structure associated with a secret
  */
 struct _virSecret {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
+    virObject object;
     virConnectPtr conn;                  /* pointer back to the connection */
     unsigned char uuid[VIR_UUID_BUFLEN]; /* the domain unique identifier */
     int usageType;                       /* the type of usage */
@@ -294,9 +239,8 @@ typedef int (*virStreamFinishFunc)(virStreamPtr, void *opaque);
  * Internal structure associated with an input stream
  */
 struct _virStream {
-    unsigned int magic;
+    virObject object;
     virConnectPtr conn;
-    int refs;
     unsigned int flags;
 
     virStreamDriverPtr driver;
@@ -309,77 +253,59 @@ struct _virStream {
  * Internal structure associated with a domain snapshot
  */
 struct _virDomainSnapshot {
-    unsigned int magic;
-    int refs;
+    virObject object;
     char *name;
     virDomainPtr domain;
 };
 
-/************************************************************************
- *									*
- *	API for domain/connections (de)allocations and lookups		*
- *									*
- ************************************************************************/
+/**
+* _virNWFilter:
+*
+* Internal structure associated to a network filter
+*/
+struct _virNWFilter {
+    virObject object;
+    virConnectPtr conn;                  /* pointer back to the connection */
+    char *name;                          /* the network filter external name */
+    unsigned char uuid[VIR_UUID_BUFLEN]; /* the network filter unique identifier */
+};
+
+
+/*
+ * Helper APIs for allocating new object instances
+ */
 
 virConnectPtr virGetConnect(void);
-int virUnrefConnect(virConnectPtr conn);
 virDomainPtr virGetDomain(virConnectPtr conn,
+                          const char *name,
+                          const unsigned char *uuid);
+virNetworkPtr virGetNetwork(virConnectPtr conn,
                             const char *name,
                             const unsigned char *uuid);
-int virUnrefDomain(virDomainPtr domain);
-virNetworkPtr virGetNetwork(virConnectPtr conn,
-                              const char *name,
-                              const unsigned char *uuid);
-int virUnrefNetwork(virNetworkPtr network);
-
 virInterfacePtr virGetInterface(virConnectPtr conn,
                                 const char *name,
                                 const char *mac);
-int virUnrefInterface(virInterfacePtr iface);
-
 virStoragePoolPtr virGetStoragePool(virConnectPtr conn,
                                       const char *name,
                                       const unsigned char *uuid);
-int virUnrefStoragePool(virStoragePoolPtr pool);
 virStorageVolPtr virGetStorageVol(virConnectPtr conn,
                                      const char *pool,
                                     const char *name,
                                     const char *key);
-int virUnrefStorageVol(virStorageVolPtr vol);
 
 virNodeDevicePtr virGetNodeDevice(virConnectPtr conn,
                                   const char *name);
-int virUnrefNodeDevice(virNodeDevicePtr dev);
-
 virSecretPtr virGetSecret(virConnectPtr conn,
                           const unsigned char *uuid,
                           int usageType,
                           const char *usageID);
-int virUnrefSecret(virSecretPtr secret);
-
 virStreamPtr virGetStream(virConnectPtr conn);
-int virUnrefStream(virStreamPtr st);
-
-/**
-* _virNWFilter:
-*
-* Internal structure associated to a network filter
-*/
-struct _virNWFilter {
-    unsigned int magic;                  /* specific value to check */
-    int refs;                            /* reference count */
-    virConnectPtr conn;                  /* pointer back to the connection */
-    char *name;                          /* the network filter external name */
-    unsigned char uuid[VIR_UUID_BUFLEN]; /* the network filter unique identifier */
-};
 
 virNWFilterPtr virGetNWFilter(virConnectPtr conn,
                                   const char *name,
                                   const unsigned char *uuid);
-int virUnrefNWFilter(virNWFilterPtr nwfilter);
 
 virDomainSnapshotPtr virGetDomainSnapshot(virDomainPtr domain,
                                           const char *name);
-int virUnrefDomainSnapshot(virDomainSnapshotPtr snapshot);
 
 #endif
diff --git a/src/libvirt.c b/src/libvirt.c
index c6640b2..c16459c 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1273,7 +1273,7 @@ do_open (const char *name,
 
 failed:
     virConfFree(conf);
-    virUnrefConnect(ret);
+    virObjectUnref(ret);
 
     return NULL;
 }
@@ -1430,10 +1430,9 @@ virConnectClose(virConnectPtr conn)
         goto error;
     }
 
-    ret = virUnrefConnect(conn);
-    if (ret < 0)
-        goto error;
-    return ret;
+    if (!virObjectUnref(conn))
+        return 0;
+    return 1;
 
 error:
     virDispatchError(NULL);
@@ -1465,10 +1464,8 @@ virConnectRef(virConnectPtr conn)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&conn->lock);
-    VIR_DEBUG("conn=%p refs=%d", conn, conn->refs);
-    conn->refs++;
-    virMutexUnlock(&conn->lock);
+    VIR_DEBUG("conn=%p refs=%d", conn, conn->object.refs);
+    virObjectRef(conn);
     return 0;
 }
 
@@ -2265,10 +2262,7 @@ virDomainFree(virDomainPtr domain)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefDomain(domain) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(domain);
     return 0;
 }
 
@@ -2297,10 +2291,9 @@ virDomainRef(virDomainPtr domain)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&domain->conn->lock);
-    VIR_DOMAIN_DEBUG(domain, "refs=%d", domain->refs);
-    domain->refs++;
-    virMutexUnlock(&domain->conn->lock);
+
+    VIR_DOMAIN_DEBUG(domain, "refs=%d", domain->object.refs);
+    virObjectRef(domain);
     return 0;
 }
 
@@ -10093,10 +10086,7 @@ virNetworkFree(virNetworkPtr network)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefNetwork(network) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(network);
     return 0;
 }
 
@@ -10125,10 +10115,8 @@ virNetworkRef(virNetworkPtr network)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&network->conn->lock);
-    VIR_DEBUG("network=%p refs=%d", network, network->refs);
-    network->refs++;
-    virMutexUnlock(&network->conn->lock);
+    VIR_DEBUG("network=%p refs=%d", network, network->object.refs);
+    virObjectRef(network);
     return 0;
 }
 
@@ -10998,10 +10986,8 @@ virInterfaceRef(virInterfacePtr iface)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&iface->conn->lock);
-    VIR_DEBUG("iface=%p refs=%d", iface, iface->refs);
-    iface->refs++;
-    virMutexUnlock(&iface->conn->lock);
+    VIR_DEBUG("iface=%p refs=%d", iface, iface->object.refs);
+    virObjectRef(iface);
     return 0;
 }
 
@@ -11026,10 +11012,7 @@ virInterfaceFree(virInterfacePtr iface)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefInterface(iface) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(iface);
     return 0;
 }
 
@@ -11935,10 +11918,7 @@ virStoragePoolFree(virStoragePoolPtr pool)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefStoragePool(pool) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(pool);
     return 0;
 
 }
@@ -11969,10 +11949,8 @@ virStoragePoolRef(virStoragePoolPtr pool)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&pool->conn->lock);
-    VIR_DEBUG("pool=%p refs=%d", pool, pool->refs);
-    pool->refs++;
-    virMutexUnlock(&pool->conn->lock);
+    VIR_DEBUG("pool=%p refs=%d", pool, pool->object.refs);
+    virObjectRef(pool);
     return 0;
 }
 
@@ -13001,10 +12979,7 @@ virStorageVolFree(virStorageVolPtr vol)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefStorageVol(vol) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(vol);
     return 0;
 }
 
@@ -13034,10 +13009,8 @@ virStorageVolRef(virStorageVolPtr vol)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&vol->conn->lock);
-    VIR_DEBUG("vol=%p refs=%d", vol, vol->refs);
-    vol->refs++;
-    virMutexUnlock(&vol->conn->lock);
+    VIR_DEBUG("vol=%p refs=%d", vol, vol->object.refs);
+    virObjectRef(vol);
     return 0;
 }
 
@@ -13576,10 +13549,7 @@ int virNodeDeviceFree(virNodeDevicePtr dev)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefNodeDevice(dev) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(dev);
     return 0;
 }
 
@@ -13609,10 +13579,8 @@ virNodeDeviceRef(virNodeDevicePtr dev)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&dev->conn->lock);
-    VIR_DEBUG("dev=%p refs=%d", dev, dev->refs);
-    dev->refs++;
-    virMutexUnlock(&dev->conn->lock);
+    VIR_DEBUG("dev=%p refs=%d", dev, dev->object.refs);
+    virObjectRef(dev);
     return 0;
 }
 
@@ -14582,10 +14550,8 @@ virSecretRef(virSecretPtr secret)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&secret->conn->lock);
-    VIR_DEBUG("secret=%p refs=%d", secret, secret->refs);
-    secret->refs++;
-    virMutexUnlock(&secret->conn->lock);
+    VIR_DEBUG("secret=%p refs=%d", secret, secret->object.refs);
+    virObjectRef(secret);
     return 0;
 }
 
@@ -14609,10 +14575,7 @@ virSecretFree(virSecretPtr secret)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefSecret(secret) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(secret);
     return 0;
 }
 
@@ -14681,10 +14644,8 @@ virStreamRef(virStreamPtr stream)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&stream->conn->lock);
-    VIR_DEBUG("stream=%p refs=%d", stream, stream->refs);
-    stream->refs++;
-    virMutexUnlock(&stream->conn->lock);
+    VIR_DEBUG("stream=%p refs=%d", stream, stream->object.refs);
+    virObjectRef(stream);
     return 0;
 }
 
@@ -15325,10 +15286,7 @@ int virStreamFree(virStreamPtr stream)
 
     /* XXX Enforce shutdown before free'ing resources ? */
 
-    if (virUnrefStream(stream) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(stream);
     return 0;
 }
 
@@ -15789,10 +15747,8 @@ virNWFilterFree(virNWFilterPtr nwfilter)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefNWFilter(nwfilter) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+
+    virObjectUnref(nwfilter);
     return 0;
 }
 
@@ -16048,10 +16004,8 @@ virNWFilterRef(virNWFilterPtr nwfilter)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&nwfilter->conn->lock);
-    VIR_DEBUG("nwfilter=%p refs=%d", nwfilter, nwfilter->refs);
-    nwfilter->refs++;
-    virMutexUnlock(&nwfilter->conn->lock);
+    VIR_DEBUG("nwfilter=%p refs=%d", nwfilter, nwfilter->object.refs);
+    virObjectRef(nwfilter);
     return 0;
 }
 
@@ -17935,10 +17889,8 @@ virDomainSnapshotRef(virDomainSnapshotPtr snapshot)
         virDispatchError(NULL);
         return -1;
     }
-    virMutexLock(&snapshot->domain->conn->lock);
-    VIR_DEBUG("snapshot=%p, refs=%d", snapshot, snapshot->refs);
-    snapshot->refs++;
-    virMutexUnlock(&snapshot->domain->conn->lock);
+    VIR_DEBUG("snapshot=%p, refs=%d", snapshot, snapshot->object.refs);
+    virObjectRef(snapshot);
     return 0;
 }
 
@@ -17964,10 +17916,7 @@ virDomainSnapshotFree(virDomainSnapshotPtr snapshot)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefDomainSnapshot(snapshot) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(snapshot);
     return 0;
 }
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1ff6735..9327d9a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -202,12 +202,17 @@ virGetSecret;
 virGetStoragePool;
 virGetStorageVol;
 virGetStream;
-virUnrefConnect;
-virUnrefDomain;
-virUnrefNWFilter;
-virUnrefSecret;
-virUnrefStorageVol;
-virUnrefStream;
+virConnectClass;
+virDomainClass;
+virDomainSnapshotClass;
+virInterfaceClass;
+virNetworkClass;
+virNodeDeviceClass;
+virNWFilterClass;
+virSecretClass;
+virStreamClass;
+virStorageVolClass;
+virStoragePoolClass;
 
 
 # dnsmasq.h
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 5136fbc..c349491 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -2089,7 +2089,7 @@ phypStorageVolCreateXML(virStoragePoolPtr pool,
     /* checking if this name already exists on this system */
     if ((dup_vol = phypVolumeLookupByName(pool, voldef->name)) != NULL) {
         VIR_ERROR(_("StoragePool name already exists."));
-        virUnrefStorageVol(dup_vol);
+        virObjectUnref(dup_vol);
         goto err;
     }
 
@@ -2126,7 +2126,7 @@ err:
     virStorageVolDefFree(voldef);
     virStoragePoolDefFree(spdef);
     if (vol)
-        virUnrefStorageVol(vol);
+        virObjectUnref(vol);
     return NULL;
 }
 
@@ -2326,7 +2326,7 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
 
 cleanup:
     if (sp)
-        virUnrefStoragePool(sp);
+        virObjectUnref(sp);
     return xml;
 }
 
@@ -2722,14 +2722,14 @@ phypStoragePoolCreateXML(virConnectPtr conn,
     /* checking if this name already exists on this system */
     if ((dup_sp = phypStoragePoolLookupByName(conn, def->name)) != NULL) {
         VIR_WARN("StoragePool name already exists.");
-        virUnrefStoragePool(dup_sp);
+        virObjectUnref(dup_sp);
         goto err;
     }
 
     /* checking if ID or UUID already exists on this system */
     if ((dup_sp = phypGetStoragePoolLookUpByUUID(conn, def->uuid)) != NULL) {
         VIR_WARN("StoragePool uuid already exists.");
-        virUnrefStoragePool(dup_sp);
+        virObjectUnref(dup_sp);
         goto err;
     }
 
@@ -2744,7 +2744,7 @@ phypStoragePoolCreateXML(virConnectPtr conn,
 err:
     virStoragePoolDefFree(def);
     if (sp)
-        virUnrefStoragePool(sp);
+        virObjectUnref(sp);
     return NULL;
 }
 
@@ -3690,7 +3690,7 @@ phypDomainCreateAndStart(virConnectPtr conn,
 err:
     virDomainDefFree(def);
     if (dom)
-        virUnrefDomain(dom);
+        virObjectUnref(dom);
     return NULL;
 }
 
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 94b2919..97697be 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1805,7 +1805,7 @@ qemuBuildRBDString(virConnectPtr conn,
 cleanup:
     VIR_FREE(secret);
     if (sec)
-        virUnrefSecret(sec);
+        virObjectUnref(sec);
 
     return ret;
 
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index f51c99a..558f064 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2285,14 +2285,14 @@ finish:
 
 cleanup:
     if (ddomain) {
-        virUnrefDomain(ddomain);
+        virObjectUnref(ddomain);
         ret = 0;
     } else {
         ret = -1;
     }
 
     if (st)
-        virUnrefStream(st);
+        virObjectUnref(st);
 
     if (orig_err) {
         virSetError(orig_err);
@@ -2479,14 +2479,14 @@ finish:
 
  cleanup:
     if (ddomain) {
-        virUnrefDomain(ddomain);
+        virObjectUnref(ddomain);
         ret = 0;
     } else {
         ret = -1;
     }
 
     if (st)
-        virUnrefStream(st);
+        virObjectUnref(st);
 
     if (orig_err) {
         virSetError(orig_err);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c5140c3..2aa6af1 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -447,7 +447,7 @@ qemuProcessGetVolumeQcowPassphrase(virConnectPtr conn,
         goto cleanup;
     data = conn->secretDriver->getValue(secret, &size, 0,
                                         VIR_SECRET_GET_VALUE_INTERNAL_CALL);
-    virUnrefSecret(secret);
+    virObjectUnref(secret);
     if (data == NULL)
         goto cleanup;
 
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index fbc630d..5b00d75 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1399,7 +1399,7 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
 
 cleanup:
     if (volobj)
-        virUnrefStorageVol(volobj);
+        virObjectUnref(volobj);
     virStorageVolDefFree(voldef);
     if (pool)
         virStoragePoolObjUnlock(pool);
@@ -1561,7 +1561,7 @@ storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
 
 cleanup:
     if (volobj)
-        virUnrefStorageVol(volobj);
+        virObjectUnref(volobj);
     virStorageVolDefFree(newvol);
     if (pool)
         virStoragePoolObjUnlock(pool);
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index ba7552c..4cdc580 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -1208,7 +1208,7 @@ static virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml,
 
     if (vboxDomainCreate(dom) < 0) {
         vboxDomainUndefineFlags(dom, 0);
-        virUnrefDomain(dom);
+        virObjectUnref(dom);
         return NULL;
     }
 
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index f1aa9b6..8751189 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -1243,7 +1243,7 @@ error:
     virXendError(VIR_ERR_INTERNAL_ERROR,
                  "%s", _("failed to parse Xend domain information"));
     if (ret != NULL)
-        virUnrefDomain(ret);
+        virObjectUnref(ret);
     return NULL;
 }
 
@@ -2606,7 +2606,7 @@ xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc,
     /* Make sure we don't leave a still-born domain around */
     if (dom != NULL) {
         xenDaemonDomainDestroyFlags(dom, 0);
-        virUnrefDomain(dom);
+        virObjectUnref(dom);
     }
     virDomainDefFree(def);
     return NULL;
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 7b00ea2..6449952 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -40,23 +40,12 @@ fakeSecretLookupByUsage(virConnectPtr conn,
                         int usageType ATTRIBUTE_UNUSED,
                         const char *usageID)
 {
-    virSecretPtr ret = NULL;
-    int err;
+    unsigned char uuid[VIR_UUID_BUFLEN];
     if (STRNEQ(usageID, "mycluster_myname"))
         return NULL;
-    err = VIR_ALLOC(ret);
-    if (err < 0)
-        return NULL;
-    ret->magic = VIR_SECRET_MAGIC;
-    ret->refs = 1;
-    ret->usageID = strdup(usageID);
-    if (!ret->usageID) {
-        VIR_FREE(ret);
-        return NULL;
-    }
-    ret->conn = conn;
-    conn->refs++;
-    return ret;
+
+    virUUIDGenerate(uuid);
+    return virGetSecret(conn, uuid, usageType, usageID);
 }
 
 static int
@@ -241,7 +230,7 @@ out:
     VIR_FREE(actualargv);
     virCommandFree(cmd);
     virDomainDefFree(vmdef);
-    virUnrefConnect(conn);
+    virObjectUnref(conn);
     return ret;
 }
 
diff --git a/tests/qemuxmlnstest.c b/tests/qemuxmlnstest.c
index 8eca466..451b168 100644
--- a/tests/qemuxmlnstest.c
+++ b/tests/qemuxmlnstest.c
@@ -166,7 +166,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
     VIR_FREE(actualargv);
     virCommandFree(cmd);
     virDomainDefFree(vmdef);
-    virUnrefConnect(conn);
+    virObjectUnref(conn);
     return ret;
 }
 
diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c
index 37e3749..93049dd 100644
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -72,7 +72,7 @@ testCompareFiles(const char *xml, const char *sexpr, int xendConfigVersion)
   VIR_FREE(gotxml);
   virDomainDefFree(def);
   if (conn)
-    virUnrefConnect(conn);
+    virObjectUnref(conn);
 
   return ret;
 }
diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c
index 9956bf2..75ced8b 100644
--- a/tests/xmconfigtest.c
+++ b/tests/xmconfigtest.c
@@ -93,7 +93,7 @@ testCompareParseXML(const char *xmcfg, const char *xml, int xendConfigVersion)
     if (conf)
         virConfFree(conf);
     virDomainDefFree(def);
-    virUnrefConnect(conn);
+    virObjectUnref(conn);
 
     return ret;
 }
@@ -147,7 +147,7 @@ testCompareFormatXML(const char *xmcfg, const char *xml, int xendConfigVersion)
     VIR_FREE(xmcfgData);
     VIR_FREE(gotxml);
     virDomainDefFree(def);
-    virUnrefConnect(conn);
+    virObjectUnref(conn);
 
     return ret;
 }
-- 
1.7.10.2




More information about the libvir-list mailing list