util: hash: Add delete-safe hash iterator

'virHashForEach' historically allowed deletion of the current element as
'virHashRemoveSet' didn't exist. To prevent us from having to deeply
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 <pkrempa@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Reviewed-by: Matt Coleman <matt@datto.com>
This commit is contained in:
Peter Krempa 2020-10-26 15:30:10 +01:00
parent 5f1b1da1b9
commit 80f3af5fd8
3 changed files with 25 additions and 3 deletions

View File

@ -2207,6 +2207,7 @@ virHashAtomicSteal;
virHashAtomicUpdate;
virHashEqual;
virHashForEach;
virHashForEachSafe;
virHashForEachSorted;
virHashFree;
virHashGetItems;

View File

@ -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,

View File

@ -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,