Merge branch '3212-implement-incremental-rehashing-for-isc_ht-hashtables-v9_18' into 'v9_18'

[9.18] Implement incremental hash table resizing in isc_ht

See merge request isc-projects/bind9!7355
This commit is contained in:
Ondřej Surý
2023-01-11 17:01:00 +00:00
10 changed files with 410 additions and 165 deletions

View File

@@ -58,6 +58,9 @@
6044. [bug] There was an "RSASHA236" typo in a log message.
[GL !7206]
5830. [func] Implement incremental resizing of isc_ht hash tables to
perform the rehashing gradually. [GL #3212]
--- 9.18.10 released ---
6043. [bug] The key file IO locks objects would never get

View File

@@ -347,7 +347,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
cfg_line, mctx, lctx, actx));
}
isc_ht_init(&inst->ht, mctx, 16);
isc_ht_init(&inst->ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
isc_mutex_init(&inst->hlock);
/*

View File

@@ -350,7 +350,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
cfg_line, mctx, lctx, actx));
}
isc_ht_init(&inst->ht, mctx, 16);
isc_ht_init(&inst->ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
isc_mutex_init(&inst->hlock);
/*

View File

@@ -143,7 +143,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
*inst = (async_instance_t){ .mctx = NULL };
isc_mem_attach(mctx, &inst->mctx);
isc_ht_init(&inst->ht, mctx, 16);
isc_ht_init(&inst->ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
isc_mutex_init(&inst->hlock);
/*

View File

@@ -477,9 +477,9 @@ dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) {
dns_name_format(&target->name, czname, DNS_NAME_FORMATSIZE);
isc_ht_init(&toadd, target->catzs->mctx, 16);
isc_ht_init(&toadd, target->catzs->mctx, 16, ISC_HT_CASE_SENSITIVE);
isc_ht_init(&tomod, target->catzs->mctx, 16);
isc_ht_init(&tomod, target->catzs->mctx, 16, ISC_HT_CASE_SENSITIVE);
isc_ht_iter_create(newzone->entries, &iter1);
@@ -759,7 +759,7 @@ dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
isc_refcount_init(&new_zones->refs, 1);
isc_ht_init(&new_zones->zones, mctx, 4);
isc_ht_init(&new_zones->zones, mctx, 4, ISC_HT_CASE_SENSITIVE);
isc_mem_attach(mctx, &new_zones->mctx);
new_zones->zmm = zmm;
@@ -811,8 +811,8 @@ dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
dns_name_init(&new_zone->name, NULL);
dns_name_dup(name, catzs->mctx, &new_zone->name);
isc_ht_init(&new_zone->entries, catzs->mctx, 4);
isc_ht_init(&new_zone->coos, catzs->mctx, 4);
isc_ht_init(&new_zone->entries, catzs->mctx, 4, ISC_HT_CASE_SENSITIVE);
isc_ht_init(&new_zone->coos, catzs->mctx, 4, ISC_HT_CASE_INSENSITIVE);
new_zone->updatetimer = NULL;
result = isc_timer_create(catzs->timermgr, isc_timertype_inactive, NULL,

View File

@@ -1544,7 +1544,7 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
* simplifies update_from_db
*/
isc_ht_init(&zone->nodes, rpzs->mctx, 1);
isc_ht_init(&zone->nodes, rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
dns_name_init(&zone->origin, NULL);
dns_name_init(&zone->client_ip, NULL);
@@ -1722,7 +1722,8 @@ setup_update(dns_rpz_zone_t *rpz) {
ISC_LOG_DEBUG(1), "rpz: %s: using hashtable size %d",
domain, hashsize);
isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize);
isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize,
ISC_HT_CASE_SENSITIVE);
result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &rpz->updbit);
if (result != ISC_R_SUCCESS) {

View File

@@ -27,9 +27,22 @@ typedef struct isc_ht_node isc_ht_node_t;
#define ISC_HT_MAGIC ISC_MAGIC('H', 'T', 'a', 'b')
#define ISC_HT_VALID(ht) ISC_MAGIC_VALID(ht, ISC_HT_MAGIC)
#define HT_NO_BITS 0
#define HT_MIN_BITS 1
#define HT_MAX_BITS 32
#define HT_OVERCOMMIT 3
#define HT_NEXTTABLE(idx) ((idx == 0) ? 1 : 0)
#define TRY_NEXTTABLE(idx, ht) (idx == ht->hindex && rehashing_in_progress(ht))
#define GOLDEN_RATIO_32 0x61C88647
#define HASHSIZE(bits) (UINT64_C(1) << (bits))
struct isc_ht_node {
void *value;
isc_ht_node_t *next;
uint32_t hashval;
size_t keysize;
unsigned char key[];
};
@@ -37,41 +50,208 @@ struct isc_ht_node {
struct isc_ht {
unsigned int magic;
isc_mem_t *mctx;
size_t size;
size_t mask;
unsigned int count;
isc_ht_node_t **table;
size_t count;
bool case_sensitive;
size_t size[2];
uint8_t hashbits[2];
isc_ht_node_t **table[2];
uint8_t hindex;
uint32_t hiter; /* rehashing iterator */
};
struct isc_ht_iter {
isc_ht_t *ht;
size_t i;
uint8_t hindex;
isc_ht_node_t *cur;
};
static isc_ht_node_t *
isc__ht_find(const isc_ht_t *ht, const unsigned char *key,
const uint32_t keysize, const uint32_t hashval, const uint8_t idx);
static void
isc__ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
const uint32_t hashval, const uint8_t idx, void *value);
static isc_result_t
isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
const uint32_t hashval, const uint8_t idx);
static uint32_t
rehash_bits(isc_ht_t *ht, size_t newcount);
static void
hashtable_new(isc_ht_t *ht, const uint8_t idx, const uint8_t bits);
static void
hashtable_free(isc_ht_t *ht, const uint8_t idx);
static void
hashtable_rehash(isc_ht_t *ht, uint32_t newbits);
static void
hashtable_rehash_one(isc_ht_t *ht);
static void
maybe_rehash(isc_ht_t *ht, size_t newcount);
static isc_result_t
isc__ht_iter_next(isc_ht_iter_t *it);
static bool
isc__ht_node_match(isc_ht_node_t *node, const uint32_t hashval,
const uint8_t *key, uint32_t keysize) {
return (node->hashval == hashval && node->keysize == keysize &&
memcmp(node->key, key, keysize) == 0);
}
static uint32_t
hash_32(uint32_t val, unsigned int bits) {
REQUIRE(bits <= HT_MAX_BITS);
/* High bits are more random. */
return (val * GOLDEN_RATIO_32 >> (32 - bits));
}
static bool
rehashing_in_progress(const isc_ht_t *ht) {
return (ht->table[HT_NEXTTABLE(ht->hindex)] != NULL);
}
static bool
hashtable_is_overcommited(isc_ht_t *ht) {
return (ht->count >= (ht->size[ht->hindex] * HT_OVERCOMMIT));
}
static uint32_t
rehash_bits(isc_ht_t *ht, size_t newcount) {
uint32_t newbits = ht->hashbits[ht->hindex];
while (newcount >= HASHSIZE(newbits) && newbits <= HT_MAX_BITS) {
newbits += 1;
}
return (newbits);
}
/*
* Rebuild the hashtable to reduce the load factor
*/
static void
hashtable_rehash(isc_ht_t *ht, uint32_t newbits) {
uint8_t oldindex = ht->hindex;
uint32_t oldbits = ht->hashbits[oldindex];
uint8_t newindex = HT_NEXTTABLE(oldindex);
REQUIRE(ht->hashbits[oldindex] >= HT_MIN_BITS);
REQUIRE(ht->hashbits[oldindex] <= HT_MAX_BITS);
REQUIRE(ht->table[oldindex] != NULL);
REQUIRE(newbits <= HT_MAX_BITS);
REQUIRE(ht->hashbits[newindex] == HT_NO_BITS);
REQUIRE(ht->table[newindex] == NULL);
REQUIRE(newbits > oldbits);
hashtable_new(ht, newindex, newbits);
ht->hindex = newindex;
hashtable_rehash_one(ht);
}
static void
hashtable_rehash_one(isc_ht_t *ht) {
isc_ht_node_t **newtable = ht->table[ht->hindex];
uint32_t oldsize = ht->size[HT_NEXTTABLE(ht->hindex)];
isc_ht_node_t **oldtable = ht->table[HT_NEXTTABLE(ht->hindex)];
isc_ht_node_t *node = NULL;
isc_ht_node_t *nextnode;
/* Find first non-empty node */
while (ht->hiter < oldsize && oldtable[ht->hiter] == NULL) {
ht->hiter++;
}
/* Rehashing complete */
if (ht->hiter == oldsize) {
hashtable_free(ht, HT_NEXTTABLE(ht->hindex));
ht->hiter = 0;
return;
}
/* Move the first non-empty node from old hashtable to new hashtable */
for (node = oldtable[ht->hiter]; node != NULL; node = nextnode) {
uint32_t hash = hash_32(node->hashval,
ht->hashbits[ht->hindex]);
nextnode = node->next;
node->next = newtable[hash];
newtable[hash] = node;
}
oldtable[ht->hiter] = NULL;
ht->hiter++;
}
static void
maybe_rehash(isc_ht_t *ht, size_t newcount) {
uint32_t newbits = rehash_bits(ht, newcount);
if (ht->hashbits[ht->hindex] < newbits && newbits <= HT_MAX_BITS) {
hashtable_rehash(ht, newbits);
}
}
static void
hashtable_new(isc_ht_t *ht, const uint8_t idx, const uint8_t bits) {
size_t size;
REQUIRE(ht->hashbits[idx] == HT_NO_BITS);
REQUIRE(ht->table[idx] == NULL);
REQUIRE(bits >= HT_MIN_BITS);
REQUIRE(bits <= HT_MAX_BITS);
ht->hashbits[idx] = bits;
ht->size[idx] = HASHSIZE(ht->hashbits[idx]);
size = ht->size[idx] * sizeof(isc_ht_node_t *);
ht->table[idx] = isc_mem_get(ht->mctx, size);
memset(ht->table[idx], 0, size);
}
static void
hashtable_free(isc_ht_t *ht, const uint8_t idx) {
size_t size = ht->size[idx] * sizeof(isc_ht_node_t *);
for (size_t i = 0; i < ht->size[idx]; i++) {
isc_ht_node_t *node = ht->table[idx][i];
while (node != NULL) {
isc_ht_node_t *next = node->next;
ht->count--;
isc_mem_put(ht->mctx, node,
sizeof(*node) + node->keysize);
node = next;
}
}
isc_mem_put(ht->mctx, ht->table[idx], size);
ht->hashbits[idx] = HT_NO_BITS;
ht->table[idx] = NULL;
}
void
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits) {
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits,
unsigned int options) {
isc_ht_t *ht = NULL;
size_t i;
bool case_sensitive = ((options & ISC_HT_CASE_INSENSITIVE) == 0);
REQUIRE(htp != NULL && *htp == NULL);
REQUIRE(mctx != NULL);
REQUIRE(bits >= 1 && bits <= (sizeof(size_t) * 8 - 1));
REQUIRE(bits >= 1 && bits <= HT_MAX_BITS);
ht = isc_mem_get(mctx, sizeof(struct isc_ht));
ht = isc_mem_get(mctx, sizeof(*ht));
*ht = (isc_ht_t){
.case_sensitive = case_sensitive,
};
ht->mctx = NULL;
isc_mem_attach(mctx, &ht->mctx);
ht->size = ((size_t)1 << bits);
ht->mask = ((size_t)1 << bits) - 1;
ht->count = 0;
ht->table = isc_mem_get(ht->mctx, ht->size * sizeof(isc_ht_node_t *));
for (i = 0; i < ht->size; i++) {
ht->table[i] = NULL;
}
hashtable_new(ht, 0, bits);
ht->magic = ISC_HT_MAGIC;
@@ -81,126 +261,180 @@ isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits) {
void
isc_ht_destroy(isc_ht_t **htp) {
isc_ht_t *ht;
size_t i;
REQUIRE(htp != NULL);
REQUIRE(ISC_HT_VALID(*htp));
ht = *htp;
*htp = NULL;
REQUIRE(ISC_HT_VALID(ht));
ht->magic = 0;
for (i = 0; i < ht->size; i++) {
isc_ht_node_t *node = ht->table[i];
while (node != NULL) {
isc_ht_node_t *next = node->next;
ht->count--;
isc_mem_put(ht->mctx, node,
offsetof(isc_ht_node_t, key) +
node->keysize);
node = next;
for (size_t i = 0; i <= 1; i++) {
if (ht->table[i] != NULL) {
hashtable_free(ht, i);
}
}
INSIST(ht->count == 0);
isc_mem_put(ht->mctx, ht->table, ht->size * sizeof(isc_ht_node_t *));
isc_mem_putanddetach(&ht->mctx, ht, sizeof(struct isc_ht));
isc_mem_putanddetach(&ht->mctx, ht, sizeof(*ht));
}
static void
isc__ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
const uint32_t hashval, const uint8_t idx, void *value) {
isc_ht_node_t *node;
uint32_t hash;
hash = hash_32(hashval, ht->hashbits[idx]);
node = isc_mem_get(ht->mctx, sizeof(*node) + keysize);
*node = (isc_ht_node_t){
.keysize = keysize,
.hashval = hashval,
.next = ht->table[idx][hash],
.value = value,
};
memmove(node->key, key, keysize);
ht->count++;
ht->table[idx][hash] = node;
}
isc_result_t
isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
isc_ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
void *value) {
isc_ht_node_t *node;
uint32_t hash;
uint32_t hashval;
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
memcmp(key, node->key, keysize) == 0)
{
return (ISC_R_EXISTS);
}
node = node->next;
if (rehashing_in_progress(ht)) {
/* Rehash in progress */
hashtable_rehash_one(ht);
} else if (hashtable_is_overcommited(ht)) {
/* Rehash requested */
maybe_rehash(ht, ht->count);
}
node = isc_mem_get(ht->mctx, offsetof(isc_ht_node_t, key) + keysize);
hashval = isc_hash32(key, keysize, ht->case_sensitive);
memmove(node->key, key, keysize);
node->keysize = keysize;
node->next = ht->table[hash & ht->mask];
node->value = value;
if (isc__ht_find(ht, key, keysize, hashval, ht->hindex) != NULL) {
return (ISC_R_EXISTS);
}
isc__ht_add(ht, key, keysize, hashval, ht->hindex, value);
ht->count++;
ht->table[hash & ht->mask] = node;
return (ISC_R_SUCCESS);
}
isc_result_t
isc_ht_find(const isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
void **valuep) {
isc_ht_node_t *node;
static isc_ht_node_t *
isc__ht_find(const isc_ht_t *ht, const unsigned char *key,
const uint32_t keysize, const uint32_t hashval,
const uint8_t idx) {
uint32_t hash;
uint8_t findex = idx;
nexttable:
hash = hash_32(hashval, ht->hashbits[findex]);
for (isc_ht_node_t *node = ht->table[findex][hash]; node != NULL;
node = node->next)
{
if (isc__ht_node_match(node, hashval, key, keysize)) {
return (node);
}
}
if (TRY_NEXTTABLE(findex, ht)) {
/*
* Rehashing in progress, check the other table
*/
findex = HT_NEXTTABLE(findex);
goto nexttable;
}
return (NULL);
}
isc_result_t
isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
const uint32_t keysize, void **valuep) {
uint32_t hashval;
isc_ht_node_t *node;
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
REQUIRE(valuep == NULL || *valuep == NULL);
hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
memcmp(key, node->key, keysize) == 0)
{
if (valuep != NULL) {
*valuep = node->value;
hashval = isc_hash32(key, keysize, ht->case_sensitive);
node = isc__ht_find(ht, key, keysize, hashval, ht->hindex);
if (node == NULL) {
return (ISC_R_NOTFOUND);
}
if (valuep != NULL) {
*valuep = node->value;
}
return (ISC_R_SUCCESS);
}
static isc_result_t
isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
const uint32_t hashval, const uint8_t idx) {
isc_ht_node_t *prev = NULL;
uint32_t hash;
hash = hash_32(hashval, ht->hashbits[idx]);
for (isc_ht_node_t *node = ht->table[idx][hash]; node != NULL;
prev = node, node = node->next)
{
if (isc__ht_node_match(node, hashval, key, keysize)) {
if (prev == NULL) {
ht->table[idx][hash] = node->next;
} else {
prev->next = node->next;
}
isc_mem_put(ht->mctx, node,
sizeof(*node) + node->keysize);
ht->count--;
return (ISC_R_SUCCESS);
}
node = node->next;
}
return (ISC_R_NOTFOUND);
}
isc_result_t
isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t keysize) {
isc_ht_node_t *node, *prev;
uint32_t hash;
isc_ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize) {
uint32_t hashval;
uint8_t hindex;
isc_result_t result;
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
prev = NULL;
hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
memcmp(key, node->key, keysize) == 0)
{
if (prev == NULL) {
ht->table[hash & ht->mask] = node->next;
} else {
prev->next = node->next;
}
isc_mem_put(ht->mctx, node,
offsetof(isc_ht_node_t, key) +
node->keysize);
ht->count--;
return (ISC_R_SUCCESS);
}
prev = node;
node = node->next;
if (rehashing_in_progress(ht)) {
/* Rehash in progress */
hashtable_rehash_one(ht);
}
return (ISC_R_NOTFOUND);
hindex = ht->hindex;
hashval = isc_hash32(key, keysize, ht->case_sensitive);
nexttable:
result = isc__ht_delete(ht, key, keysize, hashval, hindex);
if (result == ISC_R_NOTFOUND && TRY_NEXTTABLE(hindex, ht)) {
/*
* Rehashing in progress, check the other table
*/
hindex = HT_NEXTTABLE(hindex);
goto nexttable;
}
return (result);
}
void
@@ -211,10 +445,10 @@ isc_ht_iter_create(isc_ht_t *ht, isc_ht_iter_t **itp) {
REQUIRE(itp != NULL && *itp == NULL);
it = isc_mem_get(ht->mctx, sizeof(isc_ht_iter_t));
it->ht = ht;
it->i = 0;
it->cur = NULL;
*it = (isc_ht_iter_t){
.ht = ht,
.hindex = ht->hindex,
};
*itp = it;
}
@@ -229,25 +463,46 @@ isc_ht_iter_destroy(isc_ht_iter_t **itp) {
it = *itp;
*itp = NULL;
ht = it->ht;
isc_mem_put(ht->mctx, it, sizeof(isc_ht_iter_t));
isc_mem_put(ht->mctx, it, sizeof(*it));
}
isc_result_t
isc_ht_iter_first(isc_ht_iter_t *it) {
isc_ht_t *ht;
REQUIRE(it != NULL);
ht = it->ht;
it->hindex = ht->hindex;
it->i = 0;
while (it->i < it->ht->size && it->ht->table[it->i] == NULL) {
return (isc__ht_iter_next(it));
}
static isc_result_t
isc__ht_iter_next(isc_ht_iter_t *it) {
isc_ht_t *ht = it->ht;
while (it->i < ht->size[it->hindex] &&
ht->table[it->hindex][it->i] == NULL)
{
it->i++;
}
if (it->i == it->ht->size) {
return (ISC_R_NOMORE);
if (it->i < ht->size[it->hindex]) {
it->cur = ht->table[it->hindex][it->i];
return (ISC_R_SUCCESS);
}
it->cur = it->ht->table[it->i];
if (TRY_NEXTTABLE(it->hindex, ht)) {
it->hindex = HT_NEXTTABLE(it->hindex);
it->i = 0;
return (isc__ht_iter_next(it));
}
return (ISC_R_SUCCESS);
return (ISC_R_NOMORE);
}
isc_result_t
@@ -256,60 +511,36 @@ isc_ht_iter_next(isc_ht_iter_t *it) {
REQUIRE(it->cur != NULL);
it->cur = it->cur->next;
if (it->cur == NULL) {
do {
it->i++;
} while (it->i < it->ht->size && it->ht->table[it->i] == NULL);
if (it->i >= it->ht->size) {
return (ISC_R_NOMORE);
}
it->cur = it->ht->table[it->i];
if (it->cur != NULL) {
return (ISC_R_SUCCESS);
}
return (ISC_R_SUCCESS);
it->i++;
return (isc__ht_iter_next(it));
}
isc_result_t
isc_ht_iter_delcurrent_next(isc_ht_iter_t *it) {
isc_result_t result = ISC_R_SUCCESS;
isc_ht_node_t *to_delete = NULL;
isc_ht_node_t *prev = NULL;
isc_ht_node_t *node = NULL;
uint32_t hash;
isc_ht_node_t *dnode = NULL;
uint8_t dindex;
isc_ht_t *ht;
isc_result_t dresult;
REQUIRE(it != NULL);
REQUIRE(it->cur != NULL);
to_delete = it->cur;
ht = it->ht;
dnode = it->cur;
dindex = it->hindex;
it->cur = it->cur->next;
if (it->cur == NULL) {
do {
it->i++;
} while (it->i < ht->size && ht->table[it->i] == NULL);
if (it->i >= ht->size) {
result = ISC_R_NOMORE;
} else {
it->cur = ht->table[it->i];
}
}
result = isc_ht_iter_next(it);
hash = isc_hash_function(to_delete->key, to_delete->keysize, true);
node = ht->table[hash & ht->mask];
while (node != to_delete) {
prev = node;
node = node->next;
INSIST(node != NULL);
}
if (prev == NULL) {
ht->table[hash & ht->mask] = node->next;
} else {
prev->next = node->next;
}
isc_mem_put(ht->mctx, node,
offsetof(isc_ht_node_t, key) + node->keysize);
ht->count--;
dresult = isc__ht_delete(ht, dnode->key, dnode->keysize, dnode->hashval,
dindex);
INSIST(dresult == ISC_R_SUCCESS);
return (result);
}
@@ -334,8 +565,8 @@ isc_ht_iter_currentkey(isc_ht_iter_t *it, unsigned char **key,
*keysize = it->cur->keysize;
}
unsigned int
isc_ht_count(isc_ht_t *ht) {
size_t
isc_ht_count(const isc_ht_t *ht) {
REQUIRE(ISC_HT_VALID(ht));
return (ht->count);

View File

@@ -24,9 +24,15 @@
typedef struct isc_ht isc_ht_t;
typedef struct isc_ht_iter isc_ht_iter_t;
enum { ISC_HT_CASE_SENSITIVE = 0x00, ISC_HT_CASE_INSENSITIVE = 0x01 };
/*%
* Initialize hashtable at *htp, using memory context and size of (1<<bits)
*
* If 'options' contains ISC_HT_CASE_INSENSITIVE, then upper- and lower-case
* letters in key values will generate the same hash values; this can be used
* when the key for a hash table is a DNS name.
*
* Requires:
*\li 'htp' is not NULL and '*htp' is NULL.
*\li 'mctx' is a valid memory context.
@@ -34,7 +40,8 @@ typedef struct isc_ht_iter isc_ht_iter_t;
*
*/
void
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits);
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits,
unsigned int options);
/*%
* Destroy hashtable, freeing everything
@@ -51,6 +58,7 @@ isc_ht_destroy(isc_ht_t **htp);
*
* Requires:
*\li 'ht' is a valid hashtable
*\li write-lock
*
* Returns:
*\li #ISC_R_NOMEMORY -- not enough memory to create pool
@@ -58,7 +66,7 @@ isc_ht_destroy(isc_ht_t **htp);
*\li #ISC_R_SUCCESS -- all is well.
*/
isc_result_t
isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
isc_ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
void *value);
/*%
@@ -69,27 +77,29 @@ isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
*
* Requires:
* \li 'ht' is a valid hashtable
* \li read-lock
*
* Returns:
* \li #ISC_R_SUCCESS -- success
* \li #ISC_R_NOTFOUND -- key not found
*/
isc_result_t
isc_ht_find(const isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
void **valuep);
isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
const uint32_t keysize, void **valuep);
/*%
* Delete node from hashtable
*
* Requires:
*\li ht is a valid hashtable
*\li write-lock
*
* Returns:
*\li #ISC_R_NOTFOUND -- key not found
*\li #ISC_R_SUCCESS -- all is well
*/
isc_result_t
isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t keysize);
isc_ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize);
/*%
* Create an iterator for the hashtable; point '*itp' to it.
@@ -177,5 +187,5 @@ isc_ht_iter_currentkey(isc_ht_iter_t *it, unsigned char **key, size_t *keysize);
* Requires:
*\li 'ht' is a valid hashtable
*/
unsigned int
isc_ht_count(isc_ht_t *ht);
size_t
isc_ht_count(const isc_ht_t *ht);

