Introduce an API to use the virHashForEach API to go through
each element of the LookupHash calling a callback with a LookupKey
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{Key}
=> Callback function can be combined since generally all that
the NumOf cares about is counts, but the Get function also
adds some {Key} to a returned list of @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(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virobject.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virobject.h | 21 ++++++++++++++
3 files changed, 96 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b6ab173..3978106 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2334,6 +2334,7 @@ virObjectLockableNew;
virObjectLookupHashAdd;
virObjectLookupHashFind;
virObjectLookupHashFindLocked;
+virObjectLookupHashForEach;
virObjectLookupHashNew;
virObjectLookupHashRemove;
virObjectLookupKeysIsActive;
diff --git a/src/util/virobject.c b/src/util/virobject.c
index 7dbfd1b..a76f1cb 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -1019,3 +1019,77 @@ virObjectLookupHashFind(void *anyobj,
return obj;
}
+
+
+/**
+ * virObjectLookupHashForEach
+ * @anyobj: LookupHash object
+ * @callback: callback function to handle the object specific checks
+ * @opaque: callback data
+ *
+ * For each element of the objsKey1 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.
+ *
+ * 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
+virObjectLookupHashForEach(void *anyobj,
+ virHashIterator callback,
+ virObjectLookupHashForEachDataPtr data)
+{
+ virObjectLookupHashPtr hashObj = virObjectGetLookupHashObj(anyobj);
+
+ if (!hashObj)
+ return -1;
+
+ if (data->maxElems == -1) {
+ if (VIR_ALLOC_N(data->elems, virHashSize(hashObj->objsKey1) + 1) < 0)
+ return -1;
+ }
+
+ virObjectRWLockRead(hashObj);
+ virHashForEach(hashObj->objsKey1, callback, data);
+ virObjectRWUnlock(hashObj);
+
+ 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;
+}
diff --git a/src/util/virobject.h b/src/util/virobject.h
index dc668ca..ddebf6c 100644
--- a/src/util/virobject.h
+++ b/src/util/virobject.h
@@ -219,4 +219,25 @@ 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
+virObjectLookupHashForEach(void *anyobj,
+ virHashIterator callback,
+ virObjectLookupHashForEachDataPtr data)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
#endif /* __VIR_OBJECT_H */
--
2.9.4