Lines Matching defs:acache
17 /* $Id: acache.c,v 1.22 2008/02/07 23:46:54 tbox Exp $ */
35 #include <dns/acache.h>
46 #define DNS_ACACHE_VALID(acache) ISC_MAGIC_VALID(acache, ACACHE_MAGIC)
58 "acache %p: %s", acache, (m))
63 "acache %p: %s", (a), (m))
102 /* Locked by acache lock */
135 dns_acache_t *acache;
150 Locked by acache lock. */
157 isc_boolean_t overmem; /* The acache is in an overmem
175 * The actual acache object.
213 dns_acache_t *acache;
244 static inline isc_boolean_t check_noentry(dns_acache_t *acache);
245 static void destroy(dns_acache_t *acache);
246 static void shutdown_entries(dns_acache_t *acache);
247 static void shutdown_buckets(dns_acache_t *acache);
249 static inline void unlink_dbentries(dns_acache_t *acache,
251 static inline isc_result_t finddbent(dns_acache_t *acache,
253 static inline void clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry);
254 static isc_result_t acache_cleaner_init(dns_acache_t *acache,
266 * acache should be locked. If it is not, the stats can get out of whack,
270 reset_stats(dns_acache_t *acache) {
271 acache->stats.hits = 0;
272 acache->stats.queries = 0;
273 acache->stats.misses = 0;
274 acache->stats.adds = 0;
275 acache->stats.deleted = 0;
276 acache->stats.cleaned = 0;
277 acache->stats.overmem = 0;
278 acache->stats.overmem_nocreates = 0;
279 acache->stats.nomem = 0;
283 * The acache must be locked before calling.
286 check_noentry(dns_acache_t *acache) {
287 if (ISC_LIST_EMPTY(acache->entries) && acache->dbentries == 0) {
295 * The acache must be locked before calling.
298 shutdown_entries(dns_acache_t *acache) {
301 REQUIRE(DNS_ACACHE_VALID(acache));
302 INSIST(acache->shutting_down);
307 for (entry = ISC_LIST_HEAD(acache->entries);
312 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
319 if (acache->cleaner.current_entry != entry)
320 ISC_LIST_UNLINK(acache->entries, entry, link);
321 unlink_dbentries(acache, entry);
327 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
330 if (acache->cleaner.current_entry != entry)
336 * The acache must be locked before calling.
339 shutdown_buckets(dns_acache_t *acache) {
343 REQUIRE(DNS_ACACHE_VALID(acache));
344 INSIST(acache->shutting_down);
347 while ((dbent = ISC_LIST_HEAD(acache->dbbucket[i])) != NULL) {
350 ISC_LIST_UNLINK(acache->dbbucket[i], dbent, link);
354 isc_mem_put(acache->mctx, dbent, sizeof(*dbent));
356 acache->dbentries--;
360 INSIST(acache->dbentries == 0);
365 dns_acache_t *acache;
369 acache = ev->ev_arg;
370 INSIST(DNS_ACACHE_VALID(acache));
374 LOCK(&acache->lock);
376 shutdown_entries(acache);
377 shutdown_buckets(acache);
379 UNLOCK(&acache->lock);
381 dns_acache_detach(&acache);
384 /* The acache and the entry must be locked before calling. */
386 unlink_dbentries(dns_acache_t *acache, dns_acacheentry_t *ent) {
393 result = finddbent(acache, ent->origdb, &dbent);
401 result = finddbent(acache, ent->db, &dbent);
411 dns_acache_t *acache;
415 acache = entry->acache;
416 REQUIRE(DNS_ACACHE_VALID(acache));
422 clear_entry(acache, entry);
424 isc_mem_put(acache->mctx, entry, sizeof(*entry));
426 dns_acache_detach(&acache);
430 destroy(dns_acache_t *acache) {
433 REQUIRE(DNS_ACACHE_VALID(acache));
437 isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);
439 if (acache->cleaner.overmem_event != NULL)
440 isc_event_free(&acache->cleaner.overmem_event);
442 if (acache->cleaner.resched_event != NULL)
443 isc_event_free(&acache->cleaner.resched_event);
445 if (acache->task != NULL)
446 isc_task_detach(&acache->task);
449 ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
450 isc_mem_put(acache->mctx, acache->entrylocks,
451 sizeof(*acache->entrylocks) *
454 DESTROYLOCK(&acache->cleaner.lock);
456 DESTROYLOCK(&acache->lock);
457 acache->magic = 0;
459 isc_mem_putanddetach(&acache->mctx, acache, sizeof(*acache));
463 finddbent(dns_acache_t *acache, dns_db_t *db, dbentry_t **dbentryp) {
467 REQUIRE(DNS_ACACHE_VALID(acache));
472 * The caller must be holding the acache lock.
478 for (dbentry = ISC_LIST_HEAD(acache->dbbucket[bucket]);
494 clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry) {
495 REQUIRE(DNS_ACACHE_VALID(acache));
512 isc_mem_put(acache->mctx, rdataset, sizeof(*rdataset));
515 dns_name_free(entry->foundname, acache->mctx);
516 isc_mem_put(acache->mctx, entry->foundname,
539 acache_cleaner_init(dns_acache_t *acache, isc_timermgr_t *timermgr,
544 ATRACE("acache cleaner init");
552 cleaner->acache = acache;
561 cleaner->acache->live_cleaners++;
563 result = isc_task_onshutdown(acache->task,
565 acache);
568 "acache cleaner: "
578 acache->task,
590 isc_event_allocate(acache->mctx, cleaner,
600 isc_event_allocate(acache->mctx, cleaner,
619 cleaner->acache->live_cleaners--;
628 dns_acache_t *acache = cleaner->acache;
632 * parameters (except current_entry, which is locked by acache lock,)
637 INSIST(DNS_ACACHE_VALID(acache));
642 "begin acache cleaning, mem inuse %lu",
643 (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
645 LOCK(&acache->lock);
647 head = ISC_LIST_HEAD(acache->entries);
651 UNLOCK(&acache->lock);
656 isc_task_send(acache->task, &cleaner->resched_event);
664 dns_acache_t *acache = cleaner->acache;
672 LOCK(&acache->lock);
683 ISC_LIST_UNLINK(acache->entries,
690 acache->stats.overmem++;
691 acache->stats.cleaned += cleaner->ncleaned;
692 acache->stats.cleaner_runs++;
696 "acache %p stats: hits=%d misses=%d queries=%d "
700 acache,
701 acache->stats.hits, acache->stats.misses,
702 acache->stats.queries,
703 acache->stats.adds, acache->stats.deleted,
704 acache->stats.cleaned, acache->stats.cleaner_runs,
705 acache->stats.overmem, acache->stats.overmem_nocreates,
706 acache->stats.nomem);
707 reset_stats(acache);
711 UNLOCK(&acache->lock);
713 dns_acache_setcleaninginterval(cleaner->acache,
717 ISC_LOG_DEBUG(1), "end acache cleaning, "
720 (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
725 "acache is still in overmem state "
735 * This is run once for every acache-cleaning-interval as defined
747 ISC_LOG_DEBUG(1), "acache cleaning timer fired, "
775 * If the acache is in the overmem state, probabilistically decide if
805 dns_acache_t *acache = cleaner->acache;
812 INSIST(DNS_ACACHE_VALID(acache));
813 INSIST(task == acache->task);
829 LOCK(&acache->lock);
845 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
850 ISC_LIST_UNLINK(acache->entries, entry, link);
851 unlink_dbentries(acache, entry);
859 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
867 entry = ISC_LIST_HEAD(acache->entries);
881 "acache cleaner: "
889 UNLOCK(&acache->lock);
907 UNLOCK(&acache->lock);
910 ISC_LOG_DEBUG(1), "acache cleaner: checked %d entries, "
912 (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
921 * This is called when the acache either surpasses its upper limit
967 dns_acache_t *acache = arg;
970 REQUIRE(DNS_ACACHE_VALID(acache));
974 "acache memory reaches %s watermark, mem inuse %lu",
976 (unsigned long)isc_mem_inuse(acache->mctx));
978 LOCK(&acache->cleaner.lock);
980 if (acache->cleaner.overmem != overmem) {
981 acache->cleaner.overmem = overmem;
983 if (acache->cleaner.overmem_event != NULL)
984 isc_task_send(acache->task,
985 &acache->cleaner.overmem_event);
986 isc_mem_waterack(acache->mctx, mark);
989 UNLOCK(&acache->cleaner.lock);
997 dns_acache_t *acache = event->ev_arg;
1000 INSIST(task == acache->task);
1002 INSIST(DNS_ACACHE_VALID(acache));
1004 ATRACE("acache cleaner shutdown");
1006 if (CLEANER_BUSY(&acache->cleaner))
1007 end_cleaning(&acache->cleaner, event);
1011 LOCK(&acache->lock);
1013 acache->live_cleaners--;
1014 INSIST(acache->live_cleaners == 0);
1016 if (isc_refcount_current(&acache->refs) == 0) {
1017 INSIST(check_noentry(acache) == ISC_TRUE);
1026 if (acache->cleaner.cleaning_timer != NULL)
1027 isc_timer_detach(&acache->cleaner.cleaning_timer);
1032 UNLOCK(&acache->lock);
1035 destroy(acache);
1048 dns_acache_t *acache;
1054 acache = isc_mem_get(mctx, sizeof(*acache));
1055 if (acache == NULL)
1060 result = isc_refcount_init(&acache->refs, 1);
1062 isc_mem_put(mctx, acache, sizeof(*acache));
1066 result = isc_mutex_init(&acache->lock);
1068 isc_refcount_decrement(&acache->refs, NULL);
1069 isc_refcount_destroy(&acache->refs);
1070 isc_mem_put(mctx, acache, sizeof(*acache));
1074 acache->mctx = NULL;
1075 isc_mem_attach(mctx, &acache->mctx);
1076 ISC_LIST_INIT(acache->entries);
1078 acache->shutting_down = ISC_FALSE;
1080 acache->task = NULL;
1081 acache->entrylocks = NULL;
1083 result = isc_task_create(taskmgr, 1, &acache->task);
1091 isc_task_setname(acache->task, "acachetask", acache);
1092 ISC_EVENT_INIT(&acache->cevent, sizeof(acache->cevent), 0, NULL,
1095 acache->cevent_sent = ISC_FALSE;
1097 acache->dbentries = 0;
1099 ISC_LIST_INIT(acache->dbbucket[i]);
1101 acache->entrylocks = isc_mem_get(mctx, sizeof(*acache->entrylocks) *
1103 if (acache->entrylocks == NULL) {
1108 result = ACACHE_INITLOCK(&acache->entrylocks[i]);
1111 ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
1112 isc_mem_put(mctx, acache->entrylocks,
1113 sizeof(*acache->entrylocks) *
1115 acache->entrylocks = NULL;
1120 acache->live_cleaners = 0;
1121 result = acache_cleaner_init(acache, timermgr, &acache->cleaner);
1125 acache->stats.cleaner_runs = 0;
1126 reset_stats(acache);
1128 acache->magic = ACACHE_MAGIC;
1130 *acachep = acache;
1134 if (acache->task != NULL)
1135 isc_task_detach(&acache->task);
1136 DESTROYLOCK(&acache->lock);
1137 isc_refcount_decrement(&acache->refs, NULL);
1138 isc_refcount_destroy(&acache->refs);
1139 if (acache->entrylocks != NULL) {
1141 ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
1142 isc_mem_put(mctx, acache->entrylocks,
1143 sizeof(*acache->entrylocks) *
1146 isc_mem_put(mctx, acache, sizeof(*acache));
1165 dns_acache_countquerymiss(dns_acache_t *acache) {
1166 acache->stats.misses++; /* XXXSK danger: unlocked! */
1167 acache->stats.queries++; /* XXXSK danger: unlocked! */
1172 dns_acache_t *acache;
1177 acache = *acachep;
1181 isc_refcount_decrement(&acache->refs, &refs);
1183 INSIST(check_noentry(acache) == ISC_TRUE);
1192 if (should_free && acache->live_cleaners > 0) {
1193 isc_task_shutdown(acache->task);
1198 destroy(acache);
1202 dns_acache_shutdown(dns_acache_t *acache) {
1203 REQUIRE(DNS_ACACHE_VALID(acache));
1205 LOCK(&acache->lock);
1209 if (!acache->shutting_down) {
1213 INSIST(!acache->cevent_sent);
1215 acache->shutting_down = ISC_TRUE;
1217 isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);
1223 dns_acache_attach(acache, &acache_evarg);
1224 event = &acache->cevent;
1226 isc_task_send(acache->task, &event);
1227 acache->cevent_sent = ISC_TRUE;
1230 UNLOCK(&acache->lock);
1234 dns_acache_setdb(dns_acache_t *acache, dns_db_t *db) {
1239 REQUIRE(DNS_ACACHE_VALID(acache));
1244 LOCK(&acache->lock);
1247 result = finddbent(acache, db, &dbentry);
1254 dbentry = isc_mem_get(acache->mctx, sizeof(*dbentry));
1270 ISC_LIST_APPEND(acache->dbbucket[bucket], dbentry, link);
1272 acache->dbentries++;
1275 UNLOCK(&acache->lock);
1281 dns_acache_putdb(dns_acache_t *acache, dns_db_t *db) {
1287 REQUIRE(DNS_ACACHE_VALID(acache));
1292 LOCK(&acache->lock);
1295 result = finddbent(acache, db, &dbentry);
1300 UNLOCK(&acache->lock);
1311 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
1319 if (acache->cleaner.current_entry != entry)
1320 ISC_LIST_UNLINK(acache->entries, entry, link);
1321 unlink_dbentries(acache, entry);
1327 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1330 if (acache->cleaner.current_entry != entry)
1334 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
1338 if (acache->cleaner.current_entry != entry)
1339 ISC_LIST_UNLINK(acache->entries, entry, link);
1340 unlink_dbentries(acache, entry);
1346 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1349 if (acache->cleaner.current_entry != entry)
1358 ISC_LIST_UNLINK(acache->dbbucket[bucket], dbentry, link);
1361 isc_mem_put(acache->mctx, dbentry, sizeof(*dbentry));
1363 acache->dbentries--;
1365 acache->stats.deleted++;
1367 UNLOCK(&acache->lock);
1373 dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
1381 REQUIRE(DNS_ACACHE_VALID(acache));
1390 * XXXSK: It might be better to lock the acache->cleaner->lock,
1397 if (acache->cleaner.overmem) {
1398 acache->stats.overmem_nocreates++; /* XXXSK danger: unlocked! */
1402 newentry = isc_mem_get(acache->mctx, sizeof(*newentry));
1404 acache->stats.nomem++; /* XXXMLG danger: unlocked! */
1413 isc_mem_put(acache->mctx, newentry, sizeof(*newentry));
1421 newentry->acache = NULL;
1422 dns_acache_attach(acache, &newentry->acache);
1453 dns_acache_t *acache;
1463 acache = entry->acache;
1464 REQUIRE(DNS_ACACHE_VALID(acache));
1467 ACACHE_LOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
1497 ACACHE_UNLOCK(&acache->entrylocks[locknum],
1514 entry->acache->stats.hits++; /* XXXMLG danger: unlocked! */
1515 entry->acache->stats.queries++;
1517 ACACHE_UNLOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
1540 dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
1550 REQUIRE(DNS_ACACHE_VALID(acache));
1553 LOCK(&acache->lock); /* XXX: need to lock it here for ordering */
1554 ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
1594 entry->foundname = isc_mem_get(acache->mctx,
1602 result = dns_name_dup(fname, acache->mctx,
1610 crdataset = isc_mem_get(acache->mctx,
1625 result = finddbent(acache, entry->origdb, &odbent);
1630 result = finddbent(acache, db, &rdbent);
1635 ISC_LIST_APPEND(acache->entries, entry, link);
1646 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1649 acache->stats.adds++;
1650 UNLOCK(&acache->lock);
1655 clear_entry(acache, entry);
1657 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1659 UNLOCK(&acache->lock);
1666 dns_acache_t *acache;
1671 acache = entry->acache;
1673 INSIST(DNS_ACACHE_VALID(entry->acache));
1675 LOCK(&acache->lock);
1676 ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
1682 * The main link cannot be released, since the acache object has
1686 unlink_dbentries(acache, entry);
1687 clear_entry(entry->acache, entry);
1692 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1694 UNLOCK(&acache->lock);
1727 (*entryp)->acache->stats.deleted++;
1735 dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) {
1739 REQUIRE(DNS_ACACHE_VALID(acache));
1743 LOCK(&acache->lock);
1746 * It may be the case that the acache has already shut down.
1749 if (acache->cleaner.cleaning_timer == NULL)
1752 acache->cleaner.cleaning_interval = t;
1755 result = isc_timer_reset(acache->cleaner.cleaning_timer,
1759 isc_interval_set(&interval, acache->cleaner.cleaning_interval,
1761 result = isc_timer_reset(acache->cleaner.cleaning_timer,
1768 "could not set acache cleaning interval: %s",
1773 "acache %p cleaning interval set to %d.",
1774 acache, t);
1777 UNLOCK(&acache->lock);
1785 dns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size) {
1789 REQUIRE(DNS_ACACHE_VALID(acache));
1798 isc_mem_setwater(acache->mctx, water, acache, 0, 0);
1800 isc_mem_setwater(acache->mctx, water, acache,