View File

@@ -1112,7 +1112,7 @@ isc_tlsctx_cache_create(isc_mem_t *mctx, isc_tlsctx_cache_t **cachep) {
isc_refcount_init(&nc->references, 1);
isc_mem_attach(mctx, &nc->mctx);
isc_ht_init(&nc->data, mctx, 5);
isc_ht_init(&nc->data, mctx, 5, ISC_HT_CASE_SENSITIVE);
isc_rwlock_init(&nc->rwlock, 0, 0);
*cachep = nc;
@@ -1408,7 +1408,7 @@ isc_tlsctx_client_session_cache_create(
isc_mem_attach(mctx, &nc->mctx);
isc_tlsctx_attach(ctx, &nc->ctx);
isc_ht_init(&nc->buckets, mctx, 5);
isc_ht_init(&nc->buckets, mctx, 5, ISC_HT_CASE_SENSITIVE);
ISC_LIST_INIT(nc->lru_entries);
isc_mutex_init(&nc->lock);

View File

@@ -44,7 +44,7 @@ test_ht_full(int bits, uintptr_t count) {
isc_result_t result;
uintptr_t i;
isc_ht_init(&ht, mctx, bits);
isc_ht_init(&ht, mctx, bits, ISC_HT_CASE_SENSITIVE);
assert_non_null(ht);
for (i = 1; i < count; i++) {
@@ -189,7 +189,7 @@ test_ht_iterator(void) {
unsigned char key[16];
size_t tksize;
isc_ht_init(&ht, mctx, 16);
isc_ht_init(&ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
assert_non_null(ht);
for (i = 1; i <= count; i++) {
/*