[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] PATCH: 11/25: Public APIs for incrementing refcount



With the domain events code, the callbacks triggered upon events get given
a virDomainPtr object instance. In many cases it'd be desirable to grab
this object and keep it in your app code. Unfortunately it is free'd the
moment the callback finishes executing.

When allowing multiple threads to access a single virConnectPtr object
it is neccessary to ensure no thread releases it (virConnectCLose) while
another thread is still using it.

The way to address both of these problems is to allow an application to
take an explicit reference on the object in question. So this patch
exposes methods to allow an app to increment the ref count on all our
public objects. To release the ref count, the existing virConectClose/
virDOmainFree, etc methods suffice

 include/libvirt/libvirt.h    |    6 +
 include/libvirt/libvirt.h.in |    6 +
 src/libvirt.c                |  183 +++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms      |   12 ++
 4 files changed, 206 insertions(+), 1 deletion(-)

Daniel

diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -396,6 +396,7 @@ virConnectPtr           virConnectOpenAu
 virConnectPtr           virConnectOpenAuth      (const char *name,
                                                  virConnectAuthPtr auth,
                                                  int flags);
+int                     virConnectRef           (virConnectPtr conn);
 int                     virConnectClose         (virConnectPtr conn);
 const char *            virConnectGetType       (virConnectPtr conn);
 int                     virConnectGetVersion    (virConnectPtr conn,
@@ -453,6 +454,7 @@ int                     virDomainReboot 
 int                     virDomainReboot         (virDomainPtr domain,
                                                  unsigned int flags);
 int                     virDomainDestroy        (virDomainPtr domain);
+int                     virDomainRef            (virDomainPtr domain);
 int                     virDomainFree           (virDomainPtr domain);
 
 /*
@@ -765,6 +767,7 @@ int                     virNetworkCreate
  * Network destroy/free
  */
 int                     virNetworkDestroy       (virNetworkPtr network);
+int                     virNetworkRef           (virNetworkPtr network);
 int                     virNetworkFree          (virNetworkPtr network);
 
 /*
@@ -925,6 +928,7 @@ int                     virStoragePoolDe
 int                     virStoragePoolDestroy           (virStoragePoolPtr pool);
 int                     virStoragePoolDelete            (virStoragePoolPtr pool,
                                                          unsigned int flags);
+int                     virStoragePoolRef               (virStoragePoolPtr pool);
 int                     virStoragePoolFree              (virStoragePoolPtr pool);
 int                     virStoragePoolRefresh           (virStoragePoolPtr pool,
                                                          unsigned int flags);
@@ -978,6 +982,7 @@ virStorageVolPtr        virStorageVolCre
                                                          unsigned int flags);
 int                     virStorageVolDelete             (virStorageVolPtr vol,
                                                          unsigned int flags);
+int                     virStorageVolRef                (virStorageVolPtr vol);
 int                     virStorageVolFree               (virStorageVolPtr vol);
 
 int                     virStorageVolGetInfo            (virStorageVolPtr vol,
@@ -1045,6 +1050,7 @@ char *                  virNodeDeviceGet
 char *                  virNodeDeviceGetXMLDesc (virNodeDevicePtr dev,
                                                  unsigned int flags);
 
+int                     virNodeDeviceRef        (virNodeDevicePtr dev);
 int                     virNodeDeviceFree       (virNodeDevicePtr dev);
 
 /*
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -396,6 +396,7 @@ virConnectPtr           virConnectOpenAu
 virConnectPtr           virConnectOpenAuth      (const char *name,
                                                  virConnectAuthPtr auth,
                                                  int flags);
+int                     virConnectRef           (virConnectPtr conn);
 int                     virConnectClose         (virConnectPtr conn);
 const char *            virConnectGetType       (virConnectPtr conn);
 int                     virConnectGetVersion    (virConnectPtr conn,
@@ -453,6 +454,7 @@ int                     virDomainReboot 
 int                     virDomainReboot         (virDomainPtr domain,
                                                  unsigned int flags);
 int                     virDomainDestroy        (virDomainPtr domain);
+int                     virDomainRef            (virDomainPtr domain);
 int                     virDomainFree           (virDomainPtr domain);
 
 /*
@@ -765,6 +767,7 @@ int                     virNetworkCreate
  * Network destroy/free
  */
 int                     virNetworkDestroy       (virNetworkPtr network);
+int                     virNetworkRef           (virNetworkPtr network);
 int                     virNetworkFree          (virNetworkPtr network);
 
 /*
@@ -925,6 +928,7 @@ int                     virStoragePoolDe
 int                     virStoragePoolDestroy           (virStoragePoolPtr pool);
 int                     virStoragePoolDelete            (virStoragePoolPtr pool,
                                                          unsigned int flags);
+int                     virStoragePoolRef               (virStoragePoolPtr pool);
 int                     virStoragePoolFree              (virStoragePoolPtr pool);
 int                     virStoragePoolRefresh           (virStoragePoolPtr pool,
                                                          unsigned int flags);
@@ -978,6 +982,7 @@ virStorageVolPtr        virStorageVolCre
                                                          unsigned int flags);
 int                     virStorageVolDelete             (virStorageVolPtr vol,
                                                          unsigned int flags);
+int                     virStorageVolRef                (virStorageVolPtr vol);
 int                     virStorageVolFree               (virStorageVolPtr vol);
 
 int                     virStorageVolGetInfo            (virStorageVolPtr vol,
@@ -1045,6 +1050,7 @@ char *                  virNodeDeviceGet
 char *                  virNodeDeviceGetXMLDesc (virNodeDevicePtr dev,
                                                  unsigned int flags);
 
+int                     virNodeDeviceRef        (virNodeDevicePtr dev);
 int                     virNodeDeviceFree       (virNodeDevicePtr dev);
 
 /*
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1119,6 +1119,35 @@ virConnectClose(virConnectPtr conn)
     return (0);
 }
 
+/**
+ * virConnectRef:
+ * @conn: the connection to hold a reference on
+ *
+ * Increment the reference count on the connection. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virConnectClose to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection remain open until all threads have finished using
+ * it. ie, each new thread using a connection would increment
+ * the reference count.
+ */
+int
+virConnectRef(virConnectPtr conn)
+{
+    if ((!VIR_IS_CONNECT(conn))) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&conn->lock);
+    DEBUG("conn=%p refs=%d", conn, conn->refs);
+    conn->refs++;
+    virMutexUnlock(&conn->lock);
+    return 0;
+}
+
 /*
  * Not for public use.  This function is part of the internal
  * implementation of driver features in the remote case.
@@ -1775,6 +1804,36 @@ virDomainFree(virDomainPtr domain)
         return -1;
     return(0);
 }
+
+/**
+ * virDomainRef:
+ * @conn: the domain to hold a reference on
+ *
+ * Increment the reference count on the domain. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virDomainFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection remain open until all threads have finished using
+ * it. ie, each new thread using a domain would increment
+ * the reference count.
+ */
+int
+virDomainRef(virDomainPtr domain)
+{
+    if ((!VIR_IS_CONNECTED_DOMAIN(domain))) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&domain->conn->lock);
+    DEBUG("domain=%p refs=%d", domain, domain->refs);
+    domain->refs++;
+    virMutexUnlock(&domain->conn->lock);
+    return 0;
+}
+
 
 /**
  * virDomainSuspend:
@@ -4814,6 +4873,35 @@ virNetworkFree(virNetworkPtr network)
 }
 
 /**
+ * virNetworkRef:
+ * @conn: the network to hold a reference on
+ *
+ * Increment the reference count on the network. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virNetworkFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection remain open until all threads have finished using
+ * it. ie, each new thread using a network would increment
+ * the reference count.
+ */
+int
+virNetworkRef(virNetworkPtr network)
+{
+    if ((!VIR_IS_CONNECTED_NETWORK(network))) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&network->conn->lock);
+    DEBUG("network=%p refs=%d", network, network->refs);
+    network->refs++;
+    virMutexUnlock(&network->conn->lock);
+    return 0;
+}
+
+/**
  * virNetworkGetName:
  * @network: a network object
  *
@@ -5869,6 +5957,35 @@ virStoragePoolFree(virStoragePoolPtr poo
 
 
 /**
+ * virStoragePoolRef:
+ * @conn: the pool to hold a reference on
+ *
+ * Increment the reference count on the pool. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virStoragePoolFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection remain open until all threads have finished using
+ * it. ie, each new thread using a pool would increment
+ * the reference count.
+ */
+int
+virStoragePoolRef(virStoragePoolPtr pool)
+{
+    if ((!VIR_IS_CONNECTED_STORAGE_POOL(pool))) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&pool->conn->lock);
+    DEBUG("pool=%p refs=%d", pool, pool->refs);
+    pool->refs++;
+    virMutexUnlock(&pool->conn->lock);
+    return 0;
+}
+
+/**
  * virStoragePoolRefresh:
  * @pool: pointer to storage pool
  * @flags: flags to control refresh behaviour (currently unused, use 0)
@@ -6619,6 +6736,35 @@ virStorageVolFree(virStorageVolPtr vol)
     return(0);
 }
 
+
+/**
+ * virStorageVolRef:
+ * @conn: the vol to hold a reference on
+ *
+ * Increment the reference count on the vol. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virStorageVolFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection remain open until all threads have finished using
+ * it. ie, each new thread using a vol would increment
+ * the reference count.
+ */
+int
+virStorageVolRef(virStorageVolPtr vol)
+{
+    if ((!VIR_IS_CONNECTED_STORAGE_VOL(vol))) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&vol->conn->lock);
+    DEBUG("vol=%p refs=%d", vol, vol->refs);
+    vol->refs++;
+    virMutexUnlock(&vol->conn->lock);
+    return 0;
+}
 
 /**
  * virStorageVolGetInfo:
@@ -7093,6 +7239,36 @@ int virNodeDeviceFree(virNodeDevicePtr d
 }
 
 
+/**
+ * virNodeDeviceRef:
+ * @conn: the dev to hold a reference on
+ *
+ * Increment the reference count on the dev. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virNodeDeviceFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection remain open until all threads have finished using
+ * it. ie, each new thread using a dev would increment
+ * the reference count.
+ */
+int
+virNodeDeviceRef(virNodeDevicePtr dev)
+{
+    if ((!VIR_IS_CONNECTED_NODE_DEVICE(dev))) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&dev->conn->lock);
+    DEBUG("dev=%p refs=%d", dev, dev->refs);
+    dev->refs++;
+    virMutexUnlock(&dev->conn->lock);
+    return 0;
+}
+
+
 /*
  * Domain Event Notification
  */
@@ -7107,6 +7283,13 @@ int virNodeDeviceFree(virNodeDevicePtr d
  * Adds a Domain Event Callback.
  * Registering for a domain callback will enable delivery of the events
  *
+ * The virDomainPtr object handle passed into the callback upon delivery
+ * of an event is only valid for the duration of execution of the callback.
+ * If the callback wishes to keep the domain object after the callback
+ * returns, it shall take a reference to it, by calling virDomainRef.
+ * The reference can be released once the object is no longer required
+ * by calling virDomainFree.
+ *
  * Returns 0 on success, -1 on failure
  */
 int
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -236,5 +236,15 @@ LIBVIRT_0.5.0 {
 
 } LIBVIRT_0.4.5;
 
-# no new entry point in 0.5.1
+LIBVIRT_0.6.0 {
+    global:
+	virConnectRef;
+	virDomainRef;
+	virNetworkRef;
+	virStoragePoolRef;
+	virStorageVolRef;
+	virNodeDeviceRef;
+
+} LIBVIRT_0.5.0;
+
 # .... define new API here using predicted next version number ....

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]