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

📄 acache.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 4 页
字号:
	INSIST(next != NULL && next != cleaner->current_entry);	dns_acache_detachentry(&cleaner->current_entry);	dns_acache_attachentry(next, &cleaner->current_entry);	UNLOCK(&acache->lock);	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,		      ISC_LOG_DEBUG(1), "acache cleaner: checked %d entries, "		      "mem inuse %lu, sleeping", cleaner->increment,		      (unsigned long)isc_mem_inuse(cleaner->acache->mctx));	isc_task_send(task, &event);	INSIST(CLEANER_BUSY(cleaner));	return;}/* * This is called when the acache either surpasses its upper limit * or shrinks beyond its lower limit. */static voidacache_overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {	acache_cleaner_t *cleaner = event->ev_arg;	isc_boolean_t want_cleaning = ISC_FALSE;		UNUSED(task);	INSIST(event->ev_type == DNS_EVENT_ACACHEOVERMEM);	INSIST(cleaner->overmem_event == NULL);	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,		      ISC_LOG_DEBUG(1), "overmem_cleaning_action called, "		      "overmem = %d, state = %d", cleaner->overmem,		      cleaner->state);	LOCK(&cleaner->lock);	if (cleaner->overmem) {		if (cleaner->state == cleaner_s_idle)			want_cleaning = ISC_TRUE;	} else {		if (cleaner->state == cleaner_s_busy)			/*			 * end_cleaning() can't be called here because			 * then both cleaner->overmem_event and			 * cleaner->resched_event will point to this			 * event.  Set the state to done, and then			 * when the acache_incremental_cleaning_action() event			 * is posted, it will handle the end_cleaning.			 */			cleaner->state = cleaner_s_done;	}	cleaner->overmem_event = event;	UNLOCK(&cleaner->lock);	if (want_cleaning)		begin_cleaning(cleaner);}static voidwater(void *arg, int mark) {	dns_acache_t *acache = arg;	isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);	REQUIRE(DNS_ACACHE_VALID(acache));	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_ACACHE, ISC_LOG_DEBUG(1),		      "acache memory reaches %s watermark, mem inuse %lu",		      overmem ? "high" : "low",		      (unsigned long)isc_mem_inuse(acache->mctx));	LOCK(&acache->cleaner.lock);	acache->cleaner.overmem = overmem;	if (acache->cleaner.overmem_event != NULL)		isc_task_send(acache->task, &acache->cleaner.overmem_event);	UNLOCK(&acache->cleaner.lock);}/* * The cleaner task is shutting down; do the necessary cleanup. */static voidacache_cleaner_shutdown_action(isc_task_t *task, isc_event_t *event) {	dns_acache_t *acache = event->ev_arg;	isc_boolean_t should_free = ISC_FALSE;	INSIST(task == acache->task);	INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);	INSIST(DNS_ACACHE_VALID(acache));	ATRACE("acache cleaner shutdown");	if (CLEANER_BUSY(&acache->cleaner))		end_cleaning(&acache->cleaner, event);	else		isc_event_free(&event);	LOCK(&acache->lock);	acache->live_cleaners--;	INSIST(acache->live_cleaners == 0);	if (isc_refcount_current(&acache->refs) == 0) {		INSIST(check_noentry(acache) == ISC_TRUE);		should_free = ISC_TRUE;	}	/*	 * By detaching the timer in the context of its task,	 * we are guaranteed that there will be no further timer	 * events.	 */	if (acache->cleaner.cleaning_timer != NULL)		isc_timer_detach(&acache->cleaner.cleaning_timer);	/* Make sure we don't reschedule anymore. */	(void)isc_task_purge(task, NULL, DNS_EVENT_ACACHECLEAN, NULL);	UNLOCK(&acache->lock);	if (should_free)		destroy(acache);}/* *	Public functions. */isc_result_tdns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx,		  isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr){	int i;	isc_result_t result;	dns_acache_t *acache;	REQUIRE(acachep != NULL && *acachep == NULL);	REQUIRE(mctx != NULL);	REQUIRE(taskmgr != NULL);	acache = isc_mem_get(mctx, sizeof(*acache));	if (acache == NULL)		return (ISC_R_NOMEMORY);	ATRACE("create");	result = isc_refcount_init(&acache->refs, 1);	if (result != ISC_R_SUCCESS) {		isc_mem_put(mctx, acache, sizeof(*acache));		return (result);	}	result = isc_mutex_init(&acache->lock);	if (result != ISC_R_SUCCESS) {		isc_refcount_decrement(&acache->refs, NULL);		isc_refcount_destroy(&acache->refs);		isc_mem_put(mctx, acache, sizeof(*acache));		return (result);	}	acache->mctx = NULL;	isc_mem_attach(mctx, &acache->mctx);	ISC_LIST_INIT(acache->entries);	acache->shutting_down = ISC_FALSE;	acache->task = NULL;	acache->entrylocks = NULL;	result = isc_task_create(taskmgr, 1, &acache->task);	if (result != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_task_create() failed(): %s",				 dns_result_totext(result));		result = ISC_R_UNEXPECTED;		goto cleanup;	}	isc_task_setname(acache->task, "acachetask", acache);	ISC_EVENT_INIT(&acache->cevent, sizeof(acache->cevent), 0, NULL,		       DNS_EVENT_ACACHECONTROL, shutdown_task, NULL,		       NULL, NULL, NULL);	acache->cevent_sent = ISC_FALSE;	acache->dbentries = 0;	for (i = 0; i < DBBUCKETS; i++)		ISC_LIST_INIT(acache->dbbucket[i]);	acache->entrylocks = isc_mem_get(mctx, sizeof(*acache->entrylocks) *					 DEFAULT_ACACHE_ENTRY_LOCK_COUNT);	if (acache->entrylocks == NULL) {		result = ISC_R_NOMEMORY;		goto cleanup;	}	for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++) {		result = ACACHE_INITLOCK(&acache->entrylocks[i]);		if (result != ISC_R_SUCCESS) {			while (i-- > 0)				ACACHE_DESTROYLOCK(&acache->entrylocks[i]);			isc_mem_put(mctx, acache->entrylocks,				    sizeof(*acache->entrylocks) *				    DEFAULT_ACACHE_ENTRY_LOCK_COUNT);			acache->entrylocks = NULL;			goto cleanup;		}	}	acache->live_cleaners = 0;	result = acache_cleaner_init(acache, timermgr, &acache->cleaner); 	if (result != ISC_R_SUCCESS)		goto cleanup;	acache->stats.cleaner_runs = 0;	reset_stats(acache);	acache->magic = ACACHE_MAGIC;	*acachep = acache;	return (ISC_R_SUCCESS); cleanup:	if (acache->task != NULL)		isc_task_detach(&acache->task);	DESTROYLOCK(&acache->lock);	isc_refcount_decrement(&acache->refs, NULL);	isc_refcount_destroy(&acache->refs);	if (acache->entrylocks != NULL) {		for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++)			ACACHE_DESTROYLOCK(&acache->entrylocks[i]);		isc_mem_put(mctx, acache->entrylocks,			    sizeof(*acache->entrylocks) *			    DEFAULT_ACACHE_ENTRY_LOCK_COUNT);	}	isc_mem_put(mctx, acache, sizeof(*acache));	isc_mem_detach(&mctx);	return (result);}voiddns_acache_attach(dns_acache_t *source, dns_acache_t **targetp) {	REQUIRE(DNS_ACACHE_VALID(source));	REQUIRE(targetp != NULL && *targetp == NULL);	AATRACE(source, "attach");	isc_refcount_increment(&source->refs, NULL);	*targetp = source;}voiddns_acache_countquerymiss(dns_acache_t *acache) {	acache->stats.misses++; 	/* XXXSK danger: unlocked! */	acache->stats.queries++;	/* XXXSK danger: unlocked! */}voiddns_acache_detach(dns_acache_t **acachep) {	dns_acache_t *acache;	unsigned int refs;	isc_boolean_t should_free = ISC_FALSE;	REQUIRE(acachep != NULL && DNS_ACACHE_VALID(*acachep));	acache = *acachep;	ATRACE("detach");	isc_refcount_decrement(&acache->refs, &refs);	if (refs == 0) {		INSIST(check_noentry(acache) == ISC_TRUE);		should_free = ISC_TRUE;	}	*acachep = NULL;	/*	 * If we're exiting and the cleaner task exists, let it free the cache.	 */	if (should_free && acache->live_cleaners > 0) {		isc_task_shutdown(acache->task);		should_free = ISC_FALSE;	}		if (should_free)		destroy(acache);}voiddns_acache_shutdown(dns_acache_t *acache) {	REQUIRE(DNS_ACACHE_VALID(acache));	LOCK(&acache->lock);	ATRACE("shutdown");	if (!acache->shutting_down) {		isc_event_t *event;		dns_acache_t *acache_evarg = NULL;		INSIST(!acache->cevent_sent);		acache->shutting_down = ISC_TRUE;		isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);		/*		 * Self attach the object in order to prevent it from being		 * destroyed while waiting for the event.		 */		dns_acache_attach(acache, &acache_evarg);		event = &acache->cevent;		event->ev_arg = acache_evarg;		isc_task_send(acache->task, &event);		acache->cevent_sent = ISC_TRUE;	}	UNLOCK(&acache->lock);}isc_result_tdns_acache_setdb(dns_acache_t *acache, dns_db_t *db) {	int bucket;	dbentry_t *dbentry;	isc_result_t result = ISC_R_SUCCESS;	REQUIRE(DNS_ACACHE_VALID(acache));	REQUIRE(db != NULL);	ATRACE("setdb");	LOCK(&acache->lock);	dbentry = NULL;	result = finddbent(acache, db, &dbentry);	if (result == ISC_R_SUCCESS) {		result = ISC_R_EXISTS;		goto end;	}	result = ISC_R_SUCCESS;	dbentry = isc_mem_get(acache->mctx, sizeof(*dbentry));	if (dbentry == NULL) {		result = ISC_R_NOMEMORY;		goto end;	}	ISC_LINK_INIT(dbentry, link);	ISC_LIST_INIT(dbentry->originlist);	ISC_LIST_INIT(dbentry->referlist);	dbentry->db = NULL;	dns_db_attach(db, &dbentry->db);	bucket = isc_hash_calc((const unsigned char *)&db,			       sizeof(db), ISC_TRUE) % DBBUCKETS;	ISC_LIST_APPEND(acache->dbbucket[bucket], dbentry, link);	acache->dbentries++; end:	UNLOCK(&acache->lock);	return (result);}isc_result_tdns_acache_putdb(dns_acache_t *acache, dns_db_t *db) {	int bucket;	isc_result_t result;	dbentry_t *dbentry;	dns_acacheentry_t *entry;	REQUIRE(DNS_ACACHE_VALID(acache));	REQUIRE(db != NULL);	ATRACE("putdb");	LOCK(&acache->lock);	dbentry = NULL;	result = finddbent(acache, db, &dbentry);	if (result != ISC_R_SUCCESS) {		/*		 * The entry may have not been created due to memory shortage.		 */		UNLOCK(&acache->lock);		return (ISC_R_NOTFOUND);	}	/*	 * Release corresponding cache entries: for each entry, release all	 * links the entry has, and then callback to the entry holder (if any).	 * If no other external references exist (this can happen if the	 * original holder has canceled callback,) destroy it here.	 */	while ((entry = ISC_LIST_HEAD(dbentry->originlist)) != NULL) {		ACACHE_LOCK(&acache->entrylocks[entry->locknum],			    isc_rwlocktype_write);		/*		 * Releasing olink first would avoid finddbent() in		 * unlink_dbentries().		 */		ISC_LIST_UNLINK(dbentry->originlist, entry, olink);		if (acache->cleaner.current_entry != entry)			ISC_LIST_UNLINK(acache->entries, entry, link);		unlink_dbentries(acache, entry);		if (entry->callback != NULL)			(entry->callback)(entry, &entry->cbarg);		entry->callback = NULL;		ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],			      isc_rwlocktype_write);		if (acache->cleaner.current_entry != entry)			dns_acache_detachentry(&entry);	}	while ((entry = ISC_LIST_HEAD(dbentry->referlist)) != NULL) {		ACACHE_LOCK(&acache->entrylocks[entry->locknum],			    isc_rwlocktype_write);		ISC_LIST_UNLINK(dbentry->referlist, entry, rlink);		if (acache->cleaner.current_entry != entry)			ISC_LIST_UNLINK(acache->entries, entry, link);		unlink_dbentries(acache, entry);		if (entry->callback != NULL)			(entry->callback)(entry, &entry->cbarg);		entry->callback = NULL;		ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],			      isc_rwlocktype_write);		if (acache->cleaner.current_entry != entry)			dns_acache_detachentry(&entry);	}

⌨️ 快捷键说明

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