cache.c revision ec5347e2c775f027573ce5648b910361aa926c01
0bf752f4835374c820f9c22ac6b64980729d4b4aTinderbox User * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * Copyright (C) 1999-2003 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and/or distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * copyright notice and this permission notice appear in all copies.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * PERFORMANCE OF THIS SOFTWARE.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt/* $Id: cache.c,v 1.74 2007/06/18 23:47:40 tbox Exp $ */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt#define VALID_CACHE(cache) ISC_MAGIC_VALID(cache, CACHE_MAGIC)
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * Control incremental cleaning.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * DNS_CACHE_MINSIZE is how many bytes is the floor for dns_cache_setcachesize().
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * See also DNS_CACHE_CLEANERINCREMENT
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt#define DNS_CACHE_MINSIZE 2097152 /*%< Bytes. 2097152 = 2 MB */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * Control incremental cleaning.
0e5c8a65a207418b22de9ef9c12bb52c50ac8a2aMark Andrews * CLEANERINCREMENT is how many nodes are examined in one pass.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * See also DNS_CACHE_MINSIZE
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt#define DNS_CACHE_CLEANERINCREMENT 1000U /*%< Number of nodes. */
f9f81abff0ea36f19474f3b7a11bf0f17c4f116cMukund Sivaraman * A cache_cleaner_t encapsulsates the state of the periodic
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * cache cleaning.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunttypedef enum {
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt cleaner_s_idle, /*%< Waiting for cleaning-interval to expire. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt cleaner_s_done /*%< Freed enough memory after being overmem. */
7712d1660a308ec3de17f1ddbbf801eb0d663f3eEvan Hunt * Convenience macros for comprehensive assertion checking.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt#define CLEANER_IDLE(c) ((c)->state == cleaner_s_idle && \
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt#define CLEANER_BUSY(c) ((c)->state == cleaner_s_busy && \
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * Accesses to a cache cleaner object are synchronized through
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * task/event serialization, or locked from the cache object.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * Locks overmem_event, overmem. Note: never allocate memory
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * while holding this lock - that could lead to deadlock since
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * the lock is take by water() which is called from the memory
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * allocator.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt unsigned int cleaning_interval; /*% The cleaning-interval from
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt named.conf, in seconds. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt isc_event_t *resched_event; /*% Sent by cleaner task to
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt itself to reschedule */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt clean in one increment */
7712d1660a308ec3de17f1ddbbf801eb0d663f3eEvan Hunt isc_boolean_t overmem; /*% The cache is in an overmem state. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * The actual cache object.
b0ba1a6059b6d6c4b3aa77d8bc84cc443b981e01Mukund Sivaraman /* Unlocked. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt unsigned int magic;
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt /* Locked by 'lock'. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt /* Locked by 'filelock'. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt /* Access to the on-disk cache file is also locked by 'filelock'. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt *** Functions
2383eb527269d333df4222da20e4b422c3662daaEvan Huntcache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt isc_timermgr_t *timermgr, cache_cleaner_t *cleaner);
2383eb527269d333df4222da20e4b422c3662daaEvan Huntcleaning_timer_action(isc_task_t *task, isc_event_t *event);
cfe32752a66fe1f050d5ed7ddce75f6d58fe1637Evan Huntincremental_cleaning_action(isc_task_t *task, isc_event_t *event);
cfe32752a66fe1f050d5ed7ddce75f6d58fe1637Evan Huntcleaner_shutdown_action(isc_task_t *task, isc_event_t *event);
2383eb527269d333df4222da20e4b422c3662daaEvan Huntovermem_cleaning_action(isc_task_t *task, isc_event_t *event);
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * Work out how many nodes can be cleaned in the time between two
b0ba1a6059b6d6c4b3aa77d8bc84cc443b981e01Mukund Sivaraman * requests to the nameserver. Smooth the resulting number and use
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * it as a estimate for the number of nodes to be cleaned in the next
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * iteration.
2383eb527269d333df4222da20e4b422c3662daaEvan Huntadjust_increment(cache_cleaner_t *cleaner, unsigned int remaining,
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt unsigned int interval;
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt unsigned int names;
b0ba1a6059b6d6c4b3aa77d8bc84cc443b981e01Mukund Sivaraman * Tune for minumum of 100 packets per second (pps).
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt interval = 1000000 / pps; /* Interval between packets in usecs. */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
b0ba1a6059b6d6c4b3aa77d8bc84cc443b981e01Mukund Sivaraman "names=%u usec=%" ISC_PLATFORM_QUADFORMAT "u",
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * If we cleaned all the nodes in unmeasurable time
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt * double the number of nodes to be cleaned next time.
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt if (cleaner->increment > DNS_CACHE_CLEANERINCREMENT)
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt "%p:new cleaner->increment = %u\n",
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt /* Smooth */
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt ISC_LOG_DEBUG(1), "%p:new cleaner->increment = %u\n",
2383eb527269d333df4222da20e4b422c3662daaEvan Huntcache_create_db(dns_cache_t *cache, dns_db_t **db) {
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt return (dns_db_create(cache->mctx, cache->db_type, dns_rootname,
2383eb527269d333df4222da20e4b422c3662daaEvan Huntdns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt const char *db_type, unsigned int db_argc, char **db_argv,
b0ba1a6059b6d6c4b3aa77d8bc84cc443b981e01Mukund Sivaraman cache->db_argv[i] = isc_mem_strdup(mctx, db_argv[i]);
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt result = cache_cleaner_init(cache, taskmgr, timermgr, &cache->cleaner);
if (free_cache) {
if (free_cache)
char *newname;
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
return (result);
return (ISC_R_SUCCESS);
return (result);
goto unlock;
static isc_result_t
goto fail;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
fail:
return (result);
* This is run once for every cache-cleaning-interval as defined in named.conf.
if (want_cleaning)
unsigned int n_names;
while (n_names-- > 0) {
NULL);
iterator);
return result;
return (result);
if (should_free)
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
goto cleanup_db;
goto cleanup_db;
goto cleanup_node;
return (result);