2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

2993. [func] Dynamically grow adb hash tables. [RT #21186]

This commit is contained in:
Mark Andrews
2010-12-21 03:11:42 +00:00
parent 72be2e5698
commit 82f77687ab
3 changed files with 518 additions and 51 deletions

View File

@@ -1,3 +1,5 @@
2993. [func] Dynamically grow adb hash tables. [RT #21186]
2992. [contrib] contrib/check-secure-delegation.pl: A simple tool
for looking at a secure delegation. [RT #22059]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: adb.c,v 1.252 2010/12/16 09:51:29 jinmei Exp $ */
/* $Id: adb.c,v 1.253 2010/12/21 03:11:42 marka Exp $ */
/*! \file
*
@@ -65,13 +65,6 @@
#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
/*!
* The number of buckets needs to be a prime (for good hashing).
*
* XXXRTH How many buckets do we need?
*/
#define NBUCKETS 1009 /*%< how many buckets for names/addrs */
/*!
* For type 3 negative cache entries, we will remember that the address is
* broken for this long. XXXMLG This is also used for actual addresses, too.
@@ -139,30 +132,37 @@ struct dns_adb {
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
dns_adbnamelist_t names[NBUCKETS];
dns_adbnamelist_t deadnames[NBUCKETS];
/*% See dns_adbnamelist_t */
isc_mutex_t namelocks[NBUCKETS];
/*% See dns_adbnamelist_t */
isc_boolean_t name_sd[NBUCKETS];
/*% See dns_adbnamelist_t */
unsigned int name_refcnt[NBUCKETS];
unsigned int nnames;
isc_mutex_t namescntlock;
unsigned int namescnt;
dns_adbnamelist_t *names;
dns_adbnamelist_t *deadnames;
isc_mutex_t *namelocks;
isc_boolean_t *name_sd;
unsigned int *name_refcnt;
/*!
* Bucketized locks for entries.
* Bucketized locks and lists for entries.
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
dns_adbentrylist_t entries[NBUCKETS];
dns_adbentrylist_t deadentries[NBUCKETS];
isc_mutex_t entrylocks[NBUCKETS];
isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */
unsigned int entry_refcnt[NBUCKETS];
unsigned int nentries;
isc_mutex_t entriescntlock;
unsigned int entriescnt;
dns_adbentrylist_t *entries;
dns_adbentrylist_t *deadentries;
isc_mutex_t *entrylocks;
isc_boolean_t *entry_sd; /*%< shutting down */
unsigned int *entry_refcnt;
isc_event_t cevent;
isc_boolean_t cevent_sent;
isc_boolean_t shutting_down;
isc_eventlist_t whenshutdown;
isc_event_t growentries;
isc_boolean_t growentries_sent;
isc_event_t grownames;
isc_boolean_t grownames_sent;
};
/*
@@ -483,6 +483,322 @@ ttlclamp(dns_ttl_t ttl) {
return (ttl);
}
/*
* Hashing is most efficient if the number of buckets is prime.
* The sequence below is the closest previous primes to 2^n and
* 1.5 * 2^n, for values of n from 10 to 28. (The tables will
* no longer grow beyond 2^28 entries.)
*/
static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
8191, 12281, 16381, 24571, 32749,
49193, 65521, 98299, 131071, 199603,
262139, 393209, 524287, 768431, 1048573,
1572853, 2097143, 3145721, 4194301,
6291449, 8388593, 12582893, 16777213,
25165813, 33554393, 50331599, 67108859,
100663291, 134217689, 201326557,
268535431, 0 };
static void
grow_entries(isc_task_t *task, isc_event_t *ev) {
dns_adb_t *adb;
dns_adbentry_t *e;
dns_adbentrylist_t *newdeadentries = NULL;
dns_adbentrylist_t *newentries = NULL;
isc_boolean_t *newentry_sd = NULL;
isc_mutex_t *newentrylocks = NULL;
isc_result_t result;
unsigned int *newentry_refcnt = NULL;
unsigned int i, n, bucket;
adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb));
isc_event_free(&ev);
isc_task_beginexclusive(task);
i = 0;
while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
i++;
if (nbuckets[i] != 0)
n = nbuckets[i];
else
goto done;
DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
/*
* Are we shutting down?
*/
for (i = 0; i < adb->nentries; i++)
if (adb->entry_sd[i])
goto cleanup;
/*
* Grab all the resources we need.
*/
newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
if (newentries == NULL || newdeadentries == NULL ||
newentrylocks == NULL || newentry_sd == NULL ||
newentry_refcnt == NULL)
goto cleanup;
/*
* Initialise the new resources.
*/
result = isc_mutexblock_init(newentrylocks, n);
if (result != ISC_R_SUCCESS)
goto cleanup;
for (i = 0; i < n; i++) {
ISC_LIST_INIT(newentries[i]);
ISC_LIST_INIT(newdeadentries[i]);
newentry_sd[i] = ISC_FALSE;
newentry_refcnt[i] = 0;
adb->irefcnt++;
}
/*
* Move entries to new arrays.
*/
for (i = 0; i < adb->nentries; i++) {
e = ISC_LIST_HEAD(adb->entries[i]);
while (e != NULL) {
ISC_LIST_UNLINK(adb->entries[i], e, plink);
bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
e->lock_bucket = bucket;
ISC_LIST_APPEND(newentries[bucket], e, plink);
INSIST(adb->entry_refcnt[i] > 0);
adb->entry_refcnt[i]--;
newentry_refcnt[bucket]++;
e = ISC_LIST_HEAD(adb->entries[i]);
}
e = ISC_LIST_HEAD(adb->deadentries[i]);
while (e != NULL) {
ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
e->lock_bucket = bucket;
ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
INSIST(adb->entry_refcnt[i] > 0);
adb->entry_refcnt[i]--;
newentry_refcnt[bucket]++;
e = ISC_LIST_HEAD(adb->deadentries[i]);
}
INSIST(adb->entry_refcnt[i] == 0);
adb->irefcnt--;
}
/*
* Cleanup old resources.
*/
DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
isc_mem_put(adb->mctx, adb->entries,
sizeof(*adb->entries) * adb->nentries);
isc_mem_put(adb->mctx, adb->deadentries,
sizeof(*adb->deadentries) * adb->nentries);
isc_mem_put(adb->mctx, adb->entrylocks,
sizeof(*adb->entrylocks) * adb->nentries);
isc_mem_put(adb->mctx, adb->entry_sd,
sizeof(*adb->entry_sd) * adb->nentries);
isc_mem_put(adb->mctx, adb->entry_refcnt,
sizeof(*adb->entry_refcnt) * adb->nentries);
/*
* Install new resources.
*/
adb->entries = newentries;
adb->deadentries = newdeadentries;
adb->entrylocks = newentrylocks;
adb->entry_sd = newentry_sd;
adb->entry_refcnt = newentry_refcnt;
adb->nentries = n;
/*
* Only on success do we set adb->growentries_sent to ISC_FALSE.
* This will prevent us being continuously being called on error.
*/
adb->growentries_sent = ISC_FALSE;
goto done;
cleanup:
if (newentries != NULL)
isc_mem_put(adb->mctx, newentries,
sizeof(*newentries) * n);
if (newdeadentries != NULL)
isc_mem_put(adb->mctx, newdeadentries,
sizeof(*newdeadentries) * n);
if (newentrylocks != NULL)
isc_mem_put(adb->mctx, newentrylocks,
sizeof(*newentrylocks) * n);
if (newentry_sd != NULL)
isc_mem_put(adb->mctx, newentry_sd,
sizeof(*newentry_sd) * n);
if (newentry_refcnt != NULL)
isc_mem_put(adb->mctx, newentry_refcnt,
sizeof(*newentry_refcnt) * n);
done:
isc_task_endexclusive(task);
LOCK(&adb->lock);
if (dec_adb_irefcnt(adb))
check_exit(adb);
UNLOCK(&adb->lock);
DP(ISC_LOG_INFO, "adb: grow_entries finished");
}
static void
grow_names(isc_task_t *task, isc_event_t *ev) {
dns_adb_t *adb;
dns_adbname_t *name;
dns_adbnamelist_t *newdeadnames = NULL;
dns_adbnamelist_t *newnames = NULL;
isc_boolean_t *newname_sd = NULL;
isc_mutex_t *newnamelocks = NULL;
isc_result_t result;
unsigned int *newname_refcnt = NULL;
unsigned int i, n, bucket;
adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb));
isc_event_free(&ev);
isc_task_beginexclusive(task);
i = 0;
while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
i++;
if (nbuckets[i] != 0)
n = nbuckets[i];
else
goto done;
DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
/*
* Are we shutting down?
*/
for (i = 0; i < adb->nnames; i++)
if (adb->name_sd[i])
goto cleanup;
/*
* Grab all the resources we need.
*/
newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
if (newnames == NULL || newdeadnames == NULL ||
newnamelocks == NULL || newname_sd == NULL ||
newname_refcnt == NULL)
goto cleanup;
/*
* Initialise the new resources.
*/
result = isc_mutexblock_init(newnamelocks, n);
if (result != ISC_R_SUCCESS)
goto cleanup;
for (i = 0; i < n; i++) {
ISC_LIST_INIT(newnames[i]);
ISC_LIST_INIT(newdeadnames[i]);
newname_sd[i] = ISC_FALSE;
newname_refcnt[i] = 0;
adb->irefcnt++;
}
/*
* Move names to new arrays.
*/
for (i = 0; i < adb->nnames; i++) {
name = ISC_LIST_HEAD(adb->names[i]);
while (name != NULL) {
ISC_LIST_UNLINK(adb->names[i], name, plink);
bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
name->lock_bucket = bucket;
ISC_LIST_APPEND(newnames[bucket], name, plink);
INSIST(adb->name_refcnt[i] > 0);
adb->name_refcnt[i]--;
newname_refcnt[bucket]++;
name = ISC_LIST_HEAD(adb->names[i]);
}
name = ISC_LIST_HEAD(adb->deadnames[i]);
while (name != NULL) {
ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
name->lock_bucket = bucket;
ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
INSIST(adb->name_refcnt[i] > 0);
adb->name_refcnt[i]--;
newname_refcnt[bucket]++;
name = ISC_LIST_HEAD(adb->deadnames[i]);
}
INSIST(adb->name_refcnt[i] == 0);
adb->irefcnt--;
}
/*
* Cleanup old resources.
*/
DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
isc_mem_put(adb->mctx, adb->names,
sizeof(*adb->names) * adb->nnames);
isc_mem_put(adb->mctx, adb->deadnames,
sizeof(*adb->deadnames) * adb->nnames);
isc_mem_put(adb->mctx, adb->namelocks,
sizeof(*adb->namelocks) * adb->nnames);
isc_mem_put(adb->mctx, adb->name_sd,
sizeof(*adb->name_sd) * adb->nnames);
isc_mem_put(adb->mctx, adb->name_refcnt,
sizeof(*adb->name_refcnt) * adb->nnames);
/*
* Install new resources.
*/
adb->names = newnames;
adb->deadnames = newdeadnames;
adb->namelocks = newnamelocks;
adb->name_sd = newname_sd;
adb->name_refcnt = newname_refcnt;
adb->nnames = n;
/*
* Only on success do we set adb->grownames_sent to ISC_FALSE.
* This will prevent us being continuously being called on error.
*/
adb->grownames_sent = ISC_FALSE;
goto done;
cleanup:
if (newnames != NULL)
isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
if (newdeadnames != NULL)
isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
if (newnamelocks != NULL)
isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
if (newname_sd != NULL)
isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
if (newname_refcnt != NULL)
isc_mem_put(adb->mctx, newname_refcnt,
sizeof(*newname_refcnt) * n);
done:
isc_task_endexclusive(task);
LOCK(&adb->lock);
if (dec_adb_irefcnt(adb))
check_exit(adb);
UNLOCK(&adb->lock);
DP(ISC_LOG_INFO, "adb: grow_names finished");
}
/*
* Requires the adbname bucket be locked and that no entry buckets be locked.
*
@@ -836,12 +1152,12 @@ violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
*/
static isc_boolean_t
shutdown_names(dns_adb_t *adb) {
int bucket;
unsigned int bucket;
isc_boolean_t result = ISC_FALSE;
dns_adbname_t *name;
dns_adbname_t *next_name;
for (bucket = 0; bucket < NBUCKETS; bucket++) {
for (bucket = 0; bucket < adb->nnames; bucket++) {
LOCK(&adb->namelocks[bucket]);
adb->name_sd[bucket] = ISC_TRUE;
@@ -881,12 +1197,12 @@ shutdown_names(dns_adb_t *adb) {
*/
static isc_boolean_t
shutdown_entries(dns_adb_t *adb) {
int bucket;
unsigned int bucket;
isc_boolean_t result = ISC_FALSE;
dns_adbentry_t *entry;
dns_adbentry_t *next_entry;
for (bucket = 0; bucket < NBUCKETS; bucket++) {
for (bucket = 0; bucket < adb->nentries; bucket++) {
LOCK(&adb->entrylocks[bucket]);
adb->entry_sd[bucket] = ISC_TRUE;
@@ -1306,6 +1622,16 @@ new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
ISC_LIST_INIT(name->finds);
ISC_LINK_INIT(name, plink);
LOCK(&adb->namescntlock);
adb->namescnt++;
if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) {
isc_event_t *event = &adb->grownames;
inc_adb_irefcnt(adb);
isc_task_send(adb->task, &event);
adb->grownames_sent = ISC_TRUE;
}
UNLOCK(&adb->namescntlock);
return (name);
}
@@ -1329,6 +1655,9 @@ free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
dns_name_free(&n->name, adb->mctx);
isc_mempool_put(adb->nmp, n);
LOCK(&adb->namescntlock);
adb->namescnt--;
UNLOCK(&adb->namescntlock);
}
static inline dns_adbnamehook_t *
@@ -1417,6 +1746,16 @@ new_adbentry(dns_adb_t *adb) {
e->expires = 0;
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
LOCK(&adb->entriescntlock);
adb->entriescnt++;
if (!adb->growentries_sent &&
adb->entriescnt > (adb->nentries * 8)) {
isc_event_t *event = &adb->growentries;
inc_adb_irefcnt(adb);
isc_task_send(adb->task, &event);
adb->growentries_sent = ISC_TRUE;
}
UNLOCK(&adb->entriescntlock);
return (e);
}
@@ -1444,6 +1783,9 @@ free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
}
isc_mempool_put(adb->emp, e);
LOCK(&adb->entriescntlock);
adb->entriescnt--;
UNLOCK(&adb->entriescntlock);
}
static inline dns_adbfind_t *
@@ -1597,7 +1939,7 @@ find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
dns_adbname_t *adbname;
int bucket;
bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS;
bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
LOCK(&adb->namelocks[bucket]);
@@ -1639,7 +1981,7 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
dns_adbentry_t *entry, *entry_next;
int bucket;
bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
LOCK(&adb->entrylocks[bucket]);
@@ -1992,13 +2334,36 @@ destroy(dns_adb_t *adb) {
isc_mempool_destroy(&adb->aimp);
isc_mempool_destroy(&adb->afmp);
DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
isc_mem_put(adb->mctx, adb->entries,
sizeof(*adb->entries) * adb->nentries);
isc_mem_put(adb->mctx, adb->deadentries,
sizeof(*adb->deadentries) * adb->nentries);
isc_mem_put(adb->mctx, adb->entrylocks,
sizeof(*adb->entrylocks) * adb->nentries);
isc_mem_put(adb->mctx, adb->entry_sd,
sizeof(*adb->entry_sd) * adb->nentries);
isc_mem_put(adb->mctx, adb->entry_refcnt,
sizeof(*adb->entry_refcnt) * adb->nentries);
DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
isc_mem_put(adb->mctx, adb->names,
sizeof(*adb->names) * adb->nnames);
isc_mem_put(adb->mctx, adb->deadnames,
sizeof(*adb->deadnames) * adb->nnames);
isc_mem_put(adb->mctx, adb->namelocks,
sizeof(*adb->namelocks) * adb->nnames);
isc_mem_put(adb->mctx, adb->name_sd,
sizeof(*adb->name_sd) * adb->nnames);
isc_mem_put(adb->mctx, adb->name_refcnt,
sizeof(*adb->name_refcnt) * adb->nnames);
DESTROYLOCK(&adb->reflock);
DESTROYLOCK(&adb->lock);
DESTROYLOCK(&adb->mplock);
DESTROYLOCK(&adb->overmemlock);
DESTROYLOCK(&adb->entriescntlock);
DESTROYLOCK(&adb->namescntlock);
isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
}
@@ -2014,7 +2379,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
{
dns_adb_t *adb;
isc_result_t result;
int i;
unsigned int i;
REQUIRE(mem != NULL);
REQUIRE(view != NULL);
@@ -2054,6 +2419,30 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->shutting_down = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
adb->nentries = nbuckets[0];
adb->entriescnt = 0;
adb->entries = NULL;
adb->deadentries = NULL;
adb->entry_sd = NULL;
adb->entry_refcnt = NULL;
adb->entrylocks = NULL;
ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
adb, NULL, NULL);
adb->growentries_sent = ISC_FALSE;
adb->nnames = nbuckets[0];
adb->namescnt = 0;
adb->names = NULL;
adb->deadnames = NULL;
adb->name_sd = NULL;
adb->name_refcnt = NULL;
adb->namelocks = NULL;
ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
DNS_EVENT_ADBGROWNAMES, grow_names, adb,
adb, NULL, NULL);
adb->grownames_sent = ISC_FALSE;
isc_mem_attach(mem, &adb->mctx);
result = isc_mutex_init(&adb->lock);
@@ -2072,28 +2461,68 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (result != ISC_R_SUCCESS)
goto fail0e;
result = isc_mutex_init(&adb->entriescntlock);
if (result != ISC_R_SUCCESS)
goto fail0f;
result = isc_mutex_init(&adb->namescntlock);
if (result != ISC_R_SUCCESS)
goto fail0g;
#define ALLOCENTRY(adb, el) \
do { \
(adb)->el = isc_mem_get((adb)->mctx, \
sizeof(*(adb)->el) * (adb)->nentries); \
if ((adb)->el == NULL) { \
result = ISC_R_NOMEMORY; \
goto fail1; \
}\
} while (0)
ALLOCENTRY(adb, entries);
ALLOCENTRY(adb, deadentries);
ALLOCENTRY(adb, entrylocks);
ALLOCENTRY(adb, entry_sd);
ALLOCENTRY(adb, entry_refcnt);
#undef ALLOCENTRY
#define ALLOCNAME(adb, el) \
do { \
(adb)->el = isc_mem_get((adb)->mctx, \
sizeof(*(adb)->el) * (adb)->nnames); \
if ((adb)->el == NULL) { \
result = ISC_R_NOMEMORY; \
goto fail1; \
}\
} while (0)
ALLOCNAME(adb, names);
ALLOCNAME(adb, deadnames);
ALLOCNAME(adb, namelocks);
ALLOCNAME(adb, name_sd);
ALLOCNAME(adb, name_refcnt);
#undef ALLOCNAME
/*
* Initialize the bucket locks for names and elements.
* May as well initialize the list heads, too.
*/
result = isc_mutexblock_init(adb->namelocks, NBUCKETS);
result = isc_mutexblock_init(adb->namelocks, adb->nnames);
if (result != ISC_R_SUCCESS)
goto fail1;
for (i = 0; i < NBUCKETS; i++) {
for (i = 0; i < adb->nnames; i++) {
ISC_LIST_INIT(adb->names[i]);
ISC_LIST_INIT(adb->deadnames[i]);
adb->name_sd[i] = ISC_FALSE;
adb->name_refcnt[i] = 0;
adb->irefcnt++;
}
for (i = 0; i < NBUCKETS; i++) {
for (i = 0; i < adb->nentries; i++) {
ISC_LIST_INIT(adb->entries[i]);
ISC_LIST_INIT(adb->deadentries[i]);
adb->entry_sd[i] = ISC_FALSE;
adb->entry_refcnt[i] = 0;
adb->irefcnt++;
}
result = isc_mutexblock_init(adb->entrylocks, NBUCKETS);
result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
if (result != ISC_R_SUCCESS)
goto fail2;
@@ -2140,12 +2569,42 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
isc_task_detach(&adb->task);
/* clean up entrylocks */
DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
fail2: /* clean up namelocks */
DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
fail1: /* clean up only allocated memory */
if (adb->entries != NULL)
isc_mem_put(adb->mctx, adb->entries,
sizeof(*adb->entries) * adb->nentries);
if (adb->deadentries != NULL)
isc_mem_put(adb->mctx, adb->deadentries,
sizeof(*adb->deadentries) * adb->nentries);
if (adb->entrylocks != NULL)
isc_mem_put(adb->mctx, adb->entrylocks,
sizeof(*adb->entrylocks) * adb->nentries);
if (adb->entry_sd != NULL)
isc_mem_put(adb->mctx, adb->entry_sd,
sizeof(*adb->entry_sd) * adb->nentries);
if (adb->entry_refcnt != NULL)
isc_mem_put(adb->mctx, adb->entry_refcnt,
sizeof(*adb->entry_refcnt) * adb->nentries);
if (adb->names != NULL)
isc_mem_put(adb->mctx, adb->names,
sizeof(*adb->names) * adb->nnames);
if (adb->deadnames != NULL)
isc_mem_put(adb->mctx, adb->deadnames,
sizeof(*adb->deadnames) * adb->nnames);
if (adb->namelocks != NULL)
isc_mem_put(adb->mctx, adb->namelocks,
sizeof(*adb->namelocks) * adb->nnames);
if (adb->name_sd != NULL)
isc_mem_put(adb->mctx, adb->name_sd,
sizeof(*adb->name_sd) * adb->nnames);
if (adb->name_refcnt != NULL)
isc_mem_put(adb->mctx, adb->name_refcnt,
sizeof(*adb->name_refcnt) * adb->nnames);
if (adb->nmp != NULL)
isc_mempool_destroy(&adb->nmp);
if (adb->nhmp != NULL)
@@ -2161,6 +2620,10 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (adb->afmp != NULL)
isc_mempool_destroy(&adb->afmp);
DESTROYLOCK(&adb->namescntlock);
fail0g:
DESTROYLOCK(&adb->entriescntlock);
fail0f:
DESTROYLOCK(&adb->overmemlock);
fail0e:
DESTROYLOCK(&adb->reflock);
@@ -2728,7 +3191,7 @@ dns_adb_cancelfind(dns_adbfind_t *find) {
void
dns_adb_dump(dns_adb_t *adb, FILE *f) {
int i;
unsigned int i;
isc_stdtime_t now;
REQUIRE(DNS_ADB_VALID(adb));
@@ -2744,9 +3207,9 @@ dns_adb_dump(dns_adb_t *adb, FILE *f) {
LOCK(&adb->lock);
isc_stdtime_get(&now);
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nnames; i++)
RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nentries; i++)
RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
dump_adb(adb, f, ISC_FALSE, now);
@@ -2762,7 +3225,7 @@ dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
static void
dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
int i;
unsigned int i;
dns_adbname_t *name;
dns_adbentry_t *entry;
@@ -2772,15 +3235,15 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
adb, adb->erefcnt, adb->irefcnt,
isc_mempool_getallocated(adb->nhmp));
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nnames; i++)
LOCK(&adb->namelocks[i]);
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nentries; i++)
LOCK(&adb->entrylocks[i]);
/*
* Dump the names
*/
for (i = 0; i < NBUCKETS; i++) {
for (i = 0; i < adb->nnames; i++) {
name = ISC_LIST_HEAD(adb->names[i]);
if (name == NULL)
continue;
@@ -2824,7 +3287,7 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
fprintf(f, ";\n; Unassociated entries\n;\n");
for (i = 0; i < NBUCKETS; i++) {
for (i = 0; i < adb->nentries; i++) {
entry = ISC_LIST_HEAD(adb->entries[i]);
while (entry != NULL) {
if (entry->refcnt == 0)
@@ -2836,9 +3299,9 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
/*
* Unlock everything
*/
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nentries; i++)
UNLOCK(&adb->entrylocks[i]);
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nnames; i++)
UNLOCK(&adb->namelocks[i]);
}
@@ -3567,9 +4030,9 @@ dns_adb_flush(dns_adb_t *adb) {
/*
* Call our cleanup routines.
*/
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nnames; i++)
RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
for (i = 0; i < NBUCKETS; i++)
for (i = 0; i < adb->nentries; i++)
RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
#ifdef DUMP_ADB_AFTER_CLEANING
@@ -3588,7 +4051,7 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
INSIST(DNS_ADB_VALID(adb));
LOCK(&adb->lock);
bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS;
bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
LOCK(&adb->namelocks[bucket]);
adbname = ISC_LIST_HEAD(adb->names[bucket]);
while (adbname != NULL) {

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: events.h,v 1.55 2010/05/10 23:50:55 tbox Exp $ */
/* $Id: events.h,v 1.56 2010/12/21 03:11:42 marka Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
@@ -72,6 +72,8 @@
#define DNS_EVENT_MANAGEKEYS (ISC_EVENTCLASS_DNS + 42)
#define DNS_EVENT_CLIENTRESDONE (ISC_EVENTCLASS_DNS + 43)
#define DNS_EVENT_CLIENTREQDONE (ISC_EVENTCLASS_DNS + 44)
#define DNS_EVENT_ADBGROWENTRIES (ISC_EVENTCLASS_DNS + 45)
#define DNS_EVENT_ADBGROWNAMES (ISC_EVENTCLASS_DNS + 46)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)