cache.c revision fc8a6561cbb0a1fea849950a3217aacd3b8f1eac
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/*
1413616670fcb95b9ef236351502e4884ddca8bfTinderbox User * Copyright (C) 1999, 2000 Internet Software Consortium.
fcb54ce0a4f7377486df5bec83b3aa4711bf4131Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * copyright notice and this permission notice appear in all copies.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * SOFTWARE.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews/* $Id: cache.c,v 1.18 2000/04/25 19:35:39 tale Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#include <config.h>
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff#include <limits.h>
de153390f5a1f6d4fa86af91d4cae772d9846ca0Mark Andrews
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff#include <isc/assertions.h>
822f6cdabb1edd44472c7a758b5cae71376fa9beBrian Wellington#include <isc/error.h>
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington#include <isc/mutex.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <isc/time.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/util.h>
242bba8991b030b7764f0bdca3922d75c34ea51eAndreas Gustafsson
25a66b4e41e2b0a2af4840749bac80ae78c678bfMark Andrews#include <dns/cache.h>
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence#include <dns/db.h>
21f1794606dce19928cf455029e173321f166380Mark Andrews#include <dns/dbiterator.h>
973a19342597823f111fce6a8cd5adfd0e2e7c0dMark Andrews#include <dns/events.h>
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff#include <dns/log.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <dns/rdata.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <dns/types.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
058e44186b74531402c1f99088eb9dbe4926f8daMark Andrews#define CACHE_MAGIC 0x24242424U /* $$$$. */
28b863e609ff2d97b78663b46894494cfa2ea411Mark Andrews#define VALID_CACHE(cache) ((cache) != NULL && (cache)->magic == CACHE_MAGIC)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
21825a8d005ccc2dfaf12889bf9eef3413555277Brian Wellington/***
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 *** Types
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence ***/
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews/*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * A cache_cleaner_t encapsulsates the state of the periodic
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews * cache cleaning.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssontypedef struct cache_cleaner cache_cleaner_t;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafssontypedef enum {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cleaner_s_idle, /* Waiting for cleaning-interval to expire. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews cleaner_s_busy /* Currently cleaning. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews} cleaner_state_t;
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews/* Convenience macros for comprehensive assertion checking. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define CLEANER_IDLE(c) ((c)->state == cleaner_s_idle && \
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews (c)->iterator == NULL && \
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews (c)->resched_event != NULL)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define CLEANER_BUSY(c) ((c)->state == cleaner_s_busy && \
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews (c)->iterator != NULL && \
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews (c)->resched_event == NULL)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrewsstruct cache_cleaner {
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews dns_cache_t *cache;
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews isc_task_t *task;
eb6bd543c7d072efdca509eb17f8f301c1467b53Mark Andrews unsigned int cleaning_interval; /* The cleaning-interval from
deaaf94332abbfdb3aff53675546acfed16e5eb6Mark Andrews named.conf, in seconds. */
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews isc_timer_t *cleaning_timer;
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews isc_event_t *resched_event; /* Sent by cleaner task to
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence itself to reschedule */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews dns_dbiterator_t *iterator;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews int increment; /* Number of names to
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence clean in one increment */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence cleaner_state_t state; /* Idle/Busy. */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence};
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence/*
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * The actual cache object.
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestruct dns_cache {
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence /* Unlocked */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence unsigned int magic;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_mutex_t lock;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_mutex_t filelock;
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence isc_mem_t *mctx;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence /* Locked by 'lock'. */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence int references;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence int live_tasks;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence dns_rdataclass_t rdclass;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence dns_db_t *db;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence cache_cleaner_t cleaner;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence /* Locked by 'filelock'. */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence char * filename;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence /* Access to the on-disk cache file is also locked by 'filelock'. */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews};
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews/***
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews *** Functions
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews ***/
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austeinstatic isc_result_t
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencecache_cleaner_init(dns_cache_t *cache,
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson cache_cleaner_t *cleaner);
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssonstatic void
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austeincleaning_timer_action(isc_task_t *task, isc_event_t *event);
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austeinstatic void
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updaterincremental_cleaning_action(isc_task_t *task, isc_event_t *event);
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssonstatic void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencecleaner_shutdown_action(isc_task_t *task, isc_event_t *event);
2383eb527269d333df4222da20e4b422c3662daaEvan Hunt
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrenceisc_result_t
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencedns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence char *db_type, unsigned int db_argc, char **db_argv,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence dns_cache_t **cachep)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence{
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_result_t result;
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont dns_cache_t *cache;
7712d1660a308ec3de17f1ddbbf801eb0d663f3eEvan Hunt
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont REQUIRE(cachep != NULL);
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont REQUIRE(*cachep == NULL);
7712d1660a308ec3de17f1ddbbf801eb0d663f3eEvan Hunt REQUIRE(mctx != NULL);
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache = isc_mem_get(mctx, sizeof *cache);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (cache == NULL)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence return (ISC_R_NOMEMORY);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->mctx = NULL;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_attach(mctx, &cache->mctx);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence result = isc_mutex_init(&cache->lock);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (result != ISC_R_SUCCESS) {
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington UNEXPECTED_ERROR(__FILE__, __LINE__,
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington "isc_mutex_init() failed: %s",
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington dns_result_totext(result));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence result = ISC_R_UNEXPECTED;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence goto cleanup_mem;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence }
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->references = 1;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->live_tasks = 0;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->rdclass = rdclass;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->db = NULL;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence result = dns_db_create(cache->mctx, db_type, dns_rootname, ISC_TRUE,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence rdclass, db_argc, db_argv, &cache->db);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (result != ISC_R_SUCCESS)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence goto cleanup_mutex;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->filename = NULL;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cache->magic = CACHE_MAGIC;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence result = cache_cleaner_init(cache, taskmgr, timermgr,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence &cache->cleaner);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (result != ISC_R_SUCCESS)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence goto cleanup_db;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence *cachep = cache;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence return (ISC_R_SUCCESS);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cleanup_db:
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_db_detach(&cache->db);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews cleanup_mutex:
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_mutex_destroy(&cache->lock);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence cleanup_mem:
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_put(mctx, cache, sizeof *cache);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_detach(&mctx);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence return (result);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence}
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencecache_free(dns_cache_t *cache) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_t *mctx;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence REQUIRE(VALID_CACHE(cache));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence REQUIRE(cache->references == 0);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (cache->cleaner.task != NULL)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_task_detach(&cache->cleaner.task);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson if (cache->cleaner.resched_event != NULL)
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson isc_event_free(&cache->cleaner.resched_event);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (cache->cleaner.iterator != NULL)
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence dns_dbiterator_destroy(&cache->cleaner.iterator);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence if (cache->filename) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_free(cache->mctx, cache->filename);
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews cache->filename = NULL;
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews }
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (cache->db)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence dns_db_detach(&cache->db);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson isc_mutex_destroy(&cache->lock);
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews cache->magic = 0;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews mctx = cache->mctx;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews isc_mem_put(cache->mctx, cache, sizeof *cache);
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews isc_mem_detach(&mctx);
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews}
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrewsvoid
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdns_cache_attach(dns_cache_t *cache, dns_cache_t **targetp) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_CACHE(cache));
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews REQUIRE(targetp != NULL && *targetp == NULL);
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews LOCK(&cache->lock);
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews cache->references++;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews UNLOCK(&cache->lock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews *targetp = cache;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews}
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsvoid
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsdns_cache_detach(dns_cache_t **cachep) {
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews dns_cache_t *cache;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews isc_boolean_t free_cache = ISC_FALSE;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews REQUIRE(cachep != NULL);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews cache = *cachep;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews REQUIRE(VALID_CACHE(cache));
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews LOCK(&cache->lock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews REQUIRE(cache->references > 0);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews cache->references--;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews if (cache->references == 0)
6a528eaa09b6eed63144250dc61062f3a84880abMark Andrews free_cache = ISC_TRUE;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews UNLOCK(&cache->lock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews *cachep = NULL;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews if (free_cache) {
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews /* XXXRTH This is not locked! */
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews if (cache->live_tasks > 0)
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews isc_task_shutdown(cache->cleaner.task);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews else
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews cache_free(cache);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews }
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews}
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsvoid
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsdns_cache_attachdb(dns_cache_t *cache, dns_db_t **dbp) {
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews REQUIRE(VALID_CACHE(cache));
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews REQUIRE(dbp != NULL && *dbp == NULL);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews REQUIRE(cache->db != NULL);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews LOCK(&cache->lock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews dns_db_attach(cache->db, dbp);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews UNLOCK(&cache->lock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews}
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews#ifdef NOTYET
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsisc_result_t
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsdns_cache_setfilename(dns_cache_t *cahce, char *filename) /* ARGSUSED */
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews{
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews char *newname = isc_mem_strdup(filename);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews if (newname == NULL)
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews return (ISC_R_NOMEMORY);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews LOCK(&cache->filelock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews if (cache->filename)
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews isc_mem_free(cache->mctx, cache->filename);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews cache->filename = newname;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews UNLOCK(&cache->filelock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews return (ISC_R_SUCCESS);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews}
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsisc_result_t
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrewsdns_cache_load(dns_cache_t *cache) {
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews isc_result_t result;
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews if (cache->filename == NULL)
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt return (ISC_R_SUCCESS);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews LOCK(&cache->filelock);
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews /* XXX handle TTLs in a way appropriate for the cache */
f1c1aab2c9e720399d66d8db5f40515d47c45ecfMark Andrews result = dns_db_load(cache->db, cache->filename);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews UNLOCK(&cache->filelock);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews return (result);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews}
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrewsisc_result_t
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrewsdns_cache_dump(dns_cache_t *cache) {
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews /* XXX to be written */
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews return (ISC_R_NOTIMPLEMENTED);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews}
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews
23cb957a81a51a9656917ea98d0ae56b7abdcaccMark Andrews#endif
b6a0341bcb113e93bd0bc41a9f9a1fc117444da6Mark Andrews
b6a0341bcb113e93bd0bc41a9f9a1fc117444da6Mark Andrewsvoid
aa05bbdef7f7827dde158dcc913f4dade84c8511Brian Wellingtondns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int t) {
23cb957a81a51a9656917ea98d0ae56b7abdcaccMark Andrews LOCK(&cache->lock);
23cb957a81a51a9656917ea98d0ae56b7abdcaccMark Andrews cache->cleaner.cleaning_interval = t;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews if (t == 0) {
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews isc_timer_reset(cache->cleaner.cleaning_timer, isc_timertype_inactive,
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews NULL, NULL, ISC_TRUE);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews } else {
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews isc_interval_t interval;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews isc_interval_set(&interval, cache->cleaner.cleaning_interval, 0);
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews isc_timer_reset(cache->cleaner.cleaning_timer, isc_timertype_ticker,
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews NULL, &interval, ISC_FALSE);
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington }
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews UNLOCK(&cache->lock);
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews}
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews/*
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews * Initialize the cache cleaner object at *cleaner.
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews * Space for the object must be allocated by the caller.
d4422ec231e58b60693620cf298276e47f04f0ecMark Andrews */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrewsstatic isc_result_t
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrewscache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
d4422ec231e58b60693620cf298276e47f04f0ecMark Andrews isc_timermgr_t *timermgr, cache_cleaner_t *cleaner)
d4422ec231e58b60693620cf298276e47f04f0ecMark Andrews{
d4422ec231e58b60693620cf298276e47f04f0ecMark Andrews isc_result_t result;
f6407f9a0b890bebbfd5f738d9c4aef3d3315fe9Michael Graff
d4422ec231e58b60693620cf298276e47f04f0ecMark Andrews cleaner->increment = 100;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews cleaner->state = cleaner_s_idle;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews cleaner->cache = cache;
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews cleaner->iterator = NULL;
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cleaner->task = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cleaner->cleaning_timer = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cleaner->resched_event = NULL;
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrews
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrews if (taskmgr != NULL && timermgr != NULL) {
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrews result = isc_task_create(taskmgr, 1, &cleaner->task);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "isc_task_create() failed: %s",
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_result_totext(result));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = ISC_R_UNEXPECTED;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto cleanup;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cleaner->cache->live_tasks++;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_task_setname(cleaner->task, "cachecleaner", cleaner);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = isc_task_onshutdown(cleaner->task,
d981ca645597116d227a48bf37cc5edc061c854dBob Halley cleaner_shutdown_action, cache);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS) {
e6bd97dded968f82e26b270842b789bff7bca422Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "cache cleaner: "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "isc_task_onshutdown() failed: %s",
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_result_totext(result));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto cleanup;
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews }
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews cleaner->cleaning_interval = 0; /* Initially turned off. */
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington result = isc_timer_create(timermgr, isc_timertype_inactive,
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington NULL, NULL,
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews cleaner->task,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews cleaning_timer_action, cleaner,
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews &cleaner->cleaning_timer);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews if (result != ISC_R_SUCCESS) {
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews "isc_timer_create() failed: %s",
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews dns_result_totext(result));
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews result = ISC_R_UNEXPECTED;
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews goto cleanup;
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews cleaner->resched_event =
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews isc_event_allocate(cache->mctx, cleaner,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews DNS_EVENT_CACHECLEAN,
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews incremental_cleaning_action,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews cleaner, sizeof(isc_event_t));
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (cleaner->resched_event == NULL) {
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington result = ISC_R_NOMEMORY;
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington goto cleanup;
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington }
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews return (ISC_R_SUCCESS);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews cleanup:
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews if (cleaner->cleaning_timer != NULL)
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews isc_timer_detach(&cleaner->cleaning_timer);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews if (cleaner->task != NULL)
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews isc_task_detach(&cleaner->task);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews return (result);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews}
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic void
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsbegin_cleaning(cache_cleaner_t *cleaner) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_result_t result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(CLEANER_IDLE(cleaner));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Create an iterator and position it at the beginning of the cache.
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews */
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews &cleaner->iterator);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews "cache cleaner could not create "
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews "iterator: %s", isc_result_totext(result));
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews goto idle;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
d981ca645597116d227a48bf37cc5edc061c854dBob Halley result = dns_dbiterator_first(cleaner->iterator);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley if (result == ISC_R_NOMORE) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * The database is empty. We are done.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto destroyiter;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS) {
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews "cache cleaner: dns_dbiterator_first() "
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews "failed: %s", dns_result_totext(result));
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews goto destroyiter;
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews }
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews
90e303b114e56db5809fdd19805243457fa43cd9Olafur Gudmundsson isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "begin cache cleaning");
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cleaner->state = cleaner_s_busy;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_task_send(cleaner->task, &cleaner->resched_event);
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews ENSURE(CLEANER_BUSY(cleaner));
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews return;
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews destroyiter:
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews dns_dbiterator_destroy(&cleaner->iterator);
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews idle:
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews ENSURE(CLEANER_IDLE(cleaner));
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews return;
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews}
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrewsstatic void
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrewsend_cleaning(cache_cleaner_t *cleaner, isc_event_t *event) {
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews REQUIRE(CLEANER_BUSY(cleaner));
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews "end cache cleaning");
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews dns_dbiterator_destroy(&cleaner->iterator);
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews cleaner->state = cleaner_s_idle;
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews cleaner->resched_event = event;
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews ENSURE(CLEANER_IDLE(cleaner));
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews}
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews/*
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * This is run once for every cache-cleaning-interval as defined in named.conf.
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews */
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrewsstatic void
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrewscleaning_timer_action(isc_task_t *task, isc_event_t *event) {
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews cache_cleaner_t *cleaner = event->ev_arg;
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews INSIST(task == cleaner->task);
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (cleaner->state == cleaner_s_idle) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews begin_cleaning(cleaner);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews } else {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(CLEANER_BUSY(cleaner));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
d981ca645597116d227a48bf37cc5edc061c854dBob Halley DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews "cache cleaner did not finish "
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews "in one cleaning-interval");
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
19d365e4448f1782611280b020987988b7ac3210Mark Andrews isc_event_free(&event);
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington}
19d365e4448f1782611280b020987988b7ac3210Mark Andrews
19d365e4448f1782611280b020987988b7ac3210Mark Andrews/*
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * Do incremental cleaning.
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic void
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsincremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley isc_result_t result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews cache_cleaner_t *cleaner = event->ev_arg;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews isc_stdtime_t now;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews int n_names;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(event->ev_type == DNS_EVENT_CACHECLEAN);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence INSIST(CLEANER_BUSY(cleaner));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
19d365e4448f1782611280b020987988b7ac3210Mark Andrews n_names = cleaner->increment;
19d365e4448f1782611280b020987988b7ac3210Mark Andrews isc_stdtime_get(&now);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
19d365e4448f1782611280b020987988b7ac3210Mark Andrews REQUIRE(DNS_DBITERATOR_VALID(cleaner->iterator));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews while (n_names-- > 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_dbnode_t *node = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = dns_dbiterator_current(cleaner->iterator, &node,
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff (dns_name_t *) NULL);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley if (result != ISC_R_SUCCESS) {
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews "cache cleaner: dns_dbiterator_current() "
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews "failed: %s", dns_result_totext(result));
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews goto idle;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(node != NULL);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* Check TTLs, mark expired rdatasets stale. */
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews result = dns_db_expirenode(cleaner->cache->db, node, now);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (result != ISC_R_SUCCESS) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "cache cleaner: dns_db_expirenode() "
19d365e4448f1782611280b020987988b7ac3210Mark Andrews "failed: %s",
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_result_totext(result));
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington /* Continue anyway. */
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrews /* This is where the actual freeing takes place. */
7e9d637131516486630290d36c4c0db544cb700eMark Andrews dns_db_detachnode(cleaner->cache->db, &node);
19d365e4448f1782611280b020987988b7ac3210Mark Andrews
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson /* Step to the next node */
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson result = dns_dbiterator_next(cleaner->iterator);
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson if (result == ISC_R_NOMORE) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* We have successfully cleaned the whole cache. */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto idle;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (result != ISC_R_SUCCESS) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews "cache cleaner: dns_dbiterator_next() "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "failed: %s", dns_result_totext(result));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto idle;
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews }
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews }
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews /* We have successfully performed a cleaning increment. */
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews result = dns_dbiterator_pause(cleaner->iterator);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews "cache cleaner: dns_dbiterator_pause() "
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews "failed: %s", dns_result_totext(result));
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews /* Try to continue. */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews /* Still busy, reschedule. */
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews isc_task_send(task, &event);
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews INSIST(CLEANER_BUSY(cleaner));
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews return;
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews idle:
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews /* No longer busy; save the event for later use. */
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews end_cleaning(cleaner, event);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence INSIST(CLEANER_IDLE(cleaner));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence return;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence}
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews/*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Do immediate cleaning.
ad7209ea70d346527ffdcda335153831341d9dcfAndreas Gustafsson */
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrewsisc_result_t
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrewsdns_cache_clean(dns_cache_t *cache, isc_stdtime_t now) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley isc_result_t result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_dbiterator_t *iterator = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff result = dns_db_createiterator(cache->db, ISC_FALSE, &iterator);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return result;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = dns_dbiterator_first(iterator);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews while (result == ISC_R_SUCCESS) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff dns_dbnode_t *node = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = dns_dbiterator_current(iterator, &node,
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington (dns_name_t *) NULL);
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews if (result != ISC_R_SUCCESS)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff break;
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
f0a5bb8f86631ce638cb2b6c65bbb9bcf9b0cdc0Bob Halley /* Check TTLs, mark expired rdatasets stale. */
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews result = dns_db_expirenode(cache->db, node, now);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS) {
19d365e4448f1782611280b020987988b7ac3210Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews "cache cleaner: dns_db_expirenode() "
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence "failed: %s",
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson dns_result_totext(result));
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson /* Continue anyway. */
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson }
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews /* This is where the actual freeing takes place. */
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson dns_db_detachnode(cache->db, &node);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson result = dns_dbiterator_next(iterator);
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews }
19d365e4448f1782611280b020987988b7ac3210Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_dbiterator_destroy(&iterator);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews if (result == ISC_R_NOMORE)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = ISC_R_SUCCESS;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return result;
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt}
f0a5bb8f86631ce638cb2b6c65bbb9bcf9b0cdc0Bob Halley
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff/*
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * The cleaner task is shutting down; do the necessary cleanup.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff */
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrewsstatic void
7c0378745269fe49a05904935afc42b85528f53aDavid Lawrencecleaner_shutdown_action(isc_task_t *task, isc_event_t *event) {
7c0378745269fe49a05904935afc42b85528f53aDavid Lawrence dns_cache_t *cache = event->ev_arg;
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews isc_boolean_t should_free = ISC_FALSE;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews UNUSED(task);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson LOCK(&cache->lock);
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson isc_event_free(&event);
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson
3a16668468060842e847ea6556e80e1405d35cd6Brian Wellington cache->live_tasks--;
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson INSIST(cache->live_tasks == 0);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews if (cache->references == 0)
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington should_free = ISC_TRUE;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington /*
942d1a339b1fe617f7d17d66cb5fccce798d15aeBrian Wellington * By detaching the timer in the context of its task,
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington * we are guaranteed that there will be no further timer
7e9d637131516486630290d36c4c0db544cb700eMark Andrews * events.
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington */
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (cache->cleaner.cleaning_timer != NULL)
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews isc_timer_detach(&cache->cleaner.cleaning_timer);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews /* Make sure we don't reschedule anymore. */
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_task_purge(task, NULL, DNS_EVENT_CACHECLEAN, NULL);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington UNLOCK(&cache->lock);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (should_free)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington cache_free(cache);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington}
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington