Introduce an API to use the virHashForEach API to go through each element
of a specified LookupHash (via @useUUID) calling a callback with a LookupKey
object entry from the LookupHash in order for it to be processed.
Create a common structure to define the various pieces of data needed by
the callback consumers:
struct _virObjectLookupHashForEachData {
virConnectPtr conn; -> Connect ptr for @aclfilter APIs
void *aclfilter; -> 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
};
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}
=> Would typically only care about @nelems based on whether
the caller cares about @wantActive. Can also filter results
based on the @aclfilter call.
vir{Object}Get{Key}
=> Use the @elems and @maxelems in order to fill in an array
of char ** strings based on the {Key} filtering data as
necessary from the @aclfilter and possibly the @matchstr.
Callers of this function will preallocate the @elems and
supply the @maxelems value. The @nelems is used to keep track
of the number of elements.
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 assocated with 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 | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virobject.h | 20 ++++++++++++++++
3 files changed, 82 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 68961e7..f783fec 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2288,6 +2288,7 @@ virObjectLock;
virObjectLockableNew;
virObjectLookupHashAdd;
virObjectLookupHashFind;
+virObjectLookupHashForEach;
virObjectLookupHashGetName;
virObjectLookupHashGetUUID;
virObjectLookupHashNew;
diff --git a/src/util/virobject.c b/src/util/virobject.c
index 01922b3..8a994f5 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -893,3 +893,64 @@ virObjectLookupHashGetName(void *anyobj)
return obj->objsName;
}
+
+
+/**
+ * virObjectLookupHashForEach
+ * @tableobj: poolable hash table pointer to walk through
+ * @useUUID: boolean to use objsUUID
+ * @callback: callback function to handle the object specific checks
+ * @opaque: callback data
+ *
+ * For each element of the objsName hash table make a call into the
+ * callback routine to handle its task
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+virObjectLookupHashForEach(void *tableobj,
+ bool useUUID,
+ virHashIterator callback,
+ virObjectLookupHashForEachDataPtr data)
+{
+ virObjectLookupHashPtr hashObj = virObjectGetLookupHashObj(tableobj);
+ virHashTablePtr tbl;
+
+ if (!hashObj)
+ return -1;
+
+ if (useUUID)
+ tbl = hashObj->objsUUID;
+ else
+ tbl = hashObj->objsName;
+
+ if (data->maxelems == -1) {
+ if (VIR_ALLOC_N(data->elems, virHashSize(tbl) + 1) < 0)
+ return -1;
+ }
+
+ virObjectLock(hashObj);
+ virHashForEach(tbl, callback, data);
+ virObjectUnlock(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 ed99540..926c9d3 100644
--- a/src/util/virobject.h
+++ b/src/util/virobject.h
@@ -198,4 +198,24 @@ virObjectLookupHashGetUUID(void *anyobj);
virHashTablePtr
virObjectLookupHashGetName(void *anyobj);
+typedef struct _virObjectLookupHashForEachData virObjectLookupHashForEachData;
+typedef virObjectLookupHashForEachData *virObjectLookupHashForEachDataPtr;
+struct _virObjectLookupHashForEachData {
+ virConnectPtr conn;
+ void *aclfilter;
+ bool wantActive;
+ bool error;
+ const char *matchstr;
+ unsigned int flags;
+ int nelems;
+ void **elems;
+ int maxelems;
+};
+
+int
+virObjectLookupHashForEach(void *tableobj,
+ bool useUUID,
+ virHashIterator callback,
+ virObjectLookupHashForEachDataPtr data);
+
#endif /* __VIR_OBJECT_H */
--
2.9.4