[libvirt] [PATCH 2/2] Allow hash tables to use generic pointers as keys

Daniel P. Berrange berrange at redhat.com
Thu Feb 24 13:24:32 UTC 2011


Relax the restriction that the hash table key must be a string
by allowing an arbitrary hash code generator + comparison func
to be provided

* util/hash.c, util/hash.h: Allow any pointer as a key
* internal.h: Include stdbool.h as standard.
* conf/domain_conf.c, conf/domain_conf.c,
  conf/nwfilter_params.c, nwfilter/nwfilter_gentech_driver.c,
  nwfilter/nwfilter_gentech_driver.h, nwfilter/nwfilter_learnipaddr.c,
  qemu/qemu_command.c, qemu/qemu_driver.c,
  qemu/qemu_process.c, uml/uml_driver.c,
  xen/xm_internal.c: s/char */void */ in hash callbacks
---
 src/conf/domain_conf.c                 |   30 ++++----
 src/conf/nwfilter_params.c             |   14 ++--
 src/lxc/lxc_driver.c                   |    4 +-
 src/nwfilter/nwfilter_gentech_driver.c |    2 +-
 src/nwfilter/nwfilter_gentech_driver.h |    2 +-
 src/nwfilter/nwfilter_learnipaddr.c    |    4 +-
 src/qemu/qemu_command.c                |    2 +-
 src/qemu/qemu_driver.c                 |    8 +-
 src/qemu/qemu_process.c                |    4 +-
 src/uml/uml_driver.c                   |    4 +-
 src/util/hash.c                        |  115 ++++++++++++++++++++++++--------
 src/util/hash.h                        |   69 ++++++++++++++++---
 src/xen/xm_internal.c                  |    8 +-
 13 files changed, 185 insertions(+), 81 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6270cc7..e3037fb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -392,7 +392,7 @@ VIR_ENUM_IMPL(virDomainTimerMode, VIR_DOMAIN_TIMER_MODE_LAST,
 #define VIR_DOMAIN_XML_READ_FLAGS   VIR_DOMAIN_XML_INACTIVE
 
 static void
-virDomainObjListDeallocator(void *payload, const char *name ATTRIBUTE_UNUSED)
+virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
 {
     virDomainObjPtr obj = payload;
     virDomainObjLock(obj);
@@ -402,7 +402,7 @@ virDomainObjListDeallocator(void *payload, const char *name ATTRIBUTE_UNUSED)
 
 int virDomainObjListInit(virDomainObjListPtr doms)
 {
-    doms->objs = virHashCreate(50, virDomainObjListDeallocator);
+    doms->objs = virHashCreate(50, virDomainObjListDataFree);
     if (!doms->objs)
         return -1;
     return 0;
@@ -416,7 +416,7 @@ void virDomainObjListDeinit(virDomainObjListPtr doms)
 
 
 static int virDomainObjListSearchID(const void *payload,
-                                    const char *name ATTRIBUTE_UNUSED,
+                                    const void *name ATTRIBUTE_UNUSED,
                                     const void *data)
 {
     virDomainObjPtr obj = (virDomainObjPtr)payload;
@@ -457,7 +457,7 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms,
 }
 
 static int virDomainObjListSearchName(const void *payload,
-                                      const char *name ATTRIBUTE_UNUSED,
+                                      const void *name ATTRIBUTE_UNUSED,
                                       const void *data)
 {
     virDomainObjPtr obj = (virDomainObjPtr)payload;
@@ -8435,7 +8435,7 @@ void virDomainObjUnlock(virDomainObjPtr obj)
 }
 
 
-static void virDomainObjListCountActive(void *payload, const char *name ATTRIBUTE_UNUSED, void *data)
+static void virDomainObjListCountActive(void *payload, const void *name ATTRIBUTE_UNUSED, void *data)
 {
     virDomainObjPtr obj = payload;
     int *count = data;
@@ -8445,7 +8445,7 @@ static void virDomainObjListCountActive(void *payload, const char *name ATTRIBUT
     virDomainObjUnlock(obj);
 }
 
-static void virDomainObjListCountInactive(void *payload, const char *name ATTRIBUTE_UNUSED, void *data)
+static void virDomainObjListCountInactive(void *payload, const void *name ATTRIBUTE_UNUSED, void *data)
 {
     virDomainObjPtr obj = payload;
     int *count = data;
@@ -8471,7 +8471,7 @@ struct virDomainIDData {
     int *ids;
 };
 
-static void virDomainObjListCopyActiveIDs(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+static void virDomainObjListCopyActiveIDs(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr obj = payload;
     struct virDomainIDData *data = opaque;
@@ -8497,7 +8497,7 @@ struct virDomainNameData {
     char **const names;
 };
 
-static void virDomainObjListCopyInactiveNames(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+static void virDomainObjListCopyInactiveNames(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr obj = payload;
     struct virDomainNameData *data = opaque;
@@ -8753,8 +8753,8 @@ virDomainSnapshotObjPtr virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr s
 
 /* Snapshot Obj List functions */
 static void
-virDomainSnapshotObjListDeallocator(void *payload,
-                                    const char *name ATTRIBUTE_UNUSED)
+virDomainSnapshotObjListDataFree(void *payload,
+                                 const void *name ATTRIBUTE_UNUSED)
 {
     virDomainSnapshotObjPtr obj = payload;
 
@@ -8763,7 +8763,7 @@ virDomainSnapshotObjListDeallocator(void *payload,
 
 int virDomainSnapshotObjListInit(virDomainSnapshotObjListPtr snapshots)
 {
-    snapshots->objs = virHashCreate(50, virDomainSnapshotObjListDeallocator);
+    snapshots->objs = virHashCreate(50, virDomainSnapshotObjListDataFree);
     if (!snapshots->objs)
         return -1;
     return 0;
@@ -8783,7 +8783,7 @@ struct virDomainSnapshotNameData {
 };
 
 static void virDomainSnapshotObjListCopyNames(void *payload,
-                                              const char *name ATTRIBUTE_UNUSED,
+                                              const void *name ATTRIBUTE_UNUSED,
                                               void *opaque)
 {
     virDomainSnapshotObjPtr obj = payload;
@@ -8821,7 +8821,7 @@ cleanup:
 }
 
 static void virDomainSnapshotObjListCount(void *payload ATTRIBUTE_UNUSED,
-                                          const char *name ATTRIBUTE_UNUSED,
+                                          const void *name ATTRIBUTE_UNUSED,
                                           void *data)
 {
     int *count = data;
@@ -8839,7 +8839,7 @@ int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots)
 }
 
 static int virDomainSnapshotObjListSearchName(const void *payload,
-                                              const char *name ATTRIBUTE_UNUSED,
+                                              const void *name ATTRIBUTE_UNUSED,
                                               const void *data)
 {
     virDomainSnapshotObjPtr obj = (virDomainSnapshotObjPtr)payload;
@@ -8869,7 +8869,7 @@ struct snapshot_has_children {
 };
 
 static void virDomainSnapshotCountChildren(void *payload,
-                                           const char *name ATTRIBUTE_UNUSED,
+                                           const void *name ATTRIBUTE_UNUSED,
                                            void *data)
 {
     virDomainSnapshotObjPtr obj = payload;
diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c
index 729f455..211ff55 100644
--- a/src/conf/nwfilter_params.c
+++ b/src/conf/nwfilter_params.c
@@ -35,7 +35,7 @@
 #define VIR_FROM_THIS VIR_FROM_NWFILTER
 
 static void
-hashDealloc(void *payload, const char *name ATTRIBUTE_UNUSED)
+hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
 {
     VIR_FREE(payload);
 }
@@ -120,7 +120,7 @@ virNWFilterHashTableCreate(int n) {
         virReportOOMError();
         return NULL;
     }
-    ret->hashTable = virHashCreate(n, hashDealloc);
+    ret->hashTable = virHashCreate(n, hashDataFree);
     if (!ret->hashTable) {
         VIR_FREE(ret);
         return NULL;
@@ -157,7 +157,7 @@ struct addToTableStruct {
 
 
 static void
-addToTable(void *payload, const char *name, void *data)
+addToTable(void *payload, const void *name, void *data)
 {
     struct addToTableStruct *atts = (struct addToTableStruct *)data;
     char *val;
@@ -172,10 +172,10 @@ addToTable(void *payload, const char *name, void *data)
         return;
     }
 
-    if (virNWFilterHashTablePut(atts->target, name, val, 1) != 0) {
+    if (virNWFilterHashTablePut(atts->target, (const char *)name, val, 1) != 0) {
         virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Could not put variable '%s' into hashmap"),
-                               name);
+                               (const char *)name);
         atts->errOccurred = 1;
         VIR_FREE(val);
     }
@@ -265,13 +265,13 @@ struct formatterParam {
 
 
 static void
-_formatParameterAttrs(void *payload, const char *name, void *data)
+_formatParameterAttrs(void *payload, const void *name, void *data)
 {
     struct formatterParam *fp = (struct formatterParam *)data;
 
     virBufferVSprintf(fp->buf, "%s<parameter name='%s' value='%s'/>\n",
                       fp->indent,
-                      name,
+                      (const char *)name,
                       (char *)payload);
 }
 
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 70e74d5..5b6f784 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1967,7 +1967,7 @@ struct lxcAutostartData {
 };
 
 static void
-lxcAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+lxcAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr vm = payload;
     const struct lxcAutostartData *data = opaque;
@@ -2014,7 +2014,7 @@ lxcAutostartConfigs(lxc_driver_t *driver) {
 }
 
 static void
-lxcReconnectVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr vm = payload;
     lxc_driver_t *driver = opaque;
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index d81aac8..facad13 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -1012,7 +1012,7 @@ virNWFilterTeardownFilter(const virDomainNetDefPtr net)
 
 void
 virNWFilterDomainFWUpdateCB(void *payload,
-                            const char *name ATTRIBUTE_UNUSED,
+                            const void *name ATTRIBUTE_UNUSED,
                             void *data)
 {
     virDomainObjPtr obj = payload;
diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h
index 271bf85..fa86030 100644
--- a/src/nwfilter/nwfilter_gentech_driver.h
+++ b/src/nwfilter/nwfilter_gentech_driver.h
@@ -64,7 +64,7 @@ virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr,
                                                     char *ipaddr);
 
 void virNWFilterDomainFWUpdateCB(void *payload,
-                                 const char *name ATTRIBUTE_UNUSED,
+                                 const void *name,
                                  void *data);
 
 #endif
diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c
index 8f6263a..9ee439a 100644
--- a/src/nwfilter/nwfilter_learnipaddr.c
+++ b/src/nwfilter/nwfilter_learnipaddr.c
@@ -189,7 +189,7 @@ virNWFilterLockIface(const char *ifname) {
 
 
 static void
-freeIfaceLock(void *payload, const char *name ATTRIBUTE_UNUSED) {
+freeIfaceLock(void *payload, const void *name ATTRIBUTE_UNUSED) {
     VIR_FREE(payload);
 }
 
@@ -287,7 +287,7 @@ virNWFilterLookupLearnReq(int ifindex) {
 
 
 static void
-freeLearnReqEntry(void *payload, const char *name ATTRIBUTE_UNUSED) {
+freeLearnReqEntry(void *payload, const void *name ATTRIBUTE_UNUSED) {
     virNWFilterIPAddrLearnReqFree(payload);
 }
 
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4bf80d0..fa60abe 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -748,7 +748,7 @@ cleanup:
 
 static void
 qemuDomainPCIAddressSetFreeEntry(void *payload,
-                                 const char *name ATTRIBUTE_UNUSED)
+                                 const void *name ATTRIBUTE_UNUSED)
 {
     VIR_FREE(payload);
 }
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 102f780..0fe0bc8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -132,7 +132,7 @@ struct qemuAutostartData {
 };
 
 static void
-qemuAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr vm = payload;
     struct qemuAutostartData *data = opaque;
@@ -275,7 +275,7 @@ err_exit:
 }
 
 static void qemuDomainSnapshotLoad(void *payload,
-                                   const char *name ATTRIBUTE_UNUSED,
+                                   const void *name ATTRIBUTE_UNUSED,
                                    void *data)
 {
     virDomainObjPtr vm = (virDomainObjPtr)payload;
@@ -6508,7 +6508,7 @@ struct snap_remove {
 };
 
 static void qemuDomainSnapshotDiscardChildren(void *payload,
-                                              const char *name ATTRIBUTE_UNUSED,
+                                              const void *name ATTRIBUTE_UNUSED,
                                               void *data)
 {
     virDomainSnapshotObjPtr snap = payload;
@@ -6539,7 +6539,7 @@ struct snap_reparent {
 
 static void
 qemuDomainSnapshotReparentChildren(void *payload,
-                                   const char *name ATTRIBUTE_UNUSED,
+                                   const void *name ATTRIBUTE_UNUSED,
                                    void *data)
 {
     virDomainSnapshotObjPtr snap = payload;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7879165..c419c75 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -949,7 +949,7 @@ qemuProcessFindCharDevicePTYs(virDomainObjPtr vm,
     return 0;
 }
 
-static void qemuProcessFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED)
+static void qemuProcessFreePtyPath(void *payload, const void *name ATTRIBUTE_UNUSED)
 {
     VIR_FREE(payload);
 }
@@ -1783,7 +1783,7 @@ struct qemuProcessReconnectData {
  * and re-reserve the security labels in use
  */
 static void
-qemuProcessReconnect(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr obj = payload;
     struct qemuProcessReconnectData *data = opaque;
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 2af8002..7cacadb 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -149,7 +149,7 @@ struct umlAutostartData {
 };
 
 static void
-umlAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+umlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr vm = payload;
     const struct umlAutostartData *data = opaque;
@@ -508,7 +508,7 @@ umlActive(void) {
 }
 
 static void
-umlShutdownOneVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
+umlShutdownOneVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 {
     virDomainObjPtr dom = payload;
     struct uml_driver *driver = opaque;
diff --git a/src/util/hash.c b/src/util/hash.c
index c3c8b66..92ee234 100644
--- a/src/util/hash.c
+++ b/src/util/hash.c
@@ -42,7 +42,7 @@ typedef struct _virHashEntry virHashEntry;
 typedef virHashEntry *virHashEntryPtr;
 struct _virHashEntry {
     struct _virHashEntry *next;
-    char *name;
+    void *name;
     void *payload;
     int valid;
 };
@@ -55,39 +55,70 @@ struct _virHashTable {
     int size;
     int nbElems;
     virHashDataFree dataFree;
+    virHashKeyCode keyCode;
+    virHashKeyEqual keyEqual;
+    virHashKeyCopy keyCopy;
+    virHashKeyFree keyFree;
 };
 
-/*
- * virHashComputeKey:
- * Calculate the hash key
- */
-static unsigned long
-virHashComputeKey(virHashTablePtr table, const char *name)
+static unsigned long virHashStrCode(const void *name)
 {
+    const char *str = name;
     unsigned long value = 0L;
     char ch;
 
-    if (name != NULL) {
-        value += 30 * (*name);
-        while ((ch = *name++) != 0) {
+    if (str != NULL) {
+        value += 30 * (*str);
+        while ((ch = *str++) != 0) {
             value =
                 value ^ ((value << 5) + (value >> 3) + (unsigned long) ch);
         }
     }
+    return value;
+}
+
+static bool virHashStrEqual(const void *namea, const void *nameb)
+{
+    return STREQ(namea, nameb);
+}
+
+static void *virHashStrCopy(const void *name)
+{
+    return strdup(name);
+}
+
+static void virHashStrFree(void *name)
+{
+    VIR_FREE(name);
+}
+
+
+static unsigned long
+virHashComputeKey(virHashTablePtr table, const void *name)
+{
+    unsigned long value = table->keyCode(name);
     return (value % table->size);
 }
 
 /**
- * virHashCreate:
+ * virHashCreateFull:
  * @size: the size of the hash table
- * @dataFree: function to call on each entry during virHashFree
+ * @dataFree: callback to free data
+ * @keyCode: callback to compute hash code
+ * @keyEqual: callback to compare hash keys
+ * @keyCopy: callback to copy hash keys
+ * @keyFree: callback to free keys
  *
  * Create a new virHashTablePtr.
  *
  * Returns the newly created object, or NULL if an error occured.
  */
-virHashTablePtr
-virHashCreate(int size, virHashDataFree dataFree)
+virHashTablePtr virHashCreateFull(int size,
+                                  virHashDataFree dataFree,
+                                  virHashKeyCode keyCode,
+                                  virHashKeyEqual keyEqual,
+                                  virHashKeyCopy keyCopy,
+                                  virHashKeyFree keyFree)
 {
     virHashTablePtr table = NULL;
 
@@ -102,6 +133,11 @@ virHashCreate(int size, virHashDataFree dataFree)
     table->size = size;
     table->nbElems = 0;
     table->dataFree = dataFree;
+    table->keyCode = keyCode;
+    table->keyEqual = keyEqual;
+    table->keyCopy = keyCopy;
+    table->keyFree = keyFree;
+
     if (VIR_ALLOC_N(table->table, size) < 0) {
         virReportOOMError();
         VIR_FREE(table);
@@ -111,6 +147,26 @@ virHashCreate(int size, virHashDataFree dataFree)
     return table;
 }
 
+
+/**
+ * virHashCreate:
+ * @size: the size of the hash table
+ * @dataFree: callback to free data
+ *
+ * Create a new virHashTablePtr.
+ *
+ * Returns the newly created object, or NULL if an error occured.
+ */
+virHashTablePtr virHashCreate(int size, virHashDataFree dataFree)
+{
+    return virHashCreateFull(size,
+                             dataFree,
+                             virHashStrCode,
+                             virHashStrEqual,
+                             virHashStrCopy,
+                             virHashStrFree);
+}
+
 /**
  * virHashGrow:
  * @table: the hash table
@@ -231,7 +287,8 @@ virHashFree(virHashTablePtr table)
                 next = iter->next;
                 if ((table->dataFree != NULL) && (iter->payload != NULL))
                     table->dataFree(iter->payload, iter->name);
-                VIR_FREE(iter->name);
+                if (table->keyFree)
+                    table->keyFree(iter->name);
                 iter->payload = NULL;
                 if (!inside_table)
                     VIR_FREE(iter);
@@ -269,13 +326,13 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name,
     } else {
         for (insert = &(table->table[key]); insert->next != NULL;
              insert = insert->next) {
-            if (STREQ(insert->name, name)) {
+            if (table->keyEqual(insert->name, name)) {
                 found = true;
                 break;
             }
             len++;
         }
-        if (STREQ(insert->name, name))
+        if (table->keyEqual(insert->name, name))
             found = true;
     }
 
@@ -299,7 +356,7 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name,
         }
     }
 
-    new_name = strdup(name);
+    new_name = table->keyCopy(name);
     if (new_name == NULL) {
         virReportOOMError();
         if (insert != NULL)
@@ -334,7 +391,7 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name,
  * Returns 0 the addition succeeded and -1 in case of error.
  */
 int
-virHashAddEntry(virHashTablePtr table, const char *name, void *userdata)
+virHashAddEntry(virHashTablePtr table, const void *name, void *userdata)
 {
     return virHashAddOrUpdateEntry(table, name, userdata, false);
 }
@@ -352,7 +409,7 @@ virHashAddEntry(virHashTablePtr table, const char *name, void *userdata)
  * Returns 0 the addition succeeded and -1 in case of error.
  */
 int
-virHashUpdateEntry(virHashTablePtr table, const char *name,
+virHashUpdateEntry(virHashTablePtr table, const void *name,
                    void *userdata)
 {
     return virHashAddOrUpdateEntry(table, name, userdata, true);
@@ -363,12 +420,12 @@ virHashUpdateEntry(virHashTablePtr table, const char *name,
  * @table: the hash table
  * @name: the name of the userdata
  *
- * Find the userdata specified by the (@name, @name2, @name3) tuple.
+ * Find the userdata specified by @name
  *
  * Returns the a pointer to the userdata
  */
 void *
-virHashLookup(virHashTablePtr table, const char *name)
+virHashLookup(virHashTablePtr table, const void *name)
 {
     unsigned long key;
     virHashEntryPtr entry;
@@ -381,7 +438,7 @@ virHashLookup(virHashTablePtr table, const char *name)
     if (table->table[key].valid == 0)
         return (NULL);
     for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
-        if (STREQ(entry->name, name))
+        if (table->keyEqual(entry->name, name))
             return (entry->payload);
     }
     return (NULL);
@@ -398,7 +455,7 @@ virHashLookup(virHashTablePtr table, const char *name)
  *
  * Returns the a pointer to the userdata
  */
-void *virHashSteal(virHashTablePtr table, const char *name)
+void *virHashSteal(virHashTablePtr table, const void *name)
 {
     void *data = virHashLookup(table, name);
     if (data) {
@@ -440,7 +497,7 @@ virHashSize(virHashTablePtr table)
  * Returns 0 if the removal succeeded and -1 in case of error or not found.
  */
 int
-virHashRemoveEntry(virHashTablePtr table, const char *name)
+virHashRemoveEntry(virHashTablePtr table, const void *name)
 {
     unsigned long key;
     virHashEntryPtr entry;
@@ -455,11 +512,12 @@ virHashRemoveEntry(virHashTablePtr table, const char *name)
     } else {
         for (entry = &(table->table[key]); entry != NULL;
              entry = entry->next) {
-            if (STREQ(entry->name, name)) {
+            if (table->keyEqual(entry->name, name)) {
                 if (table->dataFree && (entry->payload != NULL))
                     table->dataFree(entry->payload, entry->name);
                 entry->payload = NULL;
-                VIR_FREE(entry->name);
+                if (table->keyFree)
+                    table->keyFree(entry->name);
                 if (prev) {
                     prev->next = entry->next;
                     VIR_FREE(entry);
@@ -544,7 +602,8 @@ int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *da
                 count++;
                 if (table->dataFree)
                     table->dataFree(entry->payload, entry->name);
-                VIR_FREE(entry->name);
+                if (table->keyFree)
+                    table->keyFree(entry->name);
                 table->nbElems--;
                 if (prev) {
                     prev->next = entry->next;
diff --git a/src/util/hash.h b/src/util/hash.h
index 1147f46..44ac1fb 100644
--- a/src/util/hash.h
+++ b/src/util/hash.h
@@ -29,33 +29,78 @@ typedef virHashTable *virHashTablePtr;
  *
  * Callback to free data from a hash.
  */
-typedef void (*virHashDataFree) (void *payload, const char *name);
+typedef void (*virHashDataFree) (void *payload, const void *name);
 /**
  * virHashIterator:
  * @payload: the data in the hash
- * @name: the name associated
+ * @name: the hash key
  * @data: user supplied data blob
  *
  * Callback to process a hash entry during iteration
  */
-typedef void (*virHashIterator) (void *payload, const char *name, void *data);
+typedef void (*virHashIterator) (void *payload, const void *name, void *data);
 /**
- * virHashSearcher
+ * virHashSearcher:
  * @payload: the data in the hash
- * @name: the name associated
+ * @name: the hash key
  * @data: user supplied data blob
  *
  * Callback to identify hash entry desired
  * Returns 1 if the hash entry is desired, 0 to move
  * to next entry
  */
-typedef int (*virHashSearcher) (const void *payload, const char *name,
+typedef int (*virHashSearcher) (const void *payload, const void *name,
                                 const void *data);
 
+/**
+ * virHashKeyCode:
+ * @name: the hash key
+ *
+ * Compute the hash code corresponding to the key @name
+ *
+ * Returns the hash code
+ */
+typedef unsigned long (*virHashKeyCode)(const void *name);
+/**
+ * virHashKeyEqual:
+ * @namea: the first hash key
+ * @nameb: the second hash key
+ *
+ * Compare two hash keys for equality
+ *
+ * Returns true if the keys are equal, false otherwise
+ */
+typedef bool (*virHashKeyEqual)(const void *namea, const void *nameb);
+/**
+ * virHashKeyCopy:
+ * @name: the hash key
+ *
+ * Create a copy of the hash key, duplicating
+ * memory allocation where applicable
+ *
+ * Returns a newly allocated copy of @name
+ */
+typedef void *(*virHashKeyCopy)(const void *name);
+/**
+ * virHashKeyFree:
+ * @name: the hash key
+ *
+ * Free any memory associated with the hash
+ * key @name
+ */
+typedef void (*virHashKeyFree)(void *name);
+
 /*
  * Constructor and destructor.
  */
-virHashTablePtr virHashCreate(int size, virHashDataFree dataFree);
+virHashTablePtr virHashCreate(int size,
+                              virHashDataFree dataFree);
+virHashTablePtr virHashCreateFull(int size,
+                                  virHashDataFree dataFree,
+                                  virHashKeyCode keyCode,
+                                  virHashKeyEqual keyEqual,
+                                  virHashKeyCopy keyCopy,
+                                  virHashKeyFree keyFree);
 void virHashFree(virHashTablePtr table);
 int virHashSize(virHashTablePtr table);
 
@@ -63,26 +108,26 @@ int virHashSize(virHashTablePtr table);
  * Add a new entry to the hash table.
  */
 int virHashAddEntry(virHashTablePtr table,
-                    const char *name, void *userdata);
+                    const void *name, void *userdata);
 int virHashUpdateEntry(virHashTablePtr table,
-                       const char *name,
+                       const void *name,
                        void *userdata);
 
 /*
  * Remove an entry from the hash table.
  */
 int virHashRemoveEntry(virHashTablePtr table,
-                       const char *name);
+                       const void *name);
 
 /*
  * Retrieve the userdata.
  */
-void *virHashLookup(virHashTablePtr table, const char *name);
+void *virHashLookup(virHashTablePtr table, const void *name);
 
 /*
  * Retrieve & remove the userdata.
  */
-void *virHashSteal(virHashTablePtr table, const char *name);
+void *virHashSteal(virHashTablePtr table, const void *name);
 
 
 /*
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 62e1068..7f73588 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -139,7 +139,7 @@ static int xenInotifyActive(virConnectPtr conn)
 
 
 /* Release memory associated with a cached config object */
-static void xenXMConfigFree(void *payload, const char *key ATTRIBUTE_UNUSED) {
+static void xenXMConfigFree(void *payload, const void *key ATTRIBUTE_UNUSED) {
     xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
     virDomainDefFree(entry->def);
     VIR_FREE(entry);
@@ -151,7 +151,7 @@ struct xenXMConfigReaperData {
 };
 
 /* Remove any configs which were not refreshed recently */
-static int xenXMConfigReaper(const void *payload, const char *key ATTRIBUTE_UNUSED, const void *data) {
+static int xenXMConfigReaper(const void *payload, const void *key ATTRIBUTE_UNUSED, const void *data) {
     const struct xenXMConfigReaperData *args = data;
     xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
 
@@ -938,7 +938,7 @@ cleanup:
 /*
  * Hash table iterator to search for a domain based on UUID
  */
-static int xenXMDomainSearchForUUID(const void *payload, const char *name ATTRIBUTE_UNUSED, const void *data) {
+static int xenXMDomainSearchForUUID(const void *payload, const void *name ATTRIBUTE_UNUSED, const void *data) {
     const unsigned char *wantuuid = (const unsigned char *)data;
     const xenXMConfCachePtr entry = (const xenXMConfCachePtr)payload;
 
@@ -1235,7 +1235,7 @@ struct xenXMListIteratorContext {
     char ** names;
 };
 
-static void xenXMListIterator(void *payload ATTRIBUTE_UNUSED, const char *name, void *data) {
+static void xenXMListIterator(void *payload ATTRIBUTE_UNUSED, const void *name, void *data) {
     struct xenXMListIteratorContext *ctx = data;
     virDomainPtr dom = NULL;
 
-- 
1.7.4




More information about the libvir-list mailing list