[libvirt] [PATCH v3 02/10] Convert public datatypes to inherit from virObject

Daniel P. Berrange berrange at redhat.com
Mon Aug 6 11:52:58 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                  | 1025 ++++++++++----------------------------
 src/datatypes.h                  |  277 ++++------
 src/libvirt.c                    |  145 ++----
 src/libvirt_private.syms         |   17 +-
 src/parallels/parallels_driver.c |    4 +-
 src/phyp/phyp_driver.c           |   18 +-
 src/qemu/qemu_command.c          |    3 +-
 src/qemu/qemu_migration.c        |   10 +-
 src/qemu/qemu_process.c          |    2 +-
 src/storage/storage_driver.c     |    6 +-
 src/vbox/vbox_tmpl.c             |    2 +-
 src/xen/xend_internal.c          |    5 +-
 tests/qemuxml2argvtest.c         |   21 +-
 tests/qemuxmlnstest.c            |    2 +-
 tests/sexpr2xmltest.c            |    3 +-
 tests/xmconfigtest.c             |    4 +-
 17 files changed, 445 insertions(+), 1107 deletions(-)

diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index f72bc8c..43ecdcf 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 343ee0d..e827c2d 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -35,12 +35,58 @@
     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);
+
+#undef DECLARE_CLASS
+
+    return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virDataTypes)
 
 /**
  * virGetConnect:
@@ -50,38 +96,26 @@
  * Returns a new pointer or NULL in case of error.
  */
 virConnectPtr
-virGetConnect(void) {
+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.
@@ -90,13 +124,9 @@ failed:
  * 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);
+virConnectDispose(void *obj)
+{
+    virConnectPtr conn = obj;
 
     if (conn->networkDriver)
         conn->networkDriver->close(conn);
@@ -127,35 +157,6 @@ virReleaseConnect(virConnectPtr conn) {
     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, "%s", _("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:
@@ -166,14 +167,18 @@ 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) {
+virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid)
+{
     virDomainPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("no connection"));
         return NULL;
@@ -181,39 +186,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;
 
-    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;
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
+
+    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,64 +217,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);
-    }
+    virObjectUnref(domain->conn);
 }
 
 
 /**
- * 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, "%s",
-                        _("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;
-}
-
-/**
  * virGetNetwork:
  * @conn: the hypervisor connection
  * @name: pointer to the network name
@@ -291,14 +239,18 @@ 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) {
+virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid)
+{
     virNetworkPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("no connection"));
         return NULL;
@@ -306,38 +258,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;
 
-    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;
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
+
+    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.
@@ -349,60 +288,16 @@ 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, "%s",
-                        _("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;
+    virObjectUnref(network->conn);
 }
 
 
@@ -415,15 +310,19 @@ 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
  */
 virInterfacePtr
-virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
+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, "%s", _("no connection"));
         return NULL;
@@ -434,45 +333,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.
@@ -484,58 +364,14 @@ 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, "%s",
-                        _("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;
+    virObjectUnref(iface->conn);
 }
 
 
@@ -548,15 +384,19 @@ 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
  */
 virStoragePoolPtr
 virGetStoragePool(virConnectPtr conn, const char *name,
-                  const unsigned char *uuid) {
+                  const unsigned char *uuid)
+{
     virStoragePoolPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("no connection"));
         return NULL;
