lib/dns/rbtdb.c
/*%
 * Purge some expired and/or stale (i.e. unused for some period) cache entries
 * under an overmem condition.  To recover from this condition quickly, up to
 * 2 entries will be purged.  This process is triggered while adding a new
 * entry, and we specifically avoid purging entries in the same LRU bucket as
 * the one to which the new entry will belong.  Otherwise, we might purge
 * entries of the same name of different RR types while adding RRsets from a
 * single response (consider the case where we're adding A and AAAA glue records
 * of the same NS name).
 */
%
Purge some expired and/or stale  cache entries
under an overmem condition.  To recover from this condition quickly, up to
2 entries will be purged.  This process is triggered while adding a new
entry, and we specifically avoid purging entries in the same LRU bucket as
the one to which the new entry will belong.  Otherwise, we might purge
entries of the same name of different RR types while adding RRsets from a
single response (consider the case where we're adding A and AAAA glue records
of the same NS name).
% Purge some expired and / or stale cache entries under an overmem condition . To recover from this condition quickly up to 2 entries will be purged . This process is triggered while adding a new entry and we specifically avoid purging entries in the same LRU bucket as the one to which the new entry will belong . Otherwise we might purge entries of the same name of different RR types while adding RRsets from a single response ( consider the case where we ' re adding A and AAAA glue records of the same NS name ) .
static void
overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
	      isc_stdtime_t now, isc_boolean_t tree_locked)
{
	rdatasetheader_t *header, *header_prev;
	unsigned int locknum;
	int purgecount = 2;
	for (locknum = (locknum_start + 1) % rbtdb->node_lock_count;
	     locknum != locknum_start && purgecount > 0;
	     locknum = (locknum + 1) % rbtdb->node_lock_count) {
		NODE_LOCK(&rbtdb->node_locks[locknum].lock,
			  isc_rwlocktype_write);
		header = isc_heap_element(rbtdb->heaps[locknum], 1);
		if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL) {
			expire_header(rbtdb, header, tree_locked);
			purgecount--;
		}
		for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
		     header != NULL && purgecount > 0;
		     header = header_prev) {
			header_prev = ISC_LIST_PREV(header, link);
			ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
					link);
			expire_header(rbtdb, header, tree_locked);
			purgecount--;
		}
		NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
				    isc_rwlocktype_write);
	}
}
static void overmem_purge ( dns_rbtdb_t * rbtdb , unsigned int locknum_start , isc_stdtime_t now , isc_boolean_t tree_locked ) { rdatasetheader_t * header , * header_prev ; unsigned int locknum ; int purgecount = 2 ; for ( locknum = ( locknum_start + 1 ) % rbtdb -> node_lock_count ; locknum != locknum_start && purgecount > 0 ; locknum = ( locknum + 1 ) % rbtdb -> node_lock_count ) { NODE_LOCK ( & rbtdb -> node_locks [ locknum ] . lock , isc_rwlocktype_write ) ; header = isc_heap_element ( rbtdb -> heaps [ locknum ] , 1 ) ; if ( header && header -> rdh_ttl <= now - RBTDB_VIRTUAL ) { expire_header ( rbtdb , header , tree_locked ) ; purgecount -- ; } for ( header = ISC_LIST_TAIL ( rbtdb -> rdatasets [ locknum ] ) ; header != NULL && purgecount > 0 ; header = header_prev ) { header_prev = ISC_LIST_PREV ( header , link ) ; ISC_LIST_UNLINK ( rbtdb -> rdatasets [ locknum ] , header , link ) ; expire_header ( rbtdb , header , tree_locked ) ; purgecount -- ; } NODE_UNLOCK ( & rbtdb -> node_locks [ locknum ] . lock , isc_rwlocktype_write ) ; } }
%
 Purge some expired and/or stale (i.e.
% Purge some expired and / or stale ( i . e .
/*
			 * Unlink the entry at this point to avoid checking it
			 * again even if it's currently used someone else and
			 * cannot be purged at this moment.  This entry won't be
			 * referenced any more (so unlinking is safe) since the
			 * TTL was reset to 0.
			 */