mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-27 20:11:12 -05:00
Merge branch 'ondrej-improve-isc_hashmap' into 'main'
Refactor isc_hashmap to accept custom match function See merge request isc-projects/bind9!8289
This commit is contained in:
commit
7be52f1bad
9 changed files with 425 additions and 375 deletions
165
lib/dns/adb.c
165
lib/dns/adb.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
@ -68,11 +67,10 @@
|
|||
#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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
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]);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_ptr_equal(f, &nodes[i]);
|
||||
}
|
||||
|
||||
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_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, 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);
|
||||
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]);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
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));
|
||||
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, 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++) {
|
||||
void *f = NULL;
|
||||
result = isc_hashmap_find(hashmap, NULL, upper_nodes[i].key, 16,
|
||||
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, long_nodes[i].hashval,
|
||||
long_nodes_match,
|
||||
long_nodes[i].key);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
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, 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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue