Commit 3a34b87c authored by Mark Andrews's avatar Mark Andrews
Browse files

Add cache cleaning support (disabled).

parent a21fbfdd
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.216 2000/08/24 22:15:28 bwelling Exp $ */
/* $Id: server.c,v 1.217 2000/08/31 12:15:07 marka Exp $ */
#include <config.h>
......@@ -406,6 +406,7 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
dns_cache_t *cache = NULL;
isc_result_t result;
isc_uint32_t cleaning_interval;
isc_uint32_t max_cache_size;
dns_tsig_keyring_t *ring;
dns_c_iplist_t *forwarders;
dns_view_t *pview = NULL; /* Production view */
......@@ -470,6 +471,19 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
cleaning_interval = 3600; /* Default is 1 hour. */
dns_cache_setcleaninginterval(cache, cleaning_interval);
result = ISC_R_NOTFOUND;
if (cview != NULL)
result = dns_c_view_getmaxcachesize(cview, &max_cache_size);
if (result != ISC_R_SUCCESS)
result = dns_c_ctx_getmaxcachesize(cctx, &max_cache_size);
if (result != ISC_R_SUCCESS)
max_cache_size = 0;
/*
* XXX remove once rbt if fixed
*/
max_cache_size = 0;
dns_cache_setcachesize(cache, max_cache_size);
dns_cache_detach(&cache);
/*
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: cache.c,v 1.29 2000/08/26 01:36:47 bwelling Exp $ */
/* $Id: cache.c,v 1.30 2000/08/31 12:15:08 marka Exp $ */
#include <config.h>
......@@ -69,11 +69,13 @@ struct cache_cleaner {
isc_timer_t *cleaning_timer;
isc_event_t *resched_event; /* Sent by cleaner task to
itself to reschedule */
isc_event_t *overmem_event;
dns_dbiterator_t *iterator;
int increment; /* Number of names to
clean in one increment */
cleaner_state_t state; /* Idle/Busy. */
isc_boolean_t overmem; /* The cache is in a overmem state */
};
/*
......@@ -117,6 +119,9 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event);
static void
cleaner_shutdown_action(isc_task_t *task, isc_event_t *event);
static void
overmem_cleaning_action(isc_task_t *task, isc_event_t *event);
isc_result_t
dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
......@@ -186,9 +191,14 @@ cache_free(dns_cache_t *cache) {
REQUIRE(VALID_CACHE(cache));
REQUIRE(cache->references == 0);
isc_mem_setwater(cache->mctx, NULL, NULL, 0, 0);
if (cache->cleaner.task != NULL)
isc_task_detach(&cache->cleaner.task);
if (cache->cleaner.overmem_event != NULL)
isc_event_free(&cache->cleaner.overmem_event);
if (cache->cleaner.resched_event != NULL)
isc_event_free(&cache->cleaner.resched_event);
......@@ -236,8 +246,10 @@ dns_cache_detach(dns_cache_t **cachep) {
LOCK(&cache->lock);
REQUIRE(cache->references > 0);
cache->references--;
if (cache->references == 0)
if (cache->references == 0) {
cache->cleaner.overmem = ISC_FALSE;
free_cache = ISC_TRUE;
}
UNLOCK(&cache->lock);
*cachep = NULL;
if (free_cache) {
......@@ -337,10 +349,12 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
cleaner->state = cleaner_s_idle;
cleaner->cache = cache;
cleaner->iterator = NULL;
cleaner->overmem = ISC_FALSE;
cleaner->task = NULL;
cleaner->cleaning_timer = NULL;
cleaner->resched_event = NULL;
cleaner->overmem_event = NULL;
if (taskmgr != NULL && timermgr != NULL) {
result = isc_task_create(taskmgr, 1, &cleaner->task);
......@@ -387,11 +401,23 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
result = ISC_R_NOMEMORY;
goto cleanup;
}
cleaner->overmem_event =
isc_event_allocate(cache->mctx, cleaner,
DNS_EVENT_CACHEOVERMEM,
overmem_cleaning_action,
cleaner, sizeof(isc_event_t));
if (cleaner->overmem_event == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
}
return (ISC_R_SUCCESS);
cleanup:
if (cleaner->resched_event != NULL)
isc_event_free(&cleaner->resched_event);
if (cleaner->cleaning_timer != NULL)
isc_timer_detach(&cleaner->cleaning_timer);
if (cleaner->task != NULL)
......@@ -479,6 +505,21 @@ cleaning_timer_action(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
}
static void
overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {
cache_cleaner_t *cleaner = event->ev_arg;
UNUSED(task);
INSIST(task == cleaner->task);
INSIST(event->ev_type == DNS_EVENT_CACHEOVERMEM);
INSIST(cleaner->overmem_event == NULL);
if (cleaner->state == cleaner_s_idle)
begin_cleaning(cleaner);
cleaner->overmem_event = event;
}
/*
* Do incremental cleaning.
*/
......@@ -547,6 +588,9 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
}
}
#if 0
pause:
#endif
/*
* We have successfully performed a cleaning increment.
*/
......@@ -572,6 +616,24 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
*/
end_cleaning(cleaner, event);
INSIST(CLEANER_IDLE(cleaner));
if (cleaner->overmem) {
/* Allow the iterators memory to be freed. */
if (cleaner->overmem_event != NULL) {
/* XXX remove */
fprintf(stderr, "overmem: restart\n");
isc_task_send(cleaner->task,
&cleaner->overmem_event);
}
#if 0
result = dns_dbiterator_first(cleaner->iterator);
if (result == ISC_R_SUCCESS) {
fprintf(stderr, "overmem: resetting and pausing\n");
goto pause;
}
fprintf(stderr, "dns_dbiterator_first: %s\n",
dns_result_totext(result));
#endif
}
return;
}
......@@ -583,6 +645,8 @@ dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now) {
isc_result_t result;
dns_dbiterator_t *iterator = NULL;
REQUIRE(VALID_CACHE(cache));
result = dns_db_createiterator(cache->db, ISC_FALSE, &iterator);
if (result != ISC_R_SUCCESS)
return result;
......@@ -626,6 +690,45 @@ dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now) {
return result;
}
static void
water(void *arg, int mark) {
dns_cache_t *cache = arg;
isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
REQUIRE(VALID_CACHE(cache));
dns_db_overmem(cache->db, overmem);
cache->cleaner.overmem = overmem;
if (overmem && cache->cleaner.overmem_event != NULL) {
isc_task_send(cache->cleaner.task,
&cache->cleaner.overmem_event);
}
}
void
dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
isc_uint32_t lowater;
isc_uint32_t hiwater;
REQUIRE(VALID_CACHE(cache));
#if 0
/* Impose a minumum cache size. */
if (size != 0 && size < 100000)
size = 100000;
#endif
hiwater = size - (size >> 3); /* ~(7/8) */
lowater = size - (size >> 2); /* ~(3/4) */
cache->cleaner.overmem = ISC_FALSE;
dns_db_overmem(cache->db, ISC_FALSE);
if (size == 0 || hiwater == 0 || lowater == 0) {
dns_db_overmem(cache->db, ISC_FALSE);
} else {
isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater);
}
}
/*
* The cleaner task is shutting down; do the necessary cleanup.
*/
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.c,v 1.54 2000/08/21 22:19:04 bwelling Exp $ */
/* $Id: db.c,v 1.55 2000/08/31 12:15:09 marka Exp $ */
/***
*** Imports
......@@ -624,6 +624,14 @@ dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
type, covers));
}
void
dns_db_overmem(dns_db_t *db, isc_boolean_t overmem) {
REQUIRE(DNS_DB_VALID(db));
(db->methods->overmem)(db, overmem);
}
isc_result_t
dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp)
{
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: cache.h,v 1.13 2000/08/01 01:23:43 tale Exp $ */
/* $Id: cache.h,v 1.14 2000/08/31 12:15:12 marka Exp $ */
#ifndef DNS_CACHE_H
#define DNS_CACHE_H 1
......@@ -219,6 +219,12 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int interval);
* Set the periodic cache cleaning interval to 'interval' seconds.
*/
void
dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size);
/*
* Set cache size. 0 => infinite.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_CACHE_H */
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.h,v 1.56 2000/08/22 01:20:05 bwelling Exp $ */
/* $Id: db.h,v 1.57 2000/08/31 12:15:13 marka Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
......@@ -140,6 +140,7 @@ typedef struct dns_dbmethods {
dns_rdatatype_t type,
dns_rdatatype_t covers);
isc_boolean_t (*issecure)(dns_db_t *db);
void (*overmem)(dns_db_t *db, isc_boolean_t overmem);
unsigned int (*nodecount)(dns_db_t *db);
isc_boolean_t (*ispersistent)(dns_db_t *db);
} dns_dbmethods_t;
......@@ -1131,6 +1132,12 @@ dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp);
* 'ver' is a valid version.
*/
void
dns_db_overmem(dns_db_t *db, isc_boolean_t overmem);
/*
* Enable / disable agressive cache cleaning.
*/
unsigned int
dns_db_nodecount(dns_db_t *db);
/*
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: events.h,v 1.29 2000/08/15 03:33:50 marka Exp $ */
/* $Id: events.h,v 1.30 2000/08/31 12:15:14 marka Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
......@@ -53,6 +53,7 @@
#define DNS_EVENT_ZONE (ISC_EVENTCLASS_DNS + 24)
#define DNS_EVENT_ZONESTARTXFRIN (ISC_EVENTCLASS_DNS + 25)
#define DNS_EVENT_MASTERQUANTUM (ISC_EVENTCLASS_DNS + 26)
#define DNS_EVENT_CACHEOVERMEM (ISC_EVENTCLASS_DNS + 27)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbtdb.c,v 1.121 2000/08/26 01:36:52 bwelling Exp $ */
/* $Id: rbtdb.c,v 1.122 2000/08/31 12:15:11 marka Exp $ */
/*
* Principal Author: Bob Halley
......@@ -24,6 +24,7 @@
#include <config.h>
#include <isc/mem.h>
#include <isc/random.h>
#include <isc/rwlock.h>
#include <isc/string.h>
#include <isc/util.h>
......@@ -164,6 +165,8 @@ typedef struct {
rbtdb_version_t * current_version;
rbtdb_version_t * future_version;
rbtdb_versionlist_t open_versions;
isc_boolean_t overmem;
isc_random_t random;
/* Locked by tree_lock. */
dns_rbt_t * tree;
isc_boolean_t secure;
......@@ -327,6 +330,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb) {
REQUIRE(EMPTY(rbtdb->open_versions));
REQUIRE(rbtdb->future_version == NULL);
isc_random_invalidate(&rbtdb->random);
if (rbtdb->current_version != NULL)
isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,
sizeof (rbtdb_version_t));
......@@ -2710,6 +2714,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
dns_rbtnode_t *rbtnode = node;
rdatasetheader_t *header;
isc_uint32_t val;
REQUIRE(VALID_RBTDB(rbtdb));
......@@ -2728,6 +2733,17 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
*/
header->attributes |= RDATASET_ATTR_STALE;
rbtnode->dirty = 1;
if (rbtdb->overmem)
fprintf(stderr, "overmem stale\n");
} else if (rbtdb->overmem) {
isc_random_get(&rbtdb->random, &val);
if ((val % 7) == 0) {
fprintf(stderr, "overmem expire\n");
header->ttl = 0;
header->attributes |= RDATASET_ATTR_STALE;
rbtnode->dirty = 1;
} else
fprintf(stderr, "overmem skip\n");
}
}
......@@ -2736,6 +2752,15 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
return (ISC_R_SUCCESS);
}
static void
overmem(dns_db_t *db, isc_boolean_t overmem) {
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
if ((rbtdb->common.attributes & DNS_DBATTR_CACHE) != 0) {
rbtdb->overmem = overmem;
}
}
static void
printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
......@@ -3826,7 +3851,8 @@ static dns_dbmethods_t zone_methods = {
deleterdataset,
issecure,
nodecount,
ispersistent
ispersistent,
overmem
};
static dns_dbmethods_t cache_methods = {
......@@ -3854,7 +3880,8 @@ static dns_dbmethods_t cache_methods = {
deleterdataset,
issecure,
nodecount,
ispersistent
ispersistent,
overmem
};
isc_result_t
......@@ -4003,6 +4030,8 @@ dns_rbtdb_create
rbtdb->references = 1;
rbtdb->attributes = 0;
rbtdb->secure = ISC_FALSE;
rbtdb->overmem = ISC_FALSE;
isc_random_init(&rbtdb->random);
/*
* Version Initialization.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: mem.h,v 1.40 2000/08/01 01:30:27 tale Exp $ */
/* $Id: mem.h,v 1.41 2000/08/31 12:15:17 marka Exp $ */
#ifndef ISC_MEM_H
#define ISC_MEM_H 1
......@@ -28,6 +28,10 @@
ISC_LANG_BEGINDECLS
#define ISC_MEM_LOWATER 0
#define ISC_MEM_HIWATER 1
typedef void (*isc_mem_water_t)(void *, int);
typedef void * (*isc_memalloc_t)(void *, size_t);
typedef void (*isc_memfree_t)(void *, void *);
......@@ -147,6 +151,24 @@ isc_result_t isc_mem_createx(size_t, size_t,
void *arg, isc_mem_t **);
isc_result_t isc_mem_restore(isc_mem_t *);
void
isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
size_t hiwater, size_t lowater);
/*
* Set high and low water marks for this memory context. When the memory
* usage of 'mctx' exceeds 'hiwater', '(water)(water_arg, ISC_MEM_HIWATER)'
* will be called. When the usage drops below 'lowater', 'water' will
* again be called, this time with ISC_MEM_LOWATER.
*
* Requires:
* If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
* ignored and the state is reset otherwise.
* 'water' to point to a valid function.
* 'hi_water > lo_water'
* 'lo_water != 0'
* 'hi_water != 0'
*/
/*
* Memory pools
*/
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: mem.c,v 1.60 2000/08/26 01:23:12 bwelling Exp $ */
/* $Id: mem.c,v 1.61 2000/08/31 12:15:16 marka Exp $ */
#include <config.h>
......@@ -118,6 +118,11 @@ struct isc_mem {
size_t quota;
size_t total;
size_t inuse;
size_t hi_water;
size_t lo_water;
isc_boolean_t hi_called;
isc_mem_water_t water;
void * water_arg;
ISC_LIST(isc_mempool_t) pools;
#ifdef ISC_MEM_TRACKLINES
ISC_LIST(debuglink_t) debuglist;
......@@ -651,6 +656,11 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
ctx->quota = 0;
ctx->total = 0;
ctx->inuse = 0;
ctx->hi_water = 0;
ctx->lo_water = 0;
ctx->hi_called = ISC_FALSE;
ctx->water = NULL;
ctx->water_arg = NULL;
ctx->magic = MEM_MAGIC;
isc_ondestroy_init(&ctx->ondestroy);
ISC_LIST_INIT(ctx->pools);
......@@ -813,26 +823,61 @@ check_overrun(void *mem, size_t size, size_t new_size) {
void *
isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
void *ptr;
isc_boolean_t call_water = ISC_FALSE;
REQUIRE(VALID_CONTEXT(ctx));
LOCK(&ctx->lock);
ptr = mem_getunlocked(ctx, size);
ADD_TRACE(ctx, ptr, size, file, line);
if (ctx->hi_water != 0 && !ctx->hi_called &&
ctx->inuse > ctx->hi_water) {
ctx->hi_called = ISC_TRUE;
call_water = ISC_TRUE;
}
UNLOCK(&ctx->lock);
/* XXX remove */
if (ctx->hi_water)
fprintf(stderr,"inuse %u, total %u\n", ctx->inuse, ctx->total);
if (call_water) {
/* XXX remove */
fprintf(stderr, "calling water(%p,ISC_MEM_HIWATER)\n",
ctx->water_arg);
(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
}
return (ptr);
}
void
isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
{
isc_boolean_t call_water = ISC_FALSE;
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(ptr != NULL);
LOCK(&ctx->lock);
DELETE_TRACE(ctx, ptr, size, file, line);
mem_putunlocked(ctx, ptr, size);
if (ctx->hi_called && ctx->inuse < ctx->lo_water) {
ctx->hi_called = ISC_FALSE;
call_water = ISC_TRUE;
}
UNLOCK(&ctx->lock);
/* XXX remove */
if (ctx->hi_water)
fprintf(stderr,"inuse %u, total %u\n", ctx->inuse, ctx->total);
if (call_water) {
/* XXX remove */
fprintf(stderr, "calling water(%p,ISC_MEM_LOWATER)\n",
ctx->water_arg);
(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
}
}
isc_result_t
......@@ -1083,6 +1128,35 @@ isc_mem_inuse(isc_mem_t *ctx) {
return (inuse);
}
void
isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
size_t hiwater, size_t lowater)
{
REQUIRE(VALID_CONTEXT(ctx));
if (water != NULL) {
REQUIRE(hiwater > lowater);
REQUIRE(hiwater > 0);
REQUIRE(lowater > 0);
}
LOCK(&ctx->lock);
if (water == NULL) {
ctx->water = NULL;
ctx->water_arg = NULL;
ctx->hi_water = NULL;
ctx->lo_water = NULL;
ctx->hi_called = ISC_FALSE;
} else {
ctx->water = water;
ctx->water_arg = water_arg;
ctx->hi_water = hiwater;
ctx->lo_water = lowater;
ctx->hi_called = ISC_FALSE;
}
UNLOCK(&ctx->lock);
}
/*
* Memory pool stuff
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment