[libvirt] [PATCH v5 05/15] util: Introduce virObjectLookupHashForEach{UUID|Name}

John Ferlan jferlan at redhat.com
Wed Aug 23 21:22:01 UTC 2017


Introduce an API to use the virHashForEach API to go through
each element of the LookupHash calling a callback for each object
entry from the LookupHash in order for it to be processed.

Create a common structure _virObjectLookupHashForEachData to define
the various pieces of data needed by the callback consumers. Fields
described in the API function description section.

Upon successful completion, the data.nElems is returned to the
caller and possibly various fields within the structure filled
in depending on the callers need as follows:

  vir{Object}NumOf{Elem}
  vir{Object}Get{UUID|Name}

      => Callback function can be combined since generally all that
         the NumOf cares about is counts, but the Get function also
         adds some {UUID|Name} to a returned list of @uuids/@names.

  vir{Object}Export
      => When @maxElems == -1, will cause allocation into data->elems
         of an array sized by the hash table size which will be used
         by the callback function to store addresses of objects specific
         to each {Object} that are typically associated with the
         virConnectListAll* API's from the virGet{Object}() calls.
         The @flags argument is typically used for additional filtering
         via vir{Object}Match or vir{Object}Filter APIs found in various
         vir*obj modules. Upon return from the call, the calling function
         must then move the data->elems into the returned structure.

It is up to the callback function to set @error in the event of an error
during processing resulting in calling the VIR_FREE() for each of the
@nElems already in the array.

When an error occurs, any collection done by the callback functions into
the @elems array is discarded.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/libvirt_private.syms |   2 +
 src/util/virobject.c     | 118 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virobject.h     |  27 +++++++++++
 3 files changed, 147 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 8ad7223..4d0883c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2333,6 +2333,8 @@ virObjectLockableNew;
 virObjectLookupHashAdd;
 virObjectLookupHashFind;
 virObjectLookupHashFindLocked;
+virObjectLookupHashForEachName;
+virObjectLookupHashForEachUUID;
 virObjectLookupHashNew;
 virObjectLookupHashRemove;
 virObjectNew;
diff --git a/src/util/virobject.c b/src/util/virobject.c
index 63205d3..dfd0bec 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -930,3 +930,121 @@ virObjectLookupHashFind(void *anyobj,
 
     return obj;
 }
+
+
+static int
+virObjectLookupHashForEachInternal(virHashTablePtr objsTable,
+                                   virHashIterator iter,
+                                   virObjectLookupHashForEachDataPtr data)
+{
+    if (data->maxElems == -1) {
+        if (VIR_ALLOC_N(data->elems, virHashSize(objsTable) + 1) < 0)
+            return -1;
+    }
+
+    virHashForEach(objsTable, iter, data);
+
+    if (data->error)
+        goto error;
+
+    if (data->maxElems == -1) {
+        /* trim the array to the final size */
+        ignore_value(VIR_REALLOC_N(data->elems, data->nElems + 1));
+    }
+
+    return data->nElems;
+
+ error:
+    if (data->elems) {
+        if (data->maxElems == -1) {
+            virObjectListFree(data->elems);
+        } else {
+            while (--data->nElems)
+                VIR_FREE(data->elems[data->nElems]);
+        }
+    }
+    return -1;
+}
+
+
+/**
+ * virObjectLookupHashForEach{UUID|Name}
+ * @anyobj: LookupHash object
+ * @iter: callback function to handle the object specific checks
+ * @opaque: callback data
+ *
+ * For each element of the UUID or Name hash table make a call into the
+ * callback routine to handle its task. Even if there were two hash
+ * tables all the objects exist in both, so it's only necessary to
+ * run through one of them, but two API's are required since the caller
+ * can use either.
+ *
+ * NB:
+ * struct _virObjectLookupHashForEachData {
+ *     virConnectPtr conn;     -> Connect ptr for @filter APIs
+ *     void *opaque;           -> Opaque data as determined by caller
+ *     void *filter;           -> A pointer to function for ACL calls
+ *     bool wantActive;        -> Filter active objs
+ *     bool error;             -> Set by callback functions for error
+ *     const char *matchStr;   -> Filter for specific string in many objs
+ *     unsigned int flags;     -> @flags argument to for Export calls
+ *     int nElems;             -> # of elements found and passing filters
+ *     void **elems;           -> array of elements
+ *     int maxElems;           -> maximum # of elements to collect
+ *                                Use -1 to allocate array of N table sized
+ *                                elements to use for Export functions
+ *                                Use -2 for NumOf functions to avoid the
+ *                                allocation, but allow sharing with the
+ *                                GetNames type functions
+ * };
+ *
+ * Returns number of elements found on success, -1 on failure
+ */
+int
+virObjectLookupHashForEachUUID(void *anyobj,
+                               virHashIterator iter,
+                               virObjectLookupHashForEachDataPtr data)
+{
+    virObjectLookupHashPtr hashObj = virObjectGetLookupHashObj(anyobj);
+    int ret;
+
+    if (!hashObj)
+        return -1;
+
+    if (!hashObj->objsUUID) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("no objsUUID for hashObj=%p"), hashObj);
+        return -1;
+    }
+
+    virObjectRWLockRead(hashObj);
+    ret = virObjectLookupHashForEachInternal(hashObj->objsUUID, iter, data);
+    virObjectRWUnlock(hashObj);
+
+    return ret;
+}
+
+
+int
+virObjectLookupHashForEachName(void *anyobj,
+                               virHashIterator iter,
+                               virObjectLookupHashForEachDataPtr data)
+{
+    virObjectLookupHashPtr hashObj = virObjectGetLookupHashObj(anyobj);
+    int ret;
+
+    if (!hashObj)
+        return -1;
+
+    if (!hashObj->objsName) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("no objsName for hashObj=%p"), hashObj);
+        return -1;
+    }
+
+    virObjectRWLockRead(hashObj);
+    ret = virObjectLookupHashForEachInternal(hashObj->objsName, iter, data);
+    virObjectRWUnlock(hashObj);
+
+    return ret;
+}
diff --git a/src/util/virobject.h b/src/util/virobject.h
index e5596e6..a35cf3c 100644
--- a/src/util/virobject.h
+++ b/src/util/virobject.h
@@ -205,4 +205,31 @@ virObjectLookupHashFind(void *anyobj,
                         const char *key)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
+typedef struct _virObjectLookupHashForEachData virObjectLookupHashForEachData;
+typedef virObjectLookupHashForEachData *virObjectLookupHashForEachDataPtr;
+struct _virObjectLookupHashForEachData {
+    virConnectPtr conn;
+    void *opaque;
+    void *filter;
+    bool wantActive;
+    bool error;
+    const char *matchStr;
+    unsigned int flags;
+    int nElems;
+    void **elems;
+    int maxElems;
+};
+
+int
+virObjectLookupHashForEachUUID(void *anyobj,
+                               virHashIterator iter,
+                               virObjectLookupHashForEachDataPtr data)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
+int
+virObjectLookupHashForEachName(void *anyobj,
+                               virHashIterator iter,
+                               virObjectLookupHashForEachDataPtr data)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
 #endif /* __VIR_OBJECT_H */
-- 
2.9.5




More information about the libvir-list mailing list