'virHashForEach' historically allowed deletion of the current element as 'virHashRemoveSet' didn't exits. To prevent us from having to deepy analyse all iterators add virHashForEachSafe which first gets a list of elements and iterates them outside of the hash table.
This will allow replace the internals of the hash table with other implementation which don't allow such operation. Signed-off-by: Peter Krempa <pkre...@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virhash.c | 26 +++++++++++++++++++++++--- src/util/virhash.h | 1 + 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1793b81ad9..f7b0d11ca2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2203,6 +2203,7 @@ virHashAtomicSteal; virHashAtomicUpdate; virHashEqual; virHashForEach; +virHashForEachSafe; virHashForEachSorted; virHashFree; virHashGetItems; diff --git a/src/util/virhash.c b/src/util/virhash.c index f205291de9..e54052985f 100644 --- a/src/util/virhash.c +++ b/src/util/virhash.c @@ -481,7 +481,7 @@ virHashRemoveEntry(virHashTablePtr table, const char *name) /** - * virHashForEach, virHashForEachSorted + * virHashForEach, virHashForEachSorted, virHashForEachSafe * @table: the hash table to process * @iter: callback to process each element * @opaque: opaque data to pass to the iterator @@ -490,14 +490,14 @@ virHashRemoveEntry(virHashTablePtr table, const char *name) * * The elements are iterated in arbitrary order. * - * virHashForEach allows the callback to remove the current + * virHashForEach, virHashForEachSafe allow the callback to remove the current * element using virHashRemoveEntry but calling other virHash* functions is * prohibited. Note that removing the entry invalidates @key and @payload in * the callback. * * virHashForEachSorted iterates the elements in order by sorted key. * - * virHashForEachSorted is more computationally + * virHashForEachSorted and virHashForEachSafe are more computationally * expensive than virHashForEach. * * If @iter fails and returns a negative value, the evaluation is stopped and -1 @@ -531,6 +531,26 @@ virHashForEach(virHashTablePtr table, virHashIterator iter, void *opaque) } +int +virHashForEachSafe(virHashTablePtr table, + virHashIterator iter, + void *opaque) +{ + g_autofree virHashKeyValuePairPtr items = virHashGetItems(table, NULL, false); + size_t i; + + if (!items) + return -1; + + for (i = 0; items[i].key; i++) { + if (iter((void *)items[i].value, items[i].key, opaque) < 0) + return -1; + } + + return 0; +} + + int virHashForEachSorted(virHashTablePtr table, virHashIterator iter, diff --git a/src/util/virhash.h b/src/util/virhash.h index 1a59e9799d..b00ab0447e 100644 --- a/src/util/virhash.h +++ b/src/util/virhash.h @@ -136,6 +136,7 @@ bool virHashEqual(const virHashTable *table1, * Iterators */ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *opaque); +int virHashForEachSafe(virHashTablePtr table, virHashIterator iter, void *opaque); int virHashForEachSorted(virHashTablePtr table, virHashIterator iter, void *opaque); ssize_t virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *opaque); void *virHashSearch(const virHashTable *table, virHashSearcher iter, -- 2.26.2