⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acache.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++)		ACACHE_DESTROYLOCK(&acache->entrylocks[i]);	isc_mem_put(acache->mctx, acache->entrylocks,		    sizeof(*acache->entrylocks) *		    DEFAULT_ACACHE_ENTRY_LOCK_COUNT);	DESTROYLOCK(&acache->cleaner.lock);	DESTROYLOCK(&acache->lock);	acache->magic = 0;	isc_mem_putanddetach(&acache->mctx, acache, sizeof(*acache));}static inline isc_result_tfinddbent(dns_acache_t *acache, dns_db_t *db, dbentry_t **dbentryp) {	int bucket;	dbentry_t *dbentry;	REQUIRE(DNS_ACACHE_VALID(acache));	REQUIRE(db != NULL);	REQUIRE(dbentryp != NULL && *dbentryp == NULL);	/*	 * The caller must be holding the acache lock.	 */	bucket = isc_hash_calc((const unsigned char *)&db,			       sizeof(db), ISC_TRUE) % DBBUCKETS;	for (dbentry = ISC_LIST_HEAD(acache->dbbucket[bucket]);	     dbentry != NULL;	     dbentry = ISC_LIST_NEXT(dbentry, link)) {		if (dbentry->db == db)			break;	}	*dbentryp = dbentry;	if (dbentry == NULL)		return (ISC_R_NOTFOUND);	else		return (ISC_R_SUCCESS);}static inline voidclear_entry(dns_acache_t *acache, dns_acacheentry_t *entry) {	REQUIRE(DNS_ACACHE_VALID(acache));	REQUIRE(DNS_ACACHEENTRY_VALID(entry));	/*	 * The caller must be holing the entry lock.	 */	if (entry->foundname) {		dns_rdataset_t *rdataset, *rdataset_next;		for (rdataset = ISC_LIST_HEAD(entry->foundname->list);		     rdataset != NULL;		     rdataset = rdataset_next) {			rdataset_next = ISC_LIST_NEXT(rdataset, link);			ISC_LIST_UNLINK(entry->foundname->list,					rdataset, link);			dns_rdataset_disassociate(rdataset);			isc_mem_put(acache->mctx, rdataset, sizeof(*rdataset));		}		if (dns_name_dynamic(entry->foundname))			dns_name_free(entry->foundname, acache->mctx);		isc_mem_put(acache->mctx, entry->foundname,			    sizeof(*entry->foundname)); 		entry->foundname = NULL;	}	if (entry->node != NULL) {		INSIST(entry->db != NULL);		dns_db_detachnode(entry->db, &entry->node);	}	if (entry->version != NULL) {		INSIST(entry->db != NULL);		dns_db_closeversion(entry->db, &entry->version, ISC_FALSE);	}	if (entry->db != NULL)		dns_db_detach(&entry->db);	if (entry->zone != NULL)		dns_zone_detach(&entry->zone);	if (entry->origdb != NULL)		dns_db_detach(&entry->origdb);}static isc_result_tacache_cleaner_init(dns_acache_t *acache, isc_timermgr_t *timermgr,		    acache_cleaner_t *cleaner){	int result;	ATRACE("acache cleaner init");	result = isc_mutex_init(&cleaner->lock);	if (result != ISC_R_SUCCESS)		goto fail;	cleaner->increment = DNS_ACACHE_CLEANERINCREMENT;	cleaner->state = cleaner_s_idle;	cleaner->acache = acache;	cleaner->overmem = ISC_FALSE;	cleaner->cleaning_timer = NULL;	cleaner->resched_event = NULL;	cleaner->overmem_event = NULL;	cleaner->current_entry = NULL;	if (timermgr != NULL) {		cleaner->acache->live_cleaners++;				result = isc_task_onshutdown(acache->task,					     acache_cleaner_shutdown_action,					     acache);		if (result != ISC_R_SUCCESS) {			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "acache cleaner: "					 "isc_task_onshutdown() failed: %s",					 dns_result_totext(result));			goto cleanup;		}		cleaner->cleaning_interval = 0; /* Initially turned off. */		isc_stdtime_get(&cleaner->last_cleanup_time);		result = isc_timer_create(timermgr, isc_timertype_inactive,					  NULL, NULL,					  acache->task,					  acache_cleaning_timer_action,					  cleaner, &cleaner->cleaning_timer);		if (result != ISC_R_SUCCESS) {			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "isc_timer_create() failed: %s",					 dns_result_totext(result));			result = ISC_R_UNEXPECTED;			goto cleanup;		}		cleaner->resched_event =			isc_event_allocate(acache->mctx, cleaner,					   DNS_EVENT_ACACHECLEAN,					   acache_incremental_cleaning_action,					   cleaner, sizeof(isc_event_t));		if (cleaner->resched_event == NULL) {			result = ISC_R_NOMEMORY;			goto cleanup;		}		cleaner->overmem_event =			isc_event_allocate(acache->mctx, cleaner,					   DNS_EVENT_ACACHEOVERMEM,					   acache_overmem_cleaning_action,					   cleaner, sizeof(isc_event_t));		if (cleaner->overmem_event == NULL) {			result = ISC_R_NOMEMORY;			goto cleanup;		}	}	return (ISC_R_SUCCESS); cleanup:	if (cleaner->overmem_event != NULL)		isc_event_free(&cleaner->overmem_event);	if (cleaner->resched_event != NULL)		isc_event_free(&cleaner->resched_event);	if (cleaner->cleaning_timer != NULL)		isc_timer_detach(&cleaner->cleaning_timer);	cleaner->acache->live_cleaners--;	DESTROYLOCK(&cleaner->lock); fail:	return (result);}static voidbegin_cleaning(acache_cleaner_t *cleaner) {	dns_acacheentry_t *head;	dns_acache_t *acache = cleaner->acache;	/*	 * This function does not have to lock the cleaner, since critical	 * parameters (except current_entry, which is locked by acache lock,)	 * are only used in a single task context.	 */	REQUIRE(CLEANER_IDLE(cleaner));	INSIST(DNS_ACACHE_VALID(acache));	INSIST(cleaner->current_entry == NULL);	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_ACACHE, ISC_LOG_DEBUG(1),		      "begin acache cleaning, mem inuse %lu",		      (unsigned long)isc_mem_inuse(cleaner->acache->mctx));	LOCK(&acache->lock);	head = ISC_LIST_HEAD(acache->entries);	if (head != NULL)		dns_acache_attachentry(head, &cleaner->current_entry);	UNLOCK(&acache->lock);	if (cleaner->current_entry != NULL) {		cleaner->ncleaned = 0;		cleaner->state = cleaner_s_busy;		isc_task_send(acache->task, &cleaner->resched_event);	}	return;}static voidend_cleaning(acache_cleaner_t *cleaner, isc_event_t *event) {	dns_acache_t *acache = cleaner->acache;	REQUIRE(CLEANER_BUSY(cleaner));	REQUIRE(event != NULL);	REQUIRE(DNS_ACACHEENTRY_VALID(cleaner->current_entry));	/* No need to lock the cleaner (see begin_cleaning()). */	LOCK(&acache->lock);	/*	 * Even if the cleaner has the last reference to the entry, which means	 * the entry has been unused, it may still be linked if unlinking the	 * entry has been delayed due to the reference.	 */	if (isc_refcount_current(&cleaner->current_entry->references) == 1) {		INSIST(cleaner->current_entry->callback == NULL);				if (ISC_LINK_LINKED(cleaner->current_entry, link)) {			ISC_LIST_UNLINK(acache->entries,					cleaner->current_entry, link);		}	}	dns_acache_detachentry(&cleaner->current_entry);	if (cleaner->overmem)		acache->stats.overmem++;	acache->stats.cleaned += cleaner->ncleaned;	acache->stats.cleaner_runs++;	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,		      ISC_LOG_NOTICE,		      "acache %p stats: hits=%d misses=%d queries=%d "		      "adds=%d deleted=%d "		      "cleaned=%d cleaner_runs=%d overmem=%d "		      "overmem_nocreates=%d nomem=%d",		      acache,		      acache->stats.hits, acache->stats.misses,		      acache->stats.queries,		      acache->stats.adds, acache->stats.deleted,		      acache->stats.cleaned, acache->stats.cleaner_runs,		      acache->stats.overmem, acache->stats.overmem_nocreates, 		      acache->stats.nomem);	reset_stats(acache);	isc_stdtime_get(&cleaner->last_cleanup_time);	UNLOCK(&acache->lock);	dns_acache_setcleaninginterval(cleaner->acache,				       cleaner->cleaning_interval);	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,		      ISC_LOG_DEBUG(1), "end acache cleaning, "		      "%lu entries cleaned, mem inuse %lu",		      cleaner->ncleaned,		      (unsigned long)isc_mem_inuse(cleaner->acache->mctx));	if (cleaner->overmem) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_ACACHE, ISC_LOG_NOTICE,			      "acache is still in overmem state "			      "after cleaning");	}	cleaner->ncleaned = 0;	cleaner->state = cleaner_s_idle;	cleaner->resched_event = event;}/* * This is run once for every acache-cleaning-interval as defined * in named.conf. */static voidacache_cleaning_timer_action(isc_task_t *task, isc_event_t *event) {	acache_cleaner_t *cleaner = event->ev_arg;	UNUSED(task);	INSIST(event->ev_type == ISC_TIMEREVENT_TICK);	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,		      ISC_LOG_DEBUG(1), "acache cleaning timer fired, "		      "cleaner state = %d", cleaner->state);	if (cleaner->state == cleaner_s_idle)		begin_cleaning(cleaner);	isc_event_free(&event);}/* The caller must hold entry lock. */static inline isc_boolean_tentry_stale(acache_cleaner_t *cleaner, dns_acacheentry_t *entry,	    isc_stdtime32_t now32, unsigned int interval){	/*	 * If the callback has been canceled, we definitely do not need the	 * entry.	 */	if (entry->callback == NULL)		return (ISC_TRUE);	if (interval > cleaner->cleaning_interval)		interval = cleaner->cleaning_interval;	if (entry->lastused + interval < now32)		return (ISC_TRUE);	/*	 * If the acache is in the overmem state, probabilistically decide if	 * the entry should be purged, based on the time passed from its last	 * use and the cleaning interval.	 */	if (cleaner->overmem) {		unsigned int passed =			now32 - entry->lastused; /* <= interval */		isc_uint32_t val;		if (passed > interval / 2)			return (ISC_TRUE);		isc_random_get(&val);		if (passed > interval / 4)			return (ISC_TF(val % 4 == 0));		return (ISC_TF(val % 8 == 0));	}	return (ISC_FALSE);}/* * Do incremental cleaning. */static voidacache_incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {	acache_cleaner_t *cleaner = event->ev_arg;	dns_acache_t *acache = cleaner->acache;	dns_acacheentry_t *entry, *next = NULL;	int n_entries;	isc_stdtime32_t now32, last32;	isc_stdtime_t now;	unsigned int interval;	INSIST(DNS_ACACHE_VALID(acache));	INSIST(task == acache->task);	INSIST(event->ev_type == DNS_EVENT_ACACHECLEAN);	if (cleaner->state == cleaner_s_done) {		cleaner->state = cleaner_s_busy;		end_cleaning(cleaner, event);		return;	}	INSIST(CLEANER_BUSY(cleaner));	n_entries = cleaner->increment;	isc_stdtime_get(&now);	isc_stdtime_convert32(now, &now32);	LOCK(&acache->lock);	entry = cleaner->current_entry;	isc_stdtime_convert32(cleaner->last_cleanup_time, &last32);	INSIST(now32 > last32);	interval = now32 - last32;	while (n_entries-- > 0) {		isc_boolean_t is_stale = ISC_FALSE;		INSIST(entry != NULL);		next = ISC_LIST_NEXT(entry, link);		ACACHE_LOCK(&acache->entrylocks[entry->locknum],			    isc_rwlocktype_write);		is_stale = entry_stale(cleaner, entry, now32, interval);		if (is_stale) {			ISC_LIST_UNLINK(acache->entries, entry, link);			unlink_dbentries(acache, entry);			if (entry->callback != NULL)				(entry->callback)(entry, &entry->cbarg);			entry->callback = NULL;			cleaner->ncleaned++;		}		ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],			      isc_rwlocktype_write);		if (is_stale)			dns_acache_detachentry(&entry);		if (next == NULL) {			if (cleaner->overmem) {				entry = ISC_LIST_HEAD(acache->entries);				if (entry != NULL) {					/*					 * If we are still in the overmem					 * state, keep cleaning.					 */					isc_log_write(dns_lctx,						      DNS_LOGCATEGORY_DATABASE,						      DNS_LOGMODULE_ACACHE,						      ISC_LOG_DEBUG(1),						      "acache cleaner: "						      "still overmem, "						      "reset and try again");					continue;				}			}			UNLOCK(&acache->lock);			end_cleaning(cleaner, event);			return;		}		entry = next;	}	/*	 * We have successfully performed a cleaning increment but have	 * not gone through the entire cache.  Remember the entry that will	 * be the starting point in the next clean-up, and reschedule another	 * batch.  If it fails, just try to continue anyway.	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -