util: hash: Rewrite sorting of elements in virHashGetItems

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@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-22 17:38:53 +02:00
parent 6e29698037
commit 4eb8e9ae8b
10 changed files with 63 additions and 76 deletions

View File

@ -755,13 +755,6 @@ virNWFilterParseParamAttributes(xmlNodePtr cur)
} }
static int
virNWFilterFormatParameterNameSorter(const virHashKeyValuePair *a,
const virHashKeyValuePair *b)
{
return strcmp(a->key, b->key);
}
int int
virNWFilterFormatParamAttributes(virBufferPtr buf, virNWFilterFormatParamAttributes(virBufferPtr buf,
virHashTablePtr table, virHashTablePtr table,
@ -779,8 +772,7 @@ virNWFilterFormatParamAttributes(virBufferPtr buf,
return -1; return -1;
} }
items = virHashGetItems(table, items = virHashGetItems(table, NULL, true);
virNWFilterFormatParameterNameSorter);
if (!items) if (!items)
return -1; return -1;

View File

@ -681,7 +681,7 @@ hypervSerializeEmbeddedParam(hypervParamPtr p, const char *resourceUri,
/* retrieve parameters out of hash table */ /* retrieve parameters out of hash table */
numKeys = virHashSize(p->embedded.table); numKeys = virHashSize(p->embedded.table);
items = virHashGetItems(p->embedded.table, NULL); items = virHashGetItems(p->embedded.table, NULL, false);
if (!items) { if (!items) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not read embedded param hash table")); _("Could not read embedded param hash table"));

View File

@ -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) { while (tmp && tmp->key) {
virLockSpacePtr lockspace = (virLockSpacePtr)tmp->value; virLockSpacePtr lockspace = (virLockSpacePtr)tmp->value;

View File

@ -3126,9 +3126,12 @@ virNWFilterRuleInstSortPtr(const void *a, const void *b)
static int static int
ebiptablesFilterOrderSort(const virHashKeyValuePair *a, ebiptablesFilterOrderSort(const void *va,
const virHashKeyValuePair *b) const void *vb)
{ {
const virHashKeyValuePair *a = va;
const virHashKeyValuePair *b = vb;
/* elements' values has been limited to range [-1000, 1000] */ /* elements' values has been limited to range [-1000, 1000] */
return *(virNWFilterChainPriority *)a->value - return *(virNWFilterChainPriority *)a->value -
*(virNWFilterChainPriority *)b->value; *(virNWFilterChainPriority *)b->value;
@ -3288,13 +3291,15 @@ ebtablesGetSubChainInsts(virHashTablePtr chains,
size_t *ninsts) size_t *ninsts)
{ {
g_autofree virHashKeyValuePairPtr filter_names = NULL; g_autofree virHashKeyValuePairPtr filter_names = NULL;
size_t nfilter_names;
size_t i; size_t i;
filter_names = virHashGetItems(chains, filter_names = virHashGetItems(chains, &nfilter_names, false);
ebiptablesFilterOrderSort);
if (filter_names == NULL) if (filter_names == NULL)
return -1; return -1;
qsort(filter_names, nfilter_names, sizeof(*filter_names), ebiptablesFilterOrderSort);
for (i = 0; filter_names[i].key; i++) { for (i = 0; filter_names[i].key; i++) {
g_autofree ebtablesSubChainInstPtr inst = NULL; g_autofree ebtablesSubChainInstPtr inst = NULL;
enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername( enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername(

View File

@ -79,13 +79,6 @@ qemuBuildFileList(virHashTablePtr files, const char *dir)
return 0; 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_SYSTEM_LOCATION PREFIX "/share/qemu"
#define QEMU_ETC_LOCATION SYSCONFDIR "/qemu" #define QEMU_ETC_LOCATION SYSCONFDIR "/qemu"
@ -141,7 +134,7 @@ qemuInteropFetchConfigs(const char *name,
if (virHashSize(files) == 0) if (virHashSize(files) == 0)
return 0; return 0;
if (!(pairs = virHashGetItems(files, qemuConfigFilesSorter))) if (!(pairs = virHashGetItems(files, NULL, true)))
return -1; return -1;
for (tmp = pairs; tmp->key; tmp++) { for (tmp = pairs; tmp->key; tmp++) {

View File

@ -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 virJSONValuePtr
virNetDaemonPreExecRestart(virNetDaemonPtr dmn) virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
{ {
@ -402,7 +393,7 @@ virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
goto error; goto error;
} }
if (!(srvArray = virHashGetItems(dmn->servers, daemonServerCompare))) if (!(srvArray = virHashGetItems(dmn->servers, NULL, true)))
goto error; goto error;
for (i = 0; srvArray[i].key; i++) { for (i = 0; srvArray[i].key; i++) {

View File

@ -626,49 +626,63 @@ void *virHashSearch(const virHashTable *ctable,
return NULL; return NULL;
} }
struct getKeysIter
{ struct virHashGetItemsIteratorData {
virHashKeyValuePair *sortArray; virHashKeyValuePair *items;
size_t arrayIdx; 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; data->items[data->i].key = key;
iter->sortArray[iter->arrayIdx].value = payload; data->items[data->i].value = payload;
iter->arrayIdx++; data->i++;
return 0; return 0;
} }
typedef int (*qsort_comp)(const void *, const void *);
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table, static int
virHashKeyComparator compar) virHashGetItemsKeySorter(const void *va,
const void *vb)
{ {
ssize_t numElems = virHashSize(table); const virHashKeyValuePair *a = va;
struct getKeysIter iter = { const virHashKeyValuePair *b = vb;
.arrayIdx = 0,
.sortArray = NULL,
};
if (numElems < 0) return strcmp(a->key, b->key);
return NULL;
iter.sortArray = g_new0(virHashKeyValuePair, numElems + 1);
virHashForEach(table, virHashGetKeysIterator, &iter);
if (compar)
qsort(&iter.sortArray[0], numElems, sizeof(iter.sortArray[0]),
(qsort_comp)compar);
return iter.sortArray;
} }
virHashKeyValuePairPtr
virHashGetItems(virHashTablePtr table,
size_t *nitems,
bool sortKeys)
{
size_t dummy;
struct virHashGetItemsIteratorData data = { .items = NULL, .i = 0 };
if (!nitems)
nitems = &dummy;
*nitems = virHashSize(table);
data.items = g_new0(virHashKeyValuePair, *nitems + 1);
virHashForEach(table, virHashGetItemsIterator, &data);
if (sortKeys)
qsort(data.items, *nitems, sizeof(* data.items), virHashGetItemsKeySorter);
return data.items;
}
struct virHashEqualData struct virHashEqualData
{ {
bool equal; bool equal;

View File

@ -116,10 +116,9 @@ struct _virHashKeyValuePair {
const void *key; const void *key;
const void *value; const void *value;
}; };
typedef int (*virHashKeyComparator)(const virHashKeyValuePair *,
const virHashKeyValuePair *);
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table, virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
virHashKeyComparator compar); size_t *nitems,
bool sortedKeys);
/* /*
* Compare two tables for equality: the lookup of a key's value in * Compare two tables for equality: the lookup of a key's value in

View File

@ -435,7 +435,7 @@ virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace)
goto error; goto error;
} }
tmp = pairs = virHashGetItems(lockspace->resources, NULL); tmp = pairs = virHashGetItems(lockspace->resources, NULL, false);
while (tmp && tmp->value) { while (tmp && tmp->value) {
virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value; virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value;
virJSONValuePtr child = virJSONValueNewObject(); virJSONValuePtr child = virJSONValueNewObject();

View File

@ -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 static int
testHashGetItems(const void *data G_GNUC_UNUSED) testHashGetItems(const void *data G_GNUC_UNUSED)
{ {
@ -389,14 +382,14 @@ testHashGetItems(const void *data G_GNUC_UNUSED)
goto cleanup; goto cleanup;
} }
if (!(array = virHashGetItems(hash, NULL)) || if (!(array = virHashGetItems(hash, NULL, false)) ||
array[3].key || array[3].value) { array[3].key || array[3].value) {
VIR_TEST_VERBOSE("\nfailed to get items with NULL sort"); VIR_TEST_VERBOSE("\nfailed to get items with NULL sort");
goto cleanup; goto cleanup;
} }
VIR_FREE(array); VIR_FREE(array);
if (!(array = virHashGetItems(hash, testHashGetItemsCompKey)) || if (!(array = virHashGetItems(hash, NULL, true)) ||
STRNEQ(array[0].key, "a") || STRNEQ(array[0].key, "a") ||
STRNEQ(array[0].value, "3") || STRNEQ(array[0].value, "3") ||
STRNEQ(array[1].key, "b") || STRNEQ(array[1].key, "b") ||