Lines Matching refs:acache
9 /* $Id: acache.c,v 1.22 2008/02/07 23:46:54 tbox Exp $ */
29 #include <dns/acache.h>
44 #define DNS_ACACHE_VALID(acache) ISC_MAGIC_VALID(acache, ACACHE_MAGIC)
56 "acache %p: %s", acache, (m))
61 "acache %p: %s", (a), (m))
112 /* Locked by acache lock */
145 dns_acache_t *acache;
160 Locked by acache lock. */
167 isc_boolean_t overmem; /* The acache is in an overmem
185 * The actual acache object.
223 dns_acache_t *acache;
258 static inline isc_boolean_t check_noentry(dns_acache_t *acache);
259 static void destroy(dns_acache_t *acache);
260 static void shutdown_entries(dns_acache_t *acache);
261 static void shutdown_buckets(dns_acache_t *acache);
263 static inline void unlink_dbentries(dns_acache_t *acache,
265 static inline isc_result_t finddbent(dns_acache_t *acache,
267 static inline void clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry);
268 static isc_result_t acache_cleaner_init(dns_acache_t *acache,
280 * acache should be locked. If it is not, the stats can get out of whack,
284 reset_stats(dns_acache_t *acache) {
285 acache->stats.hits = 0;
286 acache->stats.queries = 0;
287 acache->stats.misses = 0;
288 acache->stats.adds = 0;
289 acache->stats.deleted = 0;
290 acache->stats.cleaned = 0;
291 acache->stats.overmem = 0;
292 acache->stats.overmem_nocreates = 0;
293 acache->stats.nomem = 0;
297 * The acache must be locked before calling.
300 check_noentry(dns_acache_t *acache) {
301 if (ISC_LIST_EMPTY(acache->entries) && acache->dbentries == 0) {
309 * The acache must be locked before calling.
312 shutdown_entries(dns_acache_t *acache) {
315 REQUIRE(DNS_ACACHE_VALID(acache));
316 INSIST(acache->shutting_down);
321 for (entry = ISC_LIST_HEAD(acache->entries);
326 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
333 if (acache->cleaner.current_entry != entry)
334 ISC_LIST_UNLINK(acache->entries, entry, link);
335 unlink_dbentries(acache, entry);
341 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
344 if (acache->cleaner.current_entry != entry)
350 * The acache must be locked before calling.
353 shutdown_buckets(dns_acache_t *acache) {
357 REQUIRE(DNS_ACACHE_VALID(acache));
358 INSIST(acache->shutting_down);
361 while ((dbent = ISC_LIST_HEAD(acache->dbbucket[i])) != NULL) {
364 ISC_LIST_UNLINK(acache->dbbucket[i], dbent, link);
368 isc_mem_put(acache->mctx, dbent, sizeof(*dbent));
370 acache->dbentries--;
374 INSIST(acache->dbentries == 0);
379 dns_acache_t *acache;
383 acache = ev->ev_arg;
384 INSIST(DNS_ACACHE_VALID(acache));
388 LOCK(&acache->lock);
390 shutdown_entries(acache);
391 shutdown_buckets(acache);
393 UNLOCK(&acache->lock);
395 dns_acache_detach(&acache);
398 /* The acache and the entry must be locked before calling. */
400 unlink_dbentries(dns_acache_t *acache, dns_acacheentry_t *ent) {
407 result = finddbent(acache, ent->origdb, &dbent);
415 result = finddbent(acache, ent->db, &dbent);
425 dns_acache_t *acache;
429 acache = entry->acache;
430 REQUIRE(DNS_ACACHE_VALID(acache));
436 clear_entry(acache, entry);
438 isc_mem_put(acache->mctx, entry, sizeof(*entry));
440 dns_acache_detach(&acache);
444 destroy(dns_acache_t *acache) {
447 REQUIRE(DNS_ACACHE_VALID(acache));
451 isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);
453 if (acache->cleaner.overmem_event != NULL)
454 isc_event_free(&acache->cleaner.overmem_event);
456 if (acache->cleaner.resched_event != NULL)
457 isc_event_free(&acache->cleaner.resched_event);
459 if (acache->task != NULL)
460 isc_task_detach(&acache->task);
463 ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
464 isc_mem_put(acache->mctx, acache->entrylocks,
465 sizeof(*acache->entrylocks) *
468 DESTROYLOCK(&acache->cleaner.lock);
470 DESTROYLOCK(&acache->lock);
471 acache->magic = 0;
473 isc_mem_putanddetach(&acache->mctx, acache, sizeof(*acache));
477 finddbent(dns_acache_t *acache, dns_db_t *db, dbentry_t **dbentryp) {
481 REQUIRE(DNS_ACACHE_VALID(acache));
486 * The caller must be holding the acache lock.
491 for (dbentry = ISC_LIST_HEAD(acache->dbbucket[bucket]);
507 clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry) {
508 REQUIRE(DNS_ACACHE_VALID(acache));
525 isc_mem_put(acache->mctx, rdataset, sizeof(*rdataset));
528 dns_name_free(entry->foundname, acache->mctx);
529 isc_mem_put(acache->mctx, entry->foundname,
552 acache_cleaner_init(dns_acache_t *acache, isc_timermgr_t *timermgr,
557 ATRACE("acache cleaner init");
565 cleaner->acache = acache;
574 cleaner->acache->live_cleaners++;
576 result = isc_task_onshutdown(acache->task,
578 acache);
581 "acache cleaner: "
591 acache->task,
603 isc_event_allocate(acache->mctx, cleaner,
613 isc_event_allocate(acache->mctx, cleaner,
632 cleaner->acache->live_cleaners--;
641 dns_acache_t *acache = cleaner->acache;
645 * parameters (except current_entry, which is locked by acache lock,)
650 INSIST(DNS_ACACHE_VALID(acache));
655 "begin acache cleaning, mem inuse %lu",
656 (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
658 LOCK(&acache->lock);
660 head = ISC_LIST_HEAD(acache->entries);
664 UNLOCK(&acache->lock);
669 isc_task_send(acache->task, &cleaner->resched_event);
677 dns_acache_t *acache = cleaner->acache;
685 LOCK(&acache->lock);
696 ISC_LIST_UNLINK(acache->entries,
703 acache->stats.overmem++;
704 acache->stats.cleaned += cleaner->ncleaned;
705 acache->stats.cleaner_runs++;
709 "acache %p stats: hits=%d misses=%d queries=%d "
713 acache,
714 acache->stats.hits, acache->stats.misses,
715 acache->stats.queries,
716 acache->stats.adds, acache->stats.deleted,
717 acache->stats.cleaned, acache->stats.cleaner_runs,
718 acache->stats.overmem, acache->stats.overmem_nocreates,
719 acache->stats.nomem);
720 reset_stats(acache);
724 UNLOCK(&acache->lock);
726 dns_acache_setcleaninginterval(cleaner->acache,
730 ISC_LOG_DEBUG(1), "end acache cleaning, "
733 (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
738 "acache is still in overmem state "
748 * This is run once for every acache-cleaning-interval as defined
760 ISC_LOG_DEBUG(1), "acache cleaning timer fired, "
788 * If the acache is in the overmem state, probabilistically decide if
818 dns_acache_t *acache = cleaner->acache;
825 INSIST(DNS_ACACHE_VALID(acache));
826 INSIST(task == acache->task);
842 LOCK(&acache->lock);
858 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
863 ISC_LIST_UNLINK(acache->entries, entry, link);
864 unlink_dbentries(acache, entry);
872 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
880 entry = ISC_LIST_HEAD(acache->entries);
894 "acache cleaner: "
902 UNLOCK(&acache->lock);
920 UNLOCK(&acache->lock);
923 ISC_LOG_DEBUG(1), "acache cleaner: checked %d entries, "
925 (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
934 * This is called when the acache either surpasses its upper limit
980 dns_acache_t *acache = arg;
983 REQUIRE(DNS_ACACHE_VALID(acache));
987 "acache memory reaches %s watermark, mem inuse %lu",
989 (unsigned long)isc_mem_inuse(acache->mctx));
991 LOCK(&acache->cleaner.lock);
993 if (acache->cleaner.overmem != overmem) {
994 acache->cleaner.overmem = overmem;
996 if (acache->cleaner.overmem_event != NULL)
997 isc_task_send(acache->task,
998 &acache->cleaner.overmem_event);
999 isc_mem_waterack(acache->mctx, mark);
1002 UNLOCK(&acache->cleaner.lock);
1010 dns_acache_t *acache = event->ev_arg;
1013 INSIST(task == acache->task);
1015 INSIST(DNS_ACACHE_VALID(acache));
1017 ATRACE("acache cleaner shutdown");
1019 if (CLEANER_BUSY(&acache->cleaner))
1020 end_cleaning(&acache->cleaner, event);
1024 LOCK(&acache->lock);
1026 acache->live_cleaners--;
1027 INSIST(acache->live_cleaners == 0);
1029 if (isc_refcount_current(&acache->refs) == 0) {
1030 INSIST(check_noentry(acache) == ISC_TRUE);
1039 if (acache->cleaner.cleaning_timer != NULL)
1040 isc_timer_detach(&acache->cleaner.cleaning_timer);
1045 UNLOCK(&acache->lock);
1048 destroy(acache);
1061 dns_acache_t *acache;
1067 acache = isc_mem_get(mctx, sizeof(*acache));
1068 if (acache == NULL)
1073 result = isc_refcount_init(&acache->refs, 1);
1075 isc_mem_put(mctx, acache, sizeof(*acache));
1079 result = isc_mutex_init(&acache->lock);
1081 isc_refcount_decrement(&acache->refs, NULL);
1082 isc_refcount_destroy(&acache->refs);
1083 isc_mem_put(mctx, acache, sizeof(*acache));
1087 acache->mctx = NULL;
1088 isc_mem_attach(mctx, &acache->mctx);
1089 ISC_LIST_INIT(acache->entries);
1091 acache->shutting_down = ISC_FALSE;
1093 acache->task = NULL;
1094 acache->entrylocks = NULL;
1096 result = isc_task_create(taskmgr, 1, &acache->task);
1104 isc_task_setname(acache->task, "acachetask", acache);
1105 ISC_EVENT_INIT(&acache->cevent, sizeof(acache->cevent), 0, NULL,
1108 acache->cevent_sent = ISC_FALSE;
1110 acache->dbentries = 0;
1112 ISC_LIST_INIT(acache->dbbucket[i]);
1114 acache->entrylocks = isc_mem_get(mctx, sizeof(*acache->entrylocks) *
1116 if (acache->entrylocks == NULL) {
1121 result = ACACHE_INITLOCK(&acache->entrylocks[i]);
1124 ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
1125 isc_mem_put(mctx, acache->entrylocks,
1126 sizeof(*acache->entrylocks) *
1128 acache->entrylocks = NULL;
1133 acache->live_cleaners = 0;
1134 result = acache_cleaner_init(acache, timermgr, &acache->cleaner);
1138 acache->stats.cleaner_runs = 0;
1139 reset_stats(acache);
1141 acache->magic = ACACHE_MAGIC;
1143 *acachep = acache;
1147 if (acache->task != NULL)
1148 isc_task_detach(&acache->task);
1149 DESTROYLOCK(&acache->lock);
1150 isc_refcount_decrement(&acache->refs, NULL);
1151 isc_refcount_destroy(&acache->refs);
1152 if (acache->entrylocks != NULL) {
1154 ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
1155 isc_mem_put(mctx, acache->entrylocks,
1156 sizeof(*acache->entrylocks) *
1159 isc_mem_put(mctx, acache, sizeof(*acache));
1178 dns_acache_countquerymiss(dns_acache_t *acache) {
1179 acache->stats.misses++; /* XXXSK danger: unlocked! */
1180 acache->stats.queries++; /* XXXSK danger: unlocked! */
1185 dns_acache_t *acache;
1190 acache = *acachep;
1194 isc_refcount_decrement(&acache->refs, &refs);
1196 INSIST(check_noentry(acache) == ISC_TRUE);
1205 if (should_free && acache->live_cleaners > 0) {
1206 isc_task_shutdown(acache->task);
1211 destroy(acache);
1215 dns_acache_shutdown(dns_acache_t *acache) {
1216 REQUIRE(DNS_ACACHE_VALID(acache));
1218 LOCK(&acache->lock);
1222 if (!acache->shutting_down) {
1226 INSIST(!acache->cevent_sent);
1228 acache->shutting_down = ISC_TRUE;
1230 isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);
1236 dns_acache_attach(acache, &acache_evarg);
1237 event = &acache->cevent;
1239 isc_task_send(acache->task, &event);
1240 acache->cevent_sent = ISC_TRUE;
1243 UNLOCK(&acache->lock);
1247 dns_acache_setdb(dns_acache_t *acache, dns_db_t *db) {
1252 REQUIRE(DNS_ACACHE_VALID(acache));
1257 LOCK(&acache->lock);
1260 result = finddbent(acache, db, &dbentry);
1267 dbentry = isc_mem_get(acache->mctx, sizeof(*dbentry));
1282 ISC_LIST_APPEND(acache->dbbucket[bucket], dbentry, link);
1284 acache->dbentries++;
1287 UNLOCK(&acache->lock);
1293 dns_acache_putdb(dns_acache_t *acache, dns_db_t *db) {
1299 REQUIRE(DNS_ACACHE_VALID(acache));
1304 LOCK(&acache->lock);
1307 result = finddbent(acache, db, &dbentry);
1312 UNLOCK(&acache->lock);
1323 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
1331 if (acache->cleaner.current_entry != entry)
1332 ISC_LIST_UNLINK(acache->entries, entry, link);
1333 unlink_dbentries(acache, entry);
1339 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1342 if (acache->cleaner.current_entry != entry)
1346 ACACHE_LOCK(&acache->entrylocks[entry->locknum],
1350 if (acache->cleaner.current_entry != entry)
1351 ISC_LIST_UNLINK(acache->entries, entry, link);
1352 unlink_dbentries(acache, entry);
1358 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1361 if (acache->cleaner.current_entry != entry)
1370 ISC_LIST_UNLINK(acache->dbbucket[bucket], dbentry, link);
1373 isc_mem_put(acache->mctx, dbentry, sizeof(*dbentry));
1375 acache->dbentries--;
1377 acache->stats.deleted++;
1379 UNLOCK(&acache->lock);
1385 dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
1394 REQUIRE(DNS_ACACHE_VALID(acache));
1403 * XXXSK: It might be better to lock the acache->cleaner->lock,
1410 if (acache->cleaner.overmem) {
1411 acache->stats.overmem_nocreates++; /* XXXSK danger: unlocked! */
1415 newentry = isc_mem_get(acache->mctx, sizeof(*newentry));
1417 acache->stats.nomem++; /* XXXMLG danger: unlocked! */
1426 isc_mem_put(acache->mctx, newentry, sizeof(*newentry));
1434 newentry->acache = NULL;
1435 dns_acache_attach(acache, &newentry->acache);
1467 dns_acache_t *acache;
1477 acache = entry->acache;
1478 REQUIRE(DNS_ACACHE_VALID(acache));
1481 ACACHE_LOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
1511 ACACHE_UNLOCK(&acache->entrylocks[locknum],
1527 entry->acache->stats.hits++; /* XXXMLG danger: unlocked! */
1528 entry->acache->stats.queries++;
1530 ACACHE_UNLOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
1553 dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
1563 REQUIRE(DNS_ACACHE_VALID(acache));
1566 LOCK(&acache->lock); /* XXX: need to lock it here for ordering */
1567 ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
1607 entry->foundname = isc_mem_get(acache->mctx,
1615 result = dns_name_dup(fname, acache->mctx,
1623 crdataset = isc_mem_get(acache->mctx,
1638 result = finddbent(acache, entry->origdb, &odbent);
1643 result = finddbent(acache, db, &rdbent);
1648 ISC_LIST_APPEND(acache->entries, entry, link);
1659 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1662 acache->stats.adds++;
1663 UNLOCK(&acache->lock);
1668 clear_entry(acache, entry);
1670 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1672 UNLOCK(&acache->lock);
1679 dns_acache_t *acache;
1684 acache = entry->acache;
1686 INSIST(DNS_ACACHE_VALID(entry->acache));
1688 LOCK(&acache->lock);
1689 ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
1695 * The main link cannot be released, since the acache object has
1699 unlink_dbentries(acache, entry);
1700 clear_entry(entry->acache, entry);
1705 ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
1707 UNLOCK(&acache->lock);
1740 (*entryp)->acache->stats.deleted++;
1748 dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) {
1752 REQUIRE(DNS_ACACHE_VALID(acache));
1756 LOCK(&acache->lock);
1759 * It may be the case that the acache has already shut down.
1762 if (acache->cleaner.cleaning_timer == NULL)
1765 acache->cleaner.cleaning_interval = t;
1768 result = isc_timer_reset(acache->cleaner.cleaning_timer,
1772 isc_interval_set(&interval, acache->cleaner.cleaning_interval,
1774 result = isc_timer_reset(acache->cleaner.cleaning_timer,
1781 "could not set acache cleaning interval: %s",
1786 "acache %p cleaning interval set to %d.",
1787 acache, t);
1790 UNLOCK(&acache->lock);
1798 dns_acache_setcachesize(dns_acache_t *acache, size_t size) {
1801 REQUIRE(DNS_ACACHE_VALID(acache));
1810 isc_mem_setwater(acache->mctx, water, acache, 0, 0);
1812 isc_mem_setwater(acache->mctx, water, acache,