Home | History | Annotate | Download | only in dns

Lines Matching refs:cache

1 /*	$NetBSD: cache.c,v 1.1 2024/02/18 20:57:30 christos Exp $	*/
31 #include <dns/cache.h>
56 #define VALID_CACHE(cache) ISC_MAGIC_VALID(cache, CACHE_MAGIC)
77 * cache cleaning.
98 * Accesses to a cache cleaner object are synchronized through
99 * task/event serialization, or locked from the cache object.
110 dns_cache_t *cache;
120 bool overmem; /*% The cache is in an overmem state.
126 * The actual cache object.
134 isc_mem_t *mctx; /* Main cache memory */
154 /* Access to the on-disk cache file is also locked by 'filelock'. */
162 cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
175 cache_create_db(dns_cache_t *cache, dns_db_t **db) {
177 result = dns_db_create(cache->mctx, cache->db_type, dns_rootname,
178 dns_dbtype_cache, cache->rdclass, cache->db_argc,
179 cache->db_argv, db);
181 dns_db_setservestalettl(*db, cache->serve_stale_ttl);
192 dns_cache_t *cache;
202 cache = isc_mem_get(cmctx, sizeof(*cache));
204 cache->mctx = cache->hmctx = NULL;
205 isc_mem_attach(cmctx, &cache->mctx);
206 isc_mem_attach(hmctx, &cache->hmctx);
208 cache->name = NULL;
210 cache->name = isc_mem_strdup(cmctx, cachename);
213 isc_mutex_init(&cache->lock);
214 isc_mutex_init(&cache->filelock);
216 isc_refcount_init(&cache->references, 1);
217 isc_refcount_init(&cache->live_tasks, 1);
218 cache->rdclass = rdclass;
219 cache->serve_stale_ttl = 0;
221 cache->stats = NULL;
222 result = isc_stats_create(cmctx, &cache->stats,
228 cache->db_type = isc_mem_strdup(cmctx, db_type);
232 * via cache->db_argv, followed by the rest of the arguments in
235 if (strcmp(cache->db_type, "rbt") == 0) {
239 cache->db_argc = db_argc + extra;
240 cache->db_argv = NULL;
242 if (cache->db_argc != 0) {
243 cache->db_argv = isc_mem_get(cmctx,
244 cache->db_argc * sizeof(char *));
246 for (i = 0; i < cache->db_argc; i++) {
247 cache->db_argv[i] = NULL;
250 cache->db_argv[0] = (char *)hmctx;
251 for (i = extra; i < cache->db_argc; i++) {
252 cache->db_argv[i] = isc_mem_strdup(cmctx,
260 cache->db = NULL;
261 result = cache_create_db(cache, &cache->db);
273 dns_db_settask(cache->db, dbtask);
277 cache->filename = NULL;
279 cache->magic = CACHE_MAGIC;
282 * RBT-type cache DB has its own mechanism of cache cleaning and doesn't
286 result = cache_cleaner_init(cache, NULL, NULL, &cache->cleaner);
288 result = cache_cleaner_init(cache, taskmgr, timermgr,
289 &cache->cleaner);
295 result = dns_db_setcachestats(cache->db, cache->stats);
300 *cachep = cache;
304 dns_db_detach(&cache->db);
306 for (i = extra; i < cache->db_argc; i++) {
307 if (cache->db_argv[i] != NULL) {
308 isc_mem_free(cmctx, cache->db_argv[i]);
311 if (cache->db_argv != NULL) {
312 isc_mem_put(cmctx, cache->db_argv,
313 cache->db_argc * sizeof(char *));
315 isc_mem_free(cmctx, cache->db_type);
317 isc_mutex_destroy(&cache->filelock);
318 isc_stats_detach(&cache->stats);
319 isc_mutex_destroy(&cache->lock);
320 if (cache->name != NULL) {
321 isc_mem_free(cmctx, cache->name);
323 isc_mem_detach(&cache->hmctx);
324 isc_mem_putanddetach(&cache->mctx, cache, sizeof(*cache));
329 cache_free(dns_cache_t *cache) {
330 REQUIRE(VALID_CACHE(cache));
332 isc_refcount_destroy(&cache->references);
333 isc_refcount_destroy(&cache->live_tasks);
335 isc_mem_setwater(cache->mctx, NULL, NULL, 0, 0);
337 if (cache->cleaner.task != NULL) {
338 isc_task_detach(&cache->cleaner.task);
341 if (cache->cleaner.overmem_event != NULL) {
342 isc_event_free(&cache->cleaner.overmem_event);
345 if (cache->cleaner.resched_event != NULL) {
346 isc_event_free(&cache->cleaner.resched_event);
349 if (cache->cleaner.iterator != NULL) {
350 dns_dbiterator_destroy(&cache->cleaner.iterator);
353 isc_mutex_destroy(&cache->cleaner.lock);
355 if (cache->filename) {
356 isc_mem_free(cache->mctx, cache->filename);
357 cache->filename = NULL;
360 if (cache->db != NULL) {
361 dns_db_detach(&cache->db);
364 if (cache->db_argv != NULL) {
366 * We don't free db_argv[0] in "rbt" cache databases
370 if (strcmp(cache->db_type, "rbt") == 0) {
373 for (int i = extra; i < cache->db_argc; i++) {
374 if (cache->db_argv[i] != NULL) {
375 isc_mem_free(cache->mctx, cache->db_argv[i]);
378 isc_mem_put(cache->mctx, cache->db_argv,
379 cache->db_argc * sizeof(char *));
382 if (cache->db_type != NULL) {
383 isc_mem_free(cache->mctx, cache->db_type);
386 if (cache->name != NULL) {
387 isc_mem_free(cache->mctx, cache->name);
390 if (cache->stats != NULL) {
391 isc_stats_detach(&cache->stats);
394 isc_mutex_destroy(&cache->lock);
395 isc_mutex_destroy(&cache->filelock);
397 cache->magic = 0;
398 isc_mem_detach(&cache->hmctx);
399 isc_mem_putanddetach(&cache->mctx, cache, sizeof(*cache));
403 dns_cache_attach(dns_cache_t *cache, dns_cache_t **targetp) {
404 REQUIRE(VALID_CACHE(cache));
407 isc_refcount_increment(&cache->references);
409 *targetp = cache;
414 dns_cache_t *cache;
417 cache = *cachep;
419 REQUIRE(VALID_CACHE(cache));
421 if (isc_refcount_decrement(&cache->references) == 1) {
422 cache->cleaner.overmem = false;
424 * When the cache is shut down, dump it to a file if one is
427 isc_result_t result = dns_cache_dump(cache);
431 "error dumping cache: %s ",
436 * If the cleaner task exists, let it free the cache.
438 if (isc_refcount_decrement(&cache->live_tasks) > 1) {
439 isc_task_shutdown(cache->cleaner.task);
441 cache_free(cache);
447 dns_cache_attachdb(dns_cache_t *cache, dns_db_t **dbp) {
448 REQUIRE(VALID_CACHE(cache));
450 REQUIRE(cache->db != NULL);
452 LOCK(&cache->lock);
453 dns_db_attach(cache->db, dbp);
454 UNLOCK(&cache->lock);
458 dns_cache_setfilename(dns_cache_t *cache, const char *filename) {
461 REQUIRE(VALID_CACHE(cache));
464 newname = isc_mem_strdup(cache->mctx, filename);
466 LOCK(&cache->filelock);
467 if (cache->filename) {
468 isc_mem_free(cache->mctx, cache->filename);
470 cache->filename = newname;
471 UNLOCK(&cache->filelock);
477 dns_cache_load(dns_cache_t *cache) {
480 REQUIRE(VALID_CACHE(cache));
482 if (cache->filename == NULL) {
486 LOCK(&cache->filelock);
487 result = dns_db_load(cache->db, cache->filename, dns_masterformat_text,
489 UNLOCK(&cache->filelock);
495 dns_cache_dump(dns_cache_t *cache) {
498 REQUIRE(VALID_CACHE(cache));
500 if (cache->filename == NULL) {
504 LOCK(&cache->filelock);
505 result = dns_master_dump(cache->mctx, cache->db, NULL,
506 &dns_master_style_cache, cache->filename,
508 UNLOCK(&cache->filelock);
513 dns_cache_getname(dns_cache_t *cache) {
514 REQUIRE(VALID_CACHE(cache));
516 return (cache->name);
520 * Initialize the cache cleaner object at *cleaner.
525 cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
533 cleaner->cache = cache;
542 result = dns_db_createiterator(cleaner->cache->db, false,
557 isc_refcount_increment(&cleaner->cache->live_tasks);
561 cleaner_shutdown_action, cache);
563 isc_refcount_decrement0(&cleaner->cache->live_tasks);
565 "cache cleaner: "
572 cache->mctx, cleaner, DNS_EVENT_CACHECLEAN,
577 cache->mctx, cleaner, DNS_EVENT_CACHEOVERMEM,
609 * position it at the beginning of the cache.
612 result = dns_db_createiterator(cleaner->cache->db, false,
618 "cache cleaner could not create "
632 "cache cleaner: "
649 ISC_LOG_DEBUG(1), "begin cache cleaning, mem inuse %lu",
650 (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
671 ISC_LOG_DEBUG(1), "end cache cleaning, mem inuse %lu",
672 (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
679 * This is called when the cache either surpasses its upper limit
746 LOCK(&cleaner->cache->lock);
750 (void)dns_db_createiterator(cleaner->cache->db, false,
755 UNLOCK(&cleaner->cache->lock);
772 "cache cleaner: "
785 dns_db_detachnode(cleaner->cache->db, &node);
795 * some error was signaled. If the cache is still
801 "cache cleaner: "
813 "cache cleaner: "
827 * not gone through the entire cache. Free the iterator locks
836 "cache cleaner: checked %u nodes, "
839 (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
850 dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now) {
854 REQUIRE(VALID_CACHE(cache));
856 result = dns_db_createiterator(cache->db, 0, &iterator);
874 result = dns_db_expirenode(cache->db, node, now);
877 "cache cleaner: dns_db_expirenode() "
888 dns_db_detachnode(cache->db, &node);
904 dns_cache_t *cache = arg;
907 REQUIRE(VALID_CACHE(cache));
909 LOCK(&cache->cleaner.lock);
911 if (overmem != cache->cleaner.overmem) {
912 dns_db_overmem(cache->db, overmem);
913 cache->cleaner.overmem = overmem;
914 isc_mem_waterack(cache->mctx, mark);
917 if (cache->cleaner.overmem_event != NULL) {
918 isc_task_send(cache->cleaner.task,
919 &cache->cleaner.overmem_event);
922 UNLOCK(&cache->cleaner.lock);
926 dns_cache_setcachesize(dns_cache_t *cache, size_t size) {
929 REQUIRE(VALID_CACHE(cache));
932 * Impose a minimum cache size; pathological things happen if there
939 LOCK(&cache->lock);
940 cache->size = size;
941 UNLOCK(&cache->lock);
947 * If the cache was overmem and cleaning, but now with the new limits
949 * isc_mem_put for cache memory will do the right thing and trigger
955 * Disable cache memory limiting.
957 isc_mem_setwater(cache->mctx, water, cache, 0, 0);
960 * Establish new cache memory limits (either for the first
963 isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater);
966 dns_db_adjusthashsize(cache->db, size);
970 dns_cache_getcachesize(dns_cache_t *cache) {
973 REQUIRE(VALID_CACHE(cache));
975 LOCK(&cache->lock);
976 size = cache->size;
977 UNLOCK(&cache->lock);
983 dns_cache_setservestalettl(dns_cache_t *cache, dns_ttl_t ttl) {
984 REQUIRE(VALID_CACHE(cache));
986 LOCK(&cache->lock);
987 cache->serve_stale_ttl = ttl;
988 UNLOCK(&cache->lock);
990 (void)dns_db_setservestalettl(cache->db, ttl);
994 dns_cache_getservestalettl(dns_cache_t *cache) {
998 REQUIRE(VALID_CACHE(cache));
1004 result = dns_db_getservestalettl(cache->db, &ttl);
1009 dns_cache_setservestalerefresh(dns_cache_t *cache, dns_ttl_t interval) {
1010 REQUIRE(VALID_CACHE(cache));
1012 LOCK(&cache->lock);
1013 cache->serve_stale_refresh = interval;
1014 UNLOCK(&cache->lock);
1016 (void)dns_db_setservestalerefresh(cache->db, interval);
1020 dns_cache_getservestalerefresh(dns_cache_t *cache) {
1024 REQUIRE(VALID_CACHE(cache));
1026 result = dns_db_getservestalerefresh(cache->db, &interval);
1035 dns_cache_t *cache = event->ev_arg;
1039 INSIST(task == cache->cleaner.task);
1042 if (CLEANER_BUSY(&cache->cleaner)) {
1043 end_cleaning(&cache->cleaner, event);
1051 isc_refcount_decrementz(&cache->live_tasks);
1053 cache_free(cache);
1057 dns_cache_flush(dns_cache_t *cache) {
1062 result = cache_create_db(cache, &db);
1073 LOCK(&cache->lock);
1074 LOCK(&cache->cleaner.lock);
1075 if (cache->cleaner.state == cleaner_s_idle) {
1076 olddbiterator = cache->cleaner.iterator;
1077 cache->cleaner.iterator = dbiterator;
1080 if (cache->cleaner.state == cleaner_s_busy) {
1081 cache->cleaner.state = cleaner_s_done;
1083 cache->cleaner.replaceiterator = true;
1085 olddb = cache->db;
1086 cache->db = db;
1087 dns_db_setcachestats(cache->db, cache->stats);
1088 UNLOCK(&cache->cleaner.lock);
1089 UNLOCK(&cache->lock);
1212 dns_cache_flushname(dns_cache_t *cache, const dns_name_t *name) {
1213 return (dns_cache_flushnode(cache, name, false));
1217 dns_cache_flushnode(dns_cache_t *cache, const dns_name_t *name, bool tree) {
1223 return (dns_cache_flush(cache));
1226 LOCK(&cache->lock);
1227 if (cache->db != NULL) {
1228 dns_db_attach(cache->db, &db);
1230 UNLOCK(&cache->lock);
1236 result = cleartree(cache->db, name);
1238 result = dns_db_findnode(cache->db, name, false, &node);
1246 result = clearnode(cache->db, node);
1247 dns_db_detachnode(cache->db, &node);
1256 dns_cache_getstats(dns_cache_t *cache) {
1257 REQUIRE(VALID_CACHE(cache));
1258 return (cache->stats);
1262 dns_cache_updatestats(dns_cache_t *cache, isc_result_t result) {
1263 REQUIRE(VALID_CACHE(cache));
1264 if (cache->stats == NULL) {
1276 isc_stats_increment(cache->stats,
1280 isc_stats_increment(cache->stats,
1323 dns_cache_dumpstats(dns_cache_t *cache, FILE *fp) {
1327 REQUIRE(VALID_CACHE(cache));
1329 getcounters(cache->stats, isc_statsformat_file,
1333 "cache hits");
1335 "cache misses");
1338 "cache hits (from query)");
1341 "cache misses (from query)");
1344 "cache records deleted due to memory exhaustion");
1347 "cache
1348 fprintf(fp, "%20u %s\n", dns_db_nodecount(cache->db),
1349 "cache database nodes");
1350 fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)dns_db_hashsize(cache->db),
1351 "cache database hash buckets");
1353 fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_total(cache->mctx),
1354 "cache tree memory total");
1355 fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_inuse(cache->mctx),
1356 "cache tree memory in use");
1358 (uint64_t)isc_mem_maxinuse(cache->mctx),
1359 "cache tree highest memory in use");
1361 fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_total(cache->hmctx),
1362 "cache heap memory total");
1363 fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_inuse(cache->hmctx),
1364 "cache heap memory in use");
1366 (uint64_t)isc_mem_maxinuse(cache->hmctx),
1367 "cache heap highest memory in use");
1392 dns_cache_renderxml(dns_cache_t *cache, void *writer0) {
1398 REQUIRE(VALID_CACHE(cache));
1400 getcounters(cache->stats, isc_statsformat_file,
1415 TRY0(renderstat("CacheNodes", dns_db_nodecount(cache->db), writer));
1416 TRY0(renderstat("CacheBuckets", dns_db_hashsize(cache->db), writer));
1418 TRY0(renderstat("TreeMemTotal", isc_mem_total(cache->mctx), writer));
1419 TRY0(renderstat("TreeMemInUse", isc_mem_inuse(cache->mctx), writer));
1420 TRY0(renderstat("TreeMemMax", isc_mem_maxinuse(cache->mctx), writer));
1422 TRY0(renderstat("HeapMemTotal", isc_mem_total(cache->hmctx), writer));
1423 TRY0(renderstat("HeapMemInUse", isc_mem_inuse(cache->hmctx), writer));
1424 TRY0(renderstat("HeapMemMax", isc_mem_maxinuse(cache->hmctx), writer));
1440 dns_cache_renderjson(dns_cache_t *cache, void *cstats0) {
1447 REQUIRE(VALID_CACHE(cache));
1449 getcounters(cache->stats, isc_statsformat_file,
1476 obj = json_object_new_int64(dns_db_nodecount(cache->db));
1480 obj = json_object_new_int64(dns_db_hashsize(cache->db));
1484 obj = json_object_new_int64(isc_mem_total(cache->mctx));
1488 obj = json_object_new_int64(isc_mem_inuse(cache->mctx));
1492 obj = json_object_new_int64(isc_mem_maxinuse(cache->mctx));
1496 obj = json_object_new_int64(isc_mem_total(cache->hmctx));
1500 obj = json_object_new_int64(isc_mem_inuse(cache->hmctx));
1504 obj = json_object_new_int64(isc_mem_maxinuse(cache->hmctx));