summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/cache.c')
-rw-r--r--contrib/bind9/lib/dns/cache.c146
1 files changed, 109 insertions, 37 deletions
diff --git a/contrib/bind9/lib/dns/cache.c b/contrib/bind9/lib/dns/cache.c
index f45af90..011dbf7 100644
--- a/contrib/bind9/lib/dns/cache.c
+++ b/contrib/bind9/lib/dns/cache.c
@@ -15,7 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.c,v 1.45.2.4.8.15 2006/08/01 01:07:05 marka Exp $ */
+/* $Id: cache.c,v 1.57.18.16 2006/08/01 01:06:48 marka Exp $ */
+
+/*! \file */
#include <config.h>
@@ -29,6 +31,7 @@
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/events.h>
+#include <dns/lib.h>
#include <dns/log.h>
#include <dns/masterdump.h>
#include <dns/rdata.h>
@@ -39,13 +42,18 @@
#define CACHE_MAGIC ISC_MAGIC('$', '$', '$', '$')
#define VALID_CACHE(cache) ISC_MAGIC_VALID(cache, CACHE_MAGIC)
-/*
- * The following two variables control incremental cleaning.
- * MINSIZE is how many bytes is the floor for dns_cache_setcachesize().
+/*!
+ * Control incremental cleaning.
+ * DNS_CACHE_MINSIZE is how many bytes is the floor for dns_cache_setcachesize().
+ * See also DNS_CACHE_CLEANERINCREMENT
+ */
+#define DNS_CACHE_MINSIZE 2097152 /*%< Bytes. 2097152 = 2 MB */
+/*!
+ * Control incremental cleaning.
* CLEANERINCREMENT is how many nodes are examined in one pass.
+ * See also DNS_CACHE_MINSIZE
*/
-#define DNS_CACHE_MINSIZE 2097152 /* Bytes. 2097152 = 2 MB */
-#define DNS_CACHE_CLEANERINCREMENT 1000 /* Number of nodes. */
+#define DNS_CACHE_CLEANERINCREMENT 1000U /*%< Number of nodes. */
/***
*** Types
@@ -59,9 +67,9 @@
typedef struct cache_cleaner cache_cleaner_t;
typedef enum {
- cleaner_s_idle, /* Waiting for cleaning-interval to expire. */
- cleaner_s_busy, /* Currently cleaning. */
- cleaner_s_done /* Freed enough memory after being overmem. */
+ cleaner_s_idle, /*%< Waiting for cleaning-interval to expire. */
+ cleaner_s_busy, /*%< Currently cleaning. */
+ cleaner_s_done /*%< Freed enough memory after being overmem. */
} cleaner_state_t;
/*
@@ -73,13 +81,13 @@ typedef enum {
(c)->iterator != NULL && \
(c)->resched_event == NULL)
-/*
+/*%
* Accesses to a cache cleaner object are synchronized through
* task/event serialization, or locked from the cache object.
*/
struct cache_cleaner {
isc_mutex_t lock;
- /*
+ /*%<
* Locks overmem_event, overmem. Note: never allocate memory
* while holding this lock - that could lead to deadlock since
* the lock is take by water() which is called from the memory
@@ -88,22 +96,22 @@ struct cache_cleaner {
dns_cache_t *cache;
isc_task_t *task;
- unsigned int cleaning_interval; /* The cleaning-interval from
+ unsigned int cleaning_interval; /*% The cleaning-interval from
named.conf, in seconds. */
isc_timer_t *cleaning_timer;
- isc_event_t *resched_event; /* Sent by cleaner task to
+ 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
+ unsigned int increment; /*% Number of names to
clean in one increment */
- cleaner_state_t state; /* Idle/Busy. */
- isc_boolean_t overmem; /* The cache is in an overmem state. */
+ cleaner_state_t state; /*% Idle/Busy. */
+ isc_boolean_t overmem; /*% The cache is in an overmem state. */
isc_boolean_t replaceiterator;
};
-/*
+/*%
* The actual cache object.
*/
@@ -149,6 +157,79 @@ cleaner_shutdown_action(isc_task_t *task, isc_event_t *event);
static void
overmem_cleaning_action(isc_task_t *task, isc_event_t *event);
+/*%
+ * Work out how many nodes can be cleaned in the time between two
+ * requests to the nameserver. Smooth the resulting number and use
+ * it as a estimate for the number of nodes to be cleaned in the next
+ * iteration.
+ */
+static void
+adjust_increment(cache_cleaner_t *cleaner, unsigned int remaining,
+ isc_time_t *start)
+{
+ isc_time_t end;
+ isc_uint64_t usecs;
+ isc_uint64_t new;
+ unsigned int pps = dns_pps;
+ unsigned int interval;
+ unsigned int names;
+
+ /*
+ * Tune for minumum of 100 packets per second (pps).
+ */
+ if (pps < 100)
+ pps = 100;
+
+ isc_time_now(&end);
+
+ interval = 1000000 / pps; /* Interval between packets in usecs. */
+ if (interval == 0)
+ interval = 1;
+
+ INSIST(cleaner->increment >= remaining);
+ names = cleaner->increment - remaining;
+ usecs = isc_time_microdiff(&end, start);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "adjust_increment interval=%u "
+ "names=%u usec=%" ISC_PLATFORM_QUADFORMAT "u",
+ interval, names, usecs);
+
+ if (usecs == 0) {
+ /*
+ * If we cleaned all the nodes in unmeasurable time
+ * double the number of nodes to be cleaned next time.
+ */
+ if (names == cleaner->increment) {
+ cleaner->increment *= 2;
+ if (cleaner->increment > DNS_CACHE_CLEANERINCREMENT)
+ cleaner->increment = DNS_CACHE_CLEANERINCREMENT;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "%p:new cleaner->increment = %u\n",
+ cleaner, cleaner->increment);
+ }
+ return;
+ }
+
+ new = (names * interval);
+ new /= (usecs * 2);
+ if (new == 0)
+ new = 1;
+
+ /* Smooth */
+ new = (new + cleaner->increment * 7) / 8;
+
+ if (new > DNS_CACHE_CLEANERINCREMENT)
+ new = DNS_CACHE_CLEANERINCREMENT;
+
+ cleaner->increment = (unsigned int)new;
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "%p:new cleaner->increment = %u\n",
+ cleaner, cleaner->increment);
+}
+
static inline isc_result_t
cache_create_db(dns_cache_t *cache, dns_db_t **db) {
return (dns_db_create(cache->mctx, cache->db_type, dns_rootname,
@@ -178,22 +259,12 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_mem_attach(mctx, &cache->mctx);
result = isc_mutex_init(&cache->lock);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_mutex_init() failed: %s",
- dns_result_totext(result));
- result = ISC_R_UNEXPECTED;
+ if (result != ISC_R_SUCCESS)
goto cleanup_mem;
- }
result = isc_mutex_init(&cache->filelock);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_mutex_init() failed: %s",
- dns_result_totext(result));
- result = ISC_R_UNEXPECTED;
+ if (result != ISC_R_SUCCESS)
goto cleanup_lock;
- }
cache->references = 1;
cache->live_tasks = 0;
@@ -488,13 +559,8 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
isc_result_t result;
result = isc_mutex_init(&cleaner->lock);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_mutex_init() failed: %s",
- dns_result_totext(result));
- result = ISC_R_UNEXPECTED;
+ if (result != ISC_R_SUCCESS)
goto fail;
- }
cleaner->increment = DNS_CACHE_CLEANERINCREMENT;
cleaner->state = cleaner_s_idle;
@@ -740,7 +806,8 @@ static void
incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
cache_cleaner_t *cleaner = event->ev_arg;
isc_result_t result;
- int n_names;
+ unsigned int n_names;
+ isc_time_t start;
UNUSED(task);
@@ -770,6 +837,7 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
REQUIRE(DNS_DBITERATOR_VALID(cleaner->iterator));
+ isc_time_now(&start);
while (n_names-- > 0) {
dns_dbnode_t *node = NULL;
@@ -780,6 +848,7 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
"cache cleaner: dns_dbiterator_current() "
"failed: %s", dns_result_totext(result));
+ adjust_increment(cleaner, n_names, &start);
end_cleaning(cleaner, event);
return;
}
@@ -823,11 +892,14 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
}
}
+ adjust_increment(cleaner, n_names, &start);
end_cleaning(cleaner, event);
return;
}
}
+ adjust_increment(cleaner, 0U, &start);
+
/*
* We have successfully performed a cleaning increment but have
* not gone through the entire cache. Free the iterator locks
@@ -838,7 +910,7 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
- ISC_LOG_DEBUG(1), "cache cleaner: checked %d nodes, "
+ ISC_LOG_DEBUG(1), "cache cleaner: checked %u nodes, "
"mem inuse %lu, sleeping", cleaner->increment,
(unsigned long)isc_mem_inuse(cleaner->cache->mctx));
OpenPOWER on IntegriCloud