]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Refactor isc_hashmap to accept custom match function
authorOndřej Surý <ondrej@isc.org>
Mon, 28 Aug 2023 08:08:59 +0000 (10:08 +0200)
committerOndřej Surý <ondrej@isc.org>
Sat, 16 Sep 2023 05:20:48 +0000 (07:20 +0200)
Refactor isc_hashmap to allow custom matching functions.  This allows us
to have better tailored keys that don't require fixed uint8_t arrays,
but can be composed of more fields from the stored data structure.

lib/dns/adb.c
lib/dns/resolver.c
lib/dns/transport.c
lib/dns/tsig.c
lib/dns/zone.c
lib/isc/hashmap.c
lib/isc/include/isc/hashmap.h
tests/bench/load-names.c
tests/isc/hashmap_test.c

index fb99b4cf868979a7283993d4b1ef6920576b8d55..beab25b57d8664f474e8fec8ff34cb0e0d7fdd17 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <isc/async.h>
 #include <isc/atomic.h>
+#include <isc/hash.h>
 #include <isc/hashmap.h>
 #include <isc/list.h>
 #include <isc/loop.h>
@@ -127,18 +128,6 @@ struct dns_adb {
        double atr_discount;
 };
 
-typedef struct adbnamekey adbnamekey_t;
-struct adbnamekey {
-       size_t size;
-       union {
-               struct {
-                       bool start_at_zone;
-                       uint8_t name[DNS_NAME_MAXWIRE];
-               };
-               char key[sizeof(bool) + DNS_NAME_MAXWIRE];
-       };
-} __attribute__((__packed__));
-
 /*%
  * dns_adbname structure:
  *
@@ -152,9 +141,8 @@ struct dns_adbname {
        unsigned int magic;
        isc_refcount_t references;
        dns_adb_t *adb;
-       isc_buffer_t buffer;
-       adbnamekey_t key;
-       dns_name_t name;
+       dns_fixedname_t fname;
+       dns_name_t *name;
        unsigned int partial_result;
        unsigned int flags;
        dns_name_t target;
@@ -308,6 +296,10 @@ static dns_adbname_t *
 new_adbname(dns_adb_t *adb, const dns_name_t *, bool start_at_zone);
 static void
 destroy_adbname(dns_adbname_t *);
+static bool
+match_adbname(void *node, const void *key);
+static uint32_t
+hash_adbname(const dns_adbname_t *adbname);
 static dns_adbnamehook_t *
 new_adbnamehook(dns_adb_t *adb);
 static void
@@ -320,6 +312,8 @@ static dns_adbentry_t *
 new_adbentry(dns_adb_t *adb, const isc_sockaddr_t *addr);
 static void
 destroy_adbentry(dns_adbentry_t *entry);
+static bool
+match_adbentry(void *node, const void *key);
 static dns_adbfind_t *
 new_adbfind(dns_adb_t *, in_port_t);
 static void
@@ -682,6 +676,11 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
        return (ISC_R_SUCCESS);
 }
 
+static bool
+match_ptr(void *node, const void *key) {
+       return (node == key);
+}
+
 /*
  * Requires the name to be locked.
  */
@@ -720,8 +719,8 @@ expire_name(dns_adbname_t *adbname, dns_adbstatus_t astat) {
        /*
         * Remove the adbname from the hashtable...
         */
-       result = isc_hashmap_delete(adb->names, NULL, &adbname->key.key,
-                                   adbname->key.size);
+       result = isc_hashmap_delete(adb->names, hash_adbname(adbname),
+                                   match_ptr, adbname);
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
        /* ... and LRU list */
        ISC_LIST_UNLINK(adb->names_lru, adbname, link);
@@ -1018,16 +1017,12 @@ new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
 
        isc_mutex_init(&name->lock);
 
-       dns_name_init(&name->name, NULL);
-       isc_buffer_init(&name->buffer, name->key.name, DNS_NAME_MAXWIRE);
-       dns_name_setbuffer(&name->name, &name->buffer);
-       dns_name_copy(dnsname, &name->name);
+       name->name = dns_fixedname_initname(&name->fname);
+       dns_name_copy(dnsname, name->name);
        dns_name_init(&name->target, NULL);
 
-       name->key.size = dnsname->length + sizeof(bool);
        if (start_at_zone) {
                name->flags |= DNS_ADBFIND_STARTATZONE;
-               name->key.start_at_zone = true;
        }
 
        inc_adbstats(adb, dns_adbstats_namescnt);
@@ -1320,6 +1315,32 @@ free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
        isc_mem_put(adb->mctx, ai, sizeof(*ai));
 }
 
+static bool
+match_adbname(void *node, const void *key) {
+       const dns_adbname_t *adbname0 = node;
+       const dns_adbname_t *adbname1 = key;
+
+       if ((adbname0->flags & DNS_ADBFIND_STARTATZONE) !=
+           (adbname1->flags & DNS_ADBFIND_STARTATZONE))
+       {
+               return (false);
+       }
+
+       return (dns_name_equal(adbname0->name, adbname1->name));
+}
+
+static uint32_t
+hash_adbname(const dns_adbname_t *adbname) {
+       isc_hash32_t hash;
+       bool start_at_zone = adbname->flags & DNS_ADBFIND_STARTATZONE;
+
+       isc_hash32_init(&hash);
+       isc_hash32_hash(&hash, adbname->name->ndata, adbname->name->length,
+                       false);
+       isc_hash32_hash(&hash, &start_at_zone, sizeof(start_at_zone), true);
+       return (isc_hash32_finalize(&hash));
+}
+
 /*
  * Search for the name in the hash table.
  */