@@ -564,39 +404,26 @@ virGetStoragePool(virConnectPtr conn, const char *name,
     virCheckNonNullArgReturn(name, NULL);
     virCheckNonNullArgReturn(uuid, NULL);
 
-    virMutexLock(&conn->lock);
+    if (!(ret = virObjectNew(virStoragePoolClass)))
+        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->magic = VIR_STORAGE_POOL_MAGIC;
-    ret->conn = conn;
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
+
+    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.
@@ -608,60 +435,16 @@ 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, "%s",
-                        _("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;
+    virObjectUnref(pool->conn);
 }
 
 
@@ -675,15 +458,19 @@ 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
  */
 virStorageVolPtr
 virGetStorageVol(virConnectPtr conn, const char *pool, const char *name,
-                 const char *key) {
+                 const char *key)
+{
     virStorageVolPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("no connection"));
         return NULL;
@@ -691,52 +478,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.
@@ -748,59 +512,15 @@ 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, "%s",
-                        _("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;
+    virObjectUnref(vol->conn);
 }
 
 
@@ -812,7 +532,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
  */
@@ -821,44 +541,32 @@ virGetNodeDevice(virConnectPtr conn, const char *name)
 {
     virNodeDevicePtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("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);
+    ret->conn = virObjectRef(conn);
     return ret;
-
-error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 /**
- * virReleaseNodeDevice:
+ * virNodeDeviceDispose:
  * @dev: the dev to release
  *
  * Unconditionally release all memory associated with a dev.
@@ -870,53 +578,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;
+    virObjectUnref(dev->conn);
 }
 
 
@@ -927,7 +597,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
@@ -938,6 +608,9 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid,
 {
     virSecretPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("no connection"));
         return NULL;
@@ -945,37 +618,25 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid,
     virCheckNonNullArgReturn(uuid, NULL);
     virCheckNonNullArgReturn(usageID, NULL);
 
-    virMutexLock(&conn->lock);
+    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
@@ -986,117 +647,42 @@ 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);
-    }
+    virObjectUnref(secret->conn);
 }
 
-/**
- * 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, "%s",
-                        _("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;
-    }
+virStreamPtr
+virGetStream(virConnectPtr conn)
+{
+    virStreamPtr ret = NULL;
 
-    virMutexUnlock(&secret->conn->lock);
-    return refs;
-}
+    if (virDataTypesInitialize() < 0)
+        return NULL;
 
-virStreamPtr virGetStream(virConnectPtr conn) {
-    virStreamPtr ret = NULL;
+    if (!(ret = virObjectNew(virStreamClass)))
+        return NULL;
 
-    virMutexLock(&conn->lock);
+    ret->conn = virObjectRef(conn);
 
-    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;
-
-error:
-    virMutexUnlock(&conn->lock);
-    VIR_FREE(ret);
-    return NULL;
 }
 
 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;
+    virObjectUnref(st->conn);
 }
 
 
@@ -1109,14 +695,19 @@ 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) {
+virGetNWFilter(virConnectPtr conn, const char *name,
+               const unsigned char *uuid)
+{
     virNWFilterPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(VIR_ERR_INVALID_CONN, "%s", _("no connection"));
         return NULL;
@@ -1124,39 +715,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;
+
+    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.
@@ -1168,63 +746,16 @@ error:
  * which may also be released if its ref count hits zero.
  */
 static void
-virReleaseNWFilter(virNWFilterPtr nwfilter)
+virNWFilterDispose(void *obj)
 {
-    virConnectPtr conn = nwfilter->conn;
+    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, "%s",
-                        _("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;
+    virObjectUnref(nwfilter->conn);
 }
 
 
@@ -1233,85 +764,35 @@ virGetDomainSnapshot(virDomainPtr domain, const char *name)
 {
     virDomainSnapshotPtr ret = NULL;
 
+    if (virDataTypesInitialize() < 0)
+        return NULL;
+
     if (!VIR_IS_DOMAIN(domain)) {
         virLibConnError(VIR_ERR_INVALID_DOMAIN, "%s", _("bad domain"));
         return NULL;
     }
     virCheckNonNullArgReturn(name, NULL);
 
-    virMutexLock(&domain->conn->lock);
-
-    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 = virObjectNew(virDomainSnapshotClass)))
+        return NULL;
+    if (!(ret->name = strdup(name)))
+        goto no_memory;
+    ret->domain = virObjectRef(domain);
 
-    domain->refs++;
-    ret->refs++;
-    virMutexUnlock(&domain->conn->lock);
     return ret;
-
- error:
-    if (ret != NULL) {
-        VIR_FREE(ret->name);
-        VIR_FREE(ret);
-    }
+no_memory:
+    virReportOOMError();
+    virObjectUnref(ret);
     return NULL;
 }
 
 
 static void
-virReleaseDomainSnapshot(virDomainSnapshotPtr snapshot)
+virDomainSnapshotDispose(void *obj)
 {
-    virDomainPtr domain = snapshot->domain;
+    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, "%s",
-                        _("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;
+    virObjectUnref(snapshot->domain);
 }
diff --git a/src/datatypes.h b/src/datatypes.h
index cd17410..0ec2b56 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -19,125 +19,79 @@
  *
  */
 
-#ifndef __VIRT_DATATYPES_H_
-# define __VIRT_DATATYPES_H_
+#ifndef __VIR_DATATYPES_H_
+# define __VIR_DATATYPES_H_
 
 # include "internal.h"
 
 # 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((obj), virConnectClass))
+
+# define VIR_IS_DOMAIN(obj) \
+    (virObjectIsClass((obj), virDomainClass))
+# define VIR_IS_CONNECTED_DOMAIN(obj) \
+    (VIR_IS_DOMAIN(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_NETWORK(obj) \
+    (virObjectIsClass((obj), virNetworkClass))
+# define VIR_IS_CONNECTED_NETWORK(obj) \
+    (VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_INTERFACE(obj) \
+    (virObjectIsClass((obj), virInterfaceClass))
+# define VIR_IS_CONNECTED_INTERFACE(obj) \
+    (VIR_IS_INTERFACE(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_STORAGE_POOL(obj) \
+    (virObjectIsClass((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((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((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((obj), virSecretClass))
+# define VIR_IS_CONNECTED_SECRET(obj) \
+    (VIR_IS_SECRET(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_STREAM(obj) \
+    (virObjectIsClass((obj), virStreamClass))
+# define VIR_IS_CONNECTED_STREAM(obj) \
+    (VIR_IS_STREAM(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_NWFILTER(obj) \
+    (virObjectIsClass((obj), virNWFilterClass))
+# define VIR_IS_CONNECTED_NWFILTER(obj) \
+    (VIR_IS_NWFILTER(obj) && VIR_IS_CONNECT((obj)->conn))
+
+# define VIR_IS_SNAPSHOT(obj) \
+    (virObjectIsClass((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 */
 
@@ -193,8 +147,6 @@ struct _virConnect {
     virFreeCallback closeFreeCallback;
     bool closeDispatch;
     unsigned closeUnregisterCount;
-
-    int refs;                 /* reference count */
 };
 
 /**
@@ -203,8 +155,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 */
@@ -217,8 +168,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 */
@@ -230,8 +180,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 */
@@ -243,8 +192,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 */
@@ -256,8 +204,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 */
@@ -270,8 +217,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 */
@@ -283,8 +229,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 */
@@ -301,9 +246,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;
@@ -316,77 +260,56 @@ 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);
-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);
+                                      const char *name,
+                                      const unsigned char *uuid);
 virStorageVolPtr virGetStorageVol(virConnectPtr conn,
-                                  const char *pool,
-                                  const char *name,
-                                  const char *key);
-int virUnrefStorageVol(virStorageVolPtr vol);
-
+                                     const char *pool,
+                                    const char *name,
+                                    const char *key);
 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
+#endif /* __VIR_DATATYPES_H__ */
diff --git a/src/libvirt.c b/src/libvirt.c
index 3c4bf8c..1064e2e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1294,7 +1294,7 @@ do_open (const char *name,
 
 failed:
     virConfFree(conf);
-    virUnrefConnect(ret);
+    virObjectUnref(ret);
 
     return NULL;
 }
@@ -1429,14 +1429,16 @@ error:
  * matching virConnectClose, and all other references will be released
  * after the corresponding operation completes.
  *
- * Returns the number of remaining references on success
- * (positive implies that some other call still has a reference open,
- * 0 implies that no references remain and the connection is closed),
- * or -1 on failure.  It is possible for the last virConnectClose to
- * return a positive value if some other object still has a temporary
- * reference to the connection, but the application should not try to
- * further use a connection after the virConnectClose that matches the
- * initial open.
+ * Returns a positive number if at least 1 reference remains on
+ * success. The returned value should not be assumed to be the total
+ * reference count. A return of 0 implies no references remain and
+ * the connection is closed & memory has been freed. A return of -1
+ * implies a failure.
+ *
+ * It is possible for the last virConnectClose to return a positive
+ * value if some other object still has a temporary reference to the
+ * connection, but the application should not try to further use a
+ * connection after the virConnectClose that matches the initial open.
  */
 int
 virConnectClose(virConnectPtr conn)
@@ -1451,10 +1453,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);
@@ -1486,10 +1487,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;
 }
 
@@ -2286,10 +2285,7 @@ virDomainFree(virDomainPtr domain)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefDomain(domain) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(domain);
     return 0;
 }
 
@@ -2318,10 +2314,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;
 }
 
@@ -10118,10 +10113,7 @@ virNetworkFree(virNetworkPtr network)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefNetwork(network) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(network);
     return 0;
 }
 
@@ -10150,10 +10142,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;
 }
 
@@ -11023,10 +11013,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;
 }
 
@@ -11051,10 +11039,7 @@ virInterfaceFree(virInterfacePtr iface)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefInterface(iface) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(iface);
     return 0;
 }
 
@@ -11960,10 +11945,7 @@ virStoragePoolFree(virStoragePoolPtr pool)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefStoragePool(pool) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(pool);
     return 0;
 
 }
@@ -11994,10 +11976,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;
 }
 
@@ -13026,10 +13006,7 @@ virStorageVolFree(virStorageVolPtr vol)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefStorageVol(vol) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(vol);
     return 0;
 }
 
@@ -13059,10 +13036,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;
 }
 
@@ -13601,10 +13576,7 @@ int virNodeDeviceFree(virNodeDevicePtr dev)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefNodeDevice(dev) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(dev);
     return 0;
 }
 
@@ -13634,10 +13606,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;
 }
 
@@ -14607,10 +14577,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;
 }
 
@@ -14634,10 +14602,7 @@ virSecretFree(virSecretPtr secret)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefSecret(secret) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(secret);
     return 0;
 }
 
@@ -14706,10 +14671,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;
 }
 
