2
* hash.c: chained hash tables for domain and domain/connection deallocations
4
* Reference: Your favorite introductory book on algorithms
6
* Copyright (C) 2011 Red Hat, Inc.
7
* Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
9
* Permission to use, copy, modify, and distribute this software for any
10
* purpose with or without fee is hereby granted, provided that the above
11
* copyright notice and this permission notice appear in all copies.
13
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
14
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
15
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
16
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
18
* Author: breese@users.sourceforge.net
19
* Daniel Veillard <veillard@redhat.com>
27
#include "virterror_internal.h"
32
#define VIR_FROM_THIS VIR_FROM_NONE
34
#define MAX_HASH_LEN 8
36
/* #define DEBUG_GROW */
38
#define virHashIterationError(ret) \
40
VIR_ERROR(_("Hash operation not allowed during iteration")); \
45
* A single entry in the hash table
47
typedef struct _virHashEntry virHashEntry;
48
typedef virHashEntry *virHashEntryPtr;
49
struct _virHashEntry {
50
struct _virHashEntry *next;
56
* The entire hash table
58
struct _virHashTable {
59
virHashEntryPtr *table;
62
/* True iff we are iterating over hash entries. */
64
/* Pointer to the current entry during iteration. */
65
virHashEntryPtr current;
66
virHashDataFree dataFree;
67
virHashKeyCode keyCode;
68
virHashKeyEqual keyEqual;
69
virHashKeyCopy keyCopy;
70
virHashKeyFree keyFree;
73
static unsigned long virHashStrCode(const void *name)
75
const char *str = name;
76
unsigned long value = 0L;
81
while ((ch = *str++) != 0) {
83
value ^ ((value << 5) + (value >> 3) + (unsigned long) ch);
89
static bool virHashStrEqual(const void *namea, const void *nameb)
91
return STREQ(namea, nameb);
94
static void *virHashStrCopy(const void *name)
99
static void virHashStrFree(void *name)
106
virHashComputeKey(virHashTablePtr table, const void *name)
108
unsigned long value = table->keyCode(name);
109
return (value % table->size);
114
* @size: the size of the hash table
115
* @dataFree: callback to free data
116
* @keyCode: callback to compute hash code
117
* @keyEqual: callback to compare hash keys
118
* @keyCopy: callback to copy hash keys
119
* @keyFree: callback to free keys
121
* Create a new virHashTablePtr.
123
* Returns the newly created object, or NULL if an error occurred.
125
virHashTablePtr virHashCreateFull(int size,
126
virHashDataFree dataFree,
127
virHashKeyCode keyCode,
128
virHashKeyEqual keyEqual,
129
virHashKeyCopy keyCopy,
130
virHashKeyFree keyFree)
132
virHashTablePtr table = NULL;
137
if (VIR_ALLOC(table) < 0) {
144
table->dataFree = dataFree;
145
table->keyCode = keyCode;
146
table->keyEqual = keyEqual;
147
table->keyCopy = keyCopy;
148
table->keyFree = keyFree;
150
if (VIR_ALLOC_N(table->table, size) < 0) {
162
* @size: the size of the hash table
163
* @dataFree: callback to free data
165
* Create a new virHashTablePtr.
167
* Returns the newly created object, or NULL if an error occurred.
169
virHashTablePtr virHashCreate(int size, virHashDataFree dataFree)
171
return virHashCreateFull(size,
181
* @table: the hash table
182
* @size: the new size of the hash table
184
* resize the hash table
186
* Returns 0 in case of success, -1 in case of failure
189
virHashGrow(virHashTablePtr table, int size)
192
virHashEntryPtr *oldtable;
195
unsigned long nbElem = 0;
205
oldsize = table->size;
206
oldtable = table->table;
207
if (oldtable == NULL)
210
if (VIR_ALLOC_N(table->table, size) < 0) {
212
table->table = oldtable;
217
for (i = 0; i < oldsize; i++) {
218
virHashEntryPtr iter = oldtable[i];
220
virHashEntryPtr next = iter->next;
221
unsigned long key = virHashComputeKey(table, iter->name);
223
iter->next = table->table[key];
224
table->table[key] = iter;
236
VIR_DEBUG("virHashGrow : from %d to %d, %ld elems\n", oldsize,
245
* @table: the hash table
247
* Free the hash @table and its contents. The userdata is
248
* deallocated with function provided at creation time.
251
virHashFree(virHashTablePtr table)
258
for (i = 0; i < table->size; i++) {
259
virHashEntryPtr iter = table->table[i];
261
virHashEntryPtr next = iter->next;
264
table->dataFree(iter->payload, iter->name);
266
table->keyFree(iter->name);
272
VIR_FREE(table->table);
277
virHashAddOrUpdateEntry(virHashTablePtr table, const void *name,
281
unsigned long key, len = 0;
282
virHashEntryPtr entry;
285
if ((table == NULL) || (name == NULL))
288
if (table->iterating)
289
virHashIterationError(-1);
291
key = virHashComputeKey(table, name);
293
/* Check for duplicate entry */
294
for (entry = table->table[key]; entry; entry = entry->next) {
295
if (table->keyEqual(entry->name, name)) {
298
table->dataFree(entry->payload, entry->name);
299
entry->payload = userdata;
308
if (VIR_ALLOC(entry) < 0 || !(new_name = table->keyCopy(name))) {
314
entry->name = new_name;
315
entry->payload = userdata;
316
entry->next = table->table[key];
317
table->table[key] = entry;
321
if (len > MAX_HASH_LEN)
322
virHashGrow(table, MAX_HASH_LEN * table->size);
329
* @table: the hash table
330
* @name: the name of the userdata
331
* @userdata: a pointer to the userdata
333
* Add the @userdata to the hash @table. This can later be retrieved
334
* by using @name. Duplicate entries generate errors.
336
* Returns 0 the addition succeeded and -1 in case of error.
339
virHashAddEntry(virHashTablePtr table, const void *name, void *userdata)
341
return virHashAddOrUpdateEntry(table, name, userdata, false);
345
* virHashUpdateEntry:
346
* @table: the hash table
347
* @name: the name of the userdata
348
* @userdata: a pointer to the userdata
350
* Add the @userdata to the hash @table. This can later be retrieved
351
* by using @name. Existing entry for this tuple
352
* will be removed and freed with @f if found.
354
* Returns 0 the addition succeeded and -1 in case of error.
357
virHashUpdateEntry(virHashTablePtr table, const void *name,
360
return virHashAddOrUpdateEntry(table, name, userdata, true);
365
* @table: the hash table
366
* @name: the name of the userdata
368
* Find the userdata specified by @name
370
* Returns the a pointer to the userdata
373
virHashLookup(virHashTablePtr table, const void *name)
376
virHashEntryPtr entry;
381
key = virHashComputeKey(table, name);
382
for (entry = table->table[key]; entry; entry = entry->next) {
383
if (table->keyEqual(entry->name, name))
384
return entry->payload;
392
* @table: the hash table
393
* @name: the name of the userdata
395
* Find the userdata specified by @name
396
* and remove it from the hash without freeing it.
398
* Returns the a pointer to the userdata
400
void *virHashSteal(virHashTablePtr table, const void *name)
402
void *data = virHashLookup(table, name);
404
virHashDataFree dataFree = table->dataFree;
405
table->dataFree = NULL;
406
virHashRemoveEntry(table, name);
407
table->dataFree = dataFree;
415
* @table: the hash table
417
* Query the number of elements installed in the hash @table.
419
* Returns the number of elements in the hash table or
420
* -1 in case of error
423
virHashSize(virHashTablePtr table)
427
return (table->nbElems);
432
* @table: the hash table
434
* Query the size of the hash @table, i.e., number of buckets in the table.
436
* Returns the number of keys in the hash table or
437
* -1 in case of error
440
virHashTableSize(virHashTablePtr table)
449
* virHashRemoveEntry:
450
* @table: the hash table
451
* @name: the name of the userdata
453
* Find the userdata specified by the @name and remove
454
* it from the hash @table. Existing userdata for this tuple will be removed
457
* Returns 0 if the removal succeeded and -1 in case of error or not found.
460
virHashRemoveEntry(virHashTablePtr table, const void *name)
462
virHashEntryPtr entry;
463
virHashEntryPtr *nextptr;
465
if (table == NULL || name == NULL)
468
nextptr = table->table + virHashComputeKey(table, name);
469
for (entry = *nextptr; entry; entry = entry->next) {
470
if (table->keyEqual(entry->name, name)) {
471
if (table->iterating && table->current != entry)
472
virHashIterationError(-1);
475
table->dataFree(entry->payload, entry->name);
477
table->keyFree(entry->name);
478
*nextptr = entry->next;
483
nextptr = &entry->next;
492
* @table: the hash table to process
493
* @iter: callback to process each element
494
* @data: opaque data to pass to the iterator
496
* Iterates over every element in the hash table, invoking the
497
* 'iter' callback. The callback is allowed to remove the current element
498
* using virHashRemoveEntry but calling other virHash* functions is prohibited.
500
* Returns number of items iterated over upon completion, -1 on failure
502
int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data)
506
if (table == NULL || iter == NULL)
509
if (table->iterating)
510
virHashIterationError(-1);
512
table->iterating = true;
513
table->current = NULL;
514
for (i = 0 ; i < table->size ; i++) {
515
virHashEntryPtr entry = table->table[i];
517
virHashEntryPtr next = entry->next;
519
table->current = entry;
520
iter(entry->payload, entry->name, data);
521
table->current = NULL;
527
table->iterating = false;
534
* @table: the hash table to process
535
* @iter: callback to identify elements for removal
536
* @data: opaque data to pass to the iterator
538
* Iterates over all elements in the hash table, invoking the 'iter'
539
* callback. If the callback returns a non-zero value, the element
540
* will be removed from the hash table & its payload passed to the
541
* data freer callback registered at creation.
543
* Returns number of items removed on success, -1 on failure
545
int virHashRemoveSet(virHashTablePtr table,
546
virHashSearcher iter,
551
if (table == NULL || iter == NULL)
554
if (table->iterating)
555
virHashIterationError(-1);
557
table->iterating = true;
558
table->current = NULL;
559
for (i = 0 ; i < table->size ; i++) {
560
virHashEntryPtr *nextptr = table->table + i;
563
virHashEntryPtr entry = *nextptr;
564
if (!iter(entry->payload, entry->name, data)) {
565
nextptr = &entry->next;
569
table->dataFree(entry->payload, entry->name);
571
table->keyFree(entry->name);
572
*nextptr = entry->next;
578
table->iterating = false;
585
* @table: the hash table to search
586
* @iter: an iterator to identify the desired element
587
* @data: extra opaque information passed to the iter
589
* Iterates over the hash table calling the 'iter' callback
590
* for each element. The first element for which the iter
591
* returns non-zero will be returned by this function.
592
* The elements are processed in a undefined order
594
void *virHashSearch(virHashTablePtr table,
595
virHashSearcher iter,
600
if (table == NULL || iter == NULL)
603
if (table->iterating)
604
virHashIterationError(NULL);
606
table->iterating = true;
607
table->current = NULL;
608
for (i = 0 ; i < table->size ; i++) {
609
virHashEntryPtr entry;
610
for (entry = table->table[i]; entry; entry = entry->next) {
611
if (iter(entry->payload, entry->name, data)) {
612
table->iterating = false;
613
return entry->payload;
617
table->iterating = false;
624
virHashKeyValuePair *sortArray;
628
static void virHashGetKeysIterator(void *payload,
629
const void *key, void *data)
631
struct getKeysIter *iter = data;
633
iter->sortArray[iter->arrayIdx].key = key;
634
iter->sortArray[iter->arrayIdx].value = payload;
639
typedef int (*qsort_comp)(const void *, const void *);
641
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
642
virHashKeyComparator compar)
644
int numElems = virHashSize(table);
645
struct getKeysIter iter = {
653
if (VIR_ALLOC_N(iter.sortArray, numElems + 1)) {
658
virHashForEach(table, virHashGetKeysIterator, &iter);
661
qsort(&iter.sortArray[0], numElems, sizeof(iter.sortArray[0]),
664
return iter.sortArray;