diff --git a/src/util/virhash.c b/src/util/virhash.c index d6f208eacc..a8e0edfd3b 100644 --- a/src/util/virhash.c +++ b/src/util/virhash.c @@ -579,13 +579,16 @@ virHashRemoveEntry(virHashTablePtr table, const void *name) * Iterates over every element in the hash table, invoking the * 'iter' callback. The callback is allowed to remove the current element * using virHashRemoveEntry but calling other virHash* functions is prohibited. + * If @iter fails and returns a negative value, the evaluation is stopped and -1 + * is returned. * - * Returns number of items iterated over upon completion, -1 on failure + * Returns 0 on success or -1 on failure. */ -ssize_t +int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) { - size_t i, count = 0; + size_t i; + int ret = -1; if (table == NULL || iter == NULL) return -1; @@ -599,20 +602,24 @@ virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) virHashEntryPtr entry = table->table[i]; while (entry) { virHashEntryPtr next = entry->next; - table->current = entry; - iter(entry->payload, entry->name, data); + ret = iter(entry->payload, entry->name, data); table->current = NULL; - count++; + if (ret < 0) + goto cleanup; + entry = next; } } - table->iterating = false; - return count; + ret = 0; + cleanup: + table->iterating = false; + return ret; } + /** * virHashRemoveSet * @table: the hash table to process diff --git a/src/util/virhash.h b/src/util/virhash.h index ed6bba3db7..61c172b9e0 100644 --- a/src/util/virhash.h +++ b/src/util/virhash.h @@ -191,7 +191,7 @@ bool virHashEqual(const virHashTable *table1, /* * Iterators */ -ssize_t virHashForEach(virHashTablePtr table, virHashIterator iter, void *data); +int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data); ssize_t virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *data); void *virHashSearch(const virHashTable *table, virHashSearcher iter, const void *data); diff --git a/tests/virhashtest.c b/tests/virhashtest.c index 323c68e20a..a3ec13c7e8 100644 --- a/tests/virhashtest.c +++ b/tests/virhashtest.c @@ -61,24 +61,26 @@ testHashCheckForEachCount(void *payload ATTRIBUTE_UNUSED, const void *name ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED) { + size_t *count = data; + *count += 1; return 0; } static int testHashCheckCount(virHashTablePtr hash, size_t count) { - ssize_t iter_count = 0; + size_t iter_count = 0; if (virHashSize(hash) != count) { - VIR_TEST_VERBOSE("\nhash contains %zu instead of %zu elements\n", - (size_t)virHashSize(hash), count); + VIR_TEST_VERBOSE("\nhash contains %zd instead of %zu elements\n", + virHashSize(hash), count); return -1; } - iter_count = virHashForEach(hash, testHashCheckForEachCount, NULL); + virHashForEach(hash, testHashCheckForEachCount, &iter_count); if (count != iter_count) { - VIR_TEST_VERBOSE("\nhash claims to have %zu elements but iteration finds %zu\n", - count, (size_t)iter_count); + VIR_TEST_VERBOSE("\nhash claims to have %zu elements but iteration" + "finds %zu\n", count, iter_count); return -1; } @@ -250,18 +252,13 @@ testHashRemoveForEach(const void *data) { const struct testInfo *info = data; virHashTablePtr hash; - int count; int ret = -1; if (!(hash = testHashInit(0))) return -1; - count = virHashForEach(hash, (virHashIterator) info->data, hash); - - if (count != ARRAY_CARDINALITY(uuids)) { - VIR_TEST_VERBOSE("\nvirHashForEach didn't go through all entries," - " %d != %zu\n", - count, ARRAY_CARDINALITY(uuids)); + if (virHashForEach(hash, (virHashIterator) info->data, hash)) { + VIR_TEST_VERBOSE("\nvirHashForEach didn't go through all entries"); goto cleanup; } @@ -343,18 +340,13 @@ static int testHashForEach(const void *data ATTRIBUTE_UNUSED) { virHashTablePtr hash; - int count; int ret = -1; if (!(hash = testHashInit(0))) return -1; - count = virHashForEach(hash, testHashForEachIter, hash); - - if (count != ARRAY_CARDINALITY(uuids)) { - VIR_TEST_VERBOSE("\nvirHashForEach didn't go through all entries," - " %d != %zu\n", - count, ARRAY_CARDINALITY(uuids)); + if (virHashForEach(hash, testHashForEachIter, hash)) { + VIR_TEST_VERBOSE("\nvirHashForEach didn't go through all entries"); goto cleanup; }