Commit 5c024f78 authored by Tatuya JINMEI 神明達哉's avatar Tatuya JINMEI 神明達哉
Browse files

cleanups for LRU-caching code [RT #18018]

parent 62fd1414
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: config.c,v 1.86 2008/04/03 02:01:08 marka Exp $ */
/* $Id: config.c,v 1.87 2008/05/01 18:23:06 jinmei Exp $ */
/*! \file */
......@@ -124,7 +124,7 @@ options {\n\
query-source-v6 address *;\n\
notify-source *;\n\
notify-source-v6 *;\n\
cleaning-interval 60;\n\
cleaning-interval 0; /* now meaningless */\n\
min-roots 2;\n\
lame-ttl 600;\n\
max-ncache-ttl 10800; /* 3 hours */\n\
......
......@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
 
<!-- File: $Id: Bv9ARM-book.xml,v 1.350 2008/04/09 22:48:17 jinmei Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.351 2008/05/01 18:23:06 jinmei Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
 
......@@ -6870,11 +6870,14 @@ query-source-v6 address * port *;
<term><command>cleaning-interval</command></term>
<listitem>
<para>
The server will remove expired resource records
This interval is effectively obsolete. Previously,
the server would remove expired resource records
from the cache every <command>cleaning-interval</command> minutes.
The default is 60 minutes. The maximum value is 28 days
(40320 minutes).
If set to 0, no periodic cleaning will occur.
<acronym>BIND</acronym> 9 now manages cache
memory in a more sophisticated manner and does not
rely on the periodic cleaning any more.
Specifying this option therefore has no effect on
the server's behavior.
</para>
</listitem>
</varlistentry>
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: adb.c,v 1.238 2008/04/03 06:09:04 tbox Exp $ */
/* $Id: adb.c,v 1.239 2008/05/01 18:23:07 jinmei Exp $ */
/*! \file
*
......@@ -26,13 +26,6 @@
*
*/
/*%
* After we have cleaned all buckets, dump the database contents.
*/
#if 0
#define DUMP_ADB_AFTER_CLEANING
#endif
#include <config.h>
#include <limits.h>
......@@ -42,7 +35,6 @@
#include <isc/random.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
#include <dns/adb.h>
......@@ -89,16 +81,6 @@
#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
#define ADB_ENTRY_WINDOW 1800 /*%< seconds */
/*%
* Wake up every CLEAN_SECONDS and clean CLEAN_BUCKETS buckets, so that all
* buckets are cleaned in CLEAN_PERIOD seconds.
*/
#define CLEAN_PERIOD 3600
/*% See #CLEAN_PERIOD */
#define CLEAN_SECONDS 30
/*% See #CLEAN_PERIOD */
#define CLEAN_BUCKETS ((NBUCKETS * CLEAN_SECONDS) / CLEAN_PERIOD)
/*%
* The period in seconds after which an ADB name entry is regarded as stale
* and forced to be cleaned up.
......@@ -132,14 +114,6 @@ struct dns_adb {
isc_mutex_t overmemlock; /*%< Covers overmem */
isc_mem_t *mctx;
dns_view_t *view;
isc_timermgr_t *timermgr;
isc_timer_t *timer;
#ifdef LRU_DEBUG
isc_timer_t *dump_timer; /* for test */
isc_time_t dump_time; /* for test */
#define DUMP_INTERVAL 30 /* seconds */
#endif
isc_taskmgr_t *taskmgr;
isc_task_t *task;
......@@ -187,17 +161,6 @@ struct dns_adb {
isc_boolean_t cevent_sent;
isc_boolean_t shutting_down;
isc_eventlist_t whenshutdown;
#ifdef LRU_DEBUG
unsigned int stale_purge;
unsigned int stale_scan;
unsigned int stale_expire;
unsigned int stale_lru;
unsigned int nname, nname_total;
unsigned int nentry, nentry_total;
unsigned int nameuses, entryuses;
#endif
};
/*
......@@ -344,7 +307,6 @@ static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
dns_rdatatype_t);
static inline void check_exit(dns_adb_t *);
static void timer_cleanup(isc_task_t *, isc_event_t *);
static void destroy(dns_adb_t *);
static isc_boolean_t shutdown_names(dns_adb_t *);
static isc_boolean_t shutdown_entries(dns_adb_t *);
......@@ -357,10 +319,6 @@ static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t,
static void water(void *, int);
static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
#ifdef LRU_DEBUG
static void timer_dump(isc_task_t *, isc_event_t *);
#endif
/*
* MUST NOT overlap DNS_ADBFIND_* flags!
*/
......@@ -1332,11 +1290,6 @@ free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
INSIST(n->adb == adb);
#ifdef LRU_DEBUG
adb->nname--; /* XXX: omit ADB lock for brevity */
INSIST((int)adb->nname >= 0);
#endif
n->magic = 0;
dns_name_free(&n->name, adb->mctx);
......@@ -1430,11 +1383,6 @@ new_adbentry(dns_adb_t *adb) {
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
#ifdef LRU_DEBUG
adb->nentry++; /* XXX: omit ADB lock for brevity */
adb->nentry_total++;
#endif
return (e);
}
......@@ -1460,11 +1408,6 @@ free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
li = ISC_LIST_HEAD(e->lameinfo);
}
#ifdef LRU_DEBUG
adb->nentry--; /* XXX: omit ADB lock for brevity */
INSIST((int)adb->nentry >= 0);
#endif
isc_mempool_put(adb->emp, e);
}
......@@ -1609,10 +1552,6 @@ new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
ai->entry = entry;
ISC_LINK_INIT(ai, publink);
#ifdef LRU_DEBUG
adb->entryuses++; /* for debug */
#endif
return (ai);
}
......@@ -1832,18 +1771,6 @@ shutdown_task(isc_task_t *task, isc_event_t *ev) {
adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb));
/*
* Kill the timer, and then the ADB itself. Note that this implies
* that this task was the one scheduled to get timer events. If
* this is not true (and it is unfortunate there is no way to INSIST()
* this) badness will occur.
*/
LOCK(&adb->lock);
isc_timer_detach(&adb->timer);
#ifdef LRU_DEBUG
isc_timer_detach(&adb->dump_timer);
#endif
UNLOCK(&adb->lock);
isc_event_free(&ev);
destroy(adb);
}
......@@ -1928,9 +1855,6 @@ check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
result = check_expire_name(&victim, now);
if (victim == NULL) {
#ifdef LRU_DEBUG
adb->stale_expire++;
#endif
victims++;
goto next;
}
......@@ -1941,9 +1865,6 @@ check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
DNS_EVENT_ADBCANCELED,
ISC_TRUE) ==
ISC_FALSE);
#ifdef LRU_DEBUG
adb->stale_lru++;
#endif
victims++;
}
......@@ -1951,12 +1872,6 @@ check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
if (!overmem)
break;
}
#ifdef LRU_DEBUG
/* XXX: omit lock for brevity */
adb->stale_scan += scans;
adb->stale_purge += victims;
#endif
}
/*
......@@ -2042,96 +1957,10 @@ cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
return (result);
}
#if 1
static void
timer_cleanup(isc_task_t *task, isc_event_t *ev) {
UNUSED(task);
isc_event_free(&ev);
}
#else
static void
timer_cleanup(isc_task_t *task, isc_event_t *ev) {
dns_adb_t *adb;
isc_stdtime_t now;
unsigned int i;
isc_interval_t interval;
UNUSED(task);
adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb));
LOCK(&adb->lock);
isc_stdtime_get(&now);
for (i = 0; i < CLEAN_BUCKETS; i++) {
/*
* Call our cleanup routines.
*/
RUNTIME_CHECK(cleanup_names(adb, adb->next_cleanbucket, now) ==
ISC_FALSE);
RUNTIME_CHECK(cleanup_entries(adb, adb->next_cleanbucket, now)
== ISC_FALSE);
/*
* Set the next bucket to be cleaned.
*/
adb->next_cleanbucket++;
if (adb->next_cleanbucket >= NBUCKETS) {
adb->next_cleanbucket = 0;
#ifdef DUMP_ADB_AFTER_CLEANING
dump_adb(adb, stdout, ISC_TRUE, now);
#endif
}
}
/*
* Reset the timer.
* XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or
* ISC_R_NOMEMORY, but it isn't clear what could be done here
* if either one of those things happened.
*/
interval = adb->tick_interval;
if (adb->overmem)
isc_interval_set(&interval, 0, 1);
(void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
&interval, ISC_FALSE);
UNLOCK(&adb->lock);
isc_event_free(&ev);
}
#endif
static void
destroy(dns_adb_t *adb) {
adb->magic = 0;
#ifdef LRU_DEBUG
/* for debug: print statistics */
if (adb->nname_total > 0) {
INSIST(adb->nname == 0 && adb->nentry == 0);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_ADB, ISC_LOG_INFO,
"ADB %p name hit %.2f, entry hit %.2f", adb,
(double)adb->nameuses /
(adb->nname_total + adb->nameuses),
adb->entryuses > 0 ?
(double)adb->entryuses /
(adb->nentry_total + adb->entryuses) : 0);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_ADB, ISC_LOG_INFO,
"ADB %p stale name purges: %u(%u,%u)/%u",
adb, adb->stale_purge, adb->stale_expire,
adb->stale_lru, adb->stale_scan);
}
#endif
/*
* The timer is already dead, from the task's shutdown callback.
*/
isc_task_detach(&adb->task);
isc_mempool_destroy(&adb->nmp);
......@@ -2168,10 +1997,12 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
REQUIRE(mem != NULL);
REQUIRE(view != NULL);
REQUIRE(timermgr != NULL);
REQUIRE(timermgr != NULL); /* this is actually unused */
REQUIRE(taskmgr != NULL);
REQUIRE(newadb != NULL && *newadb == NULL);
UNUSED(timermgr);
adb = isc_mem_get(mem, sizeof(dns_adb_t));
if (adb == NULL)
return (ISC_R_NOMEMORY);
......@@ -2191,13 +2022,8 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->aimp = NULL;
adb->afmp = NULL;
adb->task = NULL;
adb->timer = NULL;
#ifdef LRU_DEBUG
adb->dump_timer = NULL;
#endif
adb->mctx = NULL;
adb->view = view;
adb->timermgr = timermgr;
adb->taskmgr = taskmgr;
adb->next_cleanbucket = 0;
ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
......@@ -2208,20 +2034,6 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->overmem = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
#ifdef LRU_DEBUG
/* for debug */
adb->nname = 0;
adb->nname_total = 0;
adb->nentry = 0;
adb->nentry_total = 0;
adb->stale_purge = 0;
adb->stale_scan = 0;
adb->stale_expire = 0;
adb->stale_lru = 0;
adb->nameuses = 0;
adb->entryuses = 0;
#endif
isc_mem_attach(mem, &adb->mctx);
result = isc_mutex_init(&adb->lock);
......@@ -2287,41 +2099,12 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
#undef MPINIT
/*
* Allocate a timer and a task for our periodic cleanup.
* Allocate an internal task.
*/
result = isc_task_create(adb->taskmgr, 0, &adb->task);
if (result != ISC_R_SUCCESS)
goto fail3;
isc_task_setname(adb->task, "ADB", adb);
/*
* XXXMLG When this is changed to be a config file option,
*/
isc_interval_set(&adb->tick_interval, CLEAN_SECONDS, 0);
result = isc_timer_create(adb->timermgr, isc_timertype_once,
NULL, &adb->tick_interval, adb->task,
timer_cleanup, adb, &adb->timer);
if (result != ISC_R_SUCCESS)
goto fail3;
#ifdef LRU_DEBUG
{
isc_interval_t interval;
interval.seconds = DUMP_INTERVAL;
interval.nanoseconds = 0;
RUNTIME_CHECK(isc_time_nowplusinterval(&adb->dump_time,
&interval) ==
ISC_R_SUCCESS);
result = isc_timer_create(adb->timermgr, isc_timertype_once,
&adb->dump_time, NULL, adb->task,
timer_dump, adb, &adb->dump_timer);
}
#endif
DP(ISC_LOG_DEBUG(5), "cleaning interval for adb: "
"%u buckets every %u seconds, %u buckets in system, %u cl.interval",
CLEAN_BUCKETS, CLEAN_SECONDS, NBUCKETS, CLEAN_PERIOD);
/*
* Normal return.
......@@ -2333,8 +2116,6 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
fail3:
if (adb->task != NULL)
isc_task_detach(&adb->task);
if (adb->timer != NULL)
isc_timer_detach(&adb->timer);
/* clean up entrylocks */
DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
......@@ -2578,18 +2359,10 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
adbname->flags |= NAME_GLUE_OK;
if (FIND_STARTATZONE(find))
adbname->flags |= NAME_STARTATZONE;
#ifdef LRU_DEBUG
adb->nname++; /* XXX: omit ADB lock for brevity */
adb->nname_total++;
#endif
} else {
/* Move this name forward in the LRU list */
ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
#ifdef LRU_DEBUG
adb->nameuses++;
#endif
}
adbname->last_used = now;
......@@ -3813,15 +3586,6 @@ water(void *arg, int mark) {
LOCK(&adb->overmemlock);
if (adb->overmem != overmem) {
adb->overmem = overmem;
#if 0 /* we don't need this timer for the new cleaning policy. */
if (overmem) {
isc_interval_t interval;
isc_interval_set(&interval, 0, 1);
(void)isc_timer_reset(adb->timer, isc_timertype_once,
NULL, &interval, ISC_TRUE);
}
#endif
isc_mem_waterack(adb->mctx, mark);
}
UNLOCK(&adb->overmemlock);
......@@ -3845,47 +3609,3 @@ dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) {
else
isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
}
#ifdef LRU_DEBUG
/*
* Periodic dumping of the internal state of the statistics.
* This will dump the cache contents, uses, record types, etc.
*/
static void
timer_dump(isc_task_t *task, isc_event_t *ev) {
dns_adb_t *adb;
isc_interval_t interval;
isc_time_t nexttime;
UNUSED(task);
adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb));
LOCK(&adb->lock);
if (adb->nname > 0 || adb->nentry > 0) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_ADB, ISC_LOG_INFO,
"ADB memory usage %p: mem inuse %lu, "
"%u/%u names, %u/%u entries, "
"purge/scan=%u(%u,%u)/%u, overmem=%d",
adb, (unsigned long)isc_mem_inuse(adb->mctx),
adb->nname, adb->nname_total,
adb->nentry, adb->nentry_total,
adb->stale_purge, adb->stale_expire,
adb->stale_lru, adb->stale_scan, adb->overmem);
}
interval.seconds = DUMP_INTERVAL;
interval.nanoseconds = 0;
RUNTIME_CHECK(isc_time_add(&adb->dump_time, &interval, &nexttime) ==
ISC_R_SUCCESS); /* XXX: this is not always true */
adb->dump_time = nexttime;
(void)isc_timer_reset(adb->dump_timer, isc_timertype_once,
&adb->dump_time, NULL, ISC_FALSE);
UNLOCK(&adb->lock);
isc_event_free(&ev);
}
#endif
This diff is collapsed.
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbtdb.c,v 1.259 2008/04/23 21:32:01 each Exp $ */
/* $Id: rbtdb.c,v 1.260 2008/05/01 18:23:07 jinmei Exp $ */
/*! \file */
......@@ -275,8 +275,6 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
#define RDATASET_ATTR_NXDOMAIN 0x0010
#define RDATASET_ATTR_RESIGN 0x0020
#define RDATASET_ATTR_STATCOUNT 0x0040
#define RDATASET_ATTR_CACHE 0x1000 /* for debug */
#define RDATASET_ATTR_CANCELED 0x2000 /* for debug */
typedef struct acache_cbarg {
dns_rdatasetadditional_t type;
......@@ -352,33 +350,6 @@ typedef struct rbtdb_version {
typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
#ifdef LRU_DEBUG
/* statistics info for testing */
struct cachestat {
unsigned int cache_total;
int cache_current;
unsigned int ncache_total;
int ncache_current;
unsigned int a_total;
int a_current;
unsigned int aaaa_total;
int aaaa_current;
unsigned int ns_total;
int ns_current;
unsigned int ptr_total;
int ptr_current;
unsigned int glue_total;
int glue_current;
unsigned int additional_total;
int additional_current;
unsigned int stale_purge;
unsigned int stale_scan;
unsigned int stale_expire;
unsigned int stale_lru;
};
#endif
typedef enum {
dns_db_insecure,
dns_db_partial,
......@@ -437,9 +408,6 @@ typedef struct {
/* Unlocked */
unsigned int quantum;
#ifdef LRU_DEBUG
struct cachestat cachestat;
#endif
} dns_rbtdb_t;
#define RBTDB_ATTR_LOADED 0x01
......@@ -922,41 +890,6 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
if (rbtdb->task != NULL)
isc_task_detach(&rbtdb->task);
#ifdef LRU_DEBUG
/* Experimental logging about memory usage */
if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_INFO,
"cache DB %p: mem inuse %lu, XXX node, "
"%d/%u current/total cache, %d/%u neg, %d/%u A, %d/%u AAAA, "
"%d/%u NS, %d/%u PTR, %d/%u glue, "
"%d/%u additional, purge/scan=%u(%u expiry, %u lru)/%u, "
"overmem=%d",
rbtdb,
(unsigned long)isc_mem_inuse(rbtdb->common.mctx),
rbtdb->cachestat.cache_current, rbtdb->cachestat.cache_total,
rbtdb->cachestat.ncache_current, rbtdb->cachestat.ncache_total,
rbtdb->cachestat.a_current, rbtdb->cachestat.a_total,
rbtdb->cachestat.aaaa_current, rbtdb->cachestat.aaaa_total,
rbtdb->cachestat.ns_current, rbtdb->cachestat.ns_total,
rbtdb->cachestat.ptr_current, rbtdb->cachestat.ptr_total,
rbtdb->cachestat.glue_current, rbtdb->cachestat.glue_total,
rbtdb->cachestat.additional_current,
rbtdb->cachestat.additional_total,
rbtdb->cachestat.stale_purge, rbtdb->cachestat.stale_expire,
rbtdb->cachestat.stale_lru, rbtdb->cachestat.stale_scan,
rbtdb->overmem);
INSIST(rbtdb->cachestat.cache_current == 0);
INSIST(rbtdb->cachestat.ncache_current == 0);
INSIST(rbtdb->cachestat.a_current == 0);
INSIST(rbtdb->cachestat.aaaa_current == 0);
INSIST(rbtdb->cachestat.ns_current == 0);
INSIST(rbtdb->cachestat.ptr_current == 0);
INSIST(rbtdb->cachestat.glue_current == 0);
INSIST(rbtdb->cachestat.additional_current == 0);
}
#endif
RBTDB_DESTROYLOCK(&rbtdb->lock);
rbtdb->common.magic = 0;
rbtdb->common.impmagic = 0;
......@@ -1231,69 +1164,6 @@ free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
update_rrsetstats(rbtdb, rdataset, ISC_FALSE);
}
#ifdef LRU_DEBUG
/*
* for debug: statistics update.
* Nothing in this block should have any side-effects.
*/
if (EXISTS(rdataset) &&
(rdataset->attributes & RDATASET_ATTR_CACHE) != 0) {
rbtdb->cachestat.cache_current--;
if ((rdataset->attributes & RDATASET_ATTR_CANCELED) != 0)
rbtdb->cachestat.cache_total--;
if (RBTDB_RDATATYPE_BASE(rdataset->type) == 0) {
rbtdb->cachestat.ncache_current--;
INSIST(rbtdb->cachestat.ncache_current >= 0);
if ((rdataset->attributes & RDATASET_ATTR_CANCELED)
!= 0)
rbtdb->cachestat.ncache_total--;
}
if