All but one of the callers either use the list in arbitrary order or
sorted by key. Rewrite the function so that it supports sorting by key
natively and make it return the element count. This in turn allows to
rewrite the only caller to sort by value internally.
This allows to remove multiple sorting functions which were sorting by
key and the function will be also later reused for some hash operations
internally.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/conf/nwfilter_params.c | 10 +---
src/hyperv/hyperv_wmi.c | 2 +-
src/locking/lock_daemon.c | 2 +-
src/nwfilter/nwfilter_ebiptables_driver.c | 13 +++--
src/qemu/qemu_interop_config.c | 9 +---
src/rpc/virnetdaemon.c | 11 +---
src/util/virhash.c | 66 ++++++++++++++---------
src/util/virhash.h | 5 +-
src/util/virlockspace.c | 2 +-
tests/virhashtest.c | 11 +---
10 files changed, 59 insertions(+), 72 deletions(-)
diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c
index 73160a38a4..dd2b92c97b 100644
--- a/src/conf/nwfilter_params.c
+++ b/src/conf/nwfilter_params.c
@@ -755,13 +755,6 @@ virNWFilterParseParamAttributes(xmlNodePtr cur)
}
-static int
-virNWFilterFormatParameterNameSorter(const virHashKeyValuePair *a,
- const virHashKeyValuePair *b)
-{
- return strcmp(a->key, b->key);
-}
-
int
virNWFilterFormatParamAttributes(virBufferPtr buf,
virHashTablePtr table,
@@ -779,8 +772,7 @@ virNWFilterFormatParamAttributes(virBufferPtr buf,
return -1;
}
- items = virHashGetItems(table,
- virNWFilterFormatParameterNameSorter);
+ items = virHashGetItems(table, NULL, true);
if (!items)
return -1;
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 1d0d33ec6d..7a66e4810e 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -681,7 +681,7 @@ hypervSerializeEmbeddedParam(hypervParamPtr p, const char
*resourceUri,
/* retrieve parameters out of hash table */
numKeys = virHashSize(p->embedded.table);
- items = virHashGetItems(p->embedded.table, NULL);
+ items = virHashGetItems(p->embedded.table, NULL, false);
if (!items) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not read embedded param hash table"));
diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
index 8f16dfd064..021792cc69 100644
--- a/src/locking/lock_daemon.c
+++ b/src/locking/lock_daemon.c
@@ -730,7 +730,7 @@ virLockDaemonPreExecRestart(const char *state_file,
}
- tmp = pairs = virHashGetItems(lockDaemon->lockspaces, NULL);
+ tmp = pairs = virHashGetItems(lockDaemon->lockspaces, NULL, false);
while (tmp && tmp->key) {
virLockSpacePtr lockspace = (virLockSpacePtr)tmp->value;
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c
b/src/nwfilter/nwfilter_ebiptables_driver.c
index da6f88f135..8dfc870ab7 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -3126,9 +3126,12 @@ virNWFilterRuleInstSortPtr(const void *a, const void *b)
static int
-ebiptablesFilterOrderSort(const virHashKeyValuePair *a,
- const virHashKeyValuePair *b)
+ebiptablesFilterOrderSort(const void *va,
+ const void *vb)
{
+ const virHashKeyValuePair *a = va;
+ const virHashKeyValuePair *b = vb;
+
/* elements' values has been limited to range [-1000, 1000] */
return *(virNWFilterChainPriority *)a->value -
*(virNWFilterChainPriority *)b->value;
@@ -3288,13 +3291,15 @@ ebtablesGetSubChainInsts(virHashTablePtr chains,
size_t *ninsts)
{
g_autofree virHashKeyValuePairPtr filter_names = NULL;
+ size_t nfilter_names;
size_t i;
- filter_names = virHashGetItems(chains,
- ebiptablesFilterOrderSort);
+ filter_names = virHashGetItems(chains, &nfilter_names, false);
if (filter_names == NULL)
return -1;
+ qsort(filter_names, nfilter_names, sizeof(*filter_names),
ebiptablesFilterOrderSort);
+
for (i = 0; filter_names[i].key; i++) {
g_autofree ebtablesSubChainInstPtr inst = NULL;
enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername(
diff --git a/src/qemu/qemu_interop_config.c b/src/qemu/qemu_interop_config.c
index e1c20aff11..c8b81c59a8 100644
--- a/src/qemu/qemu_interop_config.c
+++ b/src/qemu/qemu_interop_config.c
@@ -79,13 +79,6 @@ qemuBuildFileList(virHashTablePtr files, const char *dir)
return 0;
}
-static int
-qemuConfigFilesSorter(const virHashKeyValuePair *a,
- const virHashKeyValuePair *b)
-{
- return strcmp(a->key, b->key);
-}
-
#define QEMU_SYSTEM_LOCATION PREFIX "/share/qemu"
#define QEMU_ETC_LOCATION SYSCONFDIR "/qemu"
@@ -141,7 +134,7 @@ qemuInteropFetchConfigs(const char *name,
if (virHashSize(files) == 0)
return 0;
- if (!(pairs = virHashGetItems(files, qemuConfigFilesSorter)))
+ if (!(pairs = virHashGetItems(files, NULL, true)))
return -1;
for (tmp = pairs; tmp->key; tmp++) {
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
index ce13f0d927..525cbb3ce6 100644
--- a/src/rpc/virnetdaemon.c
+++ b/src/rpc/virnetdaemon.c
@@ -378,15 +378,6 @@ virNetDaemonNewPostExecRestart(virJSONValuePtr object,
}
-static int
-daemonServerCompare(const virHashKeyValuePair *a, const virHashKeyValuePair *b)
-{
- const char *as = a->key;
- const char *bs = b->key;
-
- return strcmp(as, bs);
-}
-
virJSONValuePtr
virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
{
@@ -402,7 +393,7 @@ virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
goto error;
}
- if (!(srvArray = virHashGetItems(dmn->servers, daemonServerCompare)))
+ if (!(srvArray = virHashGetItems(dmn->servers, NULL, true)))
goto error;
for (i = 0; srvArray[i].key; i++) {
diff --git a/src/util/virhash.c b/src/util/virhash.c
index b30db8a87a..f644990712 100644
--- a/src/util/virhash.c
+++ b/src/util/virhash.c
@@ -626,49 +626,63 @@ void *virHashSearch(const virHashTable *ctable,
return NULL;
}
-struct getKeysIter
-{
- virHashKeyValuePair *sortArray;
- size_t arrayIdx;
+
+struct virHashGetItemsIteratorData {
+ virHashKeyValuePair *items;
+ size_t i;
};
-static int virHashGetKeysIterator(void *payload,
- const char *key, void *data)
+
+static int
+virHashGetItemsIterator(void *payload,
+ const char *key,
+ void *opaque)
{
- struct getKeysIter *iter = data;
+ struct virHashGetItemsIteratorData *data = opaque;
- iter->sortArray[iter->arrayIdx].key = key;
- iter->sortArray[iter->arrayIdx].value = payload;
+ data->items[data->i].key = key;
+ data->items[data->i].value = payload;
- iter->arrayIdx++;
+ data->i++;
return 0;
}
-typedef int (*qsort_comp)(const void *, const void *);
-virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
- virHashKeyComparator compar)
+static int
+virHashGetItemsKeySorter(const void *va,
+ const void *vb)
{
- ssize_t numElems = virHashSize(table);
- struct getKeysIter iter = {
- .arrayIdx = 0,
- .sortArray = NULL,
- };
+ const virHashKeyValuePair *a = va;
+ const virHashKeyValuePair *b = vb;
- if (numElems < 0)
- return NULL;
+ return strcmp(a->key, b->key);
+}
+
+
+virHashKeyValuePairPtr
+virHashGetItems(virHashTablePtr table,
+ size_t *nitems,
+ bool sortKeys)
+{
+ size_t dummy;
+ struct virHashGetItemsIteratorData data = { .items = NULL, .i = 0 };
- iter.sortArray = g_new0(virHashKeyValuePair, numElems + 1);
+ if (!nitems)
+ nitems = &dummy;
- virHashForEach(table, virHashGetKeysIterator, &iter);
+ *nitems = virHashSize(table);
- if (compar)
- qsort(&iter.sortArray[0], numElems, sizeof(iter.sortArray[0]),
- (qsort_comp)compar);
+ data.items = g_new0(virHashKeyValuePair, *nitems + 1);
- return iter.sortArray;
+ virHashForEach(table, virHashGetItemsIterator, &data);
+
+ if (sortKeys)
+ qsort(data.items, *nitems, sizeof(* data.items), virHashGetItemsKeySorter);
+
+ return data.items;
}
+
struct virHashEqualData
{
bool equal;
diff --git a/src/util/virhash.h b/src/util/virhash.h
index b2ea5c9a96..688e1adf4d 100644
--- a/src/util/virhash.h
+++ b/src/util/virhash.h
@@ -116,10 +116,9 @@ struct _virHashKeyValuePair {
const void *key;
const void *value;
};
-typedef int (*virHashKeyComparator)(const virHashKeyValuePair *,
- const virHashKeyValuePair *);
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
- virHashKeyComparator compar);
+ size_t *nitems,
+ bool sortedKeys);
/*
* Compare two tables for equality: the lookup of a key's value in
diff --git a/src/util/virlockspace.c b/src/util/virlockspace.c
index 2731d46dfc..d39f2c026f 100644
--- a/src/util/virlockspace.c
+++ b/src/util/virlockspace.c
@@ -435,7 +435,7 @@ virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace)
goto error;
}
- tmp = pairs = virHashGetItems(lockspace->resources, NULL);
+ tmp = pairs = virHashGetItems(lockspace->resources, NULL, false);
while (tmp && tmp->value) {
virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value;
virJSONValuePtr child = virJSONValueNewObject();
diff --git a/tests/virhashtest.c b/tests/virhashtest.c
index 8cc3109929..93949d8b7a 100644
--- a/tests/virhashtest.c
+++ b/tests/virhashtest.c
@@ -361,13 +361,6 @@ testHashSearch(const void *data G_GNUC_UNUSED)
}
-static int
-testHashGetItemsCompKey(const virHashKeyValuePair *a,
- const virHashKeyValuePair *b)
-{
- return strcmp(a->key, b->key);
-}
-
static int
testHashGetItems(const void *data G_GNUC_UNUSED)
{
@@ -389,14 +382,14 @@ testHashGetItems(const void *data G_GNUC_UNUSED)
goto cleanup;
}
- if (!(array = virHashGetItems(hash, NULL)) ||
+ if (!(array = virHashGetItems(hash, NULL, false)) ||
array[3].key || array[3].value) {
VIR_TEST_VERBOSE("\nfailed to get items with NULL sort");
goto cleanup;
}
VIR_FREE(array);
- if (!(array = virHashGetItems(hash, testHashGetItemsCompKey)) ||
+ if (!(array = virHashGetItems(hash, NULL, true)) ||
STRNEQ(array[0].key, "a") ||
STRNEQ(array[0].value, "3") ||
STRNEQ(array[1].key, "b") ||
--
2.26.2