@@ -15350,10 +15313,7 @@ int virStreamFree(virStreamPtr stream)
 
     /* XXX Enforce shutdown before free'ing resources ? */
 
-    if (virUnrefStream(stream) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+    virObjectUnref(stream);
     return 0;
 }
 
@@ -15814,10 +15774,8 @@ virNWFilterFree(virNWFilterPtr nwfilter)
         virDispatchError(NULL);
         return -1;
     }
-    if (virUnrefNWFilter(nwfilter) < 0) {
-        virDispatchError(NULL);
-        return -1;
-    }
+
+    virObjectUnref(nwfilter);
     return 0;
 }
 
@@ -16073,10 +16031,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;
 }
 
@@ -17960,10 +17916,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;
 }
 
@@ -17989,10 +17943,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 9ed6a8d..e6884d8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -194,6 +194,9 @@ virCPUModeTypeToString;
 
 
 # datatypes.h
+virConnectClass;
+virDomainClass;
+virDomainSnapshotClass;
 virGetConnect;
 virGetDomain;
 virGetDomainSnapshot;
@@ -205,12 +208,14 @@ virGetSecret;
 virGetStoragePool;
 virGetStorageVol;
 virGetStream;
-virUnrefConnect;
-virUnrefDomain;
-virUnrefNWFilter;
-virUnrefSecret;
-virUnrefStorageVol;
-virUnrefStream;
+virInterfaceClass;
+virNetworkClass;
+virNodeDeviceClass;
+virNWFilterClass;
+virSecretClass;
+virStoragePoolClass;
+virStorageVolClass;
+virStreamClass;
 
 
 # dnsmasq.h
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index c26ea25..05db54f 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -1600,14 +1600,14 @@ parallelsCreateVm(virConnectPtr conn, virDomainDefPtr def)
         goto error2;
 
     virStoragePoolObjUnlock(pool);