@@ -1328,20 +1349,17 @@ get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
                             bool start_at_zone, isc_stdtime_t now) {
        isc_result_t result;
        dns_adbname_t *adbname = NULL;
-       uint32_t hashval;
        isc_time_t timenow;
        isc_stdtime_t last_update;
-       adbnamekey_t key;
+       dns_adbname_t key = {
+               .name = UNCONST(name),
+               .flags = (start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0,
+       };
+       uint32_t hashval = hash_adbname(&key);
        isc_rwlocktype_t locktype = isc_rwlocktype_read;
 
        isc_time_set(&timenow, now, 0);
 
-       key.start_at_zone = start_at_zone;
-       memmove(&key.name, name->ndata, name->length);
-       key.size = name->length + sizeof(bool);
-
-       hashval = isc_hashmap_hash(adb->names, &key.key, key.size);
-
        RWLOCK(&adb->names_lock, locktype);
        last_update = adb->names_last_update;
 
@@ -1354,8 +1372,8 @@ get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
                adb->names_last_update = last_update;
        }
 
-       result = isc_hashmap_find(adb->names, &hashval, key.key, key.size,
-                                 (void **)&adbname);
+       result = isc_hashmap_find(adb->names, hashval, match_adbname,
+                                 (void *)&key, (void **)&adbname);
        switch (result) {
        case ISC_R_NOTFOUND:
                UPGRADELOCK(&adb->names_lock, locktype);
@@ -1363,14 +1381,13 @@ get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
                /* Allocate a new name and add it to the hash table. */
                adbname = new_adbname(adb, name, start_at_zone);
 
-               result = isc_hashmap_add(adb->names, &hashval,
-                                        &adbname->key.key, adbname->key.size,
-                                        adbname);
+               void *found = NULL;
+               result = isc_hashmap_add(adb->names, hashval, match_adbname,
+                                        (void *)&key, adbname, &found);
                if (result == ISC_R_EXISTS) {
                        destroy_adbname(adbname);
-                       adbname = NULL;
-                       result = isc_hashmap_find(adb->names, &hashval, key.key,
-                                                 key.size, (void **)&adbname);
+                       adbname = found;
+                       result = ISC_R_SUCCESS;
                        ISC_LIST_UNLINK(adb->names_lru, adbname, link);
                }
                INSIST(result == ISC_R_SUCCESS);
@@ -1415,6 +1432,13 @@ upgrade_entries_lock(dns_adb_t *adb, isc_rwlocktype_t *locktypep,
        }
 }
 
+static bool
+match_adbentry(void *node, const void *key) {
+       dns_adbentry_t *adbentry = node;
+
+       return (isc_sockaddr_equal(&adbentry->sockaddr, key));
+}
+
 /*
  * Find the entry in the adb->entries hashtable.
  */
@@ -1425,8 +1449,7 @@ get_attached_and_locked_entry(dns_adb_t *adb, isc_stdtime_t now,
        dns_adbentry_t *adbentry = NULL;
        isc_time_t timenow;
        isc_stdtime_t last_update;
-       uint32_t hashval = isc_hashmap_hash(
-               adb->entries, (const unsigned char *)addr, sizeof(*addr));
+       uint32_t hashval = isc_sockaddr_hash(addr, true);
        isc_rwlocktype_t locktype = isc_rwlocktype_read;
 
        isc_time_set(&timenow, now, 0);
@@ -1442,8 +1465,8 @@ get_attached_and_locked_entry(dns_adb_t *adb, isc_stdtime_t now,
                upgrade_entries_lock(adb, &locktype, now);
        }
 
-       result = isc_hashmap_find(adb->entries, &hashval,
-                                 (const unsigned char *)addr, sizeof(*addr),
+       result = isc_hashmap_find(adb->entries, hashval, match_adbentry,
+                                 (const unsigned char *)addr,
                                  (void **)&adbentry);
        if (result == ISC_R_NOTFOUND) {
                upgrade_entries_lock(adb, &locktype, now);
@@ -1454,18 +1477,15 @@ get_attached_and_locked_entry(dns_adb_t *adb, isc_stdtime_t now,
                /* Allocate a new entry and add it to the hash table. */
                adbentry = new_adbentry(adb, addr);
 
-               result = isc_hashmap_add(adb->entries, &hashval,
-                                        &adbentry->sockaddr,
-                                        sizeof(adbentry->sockaddr), adbentry);
+               void *found = NULL;
+               result = isc_hashmap_add(adb->entries, hashval, match_adbentry,
+                                        &adbentry->sockaddr, adbentry, &found);
                if (result == ISC_R_SUCCESS) {
                        ISC_LIST_PREPEND(adb->entries_lru, adbentry, link);
                } else if (result == ISC_R_EXISTS) {
                        dns_adbentry_detach(&adbentry);
-
-                       result = isc_hashmap_find(adb->entries, &hashval,
-                                                 (const unsigned char *)addr,
-                                                 sizeof(*addr),
-                                                 (void **)&adbentry);
+                       adbentry = found;
+                       result = ISC_R_SUCCESS;
                }
        }
        INSIST(result == ISC_R_SUCCESS);
@@ -1684,9 +1704,10 @@ expire_entry(dns_adbentry_t *adbentry) {
        if (!ENTRY_DEAD(adbentry)) {
                adbentry->flags |= ENTRY_IS_DEAD;
 
-               result = isc_hashmap_delete(adb->entries, NULL,
-                                           &adbentry->sockaddr,
-                                           sizeof(adbentry->sockaddr));
+               result = isc_hashmap_delete(
+                       adb->entries,
+                       isc_sockaddr_hash(&adbentry->sockaddr, true), match_ptr,
+                       adbentry);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
                ISC_LIST_UNLINK(adb->entries_lru, adbentry, link);
        }
@@ -1992,12 +2013,10 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_loopmgr_t *loopmgr,
        isc_mem_create(&adb->hmctx);
        isc_mem_setname(adb->hmctx, "ADB_hashmaps");
 
-       isc_hashmap_create(adb->hmctx, ADB_HASH_BITS,
-                          ISC_HASHMAP_CASE_INSENSITIVE, &adb->names);
+       isc_hashmap_create(adb->hmctx, ADB_HASH_BITS, &adb->names);
        isc_rwlock_init(&adb->names_lock);
 
-       isc_hashmap_create(adb->hmctx, ADB_HASH_BITS,
-                          ISC_HASHMAP_CASE_SENSITIVE, &adb->entries);
+       isc_hashmap_create(adb->hmctx, ADB_HASH_BITS, &adb->entries);
        isc_rwlock_init(&adb->entries_lock);
 
        isc_mutex_init(&adb->lock);
@@ -2506,7 +2525,7 @@ dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) {
                                name->flags);
                }
                fprintf(f, "; ");
-               dns_name_print(&name->name, f);
+               dns_name_print(name->name, f);
                if (dns_name_countlabels(&name->target) > 0) {
                        fprintf(f, " alias ");
                        dns_name_print(&name->target, f);
@@ -2786,7 +2805,7 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) {
         * the configuration on which server we should send queries to.
         */
        result = dns_view_find(
-               adb->view, &adbname->name, rdtype, now, DNS_DBFIND_GLUEOK, true,
+               adb->view, adbname->name, rdtype, now, DNS_DBFIND_GLUEOK, true,
                ((adbname->flags & DNS_ADBFIND_STARTATZONE) != 0), NULL, NULL,
                fname, &rdataset, NULL);
 
@@ -2873,7 +2892,7 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) {
                rdataset.ttl = ttlclamp(rdataset.ttl);
                clean_target(adb, &adbname->target);
                adbname->expire_target = INT_MAX;
-               result = set_target(adb, &adbname->name, fname, &rdataset,
+               result = set_target(adb, adbname->name, fname, &rdataset,
                                    &adbname->target);
                if (result == ISC_R_SUCCESS) {
                        result = DNS_R_ALIAS;
@@ -2997,7 +3016,7 @@ fetch_callback(void *arg) {
                resp->rdataset->ttl = ttlclamp(resp->rdataset->ttl);
                clean_target(adb, &name->target);
                name->expire_target = INT_MAX;
-               result = set_target(adb, &name->name, resp->foundname,
+               result = set_target(adb, name->name, resp->foundname,
                                    resp->rdataset, &name->target);
                if (result == ISC_R_SUCCESS) {
                        DP(NCACHE_LEVEL,
@@ -3014,7 +3033,7 @@ fetch_callback(void *arg) {
        if (resp->result != ISC_R_SUCCESS) {
                char buf[DNS_NAME_FORMATSIZE];
 
-               dns_name_format(&name->name, buf, sizeof(buf));
+               dns_name_format(name->name, buf, sizeof(buf));
                DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", buf,
                   address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
                   isc_result_totext(resp->result));
@@ -3095,7 +3114,7 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth,
                DP(ENTER_LEVEL, "fetch_name: starting at zone for name %p",
                   adbname);
                name = dns_fixedname_initname(&fixed);
-               result = dns_view_findzonecut(adb->view, &adbname->name, name,
+               result = dns_view_findzonecut(adb->view, adbname->name, name,
                                              NULL, 0, 0, true, false,
                                              &rdataset, NULL);
                if (result != ISC_R_SUCCESS && result != DNS_R_HINT) {
@@ -3116,8 +3135,8 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth,
         * domain and nameservers.
         */
        result = dns_resolver_createfetch(
-               adb->res, &adbname->name, type, name, nameservers, NULL, NULL,
-               0, options, depth, qc, isc_loop_current(adb->loopmgr),
+               adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0,
+               options, depth, qc, isc_loop_current(adb->loopmgr),
                fetch_callback, adbname, &fetch->rdataset, NULL, &fetch->fetch);
        if (result != ISC_R_SUCCESS) {
                DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s",
@@ -3579,7 +3598,7 @@ dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
        dns_adbname_t *adbname = NULL;
        isc_result_t result;
        bool start_at_zone = false;
-       adbnamekey_t key;
+       dns_adbname_t key = { .name = UNCONST(name) };
 
        REQUIRE(DNS_ADB_VALID(adb));
        REQUIRE(name != NULL);
@@ -3593,16 +3612,14 @@ again:
        /*
         * Delete both entries - without and with DNS_ADBFIND_STARTATZONE set.
         */
-       key.start_at_zone = start_at_zone;
-       memmove(&key.name, name->ndata, name->length);
-       key.size = name->length + sizeof(bool);
+       key.flags = (start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0;
 
-       result = isc_hashmap_find(adb->names, NULL, key.key, key.size,
-                                 (void **)&adbname);
+       result = isc_hashmap_find(adb->names, hash_adbname(&key), match_adbname,
+                                 (void *)&key, (void **)&adbname);
        if (result == ISC_R_SUCCESS) {
                dns_adbname_ref(adbname);
                LOCK(&adbname->lock);
-               if (dns_name_equal(name, &adbname->name)) {
+               if (dns_name_equal(name, adbname->name)) {
                        expire_name(adbname, DNS_ADB_CANCELED);
                }
                UNLOCK(&adbname->lock);
@@ -3633,7 +3650,7 @@ dns_adb_flushnames(dns_adb_t *adb, const dns_name_t *name) {
                next = ISC_LIST_NEXT(adbname, link);
                dns_adbname_ref(adbname);
                LOCK(&adbname->lock);
-               if (dns_name_issubdomain(&adbname->name, name)) {
+               if (dns_name_issubdomain(adbname->name, name)) {
                        expire_name(adbname, DNS_ADB_CANCELED);
                }
                UNLOCK(&adbname->lock);
index 94b78a91e211273e9f61ef0182844da12c004ba4..c21513dda8d91aff90cdde6f7f99e2eb7e4208aa 100644 (file)
@@ -305,20 +305,6 @@ typedef enum {
        badns_forwarder,
 } badnstype_t;
 
-typedef struct fctxkey fctxkey_t;
-struct fctxkey {
-       size_t size;
-       union {
-               struct {
-                       unsigned int options; /* 32 bits */
-                       dns_rdatatype_t type; /* 16 bits */
-                       uint8_t name[DNS_NAME_MAXWIRE];
-               };
-               char key[sizeof(unsigned int) + sizeof(dns_rdatatype_t) +
-                        DNS_NAME_MAXWIRE];
-       };
-} __attribute__((__packed__));
-
 #define FCTXCOUNT_MAGIC                 ISC_MAGIC('F', 'C', 'n', 't')
 #define VALID_FCTXCOUNT(counter) ISC_MAGIC_VALID(counter, FCTXCOUNT_MAGIC)
 
@@ -343,7 +329,6 @@ struct fetchctx {
        dns_name_t *name;
        dns_rdatatype_t type;
        unsigned int options;
-       fctxkey_t key;
        fctxcount_t *counter;
        char *info;
        isc_mem_t *mctx;
@@ -1401,6 +1386,14 @@ fcount_logspill(fetchctx_t *fctx, fctxcount_t *counter, bool final) {
        counter->logged = now;
 }
 
+static bool
+fcount_match(void *node, const void *key) {
+       const fctxcount_t *counter = node;
+       const dns_name_t *domain = key;
+
+       return (dns_name_equal(counter->domain, domain));
+}
+
 static isc_result_t
 fcount_incr(fetchctx_t *fctx, bool force) {
        isc_result_t result = ISC_R_SUCCESS;
@@ -1420,12 +1413,11 @@ fcount_incr(fetchctx_t *fctx, bool force) {
                return (ISC_R_SUCCESS);
        }
 
-       hashval = isc_hashmap_hash(res->counters, fctx->domain->ndata,
-                                  fctx->domain->length);
+       hashval = dns_name_hash(fctx->domain);
 
        RWLOCK(&res->counters_lock, locktype);
-       result = isc_hashmap_find(res->counters, &hashval, fctx->domain->ndata,
-                                 fctx->domain->length, (void **)&counter);
+       result = isc_hashmap_find(res->counters, hashval, fcount_match,
+                                 fctx->domain, (void **)&counter);
        switch (result) {
        case ISC_R_SUCCESS:
                break;
@@ -1443,17 +1435,15 @@ fcount_incr(fetchctx_t *fctx, bool force) {
 
                UPGRADELOCK(&res->counters_lock, locktype);
 
-               result = isc_hashmap_add(res->counters, &hashval,
-                                        counter->domain->ndata,
-                                        counter->domain->length, counter);
+               void *found = NULL;
+               result = isc_hashmap_add(res->counters, hashval, fcount_match,
+                                        counter->domain, counter, &found);
                if (result == ISC_R_EXISTS) {
                        isc_mutex_destroy(&counter->lock);
                        isc_mem_putanddetach(&counter->mctx, counter,
                                             sizeof(*counter));
-                       counter = NULL;
-                       result = isc_hashmap_find(
-                               res->counters, &hashval, fctx->domain->ndata,
-                               fctx->domain->length, (void **)&counter);
+                       counter = found;
+                       result = ISC_R_SUCCESS;
                }
 
                INSIST(result == ISC_R_SUCCESS);
@@ -1481,6 +1471,11 @@ fcount_incr(fetchctx_t *fctx, bool force) {
        return (result);
 }
 
+static bool
+match_ptr(void *node, const void *key) {
+       return (node == key);
+}
+
 static void
 fcount_decr(fetchctx_t *fctx) {
        REQUIRE(fctx != NULL);
@@ -1508,9 +1503,9 @@ fcount_decr(fetchctx_t *fctx) {
                return;
        }
 
-       isc_result_t result = isc_hashmap_delete(fctx->res->counters, NULL,
-                                                counter->domain->ndata,
-                                                counter->domain->length);
+       isc_result_t result = isc_hashmap_delete(fctx->res->counters,
+                                                dns_name_hash(counter->domain),
+                                                match_ptr, counter);
        INSIST(result == ISC_R_SUCCESS);
 
        fcount_logspill(fctx, counter, true);
@@ -4523,8 +4518,6 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
                .fwdpolicy = dns_fwdpolicy_none,
                .result = ISC_R_FAILURE,
                .loop = loop,
-               .key = { .size = sizeof(unsigned int) +
-                                sizeof(dns_rdatatype_t) + name->length },
        };
 
        isc_mem_attach(mctx, &fctx->mctx);
@@ -4532,10 +4525,6 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
 
        isc_mutex_init(&fctx->lock);
 
-       fctx->key.options = options;
-       fctx->key.type = type;
-       isc_ascii_lowercopy(fctx->key.name, name->ndata, name->length);
-
        if (qc != NULL) {
                isc_counter_attach(qc, &fctx->qc);
        } else {
@@ -6999,21 +6988,39 @@ ISC_REFCOUNT_TRACE_IMPL(fetchctx, fctx_destroy);
 ISC_REFCOUNT_IMPL(fetchctx, fctx_destroy);
 #endif
 
+static uint32_t
+fctx_hash(fetchctx_t *fctx) {
+       isc_hash32_t hash32;
+       isc_hash32_init(&hash32);
+       isc_hash32_hash(&hash32, fctx->name->ndata, fctx->name->length, false);
+       isc_hash32_hash(&hash32, &fctx->options, sizeof(fctx->options), true);
+       isc_hash32_hash(&hash32, &fctx->type, sizeof(fctx->type), true);
+       return (isc_hash32_finalize(&hash32));
+}
+
+static bool
+fctx_match(void *node, const void *key) {
+       const fetchctx_t *fctx0 = node;
+       const fetchctx_t *fctx1 = key;
+
+       return (fctx0->options == fctx1->options &&
+               fctx0->type == fctx1->type &&
+               dns_name_equal(fctx0->name, fctx1->name));
+}
+
 /* Must be fctx locked */
 static void
 release_fctx(fetchctx_t *fctx) {
        isc_result_t result;
        dns_resolver_t *res = fctx->res;
-       uint32_t hashval = isc_hashmap_hash(res->fctxs, fctx->key.key,
-                                           fctx->key.size);
 
        if (!fctx->hashed) {
                return;
        }
 
        RWLOCK(&res->fctxs_lock, isc_rwlocktype_write);
-       result = isc_hashmap_delete(res->fctxs, &hashval, fctx->key.key,
-                                   fctx->key.size);
+       result = isc_hashmap_delete(res->fctxs, fctx_hash(fctx), match_ptr,
+                                   fctx);
        INSIST(result == ISC_R_SUCCESS);
        fctx->hashed = false;
        RWUNLOCK(&res->fctxs_lock, isc_rwlocktype_write);
@@ -9974,13 +9981,10 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
 
        res->badcache = dns_badcache_new(res->mctx);
 
-       /* This needs to be case sensitive to not lowercase options and type */
-       isc_hashmap_create(view->mctx, RES_DOMAIN_HASH_BITS,
-                          ISC_HASHMAP_CASE_SENSITIVE, &res->fctxs);
+       isc_hashmap_create(view->mctx, RES_DOMAIN_HASH_BITS, &res->fctxs);
        isc_rwlock_init(&res->fctxs_lock);
 
-       isc_hashmap_create(view->mctx, RES_DOMAIN_HASH_BITS,
-                          ISC_HASHMAP_CASE_INSENSITIVE, &res->counters);
+       isc_hashmap_create(view->mctx, RES_DOMAIN_HASH_BITS, &res->counters);
        isc_rwlock_init(&res->counters_lock);
 
        if (dispatchv4 != NULL) {
@@ -10294,34 +10298,23 @@ get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
                  unsigned int options, unsigned int depth, isc_counter_t *qc,
                  fetchctx_t **fctxp, bool *new_fctx) {
        isc_result_t result;
-       uint32_t hashval;
-       fctxkey_t key = {
-               .size = sizeof(unsigned int) + sizeof(dns_rdatatype_t) +
-                       name->length,
+       fetchctx_t key = {
+               .name = UNCONST(name),
+               .options = options,
+               .type = type,
        };
        fetchctx_t *fctx = NULL;
        isc_rwlocktype_t locktype = isc_rwlocktype_read;
-
-       STATIC_ASSERT(sizeof(key.options) == sizeof(options),
-                     "key options size mismatch");
-       STATIC_ASSERT(sizeof(key.type) == sizeof(type),
-                     "key type size mismatch");
-
-       key.options = options;
-       key.type = type;
-       isc_ascii_lowercopy(key.name, name->ndata, name->length);
-
-       hashval = isc_hashmap_hash(res->fctxs, key.key, key.size);
+       uint32_t hashval = fctx_hash(&key);
 
 again:
        RWLOCK(&res->fctxs_lock, locktype);
-       result = isc_hashmap_find(res->fctxs, &hashval, key.key, key.size,
+       result = isc_hashmap_find(res->fctxs, hashval, fctx_match, &key,
                                  (void **)&fctx);
        switch (result) {
        case ISC_R_SUCCESS:
                break;
        case ISC_R_NOTFOUND:
-               /* FIXME: pass key to fctx_create(?) */
                result = fctx_create(res, loop, name, type, domain, nameservers,
                                     client, options, depth, qc, &fctx);
                if (result != ISC_R_SUCCESS) {
@@ -10329,15 +10322,17 @@ again:
                }
 
                UPGRADELOCK(&res->fctxs_lock, locktype);
-               result = isc_hashmap_add(res->fctxs, &hashval, fctx->key.key,
-                                        fctx->key.size, fctx);
+
+               void *found = NULL;
+               result = isc_hashmap_add(res->fctxs, hashval, fctx_match, fctx,
+                                        fctx, &found);
                if (result == ISC_R_SUCCESS) {
                        *new_fctx = true;
                        fctx->hashed = true;
                } else {
                        fctx_done_detach(&fctx, result);
-                       result = isc_hashmap_find(res->fctxs, &hashval, key.key,
-                                                 key.size, (void **)&fctx);
+                       fctx = found;
+                       result = ISC_R_SUCCESS;
                }
                INSIST(result == ISC_R_SUCCESS);
                break;
index f961f6a3b8079a3c35d102e32435bdfb5934b164..010bff7de010a5c93d88d972d4f62e22809fe0c7 100644 (file)
@@ -67,6 +67,13 @@ struct dns_transport {
        } doh;
 };
 
+static bool
+transport_match(void *node, const void *key) {
+       dns_transport_t *transport = node;
+
+       return (dns_name_equal(transport->name, key));
+}
+
 static isc_result_t
 list_add(dns_transport_list_t *list, const dns_name_t *name,
         const dns_transport_type_t type, dns_transport_t *transport) {
@@ -79,8 +86,8 @@ list_add(dns_transport_list_t *list, const dns_name_t *name,
 
        transport->name = dns_fixedname_initname(&transport->fn);
        dns_name_copy(name, transport->name);
-       result = isc_hashmap_add(hm, NULL, transport->name->ndata,
-                                transport->name->length, transport);
+       result = isc_hashmap_add(hm, dns_name_hash(name), transport_match, name,
+                                transport, NULL);
        RWUNLOCK(&list->lock, isc_rwlocktype_write);
 
        return (result);
@@ -631,8 +638,8 @@ dns_transport_find(const dns_transport_type_t type, const dns_name_t *name,
        hm = list->transports[type];
 
        RWLOCK(&list->lock, isc_rwlocktype_read);
-       result = isc_hashmap_find(hm, NULL, name->ndata, name->length,
-                                 (void **)&transport);
+       result = isc_hashmap_find(hm, dns_name_hash(name), transport_match,
+                                 name, (void **)&transport);
        if (result == ISC_R_SUCCESS) {
                isc_refcount_increment(&transport->references);
        }
@@ -655,8 +662,7 @@ dns_transport_list_new(isc_mem_t *mctx) {
        list->magic = TRANSPORT_LIST_MAGIC;
 
        for (size_t type = 0; type < DNS_TRANSPORT_COUNT; type++) {
-               isc_hashmap_create(list->mctx, 10, ISC_HASHMAP_CASE_INSENSITIVE,
-                                  &list->transports[type]);
+               isc_hashmap_create(list->mctx, 10, &list->transports[type]);
        }
 
        return (list);
index fbefeb3ba4b11ffcfe3c6dbed4a1d308b2c042d4..8b03b2dba68b284fd556c2d62d568898862a9ad4 100644 (file)
@@ -154,13 +154,25 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
        }
 }
 
+static bool
+tkey_match(void *node, const void *key) {
+       dns_tsigkey_t *tkey = node;
+
+       return (dns_name_equal(tkey->name, key));
+}
+
+static bool
+match_ptr(void *node, const void *key) {
+       return (node == key);
+}
+
 static void
 rm_hashmap(dns_tsigkey_t *tkey) {
        REQUIRE(VALID_TSIGKEY(tkey));
        REQUIRE(VALID_TSIGKEYRING(tkey->ring));
 
-       (void)isc_hashmap_delete(tkey->ring->keys, NULL, tkey->name->ndata,
-                                tkey->name->length);
+       (void)isc_hashmap_delete(tkey->ring->keys, dns_name_hash(tkey->name),
+                                match_ptr, tkey);
        dns_tsigkey_detach(&tkey);
 }
 
@@ -1534,8 +1546,8 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name,
        REQUIRE(tsigkey != NULL && *tsigkey == NULL);
 
        RWLOCK(&ring->lock, isc_rwlocktype_read);
-       result = isc_hashmap_find(ring->keys, NULL, name->ndata, name->length,
-                                 (void **)&key);
+       result = isc_hashmap_find(ring->keys, dns_name_hash(name), tkey_match,
+                                 name, (void **)&key);
        if (result == ISC_R_NOTFOUND) {
                RWUNLOCK(&ring->lock, isc_rwlocktype_read);
                return (result);
@@ -1574,7 +1586,7 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsigkeyring_t **ringp) {
                .lru = ISC_LIST_INITIALIZER,
        };
 
-       isc_hashmap_create(mctx, 12, ISC_HASHMAP_CASE_INSENSITIVE, &ring->keys);
+       isc_hashmap_create(mctx, 12, &ring->keys);
        isc_rwlock_init(&ring->lock);
        isc_mem_attach(mctx, &ring->mctx);
        isc_refcount_init(&ring->references, 1);
@@ -1592,8 +1604,8 @@ dns_tsigkeyring_add(dns_tsigkeyring_t *ring, dns_tsigkey_t *tkey) {
        REQUIRE(tkey->ring == NULL);
 
        RWLOCK(&ring->lock, isc_rwlocktype_write);
-       result = isc_hashmap_add(ring->keys, NULL, tkey->name->ndata,
-                                tkey->name->length, tkey);
+       result = isc_hashmap_add(ring->keys, dns_name_hash(tkey->name),
+                                tkey_match, tkey->name, tkey, NULL);
        if (result == ISC_R_SUCCESS) {
                dns_tsigkey_ref(tkey);
                tkey->ring = ring;
index d65680b9ebb80c2935dac27799365dc974180202..9a87540586d490e6cac307dcb4da025b3415f8cb 100644 (file)
@@ -18121,8 +18121,7 @@ zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
 
        isc_mem_attach(zmgr->mctx, &mgmt->mctx);
        isc_rwlock_init(&mgmt->lock);
-       isc_hashmap_create(mgmt->mctx, DNS_KEYMGMT_HASH_BITS,
-                          ISC_HASHMAP_CASE_SENSITIVE, &mgmt->table);
+       isc_hashmap_create(mgmt->mctx, DNS_KEYMGMT_HASH_BITS, &mgmt->table);
 
        zmgr->keymgmt = mgmt;
 }
@@ -18144,6 +18143,13 @@ zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
        isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
 }
 
+static bool
+kfio_match(void *node, const void *key) {
+       const dns_keyfileio_t *kfio = node;
+
+       return (dns_name_equal(kfio->name, key));
+}
+
 static void
 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
                    dns_keyfileio_t **added) {
@@ -18161,8 +18167,8 @@ zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
 
        RWLOCK(&mgmt->lock, isc_rwlocktype_write);
 
-       result = isc_hashmap_find(mgmt->table, NULL, name->ndata, name->length,
-                                 (void **)&kfio);
+       result = isc_hashmap_find(mgmt->table, dns_name_hash(name), kfio_match,
+                                 name, (void **)&kfio);
        switch (result) {
        case ISC_R_SUCCESS:
                isc_refcount_increment(&kfio->references);
@@ -18177,8 +18183,8 @@ zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
                dns_name_copy(name, kfio->name);
 
                isc_mutex_init(&kfio->lock);
-               result = isc_hashmap_add(mgmt->table, NULL, kfio->name->ndata,
-                                        kfio->name->length, kfio);
+               result = isc_hashmap_add(mgmt->table, dns_name_hash(kfio->name),
+                                        kfio_match, kfio->name, kfio, NULL);
                INSIST(result == ISC_R_SUCCESS);
                break;
        default:
@@ -18188,6 +18194,11 @@ zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
        RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
 }
 
+static bool
+match_ptr(void *node, const void *key) {
+       return (node == key);
+}
+
 static void
 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_keyfileio_t **deleted) {
        REQUIRE(DNS_KEYMGMT_VALID(zmgr->keymgmt));
@@ -18206,9 +18217,9 @@ zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_keyfileio_t **deleted) {
                kfio->magic = 0;
                isc_mutex_destroy(&kfio->lock);
 
-               result = isc_hashmap_delete(mgmt->table, NULL,
-                                           kfio->name->ndata,
-                                           kfio->name->length);
+               result = isc_hashmap_delete(mgmt->table,
+                                           dns_name_hash(kfio->name),
+                                           match_ptr, kfio);
                INSIST(result == ISC_R_SUCCESS);
 
                isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
index b54e61137e8702ac4447248b815a6835c682144d..3316bac6c348cdf9cea5698fade7101b5fed484a 100644 (file)
@@ -37,7 +37,6 @@
 #include <isc/magic.h>
 #include <isc/mem.h>
 #include <isc/result.h>
-#include <isc/siphash.h>
 #include <isc/types.h>
 #include <isc/util.h>
 
 #define HASHMAP_MAX_BITS 32U
 
 typedef struct hashmap_node {
-       const uint8_t *key;
+       const void *key;
        void *value;
        uint32_t hashval;
        uint32_t psl;
-       uint16_t keysize;
 } hashmap_node_t;
 
 typedef struct hashmap_table {
@@ -84,12 +82,10 @@ typedef struct hashmap_table {
 
 struct isc_hashmap {
        unsigned int magic;
-       bool case_sensitive;
        uint8_t hindex;
        uint32_t hiter; /* rehashing iterator */
        isc_mem_t *mctx;
        size_t count;
-       uint8_t hash_key[16];
        hashmap_table_t tables[HASHMAP_NUM_TABLES];
 };
 
@@ -101,8 +97,9 @@ struct isc_hashmap_iter {
 };
 
 static isc_result_t
-hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval, const uint8_t *key,
-           const uint32_t keysize, void *value, uint8_t idx);
+hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval,
+           isc_hashmap_match_fn match, const uint8_t *key, void *value,
+           void **foundp, uint8_t idx);
 
 static void
 hashmap_rehash_one(isc_hashmap_t *hashmap);
@@ -133,14 +130,11 @@ try_nexttable(const isc_hashmap_t *hashmap, uint8_t idx) {
 
 static void
 hashmap_node_init(hashmap_node_t *node, const uint32_t hashval,
-                 const uint8_t *key, const uint32_t keysize, void *value) {
-       REQUIRE(key != NULL && keysize <= UINT16_MAX);
-
+                 const uint8_t *key, void *value) {
        *node = (hashmap_node_t){
                .value = value,
                .hashval = hashval,
                .key = key,
-               .keysize = keysize,
                .psl = 0,
        };
 }
@@ -210,10 +204,8 @@ hashmap_free_table(isc_hashmap_t *hashmap, const uint8_t idx, bool cleanup) {
 }
 
 void
-isc_hashmap_create(isc_mem_t *mctx, uint8_t bits, unsigned int options,
-                  isc_hashmap_t **hashmapp) {
+isc_hashmap_create(isc_mem_t *mctx, uint8_t bits, isc_hashmap_t **hashmapp) {
        isc_hashmap_t *hashmap = isc_mem_get(mctx, sizeof(*hashmap));
-       bool case_sensitive = ((options & ISC_HASHMAP_CASE_INSENSITIVE) == 0);
 
        REQUIRE(hashmapp != NULL && *hashmapp == NULL);
        REQUIRE(mctx != NULL);
@@ -221,15 +213,9 @@ isc_hashmap_create(isc_mem_t *mctx, uint8_t bits, unsigned int options,
 
        *hashmap = (isc_hashmap_t){
                .magic = ISC_HASHMAP_MAGIC,
-               .hash_key = { 0, 1 },
-               .case_sensitive = case_sensitive,
        };
        isc_mem_attach(mctx, &hashmap->mctx);
 
-#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(UNIT_TESTING)
-       isc_entropy_get(hashmap->hash_key, sizeof(hashmap->hash_key));
-#endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
-
        hashmap_create_table(hashmap, 0, bits);
 
        hashmap->magic = ISC_HASHMAP_MAGIC;
@@ -259,18 +245,9 @@ isc_hashmap_destroy(isc_hashmap_t **hashmapp) {
        isc_mem_putanddetach(&hashmap->mctx, hashmap, sizeof(*hashmap));
 }
 
-static bool
-hashmap_match(hashmap_node_t *node, const uint32_t hashval, const uint8_t *key,
-             const uint32_t keysize, const bool case_sensitive) {
-       return (node->hashval == hashval && node->keysize == keysize &&
-               (case_sensitive
-                        ? (memcmp(node->key, key, keysize) == 0)
-                        : (isc_ascii_lowerequal(node->key, key, keysize))));
-}
-
 static hashmap_node_t *
 hashmap_find(const isc_hashmap_t *hashmap, const uint32_t hashval,
-            const uint8_t *key, uint32_t keysize, uint32_t *pslp,
+            isc_hashmap_match_fn match, const uint8_t *key, uint32_t *pslp,
             uint8_t *idxp) {
        uint32_t hash;
        uint32_t psl;
@@ -292,12 +269,12 @@ nexttable:
                        break;
                }
 
-               if (hashmap_match(node, hashval, key, keysize,
-                                 hashmap->case_sensitive))
-               {
-                       *pslp = psl;
-                       *idxp = idx;
-                       return (node);
+               if (node->hashval == hashval) {
+                       if (match(node->value, key)) {
+                               *pslp = psl;
+                               *idxp = idx;
+                               return (node);
+                       }
                }
 
                psl++;
@@ -310,34 +287,15 @@ nexttable:
        return (NULL);
 }
 
-uint32_t
-isc_hashmap_hash(const isc_hashmap_t *hashmap, const void *key,
-                uint32_t keysize) {
-       REQUIRE(ISC_HASHMAP_VALID(hashmap));
-
-       uint32_t hashval;
-
-       isc_halfsiphash24(hashmap->hash_key, key, keysize,
-                         hashmap->case_sensitive, (uint8_t *)&hashval);
-
-       return (hashval);
-}
-
 isc_result_t
-isc_hashmap_find(const isc_hashmap_t *hashmap, const uint32_t *hashvalp,
-                const void *key, uint32_t keysize, void **valuep) {
+isc_hashmap_find(const isc_hashmap_t *hashmap, const uint32_t hashval,
+                isc_hashmap_match_fn match, const void *key, void **valuep) {
        REQUIRE(ISC_HASHMAP_VALID(hashmap));
-       REQUIRE(key != NULL && keysize <= UINT16_MAX);
        REQUIRE(valuep == NULL || *valuep == NULL);
 
-       hashmap_node_t *node = NULL;
        uint8_t idx = hashmap->hindex;
-       uint32_t hashval = (hashvalp != NULL)
-                                  ? *hashvalp
-                                  : isc_hashmap_hash(hashmap, key, keysize);
-
-       node = hashmap_find(hashmap, hashval, key, keysize, &(uint32_t){ 0 },
-                           &idx);
+       hashmap_node_t *node = hashmap_find(hashmap, hashval, match, key,
+                                           &(uint32_t){ 0 }, &idx);
        if (node == NULL) {
                return (ISC_R_NOTFOUND);
        }
@@ -384,7 +342,6 @@ hashmap_rehash_one(isc_hashmap_t *hashmap) {
        uint32_t oldsize = hashmap->tables[oldidx].size;
        hashmap_node_t *oldtable = hashmap->tables[oldidx].table;
        hashmap_node_t node;
-       isc_result_t result;
 
        /* Find first non-empty node */
        while (hashmap->hiter < oldsize && oldtable[hashmap->hiter].key == NULL)
@@ -406,8 +363,8 @@ hashmap_rehash_one(isc_hashmap_t *hashmap) {
        hashmap_delete_node(hashmap, &oldtable[hashmap->hiter], node.hashval,
                            node.psl, oldidx);
 
-       result = hashmap_add(hashmap, node.hashval, node.key, node.keysize,
-                            node.value, hashmap->hindex);
+       isc_result_t result = hashmap_add(hashmap, node.hashval, NULL, node.key,
+                                         node.value, NULL, hashmap->hindex);
        INSIST(result == ISC_R_SUCCESS);
 
        /*
@@ -478,18 +435,15 @@ hashmap_rehash_start_shrink(isc_hashmap_t *hashmap) {
 }
 
 isc_result_t
-isc_hashmap_delete(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
-                  const void *key, uint32_t keysize) {
+isc_hashmap_delete(isc_hashmap_t *hashmap, const uint32_t hashval,
+                  isc_hashmap_match_fn match, const void *key) {
        REQUIRE(ISC_HASHMAP_VALID(hashmap));
-       REQUIRE(key != NULL && keysize <= UINT16_MAX);
+       REQUIRE(key != NULL);
 
        hashmap_node_t *node;
        isc_result_t result = ISC_R_NOTFOUND;
        uint32_t psl = 0;
        uint8_t idx;
-       uint32_t hashval = (hashvalp != NULL)
-                                  ? *hashvalp
-                                  : isc_hashmap_hash(hashmap, key, keysize);
 
        if (rehashing_in_progress(hashmap)) {
                hashmap_rehash_one(hashmap);
@@ -501,7 +455,7 @@ isc_hashmap_delete(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
        /* Initialize idx after possible shrink start */
        idx = hashmap->hindex;
 
-       node = hashmap_find(hashmap, hashval, key, keysize, &psl, &idx);
+       node = hashmap_find(hashmap, hashval, match, key, &psl, &idx);
        if (node != NULL) {
                INSIST(node->key != NULL);
                hashmap_delete_node(hashmap, node, hashval, psl, idx);
@@ -532,8 +486,9 @@ under_threshold(isc_hashmap_t *hashmap) {
 }
 
 static isc_result_t
-hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval, const uint8_t *key,
-           const uint32_t keysize, void *value, uint8_t idx) {
+hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval,
+           isc_hashmap_match_fn match, const uint8_t *key, void *value,
+           void **foundp, uint8_t idx) {
        uint32_t hash;
        uint32_t psl = 0;
        hashmap_node_t node;
@@ -543,7 +498,7 @@ hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval, const uint8_t *key,
        hash = isc_hash_bits32(hashval, hashmap->tables[idx].hashbits);
 
        /* Initialize the node to be store to 'node' */
-       hashmap_node_init(&node, hashval, key, keysize, value);
+       hashmap_node_init(&node, hashval, key, value);
 
        psl = 0;
        while (true) {
@@ -556,11 +511,13 @@ hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval, const uint8_t *key,
                        break;
                }
 
-               if (hashmap_match(current, hashval, key, keysize,
-                                 hashmap->case_sensitive))
-               {
-                       return (ISC_R_EXISTS);
+               if (current->hashval == hashval) {
+                       if (match != NULL && match(current->value, key)) {
+                               SET_IF_NOT_NULL(foundp, current->value);
+                               return (ISC_R_EXISTS);
+                       }
                }
+
                /* Found rich node */
                if (node.psl > current->psl) {
                        /* Swap the poor with the rich node */
@@ -591,15 +548,11 @@ hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval, const uint8_t *key,
 }
 
 isc_result_t
-isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
-               const void *key, uint32_t keysize, void *value) {
+isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval,
+               isc_hashmap_match_fn match, const void *key, void *value,
+               void **foundp) {
        REQUIRE(ISC_HASHMAP_VALID(hashmap));
-       REQUIRE(key != NULL && keysize <= UINT16_MAX);
-
-       isc_result_t result;
-       uint32_t hashval = (hashvalp != NULL)
-                                  ? *hashvalp
-                                  : isc_hashmap_hash(hashmap, key, keysize);
+       REQUIRE(key != NULL);
 
        if (rehashing_in_progress(hashmap)) {
                hashmap_rehash_one(hashmap);
@@ -613,20 +566,17 @@ isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
                uint32_t psl;
 
                /* Look for the value in the old table */
-               if (hashmap_find(hashmap, hashval, key, keysize, &psl, &fidx)) {
+               hashmap_node_t *found = hashmap_find(hashmap, hashval, match,
+                                                    key, &psl, &fidx);
+               if (found != NULL) {
+                       INSIST(found->key != NULL);
+                       SET_IF_NOT_NULL(foundp, found->value);
                        return (ISC_R_EXISTS);
                }
        }
 
-       result = hashmap_add(hashmap, hashval, key, keysize, value,
-                            hashmap->hindex);
-       switch (result) {
-       case ISC_R_SUCCESS:
-       case ISC_R_EXISTS:
-               return (result);
-       default:
-               UNREACHABLE();
-       }
+       return (hashmap_add(hashmap, hashval, match, key, value, foundp,
+                           hashmap->hindex));
 }
 
 void
@@ -727,14 +677,12 @@ isc_hashmap_iter_current(isc_hashmap_iter_t *it, void **valuep) {
 }
 
 void
-isc_hashmap_iter_currentkey(isc_hashmap_iter_t *it, const unsigned char **key,
-                           size_t *keysize) {
+isc_hashmap_iter_currentkey(isc_hashmap_iter_t *it, const unsigned char **key) {
        REQUIRE(it != NULL);
        REQUIRE(it->cur != NULL);
        REQUIRE(key != NULL && *key == NULL);
 
        *key = it->cur->key;
-       *keysize = it->cur->keysize;
 }
 
 unsigned int
index 8af0c6b7e319d142161773c72c849975e5dac87e..abd41e1fa011a3da9716f5f09d34d61fc00b1607 100644 (file)
@@ -24,7 +24,7 @@
 typedef struct isc_hashmap     isc_hashmap_t;
 typedef struct isc_hashmap_iter isc_hashmap_iter_t;
 
-enum { ISC_HASHMAP_CASE_SENSITIVE = 0x00, ISC_HASHMAP_CASE_INSENSITIVE = 0x01 };
+typedef bool (*isc_hashmap_match_fn)(void *node, const void *key);
 
 /*%
  * Create hashmap at *hashmapp, using memory context and size of (1<<bits)
@@ -36,8 +36,7 @@ enum { ISC_HASHMAP_CASE_SENSITIVE = 0x00, ISC_HASHMAP_CASE_INSENSITIVE = 0x01 };
  *
  */
 void
-isc_hashmap_create(isc_mem_t *mctx, uint8_t bits, unsigned int options,
-                  isc_hashmap_t **hashmapp);
+isc_hashmap_create(isc_mem_t *mctx, uint8_t bits, isc_hashmap_t **hashmapp);
 
 /*%
  * Destroy hashmap, freeing everything
@@ -48,20 +47,13 @@ isc_hashmap_create(isc_mem_t *mctx, uint8_t bits, unsigned int options,
 void
 isc_hashmap_destroy(isc_hashmap_t **hashmapp);
 
-/*%
- * Return current hashed value for 'key' of size 'keysize';
- */
-uint32_t
-isc_hashmap_hash(const isc_hashmap_t *hashmap, const void *key,
-                uint32_t keysize);
-
 /*%
  * Add a node to hashmap, pointed by binary key 'key' of size 'keysize';
  * set its value to 'value'
  *
  * Requires:
  * \li 'hashmap' is a valid hashmap
- * \li 'hashval' is optional precomputed hash value of 'key'
+ * \li 'hashval' is a precomputed hash value of 'key'
  * \li 'key' is non-null key of size 'keysize'
  *
  * Returns:
@@ -69,8 +61,9 @@ isc_hashmap_hash(const isc_hashmap_t *hashmap, const void *key,
  * \li #ISC_R_SUCCESS          -- all is well.
  */
 isc_result_t
-isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
-               const void *key, uint32_t keysize, void *value);
+isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t hashval,
+               isc_hashmap_match_fn match, const void *key, void *value,
+               void **foundp);
 
 /*%
  * Find a node matching 'key'/'keysize' in hashmap 'hashmap';
@@ -80,7 +73,7 @@ isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
  *
  * Requires:
  * \li 'hashmap' is a valid hashmap
- * \li 'hashval' is optional precomputed hash value of 'key'
+ * \li 'hashval' is a precomputed hash value of 'key'
  * \li 'key' is non-null key of size 'keysize'
  *
  * Returns:
@@ -88,24 +81,24 @@ isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
  * \li #ISC_R_NOTFOUND         -- key not found
  */
 isc_result_t
-isc_hashmap_find(const isc_hashmap_t *hashmap, const uint32_t *hashvalp,
-                const void *key, uint32_t keysize, void **valuep);
+isc_hashmap_find(const isc_hashmap_t *hashmap, const uint32_t hashval,
+                isc_hashmap_match_fn match, const void *key, void **valuep);
 
 /*%
  * Delete node from hashmap
  *
  * Requires:
  * \li 'hashmap' is a valid hashmap
- * \li 'hashval' is optional precomputed hash value of 'key'
- * \li 'key' is non-null key of size 'keysize'
+ * \li 'hashval' is a precomputed hash value of 'key'
+ * \li 'key' is non-null key
  *
  * Returns:
  * \li #ISC_R_NOTFOUND         -- key not found
  * \li #ISC_R_SUCCESS          -- all is well
  */
 isc_result_t
-isc_hashmap_delete(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
-                  const void *key, uint32_t keysize);
+isc_hashmap_delete(isc_hashmap_t *hashmap, const uint32_t hashval,
+                  isc_hashmap_match_fn match, const void *key);
 
 /*%
  * Create an iterator for the hashmap; point '*itp' to it.
@@ -176,8 +169,7 @@ void
 isc_hashmap_iter_current(isc_hashmap_iter_t *it, void **valuep);
 
 /*%
- * Set 'key' and 'keysize to the current key and keysize for the value
- * under the iterator
+ * Set 'key' to the current key for the value under the iterator
  *
  * Requires:
  * \li 'it' is non NULL.
@@ -185,8 +177,7 @@ isc_hashmap_iter_current(isc_hashmap_iter_t *it, void **valuep);
  * \li 'keysize' is non NULL.
  */
 void
-isc_hashmap_iter_currentkey(isc_hashmap_iter_t *it, const unsigned char **key,
-                           size_t *keysize);
+isc_hashmap_iter_currentkey(isc_hashmap_iter_t *it, const unsigned char **key);
 
 /*%
  * Returns the number of items in the hashmap.
index 2a26b0375266a45fd63d5db931c98718f51d4176..7d5c8b004e26773a0ce7d87eac39fca5abb68ebb 100644 (file)
@@ -183,24 +183,29 @@ thread_lfht(void *arg0) {
 static void *
 new_hashmap(isc_mem_t *mem) {
        isc_hashmap_t *hashmap = NULL;
-       isc_hashmap_create(mem, 1, 0, &hashmap);
+       isc_hashmap_create(mem, 1, &hashmap);
 
        return (hashmap);
 }
 
+static bool
+name_match(void *node, const void *key) {
+       return (dns_name_equal(node, key));
+}
+
 static isc_result_t
 add_hashmap(void *hashmap, size_t count) {
-       isc_result_t result =
-               isc_hashmap_add(hashmap, NULL, item[count].fixed.name.ndata,
-                               item[count].fixed.name.length, &item[count]);
+       isc_result_t result = isc_hashmap_add(
+               hashmap, dns_name_hash(&item[count].fixed.name), name_match,
+               &item[count].fixed.name, &item[count], NULL);
        return (result);
 }
 
 static isc_result_t
 get_hashmap(void *hashmap, size_t count, void **pval) {
-       isc_result_t result =
-               isc_hashmap_find(hashmap, NULL, item[count].fixed.name.ndata,
-                                item[count].fixed.name.length, pval);
+       isc_result_t result = isc_hashmap_find(
+               hashmap, dns_name_hash(&item[count].fixed.name), name_match,
+               &item[count].fixed.name, pval);
        return (result);
 }
 
index 6f2f3d3d7c079c61cc58cad3e95590db7962a248..084b84b964dc1f5a6a32cbd57cccaa8b56f819c5 100644 (file)
@@ -42,6 +42,28 @@ typedef struct test_node {
        char key[64];
 } test_node_t;
 
+static bool
+nodes_match(void *node0, const void *key) {
+       struct test_node *node = node0;
+
+       return (memcmp(node->key, key, 16) == 0);
+}
+
+static bool
+long_nodes_match(void *node0, const void *key) {
+       struct test_node *node = node0;
+       size_t len = strlen(key);
+
+       return (memcmp(node->key, key, len) == 0);
+}
+
+static bool
+upper_nodes_match(void *node0, const void *key) {
+       struct test_node *node = node0;
+
+       return (isc_ascii_lowerequal((uint8_t *)node->key, key, 16));
+}
+
 static void
 test_hashmap_full(uint8_t init_bits, uintptr_t count) {
        isc_hashmap_t *hashmap = NULL;
@@ -52,8 +74,7 @@ test_hashmap_full(uint8_t init_bits, uintptr_t count) {
        long_nodes = isc_mem_cget(mctx, count, sizeof(nodes[0]));
        upper_nodes = isc_mem_cget(mctx, count, sizeof(nodes[0]));
 
-       isc_hashmap_create(mctx, init_bits, ISC_HASHMAP_CASE_SENSITIVE,
-                          &hashmap);
+       isc_hashmap_create(mctx, init_bits, &hashmap);
        assert_non_null(hashmap);
 
        /*
@@ -62,55 +83,67 @@ test_hashmap_full(uint8_t init_bits, uintptr_t count) {
         */
        for (size_t i = 0; i < count; i++) {
                /* short keys */
-               snprintf(nodes[i].key, 16, "%u", (unsigned int)i);
-               strlcat(nodes[i].key, " key of a raw hashmap!!", 16);
+               snprintf((char *)nodes[i].key, 16, "%u", (unsigned int)i);
+               strlcat((char *)nodes[i].key, " key of a raw hashmap!!", 16);
+               nodes[i].hashval = isc_hash32(nodes[i].key, 16, true);
 
                /* long keys */
-               snprintf(long_nodes[i].key, sizeof(long_nodes[i].key), "%u",
-                        (unsigned int)i);
-               strlcat(long_nodes[i].key, " key of a raw hashmap!!",
+               snprintf((char *)long_nodes[i].key, sizeof(long_nodes[i].key),
+                        "%u", (unsigned int)i);
+               strlcat((char *)long_nodes[i].key, " key of a raw hashmap!!",
                        sizeof(long_nodes[i].key));
+               long_nodes[i].hashval = isc_hash32(
+                       long_nodes[i].key,
+                       strlen((const char *)long_nodes[i].key), true);
 
                /* (some) uppercase keys */
-               snprintf(upper_nodes[i].key, 16, "%u", (unsigned int)i);
-               strlcat(upper_nodes[i].key, " KEY of a raw hashmap!!", 16);
+               snprintf((char *)upper_nodes[i].key, 16, "%u", (unsigned int)i);
+               strlcat((char *)upper_nodes[i].key, " KEY of a raw hashmap!!",
+                       16);
+               upper_nodes[i].hashval = isc_hash32(upper_nodes[i].key, 16,
+                                                   false);
        }
 
        /* insert short nodes */
        for (size_t i = 0; i < count; i++) {
-               nodes[i].hashval = isc_hashmap_hash(hashmap, nodes[i].key, 16);
-               result = isc_hashmap_add(hashmap, &(nodes[i]).hashval,
-                                        nodes[i].key, 16, &nodes[i]);
+               void *f = NULL;
+               result = isc_hashmap_add(hashmap, nodes[i].hashval, nodes_match,
+                                        nodes[i].key, &nodes[i], &f);
                assert_int_equal(result, ISC_R_SUCCESS);
+               assert_ptr_equal(f, NULL);
        }
 
        /* check if the short nodes were insert */
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_find(hashmap, &(nodes[i]).hashval,
-                                         nodes[i].key, 16, &f);
+               result = isc_hashmap_find(hashmap, nodes[i].hashval,
+                                         nodes_match, nodes[i].key, &f);
                assert_int_equal(result, ISC_R_SUCCESS);
                assert_ptr_equal(&nodes[i], f);
        }
 
        /* check for double inserts */
        for (size_t i = 0; i < count; i++) {
-               result = isc_hashmap_add(hashmap, NULL, nodes[i].key, 16,
-                                        &nodes[i]);
+               void *f = NULL;
+               result = isc_hashmap_add(hashmap, nodes[i].hashval, nodes_match,
+                                        nodes[i].key, &nodes[i], &f);
                assert_int_equal(result, ISC_R_EXISTS);
+               assert_ptr_equal(f, &nodes[i]);
        }
 
        for (size_t i = 0; i < count; i++) {
-               result =
-                       isc_hashmap_add(hashmap, NULL, long_nodes[i].key,
-                                       strlen((const char *)long_nodes[i].key),
-                                       &long_nodes[i]);
+               void *f = NULL;
+               result = isc_hashmap_add(hashmap, long_nodes[i].hashval,
+                                        long_nodes_match, long_nodes[i].key,
+                                        &long_nodes[i], &f);
                assert_int_equal(result, ISC_R_SUCCESS);
+               assert_ptr_equal(f, NULL);
        }
 
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_find(hashmap, NULL, upper_nodes[i].key, 16,
+               result = isc_hashmap_find(hashmap, upper_nodes[i].hashval,
+                                         long_nodes_match, upper_nodes[i].key,
                                          &f);
                assert_int_equal(result, ISC_R_NOTFOUND);
                assert_null(f);
@@ -118,45 +151,50 @@ test_hashmap_full(uint8_t init_bits, uintptr_t count) {
 
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_find(
-                       hashmap, NULL, long_nodes[i].key,
-                       strlen((const char *)long_nodes[i].key), &f);
+               result = isc_hashmap_find(hashmap, long_nodes[i].hashval,
+                                         long_nodes_match, long_nodes[i].key,
+                                         &f);
                assert_int_equal(result, ISC_R_SUCCESS);
                assert_ptr_equal(f, &long_nodes[i]);
        }
 
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_delete(hashmap, &nodes[i].hashval,
-                                           nodes[i].key, 16);
+               result = isc_hashmap_delete(hashmap, nodes[i].hashval,
+                                           nodes_match, nodes[i].key);
                assert_int_equal(result, ISC_R_SUCCESS);
-               result = isc_hashmap_find(hashmap, NULL, nodes[i].key, 16, &f);
+               result = isc_hashmap_find(hashmap, nodes[i].hashval,
+                                         nodes_match, nodes[i].key, &f);
                assert_int_equal(result, ISC_R_NOTFOUND);
                assert_null(f);
        }
 
        for (size_t i = 0; i < count; i++) {
-               result = isc_hashmap_add(hashmap, NULL, upper_nodes[i].key, 16,
-                                        &upper_nodes[i]);
+               void *f = NULL;
+               result = isc_hashmap_add(hashmap, upper_nodes[i].hashval,
+                                        upper_nodes_match, upper_nodes[i].key,
+                                        &upper_nodes[i], &f);
                assert_int_equal(result, ISC_R_SUCCESS);
+               assert_ptr_equal(f, NULL);
        }
 
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_delete(
-                       hashmap, NULL, long_nodes[i].key,
-                       strlen((const char *)long_nodes[i].key));
+               result = isc_hashmap_delete(hashmap, long_nodes[i].hashval,
+                                           long_nodes_match,
+                                           long_nodes[i].key);
                assert_int_equal(result, ISC_R_SUCCESS);
-               result = isc_hashmap_find(
-                       hashmap, NULL, long_nodes[i].key,
-                       strlen((const char *)long_nodes[i].key), &f);
+               result = isc_hashmap_find(hashmap, long_nodes[i].hashval,
+                                         long_nodes_match, long_nodes[i].key,
+                                         &f);
                assert_int_equal(result, ISC_R_NOTFOUND);
                assert_null(f);
        }
 
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_find(hashmap, NULL, upper_nodes[i].key, 16,
+               result = isc_hashmap_find(hashmap, upper_nodes[i].hashval,
+                                         upper_nodes_match, upper_nodes[i].key,
                                          &f);
                assert_int_equal(result, ISC_R_SUCCESS);
                assert_ptr_equal(f, &upper_nodes[i]);
@@ -164,7 +202,8 @@ test_hashmap_full(uint8_t init_bits, uintptr_t count) {
 
        for (size_t i = 0; i < count; i++) {
                void *f = NULL;
-               result = isc_hashmap_find(hashmap, NULL, nodes[i].key, 16, &f);
+               result = isc_hashmap_find(hashmap, nodes[i].hashval,
+                                         nodes_match, nodes[i].key, &f);
                assert_int_equal(result, ISC_R_NOTFOUND);
                assert_null(f);
        }
@@ -184,25 +223,26 @@ test_hashmap_iterator(void) {
        isc_hashmap_iter_t *iter = NULL;
        size_t count = 7600;
        uint32_t walked;
-       size_t tksize;
        test_node_t *nodes;
 
        nodes = isc_mem_cget(mctx, count, sizeof(nodes[0]));
 
-       isc_hashmap_create(mctx, HASHMAP_MIN_BITS, ISC_HASHMAP_CASE_SENSITIVE,
-                          &hashmap);
+       isc_hashmap_create(mctx, HASHMAP_MIN_BITS, &hashmap);
        assert_non_null(hashmap);
 
        for (size_t i = 0; i < count; i++) {
                /* short keys */
-               snprintf(nodes[i].key, 16, "%u", (unsigned int)i);
-               strlcat(nodes[i].key, " key of a raw hashmap!!", 16);
+               snprintf((char *)nodes[i].key, 16, "%u", (unsigned int)i);
+               strlcat((char *)nodes[i].key, " key of a raw hashmap!!", 16);
+               nodes[i].hashval = isc_hash32(nodes[i].key, 16, true);
        }
 
        for (size_t i = 0; i < count; i++) {
-               result = isc_hashmap_add(hashmap, NULL, nodes[i].key, 16,
-                                        &nodes[i]);
+               void *f = NULL;
+               result = isc_hashmap_add(hashmap, nodes[i].hashval, nodes_match,
+                                        nodes[i].key, &nodes[i], &f);
                assert_int_equal(result, ISC_R_SUCCESS);
+               assert_ptr_equal(f, NULL);
        }
 
        /* We want to iterate while rehashing is in progress */
@@ -220,8 +260,7 @@ test_hashmap_iterator(void) {
                test_node_t *v = NULL;
 
                isc_hashmap_iter_current(iter, (void *)&v);
-               isc_hashmap_iter_currentkey(iter, &tkey, &tksize);
-               assert_int_equal(tksize, 16);
+               isc_hashmap_iter_currentkey(iter, &tkey);
 
                i = v - &nodes[0];
 
@@ -245,8 +284,7 @@ test_hashmap_iterator(void) {
                test_node_t *v = NULL;
 
                isc_hashmap_iter_current(iter, (void *)&v);
-               isc_hashmap_iter_currentkey(iter, &tkey, &tksize);
-               assert_int_equal(tksize, 16);
+               isc_hashmap_iter_currentkey(iter, &tkey);
 
                i = v - nodes;
                snprintf(key, 16, "%u", (unsigned int)i);
@@ -273,8 +311,7 @@ test_hashmap_iterator(void) {
                test_node_t *v = NULL;
 
                isc_hashmap_iter_current(iter, (void *)&v);
-               isc_hashmap_iter_currentkey(iter, &tkey, &tksize);
-               assert_int_equal(tksize, 16);
+               isc_hashmap_iter_currentkey(iter, &tkey);
 
                i = v - nodes;
                snprintf(key, 16, "%u", (unsigned int)i);
@@ -356,15 +393,15 @@ ISC_RUN_TEST_IMPL(isc_hashmap_hash_zero_length) {
        bool again = false;
 
 again:
-       isc_hashmap_create(mctx, 1, ISC_HASHMAP_CASE_SENSITIVE, &hashmap);
+       isc_hashmap_create(mctx, 1, &hashmap);
 
-       hashval = isc_hashmap_hash(hashmap, "", 0);
+       hashval = isc_hash32("", 0, true);
 
        isc_hashmap_destroy(&hashmap);
 
        if (hashval == 0 && !again) {
                /*
-                * We could be extremely unlock and the siphash could hash the
+                * We could be extremely unlucky and the siphash could hash the
                 * zero length string to 0, so try one more time.
                 */
                again = true;
@@ -374,50 +411,78 @@ again:
        assert_int_not_equal(hashval, 0);
 }
 
+static bool
+case_match(void *node0, const void *key) {
+       struct test_node *node = node0;
+       size_t len = strlen(key);
+
+       return (memcmp(node->key, key, len) == 0);
+}
+
+static bool
+nocase_match(void *node0, const void *key) {
+       struct test_node *node = node0;
+       size_t len = strlen(key);
+
+       return (isc_ascii_lowerequal((uint8_t *)node->key, key, len));
+}
+
 ISC_RUN_TEST_IMPL(isc_hashmap_case) {
        isc_result_t result;
        isc_hashmap_t *hashmap = NULL;
        test_node_t lower = { .key = "isc_hashmap_case" };
+       test_node_t same = { .key = "isc_hashmap_case" };
        test_node_t upper = { .key = "ISC_HASHMAP_CASE" };
        test_node_t mixed = { .key = "IsC_hAsHmAp_CaSe" };
+       void *f = NULL;
 
-       isc_hashmap_create(mctx, 1, ISC_HASHMAP_CASE_SENSITIVE, &hashmap);
+       isc_hashmap_create(mctx, 1, &hashmap);
 
-       result = isc_hashmap_add(hashmap, NULL, lower.key, strlen(lower.key),
-                                &lower);
+       result = isc_hashmap_add(hashmap,
+                                isc_hash32(lower.key, strlen(lower.key), true),
+                                case_match, lower.key, &lower, NULL);
        assert_int_equal(result, ISC_R_SUCCESS);
 
-       result = isc_hashmap_add(hashmap, NULL, lower.key, strlen(lower.key),
-                                &lower);
+       result = isc_hashmap_add(hashmap,
+                                isc_hash32(same.key, strlen(same.key), true),
+                                case_match, same.key, &same, NULL);
        assert_int_equal(result, ISC_R_EXISTS);
 
-       result = isc_hashmap_add(hashmap, NULL, upper.key, strlen(upper.key),
-                                &upper);
+       result = isc_hashmap_add(hashmap,
+                                isc_hash32(upper.key, strlen(upper.key), true),
+                                case_match, upper.key, &upper, NULL);
        assert_int_equal(result, ISC_R_SUCCESS);
 
-       result = isc_hashmap_find(hashmap, NULL, mixed.key, strlen(mixed.key),
-                                 &(void *){ NULL });
+       result = isc_hashmap_find(
+               hashmap, isc_hash32(mixed.key, strlen(mixed.key), true),
+               case_match, mixed.key, &f);
        assert_int_equal(result, ISC_R_NOTFOUND);
+       assert_ptr_equal(f, NULL);
 
        isc_hashmap_destroy(&hashmap);
 
-       isc_hashmap_create(mctx, 1, ISC_HASHMAP_CASE_INSENSITIVE, &hashmap);
+       isc_hashmap_create(mctx, 1, &hashmap);
 
-       result = isc_hashmap_add(hashmap, NULL, lower.key, strlen(lower.key),
-                                &lower);
+       result = isc_hashmap_add(
+               hashmap, isc_hash32(lower.key, strlen(lower.key), false),
+               nocase_match, lower.key, &lower, NULL);
        assert_int_equal(result, ISC_R_SUCCESS);
 
-       result = isc_hashmap_add(hashmap, NULL, lower.key, strlen(lower.key),
-                                &lower);
+       result = isc_hashmap_add(hashmap,
+                                isc_hash32(same.key, strlen(same.key), false),
+                                nocase_match, same.key, &same, NULL);
        assert_int_equal(result, ISC_R_EXISTS);
 
-       result = isc_hashmap_add(hashmap, NULL, upper.key, strlen(upper.key),
-                                &upper);
+       result = isc_hashmap_add(
+               hashmap, isc_hash32(upper.key, strlen(upper.key), false),
+               nocase_match, upper.key, &upper, NULL);
        assert_int_equal(result, ISC_R_EXISTS);
 
-       result = isc_hashmap_find(hashmap, NULL, mixed.key, strlen(mixed.key),
-                                 &(void *){ NULL });
+       result = isc_hashmap_find(
+               hashmap, isc_hash32(mixed.key, strlen(mixed.key), false),
+               nocase_match, mixed.key, &f);
        assert_int_equal(result, ISC_R_SUCCESS);
+       assert_ptr_equal(f, &lower);
 
        isc_hashmap_destroy(&hashmap);
 }