From 294802790e8030f1c19b6c2c5d5204b6f464c729 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Wed, 24 Nov 1999 19:23:27 +0000 Subject: [PATCH] Fix a lot of negative caching issues. I believe the code will use ncache responses from fetches and database lookups correctly now, but there needs to be a little more cleanup here and there. Bugs exist. --- lib/dns/adb.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 034a7039d3..cdc132dc3f 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -25,6 +25,11 @@ * */ +/* + * After we have cleaned all buckets, dump the database contents. + */ +#define DUMP_ADB_AFTER_CLEANING + #include #include @@ -352,6 +357,10 @@ static isc_result_t dbfind_a6(dns_adbname_t *, isc_stdtime_t, isc_boolean_t); #define CLEAN_LEVEL 100 #define DEF_LEVEL 5 +#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \ + (r) == DNS_R_NCACHENXRRSET) + + static void DP(int level, char *format, ...) { @@ -462,12 +471,17 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset, UNLOCK(&adb->entrylocks[addr_bucket]); if (new_addresses_added) { - if (rdtype == dns_rdatatype_a) + if (rdtype == dns_rdatatype_a) { + DP(1, "expire_v4 set to MIN(%u,%u) import_rdataset", + adbname->expire_v4, now + rdataset->ttl); adbname->expire_v4 = ISC_MIN(adbname->expire_v4, now + rdataset->ttl); - else + } else { + DP(1, "expire_v6 set to MIN(%u,%u) import_rdataset", + adbname->expire_v6, now + rdataset->ttl); adbname->expire_v6 = ISC_MIN(adbname->expire_v6, now + rdataset->ttl); + } /* * Lie a little here. This is more or less so code that cares @@ -538,6 +552,8 @@ import_a6(dns_a6context_t *a6ctx) if (addr_bucket != DNS_ADB_INVALIDBUCKET) UNLOCK(&adb->entrylocks[addr_bucket]); + DP(1, "expire_v6 set to MIN(%u,%u) in import_v6", + name->expire_v6, a6ctx->expiration); name->expire_v6 = ISC_MIN(name->expire_v6, a6ctx->expiration); if (address_added) @@ -1739,6 +1755,7 @@ cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) dns_adbname_t *next_name; DP(CLEAN_LEVEL, "cleaning bucket %d", bucket); + LOCK(&adb->namelocks[bucket]); if (adb->name_sd[bucket]) { UNLOCK(&adb->namelocks[bucket]); @@ -1785,8 +1802,12 @@ timer_cleanup(isc_task_t *task, isc_event_t *ev) * Set the next bucket to be cleaned. */ adb->next_namebucket++; - if (adb->next_namebucket >= NBUCKETS) + if (adb->next_namebucket >= NBUCKETS) { adb->next_namebucket = 0; +#ifdef DUMP_ADB_AFTER_CLEANING + dump_adb(adb, stdout); +#endif + } #if 0 /* @@ -2195,6 +2216,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, goto v6; } + /* + * Listen to negative cache hints, and don't start + * another query. + */ + if (NCACHE_RESULT(result)) + goto v6; + /* * Try to start fetches for v4. */ @@ -2219,6 +2247,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, goto copy; } + /* + * Listen to negative cache hints, and don't start + * another query. + */ + if (NCACHE_RESULT(result)) + goto copy; + /* * Try to start fetches for a6. */ @@ -2899,10 +2934,10 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, */ if (rdtype == dns_rdatatype_a) { adbname->expire_v4 = rdataset.ttl + now; - DP(3, "adb name %p: Caching negative entry for A (ttl %u)", + DP(1, "adb name %p: Caching negative entry for A (ttl %u)", adbname, rdataset.ttl); } else { - DP(3, "adb name %p: Caching negative entry for AAAA (ttl %u)", + DP(1, "adb name %p: Caching negative entry for AAAA (ttl %u)", adbname, rdataset.ttl); adbname->expire_v6 = rdataset.ttl + now; } @@ -2954,7 +2989,10 @@ dbfind_a6(dns_adbname_t *adbname, isc_stdtime_t now, isc_boolean_t use_hints) * We found a negative cache entry. Pull the TTL from it * so we won't ask again for a while. */ - adbname->expire_v6 = rdataset.ttl + now; + DP(1, "adb name %p: Caching negative entry for A6 (ttl %u)", + adbname, rdataset.ttl); + adbname->expire_v6 = ISC_MIN(rdataset.ttl + now, + adbname->expire_v6); } if (dns_rdataset_isassociated(&rdataset)) @@ -3043,6 +3081,26 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) return; } + /* + * If we got a negative cache response, remember it. + */ + if (NCACHE_RESULT(dev->result)) { + if (address_type == DNS_ADBFIND_INET) { + DP(1, "adb fetch name %p: " + "Caching negative entry for A (ttl %u)", + name, dev->rdataset->ttl); + name->expire_v4 = ISC_MIN(name->expire_v4, + dev->rdataset->ttl + now); + } else { + DP(1, "adb fetch name %p: " + "Caching negative entry for AAAA (ttl %u)", + name, dev->rdataset->ttl); + name->expire_v6 = ISC_MIN(name->expire_v6, + dev->rdataset->ttl + now); + } + goto out; + } + /* * Did we get back junk? If so, and there are no more fetches * sitting out there, tell all the finds about it. @@ -3053,6 +3111,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); else name->expire_v6 = ISC_MIN(name->expire_v6, now + 300); + DP(1, "got junk in fetch for name %p (%s)", + name, isc_result_totext(dev->result)); goto out; } @@ -3163,6 +3223,17 @@ fetch_callback_a6(isc_task_t *task, isc_event_t *ev) DP(DEF_LEVEL, "name %p: A6 failed, result %u", name, dev->result); + /* + * If we got a negative cache response, remember it. + */ + if (NCACHE_RESULT(dev->result)) { + DP(1, "adb fetch name %p: " + "Caching negative entry for A6 (ttl %u)", + name, dev->rdataset->ttl); + name->expire_v6 = ISC_MIN(name->expire_v6, + dev->rdataset->ttl + now); + } + if (FETCH_USEHINTS(fetch)) use_hints = ISC_TRUE; else @@ -3187,6 +3258,13 @@ fetch_callback_a6(isc_task_t *task, isc_event_t *ev) goto out; } + /* + * Listen to negative cache hints, and don't start + * another query. + */ + if (NCACHE_RESULT(result)) + goto out; + /* * Try to start fetches for AAAA. */