-    virUnrefStorageVol(vol);
+    virObjectUnref(vol);
 
     return 0;
 
   error2:
     virStoragePoolObjUnlock(pool);
   error:
-    virUnrefStorageVol(vol);
+    virObjectUnref(vol);
     return -1;
 }
 
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 0ebdfff..2707a4d 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -2085,7 +2085,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;
     }
 
@@ -2121,8 +2121,7 @@ err:
     VIR_FREE(key);
     virStorageVolDefFree(voldef);
     virStoragePoolDefFree(spdef);
-    if (vol)
-        virUnrefStorageVol(vol);
+    virObjectUnref(vol);
     return NULL;
 }
 
@@ -2321,8 +2320,7 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
     VIR_FREE(voldef.key);
 
 cleanup:
-    if (sp)
-        virUnrefStoragePool(sp);
+    virObjectUnref(sp);
     return xml;
 }
 
@@ -2718,14 +2716,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;
     }
 
@@ -2739,8 +2737,7 @@ phypStoragePoolCreateXML(virConnectPtr conn,
 
 err:
     virStoragePoolDefFree(def);
-    if (sp)
-        virUnrefStoragePool(sp);
+    virObjectUnref(sp);
     return NULL;
 }
 
@@ -3685,8 +3682,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 6ad65a6..b52d13e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1896,8 +1896,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 7663e5e..003c399 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2285,14 +2285,13 @@ 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 +2478,13 @@ 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 685ea7c..0d4f5ae 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 6d7dd2b..3dc66db 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1398,8 +1398,7 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
     voldef = NULL;
 
 cleanup:
-    if (volobj)
-        virUnrefStorageVol(volobj);
+    virObjectUnref(volobj);
     virStorageVolDefFree(voldef);
     if (pool)
         virStoragePoolObjUnlock(pool);
@@ -1560,8 +1559,7 @@ storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
     volobj = NULL;
 
 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 b672b24..8185c3a 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -1204,7 +1204,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 9c27933..892d0e5 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -1236,8 +1236,7 @@ sexpr_to_domain(virConnectPtr conn, const struct sexpr *root)
 error:
     virReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("failed to parse Xend domain information"));
-    if (ret != NULL)
-        virUnrefDomain(ret);
+    virObjectUnref(ret);
     return NULL;
 }
 
@@ -2600,7 +2599,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 39fcd9f..1adba78 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
@@ -239,7 +228,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 0bc821d..253c89e 100644
--- a/tests/qemuxmlnstest.c
+++ b/tests/qemuxmlnstest.c
@@ -157,7 +157,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..9b9b09d 100644
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -71,8 +71,7 @@ testCompareFiles(const char *xml, const char *sexpr, int xendConfigVersion)
   VIR_FREE(sexprData);
   VIR_FREE(gotxml);
   virDomainDefFree(def);
-  if (conn)
-    virUnrefConnect(conn);
+  virObjectUnref(conn);
 
   return ret;
 }
diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c
index 3a0937e..826bed8 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.4




More information about the libvir-list mailing list