#include <isc/async.h>
#include <isc/atomic.h>
+#include <isc/hash.h>
#include <isc/hashmap.h>
#include <isc/list.h>
#include <isc/loop.h>
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:
*
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;
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
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
return (ISC_R_SUCCESS);
}
+static bool
+match_ptr(void *node, const void *key) {
+ return (node == key);
+}
+
/*
* Requires the name to be locked.
*/
/*
* 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);
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);
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.
*/
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;
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);
/* 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);
}
}
+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.
*/
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);
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);
/* 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);
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);
}
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);
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);
* 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);
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;
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,
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));
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) {
* 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",
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);
/*
* 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);
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);
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)
dns_name_t *name;
dns_rdatatype_t type;
unsigned int options;
- fctxkey_t key;
fctxcount_t *counter;
char *info;
isc_mem_t *mctx;
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;
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;
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);
return (result);
}
+static bool
+match_ptr(void *node, const void *key) {
+ return (node == key);
+}
+
static void
fcount_decr(fetchctx_t *fctx) {
REQUIRE(fctx != NULL);
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);
.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);
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 {
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);
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) {
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) {
}
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;
} 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) {
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);
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);
}
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);
}
}
+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);
}
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);
.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);
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;
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;
}
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) {
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);
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:
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));
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));
#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 {
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];
};
};
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);
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,
};
}
}
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);
*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;
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;
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++;
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);
}
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)
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);
/*
}
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);
/* 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);
}
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;
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) {
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 */
}
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);
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
}
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
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)
*
*/
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
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:
* \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';
*
* 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:
* \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.
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.
* \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.
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);
}
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;
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);
/*
*/
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);
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]);
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);
}
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 */
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];
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);
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);
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;
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);
}